Files
document-server/frontend/book-editor.html
Hyungi Ahn e983d01a83 Fix: PDF 매칭 드롭다운 값 바인딩 문제 해결
- Alpine.js에서 :value="null"이 문자열로 변환되는 문제 수정
- option value를 빈 문자열("")로 변경
- JavaScript에서 null 값을 빈 문자열로 변환하여 UI 바인딩 개선
- 저장 시 빈 문자열과 null 모두 처리하도록 수정
2025-09-03 18:35:50 +09:00

200 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>서적 편집 - Document Server</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
<style>
.sortable-ghost {
opacity: 0.4;
}
.sortable-chosen {
background-color: #f3f4f6;
}
.sortable-drag {
background-color: white;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
</style>
</head>
<body class="bg-gray-50 min-h-screen" x-data="bookEditorApp()">
<!-- 헤더 -->
<div id="header-container"></div>
<!-- 메인 컨텐츠 -->
<main class="container mx-auto px-4 py-8">
<!-- 헤더 섹션 -->
<div class="mb-8">
<div class="flex items-center justify-between mb-4">
<button @click="goBack()"
class="flex items-center px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-lg transition-colors">
<i class="fas fa-arrow-left mr-2"></i>서적으로 돌아가기
</button>
<button @click="saveChanges()"
:disabled="saving"
class="flex items-center px-6 py-2 bg-green-600 hover:bg-green-700 disabled:bg-gray-400 text-white rounded-lg transition-colors">
<i class="fas fa-save mr-2"></i>
<span x-text="saving ? '저장 중...' : '변경사항 저장'"></span>
</button>
</div>
<div class="bg-white rounded-lg shadow-sm border p-6">
<div class="flex items-center mb-4">
<div class="w-16 h-16 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-lg flex items-center justify-center mr-6">
<i class="fas fa-book text-white text-2xl"></i>
</div>
<div>
<h1 class="text-2xl font-bold text-gray-900" x-text="bookInfo.title"></h1>
<p class="text-gray-600 mt-1" x-show="bookInfo.author" x-text="bookInfo.author"></p>
<p class="text-sm text-gray-500 mt-2">
<span x-text="documents.length"></span>개 문서 편집
</p>
</div>
</div>
</div>
</div>
<!-- 로딩 상태 -->
<div x-show="loading" class="text-center py-12">
<i class="fas fa-spinner fa-spin text-3xl text-gray-400 mb-4"></i>
<p class="text-gray-500">데이터를 불러오는 중...</p>
</div>
<!-- 편집 섹션 -->
<div x-show="!loading" class="space-y-8">
<!-- 서적 정보 편집 -->
<div class="bg-white rounded-lg shadow-sm border">
<div class="p-6 border-b border-gray-200">
<h2 class="text-lg font-semibold text-gray-900 flex items-center">
<i class="fas fa-info-circle mr-2 text-blue-600"></i>
서적 정보
</h2>
</div>
<div class="p-6 space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">서적 제목</label>
<input type="text"
x-model="bookInfo.title"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">저자</label>
<input type="text"
x-model="bookInfo.author"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">설명</label>
<textarea x-model="bookInfo.description"
rows="3"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"></textarea>
</div>
</div>
</div>
<!-- 문서 순서 및 PDF 매칭 편집 -->
<div class="bg-white rounded-lg shadow-sm border">
<div class="p-6 border-b border-gray-200">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold text-gray-900 flex items-center">
<i class="fas fa-list-ol mr-2 text-green-600"></i>
문서 순서 및 PDF 매칭
</h2>
<div class="flex space-x-2">
<button @click="autoSortByName()"
class="px-3 py-1.5 bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors text-sm">
<i class="fas fa-sort-alpha-down mr-1"></i>이름순 정렬
</button>
<button @click="reverseOrder()"
class="px-3 py-1.5 bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 transition-colors text-sm">
<i class="fas fa-exchange-alt mr-1"></i>순서 뒤집기
</button>
</div>
</div>
</div>
<div class="p-6">
<div id="sortable-list" class="space-y-3">
<template x-for="(doc, index) in documents" :key="doc.id">
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 cursor-move hover:bg-gray-100 transition-colors"
:data-id="doc.id">
<div class="flex items-center justify-between">
<div class="flex items-center flex-1">
<!-- 드래그 핸들 -->
<div class="mr-4 text-gray-400">
<i class="fas fa-grip-vertical"></i>
</div>
<!-- 순서 번호 -->
<div class="w-8 h-8 bg-blue-600 text-white rounded-full flex items-center justify-center text-sm font-medium mr-4">
<span x-text="index + 1"></span>
</div>
<!-- 문서 정보 -->
<div class="flex-1">
<h3 class="font-medium text-gray-900" x-text="doc.title"></h3>
<p class="text-sm text-gray-500" x-text="doc.description || '설명 없음'"></p>
</div>
</div>
<!-- PDF 매칭 및 컨트롤 -->
<div class="flex items-center space-x-3">
<!-- PDF 매칭 드롭다운 -->
<div class="min-w-48 relative">
<select x-model="doc.matched_pdf_id"
:class="doc.matched_pdf_id ? 'border-green-300 bg-green-50' : 'border-gray-300'"
class="w-full px-3 py-2 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm">
<option value="">PDF 매칭 없음</option>
<template x-for="pdf in availablePDFs" :key="pdf.id">
<option :value="pdf.id" x-text="pdf.title"></option>
</template>
</select>
<!-- 매칭 상태 표시 -->
<div x-show="doc.matched_pdf_id" class="absolute -top-1 -right-1">
<div class="w-3 h-3 bg-green-500 rounded-full border-2 border-white"></div>
</div>
</div>
<!-- 이동 버튼 -->
<div class="flex flex-col space-y-1">
<button @click="moveUp(index)"
:disabled="index === 0"
class="p-1 text-gray-400 hover:text-blue-600 disabled:opacity-30 disabled:cursor-not-allowed">
<i class="fas fa-chevron-up text-xs"></i>
</button>
<button @click="moveDown(index)"
:disabled="index === documents.length - 1"
class="p-1 text-gray-400 hover:text-blue-600 disabled:opacity-30 disabled:cursor-not-allowed">
<i class="fas fa-chevron-down text-xs"></i>
</button>
</div>
</div>
</div>
</div>
</template>
</div>
<!-- 빈 상태 -->
<div x-show="documents.length === 0" class="text-center py-8">
<i class="fas fa-file-alt text-gray-400 text-3xl mb-4"></i>
<p class="text-gray-500">편집할 문서가 없습니다</p>
</div>
</div>
</div>
</div>
</main>
<!-- JavaScript 파일들 -->
<script src="/static/js/api.js?v=2025012384"></script>
<script src="/static/js/auth.js?v=2025012351"></script>
<script src="/static/js/header-loader.js?v=2025012351"></script>
<script src="/static/js/book-editor.js?v=2025012461"></script>
</body>
</html>