dev-jaanvi #1
|
@ -1,17 +1,20 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Dialog,
|
Typography,
|
||||||
DialogActions,
|
Modal,
|
||||||
DialogContent,
|
InputAdornment,
|
||||||
DialogTitle,
|
|
||||||
IconButton,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import Visibility from "@mui/icons-material/Visibility";
|
||||||
|
import VisibilityOff from "@mui/icons-material/VisibilityOff";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { Visibility, VisibilityOff } from "@mui/icons-material";
|
import {
|
||||||
|
CustomIconButton,
|
||||||
|
CustomTextField,
|
||||||
|
} from "../AddUserModel/styled.css.tsx";
|
||||||
|
|
||||||
//By Jaanvi : Edit Model :: 11-feb-25
|
//By Jaanvi : Edit Model :: 11-feb-25
|
||||||
interface AddEditCategoryModalProps {
|
interface AddEditCategoryModalProps {
|
||||||
|
@ -44,6 +47,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
|
||||||
handleUpdate,
|
handleUpdate,
|
||||||
editRow,
|
editRow,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [showPassword, setShowPassword] = React.useState(false);
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
@ -59,7 +63,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
|
||||||
password: "",
|
password: "",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = (data: FormData) => {
|
const onSubmit = (data: FormData) => {
|
||||||
if (editRow) {
|
if (editRow) {
|
||||||
handleUpdate(
|
handleUpdate(
|
||||||
|
@ -77,6 +81,10 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
|
||||||
reset();
|
reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const togglePasswordVisibility = () => {
|
||||||
|
setShowPassword((prev) => !prev);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editRow) {
|
if (editRow) {
|
||||||
setValue("name", editRow.name);
|
setValue("name", editRow.name);
|
||||||
|
@ -88,217 +96,327 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
|
||||||
}
|
}
|
||||||
}, [editRow, setValue, reset]);
|
}, [editRow, setValue, reset]);
|
||||||
|
|
||||||
const [showPassword, setShowPassword] = React.useState(false);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Modal
|
||||||
open={open}
|
open={open}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
maxWidth="md"
|
aria-labelledby="add-edit-category-modal"
|
||||||
fullWidth
|
|
||||||
PaperProps={{
|
|
||||||
component: "form",
|
|
||||||
onSubmit: handleSubmit(onSubmit),
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<DialogTitle
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
position: "absolute",
|
||||||
alignItems: "center",
|
top: "50%",
|
||||||
justifyContent: "space-between",
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
width: 600,
|
||||||
|
bgcolor: "background.paper",
|
||||||
|
boxShadow: 24,
|
||||||
|
p: 3,
|
||||||
|
borderRadius: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{editRow ? "Edit Admin" : "Add Admin"}
|
{/* Header */}
|
||||||
<Box
|
<Box
|
||||||
onClick={handleClose}
|
|
||||||
sx={{
|
sx={{
|
||||||
cursor: "pointer",
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseIcon />
|
<Typography variant="h6" fontWeight={600}>
|
||||||
|
{editRow ? "Edit Admin" : "Add Admin"}
|
||||||
|
</Typography>
|
||||||
|
<CustomIconButton onClick={handleClose}>
|
||||||
|
<CloseIcon />
|
||||||
|
</CustomIconButton>
|
||||||
</Box>
|
</Box>
|
||||||
</DialogTitle>
|
|
||||||
|
|
||||||
<DialogContent>
|
{/* Horizontal Line */}
|
||||||
<Controller
|
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
||||||
name="name"
|
|
||||||
control={control}
|
|
||||||
rules={{
|
|
||||||
required: "Admin Name is required",
|
|
||||||
minLength: {
|
|
||||||
value: 3,
|
|
||||||
message: "Minimum 3 characters required",
|
|
||||||
},
|
|
||||||
maxLength: {
|
|
||||||
value: 30,
|
|
||||||
message: "Maximum 30 characters allowed",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
render={({ field }) => (
|
|
||||||
<TextField
|
|
||||||
{...field}
|
|
||||||
autoFocus
|
|
||||||
required
|
|
||||||
margin="dense"
|
|
||||||
label="Admin Name"
|
|
||||||
type="text"
|
|
||||||
fullWidth
|
|
||||||
variant="standard"
|
|
||||||
error={!!errors.name}
|
|
||||||
helperText={errors.name?.message}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Controller
|
{/* Form */}
|
||||||
name="email"
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
control={control}
|
{/* Input Fields */}
|
||||||
rules={{
|
<Box
|
||||||
required: "Email is required",
|
sx={{
|
||||||
pattern: {
|
display: "flex",
|
||||||
value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
flexDirection: "column",
|
||||||
message: "Invalid email address",
|
gap: 2,
|
||||||
},
|
|
||||||
}}
|
|
||||||
render={({ field }) => (
|
|
||||||
<TextField
|
|
||||||
{...field}
|
|
||||||
required
|
|
||||||
margin="dense"
|
|
||||||
label="Email"
|
|
||||||
type="email"
|
|
||||||
fullWidth
|
|
||||||
variant="standard"
|
|
||||||
error={!!errors.email}
|
|
||||||
helperText={errors.email?.message}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{!editRow && (
|
|
||||||
<Controller
|
|
||||||
name="password"
|
|
||||||
control={control}
|
|
||||||
rules={{
|
|
||||||
required: "password is required",
|
|
||||||
}}
|
}}
|
||||||
render={({ field }) => (
|
>
|
||||||
<>
|
{/* First Row - Two Inputs */}
|
||||||
|
<Box sx={{ display: "flex", gap: 2 }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "50%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Admin Name
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="name"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Admin Name is required",
|
||||||
|
minLength: {
|
||||||
|
value: 3,
|
||||||
|
message:
|
||||||
|
"Minimum 3 characters required",
|
||||||
|
},
|
||||||
|
maxLength: {
|
||||||
|
value: 30,
|
||||||
|
message:
|
||||||
|
"Maximum 30 characters allowed",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
required
|
||||||
|
placeholder="Enter Admin Name"
|
||||||
|
fullWidth
|
||||||
|
size="small"
|
||||||
|
error={!!errors.name}
|
||||||
|
helperText={errors.name?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "50%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Email
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="email"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Email is required",
|
||||||
|
pattern: {
|
||||||
|
value: /\S+@\S+\.\S+/,
|
||||||
|
message:
|
||||||
|
"Please enter a valid email address.",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
error={!!errors.email}
|
||||||
|
helperText={errors.email?.message}
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
placeholder="Email"
|
||||||
|
required
|
||||||
|
fullWidth
|
||||||
|
color={
|
||||||
|
errors.email
|
||||||
|
? "error"
|
||||||
|
: "primary"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Second Row - Two Inputs */}
|
||||||
|
<Box sx={{ display: "flex", gap: 2 }}>
|
||||||
|
{!editRow && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
flexDirection: "column",
|
||||||
|
width: "50%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
fontWeight={500}
|
||||||
|
>
|
||||||
|
Password
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="password"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Password is required",
|
||||||
|
minLength: {
|
||||||
|
value: 6,
|
||||||
|
message:
|
||||||
|
"Password must be at least 6 characters long.",
|
||||||
|
},
|
||||||
|
pattern: {
|
||||||
|
value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,}$/,
|
||||||
|
message:
|
||||||
|
"Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character.",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
required
|
||||||
|
placeholder="Enter Password"
|
||||||
|
type={
|
||||||
|
showPassword
|
||||||
|
? "text"
|
||||||
|
: "password"
|
||||||
|
}
|
||||||
|
id="password"
|
||||||
|
fullWidth
|
||||||
|
color={
|
||||||
|
errors.password
|
||||||
|
? "error"
|
||||||
|
: "primary"
|
||||||
|
}
|
||||||
|
size="small"
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<CustomIconButton
|
||||||
|
aria-label="toggle password visibility"
|
||||||
|
onClick={
|
||||||
|
togglePasswordVisibility
|
||||||
|
}
|
||||||
|
edge="end"
|
||||||
|
>
|
||||||
|
{showPassword ? (
|
||||||
|
<VisibilityOff />
|
||||||
|
) : (
|
||||||
|
<Visibility />
|
||||||
|
)}
|
||||||
|
</CustomIconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
error={!!errors.password}
|
||||||
|
helperText={
|
||||||
|
errors.password?.message
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "50%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Phone Number
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="phone"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Phone number is required",
|
||||||
|
pattern: {
|
||||||
|
value: /^[0-9]*$/,
|
||||||
|
message: "Only numbers are allowed",
|
||||||
|
},
|
||||||
|
minLength: {
|
||||||
|
value: 6,
|
||||||
|
message:
|
||||||
|
"Phone number must be at least 6 digits",
|
||||||
|
},
|
||||||
|
maxLength: {
|
||||||
|
value: 14,
|
||||||
|
message:
|
||||||
|
"Phone number must be at most 14 digits",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
required
|
||||||
|
placeholder="Enter Phone Number"
|
||||||
|
size="small"
|
||||||
|
error={!!errors.phone}
|
||||||
|
helperText={errors.phone?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Third Row - One Input */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "50%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Address
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="registeredAddress"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Address is required",
|
||||||
|
maxLength: {
|
||||||
|
value: 100,
|
||||||
|
message:
|
||||||
|
"Address cannot exceed 100 characters",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
{...field}
|
{...field}
|
||||||
required
|
required
|
||||||
margin="dense"
|
placeholder="Enter Address"
|
||||||
label="Password"
|
|
||||||
type={
|
|
||||||
showPassword ? "text" : "password"
|
|
||||||
}
|
|
||||||
id="password"
|
|
||||||
autoComplete="current-password"
|
|
||||||
autoFocus
|
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="standard"
|
size="small"
|
||||||
error={!!errors.password}
|
error={!!errors.registeredAddress}
|
||||||
helperText={errors.password?.message}
|
helperText={
|
||||||
/>
|
errors.registeredAddress?.message
|
||||||
<IconButton
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
right: "10px",
|
|
||||||
top: "50%",
|
|
||||||
transform: "translateY(-50%)", // Center vertically
|
|
||||||
backgroundColor: "transparent", // Remove background color
|
|
||||||
border: "none", // Remove any border
|
|
||||||
boxShadow: "none", // Remove any shadow
|
|
||||||
padding: 0, // Remove padding to ensure it's fully transparent
|
|
||||||
|
|
||||||
|
|
||||||
}}
|
|
||||||
onClick={() =>
|
|
||||||
setShowPassword((prev) => !prev)
|
|
||||||
}
|
}
|
||||||
>
|
/>
|
||||||
{showPassword ? (
|
)}
|
||||||
<VisibilityOff />
|
/>
|
||||||
) : (
|
</Box>
|
||||||
<Visibility />
|
</Box>
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Controller
|
|
||||||
name="phone"
|
|
||||||
control={control}
|
|
||||||
rules={{
|
|
||||||
required: "Phone number is required",
|
|
||||||
pattern: {
|
|
||||||
value: /^[0-9]*$/,
|
|
||||||
message: "Only numbers are allowed",
|
|
||||||
},
|
|
||||||
minLength: {
|
|
||||||
value: 6,
|
|
||||||
message: "Phone number must be exactly 6 digits",
|
|
||||||
},
|
|
||||||
maxLength: {
|
|
||||||
value: 14,
|
|
||||||
message: "Phone number must be exactly 14 digits",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
render={({ field }) => (
|
|
||||||
<TextField
|
|
||||||
{...field}
|
|
||||||
required
|
|
||||||
margin="dense"
|
|
||||||
label="Phone Number"
|
|
||||||
type="tel"
|
|
||||||
fullWidth
|
|
||||||
variant="standard"
|
|
||||||
error={!!errors.phone}
|
|
||||||
helperText={errors.phone?.message}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Controller
|
{/* Submit Button */}
|
||||||
name="registeredAddress"
|
<Box
|
||||||
control={control}
|
sx={{
|
||||||
rules={{
|
display: "flex",
|
||||||
required: "Address is required",
|
justifyContent: "flex-end",
|
||||||
maxLength: {
|
width: "100%",
|
||||||
value: 100,
|
mt: 3,
|
||||||
message: "Address cannot exceed 100 characters",
|
}}
|
||||||
},
|
>
|
||||||
}}
|
<Button
|
||||||
render={({ field }) => (
|
type="submit"
|
||||||
<TextField
|
sx={{
|
||||||
{...field}
|
backgroundColor: "#52ACDF",
|
||||||
required
|
color: "white",
|
||||||
margin="dense"
|
borderRadius: "8px",
|
||||||
label="Address"
|
width: "117px",
|
||||||
type="text"
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
fullWidth
|
}}
|
||||||
variant="standard"
|
>
|
||||||
error={!!errors.registeredAddress}
|
{editRow ? "Update Admin" : "Add Admin"}
|
||||||
helperText={errors.registeredAddress?.message}
|
</Button>
|
||||||
/>
|
</Box>
|
||||||
)}
|
</form>
|
||||||
/>
|
</Box>
|
||||||
</DialogContent>
|
</Modal>
|
||||||
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={handleClose}>Cancel</Button>
|
|
||||||
<Button type="submit">{editRow ? "Update" : "Create"}</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,27 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Dialog,
|
Typography,
|
||||||
DialogActions,
|
|
||||||
DialogContent,
|
|
||||||
DialogTitle,
|
|
||||||
TextField,
|
TextField,
|
||||||
|
Modal,
|
||||||
|
IconButton,
|
||||||
|
InputAdornment,
|
||||||
|
styled,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import Visibility from "@mui/icons-material/Visibility";
|
||||||
|
import VisibilityOff from "@mui/icons-material/VisibilityOff";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
|
import { CustomIconButton, CustomTextField } from "./styled.css.tsx";
|
||||||
|
|
||||||
//By Jaanvi : Edit Model :: 11-feb-25
|
|
||||||
|
interface FormData {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
phone: string;
|
||||||
|
}
|
||||||
interface AddUserModalProps {
|
interface AddUserModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
|
@ -20,52 +30,55 @@ interface AddUserModalProps {
|
||||||
id: string,
|
id: string,
|
||||||
name: string,
|
name: string,
|
||||||
email: string,
|
email: string,
|
||||||
|
password: string,
|
||||||
phone: string,
|
phone: string,
|
||||||
password: string
|
|
||||||
) => void;
|
) => void;
|
||||||
editRow: any;
|
editRow: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FormData {
|
|
||||||
name: string;
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
const AddUserModal: React.FC<AddUserModalProps> = ({
|
const AddUserModal: React.FC<AddUserModalProps> = ({
|
||||||
open,
|
open,
|
||||||
handleClose,
|
handleClose,
|
||||||
handleCreate,
|
handleCreate,
|
||||||
|
handleUpdate,
|
||||||
editRow,
|
editRow,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
setValue,
|
|
||||||
reset,
|
reset,
|
||||||
} = useForm<FormData>({
|
} = useForm<FormData>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
email: "",
|
||||||
|
password: "",
|
||||||
phone: "",
|
phone: "",
|
||||||
password: "",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (editRow) {
|
||||||
|
// setValue("name", editRow.name);
|
||||||
|
// setValue("email", editRow.email);
|
||||||
|
// setValue("password", editRow.password);
|
||||||
|
// setValue("phone", editRow.phone);
|
||||||
|
// } else {
|
||||||
|
// reset();
|
||||||
|
// }
|
||||||
|
// }, [editRow, setValue, reset]);
|
||||||
|
|
||||||
const onSubmit = (data: FormData) => {
|
const onSubmit = (data: FormData) => {
|
||||||
if (editRow) {
|
if (editRow) {
|
||||||
|
|
||||||
handleUpdate(
|
handleUpdate(
|
||||||
editRow.id,
|
editRow.id,
|
||||||
data.name,
|
data.name,
|
||||||
data.email,
|
data.email,
|
||||||
data.phone,
|
data.password,
|
||||||
data.password
|
data.phone
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
handleCreate(data);
|
handleCreate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,156 +86,290 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
|
||||||
reset();
|
reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const togglePasswordVisibility = () => {
|
||||||
|
setShowPassword((prev) => !prev);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Modal
|
||||||
open={open}
|
open={open}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
maxWidth="md"
|
aria-labelledby="add-user-modal"
|
||||||
fullWidth
|
|
||||||
PaperProps={{
|
|
||||||
component: "form",
|
|
||||||
onSubmit: handleSubmit(onSubmit),
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<DialogTitle
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
position: "absolute",
|
||||||
alignItems: "center",
|
top: "50%",
|
||||||
justifyContent: "space-between",
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
width: 600, // Adjusted the width for a wider modal
|
||||||
|
bgcolor: "background.paper",
|
||||||
|
boxShadow: 24,
|
||||||
|
p: 3,
|
||||||
|
borderRadius: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{editRow ? "Edit User" : "Add User"}
|
{/* Header */}
|
||||||
<Box
|
<Box
|
||||||
onClick={handleClose}
|
|
||||||
sx={{
|
sx={{
|
||||||
cursor: "pointer",
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseIcon />
|
<Typography variant="h6" fontWeight={600}>
|
||||||
|
{editRow ? "Edit User" : "Add User"}
|
||||||
|
</Typography>
|
||||||
|
<CustomIconButton onClick={handleClose}>
|
||||||
|
<CloseIcon />
|
||||||
|
</CustomIconButton>
|
||||||
</Box>
|
</Box>
|
||||||
</DialogTitle>
|
|
||||||
|
|
||||||
<DialogContent>
|
{/* Horizontal Line */}
|
||||||
<Controller
|
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
||||||
name="name"
|
|
||||||
control={control}
|
|
||||||
rules={{
|
|
||||||
required: "Admin Name is required",
|
|
||||||
minLength: {
|
|
||||||
value: 3,
|
|
||||||
message: "Minimum 3 characters required",
|
|
||||||
},
|
|
||||||
maxLength: {
|
|
||||||
value: 30,
|
|
||||||
message: "Maximum 30 characters allowed",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
render={({ field }) => (
|
|
||||||
<TextField
|
|
||||||
{...field}
|
|
||||||
autoFocus
|
|
||||||
required
|
|
||||||
margin="dense"
|
|
||||||
label="User Name"
|
|
||||||
type="text"
|
|
||||||
fullWidth
|
|
||||||
variant="standard"
|
|
||||||
error={!!errors.name}
|
|
||||||
helperText={errors.name?.message}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Controller
|
{/* Form */}
|
||||||
name="email"
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
control={control}
|
{/* Input Fields */}
|
||||||
rules={{
|
<Box
|
||||||
required: "Email is required",
|
sx={{
|
||||||
pattern: {
|
display: "flex",
|
||||||
value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
flexDirection: "column",
|
||||||
message: "Invalid email address",
|
gap: 2,
|
||||||
},
|
}}
|
||||||
}}
|
>
|
||||||
render={({ field }) => (
|
{/* First Row - Two Inputs */}
|
||||||
<TextField
|
<Box sx={{ display: "flex", gap: 2 }}>
|
||||||
{...field}
|
<Box
|
||||||
required
|
sx={{
|
||||||
margin="dense"
|
display: "flex",
|
||||||
label="Email"
|
flexDirection: "column",
|
||||||
type="email"
|
width: "100%",
|
||||||
fullWidth
|
}}
|
||||||
variant="standard"
|
>
|
||||||
error={!!errors.email}
|
<Typography variant="body2" fontWeight={500}>
|
||||||
helperText={errors.email?.message}
|
User Name
|
||||||
/>
|
</Typography>
|
||||||
)}
|
<Controller
|
||||||
/>
|
name="name"
|
||||||
<Controller
|
control={control}
|
||||||
name="password"
|
rules={{
|
||||||
control={control}
|
required: "User Name is required",
|
||||||
rules={{
|
minLength: {
|
||||||
required: "password is required",
|
value: 3,
|
||||||
}}
|
message:
|
||||||
render={({ field }) => (
|
"Minimum 3 characters required",
|
||||||
<TextField
|
},
|
||||||
{...field}
|
maxLength: {
|
||||||
required
|
value: 30,
|
||||||
margin="dense"
|
message:
|
||||||
label="Password"
|
"Maximum 30 characters allowed",
|
||||||
type="password"
|
},
|
||||||
fullWidth
|
}}
|
||||||
variant="standard"
|
render={({ field }) => (
|
||||||
error={!!errors.password}
|
<CustomTextField
|
||||||
helperText={errors.password?.message}
|
{...field}
|
||||||
/>
|
required
|
||||||
)}
|
placeholder="Enter User Name"
|
||||||
/>
|
fullWidth
|
||||||
<Controller
|
size="small"
|
||||||
name="phone"
|
error={!!errors.name}
|
||||||
control={control}
|
helperText={errors.name?.message}
|
||||||
rules={{
|
/>
|
||||||
required: "Phone number is required",
|
)}
|
||||||
pattern: {
|
/>
|
||||||
value: /^[0-9]*$/,
|
</Box>
|
||||||
message: "Only numbers are allowed",
|
|
||||||
},
|
|
||||||
minLength: {
|
|
||||||
value: 6,
|
|
||||||
message: "Phone number must be exactly 6 digits",
|
|
||||||
},
|
|
||||||
maxLength: {
|
|
||||||
value: 14,
|
|
||||||
message: "Phone number must be exactly 14 digits",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
render={({ field }) => (
|
|
||||||
<TextField
|
|
||||||
{...field}
|
|
||||||
required
|
|
||||||
margin="dense"
|
|
||||||
label="Phone Number"
|
|
||||||
type="tel"
|
|
||||||
fullWidth
|
|
||||||
variant="standard"
|
|
||||||
error={!!errors.phone}
|
|
||||||
helperText={errors.phone?.message}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</DialogContent>
|
|
||||||
|
|
||||||
<DialogActions>
|
<Box
|
||||||
<Button onClick={handleClose}>Cancel</Button>
|
sx={{
|
||||||
<Button type="submit">Create</Button>
|
display: "flex",
|
||||||
</DialogActions>
|
flexDirection: "column",
|
||||||
</Dialog>
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Email
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="email"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Email is required",
|
||||||
|
pattern: {
|
||||||
|
value: /\S+@\S+\.\S+/,
|
||||||
|
message:
|
||||||
|
"Please enter a valid email address.",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
error={!!errors.email}
|
||||||
|
helperText={errors.email?.message}
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
placeholder="Email"
|
||||||
|
required
|
||||||
|
fullWidth
|
||||||
|
color={
|
||||||
|
errors.email
|
||||||
|
? "error"
|
||||||
|
: "primary"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Second Row - Two Inputs */}
|
||||||
|
<Box sx={{ display: "flex", gap: 2 }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Password
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="password"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Password is required",
|
||||||
|
minLength: {
|
||||||
|
value: 6,
|
||||||
|
message:
|
||||||
|
"Password must be at least 6 characters long.",
|
||||||
|
},
|
||||||
|
pattern: {
|
||||||
|
value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,}$/,
|
||||||
|
message:
|
||||||
|
"Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character.",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
required
|
||||||
|
placeholder="Enter Password"
|
||||||
|
type={
|
||||||
|
showPassword
|
||||||
|
? "text"
|
||||||
|
: "password"
|
||||||
|
}
|
||||||
|
id="password"
|
||||||
|
fullWidth
|
||||||
|
color={
|
||||||
|
errors.password
|
||||||
|
? "error"
|
||||||
|
: "primary"
|
||||||
|
}
|
||||||
|
size="small"
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<CustomIconButton
|
||||||
|
aria-label="toggle password visibility"
|
||||||
|
onClick={
|
||||||
|
togglePasswordVisibility
|
||||||
|
}
|
||||||
|
edge="end"
|
||||||
|
>
|
||||||
|
{showPassword ? (
|
||||||
|
<VisibilityOff />
|
||||||
|
) : (
|
||||||
|
<Visibility />
|
||||||
|
)}
|
||||||
|
</CustomIconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
error={!!errors.password}
|
||||||
|
helperText={
|
||||||
|
errors.password?.message
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Phone Number
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="phone"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Phone number is required",
|
||||||
|
pattern: {
|
||||||
|
value: /^[0-9]*$/,
|
||||||
|
message: "Only numbers are allowed",
|
||||||
|
},
|
||||||
|
minLength: {
|
||||||
|
value: 6,
|
||||||
|
message:
|
||||||
|
"Phone number must be at least 6 digits",
|
||||||
|
},
|
||||||
|
maxLength: {
|
||||||
|
value: 14,
|
||||||
|
message:
|
||||||
|
"Phone number must be at most 14 digits",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
required
|
||||||
|
placeholder="Enter Phone Number"
|
||||||
|
size="small"
|
||||||
|
error={!!errors.phone}
|
||||||
|
helperText={errors.phone?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Submit Button */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
width: "100%",
|
||||||
|
mt: 3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#52ACDF",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
width: "117px",
|
||||||
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{editRow ? "Update User" : "Add User"}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</form>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AddUserModal;
|
export default AddUserModal;
|
||||||
function handleUpdate(id: any, name: string, email: string, phone: string, password: string) {
|
function setValue(arg0: string, name: any) {
|
||||||
throw new Error("Function not implemented.");
|
throw new Error("Function not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
src/components/AddUserModel/styled.css.tsx
Normal file
26
src/components/AddUserModel/styled.css.tsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { styled } from "@mui/material/styles";
|
||||||
|
import { IconButton, TextField } from "@mui/material";
|
||||||
|
export const CustomIconButton = styled(IconButton)({
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#272727",
|
||||||
|
},
|
||||||
|
"*:where([data-mui-color-scheme='dark']) &": {
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
border: "none",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Custom TextField with different placeholder color
|
||||||
|
export const CustomTextField = styled(TextField)({
|
||||||
|
"& .MuiInputBase-input::placeholder": {
|
||||||
|
color: "#D9D8D8",
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
"& .MuiInputBase-root.Mui-focused .MuiInputBase-input::placeholder": {
|
||||||
|
color: "darkgray",
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,42 +1,28 @@
|
||||||
import { useState } from "react";
|
import { useForm } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Typography,
|
Typography,
|
||||||
TextField,
|
|
||||||
Modal,
|
Modal,
|
||||||
IconButton,
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import { CustomIconButton, CustomTextField } from "../AddUserModel/styled.css.tsx";
|
||||||
export default function AddVehicleModal({
|
export default function AddVehicleModal({
|
||||||
open,
|
open,
|
||||||
handleClose,
|
handleClose,
|
||||||
handleAddVehicle,
|
handleAddVehicle,
|
||||||
}) {
|
}) {
|
||||||
// State for input fields
|
const {
|
||||||
const [name, setName] = useState("");
|
register,
|
||||||
const [company, setCompany] = useState("");
|
handleSubmit,
|
||||||
const [modelName, setModelName] = useState("");
|
formState: { errors },
|
||||||
const [chargeType, setChargeType] = useState("");
|
reset,
|
||||||
const [imageUrl, setImageUrl] = useState("");
|
} = useForm();
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const onSubmit = (data: any) => {
|
||||||
if (!name || !company || !modelName || !chargeType || !imageUrl) {
|
handleAddVehicle(data); // Add vehicle to table
|
||||||
alert("Please fill all fields");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newVehicle = {
|
|
||||||
name,
|
|
||||||
company,
|
|
||||||
modelName,
|
|
||||||
chargeType,
|
|
||||||
imageUrl,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleAddVehicle(newVehicle); // Add vehicle to table
|
|
||||||
handleClose(); // Close modal after adding
|
handleClose(); // Close modal after adding
|
||||||
|
reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -69,127 +55,197 @@ export default function AddVehicleModal({
|
||||||
<Typography variant="h6" fontWeight={600}>
|
<Typography variant="h6" fontWeight={600}>
|
||||||
Add Vehicle
|
Add Vehicle
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconButton onClick={handleClose}>
|
<CustomIconButton onClick={handleClose}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</CustomIconButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Horizontal Line */}
|
{/* Horizontal Line */}
|
||||||
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
||||||
|
|
||||||
{/* Input Fields */}
|
{/* Form */}
|
||||||
<Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
{/* First Row - Two Inputs */}
|
{/* Input Fields */}
|
||||||
<Box sx={{ display: "flex", gap: 2 }}>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="body2" fontWeight={500}>
|
|
||||||
Vehicle Name
|
|
||||||
</Typography>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
placeholder="Enter Vehicle Name"
|
|
||||||
size="small"
|
|
||||||
value={name}
|
|
||||||
onChange={(e) => setName(e.target.value)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="body2" fontWeight={500}>
|
|
||||||
Company
|
|
||||||
</Typography>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
placeholder="Enter Company Name"
|
|
||||||
size="small"
|
|
||||||
value={company}
|
|
||||||
onChange={(e) => setCompany(e.target.value)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Second Row - Two Inputs */}
|
|
||||||
<Box sx={{ display: "flex", gap: 2 }}>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="body2" fontWeight={500}>
|
|
||||||
Model Name
|
|
||||||
</Typography>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
placeholder="Enter Model Name"
|
|
||||||
size="small"
|
|
||||||
value={modelName}
|
|
||||||
onChange={(e) => setModelName(e.target.value)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="body2" fontWeight={500}>
|
|
||||||
Charge Type
|
|
||||||
</Typography>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
placeholder="Enter Charge Type"
|
|
||||||
size="small"
|
|
||||||
value={chargeType}
|
|
||||||
onChange={(e) => setChargeType(e.target.value)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Third Row - Image URL */}
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
width: "100%",
|
gap: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="body2" fontWeight={500}>
|
{/* First Row - Two Inputs */}
|
||||||
Image URL
|
<Box sx={{ display: "flex", gap: 2 }}>
|
||||||
</Typography>
|
<Box
|
||||||
<TextField
|
sx={{
|
||||||
fullWidth
|
display: "flex",
|
||||||
placeholder="Enter Image URL"
|
flexDirection: "column",
|
||||||
size="small"
|
width: "100%",
|
||||||
value={imageUrl}
|
}}
|
||||||
onChange={(e) => setImageUrl(e.target.value)}
|
>
|
||||||
/>
|
<Typography variant="body2" fontWeight={500}>
|
||||||
</Box>
|
Vehicle Name
|
||||||
</Box>
|
</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
fullWidth
|
||||||
|
placeholder="Enter Vehicle Name"
|
||||||
|
size="small"
|
||||||
|
error={!!errors.name}
|
||||||
|
helperText={
|
||||||
|
errors.name ? errors.name.message : ""
|
||||||
|
}
|
||||||
|
{...register("name", {
|
||||||
|
required: "Vehicle Name is required",
|
||||||
|
minLength: {
|
||||||
|
value: 2,
|
||||||
|
message:
|
||||||
|
"Vehicle Name must be at least 2 characters long",
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* Submit Button */}
|
<Box
|
||||||
<Box
|
sx={{
|
||||||
sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}
|
display: "flex",
|
||||||
>
|
flexDirection: "column",
|
||||||
<Button variant="contained" onClick={handleSubmit}>
|
width: "100%",
|
||||||
Add Vehicle
|
}}
|
||||||
</Button>
|
>
|
||||||
</Box>
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Company
|
||||||
|
</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
fullWidth
|
||||||
|
placeholder="Enter Company Name"
|
||||||
|
size="small"
|
||||||
|
error={!!errors.company}
|
||||||
|
helperText={
|
||||||
|
errors.company
|
||||||
|
? errors.company.message
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
{...register("company", {
|
||||||
|
required: "Company is required",
|
||||||
|
minLength: {
|
||||||
|
value: 5,
|
||||||
|
message:
|
||||||
|
"Company must be at least 5 characters long",
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Second Row - Two Inputs */}
|
||||||
|
<Box sx={{ display: "flex", gap: 2 }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Model Name
|
||||||
|
</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
fullWidth
|
||||||
|
placeholder="Enter Model Name"
|
||||||
|
size="small"
|
||||||
|
error={!!errors.modelName}
|
||||||
|
helperText={
|
||||||
|
errors.modelName
|
||||||
|
? errors.modelName.message
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
{...register("modelName", {
|
||||||
|
required: "Model Name is required",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Charge Type
|
||||||
|
</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
fullWidth
|
||||||
|
placeholder="Enter Charge Type"
|
||||||
|
size="small"
|
||||||
|
error={!!errors.chargeType}
|
||||||
|
helperText={
|
||||||
|
errors.chargeType
|
||||||
|
? errors.chargeType.message
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
{...register("chargeType", {
|
||||||
|
required: "Charge Type is required",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Third Row - Image URL */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" fontWeight={500}>
|
||||||
|
Image URL
|
||||||
|
</Typography>
|
||||||
|
<CustomTextField
|
||||||
|
fullWidth
|
||||||
|
placeholder="Enter Image URL"
|
||||||
|
size="small"
|
||||||
|
error={!!errors.imageUrl}
|
||||||
|
helperText={
|
||||||
|
errors.imageUrl
|
||||||
|
? errors.imageUrl.message
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
{...register("imageUrl", {
|
||||||
|
required: "Image URL is required",
|
||||||
|
pattern: {
|
||||||
|
value: /^(https?:\/\/)?((([a-zA-Z\d]([a-zA-Z\d-]*[a-zA-Z\d])*)\.)+[a-zA-Z]{2,}|((\d{1,3}\.){3}\d{1,3}))(:\d+)?(\/[-a-zA-Z\d%_.~+]*)*(\?[;&a-zA-Z\d%_.~+=-]*)?(#[-a-zA-Z\d_]*)?$/,
|
||||||
|
message: "Please enter a valid URL",
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Submit Button */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
mt: 3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
|
||||||
|
type="submit"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#52ACDF",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
width: "117px",
|
||||||
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add Vehicle
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</form>
|
||||||
</Box>
|
</Box>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,9 +15,9 @@ import { useDispatch } from "react-redux";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
IconButton,
|
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
Menu,
|
Menu,
|
||||||
|
IconButton,
|
||||||
Pagination,
|
Pagination,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
|
@ -30,7 +30,9 @@ import VehicleViewModal from "../Modals/VehicleViewModal";
|
||||||
|
|
||||||
import SearchIcon from "@mui/icons-material/Search";
|
import SearchIcon from "@mui/icons-material/Search";
|
||||||
import TuneIcon from "@mui/icons-material/Tune";
|
import TuneIcon from "@mui/icons-material/Tune";
|
||||||
|
import {
|
||||||
|
CustomIconButton,
|
||||||
|
} from "../AddUserModel/styled.css.tsx";
|
||||||
// Styled components for customization
|
// Styled components for customization
|
||||||
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
[`&.${tableCellClasses.head}`]: {
|
[`&.${tableCellClasses.head}`]: {
|
||||||
|
@ -248,11 +250,15 @@ const filteredRows = rows.filter(
|
||||||
borderColor: "#52ACDF",
|
borderColor: "#52ACDF",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"& .MuiInputBase-input::placeholder": {
|
||||||
|
color: "#D9D8D8",
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
<InputAdornment position="start">
|
<InputAdornment position="start">
|
||||||
<SearchIcon sx={{ color: "#272727" }} />
|
<SearchIcon sx={{ color: "#52ACDF" }} />
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
|
@ -361,7 +367,7 @@ const filteredRows = rows.filter(
|
||||||
) : column.id !== "action" ? (
|
) : column.id !== "action" ? (
|
||||||
row[column.id]
|
row[column.id]
|
||||||
) : (
|
) : (
|
||||||
<IconButton
|
<CustomIconButton
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
handleClick(e, row);
|
handleClick(e, row);
|
||||||
setRowData(row); // Store the selected row
|
setRowData(row); // Store the selected row
|
||||||
|
@ -371,20 +377,13 @@ const filteredRows = rows.filter(
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
width: "auto",
|
width: "auto",
|
||||||
height: "auto",
|
height: "auto",
|
||||||
backgroundColor:
|
|
||||||
"transparent",
|
|
||||||
color: "#FFFFFF",
|
color: "#FFFFFF",
|
||||||
border: "none",
|
|
||||||
"&:hover": {
|
|
||||||
backgroundColor:
|
|
||||||
"transparent",
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MoreHorizRoundedIcon
|
<MoreHorizRoundedIcon
|
||||||
sx={{ fontSize: "24px" }}
|
sx={{ fontSize: "24px" }}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</CustomIconButton>
|
||||||
)}
|
)}
|
||||||
</StyledTableCell>
|
</StyledTableCell>
|
||||||
))}
|
))}
|
||||||
|
@ -442,6 +441,9 @@ const filteredRows = rows.filter(
|
||||||
[`& .${paperClasses.root}`]: {
|
[`& .${paperClasses.root}`]: {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
},
|
},
|
||||||
|
"& .MuiList-root": {
|
||||||
|
background: "#272727", // Remove any divider under menu items
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
|
@ -531,7 +533,7 @@ const filteredRows = rows.filter(
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
py: 0,
|
py: 0,
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
color: "red",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
|
|
|
@ -3,14 +3,15 @@ import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Typography,
|
Typography,
|
||||||
TextField,
|
|
||||||
Modal,
|
Modal,
|
||||||
IconButton,
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { updateVehicle } from "../../redux/slices/VehicleSlice";
|
import { updateVehicle } from "../../redux/slices/VehicleSlice";
|
||||||
|
import {
|
||||||
|
CustomIconButton,
|
||||||
|
CustomTextField,
|
||||||
|
} from "../AddUserModel/styled.css.tsx";
|
||||||
interface EditVehicleModalProps {
|
interface EditVehicleModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
|
@ -115,9 +116,9 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
|
||||||
<Typography variant="h6" fontWeight={600}>
|
<Typography variant="h6" fontWeight={600}>
|
||||||
Edit Vehicle
|
Edit Vehicle
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconButton onClick={handleClose}>
|
<CustomIconButton onClick={handleClose}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</CustomIconButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Horizontal Line */}
|
{/* Horizontal Line */}
|
||||||
|
@ -146,7 +147,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
|
||||||
control={control}
|
control={control}
|
||||||
rules={{ required: "Vehicle Name is required" }}
|
rules={{ required: "Vehicle Name is required" }}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TextField
|
<CustomTextField
|
||||||
{...field}
|
{...field}
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="Enter Vehicle Name"
|
placeholder="Enter Vehicle Name"
|
||||||
|
@ -177,7 +178,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
|
||||||
control={control}
|
control={control}
|
||||||
rules={{ required: "Company is required" }}
|
rules={{ required: "Company is required" }}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TextField
|
<CustomTextField
|
||||||
{...field}
|
{...field}
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="Enter Company Name"
|
placeholder="Enter Company Name"
|
||||||
|
@ -211,7 +212,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
|
||||||
control={control}
|
control={control}
|
||||||
rules={{ required: "Model Name is required" }}
|
rules={{ required: "Model Name is required" }}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TextField
|
<CustomTextField
|
||||||
{...field}
|
{...field}
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="Enter Model Name"
|
placeholder="Enter Model Name"
|
||||||
|
@ -242,7 +243,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
|
||||||
control={control}
|
control={control}
|
||||||
rules={{ required: "Charge Type is required" }}
|
rules={{ required: "Charge Type is required" }}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TextField
|
<CustomTextField
|
||||||
{...field}
|
{...field}
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="Enter Charge Type"
|
placeholder="Enter Charge Type"
|
||||||
|
@ -271,7 +272,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
|
||||||
control={control}
|
control={control}
|
||||||
rules={{ required: "Image URL is required" }}
|
rules={{ required: "Image URL is required" }}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TextField
|
<CustomTextField
|
||||||
{...field}
|
{...field}
|
||||||
fullWidth
|
fullWidth
|
||||||
placeholder="Enter Image URL"
|
placeholder="Enter Image URL"
|
||||||
|
@ -288,7 +289,16 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
|
||||||
<Box
|
<Box
|
||||||
sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}
|
sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}
|
||||||
>
|
>
|
||||||
<Button variant="contained" type="submit">
|
<Button
|
||||||
|
type="submit"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#52ACDF",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
width: "117px",
|
||||||
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
Update Vehicle
|
Update Vehicle
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Box, Modal, Typography, Divider } from "@mui/material";
|
import { Box, Modal, Typography, Divider, Grid } from "@mui/material";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "../../../redux/reducers";
|
import { RootState } from "../../../redux/reducers";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setViewModal: Function;
|
setViewModal: Function;
|
||||||
handleView: (id: string | undefined) => void;
|
handleView: (id: string | undefined) => void;
|
||||||
id?: number | undefined;
|
id?: number | undefined;
|
||||||
};
|
};
|
||||||
;
|
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
|
@ -30,13 +27,10 @@ const style = {
|
||||||
gap: 2,
|
gap: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function VehicleViewModal({
|
export default function VehicleViewModal({ open, setViewModal, id }: Props) {
|
||||||
open,
|
const { vehicles } = useSelector(
|
||||||
setViewModal,
|
(state: RootState) => state.vehicleReducer
|
||||||
id,
|
);
|
||||||
|
|
||||||
}: Props) {
|
|
||||||
const { vehicles } = useSelector((state: RootState) => state.vehicleReducer);
|
|
||||||
const [selectedVehicle, setSelectedVehicle] = useState<any>(null);
|
const [selectedVehicle, setSelectedVehicle] = useState<any>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -86,37 +80,37 @@ const { vehicles } = useSelector((state: RootState) => state.vehicleReducer);
|
||||||
<Divider sx={{ width: "100%" }} />
|
<Divider sx={{ width: "100%" }} />
|
||||||
|
|
||||||
{selectedVehicle ? (
|
{selectedVehicle ? (
|
||||||
<Box
|
<Grid container spacing={2} sx={{ width: "80%" }}>
|
||||||
sx={{
|
<Grid item xs={6}>
|
||||||
width: "80%",
|
<Typography variant="body1">
|
||||||
textAlign: "left",
|
<strong>Name:</strong> {selectedVehicle.name}
|
||||||
display: "flex",
|
</Typography>
|
||||||
flexDirection: "column",
|
</Grid>
|
||||||
gap: 1.5,
|
<Grid item xs={6}>
|
||||||
whiteSpace: "pre-wrap",
|
<Typography variant="body1">
|
||||||
wordBreak: "break-word",
|
<strong>Company:</strong>{" "}
|
||||||
overflowWrap: "break-word",
|
{selectedVehicle.company}
|
||||||
}}
|
</Typography>
|
||||||
>
|
</Grid>
|
||||||
<Typography variant="body1">
|
<Grid item xs={6}>
|
||||||
<strong>Name:</strong> {selectedVehicle.name}
|
<Typography variant="body1">
|
||||||
</Typography>
|
<strong>Model Name:</strong>{" "}
|
||||||
<Typography variant="body1">
|
{selectedVehicle.modelName}
|
||||||
<strong>Company:</strong> {selectedVehicle.company}
|
</Typography>
|
||||||
</Typography>
|
</Grid>
|
||||||
<Typography variant="body1">
|
<Grid item xs={6}>
|
||||||
<strong>Model Name:</strong>{" "}
|
<Typography variant="body1">
|
||||||
{selectedVehicle.modelName}
|
<strong>Charge Type:</strong>{" "}
|
||||||
</Typography>
|
{selectedVehicle.chargeType}
|
||||||
<Typography variant="body1">
|
</Typography>
|
||||||
<strong>Charge Type:</strong>{" "}
|
</Grid>
|
||||||
{selectedVehicle.chargeType}
|
<Grid item xs={6}>
|
||||||
</Typography>
|
<Typography variant="body1">
|
||||||
<Typography variant="body1">
|
<strong>Image URL:</strong>{" "}
|
||||||
<strong>Image URL:</strong>{" "}
|
{selectedVehicle.imageUrl}
|
||||||
{selectedVehicle.imageUrl}
|
</Typography>
|
||||||
</Typography>
|
</Grid>
|
||||||
</Box>
|
</Grid>
|
||||||
) : (
|
) : (
|
||||||
<Typography align="center">
|
<Typography align="center">
|
||||||
No vehicle found with this ID
|
No vehicle found with this ID
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Box, Button, Modal, Typography, Divider } from "@mui/material";
|
import { Box, Button, Modal, Typography, Divider, Grid } from "@mui/material";
|
||||||
import { RootState } from "../../../redux/store/store";
|
import { RootState } from "../../../redux/store/store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
@ -10,12 +10,14 @@ type Props = {
|
||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const style = {
|
const mainContainerStyle = {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: "50%",
|
top: "50%",
|
||||||
left: "50%",
|
left: "50%",
|
||||||
transform: "translate(-50%, -50%)",
|
transform: "translate(-50%, -50%)",
|
||||||
width: 400,
|
// width: "544px",
|
||||||
|
// height: "190px",
|
||||||
|
gap: "8px",
|
||||||
bgcolor: "background.paper",
|
bgcolor: "background.paper",
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
|
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
|
||||||
|
@ -23,15 +25,16 @@ const style = {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const btnStyle = {
|
const headerLayoutStyle = {
|
||||||
mt: 2,
|
// width: 544,
|
||||||
px: 5,
|
// height: 48,
|
||||||
py: 1.2,
|
gap: "24px",
|
||||||
width: "100%",
|
paddingBottom: "12px",
|
||||||
textTransform: "capitalize",
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ViewModal({ open, setViewModal, id }: Props) {
|
export default function ViewModal({ open, setViewModal, id }: Props) {
|
||||||
|
@ -51,75 +54,79 @@ export default function ViewModal({ open, setViewModal, id }: Props) {
|
||||||
aria-labelledby="modal-title"
|
aria-labelledby="modal-title"
|
||||||
aria-describedby="modal-description"
|
aria-describedby="modal-description"
|
||||||
>
|
>
|
||||||
<Box sx={style}>
|
<Box sx={mainContainerStyle}>
|
||||||
<Typography
|
<Box sx={headerLayoutStyle}>
|
||||||
id="modal-title"
|
<Typography
|
||||||
variant="h5"
|
id="modal-title"
|
||||||
fontWeight="bold"
|
variant="h5"
|
||||||
sx={{ width: "100%" }}
|
fontWeight="bold"
|
||||||
>
|
sx={{ flex: 1, textAlign: "center" }}
|
||||||
|
>
|
||||||
|
{selectedAdmin?.name}'s Details
|
||||||
|
</Typography>
|
||||||
<Box
|
<Box
|
||||||
|
onClick={() => setViewModal(false)}
|
||||||
sx={{
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
marginLeft: "auto", // Ensures the button is at the right end
|
||||||
width: "100%",
|
justifyContent:"flex-end"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ flex: 1, textAlign: "center" }}>
|
<CloseIcon />
|
||||||
{selectedAdmin?.name}'s Details
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
onClick={() => setViewModal(false)}
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CloseIcon />
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Typography>
|
</Box>
|
||||||
|
|
||||||
<Divider sx={{ width: "100%" }} />
|
<Divider sx={{ width: "100%" }} />
|
||||||
|
|
||||||
{selectedAdmin ? (
|
{selectedAdmin ? (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: "80%",
|
width: "100%",
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: 1.5,
|
gap: 1.5,
|
||||||
whiteSpace: "pre-wrap", // the text wraps properly
|
whiteSpace: "pre-wrap",
|
||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
overflowWrap: "break-word",
|
overflowWrap: "break-word",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="body1">
|
<Grid container spacing={2}>
|
||||||
<b>Name:</b> {selectedAdmin.name}
|
<Grid item xs={6}>
|
||||||
</Typography>
|
<Typography>
|
||||||
<Typography variant="body1">
|
<b>Name:</b>
|
||||||
<strong>Email:</strong> {selectedAdmin.email}
|
</Typography>
|
||||||
</Typography>
|
<Typography>{selectedAdmin.name}</Typography>
|
||||||
<Typography variant="body1">
|
</Grid>
|
||||||
<strong>Phone:</strong> {selectedAdmin.phone}
|
<Grid item xs={6}>
|
||||||
</Typography>
|
<Typography>
|
||||||
<Typography variant="body1">
|
<b>Phone:</b>
|
||||||
<strong>Address:</strong>{" "}
|
</Typography>
|
||||||
{selectedAdmin.registeredAddress ?? "N/A"}
|
<Typography>{selectedAdmin.phone}</Typography>
|
||||||
</Typography>
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Typography>
|
||||||
|
<b>Email:</b>
|
||||||
|
</Typography>
|
||||||
|
<Typography>{selectedAdmin.email}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6}>
|
||||||
|
<Typography>
|
||||||
|
<b>Address:</b>
|
||||||
|
</Typography>
|
||||||
|
<Typography>
|
||||||
|
{selectedAdmin.registeredAddress ?? "N/A"}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Typography align="center">
|
<Typography align="center">
|
||||||
No admin found with this ID
|
No admin found with this ID
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* <Button variant="contained" color="error" sx={btnStyle} onClick={() => setViewModal(false)}>
|
|
||||||
Close
|
|
||||||
</Button> */}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default function OptionsMenu({ avatar }: { avatar?: boolean }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<ExpandMoreIcon onClick={handleClick} sx={{cursor:"pointer"}}/>
|
<ExpandMoreIcon onClick={handleClick} sx={{ cursor: "pointer" }} />
|
||||||
<Menu
|
<Menu
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
id="top-menu"
|
id="top-menu"
|
||||||
|
@ -39,6 +39,10 @@ export default function OptionsMenu({ avatar }: { avatar?: boolean }) {
|
||||||
overflow: "visible",
|
overflow: "visible",
|
||||||
filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
|
filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
|
||||||
mt: 1.5,
|
mt: 1.5,
|
||||||
|
|
||||||
|
"& .MuiList-root": {
|
||||||
|
background: "#272727", // Remove any divider under menu items
|
||||||
|
},
|
||||||
"& .MuiMenuItem-root": {
|
"& .MuiMenuItem-root": {
|
||||||
borderBottom: "none", // Remove any divider under menu items
|
borderBottom: "none", // Remove any divider under menu items
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,9 +11,8 @@ import {
|
||||||
Typography,
|
Typography,
|
||||||
Box,
|
Box,
|
||||||
Grid,
|
Grid,
|
||||||
FormControlLabel,
|
|
||||||
Button,
|
Button,
|
||||||
TextField,
|
FormControlLabel,
|
||||||
Snackbar,
|
Snackbar,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useNavigate } from "react-router-dom"; // Import useNavigate
|
import { useNavigate } from "react-router-dom"; // Import useNavigate
|
||||||
|
@ -21,6 +20,9 @@ import { useDispatch, useSelector } from "react-redux";
|
||||||
import { createRole } from "../../redux/slices/roleSlice"; // Import the createRole action
|
import { createRole } from "../../redux/slices/roleSlice"; // Import the createRole action
|
||||||
import { AppDispatch, RootState } from "../../redux/store/store"; // Assuming this is the path to your store file
|
import { AppDispatch, RootState } from "../../redux/store/store"; // Assuming this is the path to your store file
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import {
|
||||||
|
CustomTextField,
|
||||||
|
} from "../../components/AddUserModel/styled.css.tsx";
|
||||||
// Define the data structure for permission
|
// Define the data structure for permission
|
||||||
interface Permission {
|
interface Permission {
|
||||||
module: string;
|
module: string;
|
||||||
|
@ -155,7 +157,7 @@ const AddEditRolePage: React.FC = () => {
|
||||||
{/* Role Name Input */}
|
{/* Role Name Input */}
|
||||||
<Box sx={{ mb: 2 }}>
|
<Box sx={{ mb: 2 }}>
|
||||||
<label>Role Name</label>
|
<label>Role Name</label>
|
||||||
<TextField
|
<CustomTextField
|
||||||
placeholder="Enter role name"
|
placeholder="Enter role name"
|
||||||
value={roleName}
|
value={roleName}
|
||||||
onChange={handleRoleNameChange}
|
onChange={handleRoleNameChange}
|
||||||
|
@ -256,10 +258,15 @@ const AddEditRolePage: React.FC = () => {
|
||||||
{/* Submit Button */}
|
{/* Submit Button */}
|
||||||
<Box sx={{ mt: 2, display: "flex", justifyContent: "flex-end" }}>
|
<Box sx={{ mt: 2, display: "flex", justifyContent: "flex-end" }}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#52ACDF",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
width: "117px",
|
||||||
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{loading ? "Saving..." : "Save Role"}
|
{loading ? "Saving..." : "Save Role"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -14,6 +14,7 @@ export const dataDisplayCustomizations = {
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
|
|
||||||
gap: 0,
|
gap: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -385,7 +385,7 @@ export const inputsCustomizations = {
|
||||||
color: (theme.vars || theme).palette.text.primary,
|
color: (theme.vars || theme).palette.text.primary,
|
||||||
borderRadius: (theme.vars || theme).shape.borderRadius,
|
borderRadius: (theme.vars || theme).shape.borderRadius,
|
||||||
border: `1px solid ${(theme.vars || theme).palette.divider}`,
|
border: `1px solid ${(theme.vars || theme).palette.divider}`,
|
||||||
backgroundColor: (theme.vars || theme).palette.background.default,
|
backgroundColor: "#272727",
|
||||||
transition: 'border 120ms ease-in',
|
transition: 'border 120ms ease-in',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
borderColor: gray[400],
|
borderColor: gray[400],
|
||||||
|
|
Loading…
Reference in a new issue