"use client";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { IoClose } from "react-icons/io5";
import { getSubmitPath } from "@/lib/get-submit-path";
import {
getLocalSectionProgress,
getStoredAge,
} from "@/components/Componentes/progress-helper";
import QuestionCard from "@/components/Componentes/question-card";
import RequiredStepsCard from "@/components/Componentes/required-steps-card";
import Button from "@/components/Componentes/button";
import InformationSheet from "@/components/Componentes/information-sheet";
import NavigationButton from "@/components/Componentes/navigation-button";
import { FixToTheEnd } from "@/components/Componentes/fix-to-the-end";
import { LoadingSkeleton } from "@/components/Componentes/loading-skeleton";
import { PageBackground } from "@/components/Componentes/page-background";
import ErrorToast from "@/components/Componentes/error-toast";
import { useQueryClient } from "@tanstack/react-query";
import { useStartMarriageMatchMutation } from "@/hooks/marriage/use-match-start";
import { useMarriageProfileQuery } from "@/hooks/marriage/use-profile-main";
import { useMarriageSectionsQuery } from "@/hooks/marriage/use-sections";
import { useFormSchemaQuery } from "@/hooks/marriage/use-form-schema";
import { convertSchemaToFrontendItems } from "@/lib/schema-adapter";
import type { QuestionListItem } from "@/data/question-data";
import { useCloseServiceOnBack } from "@/hooks/use-close-service-on-back";
import {
clearMatchStartGrace,
markMatchStarted,
} from "@/lib/match-start-grace";
import { localizePath } from "@/translations/config";
import { useI18n } from "@/translations/provider";
import { triggerSilentReload } from "@/components/Componentes/silent-reloader";
import SectionsRequest from "./sections-request";
export default function QuestionsListPage() {
useCloseServiceOnBack();
const { dictionary: t, locale } = useI18n();
const router = useRouter();
const queryClient = useQueryClient();
const { data: profile, isLoading: isProfileLoading } =
useMarriageProfileQuery();
const { data: sections, isLoading: isSectionsLoading } =
useMarriageSectionsQuery();
const { data: schema, isLoading: isSchemaLoading } =
useFormSchemaQuery("profile", locale);
useEffect(() => {
triggerSilentReload(queryClient);
}, [queryClient]);
const startMatchMutation = useStartMarriageMatchMutation({
onSuccess: () => {
markMatchStarted();
router.push(localizePath("/finding-match", locale));
},
onError: () => {
// Never pretend the request went through – the user stays here and can
// retry instead of being parked on the waiting screen forever.
clearMatchStartGrace();
},
});
const [isOptionalInfoSheetOpen, setIsOptionalInfoSheetOpen] = useState(false);
const [selectedSection, setSelectedSection] =
useState(null);
const questionListItems = useMemo(
() => convertSchemaToFrontendItems(schema, locale),
[schema, locale],
);
const sectionProgressBySlug = useMemo(() => {
const progressBySlug = new Map();
if (schema?.progress?.sections_progress) {
Object.entries(schema.progress.sections_progress).forEach(([slug, prog]) => {
progressBySlug.set(slug, Math.max(0, Math.min(100, Math.round(prog.completion_percent))));
});
}
// Add fallback for combined section from the schema adapter which attaches it to questionListItems directly
questionListItems.forEach((item) => {
progressBySlug.set(item.slug, item.progress);
});
return progressBySlug;
}, [schema, questionListItems]);
const requiredQuestionListItems = useMemo(
() => questionListItems.filter((item) => Boolean(item.required)),
[questionListItems],
);
const allRequiredSectionsCompleted = useMemo(() => {
if (requiredQuestionListItems.length === 0) {
return false;
}
return requiredQuestionListItems.every((item) => {
const progress = sectionProgressBySlug.get(item.slug) ?? 0;
return progress >= 100;
});
}, [requiredQuestionListItems, sectionProgressBySlug]);
const profileStatus = profile?.status;
const isProfileSuspended = profileStatus === "suspended";
const isProfileBlocked =
profileStatus === "in_case" || profileStatus === "matched";
const canStartMatch =
!isProfileSuspended && !isProfileBlocked && allRequiredSectionsCompleted;
const [isSyncError, setIsSyncError] = useState(false);
const [isSyncing, setIsSyncing] = useState(false);
const [toastMessage, setToastMessage] = useState(null);
useEffect(() => {
if (startMatchMutation.isError || isSyncError) {
setToastMessage(
t[
"Sending the match request failed. Please check your connection and try again."
],
);
}
}, [
startMatchMutation.isError,
isSyncError,
t[
"Sending the match request failed. Please check your connection and try again."
],
]);
const handleCloseToast = () => {
setToastMessage(null);
setIsSyncError(false);
startMatchMutation.reset();
};
const isStartMatchDisabled =
startMatchMutation.isPending || isSyncing || !canStartMatch;
const hasIncompleteOptionalSections = useMemo(() => {
return questionListItems.some(
(item) =>
!item.required && (sectionProgressBySlug.get(item.slug) ?? 0) < 100,
);
}, [questionListItems, sectionProgressBySlug]);
const handleStartMatch = async () => {
if (isStartMatchDisabled || isSyncing) {
return;
}
setIsSyncing(true);
setIsSyncError(false);
try {
const slugsToCheck = [
"personal_info",
"contact_residence_family_communication",
"appearance_health_activity",
"education_career_economic_status",
"family_marital_history",
"beliefs_lifestyle_boundaries",
"future_spouse_criteria",
"identity_verification",
];
for (const slug of slugsToCheck) {
const rawValue = window.localStorage.getItem(
`marriage:sections:${slug}:answers`,
);
if (rawValue) {
const storedValue = JSON.parse(rawValue);
if (storedValue.pending_sync && storedValue.fields) {
const payload = {
current_step: storedValue.current_step,
fields: storedValue.fields,
};
const { updateMarriageSectionData } = await import(
"@/hooks/marriage/use-section-data"
);
await updateMarriageSectionData(slug, payload);
storedValue.pending_sync = false;
window.localStorage.setItem(
`marriage:sections:${slug}:answers`,
JSON.stringify(storedValue),
);
}
}
}
await queryClient.invalidateQueries();
startMatchMutation.mutate();
} catch (err) {
console.error("Failed to sync pending sections:", err);
setIsSyncError(true);
} finally {
setIsSyncing(false);
}
};
if (isProfileLoading || isSectionsLoading || isSchemaLoading) {
return (
<>
{
e.preventDefault();
if (typeof window !== "undefined" && (window as any).HabibApp) {
(window as any).HabibApp.postMessage(
JSON.stringify({ action: "close_service" }),
);
} else {
router.push("/");
}
}}
/>
{t["Profile registration"]}
{/* Required Steps Card Skeleton */}
{/* Section Cards Skeletons */}
{Array.from({ length: 6 }).map((_, idx) => (
))}
>
);
}
return (
<>
{toastMessage && (
)}
{isOptionalInfoSheetOpen ? (
{
t[
"You've completed all required fields. However, filling in all sections will help us find better matches for you"
]
}
}
onClose={() => setIsOptionalInfoSheetOpen(false)}
buttons={({ close }) => (
{t["Cancel"]}
{
close();
handleStartMatch();
}}
>
{t["Submit"]}
)}
/>
) : null}
{selectedSection ? (
(
{selectedSection.title}
)}
description={
{selectedSection.summary}
}
onClose={() => setSelectedSection(null)}
className="text-left"
/>
) : null}
{
e.preventDefault();
if (typeof window !== "undefined" && (window as any).HabibApp) {
(window as any).HabibApp.postMessage(
JSON.stringify({ action: "close_service" }),
);
} else {
router.push("/");
}
}}
/>
{t["Profile registration"]}
{questionListItems.map((item) => (
setSelectedSection(section)}
/>
))}
{
if (hasIncompleteOptionalSections) {
setIsOptionalInfoSheetOpen(true);
return;
}
handleStartMatch();
}}
>
{t["Submit"]}
>
);
}