60 changed files with 7934 additions and 3423 deletions
-
31src/app/[lang]/page.tsx
-
2src/app/api/proxy/route.ts
-
15src/app/candidate-contact/candidate-contact-client.tsx
-
38src/app/candidate-contact/page.tsx
-
50src/app/finding-match/finding-match-client.tsx
-
38src/app/finding-match/page.tsx
-
4src/app/globals.css
-
41src/app/intro/page.tsx
-
49src/app/layout.tsx
-
4src/app/marriage-advisors/page.tsx
-
148src/app/new-match/new-match-client.tsx
-
38src/app/new-match/page.tsx
-
14src/app/new-match/profile/page.tsx
-
13src/app/page.tsx
-
17src/app/providers.tsx
-
1src/app/questions-list/[slug]/question-detail-client.test.tsx
-
10src/app/questions-list/[slug]/question-detail-client.tsx
-
48src/app/questions-list/page.tsx
-
28src/app/questions-list/questions-list-client.tsx
-
38src/app/request-accepted/page.tsx
-
67src/app/request-accepted/request-accepted-client.tsx
-
38src/app/request-sent/page.tsx
-
46src/app/request-sent/request-sent-client.tsx
-
5src/app/terms/page.tsx
-
4src/components/Componentes/auth-data-boundary.tsx
-
2src/components/Componentes/button.tsx
-
7src/components/Componentes/fix-to-the-end.tsx
-
8src/components/Componentes/question-exit-navigation-button.tsx
-
4807src/data/countries.ts
-
7src/hooks/marriage/use-match-start.ts
-
69src/hooks/marriage/use-profile-main.ts
-
15src/hooks/use-habib-web-ready.ts
-
47src/lib/auth-bridge.ts
-
8src/lib/cookies.ts
-
14src/lib/entry-route-cache.ts
-
30src/lib/marriage-field-formatter.ts
-
50src/lib/user-scoped-storage.test.ts
-
82src/lib/user-scoped-storage.ts
-
52src/translations/locales/ar.json
-
40src/translations/locales/az.json
-
40src/translations/locales/bn.json
-
160src/translations/locales/da.json
-
200src/translations/locales/de.json
-
210src/translations/locales/es.json
-
248src/translations/locales/fr.json
-
364src/translations/locales/gu.json
-
226src/translations/locales/ha.json
-
384src/translations/locales/he.json
-
368src/translations/locales/hi.json
-
168src/translations/locales/id.json
-
388src/translations/locales/ks.json
-
284src/translations/locales/pt.json
-
354src/translations/locales/ru.json
-
234src/translations/locales/sw.json
-
384src/translations/locales/tg.json
-
280src/translations/locales/tr.json
-
76src/translations/locales/ul.json
-
388src/translations/locales/ur.json
-
320src/translations/locales/uz.json
-
180src/translations/locales/zh.json
@ -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"; |
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 ( |
|
||||
<HydrationBoundary state={dehydrate(queryClient)}> |
|
||||
<CandidateContactClient /> |
|
||||
</HydrationBoundary> |
|
||||
); |
|
||||
|
export default function CandidateContactPage() { |
||||
|
return <CandidateContactClient />; |
||||
} |
} |
||||
@ -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"; |
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 ( |
|
||||
<HydrationBoundary state={dehydrate(queryClient)}> |
|
||||
<FindingMatchClient /> |
|
||||
</HydrationBoundary> |
|
||||
); |
|
||||
|
export default function FindingMatchPage() { |
||||
|
return <FindingMatchClient />; |
||||
} |
} |
||||
@ -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"; |
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 ( |
|
||||
<HydrationBoundary state={dehydrate(queryClient)}> |
|
||||
<IntroClient /> |
|
||||
</HydrationBoundary> |
|
||||
); |
|
||||
|
export default function IntroPage() { |
||||
|
return <IntroClient />; |
||||
} |
} |
||||
@ -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"; |
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 ( |
|
||||
<HydrationBoundary state={dehydrate(queryClient)}> |
|
||||
<NewMatchClient /> |
|
||||
</HydrationBoundary> |
|
||||
); |
|
||||
|
export default function NewMatchPage() { |
||||
|
return <NewMatchClient />; |
||||
} |
} |
||||
@ -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"; |
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 ( |
|
||||
<HydrationBoundary state={dehydrate(queryClient)}> |
|
||||
<QuestionsListClient /> |
|
||||
</HydrationBoundary> |
|
||||
); |
|
||||
|
export default function QuestionsListPage() { |
||||
|
return <QuestionsListClient />; |
||||
} |
} |
||||
@ -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"; |
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 ( |
|
||||
<HydrationBoundary state={dehydrate(queryClient)}> |
|
||||
<RequestAcceptedClient /> |
|
||||
</HydrationBoundary> |
|
||||
); |
|
||||
|
export default function RequestAcceptedPage() { |
||||
|
return <RequestAcceptedClient />; |
||||
} |
} |
||||
@ -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"; |
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 ( |
|
||||
<HydrationBoundary state={dehydrate(queryClient)}> |
|
||||
<RequestSentClient /> |
|
||||
</HydrationBoundary> |
|
||||
); |
|
||||
|
export default function RequestSentPage() { |
||||
|
return <RequestSentClient />; |
||||
} |
} |
||||
4807
src/data/countries.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue