diff --git a/src/components/CustomFileUpload.jsx b/src/components/CustomFileUpload.jsx
index 7e2c3ab..4fa1f9c 100644
--- a/src/components/CustomFileUpload.jsx
+++ b/src/components/CustomFileUpload.jsx
@@ -116,10 +116,7 @@ const CustomFileUpload = forwardRef(function CustomFileUpload(
try {
setIsLoading(true);
const response = await getPresignedUrl(filePayload);
-
- // Debug the response structure
- console.log('API Response:', response);
-
+
// Check if we have a valid response with the expected structure
if (response?.data?.data?.Key) {
// Use the Key from the response
@@ -128,7 +125,6 @@ const CustomFileUpload = forwardRef(function CustomFileUpload(
} else {
// If the expected structure is not found, try to find the key in a different location
// or use a fallback value
- console.log('Response structure is different than expected');
// Try different possible paths to find the key
const key = response?.data?.Key ||
@@ -136,7 +132,6 @@ const CustomFileUpload = forwardRef(function CustomFileUpload(
response?.Key ||
value.name; // Fallback to the file name if key not found
- console.log('Using key:', key);
onUploadDone(documentName, key);
// Try to find the API URL similarly
diff --git a/src/config/api.js b/src/config/api.js
index 2ac1711..84415af 100644
--- a/src/config/api.js
+++ b/src/config/api.js
@@ -1,9 +1,9 @@
-import axios from 'axios';
-import { API_BASE_URL } from '../common/envVariables';
-import { ERRORS, NOTIFICATION } from '../constants';
-import { pushNotification } from '../utils/notification';
-import { commonLogoutFunc } from '../utils/share';
-import store from '../redux/store';
+import axios from "axios";
+import { API_BASE_URL } from "../common/envVariables";
+import { ERRORS, NOTIFICATION } from "../constants";
+import { pushNotification } from "../utils/notification";
+import { commonLogoutFunc } from "../utils/share";
+import store from "../redux/store";
export const axiosInstance = axios.create({
baseURL: API_BASE_URL,
@@ -20,10 +20,15 @@ export const axiosInstance = axios.create({
axiosInstance.interceptors.request.use(
async function (config) {
try {
- const token = JSON.parse(localStorage.getItem('redux'));
+ const token = JSON.parse(localStorage.getItem("redux"));
if (token?.login?.token) {
config.headers.Authorization = `Bearer ${token?.login?.token}`;
}
+ // if url is dev-ai-appointment.s3.amazonaws.com
+ if (config.url?.includes("dev-ai-appointment.s3.amazonaws.com")) {
+ config.headers.Authorization = null;
+ }
+
const state = store.getState();
const companyId = state?.loginAsCompanyAdmin?.companyId; // Extract companyId
if (companyId) {
@@ -58,7 +63,7 @@ axiosInstance.interceptors.response.use(
console.log(error);
if (!error?.response?.data) {
pushNotification(error.message, NOTIFICATION.ERROR);
- if (error.message !== 'Network Error') commonLogoutFunc();
+ if (error.message !== "Network Error") commonLogoutFunc();
} else if (
error?.response?.data?.error &&
error?.response?.data?.error[0]?.message
@@ -91,10 +96,10 @@ axiosInstance.interceptors.response.use(
export const fileDownloadAxios = axios.create({
baseURL: API_BASE_URL,
- responseType: 'blob',
+ responseType: "blob",
crossDomain: true,
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
withCredentials: true,
timeout: 300000,
@@ -103,10 +108,16 @@ export const fileDownloadAxios = axios.create({
fileDownloadAxios.interceptors.request.use(
async function (config) {
try {
- const token = JSON.parse(localStorage.getItem('redux'));
+ const token = JSON.parse(localStorage.getItem("redux"));
if (token?.data?.data) {
config.headers.Authorization = `${token?.data?.data}`;
}
+
+ // if url is dev-ai-appointment.s3.amazonaws.com
+ if (config.url?.includes("dev-ai-appointment.s3.amazonaws.com")) {
+ config.headers.Authorization = null;
+ }
+
const state = store.getState();
const companyId = state?.loginAsCompanyAdmin?.companyId; // Extract companyId
if (companyId) {
@@ -131,7 +142,7 @@ fileDownloadAxios.interceptors.response.use(
async function (response) {
// Handle error response (when server responds with JSON instead of a file)
if (
- response?.headers['content-type']?.includes('application/json') &&
+ response?.headers["content-type"]?.includes("application/json") &&
response?.data
) {
try {
@@ -140,14 +151,14 @@ fileDownloadAxios.interceptors.response.use(
if (parsedError?.error) {
pushNotification(
- parsedError?.message || 'Download failed',
+ parsedError?.message || "Download failed",
NOTIFICATION.ERROR
);
return Promise.reject(parsedError);
}
} catch (err) {
// eslint-disable-next-line no-console
- console.error('Error parsing error response', err);
+ console.error("Error parsing error response", err);
}
}
@@ -159,26 +170,26 @@ fileDownloadAxios.interceptors.response.use(
if (!error?.response?.data) {
pushNotification(error.message, NOTIFICATION.ERROR);
- if (error.message !== 'Network Error') commonLogoutFunc();
+ if (error.message !== "Network Error") commonLogoutFunc();
} else {
// Handle error message from API
- const contentType = error?.response?.headers?.['content-type'];
+ const contentType = error?.response?.headers?.["content-type"];
- if (contentType?.includes('application/json')) {
+ if (contentType?.includes("application/json")) {
error.response.data.text().then((text) => {
try {
const parsedError = JSON.parse(text);
pushNotification(
- parsedError.message || 'Something went wrong',
+ parsedError.message || "Something went wrong",
NOTIFICATION.ERROR
);
} catch (err) {
- pushNotification('Unknown error occurred', NOTIFICATION.ERROR);
+ pushNotification("Unknown error occurred", NOTIFICATION.ERROR);
}
});
} else {
pushNotification(
- error?.response?.data?.message || 'Download failed',
+ error?.response?.data?.message || "Download failed",
NOTIFICATION.ERROR
);
}
diff --git a/src/layouts/mainLayout/components/Sidebar.jsx b/src/layouts/mainLayout/components/Sidebar.jsx
index dc9fd49..168c0fa 100644
--- a/src/layouts/mainLayout/components/Sidebar.jsx
+++ b/src/layouts/mainLayout/components/Sidebar.jsx
@@ -21,9 +21,12 @@ import { CLINIC_STATUS, HIDE_MODULES } from "../../../constants";
import { isBSPortal } from "../../../utils/share";
import { hideAndShowFunctionality } from "../../../views/Signup/signupAction";
import { useStyles } from "../mainLayoutStyles";
-
// Import the configuration from the separate file
import { SIDEBAR_CONFIG } from "./sideBarConfig"; // Adjust path if necessary
+import {
+ selectClinicStatus,
+ selectUserRole,
+} from "../../../redux/userRoleSlice";
// NOTE: Removed the internal SIDEBAR_ITEMS definition.
// We will now use the imported SIDEBAR_CONFIG.
@@ -41,6 +44,7 @@ const Sidebar = ({ onClose, showCloseIcon }) => {
const [childRoute, setchildRoute] = useState("");
const [combinedRoute, setcombinedRoute] = useState("");
const dispatch = useDispatch();
+ const clinicStatus = useSelector(selectClinicStatus);
// Assuming companyStatus is fetched or defined elsewhere correctly
const companyStatus = "APPROVED"; // Example status, replace with actual logic if needed
@@ -83,88 +87,85 @@ const Sidebar = ({ onClose, showCloseIcon }) => {
const userRole = useSelector((state) => state.userRole.role);
// Function to determine visibility and render a single sidebar item link
- const checkVisibility = (item, i) => {
- // Check if the user has the necessary role for this item
- const hasRole = !item.roles || item.roles.includes(userRole);
+ // The checkVisibility function with fixed logic
+const checkVisibility = (item, i) => {
+ // Check if the user has the necessary role for this item
+ const hasRole = !item.roles || item.roles.includes(userRole);
- // Determine if the feature related to this item should be hidden
- let hideFeature =
- (companyStatus === CLINIC_STATUS.APPROVED &&
- HIDE_FUNCTIONALITY &&
- HIDE_MODULES.includes(item?.path)) ||
- (isSuperAdmin && HIDE_FUNCTIONALITY && HIDE_MODULES.includes(item?.path));
+ // Only render if user has the required role
+ if (hasRole) {
+ // Determine if the link should be disabled
+ // FIXED LOGIC: If clinic status is rejected, only allow "/" and "/docs" paths
+ const isDisabled = (clinicStatus === "rejected" || clinicStatus === "under_review" || clinicStatus === "payment_due") && !(item.path == "" || item.path == "docs");
+
+ // Set the correct target path
+ const targetPath = isDisabled ? "#" : `/${item.path}`;
+ const isActive = activeLink === item.path; // Check if this link is the active one
- // Only render if user has the required role
- if (hasRole) {
- // Determine if the link should be disabled
- const isDisabled =
- (!isSuperAdmin && companyStatus !== CLINIC_STATUS.APPROVED) || hideFeature;
- const targetPath = isDisabled ? "#" : `/${item.path}`;
- const isActive = activeLink === item.path; // Check if this link is the active one
-
- return (
- handleHideFeatures(hideFeature)} // This seems odd, clicking the box hides features? Review this logic.
- key={item.path || i} // Use a stable key like item.path
+ return (
+ handleHideFeatures(isDisabled)} // Pass isDisabled to handleHideFeatures
+ key={item.path || i} // Use a stable key like item.path
+ >
+ {
+ if (isDisabled) e.preventDefault();
+ handleLinkClick(item.path); // Set active link on click
+ }}
>
- {
- if (isDisabled) e.preventDefault();
- handleLinkClick(item.path); // Set active link on click
- }}
+
-
-
- {isActive
- ? React.createElement(item.activeIcon, {
- className: classes.sidebarLinkIcons,
- })
- : React.createElement(item.icon, {
- className: classes.sidebarLinkIcons,
- style: { color: "black" },
- })}
-
-
-
-
-
- );
- }
- return null; // Return null if item shouldn't be rendered
- };
+
+ {isActive
+ ? React.createElement(item.activeIcon, {
+ className: classes.sidebarLinkIcons,
+ })
+ : React.createElement(item.icon, {
+ className: classes.sidebarLinkIcons,
+ style: { color: "black" },
+ })}
+
+
+
+
+
+ );
+ }
+ return null; // Return null if item shouldn't be rendered
+};
// Function to render a sidebar item that has children (accordion)
const rendersideMenu = (item, i) => {
// Check if the parent item has the necessary role
const hasParentRole = !item.roles || item.roles.includes(userRole);
-
+
// Only proceed if the parent item has the necessary role
if (!hasParentRole) return null;
-
+
// Filter visible children first
const visibleChildren = item.children
?.filter((childItem) => {
// Check if child has the necessary role
- const hasChildRole = !childItem.roles || childItem.roles.includes(userRole);
+ const hasChildRole =
+ !childItem.roles || childItem.roles.includes(userRole);
return hasChildRole;
})
.filter(Boolean); // Filter out any null/undefined results
diff --git a/src/layouts/mainLayout/components/sideBarConfig.js b/src/layouts/mainLayout/components/sideBarConfig.js
index 4284e25..1592774 100644
--- a/src/layouts/mainLayout/components/sideBarConfig.js
+++ b/src/layouts/mainLayout/components/sideBarConfig.js
@@ -82,4 +82,13 @@ export const SIDEBAR_CONFIG = [
// Clinic admin can access call transcripts
roles: [USER_ROLES.CLINIC_ADMIN]
},
+ {
+ text: 'Clinic Documents',
+ path: 'docs',
+ requireSaprateApp: false,
+ icon: ArticleOutlinedIcon,
+ activeIcon: ArticleIcon,
+ // Clinic admin can access call transcripts
+ roles: [USER_ROLES.CLINIC_ADMIN]
+ },
];
diff --git a/src/redux/userRoleSlice.js b/src/redux/userRoleSlice.js
index 6898a07..415487d 100644
--- a/src/redux/userRoleSlice.js
+++ b/src/redux/userRoleSlice.js
@@ -1,19 +1,22 @@
// Initial state
const initialState = {
role: null,
+ clinicStatus: null,
};
// Action types
const SET_USER_ROLE = 'userRole/SET_USER_ROLE';
// Action creators
-export const setUserRole = (role) => ({
+export const setUserRole = (role, clinicStatus) => ({
type: SET_USER_ROLE,
payload: role,
+ clinicStatus: clinicStatus,
});
// Selector to get user role
export const selectUserRole = (state) => state.userRole.role;
+export const selectClinicStatus = (state) => state.userRole.clinicStatus;
// Reducer
export default function userRoleReducer(state = initialState, action) {
@@ -22,6 +25,7 @@ export default function userRoleReducer(state = initialState, action) {
return {
...state,
role: action.payload,
+ clinicStatus: action.clinicStatus,
};
default:
return state;
diff --git a/src/routes/index.js b/src/routes/index.js
index 5d15106..6d7efa8 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -4,7 +4,7 @@ import ClinicsList from "../views/ClinicsList";
import Dashboard from "../views/Dashboard";
import StaffManagement from "../views/StaffManagement";
import ClinicDetails from "../views/ClinicDetails";
-import Login from '../views/Login';
+import Login from "../views/Login";
import YourDetailsForm from "../views/Signup/YourDetailsForm";
import MockPayment from "../views/MockPayment";
import Users from "../views/User";
@@ -13,6 +13,7 @@ import ClinicTranscripts from "../views/ClinicTranscripts";
import ContractManagement from "../views/ContractManagement";
import MasterDataManagement from "../views/MasterData";
import PaymentManagement from "../views/PaymentManagement";
+import ClinicDocUpdater from "../views/ClinicDocUpdate";
export const routesData = [
{
@@ -28,6 +29,7 @@ export const routesData = [
{ path: "/transcripts", component: ClinicTranscripts },
{ path: "/masterData", component: MasterDataManagement },
{ path: "/payment-management", component: PaymentManagement },
+ { path: "/docs", component: ClinicDocUpdater },
],
isProtected: true,
},
@@ -38,7 +40,7 @@ export const routesData = [
{ path: "/auth/login", component: Login },
{ path: "/auth/signup/payment", component: MockPayment },
{
- path: 'signup/your-details',
+ path: "signup/your-details",
component: YourDetailsForm,
},
],
diff --git a/src/views/ClinicDocUpdate/index.jsx b/src/views/ClinicDocUpdate/index.jsx
new file mode 100644
index 0000000..8305706
--- /dev/null
+++ b/src/views/ClinicDocUpdate/index.jsx
@@ -0,0 +1,197 @@
+import { Button, Grid, Paper, Typography } from "@mui/material";
+import { Box } from "@mui/system";
+import React, { useEffect, useState } from "react";
+import CustomFileUpload from "../../components/CustomFileUpload";
+import { useFormik } from "formik";
+import * as Yup from "yup";
+import { MAX_FILE_SIZE_IN_MB, MAX_FILES } from "../../constants";
+import { updateClinicDocs } from "../../services/clinics.service";
+import { useNavigate } from "react-router-dom";
+
+const ClinicDocUpdater = () => {
+ const navigate = useNavigate();
+ // Use state instead of ref for initial form data
+ const [initialFormData, setInitialFormData] = useState({
+ companyABNImage: "",
+ contract: "",
+ logo: "",
+ clinicId: "",
+ });
+
+ // Track if data is loaded
+ const [isDataLoaded, setIsDataLoaded] = useState(false);
+
+ useEffect(() => {
+ // Load user data from localStorage
+ try {
+ const user = JSON.parse(localStorage.getItem("user"));
+
+ if (user && user.created_clinics ) {
+ setInitialFormData({
+ companyABNImage: user.created_clinics.abn_doc || "",
+ contract: user.created_clinics.contract_doc || "",
+ logo: user.created_clinics.logo || "",
+ clinicId: user.created_clinics.id || "",
+ });
+ }
+ } catch (error) {
+ console.error("Error loading user data:", error);
+ } finally {
+ setIsDataLoaded(true);
+ }
+ }, []);
+
+ const validationSchema = Yup.object().shape({
+ companyABNImage: Yup.string().required("Clinic ABN document is required"),
+ contract: Yup.string().required("Contract is required"),
+ logo: Yup.string().required("Logo is required"),
+ });
+
+ const handleFormSubmit = async () => {
+ console.log("Form values:", formik.values);
+ const payload = {
+ abn_doc: formik.values.companyABNImage,
+ contract_doc: formik.values.contract,
+ logo: formik.values.logo,
+ }
+
+ const resp = await updateClinicDocs(formik.values.clinicId, payload);
+ console.log(resp);
+
+ // clear localStorage
+ localStorage.removeItem("user");
+ // redirect to login
+ navigate("/");
+ };
+
+ const handleSubmit = async () => {
+ formik.handleSubmit();
+ };
+
+ // Initialize formik only after data is loaded
+ const formik = useFormik({
+ initialValues: initialFormData,
+ validationSchema,
+ onSubmit: handleFormSubmit,
+ enableReinitialize: true, // This is key - it will update form values when initialValues change
+ });
+
+ // Set uploaded file URL
+ const setUploadedFileUrl = (documentName, fileUrl) => {
+ console.log("Document Name:", documentName);
+ console.log("File URL:", fileUrl);
+ console.log("File URL Type:", typeof fileUrl);
+
+ if (documentName && fileUrl !== undefined) {
+ formik.setFieldValue(documentName, fileUrl);
+ console.log("After setting value:", formik.values[documentName]);
+ } else {
+ console.error("Invalid parameters for setUploadedFileUrl:", {
+ documentName,
+ fileUrl,
+ });
+ }
+ };
+
+ return (
+
+
+
+
+
+ Clinic Docs
+
+
+ {isDataLoaded ? (
+
+ ) : (
+
+ Loading clinic documents...
+
+ )}
+
+
+
+ );
+};
+
+export default ClinicDocUpdater;
diff --git a/src/views/Dashboard/helper.js b/src/views/Dashboard/helper.js
new file mode 100644
index 0000000..d3baddd
--- /dev/null
+++ b/src/views/Dashboard/helper.js
@@ -0,0 +1,30 @@
+export const convertToSignupForm = (data) => {
+ return {
+ name: data.name,
+ email: data.email,
+ password: data.password,
+ mobileNumber: data.mobileNumber,
+ mobilePrefix: data.mobilePrefix,
+ companyName: data.companyName,
+ designation: data.designation,
+ businessPhonePrefix: data.businessPhonePrefix,
+ businessPhone: data.businessPhone,
+ emergencyBusinessPhone: data.emergencyBusinessPhone,
+ emergencyBusinessPhonePrefix: data.emergencyBusinessPhonePrefix,
+ businessFax: data.businessFax,
+ clinicLogo: data.clinicLogo,
+ businessEmail: data.businessEmail,
+ pincode: data.pincode,
+ state: data.state,
+ locality: data.locality,
+ country: data.country,
+ fullAddress: data.fullAddress,
+ companyABNImageNumber: data.companyABNImageNumber,
+ companyABNImage: data.companyABNImage,
+ termsAccepted: data.termsAccepted,
+ practiceManagementSystem: data.practiceManagementSystem,
+ practiceId: data.practiceId,
+ practiceName: data.practiceName,
+ contract: data.contract,
+ };
+};
diff --git a/src/views/Dashboard/index.jsx b/src/views/Dashboard/index.jsx
index 4000f18..ea737e4 100644
--- a/src/views/Dashboard/index.jsx
+++ b/src/views/Dashboard/index.jsx
@@ -7,7 +7,12 @@ import SuperAdmin from "./components/SuperAdmin";
import { selectUserRole, setUserRole } from "../../redux/userRoleSlice";
import Totals from "./Tiles/Totals";
import { useStyles } from "./dashboardStyles";
-import { USER_ROLES } from "../../constants";
+import { NOTIFICATION, USER_ROLES } from "../../constants";
+import { getClinicsById } from "../../services/clinics.service";
+import { pushNotification } from "../../utils/notification";
+import { useNavigate } from "react-router-dom";
+import { updateFormDetails } from "../Signup/signupAction";
+import { convertToSignupForm } from "./helper";
function Dashboard() {
const classes = useStyles();
@@ -31,7 +36,51 @@ function Dashboard() {
const userRole = useSelector(selectUserRole);
const user = useSelector((state) => state.login.user);
+ const navigation = useNavigate();
+
+ const getClinic = async () => {
+ setIsLoading(true);
+ const resp = await getClinicsById(user.created_clinics[0].id);
+
+
+ // if(resp?.data?.data?.error){
+ // setIsActive(false);
+ // pushNotification("Error while fetching clinic data", NOTIFICATION.ERROR);
+ // navigation("/auth/signup/your-details?status=error");
+ // }
+
+ const status = resp?.data?.data?.clinic?.status;
+
+ if(status == "rejected"){
+ setIsActive(false);
+
+ // update user state with latest clinic
+ localStorage.setItem("user", JSON.stringify({
+ ...user,
+ created_clinics: resp?.data?.data?.clinic
+ }))
+
+ dispatch(setUserRole(USER_ROLES.CLINIC_ADMIN, "rejected"));
+
+ pushNotification(resp?.data?.data?.fileStatus?.reason || "Your clinic registration has been rejected", NOTIFICATION.WARNING);
+ navigation("/docs");
+ }
+
+ // if(status=="payment_due"){
+ // setIsActive(false);
+ // pushNotification("Payment due", NOTIFICATION.WARNING);
+ // }
+
+ // if(status=="requested_doc"){
+ // setIsActive(false);
+ // pushNotification("Documents requested", NOTIFICATION.WARNING);
+ // }
+
+ setIsLoading(false);
+ };
+
useEffect(() => {
+ getClinic();
// Determine user role based on user data from login reducer
if (user) {
// Check if user is a super admin
@@ -44,9 +93,9 @@ function Dashboard() {
setIsActive(clinicStatus == "active");
if (isSuperAdmin) {
- dispatch(setUserRole(USER_ROLES.SUPER_ADMIN));
+ dispatch(setUserRole(USER_ROLES.SUPER_ADMIN, clinicStatus));
} else {
- dispatch(setUserRole(USER_ROLES.CLINIC_ADMIN));
+ dispatch(setUserRole(USER_ROLES.CLINIC_ADMIN, clinicStatus));
}
}
setIsLoading(false);
diff --git a/src/views/Signup/YourDetailsForm.jsx b/src/views/Signup/YourDetailsForm.jsx
index 7093827..f24ec19 100644
--- a/src/views/Signup/YourDetailsForm.jsx
+++ b/src/views/Signup/YourDetailsForm.jsx
@@ -94,6 +94,11 @@ function YourDetailsForm() {
const selectedLocalityRef = useRef();
const [testConnection, setTestConnDone] = useState(false);
+
+ const errorStatus = new URLSearchParams(window.location.search).get("status");
+
+ console.log(errorStatus)
+
useEffect(() => {
setIsLoading(true);
getLatestClinicId().then((res) => {
@@ -209,6 +214,7 @@ function YourDetailsForm() {
if (yourDetailsFormData) {
defaultFormData.current = { ...yourDetailsFormData };
+ console.log(yourDetailsFormData)
// setLocalityOption([yourDetailsFormData?.locality])
selectedLocalityRef.current = yourDetailsFormData?.locality;
}