feat: freeze clinic improved

This commit is contained in:
deepvasoya 2025-05-22 16:34:50 +05:30
parent 34bec707ca
commit 1f7c183e7e
4 changed files with 208 additions and 61 deletions

View File

@ -42,6 +42,7 @@ export const CLINIC_STATUS = {
APPROVED: 'APPROVED', APPROVED: 'APPROVED',
APPROVAL_PENDING_DOCUMENT_RESUBMITTED: APPROVAL_PENDING_DOCUMENT_RESUBMITTED:
'APPROVAL_PENDING_DOCUMENT_RESUBMITTED', 'APPROVAL_PENDING_DOCUMENT_RESUBMITTED',
INACTIVE: 'inactive',
}; };
export const CLINIC_DOCUMENT_STATUS = { export const CLINIC_DOCUMENT_STATUS = {

View File

@ -16,8 +16,6 @@ import { clinicsData, registeredClinicsData } from "../mock/clinics";
// }; // };
export const getClinics = (params) => { export const getClinics = (params) => {
console.log(params);
let searchParams = new URLSearchParams(); let searchParams = new URLSearchParams();
searchParams.append("size", params?.pagination?.pageSize ?? 10); searchParams.append("size", params?.pagination?.pageSize ?? 10);
searchParams.append("page", params?.pagination.pageIndex ?? 0); searchParams.append("page", params?.pagination.pageIndex ?? 0);

View File

@ -12,7 +12,7 @@ export const getDashboardStats = () => {
export const getSignupMasterPricing = () => { export const getSignupMasterPricing = () => {
const url = '/dashboard/signup-pricing-master/'; const url = '/dashboard/signup-pricing-master';
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axiosInstance axiosInstance
.get(url) .get(url)
@ -23,7 +23,7 @@ export const getSignupMasterPricing = () => {
export const setSignupMasterPricing = (data) => { export const setSignupMasterPricing = (data) => {
const url = '/dashboard/signup-pricing-master/'; const url = '/dashboard/signup-pricing-master';
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axiosInstance axiosInstance
.post(url, data) .post(url, data)

View File

@ -1,49 +1,63 @@
import React, { useState, useMemo, useEffect, useRef } from "react"; import React, { useState, useMemo, useEffect, useRef } from "react";
import { useTheme } from "@emotion/react"; import { useTheme } from "@emotion/react";
import { useLocation, useNavigate, Link } from "react-router-dom"; import { useLocation, useNavigate, Link } from "react-router-dom";
import StoreIcon from '@mui/icons-material/Store'; import StoreIcon from "@mui/icons-material/Store";
import DescriptionIcon from '@mui/icons-material/Description'; import BlockIcon from "@mui/icons-material/Block";
import { Box, Chip,Tab, Tabs } from '@mui/material'; import {
import { differenceInDays, format } from 'date-fns'; Box,
import { LoadingButton } from '@mui/lab'; Chip,
import FileDownloadIcon from '@mui/icons-material/FileDownload'; Tab,
Tabs,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Button,
Typography,
IconButton,
} from "@mui/material";
import { differenceInDays, format } from "date-fns";
import { LoadingButton } from "@mui/lab";
import FileDownloadIcon from "@mui/icons-material/FileDownload";
import CloseIcon from "@mui/icons-material/Close";
import { useStyles } from "./clinicListStyles"; import { useStyles } from "./clinicListStyles";
import { CLINIC_STATUS, CLINIC_TYPE, NOT_AVAILABLE_TEXT, PLAN_STATUS_TYPE } from "../../constants"; import {
import { getClinics } from "../../services/clinics.service"; CLINIC_STATUS,
CLINIC_TYPE,
NOT_AVAILABLE_TEXT,
NOTIFICATION,
PLAN_STATUS_TYPE,
} from "../../constants";
import { getClinics, updateClinicStatus } from "../../services/clinics.service";
import CustomBreadcrumbs from "../../components/CustomBreadcrumbs"; import CustomBreadcrumbs from "../../components/CustomBreadcrumbs";
import Table from "../../components/Table"; import Table from "../../components/Table";
import TableSelect from "../../components/TableSelect"; import TableSelect from "../../components/TableSelect";
import PageHeader from '../../components/PageHeader'; import PageHeader from "../../components/PageHeader";
import { pushNotification } from "../../utils/notification";
const ClinicsList = () => { const ClinicsList = () => {
const theme = useTheme(); const theme = useTheme();
const ref = useRef(null); const ref = useRef(null);
const classes = useStyles(); const classes = useStyles();
const params = useLocation(); const params = useLocation();
const navigate = useNavigate();
const queryParams = new URLSearchParams(params.search); const queryParams = new URLSearchParams(params.search);
const [type, setType] = useState( const [type, setType] = useState(
queryParams.get("tab") ?? CLINIC_TYPE.UNREGISTERED queryParams.get("tab") ?? CLINIC_TYPE.UNREGISTERED
); );
const showNewPlanAddedModel =
Boolean(queryParams.get("isPlanCreated")) ?? false;
const [isDownloading, setIsDownloading] = useState(false); const [isDownloading, setIsDownloading] = useState(false);
const [totalActive, setTotalActive] = useState(0); const [totalActive, setTotalActive] = useState(0);
const [totalInactive, setTotalInactive] = useState(0); const [totalInactive, setTotalInactive] = useState(0);
const [showModel, setShowModel] = useState(false);
const [modelType, setModelType] = useState("");
const [rowActionData, setRowActionData] = useState("");
const [isEmailSentPopupOpen, setIsEmailSentPopupOpen] = useState(false);
const emailList = useRef();
// State for freeze clinic confirmation dialog
const [freezeDialogOpen, setFreezeDialogOpen] = useState(false);
const [clinicToFreeze, setClinicToFreeze] = useState(null);
const UNREGISTERED_CLINIC_STATUS_OPTIONS = [ const UNREGISTERED_CLINIC_STATUS_OPTIONS = [
{ id: 1, name: CLINIC_STATUS.NOT_REVIEWED, showName: 'Approval Pending' }, { id: 1, name: CLINIC_STATUS.NOT_REVIEWED, showName: "Approval Pending" },
{ id: 2, name: CLINIC_STATUS.APPROVAL_PENDING_DOCUMENT_RESUBMITTED }, { id: 2, name: CLINIC_STATUS.APPROVAL_PENDING_DOCUMENT_RESUBMITTED },
{ id: 3, name: CLINIC_STATUS.ON_HOLD, showName: 'On Hold' }, { id: 3, name: CLINIC_STATUS.ON_HOLD, showName: "On Hold" },
{ id: 4, name: CLINIC_STATUS.REJECTED, showName: 'Rejected' }, { id: 4, name: CLINIC_STATUS.REJECTED, showName: "Rejected" },
]; ];
const columnsUnregistered = useMemo( const columnsUnregistered = useMemo(
@ -79,7 +93,11 @@ const ClinicsList = () => {
<> <>
<div className={classes.companyNameTableColumn}> <div className={classes.companyNameTableColumn}>
{row?.original?.logo ? ( {row?.original?.logo ? (
<img alt="logo" className={classes.companyNameLogo} src={row?.original?.logo}/> <img
alt="logo"
className={classes.companyNameLogo}
src={row?.original?.logo}
/>
) : ( ) : (
<StoreIcon /> <StoreIcon />
)} )}
@ -121,10 +139,7 @@ const ClinicsList = () => {
<> <>
<div> <div>
{row?.original?.update_time {row?.original?.update_time
? format( ? format(new Date(row.original.update_time), "dd MMM yyyy")
new Date(row.original.update_time),
"dd MMM yyyy"
)
: NOT_AVAILABLE_TEXT} : NOT_AVAILABLE_TEXT}
</div> </div>
</> </>
@ -275,7 +290,11 @@ const ClinicsList = () => {
<> <>
<div className={classes.companyNameTableColumn}> <div className={classes.companyNameTableColumn}>
{row?.original?.logo ? ( {row?.original?.logo ? (
<img className={classes.companyNameLogo} src={row?.original?.logo} alt="logo" /> <img
className={classes.companyNameLogo}
src={row?.original?.logo}
alt="logo"
/>
) : ( ) : (
<StoreIcon /> <StoreIcon />
)} )}
@ -330,6 +349,26 @@ const ClinicsList = () => {
); );
}, },
}, },
{
enableSorting: false,
size: 100,
header: "Actions",
Cell: ({ row }) => {
return (
<div className={classes.actions}>
<Button
variant="contained"
color="primary"
onClick={() => openFreezeConfirmation(row)}
>
{row.original.status === CLINIC_STATUS.INACTIVE
? "Unfreeze"
: "Freeze"}
</Button>
</div>
);
},
},
].filter(Boolean), ].filter(Boolean),
[type] [type]
); );
@ -373,10 +412,53 @@ const ClinicsList = () => {
// } // }
}; };
const handleRequestSentClose = () => { // Open freeze confirmation dialog
// setIsEmailSentPopupOpen(false); const openFreezeConfirmation = (row) => {
setClinicToFreeze(row.original);
setFreezeDialogOpen(true);
}; };
// Handle freeze/unfreeze clinic after confirmation
const handleFreezeClinic = async () => {
try {
// Determine if we're freezing or unfreezing based on current status
const isCurrentlyFrozen = clinicToFreeze.status === CLINIC_STATUS.INACTIVE;
const newStatus = isCurrentlyFrozen ? "active" : CLINIC_STATUS.INACTIVE;
const payload = {
clinic_id: clinicToFreeze.id,
status: newStatus,
};
const resp = await updateClinicStatus(payload);
// Show appropriate success message
const successMessage = isCurrentlyFrozen
? "Clinic unfrozen successfully"
: "Clinic frozen successfully";
pushNotification(successMessage, NOTIFICATION.SUCCESS);
// Refresh the table
if (ref.current) {
ref.current.reFetchData();
}
} catch (error) {
// Show appropriate error message
const isCurrentlyFrozen = clinicToFreeze.status === CLINIC_STATUS.INACTIVE;
const errorMessage = isCurrentlyFrozen
? "Failed to unfreeze clinic"
: "Failed to freeze clinic";
console.error(`Error ${isCurrentlyFrozen ? 'unfreezing' : 'freezing'} clinic:`, error);
pushNotification(errorMessage, NOTIFICATION.ERROR);
}
// Close the dialog
setFreezeDialogOpen(false);
setClinicToFreeze(null);
};
const breadcrumbs = [ const breadcrumbs = [
{ {
label: "Dashboard", label: "Dashboard",
@ -385,7 +467,7 @@ const ClinicsList = () => {
{ {
label: "Clinic List", label: "Clinic List",
path: "/clinics", path: "/clinics",
query: { tab: queryParams.get('tab') || 'UNREGISTERED' } query: { tab: queryParams.get("tab") || "UNREGISTERED" },
}, },
]; ];
@ -400,14 +482,18 @@ const ClinicsList = () => {
<PageHeader <PageHeader
pageTitle="Clinic List" pageTitle="Clinic List"
hideAddButton hideAddButton
addButtonIcon={ addButtonIcon={<FileDownloadIcon />}
<FileDownloadIcon />
}
extraComponent={ extraComponent={
<Box className={classes.tabsBox}> <Box className={classes.tabsBox}>
<Tabs value={type} onChange={handleTabsChange}> <Tabs value={type} onChange={handleTabsChange}>
<Tab value={CLINIC_TYPE.UNREGISTERED} label={`Unregistered (${totalInactive})`} /> <Tab
<Tab value={CLINIC_TYPE.REGISTERED} label={`Registered (${totalActive})`} /> value={CLINIC_TYPE.UNREGISTERED}
label={`Unregistered (${totalInactive})`}
/>
<Tab
value={CLINIC_TYPE.REGISTERED}
label={`Registered (${totalActive})`}
/>
{/* <Tab value={COMPANY_TYPE.SUBSCRIBED} label="Subscribers" /> */} {/* <Tab value={COMPANY_TYPE.SUBSCRIBED} label="Subscribers" /> */}
</Tabs> </Tabs>
</Box> </Box>
@ -418,9 +504,7 @@ const ClinicsList = () => {
color="primary" color="primary"
variant="outlined" variant="outlined"
loading={isDownloading} loading={isDownloading}
startIcon={ startIcon={<FileDownloadIcon />}
<FileDownloadIcon />
}
// onClick={handleExport} // onClick={handleExport}
> >
Download Excel Download Excel
@ -456,26 +540,90 @@ const ClinicsList = () => {
ref={ref} ref={ref}
showAction={true} showAction={true}
searchText="Clinics" searchText="Clinics"
actions={[
{
onClick: (row) =>
handleModelOpen(row, "transactionHistory"),
text: "Freeze Clinic",
icon: (
<DescriptionIcon />
// <img
// src={TransactionHistoryIcon}
// className={classes.tableActionIcons}
// alt="transaction history"
// />
),
},
]}
/> />
)} )}
</Box> </Box>
</Box> </Box>
</Box> </Box>
{/* Freeze Clinic Confirmation Dialog */}
<Dialog
open={freezeDialogOpen}
onClose={() => setFreezeDialogOpen(false)}
maxWidth="xs"
fullWidth
PaperProps={{
sx: {
borderRadius: "12px",
overflow: "hidden",
},
}}
>
<DialogTitle
sx={{
padding: "16px 24px",
backgroundColor: (theme) => theme.palette.error.main,
color: "white",
fontWeight: "bold",
position: "relative",
}}
>
{clinicToFreeze?.status === CLINIC_STATUS.INACTIVE
? "Confirm Unfreeze Clinic"
: "Confirm Freeze Clinic"}
<IconButton
aria-label="close"
onClick={() => setFreezeDialogOpen(false)}
sx={{
position: "absolute",
right: 8,
top: 8,
color: "white",
}}
>
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent sx={{ padding: "24px 24px 16px", mt: 1 }}>
<Typography variant="body1">
{clinicToFreeze?.status === CLINIC_STATUS.INACTIVE
? `Are you sure you want to unfreeze ${clinicToFreeze?.name}? This will restore the clinic's access to the system.`
: `Are you sure you want to freeze ${clinicToFreeze?.name}? This will prevent the clinic from accessing the system until unfrozen.`
}
</Typography>
</DialogContent>
<DialogActions
sx={{
padding: "16px 24px",
borderTop: "1px solid",
borderColor: (theme) => theme.palette.grey[200],
justifyContent: "space-between",
}}
>
<Button
onClick={() => setFreezeDialogOpen(false)}
sx={{
color: (theme) => theme.palette.grey[700],
fontWeight: "medium",
}}
>
Cancel
</Button>
<Button
onClick={handleFreezeClinic}
variant="contained"
color="error"
sx={{
borderRadius: "8px",
px: 3,
}}
>
{clinicToFreeze?.status === CLINIC_STATUS.INACTIVE ? "Unfreeze" : "Freeze"}
</Button>
</DialogActions>
</Dialog>
</> </>
); );
}; };