'use client'; import { useEffect, useMemo, useRef, useState, type FormEvent } from 'react'; import type { SceneTheme } from '@/entities/scene'; import type { GoalChip, SoundPreset, TimerPreset } from '@/entities/session'; import { SceneSelectCarousel } from '@/features/scene-select'; import { SessionGoalField } from '@/features/session-goal'; import { Button } from '@/shared/ui'; import { cn } from '@/shared/lib/cn'; type RitualPopover = 'space' | 'timer' | 'sound'; interface SpaceSetupDrawerWidgetProps { open: boolean; scenes: SceneTheme[]; selectedSceneId: string; selectedTimerLabel: string; selectedSoundPresetId: string; goalInput: string; selectedGoalId: string | null; goalChips: GoalChip[]; soundPresets: SoundPreset[]; timerPresets: TimerPreset[]; canStart: boolean; onSceneSelect: (sceneId: string) => void; onTimerSelect: (timerLabel: string) => void; onSoundSelect: (soundPresetId: string) => void; onGoalChange: (value: string) => void; onGoalChipSelect: (chip: GoalChip) => void; onStart: () => void; resumeHint?: { goal: string; onResume: () => void; onStartFresh: () => void; }; } interface SummaryChipProps { label: string; value: string; open: boolean; onClick: () => void; } const SummaryChip = ({ label, value, open, onClick }: SummaryChipProps) => { return ( ); }; export const SpaceSetupDrawerWidget = ({ open, scenes, selectedSceneId, selectedTimerLabel, selectedSoundPresetId, goalInput, selectedGoalId, goalChips, soundPresets, timerPresets, canStart, onSceneSelect, onTimerSelect, onSoundSelect, onGoalChange, onGoalChipSelect, onStart, resumeHint, }: SpaceSetupDrawerWidgetProps) => { const [openPopover, setOpenPopover] = useState(null); const panelRef = useRef(null); const selectedScene = useMemo(() => { return scenes.find((scene) => scene.id === selectedSceneId) ?? scenes[0]; }, [scenes, selectedSceneId]); const selectedSoundLabel = useMemo(() => { return ( soundPresets.find((preset) => preset.id === selectedSoundPresetId)?.label ?? soundPresets[0]?.label ?? '기본' ); }, [selectedSoundPresetId, soundPresets]); useEffect(() => { if (!openPopover) { return; } const handleEscape = (event: KeyboardEvent) => { if (event.key === 'Escape') { setOpenPopover(null); } }; const handlePointerDown = (event: MouseEvent) => { const target = event.target as Node; if (!panelRef.current?.contains(target)) { setOpenPopover(null); } }; document.addEventListener('keydown', handleEscape); document.addEventListener('mousedown', handlePointerDown); return () => { document.removeEventListener('keydown', handleEscape); document.removeEventListener('mousedown', handlePointerDown); }; }, [openPopover]); if (!open) { return null; } const togglePopover = (popover: RitualPopover) => { setOpenPopover((current) => (current === popover ? null : popover)); }; const handleSubmit = (event: FormEvent) => { event.preventDefault(); if (!canStart) { return; } onStart(); }; return (

Ritual

이번 한 조각을 정하고 시작해요.

목표를 정한 뒤 HUD의 시작 버튼으로 실제 세션을 시작해요.

{resumeHint ? (

지난 한 조각 이어서

{resumeHint.goal}

) : null}
togglePopover('space')} /> togglePopover('timer')} /> togglePopover('sound')} />
{openPopover === 'space' ? (
{ onSceneSelect(sceneId); setOpenPopover(null); }} />
) : null} {openPopover === 'timer' ? (
{timerPresets.slice(0, 3).map((preset) => { const selected = preset.label === selectedTimerLabel; return ( ); })}
) : null} {openPopover === 'sound' ? (
{soundPresets.slice(0, 6).map((preset) => { const selected = preset.id === selectedSoundPresetId; return ( ); })}
) : null}
{!canStart ?

목표를 적으면 시작할 수 있어요.

: null}
); };