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 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
|
* Props for DateTimeFields component
|
||||||
@@ -40,104 +45,130 @@ export const DateTimeFields: React.FC<DateTimeFieldsProps> = ({
|
|||||||
onEndTimeChange,
|
onEndTimeChange,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Box display="flex" gap={1} flexDirection="column">
|
<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="en">
|
||||||
{/* First row: 4 fields */}
|
<Box display="flex" gap={1} flexDirection="column">
|
||||||
<Box display="flex" gap={1} flexDirection="row" alignItems="flex-start">
|
{/* First row: 4 fields */}
|
||||||
{/* Start Date - 30% */}
|
<Box display="flex" gap={1} flexDirection="row" alignItems="flex-start">
|
||||||
<Box sx={{ flexGrow: 0.3, flexBasis: "30%" }}>
|
{/* Start Date - 30% */}
|
||||||
{showMore && (
|
<Box sx={{ flexGrow: 0.3, flexBasis: "25%", minWidth: 0 }}>
|
||||||
<Typography variant="caption" display="block" mb={0.5}>
|
{showMore && (
|
||||||
Start Date
|
<Typography variant="caption" display="block" mb={0.5}>
|
||||||
</Typography>
|
Start Date
|
||||||
)}
|
</Typography>
|
||||||
<TextField
|
)}
|
||||||
fullWidth
|
<DatePicker
|
||||||
label={!showMore ? "Start Date" : ""}
|
label={!showMore ? "Start Date" : ""}
|
||||||
type="date"
|
value={startDate ? moment(startDate) : null}
|
||||||
value={startDate}
|
onChange={(newValue: Moment | null) => {
|
||||||
onChange={(e) => onStartDateChange(e.target.value)}
|
onStartDateChange(newValue?.format("YYYY-MM-DD") || "");
|
||||||
size="small"
|
}}
|
||||||
margin="dense"
|
slotProps={{
|
||||||
InputLabelProps={{ shrink: true }}
|
textField: {
|
||||||
/>
|
size: "small",
|
||||||
</Box>
|
margin: "dense" as const,
|
||||||
|
fullWidth: true,
|
||||||
|
InputLabelProps: { shrink: true },
|
||||||
|
sx: { width: "100%" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* Start Time - 20% */}
|
{/* Start Time - 20% */}
|
||||||
<Box sx={{ flexGrow: 0.2, flexBasis: "20%" }}>
|
<Box sx={{ flexGrow: 0.2, flexBasis: "25%", minWidth: 0 }}>
|
||||||
{showMore && (
|
{showMore && (
|
||||||
<Typography variant="caption" display="block" mb={0.5}>
|
<Typography variant="caption" display="block" mb={0.5}>
|
||||||
Start Time
|
Start Time
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<TextField
|
<TimePicker
|
||||||
fullWidth
|
label={!showMore ? "Start Time" : ""}
|
||||||
label={!showMore ? "Start Time" : ""}
|
value={startTime ? moment(startTime, "HH:mm") : null}
|
||||||
type="time"
|
onChange={(newValue: Moment | null) => {
|
||||||
value={startTime}
|
onStartTimeChange(newValue?.format("HH:mm") || "");
|
||||||
onChange={(e) => onStartTimeChange(e.target.value)}
|
}}
|
||||||
disabled={allday}
|
disabled={allday}
|
||||||
size="small"
|
slotProps={{
|
||||||
margin="dense"
|
textField: {
|
||||||
InputLabelProps={{ shrink: true }}
|
size: "small",
|
||||||
/>
|
margin: "dense" as const,
|
||||||
</Box>
|
fullWidth: true,
|
||||||
|
InputLabelProps: { shrink: true },
|
||||||
|
sx: { width: "100%" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* End Time - 20% */}
|
{/* End Time - 20% */}
|
||||||
<Box sx={{ flexGrow: 0.2, flexBasis: "20%" }}>
|
<Box sx={{ flexGrow: 0.2, flexBasis: "25%", minWidth: 0 }}>
|
||||||
{showMore && (
|
{showMore && (
|
||||||
<Typography variant="caption" display="block" mb={0.5}>
|
<Typography variant="caption" display="block" mb={0.5}>
|
||||||
End Time
|
End Time
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<TextField
|
<TimePicker
|
||||||
fullWidth
|
label={!showMore ? "End Time" : ""}
|
||||||
label={!showMore ? "End Time" : ""}
|
value={endTime ? moment(endTime, "HH:mm") : null}
|
||||||
type="time"
|
onChange={(newValue: Moment | null) => {
|
||||||
value={endTime}
|
onEndTimeChange(newValue?.format("HH:mm") || "");
|
||||||
onChange={(e) => onEndTimeChange(e.target.value)}
|
}}
|
||||||
disabled={allday}
|
disabled={allday}
|
||||||
error={!!validation.errors.dateTime}
|
slotProps={{
|
||||||
size="small"
|
textField: {
|
||||||
margin="dense"
|
size: "small",
|
||||||
InputLabelProps={{ shrink: true }}
|
margin: "dense" as const,
|
||||||
/>
|
fullWidth: true,
|
||||||
</Box>
|
InputLabelProps: { shrink: true },
|
||||||
|
error: !!validation.errors.dateTime,
|
||||||
|
sx: { width: "100%" },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* End Date - 30% */}
|
{/* End Date - 30% */}
|
||||||
<Box sx={{ flexGrow: 0.3, flexBasis: "30%" }}>
|
<Box sx={{ flexGrow: 0.3, flexBasis: "25%", minWidth: 0 }}>
|
||||||
{showMore && (
|
{showMore && (
|
||||||
<Typography variant="caption" display="block" mb={0.5}>
|
<Typography variant="caption" display="block" mb={0.5}>
|
||||||
End Date
|
End Date
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<TextField
|
<DatePicker
|
||||||
fullWidth
|
label={!showMore ? "End Date" : ""}
|
||||||
label={!showMore ? "End Date" : ""}
|
value={endDate ? moment(endDate) : null}
|
||||||
type="date"
|
onChange={(newValue: Moment | null) => {
|
||||||
value={endDate}
|
onEndDateChange(newValue?.format("YYYY-MM-DD") || "");
|
||||||
onChange={(e) => onEndDateChange(e.target.value)}
|
}}
|
||||||
error={!!validation.errors.dateTime}
|
slotProps={{
|
||||||
size="small"
|
textField: {
|
||||||
margin="dense"
|
size: "small",
|
||||||
InputLabelProps={{ shrink: true }}
|
margin: "dense" as const,
|
||||||
/>
|
fullWidth: true,
|
||||||
</Box>
|
InputLabelProps: { shrink: true },
|
||||||
</Box>
|
error: !!validation.errors.dateTime,
|
||||||
|
sx: { width: "100%" },
|
||||||
{/* 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>
|
|
||||||
</Box>
|
</Box>
|
||||||
</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