fix(purchase): 네비 명칭/권한 수정 + 검색 재선택 가능하도록 개선

- 네비: '소모품 관리' → '소모품 구매 관리'(admin only), 일반 사용자는 '소모품 신청'만 표시
- 권한: purchase.request_mobile → purchase.request alias 등록 (비관리자 접근 가능)
- 검색: 품목 선택 후 다시 입력하면 이전 선택 자동 해제 (데스크탑+모바일)
- 모바일: selectSearchItem에서 불필요한 API 재호출 제거, 로컬 캐시 활용

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-04-01 09:50:15 +09:00
parent 798cc38945
commit dcd40e692f
5 changed files with 37 additions and 23 deletions

View File

@@ -6,8 +6,8 @@
<title>소모품 신청 - TK 공장관리</title> <title>소모품 신청 - TK 공장관리</title>
<script src="https://cdn.tailwindcss.com"></script> <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="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="/static/css/tkfb.css?v=2026040101"> <link rel="stylesheet" href="/static/css/tkfb.css?v=2026040102">
<link rel="stylesheet" href="/css/purchase-mobile.css?v=2026040101"> <link rel="stylesheet" href="/css/purchase-mobile.css?v=2026040102">
<script src="https://cdn.jsdelivr.net/npm/heic2any@0.0.4/dist/heic2any.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/heic2any@0.0.4/dist/heic2any.min.js"></script>
</head> </head>
<body class="bg-gray-50"> <body class="bg-gray-50">
@@ -140,8 +140,8 @@
<div class="pm-sheet-body" id="detailContent"></div> <div class="pm-sheet-body" id="detailContent"></div>
</div> </div>
<script src="/static/js/tkfb-core.js?v=2026040101"></script> <script src="/static/js/tkfb-core.js?v=2026040102"></script>
<script src="/static/js/purchase-request-mobile.js?v=2026040101"></script> <script src="/static/js/purchase-request-mobile.js?v=2026040102"></script>
<script src="/static/js/shared-bottom-nav.js?v=2026040101"></script> <script src="/static/js/shared-bottom-nav.js?v=2026040102"></script>
</body> </body>
</html> </html>

View File

@@ -310,7 +310,7 @@
</div> </div>
</div> </div>
</div> </div>
<script src="/static/js/tkfb-core.js?v=2026040101"></script> <script src="/static/js/tkfb-core.js?v=2026040102"></script>
<script src="/static/js/purchase-request.js?v=2026040101"></script> <script src="/static/js/purchase-request.js?v=2026040102"></script>
</body> </body>
</html> </html>

View File

@@ -191,6 +191,14 @@ document.addEventListener('DOMContentLoaded', () => {
const input = document.getElementById('searchInput'); const input = document.getElementById('searchInput');
input.addEventListener('input', () => { input.addEventListener('input', () => {
clearTimeout(searchTimer); clearTimeout(searchTimer);
// 검색어 입력 시 이전 선택 자동 해제
if (document.getElementById('selectedItemId').value || document.getElementById('selectedCustomName').value) {
document.getElementById('selectedItemWrap').classList.add('hidden');
document.getElementById('selectedItemId').value = '';
document.getElementById('selectedCustomName').value = '';
document.getElementById('newItemForm').classList.add('hidden');
isRegisterMode = false;
}
const q = input.value.trim(); const q = input.value.trim();
if (q.length === 0) { if (q.length === 0) {
document.getElementById('searchResults').classList.remove('open'); document.getElementById('searchResults').classList.remove('open');
@@ -212,6 +220,7 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
function renderSearchResults(items, query) { function renderSearchResults(items, query) {
lastSearchResults = items;
const container = document.getElementById('searchResults'); const container = document.getElementById('searchResults');
let html = ''; let html = '';
@@ -240,13 +249,10 @@ function renderSearchResults(items, query) {
} }
/* ===== 품목 선택 ===== */ /* ===== 품목 선택 ===== */
let searchItemsCache = []; let lastSearchResults = [];
function selectSearchItem(itemId) { function selectSearchItem(itemId) {
// API 검색 결과에서 선택 — searchResults에서 데이터 가져오기 const item = lastSearchResults.find(i => i.item_id === itemId);
api('/purchase-requests/search?q=' + encodeURIComponent(document.getElementById('searchInput').value.trim()))
.then(res => {
const item = (res.data || []).find(i => i.item_id === itemId);
if (!item) return; if (!item) return;
document.getElementById('selectedItemId').value = item.item_id; document.getElementById('selectedItemId').value = item.item_id;
document.getElementById('selectedCustomName').value = ''; document.getElementById('selectedCustomName').value = '';
@@ -254,9 +260,9 @@ function selectSearchItem(itemId) {
document.getElementById('selectedItemMeta').textContent = (CAT_LABELS[item.category] || '') + (item.base_price ? ' · ' + Number(item.base_price).toLocaleString() + '원' : ''); document.getElementById('selectedItemMeta').textContent = (CAT_LABELS[item.category] || '') + (item.base_price ? ' · ' + Number(item.base_price).toLocaleString() + '원' : '');
document.getElementById('selectedItemWrap').classList.remove('hidden'); document.getElementById('selectedItemWrap').classList.remove('hidden');
document.getElementById('searchResults').classList.remove('open'); document.getElementById('searchResults').classList.remove('open');
document.getElementById('searchInput').value = '';
document.getElementById('newItemForm').classList.add('hidden'); document.getElementById('newItemForm').classList.add('hidden');
isRegisterMode = false; isRegisterMode = false;
});
} }
function selectNewItem() { function selectNewItem() {

View File

@@ -51,6 +51,13 @@ function initItemSearch() {
input.addEventListener('input', () => { input.addEventListener('input', () => {
clearTimeout(searchDebounceTimer); clearTimeout(searchDebounceTimer);
// 검색어 변경 시 이전 선택 자동 해제
if (document.getElementById('prItemId').value) {
document.getElementById('prItemId').value = '';
document.getElementById('prCustomItemName').value = '';
document.getElementById('prItemPreview').classList.add('hidden');
document.getElementById('prCustomCategoryWrap').classList.add('hidden');
}
searchDebounceTimer = setTimeout(() => { searchDebounceTimer = setTimeout(() => {
const query = input.value.trim(); const query = input.value.trim();
if (query.length === 0) { if (query.length === 0) {

View File

@@ -134,7 +134,7 @@ const NAV_MENU = [
]}, ]},
{ cat: '소모품 관리', items: [ { cat: '소모품 관리', items: [
{ href: '/pages/purchase/request-mobile.html', icon: 'fa-shopping-cart', label: '소모품 신청', key: 'purchase.request_mobile' }, { href: '/pages/purchase/request-mobile.html', icon: 'fa-shopping-cart', label: '소모품 신청', key: 'purchase.request_mobile' },
{ href: '/pages/purchase/request.html', icon: 'fa-clipboard-list', label: '소모품 관리', key: 'purchase.request' }, { href: '/pages/purchase/request.html', icon: 'fa-clipboard-list', label: '소모품 구매 관리', key: 'purchase.request', admin: true },
{ href: '/pages/admin/purchase-analysis.html', icon: 'fa-chart-line', label: '소모품 분석', key: 'purchase.analysis', admin: true }, { href: '/pages/admin/purchase-analysis.html', icon: 'fa-chart-line', label: '소모품 분석', key: 'purchase.analysis', admin: true },
]}, ]},
{ cat: '근태 관리', items: [ { cat: '근태 관리', items: [
@@ -170,6 +170,7 @@ const PAGE_KEY_ALIASES = {
'attendance.work_status': 'inspection.work_status', 'attendance.work_status': 'inspection.work_status',
'work.meeting_detail': 'work.meetings', 'work.meeting_detail': 'work.meetings',
'work.proxy_input': 'work.daily_status', 'work.proxy_input': 'work.daily_status',
'purchase.request_mobile': 'purchase.request',
}; };
function _getCurrentPageKey() { function _getCurrentPageKey() {