import { useCallback, useEffect, useMemo, useState } from 'react'; import { useAppSelector } from '@akinon/next/redux/hooks'; import { useSession } from 'next-auth/react'; import type { RootState } from '@theme/redux/store'; import type { SectionStatus } from '../accordion-section'; export type SectionId = 'contact' | 'address' | 'shipping' | 'payment'; export interface SectionState { id: SectionId; status: SectionStatus; isComplete: boolean; } interface UseSectionStateOptions { autoAdvance?: boolean; } export const useSectionState = ({ autoAdvance = true }: UseSectionStateOptions = {}) => { const { data: session } = useSession(); const preOrder = useAppSelector( (state: RootState) => state.checkout.preOrder ); const isAuthenticated = Boolean(session?.user); const contactComplete = isAuthenticated || Boolean(preOrder?.is_guest); const addressComplete = Boolean( preOrder?.shipping_address?.pk && preOrder?.billing_address?.pk ); const shippingComplete = Boolean(preOrder?.shipping_option?.pk); const completion = useMemo( () => ({ contact: contactComplete, address: addressComplete, shipping: shippingComplete, payment: false }), [contactComplete, addressComplete, shippingComplete] ); const firstIncomplete = useMemo(() => { if (!completion.contact) return 'contact'; if (!completion.address) return 'address'; if (!completion.shipping) return 'shipping'; return 'payment'; }, [completion]); const [activeSection, setActiveSection] = useState(firstIncomplete); const [touchedSections, setTouchedSections] = useState>( () => new Set() ); useEffect(() => { if (!autoAdvance) return; if (touchedSections.has(activeSection)) return; if (firstIncomplete !== activeSection) { setActiveSection(firstIncomplete); } }, [firstIncomplete, autoAdvance, activeSection, touchedSections]); const openSection = useCallback((id: SectionId) => { setActiveSection(id); setTouchedSections((prev) => { const next = new Set(prev); next.add(id); return next; }); }, []); const sections = useMemo(() => { const order: SectionId[] = ['contact', 'address', 'shipping', 'payment']; return order.map((id) => { const isComplete = completion[id]; let status: SectionStatus; if (id === activeSection) { status = 'active'; } else if (isComplete) { status = 'completed'; } else { const indexCurrent = order.indexOf(activeSection); const indexThis = order.indexOf(id); status = indexThis < indexCurrent ? 'completed' : 'locked'; } return { id, status, isComplete }; }); }, [completion, activeSection]); const allComplete = completion.contact && completion.address && completion.shipping; return { sections, activeSection, openSection, allComplete, completion, isAuthenticated }; };