diff --git a/app/api/study_cards.py b/app/api/study_cards.py index c5047ba..5c4914e 100644 --- a/app/api/study_cards.py +++ b/app/api/study_cards.py @@ -38,6 +38,7 @@ class CardEvidence(BaseModel): class CardItem(BaseModel): id: int + source_kind: str = "question" format: str cue: str fact: str @@ -142,19 +143,34 @@ async def list_cards( ).all() q_meta = {r.id: (r.question_text, r.correct_choice) for r in q_rows} - # 그룹핑 (출제순서=rows 순서 유지) - groups: dict[int | None, CardQuestionGroup] = {} - order: list[int | None] = [] + # 그룹핑 (출제순서=rows 순서 유지). question 카드는 출처 문제별, + # manual(직접 추가) 카드는 extra.material 별로 묶는다. + groups: dict[str, CardQuestionGroup] = {} + order: list[str] = [] for c in rows: - key = c.source_question_id - if key not in groups: - qt, cc = q_meta.get(key, (None, None)) if key is not None else (None, None) - groups[key] = CardQuestionGroup(source_question_id=key, question_text=qt, correct_choice=cc, cards=[]) - order.append(key) - groups[key].cards.append( + if c.source_question_id is not None: + gkey = f"q:{c.source_question_id}" + else: + material = c.extra.get("material") if isinstance(c.extra, dict) else None + gkey = f"m:{material or '직접 추가'}" + if gkey not in groups: + if c.source_question_id is not None: + qt, cc = q_meta.get(c.source_question_id, (None, None)) + groups[gkey] = CardQuestionGroup( + source_question_id=c.source_question_id, question_text=qt, correct_choice=cc, cards=[] + ) + else: + material = c.extra.get("material") if isinstance(c.extra, dict) else None + groups[gkey] = CardQuestionGroup( + source_question_id=None, + question_text=(f"[자료] {material}" if material else "직접 추가 카드"), + correct_choice=None, cards=[], + ) + order.append(gkey) + groups[gkey].cards.append( CardItem( - id=c.id, format=c.format, cue=c.cue, fact=c.fact, cloze_text=c.cloze_text, - needs_review=c.needs_review, flagged_by=c.flagged_by, + id=c.id, source_kind=c.source_kind, format=c.format, cue=c.cue, fact=c.fact, + cloze_text=c.cloze_text, needs_review=c.needs_review, flagged_by=c.flagged_by, evidence=ev_by_card.get(c.id, []), ) ) @@ -221,8 +237,8 @@ async def update_card( raise HTTPException(status_code=409, detail="같은 정답의 중복 카드가 이미 있습니다") return CardItem( - id=card.id, format=card.format, cue=card.cue, fact=card.fact, cloze_text=card.cloze_text, - needs_review=card.needs_review, flagged_by=card.flagged_by, evidence=[], + id=card.id, source_kind=card.source_kind, format=card.format, cue=card.cue, fact=card.fact, + cloze_text=card.cloze_text, needs_review=card.needs_review, flagged_by=card.flagged_by, evidence=[], ) diff --git a/frontend/src/routes/study/cards-review/+page.svelte b/frontend/src/routes/study/cards-review/+page.svelte index 240fd02..ed828ba 100644 --- a/frontend/src/routes/study/cards-review/+page.svelte +++ b/frontend/src/routes/study/cards-review/+page.svelte @@ -211,6 +211,8 @@ {#if c.evidence?.length}