feat(queryKey) : queryKey applied with one approach
This commit is contained in:
@@ -51,6 +51,17 @@ interface ClaimsRecentTableProps {
|
|||||||
patientId?: number;
|
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({
|
export default function ClaimsRecentTable({
|
||||||
allowEdit,
|
allowEdit,
|
||||||
allowView,
|
allowView,
|
||||||
@@ -89,17 +100,17 @@ export default function ClaimsRecentTable({
|
|||||||
setCurrentPage(1);
|
setCurrentPage(1);
|
||||||
}, [patientId]);
|
}, [patientId]);
|
||||||
|
|
||||||
const getClaimsQueryKey = () =>
|
const queryKey = qkClaimsRecent({
|
||||||
patientId
|
patientId: patientId ?? undefined,
|
||||||
? ["claims-recent", "patient", patientId, currentPage]
|
page: currentPage,
|
||||||
: ["claims-recent", "global", currentPage];
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: claimsData,
|
data: claimsData,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
} = useQuery<ClaimApiResponse, Error>({
|
} = useQuery<ClaimApiResponse, Error>({
|
||||||
queryKey: getClaimsQueryKey(),
|
queryKey,
|
||||||
|
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const endpoint = patientId
|
const endpoint = patientId
|
||||||
@@ -134,9 +145,7 @@ export default function ClaimsRecentTable({
|
|||||||
description: "Claim updated successfully!",
|
description: "Claim updated successfully!",
|
||||||
variant: "default",
|
variant: "default",
|
||||||
});
|
});
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });
|
||||||
queryKey: getClaimsQueryKey(),
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
toast({
|
toast({
|
||||||
@@ -154,9 +163,7 @@ export default function ClaimsRecentTable({
|
|||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setIsDeleteClaimOpen(false);
|
setIsDeleteClaimOpen(false);
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });
|
||||||
queryKey: getClaimsQueryKey(),
|
|
||||||
});
|
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Claim deleted successfully!",
|
description: "Claim deleted successfully!",
|
||||||
|
|||||||
@@ -56,6 +56,12 @@ interface PatientTableProps {
|
|||||||
onSearchChange?: (searchTerm: string) => void;
|
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({
|
export function PatientTable({
|
||||||
allowEdit,
|
allowEdit,
|
||||||
allowView,
|
allowView,
|
||||||
@@ -101,18 +107,14 @@ export function PatientTable({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const searchKeyPart = debouncedSearchCriteria?.searchTerm || "recent";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: patientsData,
|
data: patientsData,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
} = useQuery<PatientApiResponse, Error>({
|
} = useQuery<PatientApiResponse, Error>({
|
||||||
queryKey: [
|
queryKey: qkPatients(currentPage, searchKeyPart),
|
||||||
"patients",
|
|
||||||
{
|
|
||||||
page: currentPage,
|
|
||||||
search: debouncedSearchCriteria?.searchTerm || "recent",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const trimmedTerm = debouncedSearchCriteria?.searchTerm?.trim();
|
const trimmedTerm = debouncedSearchCriteria?.searchTerm?.trim();
|
||||||
const isSearch = trimmedTerm && trimmedTerm.length > 0;
|
const isSearch = trimmedTerm && trimmedTerm.length > 0;
|
||||||
@@ -176,17 +178,11 @@ export function PatientTable({
|
|||||||
const res = await apiRequest("PUT", `/api/patients/${id}`, patient);
|
const res = await apiRequest("PUT", `/api/patients/${id}`, patient);
|
||||||
return res.json();
|
return res.json();
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: async () => {
|
||||||
setIsAddPatientOpen(false);
|
setIsAddPatientOpen(false);
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: [
|
// this query every page,
|
||||||
"patients",
|
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
{
|
|
||||||
page: currentPage,
|
|
||||||
search: debouncedSearchCriteria?.searchTerm || "recent",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Patient updated successfully!",
|
description: "Patient updated successfully!",
|
||||||
@@ -207,17 +203,10 @@ export function PatientTable({
|
|||||||
const res = await apiRequest("DELETE", `/api/patients/${id}`);
|
const res = await apiRequest("DELETE", `/api/patients/${id}`);
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: async () => {
|
||||||
setIsDeletePatientOpen(false);
|
setIsDeletePatientOpen(false);
|
||||||
queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
queryKey: [
|
|
||||||
"patients",
|
|
||||||
{
|
|
||||||
page: currentPage,
|
|
||||||
search: debouncedSearchCriteria?.searchTerm || "recent",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Patient deleted successfully!",
|
description: "Patient deleted successfully!",
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import * as React from "react";
|
|||||||
|
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
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 { useMutation } from "@tanstack/react-query";
|
||||||
import { apiRequest } from "@/lib/queryClient";
|
import { apiRequest, queryClient } from "@/lib/queryClient";
|
||||||
import { toast } from "@/hooks/use-toast";
|
import { toast } from "@/hooks/use-toast";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
flexRender,
|
flexRender,
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
} from "@tanstack/react-table";
|
} 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 ----------------
|
// ---------------- Types ----------------
|
||||||
|
|
||||||
@@ -211,6 +212,20 @@ export default function PaymentOCRBlock() {
|
|||||||
if (!res.ok) throw new Error("Failed to save OCR payments");
|
if (!res.ok) throw new Error("Failed to save OCR payments");
|
||||||
|
|
||||||
toast({ title: "Saved", description: "OCR rows saved successfully" });
|
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) {
|
} catch (err: any) {
|
||||||
toast({
|
toast({
|
||||||
title: "Error",
|
title: "Error",
|
||||||
|
|||||||
@@ -58,6 +58,22 @@ interface PaymentsRecentTableProps {
|
|||||||
patientId?: number;
|
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({
|
export default function PaymentsRecentTable({
|
||||||
allowEdit,
|
allowEdit,
|
||||||
allowDelete,
|
allowDelete,
|
||||||
@@ -94,17 +110,17 @@ export default function PaymentsRecentTable({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPaymentsQueryKey = () =>
|
const queryKey = qkPaymentsRecent({
|
||||||
patientId
|
patientId: patientId ?? undefined,
|
||||||
? ["payments-recent", "patient", patientId, currentPage]
|
page: currentPage,
|
||||||
: ["payments-recent", "global", currentPage];
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: paymentsData,
|
data: paymentsData,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
} = useQuery<PaymentApiResponse>({
|
} = useQuery<PaymentApiResponse>({
|
||||||
queryKey: getPaymentsQueryKey(),
|
queryKey,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const endpoint = patientId
|
const endpoint = patientId
|
||||||
? `/api/payments/patient/${patientId}?limit=${paymentsPerPage}&offset=${offset}`
|
? `/api/payments/patient/${patientId}?limit=${paymentsPerPage}&offset=${offset}`
|
||||||
@@ -141,8 +157,9 @@ export default function PaymentsRecentTable({
|
|||||||
description: "Payment updated successfully!",
|
description: "Payment updated successfully!",
|
||||||
});
|
});
|
||||||
|
|
||||||
queryClient.invalidateQueries({
|
// 🔄 refresh this table page
|
||||||
queryKey: getPaymentsQueryKey(),
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: QK_PAYMENTS_RECENT_BASE,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch updated payment and set into local state
|
// Fetch updated payment and set into local state
|
||||||
@@ -193,8 +210,8 @@ export default function PaymentsRecentTable({
|
|||||||
description: "Payment Status updated successfully!",
|
description: "Payment Status updated successfully!",
|
||||||
});
|
});
|
||||||
|
|
||||||
queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({
|
||||||
queryKey: getPaymentsQueryKey(),
|
queryKey: QK_PAYMENTS_RECENT_BASE,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch updated payment and set into local state
|
// Fetch updated payment and set into local state
|
||||||
@@ -233,12 +250,14 @@ export default function PaymentsRecentTable({
|
|||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: async () => {
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Payment updated successfully!",
|
description: "Payment updated successfully!",
|
||||||
});
|
});
|
||||||
queryClient.invalidateQueries({ queryKey: getPaymentsQueryKey() });
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: QK_PAYMENTS_RECENT_BASE,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onError: (error: any) => {
|
onError: (error: any) => {
|
||||||
toast({
|
toast({
|
||||||
@@ -271,10 +290,10 @@ export default function PaymentsRecentTable({
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: () => {
|
onSuccess: async () => {
|
||||||
setIsDeletePaymentOpen(false);
|
setIsDeletePaymentOpen(false);
|
||||||
queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({
|
||||||
queryKey: getPaymentsQueryKey(),
|
queryKey: QK_PAYMENTS_RECENT_BASE,
|
||||||
});
|
});
|
||||||
toast({
|
toast({
|
||||||
title: "Deleted",
|
title: "Deleted",
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ import {
|
|||||||
} from "@/redux/slices/seleniumClaimSubmitTaskSlice";
|
} from "@/redux/slices/seleniumClaimSubmitTaskSlice";
|
||||||
import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner";
|
import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner";
|
||||||
import { formatLocalDate } from "@/utils/dateUtils";
|
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 ClaimsOfPatientModal from "@/components/claims/claims-of-patient-table";
|
||||||
import {
|
import {
|
||||||
Claim,
|
Claim,
|
||||||
@@ -128,10 +130,7 @@ export default function ClaimsPage() {
|
|||||||
return res.json();
|
return res.json();
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({ queryKey: QK_CLAIMS_BASE });
|
||||||
queryKey: ["claims-recent"],
|
|
||||||
exact: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Claim created successfully",
|
title: "Claim created successfully",
|
||||||
|
|||||||
@@ -29,11 +29,14 @@ import {
|
|||||||
Patient,
|
Patient,
|
||||||
UpdateAppointment,
|
UpdateAppointment,
|
||||||
} from "@repo/db/types";
|
} from "@repo/db/types";
|
||||||
|
import { QK_PATIENTS_BASE } from "@/components/patients/patient-table";
|
||||||
|
|
||||||
// Type for the ref to access modal methods
|
// Type for the ref to access modal methods
|
||||||
type AddPatientModalRef = {
|
type AddPatientModalRef = {
|
||||||
shouldSchedule: boolean;
|
shouldSchedule: boolean;
|
||||||
|
shouldClaim: boolean;
|
||||||
navigateToSchedule: (patientId: number) => void;
|
navigateToSchedule: (patientId: number) => void;
|
||||||
|
navigateToClaim: (patientId: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
@@ -84,7 +87,8 @@ export default function Dashboard() {
|
|||||||
},
|
},
|
||||||
onSuccess: (newPatient) => {
|
onSuccess: (newPatient) => {
|
||||||
setIsAddPatientOpen(false);
|
setIsAddPatientOpen(false);
|
||||||
queryClient.invalidateQueries({ queryKey: ["patients"] });
|
|
||||||
|
queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Patient added successfully!",
|
description: "Patient added successfully!",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { SeleniumTaskBanner } from "@/components/ui/selenium-task-banner";
|
|||||||
import { formatLocalDate, parseLocalDate } from "@/utils/dateUtils";
|
import { formatLocalDate, parseLocalDate } from "@/utils/dateUtils";
|
||||||
import { InsertPatient, Patient } from "@repo/db/types";
|
import { InsertPatient, Patient } from "@repo/db/types";
|
||||||
import { DateInput } from "@/components/ui/dateInput";
|
import { DateInput } from "@/components/ui/dateInput";
|
||||||
|
import { QK_PATIENTS_BASE } from "@/components/patients/patient-table";
|
||||||
|
|
||||||
export default function InsuranceEligibilityPage() {
|
export default function InsuranceEligibilityPage() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
@@ -77,7 +78,7 @@ export default function InsuranceEligibilityPage() {
|
|||||||
return res.json();
|
return res.json();
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["patients"] });
|
queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Patient added successfully!",
|
description: "Patient added successfully!",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useRef } from "react";
|
import { useState, useRef } from "react";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
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 { AddPatientModal } from "@/components/patients/add-patient-modal";
|
||||||
import { FileUploadZone } from "@/components/file-upload/file-upload-zone";
|
import { FileUploadZone } from "@/components/file-upload/file-upload-zone";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -18,6 +18,7 @@ import { useAuth } from "@/hooks/use-auth";
|
|||||||
import useExtractPdfData from "@/hooks/use-extractPdfData";
|
import useExtractPdfData from "@/hooks/use-extractPdfData";
|
||||||
import { useLocation } from "wouter";
|
import { useLocation } from "wouter";
|
||||||
import { InsertPatient, Patient } from "@repo/db/types";
|
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 for the ref to access modal methods
|
||||||
type AddPatientModalRef = {
|
type AddPatientModalRef = {
|
||||||
@@ -52,7 +53,7 @@ export default function PatientsPage() {
|
|||||||
},
|
},
|
||||||
onSuccess: (newPatient) => {
|
onSuccess: (newPatient) => {
|
||||||
setIsAddPatientOpen(false);
|
setIsAddPatientOpen(false);
|
||||||
queryClient.invalidateQueries({ queryKey: ["patients"] });
|
queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Patient added successfully!",
|
description: "Patient added successfully!",
|
||||||
|
|||||||
Reference in New Issue
Block a user