From 66a906a156d9699ab95f6e6a66305fe448dd21d8 Mon Sep 17 00:00:00 2001 From: hyungi Date: Sun, 7 Jun 2026 21:00:08 +0900 Subject: [PATCH] =?UTF-8?q?feat(ui):=20study/topics=20=ED=95=99=EC=8A=B5?= =?UTF-8?q?=20=EC=A7=84=EB=8B=A8(study=5Fdiagnosis)=20=ED=8C=A8=EB=84=90?= =?UTF-8?q?=20=E2=80=94=20=EC=9D=B4=EB=93=9C=20=EC=BD=94=EC=B9=98=20?= =?UTF-8?q?=ED=91=9C=EB=A9=B4=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit eid study_diagnosis 백엔드(/api/study-topics/diagnosis/generate)에 프론트 진입점 추가. 학습 주제 페이지 상단 '학습 진단' 카드: [진단 생성] → POST → 코치 응답(약점 Top-N·근거· 복습세트 초안) 마크다운 렌더. data 없으면 status=none 안내(토픽 focus 유도). LLM 호출이라 버튼 트리거. 디자인 토큰·no-emoji. 백엔드 무변(frontend-only). Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/routes/study/topics/+page.svelte | 68 ++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/frontend/src/routes/study/topics/+page.svelte b/frontend/src/routes/study/topics/+page.svelte index 40d16bd..0b4704c 100644 --- a/frontend/src/routes/study/topics/+page.svelte +++ b/frontend/src/routes/study/topics/+page.svelte @@ -13,7 +13,7 @@ import { goto } from '$app/navigation'; import { api } from '$lib/api'; import { addToast } from '$lib/stores/toast'; - import { Plus, ArrowLeft, FolderKanban, Trash2, Pencil } from 'lucide-svelte'; + import { Plus, ArrowLeft, FolderKanban, Trash2, Pencil, Activity } from 'lucide-svelte'; import Button from '$lib/components/ui/Button.svelte'; import Card from '$lib/components/ui/Card.svelte'; import EmptyState from '$lib/components/ui/EmptyState.svelte'; @@ -21,6 +21,7 @@ import TextInput from '$lib/components/ui/TextInput.svelte'; import Select from '$lib/components/ui/Select.svelte'; import Textarea from '$lib/components/ui/Textarea.svelte'; + import { renderMathMarkdown } from '$lib/utils/mathMarkdown'; const STUDY_TYPE_OPTIONS = [ { value: '', label: '미지정' }, @@ -35,6 +36,29 @@ let total = $state(0); let loading = $state(true); + // ─── 이드 학습 진단 (study_diagnosis surface) ─── + // 워커(study_weakness)가 산출한 최신 약점 스냅샷을 코치 언어로 번역. 데이터 없으면 status='none'. + // LLM 호출이라 버튼 트리거(자동 호출 X). + let diag = $state(null); // StudyDiagnosisResponse | null + let diagLoading = $state(false); + async function generateDiagnosis() { + if (diagLoading) return; + diagLoading = true; + try { + diag = await api('/study-topics/diagnosis/generate', { method: 'POST' }); + } catch { + addToast('error', '진단 생성 실패'); + } finally { + diagLoading = false; + } + } + function fmtDiagTime(s) { + if (!s) return ''; + const d = new Date(s); + if (isNaN(d.getTime())) return ''; + return d.toLocaleString('ko-KR', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); + } + // 생성 폼 let formOpen = $state(false); let f_name = $state(''); @@ -205,6 +229,48 @@

한 주제 아래에 필기 세션과 자료를 묶어 보고 진도 관리. 향후 단어장·오디오·문제세트도 같은 묶음으로 연결됩니다.

+ + + {#snippet children()} +
+
+
+ + 학습 진단 + +
+ +
+ + {#if diagLoading} +
+ +
+ {:else if diag && diag.status === 'ready'} +
{@html renderMathMarkdown(diag.content)}
+ {#if diag.review_set_draft_id} +
+ 권장 복습세트 초안 #{diag.review_set_draft_id} — 복습함에서 1클릭 확인 후 편성 +
+ {/if} +
+ {#if diag.snapshot_at}스냅샷 {fmtDiagTime(diag.snapshot_at)}{/if}{#if diag.generated_at} · 생성 {fmtDiagTime(diag.generated_at)}{/if}{#if diag.model} · {diag.model}{/if} +
+ {:else if diag && diag.status === 'none'} +

+ 아직 진단할 약점 데이터가 없습니다. 학습 주제를 공부중으로 표시하면 매일 새벽 누적 풀이에서 약점·태도 스냅샷이 만들어지고, 여기서 진단 코치를 받을 수 있습니다. +

+ {:else} +

+ 누적 학습 이력을 근거로 약점 토픽과 학습 태도를 진단합니다. 진단 생성을 눌러보세요. +

+ {/if} +
+ {/snippet} +
+ {#snippet children()}