feat(flow): session routing contract 정리

This commit is contained in:
2026-03-15 18:40:00 +09:00
parent cbeeb38413
commit 6a0710d023
6 changed files with 52 additions and 13 deletions

View File

@@ -43,6 +43,7 @@ const entryCopy = {
resumeRunning: '진행 중인 세션이 있어요.',
resumePaused: '잠시 멈춘 세션이 있어요.',
resumeCta: '이어서 들어가기',
resumeRouting: '진행 중인 세션으로 돌아가는 중이에요.',
resumeMicroStepLabel: '마지막 한 조각',
resumeNewGoalHint: '새 목표는 현재 세션을 마무리한 뒤 시작할 수 있어요.',
loadFailed: '세션 상태를 불러오지 못했어요. 새로 시작은 계속 할 수 있어요.',
@@ -176,6 +177,8 @@ export const FocusDashboardWidget = () => {
const reviewTeaserHelper = isPro ? entryCopy.reviewHelperPro : entryCopy.reviewHelper;
const reviewTeaserCta = isPro ? entryCopy.reviewCtaPro : entryCopy.reviewCta;
const entryRitualHint = reviewEntryPresetConfig ? `추천 ritual · ${reviewEntryPresetConfig.label}` : entryCopy.ritualHint;
const isRunningSession = currentSession?.state === 'running';
const isPausedSession = currentSession?.state === 'paused';
useEffect(() => {
let cancelled = false;
@@ -210,6 +213,12 @@ export const FocusDashboardWidget = () => {
};
}, []);
useEffect(() => {
if (!isCheckingSession && isRunningSession) {
router.replace('/space');
}
}, [isCheckingSession, isRunningSession, router]);
const openPaywall = () => {
if (!isPro) {
setPaywallSource('app-entry-plan-pill');
@@ -250,13 +259,13 @@ export const FocusDashboardWidget = () => {
};
const handleResumeSession = () => {
router.push('/space');
router.push('/space?resume=continue');
};
const shouldShowWeeklyReviewTeaser =
!isCheckingSession && !currentSession && hasEnoughWeeklyData && !isReviewReturn;
const shouldShowResumeReviewEntry =
!isCheckingSession && Boolean(currentSession) && hasEnoughWeeklyData;
!isCheckingSession && isPausedSession && hasEnoughWeeklyData;
return (
<div className="relative min-h-dvh overflow-hidden bg-slate-950 text-white selection:bg-white/20">
@@ -305,7 +314,14 @@ export const FocusDashboardWidget = () => {
</div>
) : null}
{currentSession ? (
{isRunningSession ? (
<div className={cn(goalCardClass, 'space-y-4 text-center')}>
<p className="text-[11px] font-medium uppercase tracking-[0.18em] text-white/46">
{entryCopy.resumeEyebrow}
</p>
<p className="text-[15px] text-white/72">{entryCopy.resumeRouting}</p>
</div>
) : currentSession ? (
<div className={cn(goalCardClass, 'space-y-5')}>
<div className="space-y-3">
<p className="text-[11px] font-medium uppercase tracking-[0.18em] text-white/46">
@@ -315,7 +331,7 @@ export const FocusDashboardWidget = () => {
{currentSession.goal}
</h1>
<p className="text-sm text-white/68">
{currentSession.state === 'paused' ? entryCopy.resumePaused : entryCopy.resumeRunning}
{entryCopy.resumePaused}
</p>
{currentSession.microStep ? (
<div className="rounded-[1.1rem] border border-white/10 bg-white/[0.04] px-4 py-3">