fix(space): stabilize unfinished end session close

This commit is contained in:
2026-03-17 18:38:32 +09:00
parent cd91ff9ae5
commit fd1b7123e2
2 changed files with 28 additions and 9 deletions

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useEffect, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { cn } from '@/shared/lib/cn'; import { cn } from '@/shared/lib/cn';
import type { CompletionResult } from '@/features/focus-session'; import type { CompletionResult } from '@/features/focus-session';
@@ -30,19 +30,25 @@ export const EndSessionConfirmModal = ({
const [stage, setStage] = useState<EndSessionStage>('decision'); const [stage, setStage] = useState<EndSessionStage>('decision');
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [result, setResult] = useState<CompletionResult | null>(null); const [result, setResult] = useState<CompletionResult | null>(null);
const resetTimerRef = useRef<number | null>(null);
const trimmedGoal = currentGoal.trim() || '목표 없음'; const trimmedGoal = currentGoal.trim() || '목표 없음';
useEffect(() => { useEffect(() => {
if (!open) { if (!open) {
setTimeout(() => { resetTimerRef.current = window.setTimeout(() => {
setStage('decision'); setStage('decision');
setResult(null); setResult(null);
}, 500); // Reset after close animation }, 500);
setIsSubmitting(false); setIsSubmitting(false);
return; return;
} }
if (resetTimerRef.current !== null) {
window.clearTimeout(resetTimerRef.current);
resetTimerRef.current = null;
}
const handleEscape = (e: KeyboardEvent) => { const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape' && !isSubmitting) { if (e.key === 'Escape' && !isSubmitting) {
onClose(); onClose();
@@ -50,9 +56,19 @@ export const EndSessionConfirmModal = ({
}; };
window.addEventListener('keydown', handleEscape); window.addEventListener('keydown', handleEscape);
return () => window.removeEventListener('keydown', handleEscape); return () => {
window.removeEventListener('keydown', handleEscape);
};
}, [open, isSubmitting, onClose]); }, [open, isSubmitting, onClose]);
useEffect(() => {
return () => {
if (resetTimerRef.current !== null) {
window.clearTimeout(resetTimerRef.current);
}
};
}, []);
const handleFinish = async () => { const handleFinish = async () => {
if (isSubmitting) return; if (isSubmitting) return;
setIsSubmitting(true); setIsSubmitting(true);

View File

@@ -326,18 +326,21 @@ export const SpaceWorkspaceWidget = () => {
if (pendingCompletionResult) { if (pendingCompletionResult) {
setPendingCompletionResult(null); setPendingCompletionResult(null);
setCurrentSessionThoughts([]); setCurrentSessionThoughts([]);
void router.replace('/app');
return true; return true;
} }
const completionResult = await controls.handleManualEnd(); const completionResult = await controls.handleManualEnd();
if (completionResult) { if (completionResult) {
setPendingCompletionResult(completionResult);
setCurrentSessionThoughts([]); setCurrentSessionThoughts([]);
void router.replace('/app');
return true;
} else { } else {
// If no result (cancelled or error), still try to go back if session is gone if (!currentSession) {
if (!currentSession) router.replace('/app'); void router.replace('/app');
}
} }
return Boolean(completionResult); return false;
}} }}
/> />
) : null} ) : null}