From 3fe4c16d3ade0811a1ca509601a550f109977b0c Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Tue, 14 Apr 2026 14:25:19 +0900 Subject: [PATCH] =?UTF-8?q?refactor(dashboard):=20UI/UX=20=EC=9E=AC?= =?UTF-8?q?=EC=84=A4=EA=B3=84=20=E2=80=94=20=EC=A0=95=EB=B3=B4=20=EC=9C=84?= =?UTF-8?q?=EA=B3=84=20+=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 대시보드 전면 재작성: - 핀 메모: 최상단 조건부 컴팩트 띠 (pinned=true API 파라미터 추가) - 4개 핵심 카드: 문서함/메모/뉴스/승인대기 (2×2 모바일, 4열 데스크탑) - 승인 대기: 액션형 카드 (warning + 검토하기 CTA) - 최근 활동: 전체 너비, 2줄 스캔형, 법령 알림 뱃지 - 파이프라인: details 기반 접힘 (실패 시 자동 펼침, 수동 접힘 유지) - 시스템 상태: 헤더 인라인 배지 (비클릭) - CalDAV stub/도메인 분포 위젯 제거 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/api/memos.py | 4 + frontend/src/routes/+page.svelte | 571 +++++++++++++------------------ 2 files changed, 240 insertions(+), 335 deletions(-) diff --git a/app/api/memos.py b/app/api/memos.py index 94907b0..c70e165 100644 --- a/app/api/memos.py +++ b/app/api/memos.py @@ -173,6 +173,7 @@ async def list_memos( page_size: int = Query(20, ge=1, le=100), tag: str | None = Query(None, description="user_tags 또는 ai_tags 필터"), archived: bool = Query(False, description="true면 아카이브 목록"), + pinned: bool | None = Query(None, description="true면 핀 고정된 메모만"), ): """메모 목록 — 활성: 핀 우선 + 최신순 / 아카이브: 최신순 (핀 무시)""" base = select(Document).where( @@ -182,6 +183,9 @@ async def list_memos( Document.archived == archived, ) + if pinned is not None: + base = base.where(Document.pinned == pinned) + if tag: base = base.where( Document.user_tags.op("@>")(f'["{tag}"]') diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 7e4ce36..e368ec4 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,51 +1,43 @@
-
-

대시보드

+
+ + +
+

대시보드

+ {#if systemView} + + {systemView.label} + + + {/if} +
{#if loading} - -
+ +
{#each Array(4) as _} -
- - - - - -
+ {/each} -
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
+ + {:else if summary} -
- - -
- - -

문서함

-

{(summary.documents_count ?? 0).toLocaleString()}

-

- {summary.today_added > 0 ? `+${summary.today_added} 오늘` : '-'} -

-
-
- - -

메모

-

{(summary.memos_count ?? 0).toLocaleString()}

-

-

-
-
- - - -

뉴스

-

{(summary.news_count ?? 0).toLocaleString()}

-

-

-
-
- - - -

승인 대기

-

{summary.inbox_count}

-

- {summary.inbox_count > 0 ? '분류하기 →' : '-'} -

-
-
- -
- -

법령 알림

-

{summary.law_alerts}

-

- {summary.law_alerts > 0 ? '오늘 변경' : '-'} -

-
-
- -
- -

시스템

- {#if systemView} -

{systemView.label}

-

{systemView.sub}

- {/if} -
-
+ + {#if pinnedMemos.length > 0} +
+ {#each pinnedMemos as memo (memo.id)} + + + {memo.content?.split('\n')[0] || '메모'} + + {/each} + {#if pinnedMemos.length >= 3} + 더보기 → + {/if}
+ {/if} - - + + + +
+

최근 활동

+
+ {#if summary.law_alerts > 0} + + 법령 {summary.law_alerts} + + {/if} +
+
+ + {#if summary.recent_documents.length > 0} + + {:else} + + {/if} +
+ + +
{ if (!e.currentTarget.open) pipelineManualClosed = true; }} + > + + + + 파이프라인 + + + {#if totalFailed > 0} + 실패 {totalFailed} + {/if} + {#if totalPending > 0} + 대기 {totalPending} + {/if} + {#if totalFailed === 0 && totalPending === 0} + 처리 완료 + {/if} + + + +
+ {#if pipelineRows.length > 0} +
+ {#each pipelineRows as row (row.stage)} +
+
+ {row.label} + + 대기 {row.pending} · + 처리 {row.processing} · + 실패 0 ? 'text-error' : ''}>{row.failed} + +
+
+ {#if row.pending > 0} +
+ {/if} + {#if row.processing > 0} +
+ {/if} + {#if row.failed > 0} +
+ {/if} +
+
+ {/each} +
+ {:else} +

최근 24시간 처리 작업 없음

+ {/if} +
+
+ {/if}
+ +