diff --git a/src/components/AddSlotModal/addSlotModal.tsx b/src/components/AddSlotModal/addSlotModal.tsx index d6602de..930bb2e 100644 --- a/src/components/AddSlotModal/addSlotModal.tsx +++ b/src/components/AddSlotModal/addSlotModal.tsx @@ -1,4 +1,152 @@ -import React, { useState } from "react"; +// import React, { useState } from "react"; +// import { +// Dialog, +// DialogActions, +// DialogContent, +// DialogTitle, +// Button, +// TextField, +// Typography, +// Box, +// } from "@mui/material"; +// import { useForm } from "react-hook-form"; + +// const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => { +// const { +// register, +// handleSubmit, +// reset, +// formState: { errors }, +// } = useForm(); +// const [isAvailable, setIsAvailable] = useState(true); // Default is available + +// // Get today's date in the format yyyy-mm-dd +// const today = new Date().toISOString().split("T")[0]; + +// const onSubmit = (data: { +// date: string; +// startHour: string; +// endHour: string; +// }) => { +// handleAddSlot({ ...data, isAvailable }); +// reset(); +// handleClose(); +// }; + +// return ( +// +// Add EV Slot +// +//
+// +// Date +// +// +// value >= today || "Date cannot be in the past", +// })} +// // label="Date" +// // sx={{ marginTop: 1 }} +// type="date" +// fullWidth +// margin="normal" +// slotProps={{ +// inputLabel: { +// shrink: true, +// }, +// }} +// error={!!errors.date} +// helperText={errors.date?.message} +// // Set the min value to today's date +// inputProps={{ min: today }} +// /> +// +// Start Hour +// +// +// +// End Hour +// +// +// {/* Availability Toggle */} +// + +// +// +// {isAvailable ? "Available" : "Not Available"} +// +// +// +// + +// +// +// +//
+//
+// ); +// }; + +// export default AddSlotModal; +import React, { useState, useEffect } from "react"; import { Dialog, DialogActions, @@ -8,6 +156,12 @@ import { TextField, Typography, Box, + FormControlLabel, + Switch, + MenuItem, + Select, + FormControl, + InputLabel, } from "@mui/material"; import { useForm } from "react-hook-form"; @@ -16,19 +170,77 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => { register, handleSubmit, reset, + watch, formState: { errors }, } = useForm(); - const [isAvailable, setIsAvailable] = useState(true); // Default is available + const [isAvailable, setIsAvailable] = useState(true); + const [isDateRange, setIsDateRange] = useState(false); + const [durationUnit, setDurationUnit] = useState("minutes"); + const [minEndTime, setMinEndTime] = useState(""); // Get today's date in the format yyyy-mm-dd const today = new Date().toISOString().split("T")[0]; - const onSubmit = (data: { - date: string; - startHour: string; - endHour: string; - }) => { - handleAddSlot({ ...data, isAvailable }); + // Watch the start time value + const startHour = watch("startHour"); + + useEffect(() => { + if (startHour) { + setMinEndTime(startHour); + } + }, [startHour]); + + const onSubmit = (data: any) => { + const { date, startDate, endDate, startHour, endHour, duration } = data; + const slots: { date: string; startHour: string; endHour: string; isAvailable: boolean; duration: number; }[] = []; + + const generateSlotsForDate = (date: string) => { + const startTime = new Date(`1970-01-01T${startHour}:00`); + const endTime = new Date(`1970-01-01T${endHour}:00`); + let durationMinutes = parseInt(duration, 10); + + if (durationUnit === "hours") { + durationMinutes *= 60; + } + + for ( + let time = startTime; + time < endTime; + time.setMinutes(time.getMinutes() + durationMinutes) + ) { + const slotEndTime = new Date(time); + slotEndTime.setMinutes( + slotEndTime.getMinutes() + durationMinutes + ); + + if (slotEndTime <= endTime) { + slots.push({ + date, + startHour: time.toTimeString().slice(0, 5), + endHour: slotEndTime.toTimeString().slice(0, 5), + isAvailable, + duration: durationMinutes, + }); + } + } + }; + + if (isDateRange) { + const start = new Date(startDate); + const end = new Date(endDate); + for ( + let d = new Date(start); + d <= end; + d.setDate(d.getDate() + 1) + ) { + const dateString = d.toISOString().split("T")[0]; + generateSlotsForDate(dateString); + } + } else { + generateSlotsForDate(date); + } + + handleAddSlot(slots); reset(); handleClose(); }; @@ -38,30 +250,73 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => { Add EV Slot
- - Date - - - value >= today || "Date cannot be in the past", - })} - // label="Date" - // sx={{ marginTop: 1 }} - type="date" - fullWidth - margin="normal" - slotProps={{ - inputLabel: { - shrink: true, - }, - }} - error={!!errors.date} - helperText={errors.date?.message} - // Set the min value to today's date - inputProps={{ min: today }} + setIsDateRange(!isDateRange)} + /> + } + label="Select Date Range" /> + {isDateRange ? ( + <> + + Start Date + + + value >= today || + "Start date cannot be in the past", + })} + type="date" + fullWidth + margin="normal" + error={!!errors.startDate} + helperText={errors.startDate?.message} + inputProps={{ min: today }} + /> + + End Date + + + value >= today || + "End date cannot be in the past", + })} + type="date" + fullWidth + margin="normal" + error={!!errors.endDate} + helperText={errors.endDate?.message} + inputProps={{ min: today }} + /> + + ) : ( + <> + + Date + + + value >= today || + "Date cannot be in the past", + })} + type="date" + fullWidth + margin="normal" + error={!!errors.date} + helperText={errors.date?.message} + inputProps={{ min: today }} + /> + + )} Start Hour @@ -69,16 +324,9 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => { {...register("startHour", { required: "Start hour is required", })} - // label="Start Hour" type="time" - // sx={{ marginTop: 1 }} fullWidth margin="normal" - slotProps={{ - inputLabel: { - shrink: true, - }, - }} error={!!errors.startHour} helperText={errors.startHour?.message} /> @@ -88,32 +336,60 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => { + value > startHour || + "End hour must be after start hour", })} - // label="End Hour" type="time" - // sx={{ marginTop: 1 }} fullWidth margin="normal" - InputLabelProps={{ - shrink: true, - }} error={!!errors.endHour} helperText={errors.endHour?.message} + inputProps={{ min: minEndTime }} /> - {/* Availability Toggle */} + + Slot Duration + + + + + Unit + + + - @@ -125,7 +401,6 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => { - + + {isAvailable ? "Available" : "Not Available"} + + + + + + + +
+ + ); +}; + +export default AddSlotModal; diff --git a/src/components/EditVehicleModal/editVehicleModal.tsx b/src/components/EditVehicleModal/editVehicleModal.tsx index e7a6863..3501516 100644 --- a/src/components/EditVehicleModal/editVehicleModal.tsx +++ b/src/components/EditVehicleModal/editVehicleModal.tsx @@ -1,27 +1,20 @@ -import React, { useEffect } from "react"; -import { - Box, - Button, - Typography, - Modal, -} from "@mui/material"; +import React, { useEffect, useState } from "react"; +import { Box, Button, Typography, Modal } from "@mui/material"; import CloseIcon from "@mui/icons-material/Close"; import { useForm, Controller } from "react-hook-form"; import { updateVehicle } from "../../redux/slices/VehicleSlice"; -import { - CustomIconButton, - CustomTextField, -} from "../AddUserModal/styled.css"; +import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css"; + interface EditVehicleModalProps { open: boolean; handleClose: () => void; handleUpdate: ( id: string, name: string, - email: string, - phone: string, - registeredAddress: string, - imageUrl: string + company: string, + modelName: string, + chargeType: string, + imageUrl: File | null ) => void; editRow: any; } @@ -31,7 +24,7 @@ interface FormData { company: string; modelName: string; chargeType: string; - imageUrl: string; + imageUrl: File | null; } const EditVehicleModal: React.FC = ({ @@ -52,37 +45,57 @@ const EditVehicleModal: React.FC = ({ company: "", modelName: "", chargeType: "", - imageUrl: "", + imageUrl: null, }, }); // Set values if editRow is provided + const [imagePreview, setImagePreview] = useState(null); + useEffect(() => { if (editRow) { + // Construct full image URL + const imageUrl = `${process.env.REACT_APP_BACKEND_URL}/image/${editRow.imageUrl}`; + setImagePreview(imageUrl); // Set the image URL to display the preview setValue("name", editRow.name); setValue("company", editRow.company); setValue("modelName", editRow.modelName); setValue("chargeType", editRow.chargeType); - setValue("imageUrl", editRow.imageUrl); } else { reset(); } }, [editRow, setValue, reset]); - const onSubmit = (data: FormData) => { - if (editRow) { - handleUpdate( - editRow.id, - data.name, - data.company, - data.modelName, - data.chargeType, - data.imageUrl - ); - } - handleClose(); // Close the modal - reset(); // Reset the form fields - }; + + +const handleImageChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file) { + setImagePreview(URL.createObjectURL(file)); // Preview the image + setValue("imageUrl", file); // Set the file in the form + } +}; + +const onSubmit = (data: FormData) => { + // Check if a new image was selected and set its URL or filename + const imageUrl = data.imageUrl + ? `${process.env.REACT_APP_BACKEND_URL}/image/${data.imageUrl.name}` // Assuming image is a file object + : editRow?.imageUrl; // Keep existing image if not changed + + handleUpdate( + editRow.id, + data.name, + data.company, + data.modelName, + data.chargeType, + imageUrl // Send the updated image URL or filename to backend + ); + + handleClose(); + reset(); +}; + + return ( = ({ name="name" control={control} rules={{ - required: "Vehicle Name is required", - minLength: { - value: 3, - message: - "Minimum 3 characters required", - }, - maxLength: { - value: 30, - message: - "Maximum 30 characters allowed", - }, - pattern: { - value: /^[A-Za-z\s]+$/, // Only letters and spaces are allowed - message: - "Vehicle Name must only contain letters and spaces", - }, - }} + required: "Vehicle Name is required", + minLength: { + value: 3, + message: + "Minimum 3 characters required", + }, + maxLength: { + value: 30, + message: + "Maximum 30 characters allowed", + }, + pattern: { + value: /^[A-Za-z\s]+$/, // Only letters and spaces are allowed + message: + "Vehicle Name must only contain letters and spaces", + }, + }} render={({ field }) => ( = ({ sx={{ marginTop: 1 }} error={!!errors.name} helperText={errors.name?.message} - /> )} /> @@ -283,7 +295,7 @@ const EditVehicleModal: React.FC = ({ - {/* Third Row - Image URL Input */} + {/* Image Upload */} = ({ }} > - Image URL + Upload Image - ( - + Upload Image + + + {imagePreview && ( + + + Preview: + + image preview - )} - /> + + )} diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 6843b06..a086df8 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -61,7 +61,7 @@ export default function Header() { }} > {/* Search Bar */} - - + */} {/* Notification and Profile Section */} - + /> */}