diff --git a/src/components/AddEditCategoryModal/index.tsx b/src/components/AddEditCategoryModal/index.tsx index 656db62..b356e3b 100644 --- a/src/components/AddEditCategoryModal/index.tsx +++ b/src/components/AddEditCategoryModal/index.tsx @@ -45,7 +45,7 @@ const AddEditCategoryModal: React.FC = ({ open, handl onSubmit: handleSubmit(onSubmit), }} > - {editRow ? "Editwefwefwe" : 'Add'} Category + {editRow ? "Edit" : 'Add'} Category = ({ open, handleClose,e onSubmit: handleSubmit(onSubmit), }} > - {editRow ? "Editsefwefwe" : 'Add'} Tag + {editRow ? "Edit" : 'Add'} Tag ({ - [`&.${tableCellClasses.head}`]: { - backgroundColor: ' #1565c0', - color: theme.palette.common.white, - }, - [`&.${tableCellClasses.body}`]: { - fontSize: 14, - }, -})); + [`&.${tableCellClasses.head}`]: { + backgroundColor: " #1565c0", + color: theme.palette.common.white, + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14, + }, +})) const StyledTableRow = styled(TableRow)(({ theme }) => ({ - '&:nth-of-type(odd)': { - backgroundColor: theme.palette.action.hover, - }, - '&:last-child td, &:last-child th': { - border: 0, - }, -})); + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, + }, + "&:last-child td, &:last-child th": { + border: 0, + }, +})) interface Column { - id: string; - label: string; - align?: 'left' | 'center' | 'right'; + id: string + label: string + align?: "left" | "center" | "right" } interface Row { - [key: string]: any; + [key: string]: any } interface CustomTableProps { - columns: Column[]; - rows: Row[]; - setDeleteModal: Function; - setRowData: Function; - setModalOpen: Function; + columns: Column[] + rows: Row[] + setDeleteModal: Function + setRowData: Function + setModalOpen: Function + deleteModal: boolean } const CustomTable: React.FC = ({ - columns, - rows, - setDeleteModal, - setRowData, - setModalOpen, + columns, + rows, + setDeleteModal, + deleteModal, + setRowData, + setModalOpen, }) => { - console.log('columnsss', columns, rows); + // console.log("columnsss", columns, rows) + const dispatch = useDispatch() + const [anchorEl, setAnchorEl] = React.useState(null) + const [selectedRow, setSelectedRow] = React.useState(null) + const open = Boolean(anchorEl) - const [anchorEl, setAnchorEl] = React.useState(null); - const open = Boolean(anchorEl); - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; - const handleClose = () => { - setAnchorEl(null); - }; - - const isImage = (value: any) => { - if (typeof value === 'string') { - return value.startsWith('http') || value.startsWith('data:image'); // Check for URL or base64 image + const handleClick = (event: React.MouseEvent, row: Row) => { + setAnchorEl(event.currentTarget) + setSelectedRow(row) // Ensure the row data is set } - return false; - }; - return ( - - - - - {columns.map((column) => ( - - {column.label} - - ))} - - - - {rows.map((row, rowIndex) => ( - - {columns.map((column) => ( - - {isImage(row[column.id]) ? ( - Row - ) : column.id !== 'action' ? ( - row[column.id] - ) : ( - { - handleClick(e); - setRowData(row); - }} + const handleClose = () => { + setAnchorEl(null) + } + + const isImage = (value: any) => { + if (typeof value === "string") { + return value.startsWith("http") || value.startsWith("data:image") // Check for URL or base64 image + } + return false + } + + const handleDeleteButton = (id: string | undefined) => { + if (!id) console.error("ID not found", id) + + dispatch(deleteAdmin(id || "")) + setDeleteModal(false) // Close the modal only after deletion + handleClose() + } + + return ( + +
+ + + {columns.map((column) => ( + + {column.label} + + ))} + + + + {rows.map((row, rowIndex) => ( + + {columns.map((column) => ( + + {isImage(row[column.id]) ? ( + Row + ) : column.id !== "action" ? ( + row[column.id] + ) : ( + { + handleClick(e, row) + setSelectedRow(row) // Store the selected row + }} + > + + + )} + + ))} + + ))} + +
+ {open && ( + + - - - )} - - ))} - - ))} - - - {open && ( - - - - - - - )} - - ); -}; + -export default CustomTable; + + {deleteModal && ( + + handleDeleteButton(selectedRow?.id) + } + open={deleteModal} + setDeleteModal={setDeleteModal} + id={selectedRow?.id} + /> + )} + + + )} +
+ ) +} + +export default CustomTable diff --git a/src/components/Modals/DeleteModal/DeleteModal.tsx b/src/components/Modals/DeleteModal/DeleteModal.tsx index 5e242d3..e7d03d8 100644 --- a/src/components/Modals/DeleteModal/DeleteModal.tsx +++ b/src/components/Modals/DeleteModal/DeleteModal.tsx @@ -1,77 +1,84 @@ -import { Box, Button, Modal, Typography } from '@mui/material'; -import { MouseEventHandler } from 'react'; +import { Box, Button, Modal, Typography } from "@mui/material" type Props = { - open: boolean; - setDeleteModal: Function; - handleDelete: MouseEventHandler; -}; + open: boolean + setDeleteModal: Function + handleDelete: (id: string | undefined) => void + id?: string | undefined +} const style = { - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - width: 330, - bgcolor: 'background.paper', - borderRadius: 1.5, - boxShadow: 24, - p: 3, -}; + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: 330, + bgcolor: "background.paper", + borderRadius: 1.5, + boxShadow: 24, + p: 3, +} -const btnStyle = { py: 1, px: 5, width: '50%', textTransform: 'capitalize' }; +const btnStyle = { py: 1, px: 5, width: "50%", textTransform: "capitalize" } export default function DeleteModal({ - open, - setDeleteModal, - handleDelete, + open, + setDeleteModal, + handleDelete, + id, }: Props) { - return ( - - - - Delete Record - - - Are you sure you want to delete this record? - - - - - - - - ); + + + Delete Record + + + Are you sure you want to delete this record? + + + + + + + + ) } diff --git a/src/lib/https.ts b/src/lib/https.ts index 093782b..b7443bd 100644 --- a/src/lib/https.ts +++ b/src/lib/https.ts @@ -17,7 +17,6 @@ import axios, { AxiosInstance } from 'axios'; -// Axios instance for the production backend const backendHttp = axios.create({ baseURL: process.env.REACT_APP_BACKEND_URL, }); diff --git a/src/pages/AdminList/index.tsx b/src/pages/AdminList/index.tsx index 2502445..fc1ae57 100644 --- a/src/pages/AdminList/index.tsx +++ b/src/pages/AdminList/index.tsx @@ -3,12 +3,11 @@ import { Box, Button, Typography } from "@mui/material" import AddEditCategoryModal from "../../components/AddEditCategoryModal" import { useForm } from "react-hook-form" import CustomTable from "../../components/CustomTable" -import DeleteModal from "../../components/Modals/DeleteModal/DeleteModal" +// import DeleteModal from "../../components/Modals/DeleteModal/DeleteModal" import { useDispatch, useSelector } from "react-redux" import { adminList } from "../../redux/slices/authSlice" import { AppDispatch, RootState } from "../../redux/store/store" // Import RootState for selector - // Sample data for categories export default function AdminList() { @@ -19,21 +18,16 @@ export default function AdminList() { const [deleteModal, setDeleteModal] = React.useState(false) const [rowData, setRowData] = React.useState(null) - const dispatch = useDispatch(); + const dispatch = useDispatch() // Fetching admin data from the Redux store - const admins = useSelector((state: RootState) => state.auth.admins); - - - console.log(admins, "woihfiuwhfownfownefoi") - + const admins = useSelector((state: RootState) => state.auth.admins) // Dispatching the API call when the component mounts useEffect(() => { - dispatch(adminList()); - }, [dispatch]); - + dispatch(adminList()) + }, [dispatch]) - const handleClickOpen = () => { + const handleClickOpen = () => { setModalOpen(true) setEditRow(null) } @@ -43,9 +37,9 @@ export default function AdminList() { reset() } - const handleDelete = () => { - setDeleteModal(false) - } + // const handleDelete = () => { + // setDeleteModal(false) + // } const categoryColumns = [ { id: "srno", label: "Sr No" }, @@ -55,11 +49,19 @@ export default function AdminList() { ] // If no admins are available, display the sample data - const categoryRows = admins?.length ? admins?.map((admin: { name: any; role: any }, index: number) => ({ - srno: index + 1, - name: admin?.name, - role: admin.role, - })) : [] + const categoryRows = admins?.length + ? admins?.map( + ( + admin: { id: string; name: string; role: string }, + index: number + ) => ({ + id: admin.id, + srno: index + 1, + name: admin?.name, + role: admin.role, + }) + ) + : [] return ( <> @@ -97,6 +99,7 @@ export default function AdminList() { rows={categoryRows} editRow={editRow} setDeleteModal={setDeleteModal} + deleteModal={deleteModal} setRowData={setRowData} setModalOpen={setModalOpen} /> @@ -105,11 +108,11 @@ export default function AdminList() { handleClose={handleCloseModal} editRow={rowData} /> - + /> */} ) } diff --git a/src/redux/slices/authSlice.ts b/src/redux/slices/authSlice.ts index aff6def..f725726 100644 --- a/src/redux/slices/authSlice.ts +++ b/src/redux/slices/authSlice.ts @@ -1,26 +1,36 @@ -import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit" +import { + createSlice, + createAsyncThunk, + PayloadAction, + isRejectedWithValue, +} from "@reduxjs/toolkit" import axios from "axios" import { backendHttp, apiHttp } from "../../lib/https" import { toast } from "react-toastify" // Define types for state interface User { - map(arg0: (admin: { name: any; role: any }, index: number) => { srno: number; name: any; role: any }): unknown + map( + arg0: ( + admin: { name: any; role: any }, + index: number + ) => { srno: number; name: any; role: any } + ): unknown id: string email: string } interface Admin { - id: string, - name: string, + id: string + name: string role: string } interface AuthState { - user: User | null; - admins: Admin[]; - isAuthenticated: boolean; - isLoading: boolean; - error: string | null; + user: User | null + admins: Admin[] + isAuthenticated: boolean + isLoading: boolean + error: string | null } // Async thunk for login @@ -30,7 +40,10 @@ export const loginUser = createAsyncThunk< { rejectValue: string } >("auth/login", async ({ email, password }, { rejectWithValue }) => { try { - const response = await backendHttp.post("admin/login", { email, password }) + const response = await backendHttp.post("admin/login", { + email, + password, + }) localStorage.setItem("authToken", response.data?.data?.token) // Save token toast.success(response.data?.message) return response.data @@ -66,19 +79,56 @@ export const adminList = createAsyncThunk< { rejectValue: string } >("/auth", async (_, { rejectWithValue }) => { try { - const response = await apiHttp.get("/auth"); - console.log(response) - return response?.data?.data?.map((admin: { name: string; role: string }) => ({ - - name: admin?.name, - role: admin?.role || "N/A", - })); + const response = await apiHttp.get("/auth") + console.log(response?.data?.data) + return response?.data?.data?.map( + (admin: { id: string; name: string; role: string }) => ({ + id: admin.id, + name: admin?.name, + role: admin?.role || "N/A", + }) + ) console.log(response.data.data) } catch (error: any) { - return rejectWithValue(error.response?.data?.message || "An error occurred"); + return rejectWithValue( + error.response?.data?.message || "An error occurred" + ) } -}); +}) +export const deleteAdmin = createAsyncThunk< + string, + string, + { rejectValue: string } +>("deleteAdmin", async (id, { rejectWithValue }) => { + try { + const response = await apiHttp.delete(`/auth/${id}`) + // console.log(response, "response of deletion") + return id // Returning the deleted admin's ID + } catch (error: any) { + return rejectWithValue( + error.response?.data?.message || "An error occurred" + ) + } +}) + +// export const putAdmin = createAsyncThunk< +// Admin, // Return type (updated admin object) +// { id: string; data: Partial }, // Argument type +// { rejectValue: string } // Rejection type +// >( +// "updateAdmin", +// async ({ id, data }, { rejectWithValue }) => { +// try { +// const response = await apiHttp.put(`/auth/${id}`, data) +// return response.data // Ensure response contains the updated admin object +// } catch (error: any) { +// return rejectWithValue( +// error.response?.data?.message || "An error occurred" +// ) +// } +// } +// ) const initialState: AuthState = { user: null, @@ -86,7 +136,7 @@ const initialState: AuthState = { isAuthenticated: false, isLoading: false, error: null, -}; +} const authSlice = createSlice({ name: "auth", @@ -140,16 +190,19 @@ const authSlice = createSlice({ } ) - // created by Jaanvi and Eknoor - .addCase(adminList.pending, (state) => { + // created by Jaanvi and Eknoor + //AdminList + .addCase(adminList.pending, (state) => { state.isLoading = true state.error = null }) - .addCase(adminList.fulfilled, (state, action: PayloadAction) => { - state.isLoading = false; - state.admins = action.payload; // ✅ Store admins correctly - }) - + .addCase( + adminList.fulfilled, + (state, action: PayloadAction) => { + state.isLoading = false + state.admins = action.payload + } + ) .addCase( adminList.rejected, @@ -158,6 +211,37 @@ const authSlice = createSlice({ state.error = action.payload || "An error occurred" } ) + + .addCase(deleteAdmin.pending, (state) => { + state.isLoading = true + }) + .addCase(deleteAdmin.fulfilled, (state, action) => { + state.isLoading = false + state.admins = state.admins.filter( + (admin) => String(admin.id) !== String(action.payload) + ) + }) + .addCase(deleteAdmin.rejected, (state, action) => { + state.isLoading = false + state.error = action.payload || "Failed to delete admin" + }) + //update Admin + + // .addCase(putAdmin.pending, (state) => { + // state.isLoading = true + // state.error = null + // }) + // .addCase(putAdmin.fulfilled, (state, action: PayloadAction) => { + // state.isLoading = false + // state.admins = state.admins.map((admin) => + // admin.id === action.payload.id ? action.payload : admin + // ) + // }) + // .addCase(putAdmin.rejected, (state, action: PayloadAction) => { + // state.isLoading = false + // state.error = action.payload || "Failed to update admin" + // }) + }, })