From 3c95b7506ba05c01d673a74ea4270a855405acac Mon Sep 17 00:00:00 2001 From: Matthias Hochmeister Date: Thu, 26 Mar 2026 13:01:59 +0100 Subject: [PATCH] update --- .../src/components/shared/GermanDateField.tsx | 113 ++++-------------- 1 file changed, 22 insertions(+), 91 deletions(-) diff --git a/frontend/src/components/shared/GermanDateField.tsx b/frontend/src/components/shared/GermanDateField.tsx index 8650dd8..552a5fd 100644 --- a/frontend/src/components/shared/GermanDateField.tsx +++ b/frontend/src/components/shared/GermanDateField.tsx @@ -1,32 +1,21 @@ -import { useState, useRef } from 'react'; import TextField, { type TextFieldProps } from '@mui/material/TextField'; -import InputAdornment from '@mui/material/InputAdornment'; -import IconButton from '@mui/material/IconButton'; -import Box from '@mui/material/Box'; -import CalendarMonth from '@mui/icons-material/CalendarMonth'; -import { - toGermanDate, - toGermanDateTime, - fromGermanDate, - fromGermanDateTime, -} from '../../utils/dateInput'; +import { useTheme } from '@mui/material/styles'; export type GermanDateMode = 'date' | 'datetime'; export interface GermanDateFieldProps extends Omit { /** ISO date (YYYY-MM-DD) or datetime (YYYY-MM-DDTHH:MM) string */ value?: string | null; - /** Called with ISO date/datetime string whenever value changes to a valid date */ + /** Called with ISO date/datetime string on change */ onChange?: (isoValue: string) => void; mode?: GermanDateMode; } /** - * A MUI TextField that: - * - Displays dates in German format (TT.MM.JJJJ / TT.MM.JJJJ HH:MM) - * - Accepts free-text entry in that format - * - Has a calendar icon that opens the native browser date picker as a popup - * - onChange fires with an ISO string whenever the entered value is valid + * Themed date / datetime input that: + * - Uses the native browser date picker (locale-aware → shows DD.MM.YYYY in German browsers) + * - Properly supports dark / light mode via CSS colorScheme + * - Thin wrapper: all MUI TextField props work as expected */ export default function GermanDateField({ value, @@ -35,84 +24,26 @@ export default function GermanDateField({ sx, ...rest }: GermanDateFieldProps) { - // localValue overrides the displayed text while the user is typing - const [localValue, setLocalValue] = useState(null); - const hiddenRef = useRef(null); - - const displayed = - localValue ?? (mode === 'date' ? toGermanDate(value) : toGermanDateTime(value)); - - function handleTextChange(raw: string) { - setLocalValue(raw); - const iso = mode === 'date' ? fromGermanDate(raw) : fromGermanDateTime(raw); - if (iso) { - onChange?.(iso); - setLocalValue(null); - } - } - - function handleBlur() { - // Revert to the last valid formatted value if the text is incomplete - setLocalValue(null); - } - - function handlePickerChange(nativeVal: string) { - if (!nativeVal) return; - if (mode === 'date') { - onChange?.(nativeVal); - } else { - // Preserve current time portion if available, default to 08:00 - const time = value?.substring(11, 16) || '08:00'; - onChange?.(`${nativeVal}T${time}`); - } - } + const theme = useTheme(); + const isDark = theme.palette.mode === 'dark'; + const nativeType = mode === 'date' ? 'date' : 'datetime-local'; const nativeValue = mode === 'date' ? (value?.substring(0, 10) || '') : (value?.substring(0, 16) || ''); return ( - - handleTextChange(e.target.value)} - onBlur={handleBlur} - placeholder={mode === 'date' ? 'TT.MM.JJJJ' : 'TT.MM.JJJJ HH:MM'} - InputLabelProps={{ shrink: true, ...rest.InputLabelProps }} - InputProps={{ - endAdornment: ( - - hiddenRef.current?.showPicker?.()} - > - - - - ), - ...rest.InputProps, - }} - /> - {/* Hidden native input used solely to open the browser's date picker popup */} - handlePickerChange(e.target.value)} - tabIndex={-1} - style={{ - position: 'absolute', - bottom: 0, - left: 0, - opacity: 0, - width: '100%', - height: '100%', - pointerEvents: 'none', - }} - /> - + onChange?.(e.target.value)} + InputLabelProps={{ shrink: true, ...rest.InputLabelProps }} + sx={{ + '& input': { + colorScheme: isDark ? 'dark' : 'light', + }, + ...sx, + }} + /> ); }