From 4e981c644fdbc2f8165ae90fe91269452332551c Mon Sep 17 00:00:00 2001 From: ff Date: Mon, 13 Apr 2026 14:40:53 -0400 Subject: [PATCH] refactor: consolidate 3 identical Redux slices into one seleniumTaskSlice --- .../components/claims/claims-recent-table.tsx | 5 ++- .../insurance-status/ddma-buton-modal.tsx | 16 +++++++- apps/Frontend/src/pages/appointments-page.tsx | 10 +++-- apps/Frontend/src/pages/claims-page.tsx | 15 ++++++-- .../src/pages/insurance-status-page.tsx | 12 ++++-- .../slices/seleniumClaimSubmitTaskSlice.ts | 32 ---------------- .../seleniumEligibilityBatchCheckTaskSlice.ts | 32 ---------------- .../seleniumEligibilityCheckTaskSlice.ts | 32 ---------------- .../src/redux/slices/seleniumTaskSlice.ts | 38 +++++++++++++++++++ apps/Frontend/src/redux/store.ts | 8 +--- 10 files changed, 87 insertions(+), 113 deletions(-) delete mode 100755 apps/Frontend/src/redux/slices/seleniumClaimSubmitTaskSlice.ts delete mode 100755 apps/Frontend/src/redux/slices/seleniumEligibilityBatchCheckTaskSlice.ts delete mode 100755 apps/Frontend/src/redux/slices/seleniumEligibilityCheckTaskSlice.ts create mode 100644 apps/Frontend/src/redux/slices/seleniumTaskSlice.ts diff --git a/apps/Frontend/src/components/claims/claims-recent-table.tsx b/apps/Frontend/src/components/claims/claims-recent-table.tsx index 637a10d..3fb6de7 100755 --- a/apps/Frontend/src/components/claims/claims-recent-table.tsx +++ b/apps/Frontend/src/components/claims/claims-recent-table.tsx @@ -20,7 +20,7 @@ import { import { apiRequest, queryClient } from "@/lib/queryClient"; import { useToast } from "@/hooks/use-toast"; import { useAppDispatch } from "@/redux/hooks"; -import { setTaskStatus } from "@/redux/slices/seleniumClaimSubmitTaskSlice"; +import { setTaskStatus } from "@/redux/slices/seleniumTaskSlice"; import { Pagination, PaginationContent, @@ -473,6 +473,7 @@ export default function ClaimsRecentTable({ try { dispatch( setTaskStatus({ + key: "claimSubmit", status: "pending", message: "Sending Data to Selenium...", }) @@ -499,6 +500,7 @@ export default function ClaimsRecentTable({ if (data?.status === "success") { dispatch( setTaskStatus({ + key: "claimSubmit", status: "success", message: "Claims automation completed. Browser remains open.", }) @@ -509,6 +511,7 @@ export default function ClaimsRecentTable({ } catch { dispatch( setTaskStatus({ + key: "claimSubmit", status: "error", message: "Selenium submission failed", }) diff --git a/apps/Frontend/src/components/insurance-status/ddma-buton-modal.tsx b/apps/Frontend/src/components/insurance-status/ddma-buton-modal.tsx index 061f67d..9d39337 100755 --- a/apps/Frontend/src/components/insurance-status/ddma-buton-modal.tsx +++ b/apps/Frontend/src/components/insurance-status/ddma-buton-modal.tsx @@ -7,7 +7,7 @@ import { CheckCircle, LoaderCircleIcon, X } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { apiRequest, queryClient } from "@/lib/queryClient"; import { useAppDispatch } from "@/redux/hooks"; -import { setTaskStatus } from "@/redux/slices/seleniumEligibilityCheckTaskSlice"; +import { setTaskStatus } from "@/redux/slices/seleniumTaskSlice"; import { formatLocalDate } from "@/utils/dateUtils"; import { QK_PATIENTS_BASE } from "@/components/patients/patient-table"; @@ -178,6 +178,7 @@ export function DdmaEligibilityButton({ socket.on("connect_error", (err: any) => { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: "Connection failed", }) @@ -195,6 +196,7 @@ export function DdmaEligibilityButton({ socket.on("reconnect_attempt", (attempt: number) => { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: `Realtime reconnect attempt #${attempt}`, }) @@ -205,6 +207,7 @@ export function DdmaEligibilityButton({ socket.on("reconnect_failed", () => { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: "Reconnect failed", }) @@ -223,6 +226,7 @@ export function DdmaEligibilityButton({ socket.on("disconnect", (reason: any) => { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: "Connection disconnected", }) @@ -245,6 +249,7 @@ export function DdmaEligibilityButton({ setOtpModalOpen(true); dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: "OTP required for DDMA eligibility. Please enter the OTP.", }) @@ -256,6 +261,7 @@ export function DdmaEligibilityButton({ if (!payload?.session_id) return; dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: "OTP submitted. Finishing DDMA eligibility check...", }) @@ -270,6 +276,7 @@ export function DdmaEligibilityButton({ if (status === "completed") { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "success", message: "DDMA eligibility updated and PDF attached to patient documents.", @@ -298,6 +305,7 @@ export function DdmaEligibilityButton({ "DDMA eligibility session failed."; dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: msg, }) @@ -325,6 +333,7 @@ export function DdmaEligibilityButton({ dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: msg, }) @@ -396,6 +405,7 @@ export function DdmaEligibilityButton({ // 1) Ensure socket is connected (lazy) dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: "Opening realtime channel for DDMA eligibility...", }) @@ -412,6 +422,7 @@ export function DdmaEligibilityButton({ // 2) Start the selenium job via backend dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: "Starting DDMA eligibility check via selenium...", }) @@ -461,6 +472,7 @@ export function DdmaEligibilityButton({ setSessionId(result.session_id as string); dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: "DDMA eligibility job started. Waiting for OTP or final result...", @@ -470,6 +482,7 @@ export function DdmaEligibilityButton({ // fallback if backend returns immediate result dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "success", message: "DDMA eligibility completed.", }) @@ -479,6 +492,7 @@ export function DdmaEligibilityButton({ console.error("startDdmaEligibility error:", err); dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: err?.message || "Failed to start DDMA eligibility", }) diff --git a/apps/Frontend/src/pages/appointments-page.tsx b/apps/Frontend/src/pages/appointments-page.tsx index 94f57b3..b6815c9 100755 --- a/apps/Frontend/src/pages/appointments-page.tsx +++ b/apps/Frontend/src/pages/appointments-page.tsx @@ -50,7 +50,7 @@ import { useAppDispatch, useAppSelector } from "@/redux/hooks"; import { clearTaskStatus, setTaskStatus, -} from "@/redux/slices/seleniumEligibilityBatchCheckTaskSlice"; +} from "@/redux/slices/seleniumTaskSlice"; import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; import { PatientStatusBadge } from "@/components/appointments/patient-status-badge"; import { AppointmentProceduresDialog } from "@/components/appointment-procedures/appointment-procedures-dialog"; @@ -117,7 +117,7 @@ export default function AppointmentsPage() { }>({ open: false }); const dispatch = useAppDispatch(); const batchTask = useAppSelector( - (state) => state.seleniumEligibilityBatchCheckTask + (state) => state.seleniumTasks.eligibilityBatchCheck ); const [isCheckingAllElig, setIsCheckingAllElig] = useState(false); const [processedAppointmentIds, setProcessedAppointmentIds] = useState< @@ -743,6 +743,7 @@ export default function AppointmentsPage() { // Start: set redux task status (visible globally) dispatch( setTaskStatus({ + key: "eligibilityBatchCheck", status: "pending", message: `Checking eligibility for appointments on ${dateParam}...`, }) @@ -771,6 +772,7 @@ export default function AppointmentsPage() { // global error dispatch( setTaskStatus({ + key: "eligibilityBatchCheck", status: "error", message: `Batch eligibility failed: ${errMsg}`, }) @@ -849,6 +851,7 @@ export default function AppointmentsPage() { // global success status (summary) dispatch( setTaskStatus({ + key: "eligibilityBatchCheck", status: skippedCount > 0 ? "error" : "success", message: `Batch processed ${results.length} appointments — success: ${successCount}, warnings: ${warningCount}, skipped: ${skippedCount}.`, }) @@ -864,6 +867,7 @@ export default function AppointmentsPage() { console.error("[check-all-eligibilities] error", err); dispatch( setTaskStatus({ + key: "eligibilityBatchCheck", status: "error", message: `Batch eligibility error: ${err?.message ?? String(err)}`, }) @@ -912,7 +916,7 @@ export default function AppointmentsPage() { status={batchTask.status} message={batchTask.message} show={batchTask.show} - onClear={() => dispatch(clearTaskStatus())} + onClear={() => dispatch(clearTaskStatus("eligibilityBatchCheck"))} />
diff --git a/apps/Frontend/src/pages/claims-page.tsx b/apps/Frontend/src/pages/claims-page.tsx index 758c892..f9db03a 100755 --- a/apps/Frontend/src/pages/claims-page.tsx +++ b/apps/Frontend/src/pages/claims-page.tsx @@ -16,7 +16,7 @@ import { useAppDispatch, useAppSelector } from "@/redux/hooks"; import { setTaskStatus, clearTaskStatus, -} from "@/redux/slices/seleniumClaimSubmitTaskSlice"; +} from "@/redux/slices/seleniumTaskSlice"; import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; import ClaimsRecentTable, { QK_CLAIMS_BASE, @@ -47,7 +47,7 @@ export default function ClaimsPage() { const [previewFallbackFilename, setPreviewFallbackFilename] = useState(null); const dispatch = useAppDispatch(); const { status, message, show } = useAppSelector( - (state) => state.seleniumClaimSubmitTask + (state) => state.seleniumTasks.claimSubmit ); const { toast } = useToast(); const { user } = useAuth(); @@ -318,6 +318,7 @@ export default function ClaimsPage() { try { dispatch( setTaskStatus({ + key: "claimSubmit", status: "pending", message: "Submitting claim to Selenium...", }) @@ -336,6 +337,7 @@ export default function ClaimsPage() { dispatch( setTaskStatus({ + key: "claimSubmit", status: "pending", message: "Submitted to Selenium. Awaiting PDF...", }) @@ -357,6 +359,7 @@ export default function ClaimsPage() { } catch (error: any) { dispatch( setTaskStatus({ + key: "claimSubmit", status: "error", message: error.message || "Selenium submission failed", }) @@ -382,6 +385,7 @@ export default function ClaimsPage() { dispatch( setTaskStatus({ + key: "claimSubmit", status: "pending", message: "Downloading PDF from Selenium...", }) @@ -402,6 +406,7 @@ export default function ClaimsPage() { dispatch( setTaskStatus({ + key: "claimSubmit", status: "success", message: "Claim submitted & PDF downloaded successfully.", }) @@ -418,6 +423,7 @@ export default function ClaimsPage() { } catch (error: any) { dispatch( setTaskStatus({ + key: "claimSubmit", status: "error", message: error.message || "Failed to download PDF", }) @@ -456,6 +462,7 @@ export default function ClaimsPage() { try { dispatch( setTaskStatus({ + key: "claimSubmit", status: "pending", message: "Submitting claim pre auth to Selenium...", }) @@ -470,6 +477,7 @@ export default function ClaimsPage() { dispatch( setTaskStatus({ + key: "claimSubmit", status: "pending", message: "Submitted to Selenium. Awaiting PDF...", }) @@ -491,6 +499,7 @@ export default function ClaimsPage() { } catch (error: any) { dispatch( setTaskStatus({ + key: "claimSubmit", status: "error", message: error.message || "Selenium submission failed", }) @@ -508,7 +517,7 @@ export default function ClaimsPage() { status={status} message={message} show={show} - onClear={() => dispatch(clearTaskStatus())} + onClear={() => dispatch(clearTaskStatus("claimSubmit"))} />
diff --git a/apps/Frontend/src/pages/insurance-status-page.tsx b/apps/Frontend/src/pages/insurance-status-page.tsx index 9de0174..1fa411c 100755 --- a/apps/Frontend/src/pages/insurance-status-page.tsx +++ b/apps/Frontend/src/pages/insurance-status-page.tsx @@ -19,7 +19,7 @@ import { useAppDispatch, useAppSelector } from "@/redux/hooks"; import { setTaskStatus, clearTaskStatus, -} from "@/redux/slices/seleniumEligibilityCheckTaskSlice"; +} from "@/redux/slices/seleniumTaskSlice"; import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; import { formatLocalDate, parseLocalDate } from "@/utils/dateUtils"; import { InsertPatient, Patient } from "@repo/db/types"; @@ -34,7 +34,7 @@ export default function InsuranceStatusPage() { const { toast } = useToast(); const dispatch = useAppDispatch(); const { status, message, show } = useAppSelector( - (state) => state.seleniumEligibilityCheckTask, + (state) => state.seleniumTasks.eligibilityCheck, ); const [selectedPatient, setSelectedPatient] = useState(null); const [location] = useLocation(); @@ -121,6 +121,7 @@ export default function InsuranceStatusPage() { try { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: "Sending Data to Selenium...", }), @@ -136,6 +137,7 @@ export default function InsuranceStatusPage() { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "success", message: "Patient status is updated, and its eligibility pdf is uploaded at Document Page.", @@ -163,6 +165,7 @@ export default function InsuranceStatusPage() { } catch (error: any) { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: error.message || "Selenium submission failed", }), @@ -187,6 +190,7 @@ export default function InsuranceStatusPage() { try { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "pending", message: "Sending Data to Selenium...", }), @@ -201,6 +205,7 @@ export default function InsuranceStatusPage() { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "success", message: "Claim status is updated, and its pdf is uploaded at Document Page.", @@ -228,6 +233,7 @@ export default function InsuranceStatusPage() { } catch (error: any) { dispatch( setTaskStatus({ + key: "eligibilityCheck", status: "error", message: error.message || "Selenium submission failed", }), @@ -426,7 +432,7 @@ export default function InsuranceStatusPage() { status={status} message={message} show={show} - onClear={() => dispatch(clearTaskStatus())} + onClear={() => dispatch(clearTaskStatus("eligibilityCheck"))} />
diff --git a/apps/Frontend/src/redux/slices/seleniumClaimSubmitTaskSlice.ts b/apps/Frontend/src/redux/slices/seleniumClaimSubmitTaskSlice.ts deleted file mode 100755 index b76e738..0000000 --- a/apps/Frontend/src/redux/slices/seleniumClaimSubmitTaskSlice.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { createSlice, PayloadAction } from "@reduxjs/toolkit"; - -export type TaskStatus = "idle" | "pending" | "success" | "error"; - -export interface SeleniumTaskState { - status: TaskStatus; - message: string; - show: boolean; -} - -const initialState: SeleniumTaskState = { - status: "idle", - message: "", - show: false, -}; - -const seleniumClaimSubmitTaskSlice = createSlice({ - name: "seleniumClaimSubmitTask", - initialState, - reducers: { - setTaskStatus: ( - state: SeleniumTaskState, - action: PayloadAction> - ) => { - return { ...state, ...action.payload, show: true }; - }, - clearTaskStatus: () => initialState, - }, -}); - -export const { setTaskStatus, clearTaskStatus } = seleniumClaimSubmitTaskSlice.actions; -export default seleniumClaimSubmitTaskSlice.reducer; diff --git a/apps/Frontend/src/redux/slices/seleniumEligibilityBatchCheckTaskSlice.ts b/apps/Frontend/src/redux/slices/seleniumEligibilityBatchCheckTaskSlice.ts deleted file mode 100755 index 1ed8747..0000000 --- a/apps/Frontend/src/redux/slices/seleniumEligibilityBatchCheckTaskSlice.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { createSlice, PayloadAction } from "@reduxjs/toolkit"; - -export type TaskStatus = "idle" | "pending" | "success" | "error"; - -export interface SeleniumTaskState { - status: TaskStatus; - message: string; - show: boolean; -} - -const initialState: SeleniumTaskState = { - status: "idle", - message: "", - show: false, -}; - -const seleniumEligibilityBatchCheckTaskSlice = createSlice({ - name: "seleniumEligibilityBatchCheckTask", - initialState, - reducers: { - setTaskStatus: ( - state: SeleniumTaskState, - action: PayloadAction> - ) => { - return { ...state, ...action.payload, show: true }; - }, - clearTaskStatus: () => initialState, - }, -}); - -export const { setTaskStatus, clearTaskStatus } = seleniumEligibilityBatchCheckTaskSlice.actions; -export default seleniumEligibilityBatchCheckTaskSlice.reducer; diff --git a/apps/Frontend/src/redux/slices/seleniumEligibilityCheckTaskSlice.ts b/apps/Frontend/src/redux/slices/seleniumEligibilityCheckTaskSlice.ts deleted file mode 100755 index 7e77e32..0000000 --- a/apps/Frontend/src/redux/slices/seleniumEligibilityCheckTaskSlice.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { createSlice, PayloadAction } from "@reduxjs/toolkit"; - -export type TaskStatus = "idle" | "pending" | "success" | "error"; - -export interface SeleniumTaskState { - status: TaskStatus; - message: string; - show: boolean; -} - -const initialState: SeleniumTaskState = { - status: "idle", - message: "", - show: false, -}; - -const seleniumEligibilityCheckTaskSlice = createSlice({ - name: "seleniumEligibilityCheckTask", - initialState, - reducers: { - setTaskStatus: ( - state: SeleniumTaskState, - action: PayloadAction> - ) => { - return { ...state, ...action.payload, show: true }; - }, - clearTaskStatus: () => initialState, - }, -}); - -export const { setTaskStatus, clearTaskStatus } = seleniumEligibilityCheckTaskSlice.actions; -export default seleniumEligibilityCheckTaskSlice.reducer; diff --git a/apps/Frontend/src/redux/slices/seleniumTaskSlice.ts b/apps/Frontend/src/redux/slices/seleniumTaskSlice.ts new file mode 100644 index 0000000..07e401d --- /dev/null +++ b/apps/Frontend/src/redux/slices/seleniumTaskSlice.ts @@ -0,0 +1,38 @@ +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; + +export type TaskStatus = "idle" | "pending" | "success" | "error"; +export type TaskKey = "claimSubmit" | "eligibilityCheck" | "eligibilityBatchCheck"; + +export interface SeleniumTaskState { + status: TaskStatus; + message: string; + show: boolean; +} + +const emptyTask: SeleniumTaskState = { status: "idle", message: "", show: false }; + +const initialState: Record = { + claimSubmit: { ...emptyTask }, + eligibilityCheck: { ...emptyTask }, + eligibilityBatchCheck: { ...emptyTask }, +}; + +const seleniumTaskSlice = createSlice({ + name: "seleniumTasks", + initialState, + reducers: { + setTaskStatus: ( + state, + action: PayloadAction<{ key: TaskKey } & Partial> + ) => { + const { key, ...partial } = action.payload; + state[key] = { ...state[key], ...partial, show: true }; + }, + clearTaskStatus: (state, action: PayloadAction) => { + state[action.payload] = { ...emptyTask }; + }, + }, +}); + +export const { setTaskStatus, clearTaskStatus } = seleniumTaskSlice.actions; +export default seleniumTaskSlice.reducer; diff --git a/apps/Frontend/src/redux/store.ts b/apps/Frontend/src/redux/store.ts index be26cd5..83812f9 100755 --- a/apps/Frontend/src/redux/store.ts +++ b/apps/Frontend/src/redux/store.ts @@ -1,13 +1,9 @@ import { configureStore } from "@reduxjs/toolkit"; -import seleniumClaimSubmitTaskReducer from "./slices/seleniumClaimSubmitTaskSlice"; -import seleniumEligibilityCheckTaskReducer from "./slices/seleniumEligibilityCheckTaskSlice"; -import seleniumEligibilityBatchCheckTaskReducer from "./slices/seleniumEligibilityBatchCheckTaskSlice"; +import seleniumTasksReducer from "./slices/seleniumTaskSlice"; export const store = configureStore({ reducer: { - seleniumClaimSubmitTask: seleniumClaimSubmitTaskReducer, - seleniumEligibilityCheckTask: seleniumEligibilityCheckTaskReducer, - seleniumEligibilityBatchCheckTask: seleniumEligibilityBatchCheckTaskReducer, + seleniumTasks: seleniumTasksReducer, }, });