feat(purchase): 구매신청 검색/직접입력/사진첨부/HEIC 지원/마스터 자동등록
- 소모품 select → 검색형 드롭다운 (debounce + 키보드 탐색) - 미등록 품목 직접 입력 + 분류 선택 지원 - 사진 첨부 (base64 업로드, HEIC→JPEG 프론트 변환) - 구매 처리 시 미등록 품목 소모품 마스터 자동 등록 - item_id NULL 허용, LEFT JOIN, custom_item_name/custom_category/photo_path 컬럼 - DB 마이그레이션 필요: ALTER TABLE purchase_requests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,18 @@
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="/static/css/tkfb.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/heic2any@0.0.4/dist/heic2any.min.js"></script>
|
||||
<style>
|
||||
.item-dropdown { position: absolute; top: 100%; left: 0; right: 0; max-height: 280px; overflow-y: auto; background: white; border: 1px solid #e5e7eb; border-top: none; border-radius: 0 0 8px 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); z-index: 20; display: none; }
|
||||
.item-dropdown.open { display: block; }
|
||||
.item-dropdown-item { padding: 8px 12px; cursor: pointer; font-size: 14px; display: flex; align-items: center; gap: 8px; }
|
||||
.item-dropdown-item:hover, .item-dropdown-item.active { background: #fff7ed; }
|
||||
.item-dropdown-item .cat-tag { font-size: 11px; padding: 1px 6px; border-radius: 4px; white-space: nowrap; }
|
||||
.item-dropdown-custom { padding: 10px 12px; cursor: pointer; font-size: 14px; color: #ea580c; border-top: 1px solid #f3f4f6; display: flex; align-items: center; gap: 6px; }
|
||||
.item-dropdown-custom:hover { background: #fff7ed; }
|
||||
.photo-preview-container { position: relative; display: inline-block; }
|
||||
.photo-preview-container .remove-btn { position: absolute; top: -6px; right: -6px; width: 20px; height: 20px; border-radius: 50%; background: #ef4444; color: white; border: none; cursor: pointer; font-size: 11px; display: flex; align-items: center; justify-content: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50">
|
||||
<header class="bg-orange-700 text-white sticky top-0 z-50">
|
||||
@@ -41,12 +53,13 @@
|
||||
<!-- 구매신청 폼 -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-5 mb-6">
|
||||
<h2 class="text-base font-semibold text-gray-800 mb-4"><i class="fas fa-plus-circle text-orange-500 mr-2"></i>신규 구매신청</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-4 gap-4 items-end">
|
||||
<div class="sm:col-span-2">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-4 gap-4 items-start">
|
||||
<div class="sm:col-span-2 relative">
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">소모품 <span class="text-red-400">*</span></label>
|
||||
<select id="prItemSelect" class="w-full px-3 py-2 border rounded-lg text-sm focus:ring-2 focus:ring-orange-300" onchange="onItemSelect()">
|
||||
<option value="">소모품 선택</option>
|
||||
</select>
|
||||
<input type="text" id="prItemSearch" class="w-full px-3 py-2 border rounded-lg text-sm focus:ring-2 focus:ring-orange-300" placeholder="소모품 검색 또는 직접 입력" autocomplete="off">
|
||||
<input type="hidden" id="prItemId" value="">
|
||||
<input type="hidden" id="prCustomItemName" value="">
|
||||
<div id="prItemDropdown" class="item-dropdown"></div>
|
||||
<div id="prItemPreview" class="mt-2 hidden flex items-center gap-3 p-2 bg-gray-50 rounded-lg">
|
||||
<img id="prItemPhoto" class="w-12 h-12 rounded object-cover hidden">
|
||||
<div>
|
||||
@@ -54,6 +67,16 @@
|
||||
<div id="prItemPrice" class="text-xs text-gray-500"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 직접 입력 시 분류 선택 -->
|
||||
<div id="prCustomCategoryWrap" class="mt-2 hidden">
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">분류 <span class="text-red-400">*</span></label>
|
||||
<select id="prCustomCategory" class="w-full px-3 py-2 border rounded-lg text-sm">
|
||||
<option value="consumable">소모품</option>
|
||||
<option value="safety">안전용품</option>
|
||||
<option value="repair">수선비</option>
|
||||
<option value="equipment">설비</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">수량 <span class="text-red-400">*</span></label>
|
||||
@@ -64,6 +87,21 @@
|
||||
<input type="text" id="prNotes" class="w-full px-3 py-2 border rounded-lg text-sm" placeholder="선택 사항">
|
||||
</div>
|
||||
</div>
|
||||
<!-- 사진 첨부 -->
|
||||
<div class="mt-3">
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">사진 첨부 (선택)</label>
|
||||
<div class="flex items-center gap-3">
|
||||
<label class="px-3 py-2 border rounded-lg text-sm text-gray-600 cursor-pointer hover:bg-gray-50 inline-flex items-center gap-1">
|
||||
<i class="fas fa-camera text-orange-400"></i> 사진 선택
|
||||
<input type="file" id="prPhotoInput" accept="image/*,.heic,.heif" class="hidden" onchange="onPhotoSelected(this)">
|
||||
</label>
|
||||
<div id="prPhotoPreview" class="hidden photo-preview-container">
|
||||
<img id="prPhotoPreviewImg" class="w-16 h-16 rounded object-cover">
|
||||
<button class="remove-btn" onclick="removePhoto()" title="삭제">×</button>
|
||||
</div>
|
||||
<span id="prPhotoStatus" class="text-xs text-gray-400"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 flex justify-end">
|
||||
<button onclick="submitPurchaseRequest()" class="px-5 py-2 bg-orange-600 text-white rounded-lg text-sm hover:bg-orange-700">
|
||||
<i class="fas fa-paper-plane mr-1"></i>구매신청
|
||||
@@ -140,7 +178,15 @@
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">수량</label>
|
||||
<input type="number" id="pmQuantity" class="w-full px-3 py-2 border rounded-lg text-sm" min="1" value="1">
|
||||
</div>
|
||||
<div class="col-span-2" id="pmPriceDiffArea" class="hidden">
|
||||
<div class="col-span-2" id="pmPriceDiffArea">
|
||||
</div>
|
||||
<!-- 마스터 등록 체크박스 (미등록 품목일 때만 표시) -->
|
||||
<div class="col-span-2 hidden" id="pmMasterRegisterWrap">
|
||||
<label class="flex items-center gap-2 cursor-pointer p-2 bg-orange-50 rounded-lg">
|
||||
<input type="checkbox" id="pmRegisterToMaster" checked class="h-4 w-4 rounded text-orange-600">
|
||||
<span class="text-sm text-gray-700">소모품 마스터에 등록</span>
|
||||
<span class="text-xs text-gray-400">(구매 처리 시 자동 등록)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
<label class="block text-xs font-medium text-gray-600 mb-1">메모</label>
|
||||
@@ -175,7 +221,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/tkfb-core.js?v=20260313"></script>
|
||||
<script src="/static/js/purchase-request.js?v=20260313"></script>
|
||||
<script src="/static/js/tkfb-core.js?v=20260313b"></script>
|
||||
<script src="/static/js/purchase-request.js?v=20260313b"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user