/** * 검사 홈 — 5종 인지검사 목록/완료상태, 시작 (PRD §3.1, §3.4.1) * 설문 완료 후 시작 가능. 모바일 전용. * Phase D: MD3 디자인 토큰 + 공용 컴포넌트(PillButton, StatusBadge, InfoBanner) 적용 */ import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import { http } from '../lib/api'; import { useOrientationLock } from '../hooks/useOrientationLock'; import { ALLOW_DESKTOP } from '../lib/env'; import PillButton from '../components/PillButton'; import StatusBadge from '../components/StatusBadge'; import InfoBanner from '../components/InfoBanner'; import MatIcon from '../components/MatIcon'; interface StatusResp { todayCompleted: boolean; inProgress: boolean; round: number | null; status: string | null; done: Record; } interface CurrentResp { history: { id: number; round: number; status: string } | null; cntData: Record | null; } const TESTS = [ { key: 'MC', title: '소근육 테스트', desc: '양손의 소근육 능력을 측정', icon: 'touch_app' }, { key: 'EP', title: '표정 맞추기 테스트', desc: '사람의 감정을 인지하고, 신속하게 구분할 수 있는지 파악', icon: 'sentiment_satisfied' }, { key: 'CST', title: '카드정렬 테스트', desc: '제시되는 카드 배열을 인지하고, 동일하게 구성할 수 있는지를 파악', icon: 'style' }, { key: 'NBACK', title: 'N-BACK 테스트', desc: '이전의 기억을 떠올려 작업할 수 있는지를 파악', icon: 'nfc' }, { key: 'MR', title: '회전 도형 테스트', desc: '제시되는 도형을 인식하고, 회상 할 수 있는지를 파악', icon: 'rotate_right' }, ]; const Container = styled.div` padding-top: 16px; `; const Title = styled.h2` font-family: 'Inter', 'Pretendard', system-ui, sans-serif; font-size: 20px; font-weight: 700; color: var(--md3-on-surface); margin: 0 0 12px; `; const TestCard = styled.div<{ $done?: boolean }>` display: flex; align-items: center; gap: 14px; background: var(--md3-surface); border-radius: 16px; padding: 16px; margin-bottom: 12px; border: 1px solid ${(p) => (p.$done ? 'var(--md3-tertiary)' : 'var(--md3-outline-variant)')}; box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06); transition: border-color 0.2s, box-shadow 0.2s; .icon { display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 12px; background: var(--md3-primary-fixed-dim); color: var(--md3-primary); } .info { flex: 1; min-width: 0; } .info h3 { font-family: 'Inter', 'Pretendard', system-ui, sans-serif; font-size: 16px; font-weight: 600; color: var(--md3-on-surface); margin: 0 0 2px; } .info p { font-family: 'Inter', 'Pretendard', system-ui, sans-serif; font-size: 12px; color: var(--md3-on-surface-variant); margin: 0; line-height: 1.4; } `; const NoticeBanner = styled(InfoBanner)` && { margin-bottom: 16px; } `; const CompleteNotice = styled(InfoBanner)` && { margin: 20px 0; } `; const StartButton = styled(PillButton)` && { margin-top: 8px; } `; export default function TestHome() { const nav = useNavigate(); const orient = useOrientationLock(); const [status, setStatus] = useState(null); const [currentData, setCurrentData] = useState(null); useEffect(() => { http.get('/api/cntdata/status').then(setStatus).catch(() => {}); http.get('/api/cntdata/current').then(setCurrentData).catch(() => {}); }, []); const surveyDone = ['PHQ', 'OCI', 'KAQ', 'GAD', 'KSPIN', 'ASRS', 'EPS'].every( (k) => !!currentData?.cntData?.[k], ); if (!orient.isMobile && !ALLOW_DESKTOP) { return ( 모바일 환경에서만 인지검사가 가능합니다. ); } if (status?.todayCompleted) { return ( 오늘은 이미 검사를 완료하셨습니다. 내일 다시 시도해주세요. nav('/dashboard')}> 결과 보기 ); } return ( 인지검사 5종 {!surveyDone && ( 정서 설문을 모두 완료해야 인지검사를 시작할 수 있습니다. )} {TESTS.map((t) => (

{t.title}

{t.desc}

{status?.done?.[t.key] ? ( 완료 ) : ( 미완료 )}
))} nav('/test/start')} disabled={!surveyDone} > {surveyDone ? '검사 시작하기' : '설문 완료 후 시작 가능'}
); }