"use client"; import { useCallback, useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { useAuthModal } from "../../contexts/AuthModalContext"; import { useTranslation } from "../../contexts/MessagesContext"; import { deleteAccount, deletePublishedRule, deleteServerDraft, duplicatePublishedRule, fetchAuthSession, fetchMyPublishedRules, fetchServerDraftForProfile, logout, type MyPublishedRule, } from "../../../lib/create/api"; import { FIRST_STEP, isValidStep, } from "../create/utils/flowSteps"; import type { CreateFlowStep } from "../create/types"; import { clearAnonymousCreateFlowStorage } from "../create/utils/anonymousDraftStorage"; import { useMediaQuery } from "../../hooks/useMediaQuery"; import { ProfilePageSignedOutView, ProfilePageView, } from "./_components/ProfilePage.view"; function resolveContinueStepState( state: { currentStep?: CreateFlowStep } & Record, ): CreateFlowStep { const s = state.currentStep; if (s && isValidStep(s)) return s; return FIRST_STEP; } export default function ProfilePageClient() { const t = useTranslation("pages.profile"); const router = useRouter(); const { openLogin } = useAuthModal(); const [sessionLoaded, setSessionLoaded] = useState(false); const [user, setUser] = useState<{ id: string; email: string } | null>(null); const [rules, setRules] = useState([]); const [rulesError, setRulesError] = useState(false); const [draft, setDraft] = useState< Awaited> >(null); const [ruleDeleteTargetId, setRuleDeleteTargetId] = useState( null, ); const [ruleDeleteBusy, setRuleDeleteBusy] = useState(false); const [draftDeleteOpen, setDraftDeleteOpen] = useState(false); const [draftDeleteBusy, setDraftDeleteBusy] = useState(false); const [accountDeleteOpen, setAccountDeleteOpen] = useState(false); const [accountDeleteBusy, setAccountDeleteBusy] = useState(false); const [actionError, setActionError] = useState(null); const load = useCallback(async () => { setActionError(null); const { user: u } = await fetchAuthSession(); setUser(u); setSessionLoaded(true); if (!u) { setRules([]); setRulesError(false); setDraft(null); return; } const [r, d] = await Promise.all([ fetchMyPublishedRules(), fetchServerDraftForProfile(), ]); if (r === null) { setRules([]); setRulesError(true); } else { setRules(r); setRulesError(false); } setDraft(d); }, []); useEffect(() => { void load(); }, [load]); const handleSignOut = useCallback(async () => { setActionError(null); await logout(); setUser(null); setRules([]); setDraft(null); router.refresh(); }, [router]); const handleRequestDeleteRule = useCallback((id: string) => { setActionError(null); setRuleDeleteTargetId(id); }, []); const handleCloseDeleteRuleDialog = useCallback(() => { if (ruleDeleteBusy) return; setRuleDeleteTargetId(null); }, [ruleDeleteBusy]); const handleConfirmDeleteRule = useCallback(async () => { const id = ruleDeleteTargetId; if (!id || ruleDeleteBusy) return; setActionError(null); setRuleDeleteBusy(true); const res = await deletePublishedRule(id); setRuleDeleteBusy(false); if (res.ok === true) { setRuleDeleteTargetId(null); void load(); return; } if (res.status === 404) { setActionError(t("notFound")); setRuleDeleteTargetId(null); } else if (res.status === 403) { setActionError(t("forbidden")); setRuleDeleteTargetId(null); } else { setActionError(t("actionError")); } }, [load, ruleDeleteBusy, ruleDeleteTargetId, t]); const handleDuplicateRule = useCallback( async (id: string) => { setActionError(null); const res = await duplicatePublishedRule(id); if (res.ok === true) { void load(); } else { if (res.status === 404) { setActionError(t("notFound")); } else if (res.status === 403) { setActionError(t("forbidden")); } else { setActionError(t("actionError")); } } }, [load, t], ); const handleContinueDraft = useCallback(() => { if (draft == null || !draft.hasDraft) return; const step = resolveContinueStepState(draft.state); router.push(`/create/${step}`); }, [draft, router]); const handleRequestDeleteDraft = useCallback(() => { setActionError(null); setDraftDeleteOpen(true); }, []); const handleCloseDeleteDraftDialog = useCallback(() => { if (draftDeleteBusy) return; setDraftDeleteOpen(false); }, [draftDeleteBusy]); const handleConfirmDeleteDraft = useCallback(async () => { if (draftDeleteBusy) return; setActionError(null); setDraftDeleteBusy(true); clearAnonymousCreateFlowStorage(); await deleteServerDraft(); setDraftDeleteBusy(false); setDraftDeleteOpen(false); void load(); }, [draftDeleteBusy, load]); const handleConfirmDeleteAccount = useCallback(async () => { setActionError(null); setAccountDeleteBusy(true); const res = await deleteAccount(); setAccountDeleteBusy(false); if (res.ok) { setAccountDeleteOpen(false); setUser(null); setRules([]); setDraft(null); router.push("/"); router.refresh(); return; } setActionError(t("actionError")); }, [router, t]); /** `lg`+ layout; matches `--breakpoint-lg` in `app/tailwind.css`. */ const isProfileLgUp = useMediaQuery("(min-width: 1024px)"); /** `List` L + Bricolage section titles — Figma `22143:900247`; matches `--breakpoint-xl` (1440px). */ const isProfileXlUp = useMediaQuery("(min-width: 1440px)"); if (!sessionLoaded) { return (

{t("loading")}

); } if (!user) { return ( openLogin({ nextPath: "/profile" })} /> ); } const showDraftCard = Boolean( draft && draft.hasDraft, ); return ( { setActionError(null); setAccountDeleteOpen(true); }} onCloseDeleteAccount={() => setAccountDeleteOpen(false)} onConfirmDeleteAccount={handleConfirmDeleteAccount} /> ); }