dev-jaanvi #1
|
@ -67,29 +67,27 @@ const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
backgroundColor: "#2A2A2A",
|
backgroundColor: "#2A2A2A",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
},
|
},
|
||||||
// Make the "Action" header cell sticky
|
|
||||||
"&.action-cell": {
|
"&.action-cell": {
|
||||||
right: 0,
|
right: 0,
|
||||||
zIndex: 11, // Higher z-index to ensure it stays above other headers
|
zIndex: 11,
|
||||||
boxShadow: "-4px 0 8px rgba(0, 0, 0, 0.1)",
|
boxShadow: "-4px 0 8px rgba(0, 0, 0, 0.1)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[`&.${tableCellClasses.body}`]: {
|
[`&.${tableCellClasses.body}`]: {
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
padding: "12px 16px",
|
padding: "12px 16px",
|
||||||
borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
|
borderBottom: "none",
|
||||||
color: "#333333",
|
color: "#333333",
|
||||||
transition: "background-color 0.2s ease",
|
transition: "background-color 0.2s ease",
|
||||||
fontWeight:500,
|
fontWeight: 500,
|
||||||
// Make the "Action" body cell sticky
|
|
||||||
"&.action-cell": {
|
"&.action-cell": {
|
||||||
position: "sticky",
|
position: "sticky",
|
||||||
right: 0,
|
right: 0,
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
boxShadow: "-4px 0 8px rgba(0, 0, 0, 0.1)",
|
backgroundColor: "#DFECF1",
|
||||||
backgroundColor: "#DFECF1", // Match row background
|
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: "#D0E1E9", // Match row hover background
|
backgroundColor: "#D0E1E9",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -100,11 +98,11 @@ const StyledTableRow = styled(TableRow)(({ theme }) => ({
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: "#D0E1E9",
|
backgroundColor: "#D0E1E9",
|
||||||
},
|
},
|
||||||
"& td, & th": {
|
// "& td, & th": {
|
||||||
borderColor: "#454545",
|
// borderColor: "#454545",
|
||||||
borderWidth: "1px",
|
// borderWidth: "1px",
|
||||||
borderBottom: "1px solid #454545",
|
// // borderBottom: "1px solid #454545",
|
||||||
},
|
// },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledTableContainer = styled(TableContainer)(({ theme }) => ({
|
const StyledTableContainer = styled(TableContainer)(({ theme }) => ({
|
||||||
|
|
315
src/components/Modals/EditProfileModal/editProfileModal.tsx
Normal file
315
src/components/Modals/EditProfileModal/editProfileModal.tsx
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
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 {
|
||||||
|
CustomIconButton,
|
||||||
|
CustomTextField,
|
||||||
|
} from "../../AddUserModal/styled.css";
|
||||||
|
|
||||||
|
interface EditProfileModalProps {
|
||||||
|
open: boolean;
|
||||||
|
handleClose: () => void;
|
||||||
|
handleUpdate: (
|
||||||
|
name: string,
|
||||||
|
phone: string,
|
||||||
|
bio?: string,
|
||||||
|
profilePhoto?: string | null
|
||||||
|
) => void;
|
||||||
|
editUser: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormData {
|
||||||
|
name: string;
|
||||||
|
phone: string;
|
||||||
|
bio?: string;
|
||||||
|
profilePhoto?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const EditProfileModal: React.FC<EditProfileModalProps> = ({
|
||||||
|
open,
|
||||||
|
handleClose,
|
||||||
|
handleUpdate,
|
||||||
|
editUser,
|
||||||
|
}) => {
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
setValue,
|
||||||
|
reset,
|
||||||
|
} = useForm<FormData>();
|
||||||
|
|
||||||
|
const [imagePreview, setImagePreview] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editUser) {
|
||||||
|
setValue("name", editUser.name || "");
|
||||||
|
setValue("phone", editUser.phone || "");
|
||||||
|
setValue("bio", editUser.bio || "");
|
||||||
|
setImagePreview(editUser.profilePhoto || null);
|
||||||
|
}
|
||||||
|
}, [editUser, setValue]);
|
||||||
|
|
||||||
|
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const file = e.target.files?.[0];
|
||||||
|
if (file) {
|
||||||
|
const imageUrl = URL.createObjectURL(file);
|
||||||
|
setImagePreview(imageUrl);
|
||||||
|
setValue("profilePhoto", imageUrl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleModalClose = () => {
|
||||||
|
handleClose();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (data: FormData) => {
|
||||||
|
console.log("Form Data:-----", data);
|
||||||
|
handleUpdate(data.name, data.phone, data.bio, data.profilePhoto);
|
||||||
|
reset();
|
||||||
|
handleModalClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={open}
|
||||||
|
onClose={(e, reason) => {
|
||||||
|
if (reason !== "backdropClick") handleModalClose();
|
||||||
|
}}
|
||||||
|
aria-labelledby="edit-profile-modal"
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
component="form"
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
width: 500,
|
||||||
|
boxShadow: 24,
|
||||||
|
p: 0,
|
||||||
|
borderRadius: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Header */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
backgroundColor: "#000000",
|
||||||
|
color: "#D0E1E9",
|
||||||
|
padding: "20px 24px",
|
||||||
|
borderRadius: "10px 10px 0 0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6" fontWeight={600} fontSize="16px">
|
||||||
|
Edit Profile
|
||||||
|
</Typography>
|
||||||
|
<CustomIconButton onClick={handleModalClose}>
|
||||||
|
<CloseIcon />
|
||||||
|
</CustomIconButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#b5c4cb",
|
||||||
|
padding: "20px",
|
||||||
|
borderRadius: "0 0 10px 10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Name Field */}
|
||||||
|
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
fontWeight={500}
|
||||||
|
color="#000000"
|
||||||
|
>
|
||||||
|
Full Name
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="name"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "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]+$/,
|
||||||
|
message:
|
||||||
|
"Only letters and spaces allowed",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
fullWidth
|
||||||
|
placeholder="Enter your name"
|
||||||
|
size="small"
|
||||||
|
sx={{ mt: 1 }}
|
||||||
|
error={!!errors.name}
|
||||||
|
helperText={errors.name?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Phone Field */}
|
||||||
|
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
fontWeight={500}
|
||||||
|
color="#000000"
|
||||||
|
>
|
||||||
|
Phone Number
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="phone"
|
||||||
|
control={control}
|
||||||
|
rules={{
|
||||||
|
required: "Phone number is required",
|
||||||
|
validate: (value) => {
|
||||||
|
if (!/^[0-9]*$/.test(value))
|
||||||
|
return "Only numbers are allowed";
|
||||||
|
if (value.length < 6)
|
||||||
|
return "Must be at least 6 digits";
|
||||||
|
if (value.length > 14)
|
||||||
|
return "Must be at most 14 digits";
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
fullWidth
|
||||||
|
placeholder="Enter phone number"
|
||||||
|
size="small"
|
||||||
|
sx={{ mt: 1 }}
|
||||||
|
error={!!errors.phone}
|
||||||
|
helperText={errors.phone?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Bio Field */}
|
||||||
|
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
fontWeight={500}
|
||||||
|
color="#000000"
|
||||||
|
>
|
||||||
|
Bio
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="bio"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
fullWidth
|
||||||
|
placeholder="Add your bio details here..."
|
||||||
|
size="small"
|
||||||
|
sx={{ mt: 1 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Upload Image */}
|
||||||
|
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
fontWeight={500}
|
||||||
|
color="#000000"
|
||||||
|
>
|
||||||
|
Upload Profile Photo
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
component="label"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#000000",
|
||||||
|
color: "#D0E1E9",
|
||||||
|
borderRadius: "8px",
|
||||||
|
mt: 1,
|
||||||
|
"&:hover": { backgroundColor: "#454545" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Choose Image
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
hidden
|
||||||
|
accept="image/*"
|
||||||
|
onChange={handleImageChange}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
{imagePreview && (
|
||||||
|
<Box mt={2}>
|
||||||
|
<Typography variant="body2" color="#000000">
|
||||||
|
Preview (
|
||||||
|
{imagePreview.startsWith("blob")
|
||||||
|
? "New"
|
||||||
|
: "Existing"}
|
||||||
|
):
|
||||||
|
</Typography>
|
||||||
|
<img
|
||||||
|
src={imagePreview}
|
||||||
|
alt="Profile Preview"
|
||||||
|
style={{
|
||||||
|
maxWidth: "40%",
|
||||||
|
borderRadius: "8px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
mt: 3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#000000",
|
||||||
|
color: "#D0E1E9",
|
||||||
|
borderRadius: "8px",
|
||||||
|
fontSize: "16px",
|
||||||
|
width: "140px",
|
||||||
|
"&:hover": { backgroundColor: "#454545" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Save Changes
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditProfileModal;
|
|
@ -169,3 +169,435 @@ export default function ViewModal({ open, setViewModal, id }: Props) {
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// import {
|
||||||
|
// Box,
|
||||||
|
// Button,
|
||||||
|
// Modal,
|
||||||
|
// Typography,
|
||||||
|
// Tabs,
|
||||||
|
// Tab,
|
||||||
|
// Divider,
|
||||||
|
// Grid,
|
||||||
|
// } from "@mui/material";
|
||||||
|
// import { AppDispatch, RootState } from "../../../redux/store/store";
|
||||||
|
// import { useDispatch, useSelector } from "react-redux";
|
||||||
|
// import { useEffect, useState } from "react";
|
||||||
|
// import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
// import { managerList } from "../../../redux/slices/managerSlice";
|
||||||
|
// import {
|
||||||
|
// AsyncThunkAction,
|
||||||
|
// ThunkDispatch,
|
||||||
|
// UnknownAction,
|
||||||
|
// } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
// type Props = {
|
||||||
|
// open: boolean;
|
||||||
|
// setViewModal: Function;
|
||||||
|
// handleView: (id: string | undefined) => void;
|
||||||
|
// id?: string;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// interface TabPanelProps {
|
||||||
|
// children?: React.ReactNode;
|
||||||
|
// index: number;
|
||||||
|
// value: number;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const style = {
|
||||||
|
// position: "absolute",
|
||||||
|
// top: "50%",
|
||||||
|
// left: "50%",
|
||||||
|
// transform: "translate(-50%, -50%)",
|
||||||
|
// width: 600,
|
||||||
|
// borderRadius: 2,
|
||||||
|
// boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
|
||||||
|
// p: 0,
|
||||||
|
// display: "flex",
|
||||||
|
// flexDirection: "column",
|
||||||
|
// alignItems: "center",
|
||||||
|
// };
|
||||||
|
|
||||||
|
// function TabPanel(props: TabPanelProps) {
|
||||||
|
// const { children, value, index, ...other } = props;
|
||||||
|
// return (
|
||||||
|
// <div
|
||||||
|
// role="tabpanel"
|
||||||
|
// hidden={value !== index}
|
||||||
|
// id={`tabpanel-${index}`}
|
||||||
|
// aria-labelledby={`tab-${index}`}
|
||||||
|
// {...other}
|
||||||
|
// >
|
||||||
|
// {value === index && <Box sx={{ p: 3 }}>{children}</Box>}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export default function ViewModal({ open, setViewModal, id }: Props) {
|
||||||
|
// const { admins } = useSelector((state: RootState) => state.adminReducer);
|
||||||
|
// const { managers } = useSelector(
|
||||||
|
// (state: RootState) => state.managerReducer
|
||||||
|
// );
|
||||||
|
// const [selectedAdmin, setSelectedAdmin] = useState<any>(null);
|
||||||
|
// const selectedManager = managers.find(
|
||||||
|
// (manager) => String(manager.id) === String(selectedAdmin?.id)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const dispatch = useDispatch();
|
||||||
|
|
||||||
|
// const [tabValue, setTabValue] = useState(0);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (id) {
|
||||||
|
// const admin = admins.find((admin) => admin.id === id);
|
||||||
|
// setSelectedAdmin(admin);
|
||||||
|
// }
|
||||||
|
// }, [id, admins]);
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (open) {
|
||||||
|
// //dispatch(managerList());
|
||||||
|
// }
|
||||||
|
// }, [open, dispatch]);
|
||||||
|
// const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
|
||||||
|
// setTabValue(newValue);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <Modal
|
||||||
|
// open={open}
|
||||||
|
// aria-labelledby="modal-title"
|
||||||
|
// aria-describedby="modal-description"
|
||||||
|
// >
|
||||||
|
// <Box sx={style}>
|
||||||
|
// <Box
|
||||||
|
// sx={{
|
||||||
|
// display: "flex",
|
||||||
|
// justifyContent: "space-between",
|
||||||
|
// alignItems: "center",
|
||||||
|
// backgroundColor: "#000000",
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// padding: "20px 24px",
|
||||||
|
// borderRadius: "10px 10px 0 0",
|
||||||
|
// width: "100%",
|
||||||
|
// boxSizing: "border-box",
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <Typography
|
||||||
|
// id="modal-title"
|
||||||
|
// variant="h5"
|
||||||
|
// fontWeight="bold"
|
||||||
|
// sx={{ width: "100%" }}
|
||||||
|
// >
|
||||||
|
// <Box
|
||||||
|
// sx={{
|
||||||
|
// display: "flex",
|
||||||
|
// alignItems: "center",
|
||||||
|
// justifyContent: "space-between",
|
||||||
|
// width: "100%",
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <Box
|
||||||
|
// sx={{
|
||||||
|
// flex: 1,
|
||||||
|
// textAlign: "center",
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// {selectedAdmin?.name || "Admin"}'s Details
|
||||||
|
// </Box>
|
||||||
|
// <Box
|
||||||
|
// onClick={() => setViewModal(false)}
|
||||||
|
// sx={{
|
||||||
|
// cursor: "pointer",
|
||||||
|
// display: "flex",
|
||||||
|
// alignItems: "center",
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <CloseIcon />
|
||||||
|
// </Box>
|
||||||
|
// </Box>
|
||||||
|
// </Typography>
|
||||||
|
// </Box>
|
||||||
|
|
||||||
|
// <Box sx={{ width: "100%", backgroundColor: "#b5c4cb" }}>
|
||||||
|
// <Tabs
|
||||||
|
// value={tabValue}
|
||||||
|
// onChange={handleTabChange}
|
||||||
|
// aria-label="admin details tabs"
|
||||||
|
// sx={{
|
||||||
|
// backgroundColor: "#000000",
|
||||||
|
// "& .MuiTabs-indicator": {
|
||||||
|
// backgroundColor: "#D0E1E9",
|
||||||
|
// },
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <Tab
|
||||||
|
// label="Admin Details"
|
||||||
|
// sx={{
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// "&.Mui-selected": { color: "#D0E1E9" },
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// <Tab
|
||||||
|
// label="Manager Details"
|
||||||
|
// sx={{
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// "&.Mui-selected": { color: "#D0E1E9" },
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// <Tab
|
||||||
|
// label="Charging Stations"
|
||||||
|
// sx={{
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// "&.Mui-selected": { color: "#D0E1E9" },
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// <Tab
|
||||||
|
// label="User Details"
|
||||||
|
// sx={{
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// "&.Mui-selected": { color: "#D0E1E9" },
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// </Tabs>
|
||||||
|
|
||||||
|
// <TabPanel value={tabValue} index={0}>
|
||||||
|
// {selectedAdmin ? (
|
||||||
|
// <Grid container spacing={3}>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Name:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedAdmin.name}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Phone:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedAdmin.phone}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Email:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedAdmin.email}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Address:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedAdmin?.Admins?.[0]
|
||||||
|
// ?.registeredAddress ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// </Grid>
|
||||||
|
// ) : (
|
||||||
|
// <Typography align="center" color="#454545">
|
||||||
|
// No admin found with this ID
|
||||||
|
// </Typography>
|
||||||
|
// )}
|
||||||
|
// </TabPanel>
|
||||||
|
|
||||||
|
// <TabPanel value={tabValue} index={1}>
|
||||||
|
// {selectedManager ? (
|
||||||
|
// <Grid container spacing={3}>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Manager Name:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedManager.name ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Manager Email:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedManager.email ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Phone:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedManager.phone ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// <Grid item xs={6}>
|
||||||
|
// <Typography variant="body1" color="#000000">
|
||||||
|
// <strong>Station Name:</strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// {selectedManager.chargingStation
|
||||||
|
// ?.name ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// </Grid>
|
||||||
|
// </Grid>
|
||||||
|
// ) : (
|
||||||
|
// <Typography align="center" color="#454545">
|
||||||
|
// No manager details available
|
||||||
|
// </Typography>
|
||||||
|
// )}
|
||||||
|
// </TabPanel>
|
||||||
|
|
||||||
|
// <TabPanel value={tabValue} index={2}>
|
||||||
|
// {selectedAdmin?.chargingStations?.length > 0 ? (
|
||||||
|
// <Grid container spacing={3}>
|
||||||
|
// {selectedAdmin.chargingStations.map(
|
||||||
|
// (station: any, index: number) => (
|
||||||
|
// <Grid item xs={12} key={index}>
|
||||||
|
// <Typography
|
||||||
|
// variant="body1"
|
||||||
|
// color="#000000"
|
||||||
|
// >
|
||||||
|
// <strong>
|
||||||
|
// Station {index + 1}:
|
||||||
|
// </strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// Name:{" "}
|
||||||
|
// {station.name ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// Location:{" "}
|
||||||
|
// {station.location ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// Status:{" "}
|
||||||
|
// {station.status ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// {index <
|
||||||
|
// selectedAdmin.chargingStations
|
||||||
|
// .length -
|
||||||
|
// 1 && (
|
||||||
|
// <Divider sx={{ my: 2 }} />
|
||||||
|
// )}
|
||||||
|
// </Grid>
|
||||||
|
// )
|
||||||
|
// )}
|
||||||
|
// </Grid>
|
||||||
|
// ) : (
|
||||||
|
// <Typography align="center" color="#454545">
|
||||||
|
// No charging stations assigned
|
||||||
|
// </Typography>
|
||||||
|
// )}
|
||||||
|
// </TabPanel>
|
||||||
|
|
||||||
|
// <TabPanel value={tabValue} index={3}>
|
||||||
|
// {selectedAdmin?.users?.length > 0 ? (
|
||||||
|
// <Grid container spacing={3}>
|
||||||
|
// {selectedAdmin.users.map(
|
||||||
|
// (user: any, index: number) => (
|
||||||
|
// <Grid item xs={12} key={index}>
|
||||||
|
// <Typography
|
||||||
|
// variant="body1"
|
||||||
|
// color="#000000"
|
||||||
|
// >
|
||||||
|
// <strong>
|
||||||
|
// User {index + 1}:
|
||||||
|
// </strong>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// Name: {user.name ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// Email: {user.email ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// <Typography
|
||||||
|
// variant="body2"
|
||||||
|
// color="#454545"
|
||||||
|
// >
|
||||||
|
// Role: {user.role ?? "N/A"}
|
||||||
|
// </Typography>
|
||||||
|
// </Typography>
|
||||||
|
// {index <
|
||||||
|
// selectedAdmin.users.length -
|
||||||
|
// 1 && (
|
||||||
|
// <Divider sx={{ my: 2 }} />
|
||||||
|
// )}
|
||||||
|
// </Grid>
|
||||||
|
// )
|
||||||
|
// )}
|
||||||
|
// </Grid>
|
||||||
|
// ) : (
|
||||||
|
// <Typography align="center" color="#454545">
|
||||||
|
// No users assigned
|
||||||
|
// </Typography>
|
||||||
|
// )}
|
||||||
|
// </TabPanel>
|
||||||
|
|
||||||
|
// <Box
|
||||||
|
// sx={{
|
||||||
|
// display: "flex",
|
||||||
|
// justifyContent: "flex-end",
|
||||||
|
// p: 2,
|
||||||
|
// borderRadius: "0 0 10px 10px",
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <Button
|
||||||
|
// onClick={() => setViewModal(false)}
|
||||||
|
// sx={{
|
||||||
|
// backgroundColor: "#000000",
|
||||||
|
// color: "#D0E1E9",
|
||||||
|
// borderRadius: "8px",
|
||||||
|
// fontSize: "16px",
|
||||||
|
// width: "117px",
|
||||||
|
// "&:hover": { backgroundColor: "#454545" },
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// Close
|
||||||
|
// </Button>
|
||||||
|
// </Box>
|
||||||
|
// </Box>
|
||||||
|
// </Box>
|
||||||
|
// </Modal>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect, useState, useMemo } from "react";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
Typography,
|
Typography,
|
||||||
|
@ -14,19 +14,60 @@ import {
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { AppDispatch, RootState } from "../../redux/store/store";
|
import { AppDispatch, RootState } from "../../redux/store/store";
|
||||||
import { fetchAdminProfile } from "../../redux/slices/profileSlice";
|
import {
|
||||||
|
fetchAdminProfile,
|
||||||
|
updateProfile,
|
||||||
|
} from "../../redux/slices/profileSlice";
|
||||||
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
|
import EditProfileModal from "../../components/Modals/EditProfileModal/editProfileModal";
|
||||||
|
import { CustomIconButton } from "../../components/AddUserModal/styled.css";
|
||||||
|
|
||||||
const ProfilePage = () => {
|
const ProfilePage = () => {
|
||||||
const dispatch = useDispatch<AppDispatch>();
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
const { user, isLoading } = useSelector(
|
const { user, loading } = useSelector(
|
||||||
(state: RootState) => state?.profileReducer
|
(state: RootState) => state.profileReducer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [openEditModal, setOpenEditModal] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(fetchAdminProfile());
|
dispatch(fetchAdminProfile());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
if (isLoading) {
|
const handleOpenEditModal = () => {
|
||||||
|
setOpenEditModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setOpenEditModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdate = (
|
||||||
|
name: string,
|
||||||
|
phone: string,
|
||||||
|
bio?: string,
|
||||||
|
profilePhoto?: string | null
|
||||||
|
) => {
|
||||||
|
console.log("Dispatching updateProfile...");
|
||||||
|
dispatch(updateProfile({ name, phone, bio, profilePhoto }));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Memoizing the user data for optimization
|
||||||
|
const displayUser = useMemo(
|
||||||
|
() => ({
|
||||||
|
name: user?.name || "N/A",
|
||||||
|
email: user?.email || "N/A",
|
||||||
|
phone: user?.phone || "N/A",
|
||||||
|
bio: user?.bio || "No bio available.",
|
||||||
|
userType: user?.userType || "N/A",
|
||||||
|
profilePhoto: user?.profilePhoto || "/avatar.png", // Default image path
|
||||||
|
}),
|
||||||
|
[user]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Show loading indicator if data is being fetched
|
||||||
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -42,12 +83,7 @@ const ProfilePage = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container sx={{ py: 1 }}>
|
||||||
sx={{
|
|
||||||
py:1,
|
|
||||||
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
<Typography
|
||||||
variant="h4"
|
variant="h4"
|
||||||
gutterBottom
|
gutterBottom
|
||||||
|
@ -61,42 +97,68 @@ const ProfilePage = () => {
|
||||||
p: { xs: 2, sm: 3 },
|
p: { xs: 2, sm: 3 },
|
||||||
mx: "auto",
|
mx: "auto",
|
||||||
backgroundColor: "#000000",
|
backgroundColor: "#000000",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
// sx={{
|
|
||||||
// width: "1132px",
|
|
||||||
// height: "331px",
|
|
||||||
// gap: "24px",
|
|
||||||
// borderRadius: "12px",
|
|
||||||
// padding: "16px",
|
|
||||||
// maxWidth: "100%",
|
|
||||||
// margin: "0 auto",
|
|
||||||
// backgroundColor: "#1C1C1C",
|
|
||||||
// }}
|
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Stack direction="column" spacing={2}>
|
<Stack direction="column" spacing={2}>
|
||||||
<Stack direction="row" spacing={2} alignItems="center">
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
spacing={2}
|
||||||
|
alignItems="center"
|
||||||
|
position="relative"
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
position="relative"
|
||||||
|
sx={{
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
"&:hover .edit-icon": { opacity: 1 },
|
||||||
|
"&:hover .avatar-img": { opacity: 0.4 },
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
src="/avatar.png"
|
src={displayUser.profilePhoto}
|
||||||
sx={{ width: 60, height: 60 }}
|
sx={{
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
transition: "opacity 0.3s",
|
||||||
|
}}
|
||||||
|
className="avatar-img"
|
||||||
/>
|
/>
|
||||||
|
<CustomIconButton
|
||||||
|
onClick={handleOpenEditModal}
|
||||||
|
className="edit-icon"
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
color: "white",
|
||||||
|
opacity: 0,
|
||||||
|
transition: "opacity 0.3s",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EditIcon fontSize="small" />
|
||||||
|
</CustomIconButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body1"
|
variant="body1"
|
||||||
sx={{ color: "#D0E1E9", fontWeight: 500 }}
|
sx={{ color: "#D0E1E9", fontWeight: 500 }}
|
||||||
>
|
>
|
||||||
{user?.name || "No Admin"}
|
{displayUser.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{ color: "#D9D8D8" }}
|
sx={{ color: "#D9D8D8" }}
|
||||||
>
|
>
|
||||||
{user?.userType || "N/A"}
|
{displayUser.userType}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Divider
|
<Divider
|
||||||
flexItem
|
flexItem
|
||||||
sx={{ backgroundColor: "rgba(32, 32, 32, 0.5)" }}
|
sx={{ backgroundColor: "rgba(32, 32, 32, 0.5)" }}
|
||||||
|
@ -117,80 +179,72 @@ const ProfilePage = () => {
|
||||||
>
|
>
|
||||||
Personal Information
|
Personal Information
|
||||||
</Typography>
|
</Typography>
|
||||||
{/* <Link
|
<Link
|
||||||
|
component="button"
|
||||||
variant="body1"
|
variant="body1"
|
||||||
href="/edit-profile"
|
|
||||||
color="#52ACDF"
|
color="#52ACDF"
|
||||||
|
onClick={handleOpenEditModal}
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Link> */}
|
</Link>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Grid container spacing={3} >
|
<Grid container spacing={3}>
|
||||||
<Grid item xs={12} sm={4}>
|
<Grid item xs={12} sm={4}>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{
|
sx={{ color: "#D0E1E9", fontWeight: 500 }}
|
||||||
color: "#D0E1E9",
|
|
||||||
fontWeight: 500,
|
|
||||||
fontSize: "16px",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Full Name:
|
Full Name:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="#D9D8D8">
|
<Typography variant="body2" color="#D9D8D8">
|
||||||
{user?.name || "N/A"}
|
{displayUser.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={4}>
|
<Grid item xs={12} sm={4}>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{
|
sx={{ color: "#D0E1E9", fontWeight: 500 }}
|
||||||
color: "#D0E1E9",
|
|
||||||
fontWeight: 500,
|
|
||||||
fontSize: "16px",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Phone:
|
Phone:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="#D9D8D8">
|
<Typography variant="body2" color="#D9D8D8">
|
||||||
{user?.phone || "N/A"}
|
{displayUser.phone}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={4}>
|
<Grid item xs={12} sm={4}>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{
|
sx={{ color: "#D0E1E9", fontWeight: 500 }}
|
||||||
color: "#D0E1E9",
|
|
||||||
fontWeight: 500,
|
|
||||||
fontSize: "16px",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Email:
|
Email:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="#D9D8D8">
|
<Typography variant="body2" color="#D9D8D8">
|
||||||
{user?.email || "N/A"}
|
{displayUser.email}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={4}>
|
<Grid item xs={12} sm={4}>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{
|
sx={{ color: "#D0E1E9", fontWeight: 500 }}
|
||||||
color: "#D0E1E9",
|
|
||||||
fontWeight: 500,
|
|
||||||
fontSize: "16px",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Bio:
|
Bio:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" color="#D9D8D8">
|
<Typography variant="body2" color="#D9D8D8">
|
||||||
{user?.bio || "No bio available."}
|
{displayUser.bio}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Stack>
|
</Stack>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<EditProfileModal
|
||||||
|
open={openEditModal}
|
||||||
|
handleClose={handleClose}
|
||||||
|
handleUpdate={handleUpdate} // Passing the handleUpdate function to the modal
|
||||||
|
editUser={user} // Pass the current user to pre-fill the form in modal
|
||||||
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
|
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
|
||||||
import http from "../../lib/https";
|
import http from "../../lib/https";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import { string } from "prop-types";
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
token: string | null;
|
token: string | null;
|
||||||
|
@ -9,14 +10,26 @@ interface User {
|
||||||
email: string;
|
email: string;
|
||||||
userType: string;
|
userType: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
|
bio?: string;
|
||||||
|
profilePhoto?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AuthState {
|
interface AuthState {
|
||||||
user: User | null;
|
user: User | null;
|
||||||
|
users: User[];
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
isLoading: boolean;
|
loading: boolean;
|
||||||
|
error: null | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initialState: AuthState = {
|
||||||
|
users: [],
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
isAuthenticated: false,
|
||||||
|
user: null,
|
||||||
|
};
|
||||||
|
|
||||||
export const fetchAdminProfile = createAsyncThunk<
|
export const fetchAdminProfile = createAsyncThunk<
|
||||||
User,
|
User,
|
||||||
void,
|
void,
|
||||||
|
@ -32,18 +45,45 @@ export const fetchAdminProfile = createAsyncThunk<
|
||||||
|
|
||||||
return response.data.data;
|
return response.data.data;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error("Error Fetching Profile" + error);
|
toast.error("Error Fetching Profile: " + error.message);
|
||||||
return rejectWithValue(
|
return rejectWithValue(
|
||||||
error?.response?.data?.message || "An error occurred"
|
error?.response?.data?.message || "An error occurred"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialState: AuthState = {
|
export const updateProfile = createAsyncThunk<
|
||||||
user: null,
|
User,
|
||||||
isAuthenticated: false,
|
{
|
||||||
isLoading: false,
|
name: string;
|
||||||
};
|
phone?: string;
|
||||||
|
bio?: string;
|
||||||
|
profilePhoto?: string | null;
|
||||||
|
},
|
||||||
|
{ rejectValue: string }
|
||||||
|
>(
|
||||||
|
"updateProfile",
|
||||||
|
async ({ name, phone, bio, profilePhoto }, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const payload: any = { name };
|
||||||
|
if (phone) payload.phone = phone;
|
||||||
|
if (bio) payload.bio = bio;
|
||||||
|
if (profilePhoto) payload.profilePhoto = profilePhoto;
|
||||||
|
|
||||||
|
const response = await http.put("/edit-profile", payload);
|
||||||
|
console.log("-----------", response);
|
||||||
|
|
||||||
|
toast.success("Profile updated successfully");
|
||||||
|
return response.data.data;
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error("Error updating the profile: " + error.message);
|
||||||
|
return rejectWithValue(
|
||||||
|
error?.response?.data?.message || "An error occurred"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
const profileSlice = createSlice({
|
const profileSlice = createSlice({
|
||||||
name: "profile",
|
name: "profile",
|
||||||
|
@ -52,15 +92,29 @@ const profileSlice = createSlice({
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
builder
|
builder
|
||||||
.addCase(fetchAdminProfile.pending, (state) => {
|
.addCase(fetchAdminProfile.pending, (state) => {
|
||||||
state.isLoading = true;
|
state.loading = true;
|
||||||
})
|
})
|
||||||
.addCase(fetchAdminProfile.fulfilled, (state, action) => {
|
.addCase(fetchAdminProfile.fulfilled, (state, action) => {
|
||||||
state.isLoading = false;
|
state.loading = false;
|
||||||
state.user = action.payload;
|
state.user = action.payload;
|
||||||
state.isAuthenticated = true;
|
state.isAuthenticated = true;
|
||||||
})
|
})
|
||||||
.addCase(fetchAdminProfile.rejected, (state) => {
|
.addCase(fetchAdminProfile.rejected, (state, action) => {
|
||||||
state.isLoading = false;
|
state.loading = false;
|
||||||
|
state.error = action.payload;
|
||||||
|
})
|
||||||
|
.addCase(updateProfile.fulfilled, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.user = action.payload; // Update current user only
|
||||||
|
toast.success("Profile Details updated successfully");
|
||||||
|
})
|
||||||
|
|
||||||
|
.addCase(updateProfile.rejected, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.error = action.payload;
|
||||||
|
})
|
||||||
|
.addCase(updateProfile.pending, (state) => {
|
||||||
|
state.loading = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue