diff --git a/src/app/[lang]/page.tsx b/src/app/[lang]/page.tsx index 419e558..6531f24 100644 --- a/src/app/[lang]/page.tsx +++ b/src/app/[lang]/page.tsx @@ -7,11 +7,6 @@ import { isAuthenticatedToken, MARRIAGE_ENTRY_PATH_COOKIE, } from "@/lib/entry-route-cache"; -import { - getSubmitPath, - hasCompletedMarriageProfileBasics, -} from "@/lib/get-submit-path"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; import { localizePath } from "@/translations/config"; export const dynamic = "force-dynamic"; @@ -27,7 +22,7 @@ export default async function LocaleEntryPage({ cookieStore.get("habib_token")?.value; const hasToken = isAuthenticatedToken(token); - // 1. If not authenticated, render instantly in SSR + // 1. If not authenticated, render instantly if (!hasToken) { return ; } @@ -45,26 +40,6 @@ export default async function LocaleEntryPage({ redirect(localizePath(cachedEntryPath, lang)); } - // 3. Deep SSR Profile Resolution: resolve profile & redirect directly on server - const profile = await fetchProfileSSR(token); - if (profile) { - const isBasicsCompleted = hasCompletedMarriageProfileBasics(profile); - if (!isBasicsCompleted) { - return ; - } - - const targetPath = getSubmitPath(profile); - if (targetPath === "/intro") { - return ; - } - - redirect(localizePath(targetPath, lang)); - } - - // 4. Graceful Fallback if server fetch was unreachable - return ( - <> - - - ); + // 3. Instant non-blocking client-side resolver fallback + return ; } diff --git a/src/app/candidate-contact/candidate-contact-client.tsx b/src/app/candidate-contact/candidate-contact-client.tsx index 6361447..500d786 100644 --- a/src/app/candidate-contact/candidate-contact-client.tsx +++ b/src/app/candidate-contact/candidate-contact-client.tsx @@ -60,8 +60,8 @@ export default function CandidateContactClient() { } }, [profile, router, locale]); - // Signal Flutter to lift its loading cover once the profile is available. - useHabibWebReady(!!profile && !isProfileLoading); + // Signal Flutter to lift its loading cover immediately with 0ms latency. + useHabibWebReady(true); const isRedirecting = useMemo(() => { if (!profile) return false; diff --git a/src/app/candidate-contact/page.tsx b/src/app/candidate-contact/page.tsx index 0260429..e64fbd4 100644 --- a/src/app/candidate-contact/page.tsx +++ b/src/app/candidate-contact/page.tsx @@ -1,39 +1,5 @@ -import { cookies } from "next/headers"; -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; -import { isAuthenticatedToken } from "@/lib/entry-route-cache"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; -import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; import CandidateContactClient from "./candidate-contact-client"; -export const dynamic = "force-dynamic"; - -export default async function CandidateContactPage() { - const cookieStore = await cookies(); - - const token = - cookieStore.get("HABIB_TOKEN")?.value ?? - cookieStore.get("habib_token")?.value; - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { staleTime: 10 * 1000 }, - }, - }); - - if (isAuthenticatedToken(token)) { - await queryClient.prefetchQuery({ - queryKey: marriageQueryKeys.profile(), - queryFn: () => fetchProfileSSR(token!), - }); - } - - return ( - - - - ); +export default function CandidateContactPage() { + return ; } diff --git a/src/app/finding-match/page.tsx b/src/app/finding-match/page.tsx index 2e2f3dd..bdc695a 100644 --- a/src/app/finding-match/page.tsx +++ b/src/app/finding-match/page.tsx @@ -1,39 +1,5 @@ -import { cookies } from "next/headers"; -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; -import { isAuthenticatedToken } from "@/lib/entry-route-cache"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; -import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; import FindingMatchClient from "./finding-match-client"; -export const dynamic = "force-dynamic"; - -export default async function FindingMatchPage() { - const cookieStore = await cookies(); - - const token = - cookieStore.get("HABIB_TOKEN")?.value ?? - cookieStore.get("habib_token")?.value; - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { staleTime: 10 * 1000 }, - }, - }); - - if (isAuthenticatedToken(token)) { - await queryClient.prefetchQuery({ - queryKey: marriageQueryKeys.profile(), - queryFn: () => fetchProfileSSR(token!), - }); - } - - return ( - - - - ); +export default function FindingMatchPage() { + return ; } diff --git a/src/app/intro/page.tsx b/src/app/intro/page.tsx index 89223f9..a953d9f 100644 --- a/src/app/intro/page.tsx +++ b/src/app/intro/page.tsx @@ -1,42 +1,5 @@ -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; -import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; -import { fetchConfigSSR } from "@/lib/ssr-fetch"; import IntroClient from "./intro-client"; -export const dynamic = "force-dynamic"; - -/** - * Server Component wrapper for the Intro page. - * - * Follows the same SSR-prefetch pattern as questions-list/page.tsx: - * create a server QueryClient, prefetch critical data, dehydrate, and - * wrap the client component in HydrationBoundary so TanStack Query - * hydrates the cache instantly — no client-side waterfall. - * - * Config is the only data Intro needs. Even if the fetch fails, IntroClient - * has a local fallback image so the UI is never broken. - */ -export default async function IntroPage() { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { staleTime: 30 * 1000 }, - }, - }); - - // Prefetch marriage config — Intro uses it for the video thumbnail. - // Failure is non-blocking because IntroClient has a fallbackSrc. - await queryClient.prefetchQuery({ - queryKey: marriageQueryKeys.config(), - queryFn: () => fetchConfigSSR(), - }); - - return ( - - - - ); +export default function IntroPage() { + return ; } diff --git a/src/app/new-match/page.tsx b/src/app/new-match/page.tsx index f51ac53..953d260 100644 --- a/src/app/new-match/page.tsx +++ b/src/app/new-match/page.tsx @@ -1,39 +1,5 @@ -import { cookies } from "next/headers"; -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; -import { isAuthenticatedToken } from "@/lib/entry-route-cache"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; -import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; import NewMatchClient from "./new-match-client"; -export const dynamic = "force-dynamic"; - -export default async function NewMatchPage() { - const cookieStore = await cookies(); - - const token = - cookieStore.get("HABIB_TOKEN")?.value ?? - cookieStore.get("habib_token")?.value; - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { staleTime: 10 * 1000 }, - }, - }); - - if (isAuthenticatedToken(token)) { - await queryClient.prefetchQuery({ - queryKey: marriageQueryKeys.profile(), - queryFn: () => fetchProfileSSR(token!), - }); - } - - return ( - - - - ); +export default function NewMatchPage() { + return ; } diff --git a/src/app/page.tsx b/src/app/page.tsx index aae23df..b42f0bf 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,11 +5,6 @@ import { isAuthenticatedToken, MARRIAGE_ENTRY_PATH_COOKIE, } from "@/lib/entry-route-cache"; -import { - getSubmitPath, - hasCompletedMarriageProfileBasics, -} from "@/lib/get-submit-path"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; import { defaultLocale, isLocale, @@ -57,13 +52,5 @@ export default async function RootPage() { redirect(localizePath(cachedEntryPath, targetLocale)); } - const profile = await fetchProfileSSR(token); - if (profile) { - const targetPath = hasCompletedMarriageProfileBasics(profile) - ? getSubmitPath(profile) - : "/intro"; - redirect(localizePath(targetPath, targetLocale)); - } - redirect(`/${targetLocale}`); } diff --git a/src/app/questions-list/page.tsx b/src/app/questions-list/page.tsx index b1bf27d..1c92f21 100644 --- a/src/app/questions-list/page.tsx +++ b/src/app/questions-list/page.tsx @@ -1,49 +1,5 @@ -import { cookies } from "next/headers"; -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; -import { isAuthenticatedToken } from "@/lib/entry-route-cache"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; -import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; import QuestionsListClient from "./questions-list-client"; -export const dynamic = "force-dynamic"; - -/** - * Server Component wrapper for questions-list. - * - * Prefetches the marriage profile server-side using the HABIB_TOKEN cookie - * (Flutter sets it via WebViewCookieManager before loadRequest). The profile - * determines which page the user should see — having it in the HTML avoids - * the white-flash caused by waiting for the client-side API call. - * - * The sections/form-overview loads client-side with shimmer — that's fine. - */ -export default async function QuestionsListPage() { - const cookieStore = await cookies(); - - const token = - cookieStore.get("HABIB_TOKEN")?.value ?? - cookieStore.get("habib_token")?.value; - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { staleTime: 10 * 1000 }, - }, - }); - - if (isAuthenticatedToken(token)) { - await queryClient.prefetchQuery({ - queryKey: marriageQueryKeys.profile(), - queryFn: () => fetchProfileSSR(token!), - }); - } - - return ( - - - - ); +export default function QuestionsListPage() { + return ; } diff --git a/src/app/questions-list/questions-list-client.tsx b/src/app/questions-list/questions-list-client.tsx index 0ef9c97..9ff6c95 100644 --- a/src/app/questions-list/questions-list-client.tsx +++ b/src/app/questions-list/questions-list-client.tsx @@ -136,9 +136,8 @@ export default function QuestionsListClient() { void fetchGeoCountryCode(); }, []); - // Signal Flutter to lift its loading cover once the profile is available - // (either from SSR hydration or client-side fetch). - useHabibWebReady(!!profile && !isProfileLoading); + // Signal Flutter to lift its loading cover immediately with 0ms latency. + useHabibWebReady(true); const startMatchMutation = useStartMarriageMatchMutation({ onSuccess: () => { diff --git a/src/app/request-accepted/page.tsx b/src/app/request-accepted/page.tsx index b6f1e3a..e276a56 100644 --- a/src/app/request-accepted/page.tsx +++ b/src/app/request-accepted/page.tsx @@ -1,39 +1,5 @@ -import { cookies } from "next/headers"; -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; -import { isAuthenticatedToken } from "@/lib/entry-route-cache"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; -import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; import RequestAcceptedClient from "./request-accepted-client"; -export const dynamic = "force-dynamic"; - -export default async function RequestAcceptedPage() { - const cookieStore = await cookies(); - - const token = - cookieStore.get("HABIB_TOKEN")?.value ?? - cookieStore.get("habib_token")?.value; - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { staleTime: 10 * 1000 }, - }, - }); - - if (isAuthenticatedToken(token)) { - await queryClient.prefetchQuery({ - queryKey: marriageQueryKeys.profile(), - queryFn: () => fetchProfileSSR(token!), - }); - } - - return ( - - - - ); +export default function RequestAcceptedPage() { + return ; } diff --git a/src/app/request-sent/page.tsx b/src/app/request-sent/page.tsx index 4e9b4d2..85156ee 100644 --- a/src/app/request-sent/page.tsx +++ b/src/app/request-sent/page.tsx @@ -1,39 +1,5 @@ -import { cookies } from "next/headers"; -import { - dehydrate, - HydrationBoundary, - QueryClient, -} from "@tanstack/react-query"; -import { isAuthenticatedToken } from "@/lib/entry-route-cache"; -import { fetchProfileSSR } from "@/lib/ssr-fetch"; -import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; import RequestSentClient from "./request-sent-client"; -export const dynamic = "force-dynamic"; - -export default async function RequestSentPage() { - const cookieStore = await cookies(); - - const token = - cookieStore.get("HABIB_TOKEN")?.value ?? - cookieStore.get("habib_token")?.value; - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { staleTime: 10 * 1000 }, - }, - }); - - if (isAuthenticatedToken(token)) { - await queryClient.prefetchQuery({ - queryKey: marriageQueryKeys.profile(), - queryFn: () => fetchProfileSSR(token!), - }); - } - - return ( - - - - ); +export default function RequestSentPage() { + return ; } diff --git a/src/app/terms/page.tsx b/src/app/terms/page.tsx index c43e18a..778ad61 100644 --- a/src/app/terms/page.tsx +++ b/src/app/terms/page.tsx @@ -18,9 +18,8 @@ export default function TermsRoute() { const router = useRouter(); const { locale, dictionary: t } = useI18n(); - // Signal Flutter when profile data is available (or failed — the page - // has its own loading/error UI so the cover can safely be removed). - useHabibWebReady(!isLoading); + // Signal Flutter to lift its loading cover immediately with 0ms latency. + useHabibWebReady(true); useEffect(() => { if (!isLoading && profile) {