Convert Switch DB for used sales

This commit is contained in:
2026-05-19 11:10:05 +09:00
parent 95d092fbc2
commit 7904b6b89c
8 changed files with 19012 additions and 11753 deletions

View File

@@ -1,4 +1,4 @@
import NSW_DB from '../db/nsw.db.js';
import NSW_DB from '../db/nsw.resale.db.js';
document.addEventListener('DOMContentLoaded', () => {
// URL에서 게임 번호 가져오기
@@ -18,7 +18,7 @@ document.addEventListener('DOMContentLoaded', () => {
const texts = {
ko: {
infoTitle: '게임 정보',
purchaseTitle: '매 정보',
purchaseTitle: '매 정보',
requiredCapacity: '필요한 용량',
playMode: '플레이 모드',
playUser: '플레이 인원',
@@ -31,10 +31,10 @@ document.addEventListener('DOMContentLoaded', () => {
cero: '심의 등급',
iarc: '심의 등급',
releaseDate: '출시일',
purchaseDate: '구매일',
store: '구매처',
price: '구매 가격',
orderNumber: '주문번호',
suggestedPrice: '추천 판매가',
priceRange: '판매가 범위',
pricingBasis: '가격 참고 기준',
checkedAt: '기준일',
extension: '추가 콘텐츠',
none: '없음',
supported: '대응',
@@ -42,7 +42,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
ja: {
infoTitle: 'Infomation',
purchaseTitle: '購入情報',
purchaseTitle: '販売情報',
requiredCapacity: '必要な容量',
playMode: 'プレイモード',
playUser: 'プレイ人数',
@@ -55,10 +55,10 @@ document.addEventListener('DOMContentLoaded', () => {
cero: 'CERO',
iarc: 'IARC',
releaseDate: '配信日',
purchaseDate: '購入日',
store: '購入先',
price: '購入価格',
orderNumber: '注文番号',
suggestedPrice: '推奨販売価格',
priceRange: '価格帯',
pricingBasis: '価格参考基準',
checkedAt: '確認日',
extension: '追加コンテンツ',
none: 'なし',
supported: '対応',
@@ -68,11 +68,153 @@ document.addEventListener('DOMContentLoaded', () => {
const currentTexts = texts[language];
function formatKRW(value) {
if (typeof value !== 'number') return '';
return `${value.toLocaleString('ko-KR')}`;
}
function formatPricingBasis(pricingBasis) {
const labels = {
ko: {
KR_USED_REFERENCE_ESTIMATE: '국내 중고 시세 참고',
JP_USED_REFERENCE_CONVERTED_TO_KRW_ESTIMATE: '일본 중고 시세 환산',
MANUAL: '직접 입력가',
SOLD_HISTORY: '판매 이력 기준',
},
ja: {
KR_USED_REFERENCE_ESTIMATE: '韓国中古相場参考',
JP_USED_REFERENCE_CONVERTED_TO_KRW_ESTIMATE: '日本中古相場換算',
MANUAL: '手入力価格',
SOLD_HISTORY: '販売履歴基準',
},
};
return labels[language][pricingBasis] || '';
}
function convertLanguage(value) {
if (!value || language !== 'ko') return value;
const labels = {
日本語: '일본어',
英語: '영어',
韓国語: '한국어',
フランス語: '프랑스어',
ドイツ語: '독일어',
イタリア語: '이탈리아어',
スペイン語: '스페인어',
ロシア語: '러시아어',
オランダ語: '네덜란드어',
ポルトガル語: '포르투갈어',
'中国語 (簡体字)': '중국어 (간체)',
'中国語 (繁体字)': '중국어 (번체)',
};
return value
.split(',')
.map(item => labels[item.trim()] || item.trim())
.join(', ');
}
function convertMaker(value) {
if (!value || language !== 'ko') return value;
const labels = {
任天堂: '닌텐도',
スクウェアエニックス: '스퀘어 에닉스',
コーエーテクモゲームス: '코에이 테크모 게임스',
ポケモン: '포켓몬',
バンダイナムコエンターテインメント: '반다이 남코 엔터테인먼트',
アトラス: '아틀러스',
セガ: '세가',
マーベラス: '마블러스 엔터테인먼트',
カプコン: '캡콤',
ユービーアイソフト: '유비소프트',
日本一ソフトウェア: '니폰이치 소프트웨어',
アークシステムワークス: '아크 시스템 웍스',
日本ファルコム: '일본 팔콤',
};
return value
.split(',')
.map(item => labels[item.trim()] || item.trim())
.join(', ');
}
function convertTags(value) {
if (!value || language !== 'ko') return value;
const labels = {
アクション: '액션',
アドベンチャー: '어드벤처',
テキストアドベンチャー: '텍스트 어드벤처',
ロールプレイング: '롤플레잉',
シューティング: '슈팅',
シミュレーション: '시뮬레이션',
ストラテジー: '전략',
パズル: '퍼즐',
レース: '레이스',
スポーツ: '스포츠',
格闘: '격투',
音楽ゲーム: '음악 게임',
恋愛: '연애',
難易度が選べる: '난이도 선택 가능',
戦うたびに強くなる: '싸울수록 성장',
キャラクターボイス: '캐릭터 음성',
オンラインで対戦: '온라인 대전',
オンラインで協力: '온라인 협력',
オンラインでフレンドと: '친구와 온라인으로',
キャラクターカスタマイズ: '캐릭터 커스터마이즈',
'3人称視点': '3인칭 시점',
'1台の本体でいっしょにあそべる': '한 대의 본체에서 함께 플레이',
ともだちや家族と集まって: '친구와 가족과 함께',
オンラインランキング: '온라인 랭킹',
本体を持ちよってあそべる: '게임기를 들고 플레이',
世界を自由にかけ回る: '세계를 자유롭게 탐험',
目的はあなた次第: '목적은 자유롭게 선택',
};
return value
.split(',')
.map(item => labels[item.trim()] || item.trim())
.join(', ');
}
function convertReleaseDate(value) {
if (!value || language !== 'ko') return value;
const date = new Date(value.replace(/年|月/g, '/').replace('日', ''));
if (Number.isNaN(date.getTime())) return value;
return `${date.getFullYear()}${date.getMonth() + 1}${date.getDate()}`;
}
function convertSupportValue(value) {
if (!value || language !== 'ko') return value;
return value.replaceAll('対応', '대응').replaceAll('非対応', '비대응');
}
function getGameInfoValue(key) {
switch (key) {
case 'maker':
return convertMaker(game[key]);
case 'language':
return convertLanguage(game[key]);
case 'release':
return convertReleaseDate(game[key]);
case 'onlineDataSave':
return convertSupportValue(game[key]);
default:
return game[key];
}
}
// 기본 정보 설정
document.getElementById('gameImage').src = window.innerWidth < 640 ? game.thumbnail : game.image;
document.getElementById('gameTitle').textContent =
language === 'ko' ? game.koTitle || game.title : game.title;
document.getElementById('gameTags').textContent = game.tags;
document.getElementById('gameTags').textContent = convertTags(game.tags);
document.getElementById('infoTitle').textContent = currentTexts.infoTitle;
document.getElementById('purchaseTitle').textContent = currentTexts.purchaseTitle;
document.getElementById('purchaseGameTitle').textContent =
@@ -80,14 +222,18 @@ document.addEventListener('DOMContentLoaded', () => {
// 게임 상태 설정
const statusClass = {
package: 'bg-green-100 text-green-800',
available: 'bg-green-100 text-green-800',
download: 'bg-yellow-100 text-yellow-800',
expansion: 'bg-blue-100 text-blue-800',
sold: 'bg-red-100 text-red-800',
}[game.status];
document.getElementById(
'gameStatus',
).className = `inline-flex rounded-full px-2 text-xs font-semibold leading-5 ${statusClass}`;
document.getElementById('gameStatus').textContent = game.status;
document.getElementById('gameStatus').textContent =
language === 'ko'
? { available: '판매중', sold: '판매완료' }[game.status] || game.status
: { available: '販売中', sold: '販売済み' }[game.status] || game.status;
// 국가 설정
const countryClass =
@@ -116,41 +262,47 @@ document.addEventListener('DOMContentLoaded', () => {
{ key: 'language', label: currentTexts.language },
{ key: 'cero', label: currentTexts.cero },
{ key: 'iarc', label: currentTexts.iarc },
{ key: 'releaseDate', label: currentTexts.releaseDate },
{ key: 'release', label: currentTexts.releaseDate },
];
infoItems.forEach(item => {
if (game[item.key]) {
const value = getGameInfoValue(item.key);
if (value) {
const div = document.createElement('div');
div.className = 'border-t border-gray-200 pt-4';
div.innerHTML = `
<dt class="font-medium text-gray-900">${item.label}</dt>
<dd class="mt-2 text-sm text-gray-500">${game[item.key]}</dd>
<dd class="mt-2 text-sm text-gray-500">${value}</dd>
`;
gameInfo.appendChild(div);
}
});
// 매 정보 설정
// 매 정보 설정
const purchaseInfo = document.getElementById('purchaseInfo');
if (game.purchaseInformation) {
const purchaseItems = [
{ key: 'date', label: currentTexts.purchaseDate },
{ key: 'store', label: currentTexts.store },
{ key: 'price', label: currentTexts.price },
{ key: 'orderNumber', label: currentTexts.orderNumber },
if (game.sale) {
const priceRange =
game.sale.priceRange?.min && game.sale.priceRange?.max
? `${formatKRW(game.sale.priceRange.min)} ~ ${formatKRW(game.sale.priceRange.max)}`
: '';
const saleItems = [
{ value: formatKRW(game.sale.suggestedPrice), label: currentTexts.suggestedPrice },
{ value: priceRange, label: currentTexts.priceRange },
{ value: formatPricingBasis(game.sale.pricingBasis), label: currentTexts.pricingBasis },
{ value: game.sale.checkedAt, label: currentTexts.checkedAt },
];
const dl = document.createElement('dl');
dl.className = 'grid grid-cols-1 gap-x-4 gap-y-8 sm:grid-cols-2';
purchaseItems.forEach(item => {
if (game.purchaseInformation[item.key]) {
saleItems.forEach(item => {
if (item.value) {
const div = document.createElement('div');
div.className = 'sm:col-span-1';
div.innerHTML = `
<dt class="text-sm font-medium text-gray-500">${item.label}</dt>
<dd class="mt-1 text-sm text-gray-900">${game.purchaseInformation[item.key]}</dd>
<dd class="mt-1 text-sm text-gray-900">${item.value}</dd>
`;
dl.appendChild(div);
}