import NSW_DB from '../db/nsw.resale.db.js'; const SHOW_SOLD_BY_DEFAULT = false; document.addEventListener('DOMContentLoaded', () => { const gameList = document.getElementById('gameList'); const gameCount = document.getElementById('gameCount'); const loading = document.getElementById('loading'); const languageRadios = document.querySelectorAll('input[name="language"]'); // 언어별 UI 텍스트 const uiTexts = { ko: { title: 'Switch 중고 판매 목록', languageSelect: '언어 선택', languageDescription: '선택한 언어로 표시됩니다', korean: '한국어', japanese: '일본어', count: '개수', loading: '로딩중...', tableHeaders: { title: '제목', info: '판매가', status: '판매 상태', role: '가격 범위', location: '지역', }, sortOptions: { sortByNoDesc: '순번 최신순', sortByNo: '순번 과거순', sortByDateDesc: '발매일 최신순', sortByDate: '발매일 과거순', sortByPriceDesc: '판매가 높은순', sortByPrice: '판매가 낮은순', sortByRandom: '무작위', }, filter: { reset: '필터 초기화', koreanSupport: '한국어 지원', koreanNotSupport: '한국어 미지원', }, }, ja: { title: '中古販売リスト', languageSelect: '言語選択', languageDescription: '選択した言語で表示されます', korean: '韓国語', japanese: '日本語', count: '件数', loading: '読み込み中...', tableHeaders: { title: 'タイトル', info: '販売価格', status: '販売状態', role: '価格帯', location: '地域', }, sortOptions: { sortByNoDesc: '番号降順', sortByNo: '番号昇順', sortByDateDesc: '発売日降順', sortByDate: '発売日昇順', sortByPriceDesc: '販売価格降順', sortByPrice: '販売価格昇順', sortByRandom: 'ランダム', }, filter: { reset: 'フィルターリセット', koreanSupport: '韓国語対応', koreanNotSupport: '韓国語非対応', }, }, }; // 필터 상태 관리 객체 const filterState = { language: 'ko', filters: { language: [], status: [], country: [], cero: [], }, searchText: '', sortBy: 'sortByNoDesc', // 기본 정렬 옵션 }; // UI 텍스트 업데이트 함수 function updateUITexts() { const texts = uiTexts[filterState.language]; // 제목 업데이트 document.querySelector('h1').textContent = texts.title; // 언어 선택 섹션 업데이트 document.querySelector('label.text-base').textContent = texts.languageSelect; document.querySelector('p.text-sm').textContent = texts.languageDescription; document.querySelector('label[for="ko"]').textContent = texts.korean; document.querySelector('label[for="ja"]').textContent = texts.japanese; // 테이블 헤더 업데이트 const headers = document.querySelectorAll('th'); headers[0].textContent = texts.tableHeaders.title; headers[1].textContent = texts.tableHeaders.info; headers[2].textContent = texts.tableHeaders.status; headers[3].textContent = texts.tableHeaders.role; headers[4].textContent = texts.tableHeaders.location; // 로딩 텍스트 업데이트 loading.textContent = texts.loading; // 필터 텍스트 업데이트 document.getElementById('resetFilters').textContent = texts.filter.reset; document.querySelector('label[for="korean-support"]').textContent = texts.filter.koreanSupport; document.querySelector('label[for="korean-not-support"]').textContent = texts.filter.koreanNotSupport; } // 언어 변경 이벤트 리스너 languageRadios.forEach(radio => { radio.addEventListener('change', e => { filterState.language = e.target.value; localStorage.setItem('language', filterState.language); updateUITexts(); renderGames(); }); }); localStorage.setItem('language', filterState.language); // 언어 변환 함수 function convertLanguage(language) { if (!language) return ''; if (filterState.language !== 'ko') return language; const languages = language.split(','); const koreanLanguages = []; for (let i = 0; i < languages.length; i++) { switch (languages[i].trim()) { case '日本語': koreanLanguages.push('일본어'); break; case '英語': koreanLanguages.push('영어'); break; case '韓国語': koreanLanguages.push('한국어'); break; case 'フランス語': koreanLanguages.push('프랑스어'); break; case 'ドイツ語': koreanLanguages.push('독일어'); break; case 'イタリア語': koreanLanguages.push('이탈리아어'); break; case 'スペイン語': koreanLanguages.push('스페인어'); break; case 'ロシア語': koreanLanguages.push('러시아어'); break; case 'オランダ語': koreanLanguages.push('네덜란드어'); break; case 'ポルトガル語': koreanLanguages.push('포르투칼어'); break; case '中国語 (簡体字)': koreanLanguages.push('중국어 (간체)'); break; case '中国語 (繁体字)': koreanLanguages.push('중국어 (번체)'); break; default: koreanLanguages.push(languages[i]); break; } } return koreanLanguages.join(', '); } // 메이커 변환 함수 function convertMaker(maker) { if (!maker) return ''; if (filterState.language !== 'ko') return maker; const makers = maker.split(','); const koreanMakers = []; for (let i = 0; i < makers.length; i++) { switch (makers[i].trim()) { // 메이저 Maker case '任天堂': koreanMakers.push('닌텐도'); break; case 'スクウェア・エニックス': koreanMakers.push('스퀘어 에닉스'); break; case 'コーエーテクモゲームス': koreanMakers.push('코에이 테크모 게임스'); break; case 'ポケモン': koreanMakers.push('포켓몬'); break; case 'バンダイナムコエンターテインメント': koreanMakers.push('반다이 남코 엔터테인먼트'); break; case 'アトラス': koreanMakers.push('아틀러스'); break; case 'セガ': koreanMakers.push('세가'); break; // 소규모 Maker case '日本一ソフトウェア': koreanMakers.push('니폰이치 소프트웨어'); break; case 'エンターグラム': koreanMakers.push('Entergram'); break; case 'フライハイワークス': koreanMakers.push('Flyhigh Works'); break; case 'フリュー': koreanMakers.push('후류'); break; case 'ポノス': koreanMakers.push('포노스'); break; case 'マーベラス': koreanMakers.push('마블러스 엔터테인먼트'); break; case 'スパイク・チュンソフト': koreanMakers.push('스파이크 춘 소프트'); break; case 'ドラガミゲームス': koreanMakers.push('DRAGAMI GAMES'); break; case 'アイディアファクトリー': koreanMakers.push('Idea Factory'); break; case 'アークシステムワークス': koreanMakers.push('아크 시스템 웍스'); break; case 'ユービーアイソフト': koreanMakers.push('유비소프트'); break; case 'レイアーク': koreanMakers.push('레이아크'); break; case 'ワンオアエイト': koreanMakers.push('One or Eight'); break; case 'インティ・クリエイツ': koreanMakers.push('인티 크리에이츠'); break; case 'クラウディッドレパードエンタテインメント': koreanMakers.push('Clouded Leopard Entertainment'); break; case 'カプコン': koreanMakers.push('캡콤'); break; case 'プロトタイプ': koreanMakers.push('PROTOTYPE Ltd'); break; case 'ディースリー・パブリッシャー': koreanMakers.push('D3 퍼블리셔'); break; case 'タイトー': koreanMakers.push('타이토'); break; case 'シーエフケー': koreanMakers.push('CFK'); break; case 'アクワイア': koreanMakers.push('어콰이어'); break; case '日本ファルコム': koreanMakers.push('일본 팔콤'); break; // 거르면 되는 Maker case 'ヒューネックス': koreanMakers.push('휴넥스'); break; case 'アニプレックス': koreanMakers.push('애니플렉스'); break; case 'ジー・モード': koreanMakers.push('G-Mode'); break; case 'イザナギゲームズ': koreanMakers.push('IzanagiGames'); break; case 'ラセングル': koreanMakers.push('Lasengle'); break; case 'ケムコ': koreanMakers.push('켐코'); break; case 'ネットマーブルコーポレーション': koreanMakers.push('넷마블'); break; case '工画堂スタジオ': koreanMakers.push('코가도 스튜디오'); break; case '賈船': koreanMakers.push('COSEN'); break; case 'ジェムドロップ': koreanMakers.push('잼드롭'); break; case 'アレス': koreanMakers.push('아레스'); break; case '日本コロムビア': koreanMakers.push('일본콜롬비아'); break; case 'クリプトン・フューチャー・メディア': koreanMakers.push('크립톤 퓨처 미디어'); break; case 'イマジニア': koreanMakers.push('이매지니아'); break; default: koreanMakers.push(makers[i]); break; } } return koreanMakers.join(', '); } // 태그 변환 함수 function convertTags(tags) { if (!tags) return ''; if (filterState.language !== 'ko') return tags; const tagList = tags.split(','); const koreanTags = []; for (let i = 0; i < tagList.length; i++) { switch (tagList[i].trim()) { case 'パーティー': koreanTags.push('파티'); break; case 'シューティング': koreanTags.push('슈팅'); break; case '格闘': koreanTags.push('격투'); break; case 'パズル': koreanTags.push('퍼즐'); break; case 'レース': koreanTags.push('레이스'); break; case 'ロールプレイング': koreanTags.push('롤플레잉'); break; case 'アクション': koreanTags.push('액션'); break; case 'ストラテジー': koreanTags.push('전략'); break; case 'ドット絵': koreanTags.push('도트 그림'); break; case 'サバイバル': koreanTags.push('서바이벌'); break; case 'リズムに合わせて': koreanTags.push('리듬에 맞춰'); break; case 'カードゲーム': koreanTags.push('카드 게임'); break; case '囲碁・将棋': koreanTags.push('바둑・쇼기'); break; case 'ボードゲーム': koreanTags.push('보드 게임'); break; case 'サッカー': koreanTags.push('축구'); break; case 'テーブルゲーム': koreanTags.push('테이블 게임'); break; case 'トランプ': koreanTags.push('트럼프'); break; case '麻雀': koreanTags.push('마작'); break; case 'トレーニング': koreanTags.push('트레이닝'); break; case '視点切りかえ': koreanTags.push('관점의 전환'); break; case 'あそびが盛りだくさん': koreanTags.push('다양한 즐길거리'); break; case '新しいエリアを切りひらく': koreanTags.push('새로운 지역을 개척한다'); break; case 'あそぶたびにマップが新しい': koreanTags.push('즐길때마다 새로운 맵'); break; case '大人数でバトル': koreanTags.push('많은 인원과 배틀'); break; case '最速タイムにチャレンジ': koreanTags.push('가장 빠른 시간에 도전'); break; case 'シミュレーション': koreanTags.push('시뮬레이션'); break; case 'スポーツ': koreanTags.push('스포츠'); break; case 'バレーボール': koreanTags.push('배구'); break; case 'ゴルフ': koreanTags.push('골프'); break; case 'バスケットボール': koreanTags.push('농구'); break; case 'テニス': koreanTags.push('테니스'); break; case '野球': koreanTags.push('야구'); break; case 'ボクシング': koreanTags.push('복싱'); break; case '経営シミュレーション': koreanTags.push('경영 시뮬레이션'); break; case 'コミュニケーション': koreanTags.push('커뮤니케이션'); break; case '音楽ゲーム': koreanTags.push('음악 게임'); break; case '学習・教育': koreanTags.push('학습・교육'); break; case 'ツール': koreanTags.push('도구'); break; case 'アドベンチャー': koreanTags.push('모험'); break; case '失敗したら最初から': koreanTags.push('실패하면 처음부터'); break; case 'なぞ解き': koreanTags.push('수수께끼'); break; case 'せまる敵から守りぬく': koreanTags.push('다가오는 적으로부터 지킨다'); break; case 'すばやい判断がきめ手': koreanTags.push('재빠른 판단이 관건'); break; case 'つくれる・あそべる': koreanTags.push('만들고 즐긴다'); break; case 'テキストアドベンチャー': koreanTags.push('텍스트 어드벤처'); break; case '恋愛': koreanTags.push('연애'); break; case '最高スコアにチャレンジ': koreanTags.push('최고 점수에 도전'); break; case '世界を自由にかけ回る': koreanTags.push('세계를 자유롭게 돌아다니다'); break; case '落下に注意': koreanTags.push('낙하주의'); break; case '目的はあなた次第': koreanTags.push('목적은 당신이 선택'); break; case '戦うたびに強くなる': koreanTags.push('싸울수록 성장'); break; case '手足や体と連動して操作': koreanTags.push('몸과 연동하여 조작'); break; case 'オンラインで対戦': koreanTags.push('온라인 대전'); break; case 'オンラインで協力': koreanTags.push('온라인 협력'); break; case 'キャラクターカスタマイズ': koreanTags.push('캐릭터 커스터마이즈'); break; case '3人称視点': koreanTags.push('3인칭 시점'); break; case 'Toy-Conが使える': koreanTags.push('Toy-Con을 사용할 수 있다'); break; case '難易度が選べる': koreanTags.push('난이도 선택 가능'); break; case 'キャラクターボイス': koreanTags.push('케릭터 음성'); break; case 'オンラインでフレンドと': koreanTags.push('친구와 온라인으로'); break; case '1台の本体でいっしょにあそべる': koreanTags.push('한 대의 본체에서 함께 놀 수 있다'); break; case 'ともだちや家族と集まって': koreanTags.push('친구와 가족과 함께'); break; case 'オンラインランキング': koreanTags.push('온라인 랭킹'); break; case '本体を持ちよってあそべる': koreanTags.push('게임기를 들고 플레이'); break; case 'クロスプラットフォームプレイ対応': koreanTags.push('크로스 플랫폼 플레이 대응'); break; default: koreanTags.push(tagList[i]); break; } } return koreanTags.join(', '); } // 출시일 변환 함수 function convertReleaseDate(releaseDate) { if (!releaseDate) return ''; if (filterState.language !== 'ko') return releaseDate; const date = new Date(releaseDate.replace(/年|月/g, '/').replace('日', '')); const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); return `${year}년 ${month}월 ${day}일`; } // 국가 변환 함수 function convertCountry(country) { if (!country) return ''; switch (country) { case 'JPN': return filterState.language === 'ko' ? '일본판' : '日本版'; case 'KOR': return filterState.language === 'ko' ? '한국판' : '韓国版'; default: return country; } } function formatGameData(game) { const suggestedPrice = game.sale?.suggestedPrice; const priceRange = game.sale?.priceRange; return { ...game, formattedTitle: filterState.language === 'ko' ? game.koTitle || game.title : game.title, formattedMaker: convertMaker(game.maker), formattedLanguage: convertLanguage(game.language), formattedTags: convertTags(game.tags), formattedCountry: convertCountry(game.country), formattedSuggestedPrice: formatKRW(suggestedPrice), formattedPriceRange: priceRange?.min && priceRange?.max ? `${formatKRW(priceRange.min)} ~ ${formatKRW(priceRange.max)}` : '', formattedPricingBasis: formatPricingBasis(game.sale?.pricingBasis), formattedConfidenceDescription: formatConfidenceDescription(game.sale?.confidence), formattedSaleStatus: formatSaleStatus(game.status), }; } function formatKRW(value) { if (typeof value !== 'number') return ''; return `${value.toLocaleString('ko-KR')}원`; } function formatSaleStatus(status) { const labels = { ko: { available: '판매 가능', sold: '판매완료', }, ja: { available: '販売可', sold: '販売済み', }, }; return labels[filterState.language][status] || status; } 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[filterState.language][pricingBasis] || ''; } function formatConfidenceDescription(confidence) { const descriptions = { ko: { high: '최근 거래가가 안정적인 편이라 표시가에 가까운 거래를 기대할 수 있습니다.', medium: '중고 시세를 참고한 합리적인 기준가이며 상태에 따라 소폭 조정될 수 있습니다.', 'medium-low': '판본, 언어, 구성품에 따라 가격 차이가 있어 확인 후 조정 가능합니다.', low: '거래 사례가 적은 타이틀이라 상태 확인 후 가격 협의 여지가 있습니다.', }, ja: { high: '最近の取引価格が安定しており、表示価格に近い取引が期待できます。', medium: '中古相場を参考にした基準価格で、状態により多少調整できます。', 'medium-low': '版、言語、付属品により価格差があるため、確認後に調整できます。', low: '取引例が少ないタイトルのため、状態確認後に価格相談できます。', }, }; return descriptions[filterState.language][confidence] || ''; } function getSaleStatusClass(status) { switch (status) { case 'sold': return 'bg-red-100 text-red-800'; default: return 'bg-green-100 text-green-800'; } } function getCountryClass(country) { return country === 'JPN' ? 'text-red-600 hover:text-red-900' : 'text-indigo-600 hover:text-indigo-900'; } function createGameRow(game, index) { const tr = document.createElement('tr'); tr.className = `cursor-pointer hover:bg-indigo-50 ${index % 2 === 0 ? '' : 'bg-gray-50'}`; // 클릭 시 nsw-detail.html로 이동 (no 쿼리 포함) tr.addEventListener('click', () => { window.location.href = `nsw-detail.html?no=${encodeURIComponent(game.no)}`; }); tr.innerHTML = `