"use client"; import { useRouter } from "next/navigation"; import type { TouchEvent } from "react"; import { useEffect, useState } from "react"; import { useQueryClient } from "@tanstack/react-query"; import { useUpdateMarriageProfileBasicMutation } from "@/hooks/marriage/use-profile-basic"; import { getSubmitPath, hasCompletedMarriageProfileBasics, } from "@/lib/get-submit-path"; import { localizePath } from "@/translations/config"; import { useI18n } from "@/translations/provider"; import Button from "./button"; import NavigationButton from "./navigation-button"; import type { GenderAnswer, RegistrationAnswer } from "./slider-slide"; 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 = 5; const SWIPE_THRESHOLD = 40; 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 [touchStartX, setTouchStartX] = useState(null); const [touchStartY, setTouchStartY] = useState(null); 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 = () => { goToSlide(activeSlide - 1); }; const goToNextSlide = () => { if (activeSlide === 0 && !hasReadRules) { return; } goToSlide(activeSlide + 1); }; 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); router.prefetch?.(localizedTarget); router.replace(localizedTarget); } catch (error) { console.error("Failed to complete onboarding:", error); setSubmitError(t["Failed to update profile basic details. Please try again."] || "Failed to update profile basic details. Please try again."); } finally { setIsSubmitting(false); } }; const handleTouchStart = (event: TouchEvent) => { setTouchStartX(event.touches[0]?.clientX ?? null); setTouchStartY(event.touches[0]?.clientY ?? null); }; const handleTouchEnd = (event: TouchEvent) => { if (touchStartX === null || touchStartY === null) { return; } const touchEndX = event.changedTouches[0]?.clientX ?? touchStartX; const touchEndY = event.changedTouches[0]?.clientY ?? touchStartY; const deltaX = touchStartX - touchEndX; const deltaY = touchStartY - touchEndY; if ( Math.abs(deltaX) >= SWIPE_THRESHOLD && Math.abs(deltaX) > Math.abs(deltaY) * 1.5 ) { if (deltaX > 0) { if (activeSlide === 0 && !hasReadRules) { setTouchStartX(null); setTouchStartY(null); return; } goToNextSlide(); } else { goToPreviousSlide(); } } setTouchStartX(null); setTouchStartY(null); }; 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(); } else { router.back(); } }} />
setHasReadRules(true)} /> {hasFinalNotice ? : null}
{activeSlide === 0 ? ( ) : activeSlide === maxSlideIndex ? (
{submitError && (
{submitError}
)}
) : ( )}
); } 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 (
); }