// 페이지가 완전히 로딩된 후 실행되는 이벤트 리스너입니다. document.addEventListener('DOMContentLoaded', () => { const catSelect = document.getElementById('category_code'); // 카테고리(대분류) 셀렉트 박스 const blocks = document.querySelectorAll('.cat-block'); // 카테고리별로 동적으로 보여질 입력 폼 블록들 const catGroup = document.getElementById('category_group'); // 카테고리 구분(중분류) 셀렉트 박스 const goalBtn = document.getElementById('btn-goal'); // 학습목표 등록 모달창을 여는 통계/목표 버튼 /** * 사용자가 선택한 카테고리에 맞춰 하단 입력 폼 영역을 동적으로 노출하거나 숨기는 함수입니다. */ function applyToggle() { let name = '마이클래스'; // 기본 카테고리는 마이클래스로 설정합니다. // 카테고리 셀렉트가 있을 경우 현재 선택된 옵션의 data-name 속성을 읽어옵니다. if (catSelect) { const opt = catSelect.options[catSelect.selectedIndex]; name = opt && opt.dataset && opt.dataset.name ? opt.dataset.name : name; } // 준비된 폼 블록들(.cat-block)을 순회하며, 카테고리 이름과 일치하는 블록만 보여줍니다. blocks.forEach(b => { const cat = b.getAttribute('data-cat') || ''; const cats = cat.split(','); if (cats.includes(name)) b.classList.remove('hidden'); else b.classList.add('hidden'); }); const isIS = (name === '인사이트'); const isLD = (name === '리더십'); const isContainer = document.getElementById('issue_type_is_container'); const ldContainer = document.getElementById('issue_type_ld_container'); const isSelect = document.getElementById('issue_type_code_is'); const ldSelect = document.getElementById('issue_type_code_ld'); const offerIdContainer = document.getElementById('offer_id_container'); if (isContainer && ldContainer && isSelect && ldSelect) { if (isIS) { isContainer.classList.remove('hidden'); ldContainer.classList.add('hidden'); isSelect.disabled = false; ldSelect.disabled = true; } else if (isLD) { isContainer.classList.add('hidden'); ldContainer.classList.remove('hidden'); isSelect.disabled = true; ldSelect.disabled = false; } } if (offerIdContainer) { if (isIS) { offerIdContainer.classList.remove('hidden'); } else { offerIdContainer.classList.add('hidden'); } } const sortOrderContainer = document.getElementById('sort_order_container'); if (sortOrderContainer) { if (['CA10001', 'CA10002', 'CA10003'].includes(catSelect.value)) { sortOrderContainer.style.display = 'block'; } else { sortOrderContainer.style.display = 'none'; } } const memoBtn = document.getElementById('btn-memo-open'); if (memoBtn) { if (catSelect && catSelect.value === 'CA10001') { memoBtn.classList.remove('hidden'); } else { memoBtn.classList.add('hidden'); } } } function toggleImageUpload() { const isBizTrend = (catSelect && catSelect.value === 'CA10006'); const isPart1 = (catGroup && catGroup.value === 'CA200B01'); const imgContainer = document.getElementById('image_upload_container'); if (imgContainer) { if (isBizTrend && isPart1) { imgContainer.classList.remove('hidden'); } else { imgContainer.classList.add('hidden'); document.getElementById('image_name_input').value = ''; document.getElementById('image_name_label').textContent = '대표이미지등록(N)'; } } // 사내도서여부: 대표이미지등록과 동일 조건(비즈트렌드 + 1부)일 때만 표시 const bookYnContainer = document.getElementById('book_yn_container'); if (bookYnContainer) { if (isBizTrend && isPart1) { bookYnContainer.classList.remove('hidden'); } else { bookYnContainer.classList.add('hidden'); const bookYnChk = document.getElementById('book_yn'); if (bookYnChk) bookYnChk.checked = false; } } } window.previewImageUpload = function(input) { const label = document.getElementById('image_name_label'); if (input.files && input.files[0]) { const file = input.files[0]; if (file.size > 4 * 1024 * 1024) { alert("용량이 4MB 이하인 이미지 파일만 등록 가능합니다."); input.value = ''; label.textContent = '대표이미지등록(N)'; return; } if (!file.type.startsWith('image/')) { alert("이미지 파일만 등록 가능합니다."); input.value = ''; label.textContent = '대표이미지등록(N)'; return; } label.textContent = '대표이미지등록(Y)'; } else { label.textContent = '대표이미지등록(N)'; } }; /** * 대분류 카테고리가 변경되었을 때, 해당하는 중분류 값을 서버에서 불러와 셀렉트 박스에 세팅하는 함수입니다. */ async function loadCategoryGroup() { if (!catSelect || !catGroup) return; // 요소가 없으면 실행하지 않습니다. const code = catSelect.value; try { // 서버에서 카테고리 그룹(중분류) API 데이터를 비동기로 통신하여 가져옵니다. const res = await fetch(`../bbs/code_list.php?type=category_group&desc01=${encodeURIComponent(code)}`); const data = await res.json(); // 기존 옵션 초기화 후 기본 '선택' 옵션을 추가합니다. catGroup.innerHTML = ''; const def = document.createElement('option'); def.value = ''; def.textContent = '선택'; catGroup.appendChild(def); // 받아온 데이터 리스트를 옵션 태그로 추가합니다. (data.items || []).forEach(it => { const o = document.createElement('option'); o.value = it.code; o.textContent = it.name; catGroup.appendChild(o); }); } catch (e) { // 오류 발생 시 '선택' 옵션만 노출되도록 초기화합니다. catGroup.innerHTML = ''; } } /** * 특정 기준년도에 등록된 활성 상태의 학습목표 목록을 불러와 학습목표코드 셀렉트 박스에 세팅하는 함수입니다. */ async function loadGoals() { const yearInput = document.querySelector('input[name="base_year"]'); const goalSel = document.getElementById('goal_code'); if (!yearInput || !goalSel) return; // 카테고리가 마이클래스가 아닐 때는 학습목표코드를 조회하지 않습니다. if (catSelect) { const opt = catSelect.options[catSelect.selectedIndex]; const catName = opt && opt.dataset && opt.dataset.name ? opt.dataset.name : ''; if (catName !== '마이클래스') { goalSel.innerHTML = ''; return; } } // 연도 필드가 비어있다면 올해 연도를 기본으로 사용합니다. const year = yearInput.value || new Date().getFullYear(); // 카테고리구분(중분류)을 함께 기준으로 사용합니다. (분기 정보와 매핑) const catGroupSelect = document.getElementById('category_group'); const categoryGroup = catGroupSelect ? (catGroupSelect.value || '') : ''; try { const res = await fetch(`../bbs/code_list.php?type=learning_goal&year=${year}&category_group=${encodeURIComponent(categoryGroup)}`); const data = await res.json(); goalSel.innerHTML = ''; (data.items || []).forEach(it => { const o = document.createElement('option'); o.value = it.code; o.textContent = it.name; goalSel.appendChild(o); }); } catch (e) { goalSel.innerHTML = ''; } } const yearInput = document.querySelector('input[name="base_year"]'); if (yearInput) { yearInput.addEventListener('change', loadGoals); yearInput.addEventListener('blur', loadGoals); } // 카테고리구분이 변경되면 학습목표 코드 리스트도 재조회합니다. if (catGroup) { catGroup.addEventListener('change', () => { loadGoals(); toggleImageUpload(); }); } if (catSelect) { catSelect.addEventListener('change', () => { applyToggle(); loadCategoryGroup().then(() => { loadGoals(); toggleImageUpload(); }); }); applyToggle(); loadCategoryGroup().then(() => { loadGoals(); toggleImageUpload(); }); } const offerIdInput = document.querySelector('input[name="offer_id"]'); const isOfferCheck = document.querySelector('input[name="is_offer"]'); if (offerIdInput && isOfferCheck) { offerIdInput.addEventListener('input', () => { isOfferCheck.checked = offerIdInput.value.trim() !== ''; }); } const editBtns = document.querySelectorAll('.btn-edit'); const modalTitle = document.querySelector('#upload-modal h3'); const modalForm = document.querySelector('#upload-modal form'); const contentIdInput = document.querySelector('input[name="content_id"]'); // 수정 버튼들을 순회하며 이벤트 핸들러를 등록합니다. editBtns.forEach(btn => { btn.addEventListener('click', async () => { // 버튼에 바인딩된 해당 행의 JSON 데이터를 가져옵니다. const row = JSON.parse(btn.getAttribute('data-row')); const contentId = row && row.content_id ? row.content_id : ''; if (!contentId) { alert('콘텐츠 ID가 없습니다.'); return; } // content_id 기준으로 DB에서 최신 데이터 조회 let detail = null; try { const dRes = await fetch(`../bbs/code_list.php?type=content_detail&content_id=${encodeURIComponent(contentId)}`); const dData = await dRes.json(); if (!dData.success || !dData.item) { alert('콘텐츠 조회 실패: ' + (dData.message || '알 수 없는 오류')); return; } detail = dData.item; } catch (e) { alert('콘텐츠 조회 중 오류가 발생했습니다.'); return; } // 모달 제목을 '콘텐츠 수정'으로 변경합니다. if (modalTitle) modalTitle.textContent = '콘텐츠 수정'; // 콘텐츠 등록/수정 모달을 보여줍니다. document.getElementById('upload-modal').classList.remove('hidden'); // 삭제 버튼 보여주기 const deleteBtn = document.getElementById('btn-delete'); if (deleteBtn) deleteBtn.classList.remove('hidden'); // 선택된 행의 카테고리 정보로 폼을 세팅합니다. if (catSelect) { catSelect.value = detail.category_code || row.category_code; catSelect.disabled = true; // 카테고리 수정 불가 (읽기 모드) document.getElementById('category_code_hidden').value = row.category_code; applyToggle(); // 폼 요소를 토글합니다. await loadCategoryGroup(); // 해당하는 중분류 목록을 불러옵니다. if (catGroup) { catGroup.value = detail.category_group || row.category_group || ''; } toggleImageUpload(); // 카테고리 구분이 세팅된 후 다시 노출 제어 실행 } // 동적 노출 폼에 데이터를 바인딩합니다. const catName = catSelect.options[catSelect.selectedIndex]?.dataset.name || ''; if (catName === '마이클래스') { const yearInput = document.querySelector('input[name="base_year"]'); if (yearInput && (detail.base_year || row.base_year)) { yearInput.value = detail.base_year || row.base_year; } await loadGoals(); const goalCodeSelect = document.getElementById('goal_code'); if (goalCodeSelect && (detail.goal_code || row.goal_code)) { goalCodeSelect.value = detail.goal_code || row.goal_code; } } else if (catName === '법정교육') { const yearLaw = document.querySelector('input[name="base_year_law"]'); if (yearLaw && (detail.base_year || row.base_year)) yearLaw.value = detail.base_year || row.base_year; } else if (catName === '비즈트렌드') { const sDateBzt = document.querySelector('.cat-block[data-cat="비즈트렌드"] input[name="start_date_bzt"]'); if (sDateBzt && (detail.start_date || row.start_date)) sDateBzt.value = detail.start_date || row.start_date; // 사내도서여부 체크 상태 복원 (비즈트렌드+1부 조건에서만 표시됨) const bookYnChk = document.getElementById('book_yn'); if (bookYnChk) bookYnChk.checked = ((detail.book_yn ?? row.book_yn) === '1'); } else if (catName === '인사이트' || catName === '리더십') { const isIS = (catName === '인사이트'); const isContainer = document.getElementById('issue_type_is_container'); const ldContainer = document.getElementById('issue_type_ld_container'); const isSelect = document.getElementById('issue_type_code_is'); const ldSelect = document.getElementById('issue_type_code_ld'); const offerIdContainer = document.getElementById('offer_id_container'); if (isIS) { if (isContainer) isContainer.classList.remove('hidden'); if (ldContainer) ldContainer.classList.add('hidden'); if (isSelect) { isSelect.disabled = false; isSelect.value = detail.issue_type_code || ''; } if (ldSelect) ldSelect.disabled = true; if (offerIdContainer) offerIdContainer.classList.remove('hidden'); } else { if (isContainer) isContainer.classList.add('hidden'); if (ldContainer) ldContainer.classList.remove('hidden'); if (isSelect) isSelect.disabled = true; if (ldSelect) { ldSelect.disabled = false; ldSelect.value = detail.issue_type_code || ''; } if (offerIdContainer) offerIdContainer.classList.add('hidden'); } const isOffer = document.querySelector('input[name="is_offer"]'); if (isOffer) isOffer.checked = (detail.is_offer === '1'); const offerId = document.querySelector('input[name="offer_id"]'); if (offerId) offerId.value = detail.offer_id || ''; const desc3In = document.querySelector('textarea[name="description3"]'); if (desc3In) desc3In.value = detail.description3 || row.description3 || ''; } // 콘텐츠 기본 폼 속성들에 값을 채워넣습니다. if (contentIdInput) contentIdInput.value = detail.content_id || row.content_id; const titleIn = document.querySelector('input[name="title"]'); if (titleIn) titleIn.value = detail.title || row.title || ''; const descIn = document.querySelector('textarea[name="description"]'); if (descIn) descIn.value = detail.description || row.description || ''; const desc1In = document.querySelector('input[name="description1"]'); if (desc1In) desc1In.value = detail.description1 || row.description1 || ''; const desc2In = document.querySelector('input[name="description2"]'); if (desc2In) desc2In.value = detail.description2 || row.description2 || ''; const sortOrderIn = document.querySelector('input[name="sort_order"]'); if (sortOrderIn) sortOrderIn.value = detail.sort_order || row.sort_order || ''; const urlIn = document.querySelector('input[name="content_url"]'); if (urlIn) urlIn.value = detail.content_url || row.content_url || ''; // content_tm (영상 길이) 복원 const contentTmIn = document.getElementById('content_tm_input'); if (contentTmIn) { const tm = detail.content_tm || row.content_tm || ''; contentTmIn.value = tm; // 길이 표시 업데이트 updateDurationDisplay(tm ? parseInt(tm) : 0); } const imageLabel = document.getElementById('image_name_label'); if (imageLabel) { if (detail.image_name || row.image_name) { imageLabel.textContent = '대표이미지등록(Y)'; } else { imageLabel.textContent = '대표이미지등록(N)'; } } // Keyword binding using API const kwBtns = document.querySelectorAll('.kw-btn'); const kwCountDisplay = document.getElementById('keyword-count-display'); if (kwBtns) { kwBtns.forEach(btn => { btn.dataset.active = 'false'; const iconWrap = btn.querySelector('.kw-icon'); if (iconWrap) iconWrap.innerHTML = ''; }); try { const res = await fetch(`../bbs/code_list.php?type=content_keywords&content_id=${encodeURIComponent(row.content_id)}`); const data = await res.json(); const kws = data.items || []; kws.forEach(k => { const b = Array.from(kwBtns).find(btn => btn.dataset.code === k); if (b) { b.dataset.active = 'true'; const iconWrap = b.querySelector('.kw-icon'); if (iconWrap) iconWrap.innerHTML = ''; } }); if (kwCountDisplay) kwCountDisplay.textContent = kws.length; updateKeywordInput(); } catch (e) { console.error('Failed to load keywords', e); if (kwCountDisplay) kwCountDisplay.textContent = '0'; updateKeywordInput(); } } }); }); const goalForm = document.getElementById('goal-form'); if (goalForm) { goalForm.addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(goalForm); try { const resp = await fetch(goalForm.action, { method: 'POST', body: formData }); const data = await resp.json(); if (data.success) { alert('저장되었습니다.'); loadGoalGrid(); resetGoalForm(); } else { alert('저장 실패: ' + (data.message || '알 수 없는 오류')); } } catch (err) { alert('오류가 발생했습니다.'); } }); } // 콘텐츠 수정 모달 AJAX Submit (저장 후 모달 유지) const contentForm = document.querySelector('#upload-modal form'); if (contentForm) { contentForm.addEventListener('submit', async (e) => { e.preventDefault(); // 기본 페이지 이동 방지 const formData = new FormData(contentForm); const isNew = !formData.get('content_id'); // content_id가 없으면 새 콘텐츠 try { const resp = await fetch(contentForm.action, { method: 'POST', body: formData }); const data = await resp.json(); if (data.success) { alert('저장되었습니다.'); if (isNew) { // 새 콘텐츠 추가 시 모달 닫기 document.getElementById('upload-modal').classList.add('hidden'); location.reload(); // 페이지 새로고침으로 그리드 업데이트 } // 수정 시 모달 유지 (새로고침 없이) } else { alert('저장 실패: ' + (data.message || '알 수 없는 오류')); } } catch (err) { alert('저장에 실패했습니다.'); } }); } // 삭제 버튼 이벤트 const deleteBtn = document.getElementById('btn-delete'); if (deleteBtn) { deleteBtn.addEventListener('click', async () => { if (!confirm('정말로 이 콘텐츠를 삭제하시겠습니까?')) return; const contentId = document.querySelector('input[name="content_id"]').value; if (!contentId) return; try { const resp = await fetch('../bbs/content_delete.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `content_id=${encodeURIComponent(contentId)}` }); const data = await resp.json(); if (data.success) { alert('삭제되었습니다.'); document.getElementById('upload-modal').classList.add('hidden'); location.reload(); // 페이지 새로고침으로 그리드 업데이트 } else { alert('삭제 실패: ' + (data.message || '알 수 없는 오류')); } } catch (err) { alert('삭제에 실패했습니다.'); } }); } // Keyword Selection Logic const kwBtns = document.querySelectorAll('.kw-btn'); const kwInput = document.getElementById('kw_selected'); // Updated ID for modal hidden input function updateKeywordInput() { const activeKws = Array.from(kwBtns) .filter(btn => btn.dataset.active === 'true') .map(btn => btn.dataset.code); if (kwInput) { kwInput.value = activeKws.join(','); } } kwBtns.forEach(btn => { btn.addEventListener('click', () => { const isActive = btn.dataset.active === 'true'; btn.dataset.active = !isActive; const iconWrap = btn.querySelector('.kw-icon'); if (iconWrap) { iconWrap.innerHTML = !isActive ? '' : ''; } updateKeywordInput(); }); }); // content_url 입력 필드 blur 시 자동 영상 정보 조회 const contentUrlInput = document.getElementById('content_url_input'); if (contentUrlInput) { contentUrlInput.addEventListener('blur', () => { const val = contentUrlInput.value.trim(); if (val) fetchYouTubeInfo(); }); } }); /** * 신규 콘텐츠 등록 모달을 여는 함수입니다. (기존 데이터 초기화) */ function openNewModal() { document.getElementById('upload-modal').classList.remove('hidden'); const modalTitle = document.querySelector('#upload-modal h3'); if (modalTitle) modalTitle.textContent = '새 콘텐츠 등록'; const modalForm = document.querySelector('#upload-modal form'); if (modalForm) modalForm.reset(); const contentIdInput = document.querySelector('input[name="content_id"]'); if (contentIdInput) contentIdInput.value = ''; const imageInput = document.getElementById('image_name_input'); if (imageInput) imageInput.value = ''; const imageLabel = document.getElementById('image_name_label'); if (imageLabel) imageLabel.textContent = '대표이미지등록(N)'; // content_tm 및 YouTube 상태 초기화 const contentTmIn = document.getElementById('content_tm_input'); if (contentTmIn) contentTmIn.value = ''; const ytStatus = document.getElementById('yt-fetch-status'); if (ytStatus) ytStatus.classList.add('hidden'); const durDisplay = document.getElementById('yt-duration-display'); if (durDisplay) durDisplay.classList.add('hidden'); // 삭제 버튼 숨기기 const deleteBtn = document.getElementById('btn-delete'); if (deleteBtn) deleteBtn.classList.add('hidden'); const kwBtns = document.querySelectorAll('.kw-btn'); const kwCountDisplay = document.getElementById('keyword-count-display'); if (kwBtns) { kwBtns.forEach(btn => { btn.dataset.active = 'false'; const iconWrap = btn.querySelector('.kw-icon'); if (iconWrap) iconWrap.innerHTML = ''; }); } if (kwCountDisplay) kwCountDisplay.textContent = '0'; const kwSelected = document.getElementById('kw_selected'); if (kwSelected) kwSelected.value = ''; // 카테고리를 다시 선택 상태로 트리거하여 폼의 동적 노출 상태를 초기화합니다. const catSelect = document.getElementById('category_code'); if (catSelect) { catSelect.disabled = false; // 새 콘텐츠 등록 시에는 카테고리 선택 가능 document.getElementById('category_code_hidden').value = catSelect.value; catSelect.dispatchEvent(new Event('change')); } } /** * 학습목표 등록(및 리스트 조회) 모달을 여는 함수입니다. */ function openGoalModal() { document.getElementById('goal-modal').classList.remove('hidden'); loadGoalGrid(); resetGoalForm(); } /** * 학습목표 모달을 닫는 함수입니다. */ function closeGoalModal() { document.getElementById('goal-modal').classList.add('hidden'); } /** * 학습목표 목록을 Ajax로 불러와 표(Grid) 형식으로 그려주는 함수입니다. */ async function loadGoalGrid() { const yearInput = document.getElementById('goal_search_year'); const quarterInput = document.getElementById('goal_search_quarter'); if (!yearInput) return; const year = yearInput.value || new Date().getFullYear(); const quarter = quarterInput ? quarterInput.value : ''; const gridBody = document.getElementById('goal-grid-body'); if (!gridBody) return; // 데이터를 불러오기 전 로딩 상태 표시 gridBody.innerHTML = '