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:
lenhanphung
2025-10-27 16:33:47 +07:00
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,86 +45,111 @@ export const DateTimeFields: React.FC<DateTimeFieldsProps> = ({
onEndTimeChange, onEndTimeChange,
}) => { }) => {
return ( return (
<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="en">
<Box display="flex" gap={1} flexDirection="column"> <Box display="flex" gap={1} flexDirection="column">
{/* First row: 4 fields */} {/* First row: 4 fields */}
<Box display="flex" gap={1} flexDirection="row" alignItems="flex-start"> <Box display="flex" gap={1} flexDirection="row" alignItems="flex-start">
{/* Start Date - 30% */} {/* Start 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}>
Start Date Start Date
</Typography> </Typography>
)} )}
<TextField <DatePicker
fullWidth
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",
margin: "dense" as const,
fullWidth: true,
InputLabelProps: { shrink: true },
sx: { width: "100%" },
},
}}
/> />
</Box> </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" : ""}
type="time" value={startTime ? moment(startTime, "HH:mm") : null}
value={startTime} onChange={(newValue: Moment | null) => {
onChange={(e) => onStartTimeChange(e.target.value)} onStartTimeChange(newValue?.format("HH:mm") || "");
}}
disabled={allday} disabled={allday}
size="small" slotProps={{
margin="dense" textField: {
InputLabelProps={{ shrink: true }} size: "small",
margin: "dense" as const,
fullWidth: true,
InputLabelProps: { shrink: true },
sx: { width: "100%" },
},
}}
/> />
</Box> </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" : ""}
type="time" value={endTime ? moment(endTime, "HH:mm") : null}
value={endTime} onChange={(newValue: Moment | null) => {
onChange={(e) => onEndTimeChange(e.target.value)} onEndTimeChange(newValue?.format("HH:mm") || "");
}}
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,
InputLabelProps: { shrink: true },
error: !!validation.errors.dateTime,
sx: { width: "100%" },
},
}}
/> />
</Box> </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" : ""}
type="date" value={endDate ? moment(endDate) : null}
value={endDate} onChange={(newValue: Moment | null) => {
onChange={(e) => onEndDateChange(e.target.value)} onEndDateChange(newValue?.format("YYYY-MM-DD") || "");
error={!!validation.errors.dateTime} }}
size="small" slotProps={{
margin="dense" textField: {
InputLabelProps={{ shrink: true }} size: "small",
margin: "dense" as const,
fullWidth: true,
InputLabelProps: { shrink: true },
error: !!validation.errors.dateTime,
sx: { width: "100%" },
},
}}
/> />
</Box> </Box>
</Box> </Box>
@@ -132,12 +162,13 @@ export const DateTimeFields: React.FC<DateTimeFieldsProps> = ({
{/* Error message right column - 50% */} {/* Error message right column - 50% */}
<Box sx={{ flexGrow: 0.5, flexBasis: "50%" }}> <Box sx={{ flexGrow: 0.5, flexBasis: "50%" }}>
<Typography variant="caption" color="error"> <Typography variant="caption" sx={{ color: "error.main" }}>
{validation.errors.dateTime} {validation.errors.dateTime}
</Typography> </Typography>
</Box> </Box>
</Box> </Box>
)} )}
</Box> </Box>
</LocalizationProvider>
); );
}; };