"use client"; import { useRouter } from "next/navigation"; import { useCallback, useEffect, useState } from "react"; import { useQueryClient } from "@tanstack/react-query"; import { useUpdateMarriageProfileBasicMutation } from "@/hooks/marriage/use-profile-basic"; import { useHardwareBackHandler } from "@/hooks/use-hardware-back-handler"; import { authBridge } from "@/lib/auth-bridge"; import { setCachedMarriageEntryPath } from "@/lib/entry-route-cache"; import { isInFlutterWebView } from "@/lib/webview-actions"; import { getSubmitPath, hasCompletedMarriageProfileBasics, } from "@/lib/get-submit-path"; import { localizePath, localeDirections } from "@/translations/config"; import { useI18n } from "@/translations/provider"; import Button from "./button"; import ErrorToast from "./error-toast"; import NavigationButton from "./navigation-button"; import type { GenderAnswer, RegistrationAnswer } from "./slider-slide"; import { SHOW_INTRO_VIDEOS } from "@/config/features"; import { SliderSlideFive } from "./slider-slide-five"; import { SliderSlideFour } from "./slider-slide-four"; import { SliderSlideOne, SliderSlideOneActions } from "./slider-slide-one"; import { SliderSlideThree } from "./slider-slide-three"; import { SliderSlideTwo } from "./slider-slide-two"; const FINAL_SLIDE_COUNT = SHOW_INTRO_VIDEOS ? 5 : 4; const SLIDER_ANSWERS_STORAGE_KEY = "marriage-slider-answers"; export type SliderPageProps = { onClose?: () => void; }; export default function SliderPage({ onClose }: SliderPageProps = {}) { const router = useRouter(); const { locale } = useI18n(); const [activeSlide, setActiveSlide] = useState(0); const [selectedGender, setSelectedGender] = useState("woman"); const [selectedRegistration, setSelectedRegistration] = useState("self"); const [hasReadRules, setHasReadRules] = useState(false); const updateProfileBasicMutation = useUpdateMarriageProfileBasicMutation(); const queryClient = useQueryClient(); const [submitError, setSubmitError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const { dictionary: t } = useI18n(); const hasFinalNotice = true; const maxSlideIndex = FINAL_SLIDE_COUNT - 1; const displaySlideCount = FINAL_SLIDE_COUNT; const navDotCount = displaySlideCount; useEffect(() => { // Clear any previous slider answers on mount so abandoned onboarding starts clean if (typeof window !== "undefined") { window.localStorage.removeItem(SLIDER_ANSWERS_STORAGE_KEY); } }, []); const goToSlide = (index: number) => { const targetIndex = Math.max(0, Math.min(index, maxSlideIndex)); if (targetIndex > 0 && !hasReadRules) { return; } setActiveSlide(targetIndex); }; const goToPreviousSlide = useCallback(() => { setActiveSlide((prev) => Math.max(0, prev - 1)); }, []); const goToNextSlide = () => { if (activeSlide === 0 && !hasReadRules) { return; } goToSlide(activeSlide + 1); }; const handleBackNavigation = useCallback(() => { if (activeSlide > 0) { goToPreviousSlide(); return; } if (typeof window !== "undefined") { try { window.sessionStorage.setItem("skip_intro_redirect", "true"); } catch (e) { console.warn("sessionStorage is not accessible:", e); } } if (onClose) { onClose(); return; } if (typeof window !== "undefined" && (window as any).HabibApp) { (window as any).HabibApp.postMessage( JSON.stringify({ action: "close_service" }), ); return; } if (typeof window !== "undefined" && window.history.length > 1) { router.back(); } else { router.replace(localizePath("/intro", locale)); } }, [activeSlide, goToPreviousSlide, onClose, router, locale]); useHardwareBackHandler(() => { if (activeSlide > 0) { goToPreviousSlide(); return true; // Handled: keep WebView open, move to previous slide } if (onClose) { onClose(); return true; // Handled: closed the overlay } return false; // Root: tell Flutter to close WebView screen }); const completeSlider = async () => { if (isSubmitting) return; setIsSubmitting(true); setSubmitError(null); const genderPayload = selectedGender === "man" ? "male" : "female"; const isRegisteringPayload = selectedRegistration === "self"; try { const patchResponse = await updateProfileBasicMutation.mutateAsync({ gender: genderPayload, is_registering_for_self: isRegisteringPayload, }); if ( !hasCompletedMarriageProfileBasics(patchResponse) || patchResponse.gender !== genderPayload || patchResponse.is_registering_for_self !== isRegisteringPayload ) { throw new Error("Invalid PATCH response"); } const { getMarriageProfile } = await import("@/hooks/marriage/use-profile-main"); const freshProfile = await getMarriageProfile(); if ( !hasCompletedMarriageProfileBasics(freshProfile) || freshProfile.gender !== genderPayload || freshProfile.is_registering_for_self !== isRegisteringPayload ) { throw new Error("Invalid GET double-check response"); } const { marriageQueryKeys } = await import("@/hooks/marriage/query-keys"); queryClient.setQueryData(marriageQueryKeys.profile(), freshProfile); if (typeof window !== "undefined") { window.localStorage.removeItem(SLIDER_ANSWERS_STORAGE_KEY); } const targetPath = getSubmitPath(freshProfile); const localizedTarget = localizePath(targetPath, locale); setCachedMarriageEntryPath(targetPath); router.prefetch?.(localizedTarget); router.replace(localizedTarget); } catch (error: any) { console.error("Failed to complete onboarding:", error); const backendMessage = error?.response?.data?.detail || error?.response?.data?.message || error?.response?.data?.error; setSubmitError( backendMessage || t["Something went wrong. Please check your internet connection and try again."] || "Something went wrong. Please check your internet connection and try again." ); setIsSubmitting(false); } }; const isRtl = localeDirections?.[locale] === "rtl"; const translatePercent = (isRtl ? 1 : -1) * activeSlide * 100; return (
{submitError && ( setSubmitError(null)} /> )}
setHasReadRules(true)} /> {SHOW_INTRO_VIDEOS && ( )} {hasFinalNotice ? ( ) : null}
{activeSlide === 0 ? ( ) : activeSlide === maxSlideIndex ? ( ) : ( )}
); } type SliderStepActionsProps = { onBack: () => void; onNext: () => void; }; function SliderStepActions({ onBack, onNext }: SliderStepActionsProps) { const { dictionary: t } = useI18n(); return (
); } type SliderFinalActionsProps = { isFinishing?: boolean; onBack: () => void; onFinish: () => void | Promise; }; function SliderFinalActions({ isFinishing = false, onBack, onFinish, }: SliderFinalActionsProps) { const { dictionary: t } = useI18n(); return (
); }