feat(frontend): 절 바로가기 페이지(/clause) + 사이드바 링크 — U-1 진입점
ASME 절 식별자(UG-79 등) 입력 → /api/documents/clause-lookup → 문서·위치 결과 → 읽기뷰 이동. 절은 in_corpus=false(의미검색 비활성)라 이 정확지목 진입점이 유일 경로. 사이드바(자료실 옆 'Hash 절 바로가기')로 노출. 신규 라우트라 기존 표면 미접촉. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { api } from '$lib/api';
|
||||
import { ChevronRight, ChevronDown, FolderOpen, FolderTree, Inbox, Clock, Mail, Scale, StickyNote, GraduationCap, CalendarCheck, MessageCircle } from 'lucide-svelte';
|
||||
import { ChevronRight, ChevronDown, FolderOpen, FolderTree, Inbox, Clock, Mail, Scale, StickyNote, GraduationCap, CalendarCheck, MessageCircle, Hash } from 'lucide-svelte';
|
||||
|
||||
let tree = $state([]);
|
||||
let loading = $state(true);
|
||||
@@ -195,6 +195,13 @@
|
||||
>
|
||||
<FolderTree size={14} /> 자료실
|
||||
</a>
|
||||
<a
|
||||
href="/clause"
|
||||
class="w-full flex items-center gap-2 px-3 py-1.5 rounded-md text-sm transition-colors
|
||||
{$page.url.pathname === '/clause' ? 'bg-accent/15 text-accent' : 'text-dim hover:bg-surface hover:text-text'}"
|
||||
>
|
||||
<Hash size={14} /> 절 바로가기
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- 메모 & Inbox -->
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<script>
|
||||
// 절(clause) 바로가기 — ASME 절 식별자(예: UG-79)로 크로스-doc 위치를 조회해 읽기뷰로 이동 (U-1).
|
||||
// 절은 in_corpus=false(의미검색 비활성)라 일반 검색으론 안 잡히므로 라벨 정확지목 전용 진입점.
|
||||
import { api } from '$lib/api';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
let label = $state('');
|
||||
let hits = $state([]);
|
||||
let loading = $state(false);
|
||||
let searched = $state(false);
|
||||
let error = $state('');
|
||||
|
||||
async function lookup() {
|
||||
const q = label.trim();
|
||||
if (!q) return;
|
||||
loading = true;
|
||||
error = '';
|
||||
try {
|
||||
const res = await api(`/documents/clause-lookup?label=${encodeURIComponent(q)}`);
|
||||
hits = res?.hits ?? [];
|
||||
searched = true;
|
||||
} catch (e) {
|
||||
error = '조회에 실패했습니다.';
|
||||
hits = [];
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mx-auto max-w-3xl px-6 py-10">
|
||||
<h1 class="mb-1 text-2xl font-bold text-base">절 바로가기</h1>
|
||||
<p class="mb-6 text-sm text-dim">
|
||||
ASME 절 식별자(예: <code class="text-accent">UG-79</code>, <code class="text-accent">PG-5</code>)로 문서·위치를 찾아 이동합니다.
|
||||
</p>
|
||||
|
||||
<form onsubmit={(e) => { e.preventDefault(); lookup(); }} class="mb-6 flex gap-2">
|
||||
<input
|
||||
bind:value={label}
|
||||
placeholder="절 식별자 (UG-79, PG-5.6, A-1 …)"
|
||||
autocomplete="off"
|
||||
class="flex-1 rounded-lg border border-default bg-surface px-4 py-2.5 text-base outline-none focus:border-accent"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading || !label.trim()}
|
||||
class="rounded-lg bg-accent px-5 py-2.5 font-medium text-white hover:bg-accent-hover disabled:opacity-50"
|
||||
>
|
||||
{loading ? '조회 중…' : '찾기'}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{#if error}
|
||||
<p class="text-sm text-accent">{error}</p>
|
||||
{:else if searched && hits.length === 0}
|
||||
<p class="text-sm text-dim">'{label}' 에 해당하는 절을 찾지 못했습니다. (절은 분해된 코드 문서에만 존재합니다)</p>
|
||||
{:else if hits.length > 0}
|
||||
<div class="space-y-2">
|
||||
{#if hits.length > 1}
|
||||
<p class="text-xs text-dim">{hits.length}개 문서에 존재 — 에디션/부록을 선택하세요.</p>
|
||||
{/if}
|
||||
{#each hits as hit (hit.chunk_id)}
|
||||
<button
|
||||
onclick={() => goto(`/documents/${hit.doc_id}`)}
|
||||
class="block w-full rounded-lg border border-default bg-surface px-4 py-3 text-left transition hover:border-accent hover:bg-surface-hover"
|
||||
>
|
||||
<div class="font-medium text-base">{hit.section_title}</div>
|
||||
<div class="mt-0.5 text-xs text-dim">{hit.doc_title}</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
Reference in New Issue
Block a user