import AMIIBO_DB from '../db/amiibo.db.js'; 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: 'Amiibo DB', languageSelect: '언어 선택', languageDescription: '선택한 언어로 표시됩니다', korean: '한국어', japanese: '일본어', count: '개수', loading: '로딩중...', tableHeaders: { title: '제목', info: '정보', status: '상태', role: '역할', }, sortOptions: { sortByNoDesc: '순번 최신순', sortByNo: '순번 과거순', sortByDateDesc: '발매일 최신순', sortByDate: '발매일 과거순', sortByPurchaseDateDesc: '구매일 최신순', sortByPurchaseDate: '구매일 과거순', sortByRandom: '무작위', }, filter: { reset: '필터 초기화', koreanSupport: '한국어 지원', koreanNotSupport: '한국어 미지원', }, }, ja: { title: 'Amiibo', languageSelect: '言語選択', languageDescription: '選択した言語で表示されます', korean: '韓国語', japanese: '日本語', count: '件数', loading: '読み込み中...', tableHeaders: { title: 'タイトル', info: '情報', status: '状態', role: '役割', }, sortOptions: { sortByNoDesc: '番号降順', sortByNo: '番号昇順', sortByDateDesc: '発売日降順', sortByDate: '発売日昇順', sortByPurchaseDateDesc: '購入日降順', sortByPurchaseDate: '購入日昇順', sortByRandom: 'ランダム', }, filter: { reset: 'フィルターリセット', koreanSupport: '韓国語対応', koreanNotSupport: '韓国語非対応', }, }, }; // 필터 상태 관리 객체 const filterState = { language: 'ko', filters: { language: [], status: [], country: [], cero: [], }, sortBy: 'sortByNoDesc', // 기본 정렬 옵션 }; // 정렬 옵션 정의 const sortOptions = [ { name: '순번 최신순', value: 'sortByNoDesc' }, { name: '순번 과거순', value: 'sortByNo' }, { name: '발매일 최신순', value: 'sortByDateDesc' }, { name: '발매일 과거순', value: 'sortByDate' }, { name: '구매일 최신순', value: 'sortByPurchaseDateDesc' }, { name: '구매일 과거순', value: 'sortByPurchaseDate' }, { name: '무작위', value: 'sortByRandom' }, ]; // 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; // 로딩 텍스트 업데이트 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; updateUITexts(); renderGames(); }); }); // 출시일 변환 함수 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) { return { ...game, formattedTitle: filterState.language === 'ko' ? game.koTitle || game.title : game.title, formattedSeries: game.series, formattedReleaseDate: game.release, formattedStatus: game.status, formattedCount: game.count, }; } function getStatusClass(status) { switch (status) { case 'package': return 'bg-green-100 text-green-800'; case 'download': return 'bg-yellow-100 text-yellow-800'; case 'expansion': return 'bg-blue-100 text-blue-800'; default: return ''; } } function getCountryClass(country) { return country === 'JPN' ? 'text-red-600 hover:text-red-900' : 'text-indigo-600 hover:text-indigo-900'; } function createGameRow(amiibo, 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', () => { openImageModal(amiibo.image, amiibo.formattedTitle); }); tr.innerHTML = `
${amiibo.no}. ${amiibo.formattedTitle}
${amiibo.formattedSeries}
${amiibo.formattedStatus.isHave ? "보유" : "미보유" }
${amiibo.formattedStatus.isHave ? `
${amiibo.formattedStatus.isOpen ? "개봉" : "미개봉" }
${amiibo.formattedStatus.isDamaged ? "박스손상" : "" }
` : ''}
${amiibo.formattedCount}
`; return tr; } // 필터 초기화 함수 function resetFilters() { // 모든 체크박스 해제 document.querySelectorAll('input[type="checkbox"]').forEach(checkbox => { checkbox.checked = false; }); // 필터 상태 초기화 filterState.filters = { language: [], status: [], country: [], cero: [], }; // 게임 목록 다시 렌더링 renderGames(); } // 필터 초기화 버튼 이벤트 리스너 설정 document.getElementById('resetFilters').addEventListener('click', resetFilters); // 필터 체크박스 이벤트 리스너 설정 function setupFilterListeners() { // 언어 필터 document.querySelectorAll('input[name="language-filter"]').forEach(checkbox => { checkbox.addEventListener('change', () => { updateFilters('language'); renderGames(); }); }); // 상태 필터 document.querySelectorAll('input[name="status-filter"]').forEach(checkbox => { checkbox.addEventListener('change', () => { updateFilters('status'); renderGames(); }); }); // 국가 필터 document.querySelectorAll('input[name="country-filter"]').forEach(checkbox => { checkbox.addEventListener('change', () => { updateFilters('country'); renderGames(); }); }); // CERO 필터 document.querySelectorAll('input[name="cero-filter"]').forEach(checkbox => { checkbox.addEventListener('change', () => { updateFilters('cero'); renderGames(); }); }); } // 필터 상태 업데이트 function updateFilters(type) { const checkboxes = document.querySelectorAll(`input[name="${type}-filter"]:checked`); filterState.filters[type] = Array.from(checkboxes).map(checkbox => checkbox.value); } // 필터링 함수 function filterGames(games) { return games.filter(game => { // 언어 필터 if (filterState.filters.language.length > 0) { const hasKorean = game.language.includes('韓国語'); const hasKoreanFilter = filterState.filters.language.includes('koreanSupport'); const hasNotSupportedFilter = filterState.filters.language.includes('koreanNotSupport'); // 한국어 지원과 미지원이 모두 체크된 경우 모든 게임 표시 if (hasKoreanFilter && hasNotSupportedFilter) { return true; } // 한국어 지원만 체크된 경우 한국어 지원 게임만 표시 if (hasKoreanFilter && !hasNotSupportedFilter) { return hasKorean; } // 한국어 미지원만 체크된 경우 한국어 미지원 게임만 표시 if (!hasKoreanFilter && hasNotSupportedFilter) { return !hasKorean; } // 아무것도 체크되지 않은 경우 필터링하지 않음 return true; } // 상태 필터 if (filterState.filters.status.length > 0) { const hasExtensionFilter = filterState.filters.status.includes('extension'); const hasOtherStatusFilters = filterState.filters.status.filter(status => status !== 'extension').length > 0; // extension 필터가 체크된 경우 if (hasExtensionFilter) { // extension 값이 null이 아닌 게임만 표시 if (game.extension === null) return false; } // 다른 상태 필터가 체크된 경우 if (hasOtherStatusFilters) { const otherStatuses = filterState.filters.status.filter(status => status !== 'extension'); if (!otherStatuses.includes(game.status)) return false; } } // 국가 필터 if ( filterState.filters.country.length > 0 && !filterState.filters.country.includes(game.country) ) { return false; } // CERO 필터 if (filterState.filters.cero.length > 0 && !filterState.filters.cero.includes(game.cero)) { return false; } return true; }); } // 정렬 함수 function sortGames(games) { switch (filterState.sortBy) { case 'sortByNoDesc': return [...games].sort((a, b) => b.no - a.no); case 'sortByNo': return [...games].sort((a, b) => a.no - b.no); case 'sortByDateDesc': return [...games].sort((a, b) => { const aDate = new Date(a.release.replace(/年|月/g, '/').replace(/日/g, '')).toUTCString(); const bDate = new Date(b.release.replace(/年|月/g, '/').replace(/日/g, '')).toUTCString(); const dateDiff = new Date(bDate) - new Date(aDate); return dateDiff === 0 ? b.no - a.no : dateDiff; }); case 'sortByDate': return [...games].sort((a, b) => { const aDate = new Date(a.release.replace(/年|月/g, '/').replace(/日/g, '')).toUTCString(); const bDate = new Date(b.release.replace(/年|月/g, '/').replace(/日/g, '')).toUTCString(); const dateDiff = new Date(aDate) - new Date(bDate); return dateDiff === 0 ? b.no - a.no : dateDiff; }); case 'sortByPurchaseDateDesc': return [...games].sort((a, b) => { if (!a.purchaseInformation?.date || !b.purchaseInformation?.date) { return !a.purchaseInformation?.date ? 1 : -1; } const aDate = new Date(a.purchaseInformation.date.replace(/\./g, '/')).toUTCString(); const bDate = new Date(b.purchaseInformation.date.replace(/\./g, '/')).toUTCString(); const dateDiff = new Date(bDate) - new Date(aDate); return dateDiff === 0 ? b.no - a.no : dateDiff; }); case 'sortByPurchaseDate': return [...games].sort((a, b) => { if (!a.purchaseInformation?.date || !b.purchaseInformation?.date) { return !a.purchaseInformation?.date ? 1 : -1; } const aDate = new Date(a.purchaseInformation.date.replace(/\./g, '/')).toUTCString(); const bDate = new Date(b.purchaseInformation.date.replace(/\./g, '/')).toUTCString(); const dateDiff = new Date(aDate) - new Date(bDate); return dateDiff === 0 ? b.no - a.no : dateDiff; }); case 'sortByRandom': return [...games].sort(() => Math.random() - 0.5); default: return games; } } // 정렬 UI 초기화 function setupSortUI() { const sortButton = document.getElementById('sort-button'); const sortOptions = document.getElementById('sort-options'); const sortLabel = document.getElementById('sort-label'); // 정렬 버튼 클릭 이벤트 sortButton.addEventListener('click', () => { sortOptions.classList.toggle('hidden'); const isExpanded = sortOptions.classList.contains('hidden') ? 'false' : 'true'; sortButton.setAttribute('aria-expanded', isExpanded); }); // 정렬 옵션 클릭 이벤트 sortOptions.querySelectorAll('li').forEach(option => { option.addEventListener('click', () => { const value = option.getAttribute('data-value'); const name = uiTexts[filterState.language].sortOptions[value]; // 선택된 옵션 업데이트 sortOptions.querySelectorAll('li').forEach(li => { li.querySelector('span').classList.remove('font-semibold'); li.querySelector('svg')?.parentElement?.classList.add('hidden'); }); option.querySelector('span').classList.add('font-semibold'); const checkIcon = option.querySelector('svg')?.parentElement; if (checkIcon) checkIcon.classList.remove('hidden'); // 정렬 상태 업데이트 filterState.sortBy = value; sortButton.querySelector('span').textContent = name; sortOptions.classList.add('hidden'); sortButton.setAttribute('aria-expanded', 'false'); // 게임 목록 다시 렌더링 renderGames(); }); }); // 외부 클릭 시 드롭다운 닫기 document.addEventListener('click', e => { if (!sortButton.contains(e.target) && !sortOptions.contains(e.target)) { sortOptions.classList.add('hidden'); sortButton.setAttribute('aria-expanded', 'false'); } }); // 정렬 옵션 텍스트 업데이트 function updateSortOptionsText() { const texts = uiTexts[filterState.language].sortOptions; sortLabel.textContent = filterState.language === 'ko' ? '정렬' : '並び替え'; sortButton.querySelector('span').textContent = texts[filterState.sortBy]; sortOptions.querySelectorAll('li').forEach(option => { const value = option.getAttribute('data-value'); option.querySelector('span').textContent = texts[value]; }); } // 언어 변경 시 정렬 옵션 텍스트 업데이트 languageRadios.forEach(radio => { radio.addEventListener('change', e => { filterState.language = e.target.value; updateSortOptionsText(); }); }); // 초기 정렬 옵션 텍스트 설정 updateSortOptionsText(); } // 게임 렌더링 함수 수정 function renderGames() { loading.classList.remove('hidden'); // 데이터 포맷팅 const formattedGames = AMIIBO_DB.map(formatGameData); // 필터링 적용 const filteredGames = filterGames(formattedGames); // 정렬 적용 const sortedGames = sortGames(filteredGames); // 게임 개수 업데이트 gameCount.textContent = `${sortedGames.length} ${uiTexts[filterState.language].count}`; // 테이블 내용 업데이트 gameList.innerHTML = ''; sortedGames.forEach((game, index) => { gameList.appendChild(createGameRow(game, index)); }); loading.classList.add('hidden'); } // 초기화 setupFilterListeners(); setupSortUI(); updateUITexts(); renderGames(); }); function openImageModal(imageUrl, title) { const modal = document.getElementById('imageModal'); const modalImage = document.getElementById('modalImage'); const modalTitle = document.getElementById('modalTitle'); modalImage.src = imageUrl; modalTitle.textContent = title; modal.classList.remove('hidden'); } document.getElementById('imageModal').addEventListener('click', () => { document.getElementById('imageModal').classList.add('hidden'); });