import { w2grid, w2ui, w2popup, w2alert } from 'https://cdn.jsdelivr.net/gh/vitmalina/w2ui@master/dist/w2ui.es6.min.js' /* ------------------------------------------------- 공통 유틸 ------------------------------------------------- */ function destroyGrid(name) { if (w2ui[name]) { w2ui[name].destroy() } } function loadBaseCode(mainCd) { return fetch(`/kngil/bbs/adm_comp.php?action=base_code&main_cd=${mainCd}`) .then(res => res.json()) .then(json => { if (json.status !== 'success') { throw new Error(json.message || '공통코드 로딩 실패') } return json.items }) } /* ================================================= 상품등록 팝업 (슈퍼관리자 전용) ================================================= */ export function openProductPopup() { if (w2ui.productGrid) { w2ui.productGrid.destroy() } w2popup.open({ title: '상품등록', width: 900, height: 600, modal: true, body: `
`, onOpen(event) { event.onComplete = () => { // 1. 그리드를 생성합니다. createProductGrid('#productGrid'); // 1. 추가 버튼 document.getElementById('prodAdd').onclick = () => { const g = w2ui.productGrid if (!g) return // 신규 row용 recid (음수로 충돌 방지) const newRecid = -Date.now() g.add({ row_status: 'I', recid: newRecid, __isNew: true, // ⭐ 신규 플래그 use_yn: 'Y' }, true) g.select(newRecid) g.scrollIntoView(newRecid) // commonAdd('productGrid', { use_yn: 'Y', itm_amt: 0, area: 0 }); }; // 삭제 버튼 이벤트 연결 const removeBtn = document.getElementById('prodRemove'); if (removeBtn) { removeBtn.onclick = () => { const g = w2ui.productGrid; if (!g) return; // 1. 선택된 행 가져오기 const sel = g.getSelection(); if (!sel.length) { alert('삭제할 상품을 선택하세요.'); return; } // 2. 상품코드 추출 const ids = sel .map(recid => g.get(recid)?.itm_cd) .filter(Boolean); if (!ids.length) { alert('삭제 가능한 항목이 없습니다.'); return; } // 3. 브라우저 기본 확인창 사용 (가장 확실함) if (confirm(`선택한 ${ids.length}개의 상품을 삭제하시겠습니까?`)) { fetch('/kngil/bbs/adm_product_popup_delete.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'delete', ids: ids }) }) .then(res => { // 서버 응답이 오면 일단 텍스트로 받아서 확인 return res.text(); }) .then(text => { try { const json = JSON.parse(text); if (json.status === 'success') { alert('삭제 완료'); loadProductData(); // 목록 새로고침 } else { alert(json.message || '삭제 실패'); } } catch (e) { console.error('응답 파싱 에러:', text); alert('서버 응답 처리 중 오류가 발생했습니다.'); } }) .catch(err => { console.error('통신 에러:', err); alert('서버와 통신할 수 없습니다.'); }); } }; } // 3. 저장 버튼 document.getElementById('prodSave').onclick = () => { // 현재 사용 중인 grid const g = w2ui.productGrid if (!g) return const changes = g.getChanges() if (!changes.length) { w2alert('변경된 내용이 없습니다.') return } const inserts = [] const updates = [] changes.forEach(c => { const rec = g.get(c.recid) if (!rec) return // 🔥 핵심: 원본 rec + 변경값 c 병합 const merged = { ...rec, ...c } if (rec.__isNew) { // INSERT → 전체 row 필요 inserts.push(merged) } else { // UPDATE → PK + 변경 컬럼 updates.push({ itm_cd : merged.itm_cd, itm_nm : merged.itm_nm, area : merged.area, itm_amt: merged.itm_amt, use_yn : merged.use_yn, rmks : merged.rmks }) } }) console.log('INSERTS', inserts) console.log('UPDATES', updates) fetch('/kngil/bbs/adm_product_popup_save.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'save', inserts, updates }) }) .then(res => { // 서버가 준 응답이 괜찮은지 확인 if (!res.ok) throw new Error('서버 응답 오류'); return res.json(); // 처음부터 깔끔하게 데이터로 읽기 }) .then(json => { // 이제 json.status를 바로 쓸 수 있습니다. if (json.status === 'success') { w2alert('저장 완료'); w2ui.productGrid.save(); // 빨간 삼각형 없애기 loadProductData(); // 목록 새로고침 } else { w2alert(json.message || '저장 실패'); } }) .catch(err => { console.error('에러 발생:', err); w2alert('처리 중 오류가 발생했습니다.'); }); }; } } }) } //상품등록 그리드 export async function createProductGrid(boxId) { if (w2ui.productGrid) w2ui.productGrid.destroy(); destroyGrid('productGrid') const authItems = await loadBaseCode('BS210') const grid = new w2grid({ name: 'productGrid', box: boxId, show: { footer: true, selectColumn: true, lineNumbers: true // 행 번호를 표시하면 디버깅이 편합니다. }, columns: [ /* { field: 'row_status', text: ' ', size: '30px', attr: 'align=center', render: function (record) { // 1. 신규 추가된 행 (recid가 임시값이거나 DB에 없는 경우) if (record.is_new) return 'I'; // 2. 수정된 데이터 (w2ui.changes 객체가 존재하는 경우) if (record.w2ui && record.w2ui.changes) return 'U'; // 3. 일반 상태 return ' '; } }, */ { field: 'itm_cd', text: '상품코드', size: '80px',attr: 'align=center',style: 'text-align: center', attr: 'align=center', editable: { type: 'text' } ,sortable: true}, // name 아님! { field: 'itm_nm', text: '상품명', size: '120px', attr: 'align=center',style: 'text-align: center', editable: { type: 'text' } ,sortable: true}, // name 아님! { field: 'area', text: '제공량', size: '100px', attr: 'align=center',render: 'number:0' , editable: { type: 'float' } ,sortable: true}, // volume 아님! { field: 'itm_amt', text: '단가', size: '120px', attr: 'align=center',render: 'number:0', editable: { type: 'int' } ,sortable: true}, // { field: 'use_yn', text: '사용여부', size: '80px',attr: 'align=center',style: 'text-align: center', attr: 'align=center', editable: { type: 'list', items: authItems, filter: false ,showAll: true } , render(record) { const item = authItems.find(i => i.id === record.use_yn) return item ? item.text : record.use_yn },sortable: true }, { field: 'rmks', text: '비고', size: '200px', attr: 'align=center', editable: { type: 'text' } ,sortable: true} // memo 아님! ], records: [] // 처음엔 비워둠 }); // 데이터 호출 함수 실행 loadProductData(); return grid; } // 데이터를 서버에서 불러오는 함수 async function loadProductData() { try { w2ui.productGrid.lock('조회 중...', true); const response = await fetch('/kngil/bbs/adm_product_popup.php'); // PHP 파일 호출 const data = await response.json(); w2ui.productGrid.clear(); w2ui.productGrid.add(data); w2ui.productGrid.unlock(); } catch (e) { console.error(e); w2ui.productGrid.unlock(); w2alert('데이터 로드 실패'); } }