feat: 세션 진입 전 목표 세팅
This commit is contained in:
89
src/app/boarding/page.tsx
Normal file
89
src/app/boarding/page.tsx
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, Suspense } from 'react';
|
||||||
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
|
import { ROUTES } from '@/lib/constants';
|
||||||
|
import { saveCurrentVoyage } from '@/lib/store';
|
||||||
|
import { Voyage } from '@/types';
|
||||||
|
|
||||||
|
function BoardingContent() {
|
||||||
|
const router = useRouter();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const routeId = searchParams.get('routeId');
|
||||||
|
const route = ROUTES.find(r => r.id === routeId) || ROUTES[0];
|
||||||
|
|
||||||
|
const [mission, setMission] = useState('');
|
||||||
|
const [notes, setNotes] = useState('');
|
||||||
|
|
||||||
|
const handleDocking = () => {
|
||||||
|
if (!mission.trim()) return;
|
||||||
|
|
||||||
|
const newVoyage: Voyage = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
routeId: route.id,
|
||||||
|
routeName: route.name,
|
||||||
|
durationMinutes: route.durationMinutes,
|
||||||
|
startedAt: Date.now(),
|
||||||
|
status: 'in_progress',
|
||||||
|
missionText: mission,
|
||||||
|
notes: notes,
|
||||||
|
};
|
||||||
|
|
||||||
|
saveCurrentVoyage(newVoyage);
|
||||||
|
router.push('/flight');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col flex-1 p-6 animate-in slide-in-from-bottom-4 duration-500">
|
||||||
|
<div className="mb-8">
|
||||||
|
<h2 className="text-sm text-indigo-400 font-semibold mb-1 uppercase tracking-widest">Boarding Check</h2>
|
||||||
|
<h1 className="text-3xl font-bold text-white">{route.name} 항로 탑승</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-8 flex-1">
|
||||||
|
<div className="space-y-3">
|
||||||
|
<label className="block text-sm font-medium text-slate-300">
|
||||||
|
이번 항해의 핵심 목표
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={mission}
|
||||||
|
onChange={(e) => setMission(e.target.value)}
|
||||||
|
placeholder="예: 서론 3문단 완성하기"
|
||||||
|
className="w-full bg-slate-900/50 border-b-2 border-slate-700 focus:border-indigo-500 px-0 py-3 text-lg outline-none transition-colors placeholder:text-slate-600"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-3">
|
||||||
|
<label className="block text-sm font-medium text-slate-400">
|
||||||
|
메모 (선택)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={notes}
|
||||||
|
onChange={(e) => setNotes(e.target.value)}
|
||||||
|
placeholder="오늘의 컨디션이나 제약사항"
|
||||||
|
className="w-full bg-transparent border-b border-slate-800 focus:border-slate-500 px-0 py-2 text-base outline-none transition-colors placeholder:text-slate-700 text-slate-300"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={handleDocking}
|
||||||
|
disabled={!mission.trim()}
|
||||||
|
className="w-full py-4 bg-indigo-600 hover:bg-indigo-500 disabled:bg-slate-800 disabled:text-slate-500 text-white font-bold text-lg rounded-xl transition-all shadow-lg shadow-indigo-900/30 mt-8"
|
||||||
|
>
|
||||||
|
도킹 완료 (출항)
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BoardingPage() {
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<div className="p-6">Loading...</div>}>
|
||||||
|
<BoardingContent />
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user