From 22c344cd9eddc7002dadc733d41d0e09fe75b0fd Mon Sep 17 00:00:00 2001 From: Potenz Date: Fri, 5 Sep 2025 01:50:15 +0530 Subject: [PATCH] feat(queryKey) : queryKey applied with one approach --- .../components/claims/claims-recent-table.tsx | 29 +++++++----- .../src/components/patients/patient-table.tsx | 43 +++++++---------- .../components/payments/payment-ocr-block.tsx | 21 +++++++-- .../payments/payments-recent-table.tsx | 47 +++++++++++++------ apps/Frontend/src/pages/claims-page.tsx | 9 ++-- apps/Frontend/src/pages/dashboard.tsx | 6 ++- .../src/pages/insurance-eligibility-page.tsx | 3 +- apps/Frontend/src/pages/patients-page.tsx | 5 +- 8 files changed, 99 insertions(+), 64 deletions(-) diff --git a/apps/Frontend/src/components/claims/claims-recent-table.tsx b/apps/Frontend/src/components/claims/claims-recent-table.tsx index 309d8dc..2e49bdb 100644 --- a/apps/Frontend/src/components/claims/claims-recent-table.tsx +++ b/apps/Frontend/src/components/claims/claims-recent-table.tsx @@ -51,6 +51,17 @@ interface ClaimsRecentTableProps { patientId?: number; } +// 🔑 exported base key +export const QK_CLAIMS_BASE = ["claims-recent"] as const; +// helper for specific pages/patient scope +export const qkClaimsRecent = (opts: { + patientId?: number | null; + page: number; +}) => + opts.patientId + ? ([...QK_CLAIMS_BASE, "patient", opts.patientId, opts.page] as const) + : ([...QK_CLAIMS_BASE, "global", opts.page] as const); + export default function ClaimsRecentTable({ allowEdit, allowView, @@ -89,17 +100,17 @@ export default function ClaimsRecentTable({ setCurrentPage(1); }, [patientId]); - const getClaimsQueryKey = () => - patientId - ? ["claims-recent", "patient", patientId, currentPage] - : ["claims-recent", "global", currentPage]; + const queryKey = qkClaimsRecent({ + patientId: patientId ?? undefined, + page: currentPage, + }); const { data: claimsData, isLoading, isError, } = useQuery({ - queryKey: getClaimsQueryKey(), + queryKey, queryFn: async () => { const endpoint = patientId @@ -134,9 +145,7 @@ export default function ClaimsRecentTable({ description: "Claim updated successfully!", variant: "default", }); - queryClient.invalidateQueries({ - queryKey: getClaimsQueryKey(), - }); + queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE }); }, onError: (error) => { toast({ @@ -154,9 +163,7 @@ export default function ClaimsRecentTable({ }, onSuccess: () => { setIsDeleteClaimOpen(false); - queryClient.invalidateQueries({ - queryKey: getClaimsQueryKey(), - }); + queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE }); toast({ title: "Success", description: "Claim deleted successfully!", diff --git a/apps/Frontend/src/components/patients/patient-table.tsx b/apps/Frontend/src/components/patients/patient-table.tsx index 8e56134..86dfb7a 100644 --- a/apps/Frontend/src/components/patients/patient-table.tsx +++ b/apps/Frontend/src/components/patients/patient-table.tsx @@ -56,6 +56,12 @@ interface PatientTableProps { onSearchChange?: (searchTerm: string) => void; } +// 🔑 exported base key +export const QK_PATIENTS_BASE = ["patients"] as const; +// helper (optional) – mirrors your current key structure +export const qkPatients = (page: number, search: string) => + [...QK_PATIENTS_BASE, { page, search }] as const; + export function PatientTable({ allowEdit, allowView, @@ -101,18 +107,14 @@ export function PatientTable({ } }; + const searchKeyPart = debouncedSearchCriteria?.searchTerm || "recent"; + const { data: patientsData, isLoading, isError, } = useQuery({ - queryKey: [ - "patients", - { - page: currentPage, - search: debouncedSearchCriteria?.searchTerm || "recent", - }, - ], + queryKey: qkPatients(currentPage, searchKeyPart), queryFn: async () => { const trimmedTerm = debouncedSearchCriteria?.searchTerm?.trim(); const isSearch = trimmedTerm && trimmedTerm.length > 0; @@ -176,17 +178,11 @@ export function PatientTable({ const res = await apiRequest("PUT", `/api/patients/${id}`, patient); return res.json(); }, - onSuccess: () => { + onSuccess: async () => { setIsAddPatientOpen(false); - queryClient.invalidateQueries({ - queryKey: [ - "patients", - { - page: currentPage, - search: debouncedSearchCriteria?.searchTerm || "recent", - }, - ], - }); + + // this query every page, + await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE }); toast({ title: "Success", description: "Patient updated successfully!", @@ -207,17 +203,10 @@ export function PatientTable({ const res = await apiRequest("DELETE", `/api/patients/${id}`); return; }, - onSuccess: () => { + onSuccess: async () => { setIsDeletePatientOpen(false); - queryClient.invalidateQueries({ - queryKey: [ - "patients", - { - page: currentPage, - search: debouncedSearchCriteria?.searchTerm || "recent", - }, - ], - }); + await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE }); + toast({ title: "Success", description: "Patient deleted successfully!", diff --git a/apps/Frontend/src/components/payments/payment-ocr-block.tsx b/apps/Frontend/src/components/payments/payment-ocr-block.tsx index 47b1b85..393dc3b 100644 --- a/apps/Frontend/src/components/payments/payment-ocr-block.tsx +++ b/apps/Frontend/src/components/payments/payment-ocr-block.tsx @@ -3,9 +3,9 @@ import * as React from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { Upload, Image as ImageIcon, X, Plus, Minus } from "lucide-react"; +import { Upload, Image as ImageIcon, X, Plus } from "lucide-react"; import { useMutation } from "@tanstack/react-query"; -import { apiRequest } from "@/lib/queryClient"; +import { apiRequest, queryClient } from "@/lib/queryClient"; import { toast } from "@/hooks/use-toast"; import { @@ -14,7 +14,8 @@ import { flexRender, ColumnDef, } from "@tanstack/react-table"; -import { convertOCRDate } from "@/utils/dateUtils"; +import { QK_PAYMENTS_RECENT_BASE } from "@/components/payments/payments-recent-table"; +import { QK_PATIENTS_BASE } from "@/components/patients/patient-table"; // ---------------- Types ---------------- @@ -211,6 +212,20 @@ export default function PaymentOCRBlock() { if (!res.ok) throw new Error("Failed to save OCR payments"); toast({ title: "Saved", description: "OCR rows saved successfully" }); + + // 🔄 REFRESH both tables (all pages/filters) + await Promise.all([ + queryClient.invalidateQueries({ queryKey: QK_PAYMENTS_RECENT_BASE }), // all recent payments + queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE }), // recent patients list + ]); + + // ✅ CLEAR UI: remove files and table rows + setUploadedImages([]); + setRows([]); + setColumns([]); + setError(null); + setIsDragging(false); + if (fileInputRef.current) fileInputRef.current.value = ""; } catch (err: any) { toast({ title: "Error", diff --git a/apps/Frontend/src/components/payments/payments-recent-table.tsx b/apps/Frontend/src/components/payments/payments-recent-table.tsx index 52de626..4404c7d 100644 --- a/apps/Frontend/src/components/payments/payments-recent-table.tsx +++ b/apps/Frontend/src/components/payments/payments-recent-table.tsx @@ -58,6 +58,22 @@ interface PaymentsRecentTableProps { patientId?: number; } +// 🔑 exported base key (so others can invalidate all pages/filters) +export const QK_PAYMENTS_RECENT_BASE = ["payments-recent"] as const; +// 🔑 exported helper for specific pages/scopes +export const qkPaymentsRecent = (opts: { + patientId?: number | null; + page: number; +}) => + opts.patientId + ? ([ + ...QK_PAYMENTS_RECENT_BASE, + "patient", + opts.patientId, + opts.page, + ] as const) + : ([...QK_PAYMENTS_RECENT_BASE, "global", opts.page] as const); + export default function PaymentsRecentTable({ allowEdit, allowDelete, @@ -94,17 +110,17 @@ export default function PaymentsRecentTable({ } }; - const getPaymentsQueryKey = () => - patientId - ? ["payments-recent", "patient", patientId, currentPage] - : ["payments-recent", "global", currentPage]; + const queryKey = qkPaymentsRecent({ + patientId: patientId ?? undefined, + page: currentPage, + }); const { data: paymentsData, isLoading, isError, } = useQuery({ - queryKey: getPaymentsQueryKey(), + queryKey, queryFn: async () => { const endpoint = patientId ? `/api/payments/patient/${patientId}?limit=${paymentsPerPage}&offset=${offset}` @@ -141,8 +157,9 @@ export default function PaymentsRecentTable({ description: "Payment updated successfully!", }); - queryClient.invalidateQueries({ - queryKey: getPaymentsQueryKey(), + // 🔄 refresh this table page + await queryClient.invalidateQueries({ + queryKey: QK_PAYMENTS_RECENT_BASE, }); // Fetch updated payment and set into local state @@ -193,8 +210,8 @@ export default function PaymentsRecentTable({ description: "Payment Status updated successfully!", }); - queryClient.invalidateQueries({ - queryKey: getPaymentsQueryKey(), + await queryClient.invalidateQueries({ + queryKey: QK_PAYMENTS_RECENT_BASE, }); // Fetch updated payment and set into local state @@ -233,12 +250,14 @@ export default function PaymentsRecentTable({ } return response.json(); }, - onSuccess: () => { + onSuccess: async () => { toast({ title: "Success", description: "Payment updated successfully!", }); - queryClient.invalidateQueries({ queryKey: getPaymentsQueryKey() }); + await queryClient.invalidateQueries({ + queryKey: QK_PAYMENTS_RECENT_BASE, + }); }, onError: (error: any) => { toast({ @@ -271,10 +290,10 @@ export default function PaymentsRecentTable({ return; }, - onSuccess: () => { + onSuccess: async () => { setIsDeletePaymentOpen(false); - queryClient.invalidateQueries({ - queryKey: getPaymentsQueryKey(), + await queryClient.invalidateQueries({ + queryKey: QK_PAYMENTS_RECENT_BASE, }); toast({ title: "Deleted", diff --git a/apps/Frontend/src/pages/claims-page.tsx b/apps/Frontend/src/pages/claims-page.tsx index 0315fc3..d45bfd3 100644 --- a/apps/Frontend/src/pages/claims-page.tsx +++ b/apps/Frontend/src/pages/claims-page.tsx @@ -20,7 +20,9 @@ import { } from "@/redux/slices/seleniumClaimSubmitTaskSlice"; import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; import { formatLocalDate } from "@/utils/dateUtils"; -import ClaimsRecentTable from "@/components/claims/claims-recent-table"; +import ClaimsRecentTable, { + QK_CLAIMS_BASE, +} from "@/components/claims/claims-recent-table"; import ClaimsOfPatientModal from "@/components/claims/claims-of-patient-table"; import { Claim, @@ -128,10 +130,7 @@ export default function ClaimsPage() { return res.json(); }, onSuccess: () => { - queryClient.invalidateQueries({ - queryKey: ["claims-recent"], - exact: false, - }); + queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE }); toast({ title: "Claim created successfully", diff --git a/apps/Frontend/src/pages/dashboard.tsx b/apps/Frontend/src/pages/dashboard.tsx index 1bbc56a..72ab2ae 100644 --- a/apps/Frontend/src/pages/dashboard.tsx +++ b/apps/Frontend/src/pages/dashboard.tsx @@ -29,11 +29,14 @@ import { Patient, UpdateAppointment, } from "@repo/db/types"; +import { QK_PATIENTS_BASE } from "@/components/patients/patient-table"; // Type for the ref to access modal methods type AddPatientModalRef = { shouldSchedule: boolean; + shouldClaim: boolean; navigateToSchedule: (patientId: number) => void; + navigateToClaim: (patientId: number) => void; }; export default function Dashboard() { @@ -84,7 +87,8 @@ export default function Dashboard() { }, onSuccess: (newPatient) => { setIsAddPatientOpen(false); - queryClient.invalidateQueries({ queryKey: ["patients"] }); + + queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE }); toast({ title: "Success", description: "Patient added successfully!", diff --git a/apps/Frontend/src/pages/insurance-eligibility-page.tsx b/apps/Frontend/src/pages/insurance-eligibility-page.tsx index 9445060..0f1a838 100644 --- a/apps/Frontend/src/pages/insurance-eligibility-page.tsx +++ b/apps/Frontend/src/pages/insurance-eligibility-page.tsx @@ -24,6 +24,7 @@ import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner"; import { formatLocalDate, parseLocalDate } from "@/utils/dateUtils"; import { InsertPatient, Patient } from "@repo/db/types"; import { DateInput } from "@/components/ui/dateInput"; +import { QK_PATIENTS_BASE } from "@/components/patients/patient-table"; export default function InsuranceEligibilityPage() { const { user } = useAuth(); @@ -77,7 +78,7 @@ export default function InsuranceEligibilityPage() { return res.json(); }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["patients"] }); + queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE }); toast({ title: "Success", description: "Patient added successfully!", diff --git a/apps/Frontend/src/pages/patients-page.tsx b/apps/Frontend/src/pages/patients-page.tsx index 5a59c38..6e9d852 100644 --- a/apps/Frontend/src/pages/patients-page.tsx +++ b/apps/Frontend/src/pages/patients-page.tsx @@ -1,6 +1,6 @@ import { useState, useRef } from "react"; import { useMutation } from "@tanstack/react-query"; -import { PatientTable } from "@/components/patients/patient-table"; +import { PatientTable, qkPatients } from "@/components/patients/patient-table"; import { AddPatientModal } from "@/components/patients/add-patient-modal"; import { FileUploadZone } from "@/components/file-upload/file-upload-zone"; import { Button } from "@/components/ui/button"; @@ -18,6 +18,7 @@ import { useAuth } from "@/hooks/use-auth"; import useExtractPdfData from "@/hooks/use-extractPdfData"; import { useLocation } from "wouter"; import { InsertPatient, Patient } from "@repo/db/types"; +import { QK_PATIENTS_BASE } from "@/components/patients/patient-table"; // Type for the ref to access modal methods type AddPatientModalRef = { @@ -52,7 +53,7 @@ export default function PatientsPage() { }, onSuccess: (newPatient) => { setIsAddPatientOpen(false); - queryClient.invalidateQueries({ queryKey: ["patients"] }); + queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE }); toast({ title: "Success", description: "Patient added successfully!",