diff --git a/src/services/auth.services.js b/src/services/auth.services.js index 833785a..25e0388 100644 --- a/src/services/auth.services.js +++ b/src/services/auth.services.js @@ -81,3 +81,23 @@ export const resetPassword = (data) => { .catch((err) => reject(err)); }); }; + +export const updateAdmin = (data, id) => { + const url = `/admin/user/${id}`; + return new Promise((resolve, reject) => { + axiosInstance + .put(url, data) + .then((response) => resolve(response)) + .catch((err) => reject(err)); + }); +}; + +export const deleteAdmin = (id) => { + const url = `/admin/user/${id}`; + return new Promise((resolve, reject) => { + axiosInstance + .delete(url) + .then((response) => resolve(response)) + .catch((err) => reject(err)); + }); +}; diff --git a/src/services/clinics.service.js b/src/services/clinics.service.js index 64d607c..5262a71 100644 --- a/src/services/clinics.service.js +++ b/src/services/clinics.service.js @@ -111,8 +111,8 @@ export const getClinicOffer = (params) => { }); }; -export const updateClinicOffer = (data) => { - const url = `/admin/clinic/offer`; +export const updateClinicOffer = (data, id) => { + const url = `/admin/clinic/offer/${id}`; return new Promise((resolve, reject) => { axiosInstance .put(url, data) diff --git a/src/services/masterData.services.js b/src/services/masterData.services.js index e7c40df..e19425b 100644 --- a/src/services/masterData.services.js +++ b/src/services/masterData.services.js @@ -24,8 +24,8 @@ export const setMasterData = (data) => { }); }; -export const updateMasterData = (data) => { - const url = "/admin/master-data"; +export const updateMasterData = (data, id) => { + const url = `/admin/master-data/${id}`; return new Promise((resolve, reject) => { axiosInstance .put(url, data) @@ -33,3 +33,13 @@ export const updateMasterData = (data) => { .catch((err) => reject(err)); }); }; + +export const deleteMasterData = (id) => { + const url = `/admin/master-data/${id}`; + return new Promise((resolve, reject) => { + axiosInstance + .delete(url) + .then((response) => resolve(response)) + .catch((err) => reject(err)); + }); +}; diff --git a/src/views/Dashboard/index.jsx b/src/views/Dashboard/index.jsx index 2caaca9..96aad86 100644 --- a/src/views/Dashboard/index.jsx +++ b/src/views/Dashboard/index.jsx @@ -107,7 +107,9 @@ function Dashboard() { const clinicAdmin = ( - + {!isActive && ( + + )} diff --git a/src/views/MasterData/index.jsx b/src/views/MasterData/index.jsx index a6f4c10..d02a51a 100644 --- a/src/views/MasterData/index.jsx +++ b/src/views/MasterData/index.jsx @@ -1,5 +1,6 @@ import AddIcon from "@mui/icons-material/Add"; -import DescriptionIcon from '@mui/icons-material/Description'; +import EditIcon from "@mui/icons-material/Edit"; +import DeleteIcon from "@mui/icons-material/Delete"; import CloseIcon from "@mui/icons-material/Close"; import PersonAddIcon from "@mui/icons-material/PersonAdd"; import { @@ -21,16 +22,24 @@ import { pushNotification } from "../../utils/notification"; import { NOTIFICATION } from "../../constants"; import { useStyles } from "./masterDataStyles"; import Table from "../../components/Table"; -import { getMasterData, setMasterData } from "../../services/masterData.services"; +import { + getMasterData, + setMasterData, + updateMasterData, + deleteMasterData, +} from "../../services/masterData.services"; const MasterDataManagement = () => { const classes = useStyles(); - const ref = useRef(null); + const tableRef = useRef(null); // State for form fields const [type, setType] = useState(""); + const [editId, setEditId] = useState(null); + const [deleteId, setDeleteId] = useState(null); // State for dialog const [openDialog, setOpenDialog] = useState(false); + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); // Handle dialog open/close const handleOpenDialog = () => { @@ -41,6 +50,38 @@ const MasterDataManagement = () => { setOpenDialog(false); // Clear form setType(""); + setEditId(null); + }; + + // Open delete confirmation dialog + const openDeleteConfirmation = (id) => { + setDeleteId(id); + setDeleteDialogOpen(true); + }; + + // Handle delete master data after confirmation + const handleDelete = async () => { + try { + const resp = await deleteMasterData(deleteId); + pushNotification( + "Appointment type deleted successfully", + NOTIFICATION.SUCCESS + ); + } catch (error) { + console.error("Error deleting appointment type:", error); + pushNotification( + `Failed to delete appointment type`, + NOTIFICATION.ERROR + ); + } + + // Close the dialog and refresh the table + setDeleteDialogOpen(false); + setDeleteId(null); + + if (tableRef.current) { + tableRef.current.reFetchData(); + } }; // Handle form submission @@ -51,34 +92,49 @@ const MasterDataManagement = () => { type, }; - const response = await setMasterData(payload); + let resp; - if (response?.data?.data) { - pushNotification("Master Data created successfully!", NOTIFICATION.SUCCESS); + if (editId !== null) { + resp = await updateMasterData(payload, editId); } else { - pushNotification(response?.data?.message, NOTIFICATION.ERROR); + resp = await setMasterData(payload); + } + + if (resp?.data?.data) { + pushNotification( + "Master Data created successfully!", + NOTIFICATION.SUCCESS + ); + } else { + pushNotification(resp?.data?.message, NOTIFICATION.ERROR); + } + + // Refresh the table data + if (tableRef.current) { + tableRef.current.reFetchData(); } // Close dialog handleCloseDialog(); + setEditId(null); }; const getData = async (filters) => { try { // Remove the type parameter since it's not defined let params = { - ...filters + ...filters, }; - + const resp = await getMasterData(params); - console.log('API Response:', resp); - + console.log("API Response:", resp); + return { data: resp?.data?.data?.data, rowCount: resp?.data?.data?.total || 0, }; } catch (error) { - console.error('Error fetching admins:', error); + console.error("Error fetching admins:", error); return { data: [], rowCount: 0, @@ -86,6 +142,12 @@ const MasterDataManagement = () => { } }; + const handleEdit = async (row) => { + setEditId(row.original.id); // Store the ID for update operation + setType(row.original.type); + setOpenDialog(true); + }; + // ...................breadcrumbs array........................ const breadcrumbs = [ { @@ -121,7 +183,7 @@ const MasterDataManagement = () => { accessorKey: "type", header: "Type", enableColumnFilter: false, - } + }, // Removed the empty object that was causing the error ]); @@ -147,23 +209,20 @@ const MasterDataManagement = () => { }} searchText="Master Data" showSearchBox={true} - ref={ref} - // actions={[ - // { - // onClick: (row) => { - - // }, - // text: "Remove", - // icon: ( - // - // // transaction history - // ), - // }, - // ]} + showAction={true} + ref={tableRef} + actions={[ + { + onClick: (row) => handleEdit(row), + text: "Edit", + icon: , + }, + { + onClick: (row) => openDeleteConfirmation(row.original.id), + text: "Delete", + icon: , + }, + ]} /> @@ -173,26 +232,34 @@ const MasterDataManagement = () => { onClose={handleCloseDialog} maxWidth="sm" fullWidth + PaperProps={{ + sx: { + borderRadius: "12px", + overflow: "hidden", + }, + }} > theme.palette.primary.main, + color: "white", + fontWeight: "bold", + position: "relative", }} > - - - - Add Appointment Type - - - + {editId !== null + ? "Edit Appointment Type" + : "Add New Appointment Type"} + @@ -219,7 +286,7 @@ const MasterDataManagement = () => { + + {/* Delete Confirmation Dialog */} + setDeleteDialogOpen(false)} + maxWidth="xs" + fullWidth + PaperProps={{ + sx: { + borderRadius: "12px", + overflow: "hidden", + }, + }} + > + theme.palette.error.main, + color: "white", + fontWeight: "bold", + position: "relative", + }} + > + Confirm Deletion + setDeleteDialogOpen(false)} + sx={{ + position: "absolute", + right: 8, + top: 8, + color: "white", + }} + > + + + + + + + Are you sure you want to delete this appointment type? This action cannot be undone. + + + + theme.palette.grey[200], + justifyContent: "space-between", + }} + > + + + + + ); diff --git a/src/views/PaymentManagement/index.jsx b/src/views/PaymentManagement/index.jsx index 6be4a6c..6f2e232 100644 --- a/src/views/PaymentManagement/index.jsx +++ b/src/views/PaymentManagement/index.jsx @@ -1,5 +1,6 @@ import AddIcon from "@mui/icons-material/Add"; import EditIcon from "@mui/icons-material/Edit"; +import DeleteIcon from "@mui/icons-material/Delete"; import CloseIcon from "@mui/icons-material/Close"; import { Box, @@ -28,12 +29,13 @@ import { NOTIFICATION } from "../../constants"; import { emailRegex } from "../../utils/regex"; import { createClinicOffer, + deleteClinicOffer, getClinicOffer, + updateClinicOffer, } from "../../services/clinics.service"; const PaymentManagement = () => { const classes = useStyles(); - const ref = useRef(null); const tableRef = useRef(null); // State for payment dialog @@ -46,10 +48,11 @@ const PaymentManagement = () => { }); // State for payments list - const [paymentsList, setPaymentsList] = useState([]); - const [editPaymentIndex, setEditPaymentIndex] = useState(null); - - const handleSubmit = () => {}; + const [editPaymentId, setEditPaymentId] = useState(null); + + // State for delete confirmation dialog + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); + const [deletePaymentId, setDeletePaymentId] = useState(null); const columns = useMemo(() => [ { @@ -98,7 +101,6 @@ const PaymentManagement = () => { }; const resp = await getClinicOffer(params); - console.log("API Response:", resp); return { data: resp?.data?.data?.data, @@ -113,7 +115,7 @@ const PaymentManagement = () => { } }; - // Handle payment dialog submission + // Handle payment dialog submission (both add and update) const handleAddPayment = async () => { // Validate input if (!paymentData.clinicEmail.trim()) { @@ -143,45 +145,99 @@ const PaymentManagement = () => { : "0", }; - const resp = await createClinicOffer(payload); - console.log("API Response:", resp); + try { - // Reset form and close dialog + if (editPaymentId !== null) { + const resp = await updateClinicOffer(payload, editPaymentId); + } + else{ + const resp = await createClinicOffer(payload); + } + + // Reset form and close dialog + setPaymentData({ + clinicEmail: "", + setupFeeWaived: false, + specialOffer: false, + configurationMonth: 3, + }); + setEditPaymentId(null); + setPaymentDialogOpen(false); + + // Refresh the table data + if (tableRef.current) { + tableRef.current.reFetchData(); + pushNotification( + `Payment configuration ${editPaymentId !== null ? 'updated' : 'added'} successfully`, + NOTIFICATION.SUCCESS + ); + } + } catch (error) { + console.error("Error saving payment configuration:", error); + pushNotification( + `Failed to ${editPaymentId !== null ? 'update' : 'add'} payment configuration`, + NOTIFICATION.ERROR + ); + } + }; + + // Handle edit payment + const handleEditPayment = (rowData) => { + // Convert the data from API format to form format + const formattedData = { + clinicEmail: rowData.original.clinic_email, + setupFeeWaived: rowData.original.setup_fees_waived, + specialOffer: rowData.original.special_offer_for_month !== "0", + configurationMonth: rowData.original.special_offer_for_month !== "0" ? parseInt(rowData.original.special_offer_for_month) : 3, + }; + + setEditPaymentId(rowData.original.id); // Store the ID for update operation + setPaymentData(formattedData); + setPaymentDialogOpen(true); + }; + + // Open delete confirmation dialog + const openDeleteConfirmation = (id) => { + setDeletePaymentId(id); + setDeleteDialogOpen(true); + }; + + const handleDialog = () => { + setPaymentDialogOpen(!paymentDialogOpen); setPaymentData({ clinicEmail: "", setupFeeWaived: false, specialOffer: false, configurationMonth: 3, }); - setEditPaymentIndex(null); - setPaymentDialogOpen(false); + setEditPaymentId(null); + }; + + // Handle delete payment after confirmation + const handleDeletePayment = async () => { + try { + const resp = await deleteClinicOffer(deletePaymentId); + pushNotification( + "Payment configuration deleted successfully", + NOTIFICATION.SUCCESS + ); + } catch (error) { + console.error("Error deleting payment configuration:", error); + pushNotification( + `Failed to delete payment configuration`, + NOTIFICATION.ERROR + ); + } + + // Close the dialog and refresh the table + setDeleteDialogOpen(false); + setDeletePaymentId(null); - // Refresh the table data if (tableRef.current) { tableRef.current.reFetchData(); - pushNotification("Payment configuration added successfully", NOTIFICATION.SUCCESS); } }; - // Handle edit payment - const handleEditPayment = (index) => { - setEditPaymentIndex(index); - setPaymentData({ ...paymentsList[index] }); - setPaymentDialogOpen(true); - }; - - // Handle delete payment - const handleDeletePayment = (index) => { - const updatedPayments = [...paymentsList]; - updatedPayments.splice(index, 1); - setPaymentsList(updatedPayments); - - pushNotification( - "Payment configuration deleted successfully", - NOTIFICATION.SUCCESS - ); - }; - // Breadcrumbs const breadcrumbs = [ { label: "Dashboard", link: "/" }, @@ -194,7 +250,7 @@ const PaymentManagement = () => { } - onAddButtonClick={() => setPaymentDialogOpen(true)} + onAddButtonClick={handleDialog} /> @@ -209,13 +265,19 @@ const PaymentManagement = () => { showTopBar: false, showFilters: true, }} + showAction={true} searchText="Staff" showSearchBox={true} actions={[ { onClick: (row) => handleEditPayment(row), text: "Edit", - icon: , + icon: (), + }, + { + onClick: (row) => openDeleteConfirmation(row.original.id), + text: "Delete", + icon: (), }, ]} /> @@ -225,7 +287,7 @@ const PaymentManagement = () => { {/* Improved Dialog Box */} setPaymentDialogOpen(false)} + onClose={handleDialog} maxWidth="sm" fullWidth PaperProps={{ @@ -244,12 +306,12 @@ const PaymentManagement = () => { position: "relative", }} > - {editPaymentIndex !== null + {editPaymentId !== null ? "Edit Payment Configuration" : "Add New Payment"} setPaymentDialogOpen(false)} + onClick={handleDialog} sx={{ position: "absolute", right: 8, @@ -262,7 +324,7 @@ const PaymentManagement = () => { - + Clinic Information @@ -405,7 +467,81 @@ const PaymentManagement = () => { px: 3, }} > - {editPaymentIndex !== null ? "Update" : "Save"} + {editPaymentId !== null ? "Update" : "Save"} + + + + + {/* Delete Confirmation Dialog */} + setDeleteDialogOpen(false)} + maxWidth="xs" + fullWidth + PaperProps={{ + sx: { + borderRadius: "12px", + overflow: "hidden", + }, + }} + > + theme.palette.error.main, + color: "white", + fontWeight: "bold", + position: "relative", + }} + > + Confirm Deletion + setDeleteDialogOpen(false)} + sx={{ + position: "absolute", + right: 8, + top: 8, + color: "white", + }} + > + + + + + + + Are you sure you want to delete this payment configuration? This action cannot be undone. + + + + theme.palette.grey[200], + justifyContent: "space-between", + }} + > + + diff --git a/src/views/StaffManagement/index.jsx b/src/views/StaffManagement/index.jsx index 6c699d8..e99957e 100644 --- a/src/views/StaffManagement/index.jsx +++ b/src/views/StaffManagement/index.jsx @@ -1,4 +1,6 @@ import AddIcon from "@mui/icons-material/Add"; +import EditIcon from "@mui/icons-material/Edit"; +import DeleteIcon from "@mui/icons-material/Delete"; import CloseIcon from "@mui/icons-material/Close"; import PersonAddIcon from "@mui/icons-material/PersonAdd"; import { @@ -16,7 +18,7 @@ import { import React, { useMemo, useRef, useState } from "react"; import CustomBreadcrumbs from "../../components/CustomBreadcrumbs"; import PageHeader from "../../components/PageHeader"; -import { createAdmin, getAdmins } from "../../services/auth.services"; +import { createAdmin, getAdmins, updateAdmin, deleteAdmin } from "../../services/auth.services"; import { pushNotification } from "../../utils/notification"; import { NOTIFICATION } from "../../constants"; import { useStyles } from "./staffStyles"; @@ -25,14 +27,22 @@ import Table from "../../components/Table"; const StaffManagement = () => { const classes = useStyles(); const ref = useRef(null); + const tableRef = useRef(null); + // State for form fields const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [email, setEmail] = useState(""); const [emailError, setEmailError] = useState(""); + const [isEditMode, setIsEditMode] = useState(false); + const [editId, setEditId] = useState(null); // State for dialog const [openDialog, setOpenDialog] = useState(false); + + // State for delete confirmation dialog + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); + const [deleteId, setDeleteId] = useState(null); // Email validation function const validateEmail = (email) => { @@ -52,27 +62,52 @@ const StaffManagement = () => { setLastName(""); setEmail(""); setEmailError(""); + setIsEditMode(false); + setEditId(null); }; // Handle form submission const handleSubmit = async (e) => { e.preventDefault(); - // Validate email - if (!validateEmail(email)) { - setEmailError("Please enter a valid email address"); - return; + // For edit mode, only username is required + if (!isEditMode) { + // Validate email + if (!validateEmail(email)) { + setEmailError("Please enter a valid email address"); + return; + } } - const payload = { - username: `${firstName} ${lastName}`, - email, - }; - - const response = await createAdmin(payload); + let response; + + if (isEditMode) { + // In edit mode, only update the username + const payload = { + username: `${firstName} ${lastName}`, + }; + + response = await updateAdmin(payload, editId); + } else { + // In create mode, include both username and email + const payload = { + username: `${firstName} ${lastName}`, + email, + }; + + response = await createAdmin(payload); + } if (response?.data?.data) { - pushNotification("Admin created successfully!", NOTIFICATION.SUCCESS); + pushNotification( + `Admin ${isEditMode ? 'updated' : 'created'} successfully!`, + NOTIFICATION.SUCCESS + ); + + // Refresh the table + if (tableRef.current) { + tableRef.current.reFetchData(); + } } else { pushNotification(response?.data?.message, NOTIFICATION.ERROR); } @@ -85,18 +120,17 @@ const StaffManagement = () => { try { // Remove the type parameter since it's not defined let params = { - ...filters + ...filters, }; - + const resp = await getAdmins(params); - console.log('API Response:', resp); - + return { data: resp?.data?.data?.data, rowCount: resp?.data?.total || 0, }; } catch (error) { - console.error('Error fetching admins:', error); + console.error("Error fetching admins:", error); return { data: [], rowCount: 0, @@ -104,6 +138,52 @@ const StaffManagement = () => { } }; + const handleEdit = (row) => { + setIsEditMode(true); + setEditId(row.original.id); + + // Split the username into first and last name + const nameParts = row.original.username.split(' '); + setFirstName(nameParts[0] || ''); + setLastName(nameParts.slice(1).join(' ') || ''); + + // Set email but make it read-only in the form + setEmail(row.original.email); + + setOpenDialog(true); + } + + // Open delete confirmation dialog + const openDeleteConfirmation = (id) => { + setDeleteId(id); + setDeleteDialogOpen(true); + }; + + // Handle delete after confirmation + const handleDelete = async () => { + try { + const resp = await deleteAdmin(deleteId); + pushNotification( + "Admin deleted successfully", + NOTIFICATION.SUCCESS + ); + } catch (error) { + console.error("Error deleting admin:", error); + pushNotification( + "Failed to delete admin", + NOTIFICATION.ERROR + ); + } + + // Close the dialog and refresh the table + setDeleteDialogOpen(false); + setDeleteId(null); + + if (tableRef.current) { + tableRef.current.reFetchData(); + } + }; + // ...................breadcrumbs array........................ const breadcrumbs = [ { @@ -169,7 +249,20 @@ const StaffManagement = () => { }} searchText="Staff" showSearchBox={true} - ref={ref} + showAction={true} + ref={tableRef} + actions={[ + { + onClick: (row) => handleEdit(row), + text: "Edit", + icon: , + }, + { + onClick: (row) => openDeleteConfirmation(row.original.id), + text: "Delete", + icon: , + }, + ]} /> @@ -195,7 +288,7 @@ const StaffManagement = () => { component="span" sx={{ fontWeight: "bold", color: "#0a2d6b" }} > - Add New Staff + {isEditMode ? "Edit Staff" : "Add New Staff"} @@ -233,24 +326,38 @@ const StaffManagement = () => { }} /> - { - setEmail(e.target.value); - setEmailError(""); - }} - placeholder="Email Address" - error={!!emailError} - helperText={emailError} - required - InputLabelProps={{ - shrink: true, - }} - /> + {!isEditMode ? ( + { + setEmail(e.target.value); + setEmailError(""); + }} + placeholder="Email Address" + error={!!emailError} + helperText={emailError} + required + InputLabelProps={{ + shrink: true, + }} + /> + ) : ( + + )} @@ -268,7 +375,81 @@ const StaffManagement = () => { }, }} > - Add Admin + {isEditMode ? "Update Admin" : "Add Admin"} + + + + + {/* Delete Confirmation Dialog */} + setDeleteDialogOpen(false)} + maxWidth="xs" + fullWidth + PaperProps={{ + sx: { + borderRadius: "12px", + overflow: "hidden", + }, + }} + > + theme.palette.error.main, + color: "white", + fontWeight: "bold", + position: "relative", + }} + > + Confirm Deletion + setDeleteDialogOpen(false)} + sx={{ + position: "absolute", + right: 8, + top: 8, + color: "white", + }} + > + + + + + + + Are you sure you want to delete this admin? This action cannot be undone. + + + + theme.palette.grey[200], + justifyContent: "space-between", + }} + > + +