From 1a2b3b49af82c57cc24e4608ec754a8df3ebf136 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Fri, 3 Apr 2026 09:00:20 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=EB=B0=94=EB=A5=BC=20=EC=A0=84=EC=97=AD=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - +layout.svelte: 사이드바 + 상단 nav 통합 (로그인/셋업 제외) - 각 페이지 중복 nav 제거 (dashboard, documents, detail, inbox, settings) - 모바일 drawer + ESC 닫기 전역 처리 Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/routes/+layout.svelte | 77 ++++- frontend/src/routes/+page.svelte | 24 +- frontend/src/routes/documents/+page.svelte | 265 +++++++----------- .../src/routes/documents/[id]/+page.svelte | 15 +- frontend/src/routes/inbox/+page.svelte | 12 +- frontend/src/routes/settings/+page.svelte | 10 +- 6 files changed, 191 insertions(+), 212 deletions(-) diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 7bffba7..87881eb 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -3,12 +3,15 @@ import { browser } from '$app/environment'; import { page } from '$app/stores'; import { goto } from '$app/navigation'; - import { isAuthenticated, tryRefresh, logout } from '$lib/stores/auth'; + import { isAuthenticated, user, tryRefresh, logout } from '$lib/stores/auth'; import { toasts, removeToast } from '$lib/stores/ui'; + import Sidebar from '$lib/components/Sidebar.svelte'; import '../app.css'; const PUBLIC_PATHS = ['/login', '/setup']; + const NO_SIDEBAR_PATHS = ['/login', '/setup']; let authChecked = false; + let sidebarOpen = $state(false); onMount(async () => { if (!$isAuthenticated) { @@ -23,12 +26,18 @@ } } + // 사이드바 표시 여부 + $: showSidebar = $isAuthenticated && !NO_SIDEBAR_PATHS.some(p => $page.url.pathname.startsWith(p)); + // 키보드 단축키 function handleKeydown(e) { if (e.key === '/' && !['INPUT', 'TEXTAREA'].includes(document.activeElement?.tagName)) { e.preventDefault(); document.querySelector('[data-search-input]')?.focus(); } + if (e.key === 'Escape' && sidebarOpen) { + sidebarOpen = false; + } } @@ -39,14 +48,71 @@

로딩 중...

{:else if $isAuthenticated || PUBLIC_PATHS.some(p => $page.url.pathname.startsWith(p))} - + {#if showSidebar} +
+ + + + +
+ + + + + {#if sidebarOpen} +
+ +
+ +
+
+ {/if} + + +
+ +
+
+
+ {:else} + + {/if} {/if}
{#each $toasts as toast (toast.id)} - + {/each}
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 3af6740..ea2f3a6 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -2,8 +2,7 @@ import { onMount } from 'svelte'; import { goto } from '$app/navigation'; import { api } from '$lib/api'; - import { isAuthenticated, user, logout } from '$lib/stores/auth'; - import { sidebarOpen, addToast } from '$lib/stores/ui'; + import { addToast } from '$lib/stores/ui'; let dashboard = null; let loading = true; @@ -19,25 +18,8 @@ }); -
- - - - -
+
+

대시보드

{#if loading} diff --git a/frontend/src/routes/documents/+page.svelte b/frontend/src/routes/documents/+page.svelte index 3310e59..3ff06fb 100644 --- a/frontend/src/routes/documents/+page.svelte +++ b/frontend/src/routes/documents/+page.svelte @@ -3,7 +3,6 @@ import { goto } from '$app/navigation'; import { api } from '$lib/api'; import { addToast } from '$lib/stores/ui'; - import Sidebar from '$lib/components/Sidebar.svelte'; let documents = $state([]); let total = $state(0); @@ -12,7 +11,6 @@ let searchMode = $state('hybrid'); let searchResults = $state(null); let debounceTimer; - let sidebarOpen = $state(true); // URL params → filter (source of truth) let currentPage = $derived(parseInt($page.url.searchParams.get('page') || '1')); @@ -21,7 +19,6 @@ // URL 변경 시 데이터 재로딩 $effect(() => { - // derived 값을 읽어서 반응성 트리거 const _p = currentPage; const _d = filterDomain; const _s = filterSubGroup; @@ -73,7 +70,6 @@ } else { params.delete('mode'); } - // 빈 값 정규화 for (const [key, val] of [...params.entries()]) { if (!val) params.delete(key); } @@ -115,37 +111,42 @@ let totalPages = $derived(Math.ceil(total / 20)); let items = $derived(searchResults || documents); let hasActiveFilters = $derived(!!filterDomain || !!filterSubGroup || !!searchQuery); - - // 활성 필터 라벨 - let filterLabel = $derived(() => { - const parts = []; - if (filterDomain) parts.push(filterDomain.replace('Knowledge/', '')); - if (filterSubGroup) parts.push(filterSubGroup); - return parts.join(' / '); - }); -
- - + {/if} - -
- - diff --git a/frontend/src/routes/documents/[id]/+page.svelte b/frontend/src/routes/documents/[id]/+page.svelte index c769218..f9a01a9 100644 --- a/frontend/src/routes/documents/[id]/+page.svelte +++ b/frontend/src/routes/documents/[id]/+page.svelte @@ -33,14 +33,13 @@ } -
- +
+ +
+ 문서 + / + {doc?.title || '로딩...'} +
{#if loading}
diff --git a/frontend/src/routes/inbox/+page.svelte b/frontend/src/routes/inbox/+page.svelte index eaf1ac2..74883b5 100644 --- a/frontend/src/routes/inbox/+page.svelte +++ b/frontend/src/routes/inbox/+page.svelte @@ -97,12 +97,10 @@ ]; -
- +
{#if loading} diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte index 6adf2cf..19ec2b3 100644 --- a/frontend/src/routes/settings/+page.svelte +++ b/frontend/src/routes/settings/+page.svelte @@ -39,14 +39,8 @@ } -
- - -
+
+

계정 정보