feat: clinic approval

This commit is contained in:
deepvasoya 2025-05-20 14:53:48 +05:30
parent 8d2d652630
commit 1508c54700
3 changed files with 162 additions and 132 deletions

View File

@ -56,7 +56,7 @@ export const getClinicsById = (id) => {
};
export const updateClinicStatus = (data) => {
const url = `/admin/clinic/status/`;
const url = `/admin/clinic/status`;
return new Promise((resolve, reject) => {
axiosInstance
.put(url, data)

View File

@ -1,21 +1,21 @@
import CloseIcon from '@mui/icons-material/Close';
import DoneIcon from '@mui/icons-material/Done';
import RemoveRedEyeOutlinedIcon from '@mui/icons-material/RemoveRedEyeOutlined';
import SaveAltIcon from '@mui/icons-material/SaveAlt';
import VerifiedIcon from '@mui/icons-material/Verified';
import { Box, Button, Grid, Modal, Typography } from '@mui/material';
import { format } from 'date-fns';
import React, { useEffect, useState } from 'react';
import downloadIcon from '../../../assets/images/icon/download.svg';
import ImagePreviewComponent from '../../../components/ImagePreviewComponent';
import CloseIcon from "@mui/icons-material/Close";
import DoneIcon from "@mui/icons-material/Done";
import RemoveRedEyeOutlinedIcon from "@mui/icons-material/RemoveRedEyeOutlined";
import SaveAltIcon from "@mui/icons-material/SaveAlt";
import VerifiedIcon from "@mui/icons-material/Verified";
import { Box, Button, Grid, Modal, Typography } from "@mui/material";
import { format } from "date-fns";
import React, { useEffect, useState } from "react";
import downloadIcon from "../../../assets/images/icon/download.svg";
import ImagePreviewComponent from "../../../components/ImagePreviewComponent";
import {
ABN_NUMBER_LENGTH,
CLINIC_DOCUMENT_STATUS,
CLINIC_STATUS,
FILE_EXTENTIONS_ICONS,
GST_NUMBER_LENGTH,
} from '../../../constants';
import { useStyles } from './styles/fileEvaluateStyles';
} from "../../../constants";
import { useStyles } from "./styles/fileEvaluateStyles";
const FileEvaluate = ({
companyStatus,
@ -32,68 +32,90 @@ const FileEvaluate = ({
const [notReviewedOtherFiles, setNotReviewedOtherFiles] = useState([]);
// const getAscendingArray = (array) => {
// return filteredArray;
// };
useEffect(() => {
if (!Array.isArray(files)) return;
// Process all files at once to avoid multiple iterations
const reviewedLogo = [];
const notReviewedLogo = [];
const reviewedOther = [];
const notReviewedOther = [];
files.forEach(file => {
files.forEach((file) => {
// Handle logo documents
if (file.logo_doc) {
if (file.logo_doc_is_verified) {
reviewedLogo.push({file: file.logo_doc, documentType: 'LOGO', isVerified: file.logo_doc_is_verified});
if (file.logo_is_verified) {
reviewedLogo.push({
file: file.logo_doc,
documentType: "LOGO",
isVerified: file.logo_is_verified,
});
} else {
notReviewedLogo.push({file: file.logo_doc, documentType: 'LOGO', isVerified: file.logo_doc_is_verified});
notReviewedLogo.push({
file: file.logo_doc,
documentType: "LOGO",
isVerified: file.logo_is_verified,
});
}
}
// Handle ABN and contract documents (excluding logo docs which are handled separately)
if (file.abn_doc ) {
if (file.abn_doc) {
if (file.abn_doc_is_verified) {
reviewedOther.push({file: file.abn_doc, documentType: 'ABN', isVerified: file.abn_doc_is_verified});
}
else{
notReviewedOther.push({file: file.abn_doc, documentType: 'ABN', isVerified: file.abn_doc_is_verified});
reviewedOther.push({
file: file.abn_doc,
documentType: "ABN",
isVerified: file.abn_doc_is_verified,
});
} else {
notReviewedOther.push({
file: file.abn_doc,
documentType: "ABN",
isVerified: file.abn_doc_is_verified,
});
}
}
if (file.contract_doc) {
if (file.contract_doc_is_verified) {
reviewedOther.push({file: file.contract_doc, documentType: 'CONTRACT', isVerified: file.contract_doc_is_verified});
} else{
notReviewedOther.push({file: file.contract_doc, documentType: 'CONTRACT', isVerified: file.contract_doc_is_verified});
reviewedOther.push({
file: file.contract_doc,
documentType: "CONTRACT",
isVerified: file.contract_doc_is_verified,
});
} else {
notReviewedOther.push({
file: file.contract_doc,
documentType: "CONTRACT",
isVerified: file.contract_doc_is_verified,
});
}
}
});
// Update state with filtered files
setReviewedLogoFiles(reviewedLogo);
setNotReviewedLogoFiles(notReviewedLogo);
setReviewedOtherFiles(reviewedOther);
setNotReviewedOtherFiles(notReviewedOther);
// Debug logs
console.log('Files processed:', files.length);
console.log('reviewedLogoFiles:', reviewedLogo);
console.log('notReviewedLogoFiles:', notReviewedLogo);
console.log('reviewedOtherFiles:', reviewedOther);
console.log('notReviewedOtherFiles:', notReviewedOther);
console.log("Files processed:", files.length);
console.log("reviewedLogoFiles:", reviewedLogo);
console.log("notReviewedLogoFiles:", notReviewedLogo);
console.log("reviewedOtherFiles:", reviewedOther);
console.log("notReviewedOtherFiles:", notReviewedOther);
}, [files]);
// .........................get file name and extention function.......................
const getFileNameUsingFile = (file) => {
if (file) {
// const url = new URL(file);
// return url.pathname.split('/').pop();
return file
return file;
}
return;
};
@ -101,8 +123,8 @@ const FileEvaluate = ({
const getFileExtentionUsingFile = (file) => {
if (file) {
const url = new URL(file.file);
const fileName = url.pathname.split('/').pop();
return fileName.split('.').pop();
const fileName = url.pathname.split("/").pop();
return fileName.split(".").pop();
}
return;
};
@ -111,20 +133,20 @@ const FileEvaluate = ({
const handleActionClick = (index, file, actionType) => {
const newFile = {
...file,
status:
actionType === 'ACCEPT'
? CLINIC_DOCUMENT_STATUS.APPROVED
: CLINIC_DOCUMENT_STATUS.REJECTED,
isVerified:
actionType === "ACCEPT"
? true
: false,
};
if (file.logo_doc) {
if (file.documentType == "LOGO") {
const updatedFiles = [...notReviewedLogoFiles];
updatedFiles.splice(index, 1, newFile);
setNotReviewedLogoFiles(updatedFiles);
} else {
const updatedFiles = [...notReviewedOtherFiles];
updatedFiles.splice(index, 1, newFile);
setNotReviewedOtherFile(updatedFiles);
setNotReviewedOtherFiles(updatedFiles);
}
onFileButtonClick(newFile);
@ -132,14 +154,14 @@ const FileEvaluate = ({
// ..............buttons.................
const ActionButton = ({ index, file, actionType, onClick }) => {
const isAccept = actionType === 'ACCEPT';
const isAccept = actionType === "ACCEPT";
const buttonClass = isAccept ? classes.acceptButton : classes.rejectButton;
const icon = isAccept ? (
<DoneIcon className={classes.acceptButtonIcon} />
) : (
<CloseIcon className={classes.rejectButtonIcon} />
);
const buttonText = isAccept ? 'Accept' : 'Reject';
const buttonText = isAccept ? "Accept" : "Reject";
return (
<Button className={buttonClass} onClick={() => onClick(index, file)}>
@ -168,13 +190,13 @@ const FileEvaluate = ({
const handleDownload = (file) => {
if (file) {
const anchor = document.createElement('a');
const anchor = document.createElement("a");
anchor.href = file.file; // file is now a direct URL
// Extract filename from URL for download attribute
const fileName = file.file.split('/').pop();
const fileName = file.file.split("/").pop();
anchor.download = fileName;
anchor.click();
}
};
@ -313,19 +335,13 @@ const FileEvaluate = ({
</Box>
</Box>
<Box className={classes.buttonBox}>
{file.status === CLINIC_DOCUMENT_STATUS.REJECTED && (
<DisableRejectedButton />
)}
{file.status === CLINIC_DOCUMENT_STATUS.APPROVED && (
<DisableAcceptedButton />
)}
{file.status === CLINIC_DOCUMENT_STATUS.NOT_REVIEWED && (
<DisableRejectedButton />
)}
{!file.isVerified && <DisableRejectedButton />}
{file.isVerified && <DisableAcceptedButton />}
</Box>
</Box>
</Grid>
))}
{notReviewedLogoFiles.map((file, index) => (
<Grid key={index} className={classes.outerGrid}>
<Box className={classes.outerBox}>
@ -367,14 +383,14 @@ const FileEvaluate = ({
</Box>
</Box>
<Box className={classes.buttonBox}>
{file.status === CLINIC_STATUS.NOT_REVIEWED ? (
{file.isVerified == null ? (
<>
<ActionButton
index={index}
file={file}
actionType="REJECT"
onClick={(index, file) =>
handleActionClick(index, file, 'REJECT')
handleActionClick(index, file, "REJECT")
}
/>
<ActionButton
@ -382,33 +398,33 @@ const FileEvaluate = ({
file={file}
actionType="ACCEPT"
onClick={(index, file) =>
handleActionClick(index, file, 'ACCEPT')
handleActionClick(index, file, "ACCEPT")
}
/>
</>
) : file.status === CLINIC_DOCUMENT_STATUS.REJECTED ? (
) : file.isVerified ? (
<>
<DisableRejectedButton />
<ActionButton
index={index}
file={file}
actionType="ACCEPT"
actionType="REJECT"
onClick={(index, file) =>
handleActionClick(index, file, 'ACCEPT')
handleActionClick(index, file, "REJECT")
}
/>
<DisableAcceptedButton />
</>
) : (
<>
<ActionButton
index={index}
file={file}
actionType="REJECT"
actionType="ACCEPT"
onClick={(index, file) =>
handleActionClick(index, file, 'REJECT')
handleActionClick(index, file, "ACCEPT")
}
/>
<DisableAcceptedButton />
<DisableRejectedButton />
</>
)}
</Box>
@ -426,10 +442,10 @@ const FileEvaluate = ({
<Typography className={classes.titleOfBox}>
CLINIC {file.documentType} INFO
</Typography>
<Typography className={classes.updatedDate}>
Uploaded:{' '}
{format(new Date(file?.updatedAt), 'dd MMM yyyy')}
</Typography>
{/* <Typography className={classes.updatedDate}>
Uploaded:{" "}
{format(new Date(file?.updatedAt), "dd MMM yyyy")}
</Typography> */}
<Typography className={classes.documentNumberAndNameLabel}>
{file.documentNumber}
</Typography>
@ -465,19 +481,13 @@ const FileEvaluate = ({
</Box>
</Box>
<Box className={classes.buttonBox}>
{file.status === CLINIC_DOCUMENT_STATUS.REJECTED && (
<DisableRejectedButton />
)}
{file.status === CLINIC_DOCUMENT_STATUS.APPROVED && (
<DisableAcceptedButton />
)}
{file.status === CLINIC_DOCUMENT_STATUS.NOT_REVIEWED && (
<DisableRejectedButton />
)}
{!file.isVerified && <DisableRejectedButton />}
{file.isVerified && <DisableAcceptedButton />}
</Box>
</Box>
</Grid>
))}
<Grid xs={12}></Grid>
{notReviewedOtherFiles.map((file, index) => (
<Grid key={index} className={classes.outerGrid}>
@ -548,14 +558,14 @@ const FileEvaluate = ({
</Box>
</Box>
<Box className={classes.buttonBox}>
{file.status === CLINIC_STATUS.NOT_REVIEWED ? (
{file.isVerified == null ? (
<>
<ActionButton
index={index}
file={file}
actionType="REJECT"
onClick={(index, file) =>
handleActionClick(index, file, 'REJECT')
handleActionClick(index, file, "REJECT")
}
/>
<ActionButton
@ -563,33 +573,33 @@ const FileEvaluate = ({
file={file}
actionType="ACCEPT"
onClick={(index, file) =>
handleActionClick(index, file, 'ACCEPT')
handleActionClick(index, file, "ACCEPT")
}
/>
</>
) : file.status === CLINIC_DOCUMENT_STATUS.REJECTED ? (
) : file.isVerified ? (
<>
<DisableRejectedButton />
<ActionButton
index={index}
file={file}
actionType="ACCEPT"
actionType="REJECT"
onClick={(index, file) =>
handleActionClick(index, file, 'ACCEPT')
handleActionClick(index, file, "REJECT")
}
/>
<DisableAcceptedButton />
</>
) : (
<>
<ActionButton
index={index}
file={file}
actionType="REJECT"
actionType="ACCEPT"
onClick={(index, file) =>
handleActionClick(index, file, 'REJECT')
handleActionClick(index, file, "ACCEPT")
}
/>
<DisableAcceptedButton />
<DisableRejectedButton />
</>
)}
</Box>
@ -623,15 +633,13 @@ const FileEvaluate = ({
<Grid container>
<Grid item md={12} className={classes.previewFileTitle}>
<Typography color="white">
{previewFile.split('/').pop()}
</Typography>
<Typography color="white">{previewFile.file}</Typography>
</Grid>
</Grid>
<Grid xs={12} className={classes.previewImageGrid}>
<ImagePreviewComponent
fileUrl={previewFile}
fileUrl={previewFile.file}
fileExtension={getFileExtentionUsingFile(previewFile)}
handleDownload={() => handleDownload(previewFile)}
classes={classes}

View File

@ -135,14 +135,46 @@ function ClinicDetails() {
// ................functions.................
const handleFileButtonClick = (file) => {
const oldIndex = updateFiles.findIndex((f) => f.fileURL === file.fileURL);
const oldIndex = updateFiles.findIndex((f) => f.file === file.file);
if (oldIndex === -1) {
setUpdateFiles((prevFiles) => [...prevFiles, file]);
const newFile = {
...file,
};
if (file.documentType == "LOGO") {
newFile.logo_is_verified = file.isVerified;
clinicFiles.logo_is_verified = file.isVerified;
}
if (file.documentType == "ABN") {
newFile.abn_doc_is_verified = file.isVerified;
clinicFiles.abn_doc_is_verified = file.isVerified;
}
if (file.documentType == "CONTRACT") {
newFile.contract_doc_is_verified = file.isVerified;
clinicFiles.contract_doc_is_verified = file.isVerified;
}
setUpdateFiles((prevFiles) => [...prevFiles, newFile]);
} else {
setUpdateFiles((prevFiles) => {
const updatedFiles = [...prevFiles];
updatedFiles[oldIndex] = file;
const fileToBeUpdate = updatedFiles[oldIndex];
if (fileToBeUpdate.documentType == "LOGO") {
fileToBeUpdate.logo_is_verified = file.isVerified;
clinicFiles.logo_is_verified = file.isVerified;
}
if (fileToBeUpdate.documentType == "ABN") {
fileToBeUpdate.abn_doc_is_verified = file.isVerified;
clinicFiles.abn_doc_is_verified = file.isVerified;
}
if (fileToBeUpdate.documentType == "CONTRACT") {
fileToBeUpdate.contract_doc_is_verified = file.isVerified;
clinicFiles.contract_doc_is_verified = file.isVerified;
}
updatedFiles[oldIndex] = fileToBeUpdate;
return updatedFiles;
});
}
@ -189,7 +221,7 @@ function ClinicDetails() {
const documentStatusMap = {};
updateFiles.forEach((doc) => {
documentStatusMap[doc.documentType] = doc.status;
documentStatusMap[doc.documentType] = doc.isVerified;
});
const data = {
@ -201,9 +233,9 @@ function ClinicDetails() {
: buttonClickStatus === "On Hold"
? CLINIC_STATUS.UNDER_REVIEW.toLowerCase()
: CLINIC_STATUS.ACTIVE.toLowerCase(),
// documentStatus: {
// ...documentStatusMap,
// },
documentStatus: {
...documentStatusMap,
},
};
return data;
};
@ -229,29 +261,31 @@ function ClinicDetails() {
// ..................update file use effects................
useEffect(() => {
setIsRejectedButtonShow(
clinicFiles.abn_doc_is_verified != true &&
clinicFiles.contract_doc_is_verified != true
);
setIsOnHoldButtonShow(
clinicFiles.abn_doc_is_verified != true &&
clinicFiles.contract_doc_is_verified != true
);
// Check if any document is not verified or is null/undefined
const hasUnverifiedDocuments =
clinicFiles?.abn_doc_is_verified !== true ||
clinicFiles?.contract_doc_is_verified !== true ||
clinicFiles?.logo_is_verified !== true;
// Set button visibility based on document verification status
setIsRejectedButtonShow(hasUnverifiedDocuments);
setIsOnHoldButtonShow(hasUnverifiedDocuments);
const areAllFilesApproved =
clinicFiles.abn_doc_is_verified == true &&
clinicFiles.contract_doc_is_verified == true;
clinicFiles?.abn_doc_is_verified === true &&
clinicFiles?.contract_doc_is_verified === true &&
clinicFiles?.logo_is_verified === true;
if (
areAllFilesApproved &&
clinicData?.status === CLINIC_STATUS.UNDER_REVIEW.toLowerCase()
(clinicData?.status === CLINIC_STATUS.UNDER_REVIEW.toLowerCase() ||
clinicData?.status === CLINIC_STATUS.REJECTED.toLowerCase())
) {
setIsAcceptedButtonShow(true);
} else {
setIsAcceptedButtonShow(false);
}
}, [clinicFiles]);
}, [clinicFiles, updateFiles]);
// ..............handle table change..........
const handleTabChange = (event, newValue) => {
@ -300,19 +334,7 @@ function ClinicDetails() {
pageTitle="Clinics Details"
hideAddButton
extraComponent={
clinicData.status === CLINIC_STATUS.ACTIVE.toLowerCase() ? (
<>
<Button
className={classes.editCompanyInfoButton}
color="primary"
variant="outlined"
loading={false}
onClick={handleEditCompanyInfo}
>
Edit Clinics Info
</Button>
</>
) : (
clinicData.status !== CLINIC_STATUS.ACTIVE.toLowerCase() && (
<Box display="flex" flexDirection="row">
{/* ...rejected button.... */}
<Box>
@ -439,7 +461,7 @@ function ClinicDetails() {
contract_doc_is_verified:
clinicFiles?.contract_doc_is_verified,
logo_doc: clinicData?.logo,
logo_doc_is_verified: clinicFiles?.logo_is_verified,
logo_is_verified: clinicFiles?.logo_is_verified,
},
]
}