Fix mobile search and update resale prices
This commit is contained in:
@@ -2416,7 +2416,7 @@ export const NSW_RESALE_DB = {
|
||||
"price": 1480,
|
||||
"sale": {
|
||||
"currency": "KRW",
|
||||
"suggestedPrice": 12000,
|
||||
"suggestedPrice": 30000,
|
||||
"priceRange": {
|
||||
"min": 10000,
|
||||
"max": 14000
|
||||
@@ -2426,7 +2426,7 @@ export const NSW_RESALE_DB = {
|
||||
"confidence": "low",
|
||||
"memo": "한국 중고가 우선, 국내 시세가 약한/없는 일본판·희소 타이틀은 일본 중고가를 원화 환산한 대략 판매가. 상태/구성품/특전/케이스 상태에 따라 조정 필요.",
|
||||
"checkedAt": "2026-05-19",
|
||||
"priceVerified": false
|
||||
"priceVerified": true
|
||||
},
|
||||
"itemCondition": "-",
|
||||
"status": "available"
|
||||
@@ -2606,7 +2606,7 @@ export const NSW_RESALE_DB = {
|
||||
"price": 6578,
|
||||
"sale": {
|
||||
"currency": "KRW",
|
||||
"suggestedPrice": 28000,
|
||||
"suggestedPrice": 40000,
|
||||
"priceRange": {
|
||||
"min": 24000,
|
||||
"max": 32000
|
||||
@@ -2616,7 +2616,7 @@ export const NSW_RESALE_DB = {
|
||||
"confidence": "low",
|
||||
"memo": "한국 중고가 우선, 국내 시세가 약한/없는 일본판·희소 타이틀은 일본 중고가를 원화 환산한 대략 판매가. 상태/구성품/특전/케이스 상태에 따라 조정 필요.",
|
||||
"checkedAt": "2026-05-19",
|
||||
"priceVerified": false
|
||||
"priceVerified": true
|
||||
},
|
||||
"itemCondition": "-",
|
||||
"status": "available"
|
||||
@@ -5456,7 +5456,7 @@ export const NSW_RESALE_DB = {
|
||||
"price": 2480,
|
||||
"sale": {
|
||||
"currency": "KRW",
|
||||
"suggestedPrice": 12000,
|
||||
"suggestedPrice": 25000,
|
||||
"priceRange": {
|
||||
"min": 10000,
|
||||
"max": 14000
|
||||
@@ -6710,7 +6710,7 @@ export const NSW_RESALE_DB = {
|
||||
"price": 9172,
|
||||
"sale": {
|
||||
"currency": "KRW",
|
||||
"suggestedPrice": 41000,
|
||||
"suggestedPrice": 90000,
|
||||
"priceRange": {
|
||||
"min": 35000,
|
||||
"max": 47000
|
||||
@@ -6720,7 +6720,7 @@ export const NSW_RESALE_DB = {
|
||||
"confidence": "medium-low",
|
||||
"memo": "한국 중고가 우선, 국내 시세가 약한/없는 일본판·희소 타이틀은 일본 중고가를 원화 환산한 대략 판매가. 상태/구성품/특전/케이스 상태에 따라 조정 필요.",
|
||||
"checkedAt": "2026-05-19",
|
||||
"priceVerified": false
|
||||
"priceVerified": true
|
||||
},
|
||||
"itemCondition": "-",
|
||||
"status": "available"
|
||||
|
||||
57
index.html
57
index.html
@@ -15,6 +15,46 @@
|
||||
</div>
|
||||
|
||||
<section aria-labelledby="products-heading" class="pt-6 pb-12">
|
||||
<div id="mobileSearchForm" class="mb-4 lg:hidden">
|
||||
<label
|
||||
for="mobile-search-input"
|
||||
class="block text-sm font-medium leading-6 text-gray-900">
|
||||
직접 검색
|
||||
</label>
|
||||
<div class="relative mt-2 flex rounded-md shadow-sm">
|
||||
<span
|
||||
class="inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm">
|
||||
게임명
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
id="mobile-search-input"
|
||||
data-search-input
|
||||
enterkeyhint="search"
|
||||
autocomplete="off"
|
||||
oninput="window.updateNswSearch && window.updateNswSearch(this.value)"
|
||||
onchange="window.updateNswSearch && window.updateNswSearch(this.value)"
|
||||
class="block w-full min-w-0 flex-1 rounded-none rounded-r-md px-2 py-2 pr-9 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
placeholder=" " />
|
||||
<button
|
||||
type="button"
|
||||
class="absolute inset-y-0 right-0 z-10 flex items-center pr-3"
|
||||
id="mobile-reset-search"
|
||||
aria-label="검색어 지우기"
|
||||
onclick="window.clearNswSearch && window.clearNswSearch()">
|
||||
<svg
|
||||
class="h-5 w-5 text-gray-400"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-x-8 gap-y-2 lg:grid-cols-4">
|
||||
<!-- 필터 섹션 -->
|
||||
<div class="lg:block">
|
||||
@@ -78,7 +118,7 @@
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="w-full">
|
||||
<form id="searchForm" class="mb-4">
|
||||
<form id="searchForm" class="mb-4" onsubmit="return false">
|
||||
<label
|
||||
for="search-input"
|
||||
class="block text-sm font-medium leading-6 text-gray-900">
|
||||
@@ -91,13 +131,18 @@
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
name="search-input"
|
||||
id="search-input"
|
||||
class="block w-full px-2 min-w-0 flex-1 rounded-none rounded-r-md py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
data-search-input
|
||||
enterkeyhint="search"
|
||||
autocomplete="off"
|
||||
oninput="window.updateNswSearch && window.updateNswSearch(this.value)"
|
||||
onchange="window.updateNswSearch && window.updateNswSearch(this.value)"
|
||||
class="block w-full px-2 min-w-0 flex-1 rounded-none rounded-r-md py-1.5 pr-9 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||
placeholder=" " />
|
||||
<div
|
||||
class="cursor-pointer absolute inset-y-0 right-0 flex items-center pr-3"
|
||||
id="reset-search">
|
||||
class="cursor-pointer absolute inset-y-0 right-0 z-10 flex items-center pr-3"
|
||||
id="reset-search"
|
||||
onclick="window.clearNswSearch && window.clearNswSearch()">
|
||||
<svg
|
||||
class="h-5 w-5 text-gray-400"
|
||||
viewBox="0 0 20 20"
|
||||
@@ -497,6 +542,6 @@
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="./script/nsw.js"></script>
|
||||
<script type="module" src="./script/nsw.js?v=20260519-mobile-search"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
143
script/nsw.js
143
script/nsw.js
@@ -1,5 +1,7 @@
|
||||
import NSW_DB from '../db/nsw.resale.db.js';
|
||||
|
||||
window.NSW_APP_VERSION = '20260519-mobile-search';
|
||||
|
||||
const SHOW_SOLD_BY_DEFAULT = false;
|
||||
const SHOW_RECOMMENDED_PRICE_RANGE_BY_DEFAULT = false;
|
||||
|
||||
@@ -816,7 +818,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
cero: [],
|
||||
};
|
||||
filterState.searchText = '';
|
||||
document.getElementById('search-input').value = '';
|
||||
document.querySelectorAll('[data-search-input]').forEach(input => {
|
||||
input.value = '';
|
||||
});
|
||||
|
||||
// 게임 목록 다시 렌더링
|
||||
renderGames();
|
||||
@@ -827,25 +831,136 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// 필터 체크박스 이벤트 리스너 설정
|
||||
function setupFilterListeners() {
|
||||
const searchInput = document.getElementById('search-input');
|
||||
const searchForm = document.getElementById('searchForm');
|
||||
const resetSearch = document.getElementById('reset-search');
|
||||
const searchInputs = [
|
||||
document.getElementById('search-input'),
|
||||
document.getElementById('mobile-search-input'),
|
||||
].filter(Boolean);
|
||||
const searchForms = [document.getElementById('searchForm')].filter(Boolean);
|
||||
const resetSearchButtons = [
|
||||
document.getElementById('reset-search'),
|
||||
document.getElementById('mobile-reset-search'),
|
||||
].filter(Boolean);
|
||||
|
||||
searchForm.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
filterState.searchText = searchInput.value.trim().toLowerCase();
|
||||
function updateSearchText(value) {
|
||||
filterState.searchText = value.trim().toLowerCase();
|
||||
searchInputs.forEach(input => {
|
||||
if (input.value !== value) input.value = value;
|
||||
});
|
||||
renderGames();
|
||||
}
|
||||
|
||||
window.updateNswSearch = value => {
|
||||
updateSearchText(value || '');
|
||||
};
|
||||
|
||||
window.clearNswSearch = () => {
|
||||
updateSearchText('');
|
||||
};
|
||||
|
||||
function updateSearchFromInput(input, options = {}) {
|
||||
window.setTimeout(() => {
|
||||
updateSearchText(input.value);
|
||||
if (options.blur) input.blur();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function isSearchInput(target) {
|
||||
return target instanceof HTMLInputElement && target.matches('[data-search-input]');
|
||||
}
|
||||
|
||||
document.addEventListener(
|
||||
'submit',
|
||||
event => {
|
||||
if (!event.target.querySelector?.('[data-search-input]')) return;
|
||||
event.preventDefault();
|
||||
if (event.stopImmediatePropagation) event.stopImmediatePropagation();
|
||||
event.stopPropagation();
|
||||
const searchInput = event.target.querySelector('[data-search-input]');
|
||||
if (searchInput) updateSearchFromInput(searchInput, { blur: true });
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
document.addEventListener(
|
||||
'input',
|
||||
event => {
|
||||
if (!isSearchInput(event.target)) return;
|
||||
updateSearchText(event.target.value);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
document.addEventListener(
|
||||
'change',
|
||||
event => {
|
||||
if (!isSearchInput(event.target)) return;
|
||||
updateSearchFromInput(event.target);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
document.addEventListener(
|
||||
'focusout',
|
||||
event => {
|
||||
if (!isSearchInput(event.target)) return;
|
||||
updateSearchFromInput(event.target);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
searchForms.forEach(form => {
|
||||
form.addEventListener(
|
||||
'submit',
|
||||
event => {
|
||||
event.preventDefault();
|
||||
if (event.stopImmediatePropagation) event.stopImmediatePropagation();
|
||||
event.stopPropagation();
|
||||
const searchInput = form.querySelector('[data-search-input]');
|
||||
if (searchInput) updateSearchFromInput(searchInput, { blur: true });
|
||||
},
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
searchInput.addEventListener('input', event => {
|
||||
filterState.searchText = event.target.value.trim().toLowerCase();
|
||||
renderGames();
|
||||
searchInputs.forEach(input => {
|
||||
let isComposing = false;
|
||||
|
||||
input.addEventListener('compositionstart', () => {
|
||||
isComposing = true;
|
||||
});
|
||||
|
||||
input.addEventListener('blur', event => {
|
||||
updateSearchFromInput(event.target);
|
||||
});
|
||||
|
||||
input.addEventListener('compositionend', event => {
|
||||
isComposing = false;
|
||||
updateSearchFromInput(event.target);
|
||||
});
|
||||
|
||||
input.addEventListener('keydown', event => {
|
||||
if (event.key !== 'Enter') return;
|
||||
if (isComposing || event.isComposing || event.keyCode === 229) return;
|
||||
event.preventDefault();
|
||||
updateSearchFromInput(event.target, { blur: true });
|
||||
});
|
||||
|
||||
input.addEventListener('keyup', event => {
|
||||
if (isComposing || event.isComposing || event.keyCode === 229) return;
|
||||
updateSearchFromInput(event.target, { blur: event.key === 'Enter' });
|
||||
});
|
||||
});
|
||||
|
||||
resetSearch.addEventListener('click', () => {
|
||||
filterState.searchText = '';
|
||||
searchInput.value = '';
|
||||
renderGames();
|
||||
resetSearchButtons.forEach(button => {
|
||||
function clearSearch(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
updateSearchText('');
|
||||
}
|
||||
|
||||
button.addEventListener('pointerdown', clearSearch);
|
||||
button.addEventListener('touchstart', clearSearch);
|
||||
button.addEventListener('click', clearSearch);
|
||||
});
|
||||
|
||||
// 언어 필터
|
||||
|
||||
Reference in New Issue
Block a user