Update resale pricing data
This commit is contained in:
9341
db/nsw.db.js
9341
db/nsw.db.js
File diff suppressed because it is too large
Load Diff
3463
db/nsw.resale.db.js
3463
db/nsw.resale.db.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -43,10 +43,8 @@
|
||||
- `country` (string): `KOR` | `JPN`
|
||||
- `cero` (string|null): CERO 등급
|
||||
- `sale` (object):
|
||||
- `suggestedPrice` (number): 추천 판매가(KRW)
|
||||
- `priceRange` (object): `{ min, max }`
|
||||
- `pricingBasis`, `confidence`, `checkedAt`, `memo` 등
|
||||
- `priceVerified` (boolean): 실제 시세 확인 완료 여부. `true`이면 목록·상세 제목 앞 노란 별 표시
|
||||
- `currency` (string): `KRW`
|
||||
- `suggestedPrice` (`number` | `"none"`): 수기 입력된 판매가(KRW). 미입력 항목은 `"none"`.
|
||||
|
||||
## 필터/정렬 동작
|
||||
- 필터:
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
- 레거시 페이지/리소스(아미보, 세일 관련) 제거 후 문서와 실제 구조 정합성 점검이 필요하다.
|
||||
|
||||
## 다음 작업
|
||||
- `sale.priceVerified: true` 및 `itemCondition` 값을 타이틀별로 실제 데이터에 맞게 채운다.
|
||||
- `sale.suggestedPrice`를 타이틀별로 수기 확인해 숫자 가격으로 순차 입력한다.
|
||||
- `itemCondition` 값을 타이틀별로 실제 데이터에 맞게 채운다.
|
||||
- 목록/상세 페이지의 경로 및 텍스트 다국어 키를 재검증한다.
|
||||
- 필터 조합(언어+상태+국가+CERO) 테스트 케이스를 작성한다.
|
||||
- 데이터 스키마 검증 스크립트를 추가해 누락 필드와 오탈자를 자동 확인한다.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 작업 이력
|
||||
|
||||
## v2026.05.21-01
|
||||
- `db/nsw.resale.db.js` 기존 추정 판매가·가격 근거 필드를 제거하고 `sale.suggestedPrice: "none"` 상태로 초기화
|
||||
- `script/nsw.js`, `script/nsw-detail.js` 가격 미입력 항목에 “가격은 순차적으로 작성중입니다.” 안내 표시
|
||||
- 가격 정렬 시 숫자 가격이 있는 항목만 우선 정렬하고 미입력 항목은 뒤로 배치
|
||||
|
||||
## v2026.05.19-02
|
||||
- `script/nsw.js`, `script/nsw-detail.js` 가격 확인 별(⭐)과 순번 사이 공백 추가
|
||||
|
||||
|
||||
@@ -308,11 +308,14 @@
|
||||
<div class="lg:col-span-3">
|
||||
<div class="sm:px-6 lg:px-8">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center justify-between sm:flex-auto sm:-mx-6 lg:-mx-4">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3 sm:flex-auto sm:-mx-6 lg:-mx-4">
|
||||
<p class="mt-2 sm:mt-0 text-sm text-gray-700">
|
||||
개수:
|
||||
<span id="gameCount">0</span>
|
||||
</p>
|
||||
<p id="priceProgressNotice" class="mt-2 max-w-md text-sm text-gray-500 sm:mt-0">
|
||||
우선 이런 게임들이 있습니다. 가격은 순차적으로 작성중입니다.
|
||||
</p>
|
||||
<div class="sort">
|
||||
<div class="flex items-center gap-2">
|
||||
<label id="sort-label" class="block text-sm/6 font-medium text-gray-900">
|
||||
@@ -542,6 +545,6 @@
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="./script/nsw.js?v=20260519-mobile-search"></script>
|
||||
<script type="module" src="./script/nsw.js?v=20260521-price-pending"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -37,6 +37,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
iarc: '심의 등급',
|
||||
releaseDate: '출시일',
|
||||
suggestedPrice: '판매가',
|
||||
pricePending: '-',
|
||||
priceRange: '판매가 범위',
|
||||
pricingBasis: '가격 참고 기준',
|
||||
checkedAt: '기준일',
|
||||
@@ -63,6 +64,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
iarc: 'IARC',
|
||||
releaseDate: '配信日',
|
||||
suggestedPrice: '推奨販売価格',
|
||||
pricePending: '-',
|
||||
priceRange: '価格帯',
|
||||
pricingBasis: '価格参考基準',
|
||||
checkedAt: '確認日',
|
||||
@@ -78,7 +80,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const currentTexts = texts[language];
|
||||
|
||||
function formatKRW(value) {
|
||||
if (typeof value !== 'number') return '';
|
||||
if (typeof value !== 'number') return currentTexts.pricePending;
|
||||
return `${value.toLocaleString('ko-KR')}원`;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import NSW_DB from '../db/nsw.resale.db.js?v=20260519-mobile-search';
|
||||
import NSW_DB from '../db/nsw.resale.db.js?v=20260521-price-pending';
|
||||
|
||||
window.NSW_APP_VERSION = '20260519-mobile-search';
|
||||
window.NSW_APP_VERSION = '20260521-price-pending';
|
||||
|
||||
const SHOW_SOLD_BY_DEFAULT = false;
|
||||
const SHOW_RECOMMENDED_PRICE_RANGE_BY_DEFAULT = false;
|
||||
@@ -23,6 +23,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
korean: '한국어',
|
||||
japanese: '일본어',
|
||||
count: '개수',
|
||||
listIntro: '우선 이런 게임들이 있습니다. 가격은 순차적으로 작성중입니다.',
|
||||
pricePending: '-',
|
||||
loading: '로딩중...',
|
||||
tableHeaders: {
|
||||
title: '제목',
|
||||
@@ -54,6 +56,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
korean: '韓国語',
|
||||
japanese: '日本語',
|
||||
count: '件数',
|
||||
listIntro: 'まずは所持タイトルを掲載しています。価格は順次入力中です。',
|
||||
pricePending: '-',
|
||||
loading: '読み込み中...',
|
||||
tableHeaders: {
|
||||
title: 'タイトル',
|
||||
@@ -120,6 +124,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// 로딩 텍스트 업데이트
|
||||
loading.textContent = texts.loading;
|
||||
document.getElementById('priceProgressNotice').textContent = texts.listIntro;
|
||||
|
||||
// 필터 텍스트 업데이트
|
||||
document.getElementById('resetFilters').textContent = texts.filter.reset;
|
||||
@@ -630,10 +635,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
|
||||
function formatKRW(value) {
|
||||
if (typeof value !== 'number') return '';
|
||||
if (typeof value !== 'number') return uiTexts[filterState.language].pricePending;
|
||||
return `${value.toLocaleString('ko-KR')}원`;
|
||||
}
|
||||
|
||||
function getSuggestedPriceValue(game) {
|
||||
const suggestedPrice = game.sale?.suggestedPrice;
|
||||
return typeof suggestedPrice === 'number' ? suggestedPrice : null;
|
||||
}
|
||||
|
||||
function formatSaleStatus(status) {
|
||||
const labels = {
|
||||
ko: {
|
||||
@@ -766,8 +776,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="hidden w-32 px-3 py-4 text-sm text-gray-500 sm:table-cell">
|
||||
<div class="whitespace-nowrap font-semibold text-gray-900">
|
||||
<td class="hidden w-56 px-3 py-4 text-sm text-gray-500 sm:table-cell">
|
||||
<div class="font-semibold leading-5 text-gray-900">
|
||||
${game.formattedSuggestedPrice || '-'}
|
||||
</div>
|
||||
<div class="mt-1 text-xs text-gray-400">${game.formattedPricingBasis}</div>
|
||||
@@ -1094,12 +1104,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
case 'sortByPriceDesc':
|
||||
return [...games].sort((a, b) => {
|
||||
const priceDiff = (b.sale?.suggestedPrice || 0) - (a.sale?.suggestedPrice || 0);
|
||||
const aPrice = getSuggestedPriceValue(a);
|
||||
const bPrice = getSuggestedPriceValue(b);
|
||||
if (aPrice === null && bPrice === null) return b.no - a.no;
|
||||
if (aPrice === null) return 1;
|
||||
if (bPrice === null) return -1;
|
||||
const priceDiff = bPrice - aPrice;
|
||||
return priceDiff === 0 ? b.no - a.no : priceDiff;
|
||||
});
|
||||
case 'sortByPrice':
|
||||
return [...games].sort((a, b) => {
|
||||
const priceDiff = (a.sale?.suggestedPrice || 0) - (b.sale?.suggestedPrice || 0);
|
||||
const aPrice = getSuggestedPriceValue(a);
|
||||
const bPrice = getSuggestedPriceValue(b);
|
||||
if (aPrice === null && bPrice === null) return b.no - a.no;
|
||||
if (aPrice === null) return 1;
|
||||
if (bPrice === null) return -1;
|
||||
const priceDiff = aPrice - bPrice;
|
||||
return priceDiff === 0 ? b.no - a.no : priceDiff;
|
||||
});
|
||||
case 'sortByRandom':
|
||||
|
||||
Reference in New Issue
Block a user