fix(space): 정리된 intent hud와 리뷰 반영

This commit is contained in:
2026-03-14 16:28:26 +09:00
parent 6154bd54a8
commit bc08a049b6
17 changed files with 746 additions and 214 deletions

View File

@@ -1,6 +1,5 @@
'use client';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useEffect, useMemo, useRef, useState } from 'react';
import {
@@ -14,7 +13,6 @@ import { useMediaCatalog, getSceneStageBackgroundStyle } from '@/entities/media'
import { SOUND_PRESETS } from '@/entities/session';
import { PaywallSheetContent } from '@/features/paywall-sheet';
import { PlanPill } from '@/features/plan-pill';
import { useFocusStats } from '@/features/stats';
import { focusSessionApi } from '@/features/focus-session/api/focusSessionApi';
import { copy } from '@/shared/i18n';
import { cn } from '@/shared/lib/cn';
@@ -85,7 +83,7 @@ const itemCardGlassSelectedClass = 'border-white/40 bg-white/20 shadow-[0_0_20px
export const FocusDashboardWidget = () => {
const router = useRouter();
const { plan: planTier, isPro, setPlan } = usePlanTier();
const { plan, isLoading, isSaving, error, source, createItem, updateItem, deleteItem } = useFocusPlan();
const { plan, isLoading, isSaving, source, createItem, updateItem, deleteItem } = useFocusPlan();
const { sceneAssetMap } = useMediaCatalog();
const [step, setStep] = useState<DashboardStep>('goal');
@@ -124,11 +122,16 @@ export const FocusDashboardWidget = () => {
}, [maxItems, plan.currentItem, plan.nextItems]);
const currentItem = planItems[0] ?? null;
const shouldUseCurrentPlanDefaults =
Boolean(currentItem) && (entrySource === 'starter' || (entrySource === 'plan' && !selectedPlanItemId));
const resolvedEntryDraft = shouldUseCurrentPlanDefaults && currentItem ? currentItem.title : entryDraft;
const resolvedSelectedPlanItemId =
shouldUseCurrentPlanDefaults && currentItem ? currentItem.id : selectedPlanItemId;
const hasPendingEdit = editingState !== null;
const canAddMore = planItems.length < maxItems;
const canManagePlan = source === 'api' && !isLoading;
const trimmedEntryGoal = entryDraft.trim();
const trimmedEntryGoal = resolvedEntryDraft.trim();
const isGoalReady = trimmedEntryGoal.length > 0;
useEffect(() => {
@@ -140,15 +143,6 @@ export const FocusDashboardWidget = () => {
return () => window.cancelAnimationFrame(rafId);
}, [editingState]);
useEffect(() => {
if (!currentItem) return;
if (entrySource === 'starter' || (entrySource === 'plan' && !selectedPlanItemId)) {
setEntryDraft(currentItem.title);
setSelectedPlanItemId(currentItem.id);
setEntrySource('plan');
}
}, [currentItem, entryDraft, entrySource, selectedPlanItemId]);
const openPaywall = () => setPaywallSource(focusEntryCopy.paywallSource);
const handleSelectPlanItem = (item: FocusPlanItem) => {
@@ -162,7 +156,7 @@ export const FocusDashboardWidget = () => {
const handleSelectSuggestion = (goal: string) => {
setEntryDraft(goal);
setSelectedPlanItemId(null);
setEntrySource('starter');
setEntrySource('custom');
};
const handleEntryDraftChange = (value: string) => {
@@ -224,7 +218,7 @@ export const FocusDashboardWidget = () => {
const nextPlan = await updateItem(editingState.itemId, { title: trimmedTitle });
if (!nextPlan) return;
setEditingState(null);
if (selectedPlanItemId === editingState.itemId) {
if (resolvedSelectedPlanItemId === editingState.itemId) {
setEntryDraft(trimmedTitle);
setEntrySource('plan');
}
@@ -236,7 +230,7 @@ export const FocusDashboardWidget = () => {
if (editingState?.mode === 'edit' && editingState.itemId === itemId) {
setEditingState(null);
}
if (selectedPlanItemId === itemId) {
if (resolvedSelectedPlanItemId === itemId) {
const nextVisiblePlanItems = resolveVisiblePlanItems(nextPlan, maxItems);
const nextCurrentItem = nextVisiblePlanItems[0] ?? null;
if (nextCurrentItem) {
@@ -270,7 +264,7 @@ export const FocusDashboardWidget = () => {
sceneId: selectedSceneId,
soundPresetId: selectedSoundId,
timerPresetId: selectedTimerId,
focusPlanItemId: selectedPlanItemId || undefined,
focusPlanItemId: resolvedSelectedPlanItemId || undefined,
entryPoint: 'space-setup'
});
router.push('/space');
@@ -328,7 +322,7 @@ export const FocusDashboardWidget = () => {
<div className="w-full max-w-xl mx-auto space-y-8">
<input
ref={entryInputRef}
value={entryDraft}
value={resolvedEntryDraft}
onChange={(event) => handleEntryDraftChange(event.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleNextStep()}
placeholder={focusEntryCopy.inputPlaceholder}
@@ -359,7 +353,7 @@ export const FocusDashboardWidget = () => {
<div className="pt-8 flex flex-col items-center gap-4 opacity-70 hover:opacity-100 transition-opacity">
<div className="flex flex-wrap justify-center gap-2">
{ENTRY_SUGGESTIONS.map((suggestion) => {
const isActive = selectedPlanItemId === null && trimmedEntryGoal === suggestion.goal;
const isActive = resolvedSelectedPlanItemId === null && trimmedEntryGoal === suggestion.goal;
return (
<button
key={suggestion.id}
@@ -400,7 +394,7 @@ export const FocusDashboardWidget = () => {
<div className={panelGlassClass}>
<div className="flex items-center justify-between mb-8 pb-6 border-b border-white/10">
<div className="flex-1">
<p className="text-xs uppercase tracking-widest text-white/40 mb-2">Today's Focus</p>
<p className="mb-2 text-xs uppercase tracking-widest text-white/40">Today&apos;s Focus</p>
<p className="text-xl md:text-2xl font-light text-white truncate pr-4">{trimmedEntryGoal}</p>
</div>
<button