You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

102 lines
3.8 KiB

"use client";
import {
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query";
import { type ReactNode, useState } from "react";
import AuthDataBoundary from "@/components/Componentes/auth-data-boundary";
import FlutterLocaleSync from "@/components/Componentes/flutter-locale-sync";
import HardwareBackBridge from "@/components/Componentes/hardware-back-bridge";
import SilentReloader from "@/components/Componentes/silent-reloader";
import { ViewPaddingsProvider } from "@/components/Componentes/view-paddings-provider";
import { setCachedMarriageEntryPath } from "@/lib/entry-route-cache";
import {
getSubmitPath,
hasCompletedMarriageProfileBasics,
} from "@/lib/get-submit-path";
import { marriageQueryKeys } from "@/hooks/marriage/query-keys";
import type { MarriageProfileResponse } from "@/hooks/marriage/types";
import { saveScopedMarriageProfile } from "@/lib/user-scoped-storage";
// AppFocusReloader was extracted to SilentReloader in silent-reloader.tsx
type ProvidersProps = {
children: ReactNode;
initialProfile?: MarriageProfileResponse;
};
export default function Providers({ children, initialProfile }: ProvidersProps) {
const [queryClient] = useState(
() => {
const qc = new QueryClient({
defaultOptions: {
queries: {
// Keep the last successful response available while a fresh
// request runs. `isLoading` is therefore only true on the first
// visit to a query; later visits render cached data immediately.
refetchOnWindowFocus: false,
refetchOnMount: false,
refetchOnReconnect: false,
retry: 1,
staleTime: 30 * 1000,
// Retain page data long enough for back-navigation to be instant.
gcTime: 10 * 60 * 1000,
// React Query replaces only the changed branches of a response,
// preventing needless UI updates when a silent refresh is equal.
structuralSharing: true,
},
},
});
// Centralized reactive profile subscriber: automatically syncs every profile state update
// to LocalStorage and Flutter native entry path bridge without requiring manual calls in mutations.
qc.getQueryCache().subscribe((event) => {
if (
(event?.type === "updated" || event?.type === "added") &&
Array.isArray(event.query.queryKey) &&
event.query.queryKey[0] === "marriage" &&
event.query.queryKey[1] === "profile" &&
event.query.state.data
) {
const profile = event.query.state.data as MarriageProfileResponse;
if (profile && typeof profile === "object") {
saveScopedMarriageProfile(profile);
if (hasCompletedMarriageProfileBasics(profile)) {
setCachedMarriageEntryPath(getSubmitPath(profile));
}
}
}
});
if (initialProfile) {
console.log("⚡ [Providers] Initializing QueryClient cache with SSR initialProfile:", {
id: initialProfile.id,
status: initialProfile.status,
gender: initialProfile.gender,
has_match_summary: Boolean(initialProfile.match_summary),
match_summary_id: initialProfile.match_summary?.id,
public_info_count: initialProfile.match_summary?.public_info?.length,
});
qc.setQueryData(marriageQueryKeys.profile(), initialProfile);
} else {
console.log("ℹ️ [Providers] No initialProfile passed from SSR");
}
return qc;
},
);
return (
<QueryClientProvider client={queryClient}>
<SilentReloader>
<AuthDataBoundary>
<ViewPaddingsProvider />
<FlutterLocaleSync />
<HardwareBackBridge />
{children}
</AuthDataBoundary>
</SilentReloader>
</QueryClientProvider>
);
}