feat: replace TextField with MUI DatePicker and TimePicker in DateTimeFields
- Replace native HTML date/time inputs with MUI X Date Pickers components - Add DatePicker for start/end dates - Add TimePicker for start/end times
This commit is contained in:
committed by
Benoit TELLIER
parent
01f79553c0
commit
3c75a7e82e
@@ -1,5 +1,10 @@
|
||||
import React from "react";
|
||||
import { Box, TextField, Typography } from "@mui/material";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
|
||||
import { TimePicker } from "@mui/x-date-pickers/TimePicker";
|
||||
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
|
||||
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
|
||||
import moment, { Moment } from "moment";
|
||||
|
||||
/**
|
||||
* Props for DateTimeFields component
|
||||
@@ -40,104 +45,130 @@ export const DateTimeFields: React.FC<DateTimeFieldsProps> = ({
|
||||
onEndTimeChange,
|
||||
}) => {
|
||||
return (
|
||||
<Box display="flex" gap={1} flexDirection="column">
|
||||
{/* First row: 4 fields */}
|
||||
<Box display="flex" gap={1} flexDirection="row" alignItems="flex-start">
|
||||
{/* Start Date - 30% */}
|
||||
<Box sx={{ flexGrow: 0.3, flexBasis: "30%" }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
Start Date
|
||||
</Typography>
|
||||
)}
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "Start Date" : ""}
|
||||
type="date"
|
||||
value={startDate}
|
||||
onChange={(e) => onStartDateChange(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Box>
|
||||
<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="en">
|
||||
<Box display="flex" gap={1} flexDirection="column">
|
||||
{/* First row: 4 fields */}
|
||||
<Box display="flex" gap={1} flexDirection="row" alignItems="flex-start">
|
||||
{/* Start Date - 30% */}
|
||||
<Box sx={{ flexGrow: 0.3, flexBasis: "25%", minWidth: 0 }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
Start Date
|
||||
</Typography>
|
||||
)}
|
||||
<DatePicker
|
||||
label={!showMore ? "Start Date" : ""}
|
||||
value={startDate ? moment(startDate) : null}
|
||||
onChange={(newValue: Moment | null) => {
|
||||
onStartDateChange(newValue?.format("YYYY-MM-DD") || "");
|
||||
}}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
margin: "dense" as const,
|
||||
fullWidth: true,
|
||||
InputLabelProps: { shrink: true },
|
||||
sx: { width: "100%" },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Start Time - 20% */}
|
||||
<Box sx={{ flexGrow: 0.2, flexBasis: "20%" }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
Start Time
|
||||
</Typography>
|
||||
)}
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "Start Time" : ""}
|
||||
type="time"
|
||||
value={startTime}
|
||||
onChange={(e) => onStartTimeChange(e.target.value)}
|
||||
disabled={allday}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Box>
|
||||
{/* Start Time - 20% */}
|
||||
<Box sx={{ flexGrow: 0.2, flexBasis: "25%", minWidth: 0 }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
Start Time
|
||||
</Typography>
|
||||
)}
|
||||
<TimePicker
|
||||
label={!showMore ? "Start Time" : ""}
|
||||
value={startTime ? moment(startTime, "HH:mm") : null}
|
||||
onChange={(newValue: Moment | null) => {
|
||||
onStartTimeChange(newValue?.format("HH:mm") || "");
|
||||
}}
|
||||
disabled={allday}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
margin: "dense" as const,
|
||||
fullWidth: true,
|
||||
InputLabelProps: { shrink: true },
|
||||
sx: { width: "100%" },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* End Time - 20% */}
|
||||
<Box sx={{ flexGrow: 0.2, flexBasis: "20%" }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
End Time
|
||||
</Typography>
|
||||
)}
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "End Time" : ""}
|
||||
type="time"
|
||||
value={endTime}
|
||||
onChange={(e) => onEndTimeChange(e.target.value)}
|
||||
disabled={allday}
|
||||
error={!!validation.errors.dateTime}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Box>
|
||||
{/* End Time - 20% */}
|
||||
<Box sx={{ flexGrow: 0.2, flexBasis: "25%", minWidth: 0 }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
End Time
|
||||
</Typography>
|
||||
)}
|
||||
<TimePicker
|
||||
label={!showMore ? "End Time" : ""}
|
||||
value={endTime ? moment(endTime, "HH:mm") : null}
|
||||
onChange={(newValue: Moment | null) => {
|
||||
onEndTimeChange(newValue?.format("HH:mm") || "");
|
||||
}}
|
||||
disabled={allday}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
margin: "dense" as const,
|
||||
fullWidth: true,
|
||||
InputLabelProps: { shrink: true },
|
||||
error: !!validation.errors.dateTime,
|
||||
sx: { width: "100%" },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* End Date - 30% */}
|
||||
<Box sx={{ flexGrow: 0.3, flexBasis: "30%" }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
End Date
|
||||
</Typography>
|
||||
)}
|
||||
<TextField
|
||||
fullWidth
|
||||
label={!showMore ? "End Date" : ""}
|
||||
type="date"
|
||||
value={endDate}
|
||||
onChange={(e) => onEndDateChange(e.target.value)}
|
||||
error={!!validation.errors.dateTime}
|
||||
size="small"
|
||||
margin="dense"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Second row: Error message - 2 columns 50% each */}
|
||||
{validation.errors.dateTime && (
|
||||
<Box display="flex" gap={1} flexDirection="row">
|
||||
{/* Empty left column - 50% */}
|
||||
<Box sx={{ flexGrow: 0.5, flexBasis: "50%" }} />
|
||||
|
||||
{/* Error message right column - 50% */}
|
||||
<Box sx={{ flexGrow: 0.5, flexBasis: "50%" }}>
|
||||
<Typography variant="caption" color="error">
|
||||
{validation.errors.dateTime}
|
||||
</Typography>
|
||||
{/* End Date - 30% */}
|
||||
<Box sx={{ flexGrow: 0.3, flexBasis: "25%", minWidth: 0 }}>
|
||||
{showMore && (
|
||||
<Typography variant="caption" display="block" mb={0.5}>
|
||||
End Date
|
||||
</Typography>
|
||||
)}
|
||||
<DatePicker
|
||||
label={!showMore ? "End Date" : ""}
|
||||
value={endDate ? moment(endDate) : null}
|
||||
onChange={(newValue: Moment | null) => {
|
||||
onEndDateChange(newValue?.format("YYYY-MM-DD") || "");
|
||||
}}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: "small",
|
||||
margin: "dense" as const,
|
||||
fullWidth: true,
|
||||
InputLabelProps: { shrink: true },
|
||||
error: !!validation.errors.dateTime,
|
||||
sx: { width: "100%" },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Second row: Error message - 2 columns 50% each */}
|
||||
{validation.errors.dateTime && (
|
||||
<Box display="flex" gap={1} flexDirection="row">
|
||||
{/* Empty left column - 50% */}
|
||||
<Box sx={{ flexGrow: 0.5, flexBasis: "50%" }} />
|
||||
|
||||
{/* Error message right column - 50% */}
|
||||
<Box sx={{ flexGrow: 0.5, flexBasis: "50%" }}>
|
||||
<Typography variant="caption" sx={{ color: "error.main" }}>
|
||||
{validation.errors.dateTime}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</LocalizationProvider>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user