diff --git a/frontend/src/routes/study/cards-study/+page.svelte b/frontend/src/routes/study/cards-study/+page.svelte index 04cca6d..cecc892 100644 --- a/frontend/src/routes/study/cards-study/+page.svelte +++ b/frontend/src/routes/study/cards-study/+page.svelte @@ -42,6 +42,23 @@ let tally = $state({ correct: 0, unsure: 0, wrong: 0 }); // 복습 결과 집계 let seen = $state(0); // 그냥공부 본 카드 수 let dueCount = $state(null); // landing 배지 + let marks = $state([]); // 카드별 결과 (데스크탑 좌측 진행트랙 점): 'correct'|'unsure'|'wrong'|'seen'|'flagged' + + function setMark(kind) { + const m = [...marks]; + m[idx] = kind; + marks = m; + } + // 데스크탑 진행트랙 점 클래스 (크기+색). 현재 카드는 accent 세로막대, 지난 카드는 결과색. + function dotClass(i) { + if (i === idx && !done) return 'h-4 w-1.5 bg-accent'; + const k = marks[i]; + if (k === 'correct') return 'h-1.5 w-1.5 bg-success'; + if (k === 'unsure') return 'h-1.5 w-1.5 bg-warning'; + if (k === 'wrong') return 'h-1.5 w-1.5 bg-error'; + if (k === 'seen' || k === 'flagged') return 'h-1.5 w-1.5 bg-faint'; + return 'h-1.5 w-1.5 bg-default'; + } let current = $derived(cards[idx] ?? null); let total = $derived(cards.length); @@ -63,6 +80,7 @@ idx = 0; revealed = false; tally = { correct: 0, unsure: 0, wrong: 0 }; + marks = []; try { cards = _dueCache ?? (await fetchDue()); _dueCache = null; // 소비 @@ -81,6 +99,7 @@ idx = 0; revealed = false; seen = 0; + marks = []; try { const q = fmtFilter ? `?format=${fmtFilter}&limit=40` : '?limit=40'; cards = (await api(`/study-cards/deck${q}`)) ?? []; @@ -118,6 +137,7 @@ }); const key = label === '암' ? 'correct' : label === '애매' ? 'unsure' : 'wrong'; tally = { ...tally, [key]: tally[key] + 1 }; + setMark(key); advance(); } catch (err) { addToast('error', err?.detail || '평가 저장 실패'); @@ -132,6 +152,7 @@ try { await api(`/study-cards/${current.id}/view`, { method: 'POST' }); seen += 1; + setMark('seen'); advance(); } catch (err) { addToast('error', err?.detail || '기록 실패'); @@ -149,6 +170,7 @@ try { await api(`/study-cards/${c.id}`, { method: 'PATCH', body: JSON.stringify({ needs_review: true }) }); addToast('success', '검수함으로 보냈어요 — 이 카드는 학습에서 빠집니다'); + setMark('flagged'); advance(); } catch (err) { addToast('error', err?.detail || '신고 처리 실패'); @@ -198,7 +220,7 @@ 암기카드 학습 -
+
{#if mode === 'landing'} @@ -231,8 +253,8 @@ {#if mode === 'landing'} -

검수 완료한 암기카드를 학습합니다. 두 가지 방법 중 선택하세요.

-
+

검수 완료한 암기카드를 학습합니다. 두 가지 방법 중 선택하세요.

+
+ +
+ + - - {#if revealed} - {#if mode === 'review'} -
+ +
+
+
+ {current.format} - - + type="button" + onclick={flagCard} + disabled={flagBusy || busy} + class="flex items-center gap-1 text-[11px] text-faint transition-colors hover:text-warning disabled:opacity-50" + title="카드 내용이 이상하면 검수함으로 보냅니다" + > + 이 카드 이상해요 +
- - {:else} - + +
+ 앞 — {current.format === 'qa' ? '질문' : '회상'} +
+
{frontText(current)}
+ + {#if revealed} +
+
정답
+
{current.fact}
+ {#if current.evidence?.length && current.evidence[0].snippet} +
근거: {current.evidence[0].snippet}
+ {/if} +
+ {/if} + + {#if !revealed} + + {/if} +
+ + + {#if revealed} + {#if mode === 'review'} +
+ + + +
+ + {:else} + + {/if} {/if} - {/if} +
+ + +
{/if}