299 lines
6.9 KiB
TypeScript
299 lines
6.9 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import {
|
|
Box,
|
|
Button,
|
|
Typography,
|
|
Modal,
|
|
FormControlLabel,
|
|
Switch,
|
|
TextField,
|
|
MenuItem,
|
|
Select,
|
|
InputLabel,
|
|
FormControl,
|
|
} from "@mui/material";
|
|
import { useForm } from "react-hook-form";
|
|
import { useDispatch } from "react-redux";
|
|
import { createSlot } from "../../redux/slices/slotSlice.ts"; // Assuming this is your slice
|
|
import CloseIcon from "@mui/icons-material/Close";
|
|
import { CustomIconButton } from "../AddUserModal/styled.css"; // Assuming this is for custom styled components
|
|
|
|
const AddSlotModal = ({ open, handleClose }: any) => {
|
|
const dispatch = useDispatch(); // Get dispatch from Redux
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
reset,
|
|
watch,
|
|
formState: { errors },
|
|
} = useForm();
|
|
|
|
const [isAvailable, setIsAvailable] = useState<boolean>(true);
|
|
const [isDateRange, setIsDateRange] = useState<boolean>(false);
|
|
const [minEndTime, setMinEndTime] = useState<string>("");
|
|
const [durationUnit, setDurationUnit] = useState<string>("minutes"); // New state for duration unit
|
|
|
|
const today = new Date().toISOString().split("T")[0];
|
|
const startHour = watch("startHour");
|
|
|
|
useEffect(() => {
|
|
if (startHour) {
|
|
setMinEndTime(startHour);
|
|
}
|
|
}, [startHour]);
|
|
|
|
const onSubmit = (data: any) => {
|
|
const { date, startingDate, endingDate, startHour, endHour, duration } =
|
|
data;
|
|
|
|
const payload = isDateRange
|
|
? {
|
|
startingDate,
|
|
endingDate,
|
|
startHour,
|
|
endHour,
|
|
duration: parseInt(duration, 10),
|
|
durationUnit, // Include the duration unit (minutes or hours)
|
|
isAvailable,
|
|
}
|
|
: {
|
|
date,
|
|
startHour,
|
|
endHour,
|
|
duration: parseInt(duration, 10),
|
|
durationUnit, // Include the duration unit (minutes or hours)
|
|
isAvailable,
|
|
};
|
|
|
|
dispatch(createSlot(payload));
|
|
reset();
|
|
handleClose();
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
open={open}
|
|
onClose={(e, reason) => {
|
|
if (reason === "backdropClick") {
|
|
return;
|
|
}
|
|
handleClose();
|
|
}}
|
|
aria-labelledby="add-slot-modal"
|
|
>
|
|
<Box
|
|
component="form"
|
|
onSubmit={handleSubmit(onSubmit)}
|
|
sx={{
|
|
position: "absolute",
|
|
top: "50%",
|
|
left: "50%",
|
|
transform: "translate(-50%, -50%)",
|
|
width: 400,
|
|
bgcolor: "background.paper",
|
|
boxShadow: 24,
|
|
p: 3,
|
|
borderRadius: 2,
|
|
}}
|
|
>
|
|
{/* Header */}
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<Typography variant="h6" fontWeight={600} fontSize={"16px"}>
|
|
Add Slot
|
|
</Typography>
|
|
<CustomIconButton onClick={handleClose}>
|
|
<CloseIcon />
|
|
</CustomIconButton>
|
|
</Box>
|
|
|
|
{/* Horizontal Line */}
|
|
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
|
|
|
{/* Date Range Toggle */}
|
|
<FormControlLabel
|
|
control={
|
|
<Switch
|
|
checked={isDateRange}
|
|
onChange={() => setIsDateRange(!isDateRange)}
|
|
/>
|
|
}
|
|
label="Select Date Range"
|
|
sx={{
|
|
fontWeight: 500,
|
|
fontSize: "16px",
|
|
margin: 0,
|
|
}}
|
|
/>
|
|
|
|
{/* Date Input Fields */}
|
|
{isDateRange ? (
|
|
<>
|
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
|
Start Date
|
|
</Typography>
|
|
<TextField
|
|
{...register("startingDate", {
|
|
required: "Start date is required",
|
|
validate: (value) =>
|
|
value >= today ||
|
|
"Start date cannot be in the past",
|
|
})}
|
|
type="date"
|
|
fullWidth
|
|
error={!!errors.startingDate}
|
|
helperText={errors.startingDate?.message}
|
|
inputProps={{ min: today }}
|
|
/>
|
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
|
End Date
|
|
</Typography>
|
|
<TextField
|
|
{...register("endingDate", {
|
|
required: "End date is required",
|
|
validate: (value) =>
|
|
value >= today ||
|
|
"End date cannot be in the past",
|
|
})}
|
|
type="date"
|
|
fullWidth
|
|
error={!!errors.endingDate}
|
|
helperText={errors.endingDate?.message}
|
|
inputProps={{ min: today }}
|
|
/>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
|
Date
|
|
</Typography>
|
|
<TextField
|
|
{...register("date", {
|
|
required: "Date is required",
|
|
validate: (value) =>
|
|
value >= today ||
|
|
"Date cannot be in the past",
|
|
})}
|
|
type="date"
|
|
fullWidth
|
|
error={!!errors.date}
|
|
helperText={errors.date?.message}
|
|
inputProps={{ min: today }}
|
|
/>
|
|
</>
|
|
)}
|
|
|
|
{/* Start Hour */}
|
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
|
Start Hour
|
|
</Typography>
|
|
<TextField
|
|
{...register("startHour", {
|
|
required: "Start hour is required",
|
|
})}
|
|
type="time"
|
|
fullWidth
|
|
error={!!errors.startHour}
|
|
helperText={errors.startHour?.message}
|
|
/>
|
|
|
|
{/* End Hour */}
|
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
|
End Hour
|
|
</Typography>
|
|
<TextField
|
|
{...register("endHour", {
|
|
required: "End hour is required",
|
|
validate: (value) =>
|
|
value > startHour ||
|
|
"End hour must be after start hour",
|
|
})}
|
|
type="time"
|
|
fullWidth
|
|
error={!!errors.endHour}
|
|
helperText={errors.endHour?.message}
|
|
inputProps={{ min: minEndTime }}
|
|
/>
|
|
|
|
{/* Duration and Duration Unit */}
|
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
|
Slot Duration
|
|
</Typography>
|
|
<Box display="flex" alignItems="center" gap={2}>
|
|
<TextField
|
|
{...register("duration", {
|
|
required: "Duration is required",
|
|
pattern: {
|
|
value: /^[0-9]+$/,
|
|
message: "Duration must be a number",
|
|
},
|
|
})}
|
|
type="number"
|
|
fullWidth
|
|
error={!!errors.duration}
|
|
helperText={errors.duration?.message}
|
|
/>
|
|
|
|
{/* Dropdown for selecting Minutes/Hours */}
|
|
<FormControl fullWidth>
|
|
<InputLabel>Unit</InputLabel>
|
|
<Select
|
|
value={durationUnit}
|
|
onChange={(e) => setDurationUnit(e.target.value)}
|
|
>
|
|
<MenuItem value="minutes">Minutes</MenuItem>
|
|
<MenuItem value="hours">Hours</MenuItem>
|
|
</Select>
|
|
</FormControl>
|
|
</Box>
|
|
|
|
{/* Availability Toggle */}
|
|
<Box
|
|
display="flex"
|
|
alignItems="center"
|
|
justifyContent="space-between"
|
|
gap={2}
|
|
>
|
|
<Button
|
|
onClick={() => setIsAvailable((prev) => !prev)}
|
|
variant={isAvailable ? "contained" : "outlined"}
|
|
color="primary"
|
|
sx={{ marginTop: 1 }}
|
|
>
|
|
Check Availability
|
|
</Button>
|
|
<Typography>
|
|
{isAvailable ? "Available" : "Not Available"}
|
|
</Typography>
|
|
</Box>
|
|
|
|
{/* Submit Button */}
|
|
<Box
|
|
sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}
|
|
>
|
|
<Button
|
|
type="submit"
|
|
sx={{
|
|
backgroundColor: "#52ACDF",
|
|
color: "white",
|
|
borderRadius: "8px",
|
|
fontSize: "16px",
|
|
width: "117px",
|
|
"&:hover": { backgroundColor: "#439BC1" },
|
|
}}
|
|
>
|
|
Add Slot
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
export default AddSlotModal;
|