(() => { const { EventManager, pageHelper, utils } = ShopbySkin; const INITIAL_PAGE = 1; const PAGE_SIZE = 20; const PAGINATION_SIZE = 5; const getCookie = (name) => { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); return null; }; const memberNo = getCookie("memberNo"); const codeStatus = { "GENERATED": "사용 가능", "COMPLETED": "사용중", "TRANSMITTED": "사용 완료", "GRADING_COMPLETED": "사용 완료", } // 필터 상태 및 캐시 let isFilterActive = false; let filteredCache = []; const redirectLoginPage = () => { const nextUrl = `${location.origin}/pages/sign-in/sign-in.html`; location.href = `${nextUrl}?from=${encodeURIComponent(location.href)}`; }; // 페이지 초기화 const initPage = async () => { // 목록 불러오기 getExamCodeList({ page: INITIAL_PAGE, size: PAGE_SIZE, }); // 탭 버튼 // const tabs = document.getElementsByClassName("tab__button"); // // for (let tab of tabs) { // tab.addEventListener("click", onClickTab); // } // 모아보기 필터 const filter = document.getElementById("available"); if (filter) { filter.addEventListener("change", filterAvailable); } // 직접 등록 버튼 const button = document.getElementById("register"); if (button) { button.addEventListener("click", openRegisterModal); } // 온라인 구매 발급 버튼 const onlineButton = document.getElementById("online-register"); if (onlineButton) { onlineButton.addEventListener("click", openExamCodeListModal); } // 페이지 컨트롤 버튼 const paginationButtons = document.querySelectorAll("#exam-code-pagination > .pagination__btn"); if (paginationButtons && paginationButtons.length) { paginationButtons.forEach((button) => { button.addEventListener("click", onClickPageControl); }) } } // 모의고사 식별번호 일괄 발급 모달 오픈 const openExamCodeListModal = () => { EventManager.fire('OPEN_LAYER_MODAL', { name: 'exam-code-list-form', title: "온라인 구매 발급", modalAddClass: 'exam-code-list-form', isFull: false, data: { isModify: false, }, onClose: (e) => { const {state} = e; if (!state?.result) return; EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: `식별번호 총 ${state?.generatedCnt}건이 발급되었습니다.`, onClose: () => { location.reload(); }, }); }, }); } // 모의고사 식별번호 등록 모달 오픈 const openRegisterModal = () => { EventManager.fire('OPEN_LAYER_MODAL', { name: 'exam-code-register-form', title: "직접 등록", modalAddClass: 'exam-code-register-form', isFull: false, data: { isModify: false, }, onClose: (e) => { const { state } = e; if (state && state.result) { EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '모의고사 식별번호 등록 완료', onClose: () => { location.reload(); }, }); } }, }); } // 탭 버튼 클릭 콜백 // const onClickTab = (tab) => { // const currentTab = tab.currentTarget; // const prevActiveTab = document.querySelector(".tab__button.is-active"); // // if (prevActiveTab) { // prevActiveTab.classList.remove("is-active"); // } // // currentTab.classList.add("is-active"); // getExamCodeList({ // page: INITIAL_PAGE, // size: PAGE_SIZE, // package: currentTab.id, // }); // } // [API] 단일 페이지 fetch const fetchExamCodePage = async (option) => { if( !memberNo ) return null; let requestUrl = DSDOENV.ApiConfig.DSDO_API + `/api/v1/fo-user/mock-exam-code/${memberNo}`; if (option) requestUrl += `?${new URLSearchParams(option)}`; try { const response = await fetch(requestUrl, { method: "GET", headers: { "Content-Type": "application/json" }, }); if (!response.ok) { console.error("API 요청 중 오류 발생:", await response.json()); return null; } const { data } = await response.json(); return data; } catch (error) { console.error("API 요청 중 오류 발생:", error); return null; } } const getExamCodeList = async (option) => { const response = await fetchExamCodePage(option); if (response) updateExamCodeTable(response); } const fetchAllFilteredCodes = async () => { const firstPage = await fetchExamCodePage({ page: 1, size: PAGE_SIZE }); if (!firstPage?.content) return []; const { totalPages, content: contents } = firstPage; let remainingContent = []; if (totalPages > 1) { const pageRequests = Array.from({ length: totalPages - 1 }, (_, i) => fetchExamCodePage({ page: i + 2, size: PAGE_SIZE }) ); const responses = await Promise.all(pageRequests); remainingContent = responses .filter(res => res?.content) .flatMap(res => res.content); } return [...contents, ...remainingContent] .filter(item => item?.codeStatus === "GENERATED"); }; // 클라이언트 페이지네이션 렌더링 const renderClientPage = (page) => { const totalItems = filteredCache.length; const totalPages = Math.max(1, Math.ceil(totalItems / PAGE_SIZE)); const content = filteredCache.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE); updateExamCodeTable({ content, number: page - 1, totalPages, first: page === 1, last: page >= totalPages, }); } // 모의고사 식별번호 테이블 렌더링 const updateExamCodeTable = (data) => { const { content } = data; const table = document.getElementById("exam-code-table"); const tableBody = table.getElementsByClassName("body")[0]; const pagination = document.getElementById("exam-code-pagination"); const empty = table.querySelector(".empty-list"); if (!tableBody || !empty || !pagination) return; tableBody.innerHTML = ""; if (!content.length) { empty.classList.remove("hide"); pagination.classList.add("hide"); } else { empty.classList.add("hide"); pagination.classList.remove("hide"); content.forEach(examCode => createRow(examCode, tableBody)); updatePagination(data, pagination); } } // 모의고사 식별번호 테이블 row 렌더링 const createRow = (examCode, body) => { const row = document.createElement("div"); row.classList.add("row"); // 식별번호 유형 const type = document.createElement("div"); type.classList.add("cell"); type.innerText = examCode.issueType || '알 수 없음'; row.appendChild(type); // 모의고사 const name = document.createElement("div"); name.classList.add("cell"); name.innerText = examCode.mockExamName; row.appendChild(name); // 식별번호 const code = document.createElement("div"); code.classList.add("cell"); code.innerText = examCode.examCode; row.appendChild(code); // 상태 const status = document.createElement("div"); status.classList.add("cell"); const usedStatus = codeStatus[examCode.codeStatus] !== codeStatus["GENERATED"] && Number(examCode?.usedBy) !== Number(memberNo) ? "타 계정 사용 완료" : codeStatus[examCode.codeStatus]; const examAvailable = codeStatus[examCode.codeStatus] === codeStatus["GENERATED"] && examCode.examAvailable; const link = DSDOENV.ApiConfig.EXAM_SYSTEM; if (examAvailable) { status.style.gap = '1rem'; status.innerHTML = `${usedStatus}응시하기`; } else { status.innerHTML = `

${usedStatus}

${examCode?.usedAt ? `(${formatWithoutSeconds(examCode.usedAt)})` : ''}

`; } row.appendChild(status); if (codeStatus[examCode.codeStatus] !== codeStatus["GENERATED"]) { row.classList.add("dim"); } body.appendChild(row); } const formatWithoutSeconds = (usedAt) => { return usedAt?.slice(0, 16); }; // 사용 가능한 식별번호 모아보기 콜백 const filterAvailable = async (e) => { isFilterActive = e.currentTarget.checked; if (isFilterActive) { filteredCache = await fetchAllFilteredCodes(); renderClientPage(1); } else { filteredCache = []; getExamCodeList({ page: INITIAL_PAGE, size: PAGE_SIZE }); } } // 페이지네이션 번호 렌더링 const createPageIndicator = (pageIndex, isCurrentPage, isFirst, isLast) => { const indicator = document.createElement("span"); indicator.classList.add("indicator"); indicator.innerText = pageIndex + 1; if (isCurrentPage) { indicator.classList.add("current"); } else { indicator.addEventListener("click", () => { // const activeTab = document.querySelector(".tab__button.is-active"); // if (!activeTab) return; if (isFilterActive) { renderClientPage(pageIndex + 1); } else { getExamCodeList({ page: pageIndex + 1, size: PAGE_SIZE }); } }); } if (isFirst) { indicator.classList.add("first"); } if (isLast) { indicator.classList.add("last"); } return indicator; } // 페이지네이션 목록 업데이트 const updatePagination = (data, parent) => { const { number, totalPages, first, last } = data; const indicators = parent.getElementsByClassName("indicators")[0]; if (number === undefined || totalPages === undefined) return; indicators.innerHTML = ""; if (totalPages <= PAGINATION_SIZE) { for (let pageIndex = 0; pageIndex < totalPages; pageIndex++) { const isCurrentPage = pageIndex === number; const indicator = createPageIndicator(pageIndex, isCurrentPage, first, last); indicators.appendChild(indicator); } } else { let startPage = number + 1 < PAGINATION_SIZE ? 0 : number + 1 - 3; let endPage = startPage + PAGINATION_SIZE; if (endPage > totalPages) { startPage = totalPages - PAGINATION_SIZE; endPage = startPage + PAGINATION_SIZE; } for (let pageIndex = startPage; pageIndex < endPage; pageIndex++) { const isCurrentPage = pageIndex === number; const indicator = createPageIndicator(pageIndex, isCurrentPage, first, last); indicators.appendChild(indicator); } } } // 페이지네이션 컨트롤 버튼 콜백 const onClickPageControl = (e) => { const currentPageIndicator = document.querySelector(".indicator.current"); const isNext = e.currentTarget.className.includes("rt"); if (!currentPageIndicator) return; const currentPage = Number(currentPageIndicator.innerText); if (isNext) { if (currentPageIndicator.classList.contains("last")) return; // const activeTab = document.querySelector(".tab__button.is-active"); // if (!activeTab) return; if (isFilterActive) { renderClientPage(currentPage + 1); } else { getExamCodeList({ page: currentPage + 1, size: PAGE_SIZE }); } } else { if (currentPageIndicator.classList.contains("first")) return; if (isFilterActive) { renderClientPage(currentPage - 1); } else { getExamCodeList({ page: currentPage - 1, size: PAGE_SIZE}); // package: activeTab.id, } } } // 모의고사 식별번호 목록 초기화 window.addEventListener("load", initPage); // 로그인 여부 체크 EventManager.on("PAGE_LOAD_COMPLETED", () => { if (!utils.isSignedIn()) { EventManager.fire("MODAL_ALERT_OPEN", { noticeType: "CAUTION", message: "로그인이 필요합니다.", onClose: redirectLoginPage, }); } }); })();