(function() { 'use strict'; class NewPatientPage { constructor() { this.choicesInstances = new Map(); this.data = { nationality: '', nationalityCode: '', visitPath: '' }; this.isInitialized = false; this.KOREA_CODE = 'C202404180007'; this.allowSystemCheck = false; } init() { if (this.isInitialized) return; if (!this.validateDependencies() || !this.validateDOM()) { this.scheduleRetry(); return; } this.initChoices(); this.loadCommonCategories(); this.bindEvents(); this.isInitialized = true; $('input').attr('autocomplete', 'off'); } validateDependencies() { return !!($ && window.Choices); } validateDOM() { return !!(document.querySelector('#selectNationality')); } scheduleRetry() { setTimeout(() => this.init(), 150); } bindEvents() { const $rrn1 = $('input[name="modalUserRrn1"]'); const $rrn2 = $('input[name="modalUserRrn2"]'); $rrn2.on('keyup input', (e) => { const rrn1Val = $rrn1.val(); const rrn2Val = $(e.target).val(); if (rrn1Val.length === 6 && rrn2Val.length >= 1) { this.handleRrnInput(rrn1Val, rrn2Val.charAt(0)); } }); const nationalityInstance = this.choicesInstances.get('nationality'); if (nationalityInstance) { const element = nationalityInstance.passedElement.element; element.addEventListener('change', (event) => { this.data.nationalityCode = event.detail.value; this.updateUIByNationality(event.detail.value); }); } $('#address, #btnSearchAddress').on('click', () => { this.openAddrSearch(); }); const consentIds = ['#agreePrivacy', '#agreeProcedure', '#agreeTerms', '#refusePhoto']; $(consentIds.join(', ')).on('click', (e) => { if (!this.allowSystemCheck) { e.preventDefault(); alert('동의서 보기 버튼을 클릭하여 내용을 확인하신 후 [동의함] 버튼을 눌러주세요.'); } }); $('#btnFillTestData').on('click', () => { // 1. 기본 텍스트 정보 $('input[name="modalUserName"]').val('홍길동'); $('input[name="modalUserRrn1"]').val('950101'); $('input[name="modalUserRrn2"]').val('1234567').trigger('input'); // input 트리거로 생년월일/성별 로직 실행 $('input[name="modalPhoneNumber"]').val('01012345678'); $('input[name="address"]').val('서울특별시 강남구 테헤란로 123'); $('input[name="addressDtl"]').val('메이드유 빌딩 5층'); $('#email').val('test@madeu.com'); $('input[name="introName"]').val('관리자'); $('textarea[name="modalEtc"]').val('특이사항 없음 (테스트 데이터)'); // 2. 방문경로 (Choices.js 인스턴스 제어) const channelInstance = this.choicesInstances.get('channel'); if (channelInstance) { const firstVal = channelInstance.config.choices[1]?.value; // 첫 번째 옵션 선택 if (firstVal) channelInstance.setChoiceByValue(firstVal); } // 3. 동의서 항목 강제 체크 // 시스템 체크 허용 플래그를 일시적으로 켜서 click 방지 로직을 우회합니다. this.allowSystemCheck = true; $('#agreePrivacy, #agreeProcedure, #agreeTerms, #refusePhoto').prop('checked', true); this.allowSystemCheck = false; //alert('테스트 데이터가 입력되었습니다.'); }); } updateUIByNationality(selectedCode) { const $rrnLabel = $('label[for="modalUserRrn1"], .form-row:has(input[name="modalUserRrn1"]) label').first(); const $passportBox = $('.foreigner_box'); if (selectedCode === this.KOREA_CODE) { $rrnLabel.text('주민등록번호'); $passportBox.hide(); } else { $rrnLabel.text('외국인등록번호'); $passportBox.show(); } } handleRrnInput(rrn1, genderDigitStr) { const genderDigit = parseInt(genderDigitStr, 10); const isMale = [1, 3, 5, 7].includes(genderDigit); if (isMale) $('#genderM').prop('checked', true); else $('#genderF').prop('checked', true); let yearPrefix = [1, 2, 5, 6].includes(genderDigit) ? '19' : '20'; const year = yearPrefix + rrn1.substring(0, 2); const month = rrn1.substring(2, 4); const day = rrn1.substring(4, 6); $('#modalBirthday').val(`${year}${month}${day}`); const today = new Date(); let age = today.getFullYear() - parseInt(year); const birthDate = new Date(year, month - 1, day); const m = today.getMonth() - birthDate.getMonth(); if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) age--; $('.txtAge').text(`만 ${age}세`); } initChoices() { const choicesConfig = { searchEnabled: true, itemSelectText: '', shouldSort: false, placeholderValue: '선택하세요' }; ['nationality', 'channel'].forEach(key => { const selector = key === 'nationality' ? '#selectNationality' : '#selectChannel'; this.choicesInstances.set(key, new Choices(selector, choicesConfig)); }); } loadCommonCategories() { const categories = [{ code: 'C202404110001', key: 'nationality' }, { code: 'C202404110003', key: 'channel' }]; categories.forEach(({ code, key }) => this.fetchCategory(code, key)); } fetchCategory(code, choicesKey) { $.post('/kiosk/getCategoryItem.do', { categoryCode: code }, (data) => { if (data.rows?.length > 0) { const choices = data.rows.map(item => ({ value: item.categoryItemCode || item.commonCode, label: item.categoryItemName || item.codeName })); const instance = this.choicesInstances.get(choicesKey); if (instance) { instance.setChoices(choices, 'value', 'label', true); if (choicesKey === 'nationality') { instance.setChoiceByValue(this.KOREA_CODE); this.data.nationalityCode = this.KOREA_CODE; this.updateUIByNationality(this.KOREA_CODE); } } } }); } openAddrSearch() { let $addrDialog = $('#addrSearchDialog'); if ($addrDialog.length === 0) { $addrDialog = $('
').appendTo('body'); } $addrDialog.dialog({ modal: true, title: '주소 검색', width: 500, height: 500, resizable: false, draggable: true, open: function() { const guideElement = document.getElementById('addrSearchDialog'); new daum.Postcode({ oncomplete: (data) => { let addr = data.userSelectedType === 'R' ? data.roadAddress : data.jibunAddress; document.getElementById("address").value = addr; document.getElementById("addressDtl").focus(); $addrDialog.dialog('close'); }, width: '100%', height: '100%' }).embed(guideElement); }, close: function() { $(this).dialog('destroy').empty(); } }); } // NewPatientPage 클래스 내부에 추가 savePatientData(signatureData) { // 서버 UserDTO 구조와 매핑될 데이터 수집 const param = { userName: $('input[name="modalUserName"]').val(), nationality: this.data.nationalityCode, // Choices로 선택된 코드값 nationalityCode: 'C202404110001', // 국적 카테고리 고정값 birthday: $('#modalBirthday').val(), gender: $('input[name="modalGender"]:checked').val(), userRrn1: $('input[name="modalUserRrn1"]').val(), userRrn2: $('input[name="modalUserRrn2"]').val(), userPno: $('input[name="modalUserPno"]').val(), phoneNumber: $('input[name="modalPhoneNumber"]').val(), channel: $('#selectChannel').val(), channelCode: 'C202404110003', // 방문경로 카테고리 고정값 introUserId: $('input[name="modalRecommendId"]').val(), // 추천인 텍스트 etc: $('textarea[name="modalEtc"]').val(), smsYn: $('input[name="modalSmsYn"]:checked').val(), refusePhotoYn: $('#refusePhoto').is(':checked') ? 'Y' : 'N', signatureData: signatureData, // 서명 Base64 데이터 address: $('#address').val(), addressDtl: $('#addressDtl').val(), email: $('#email').val(), introName: $('#introName').val() }; // 로딩바가 있다면 여기서 표시 (예: $.blockUI();) console.log(param); $.ajax({ url: '/kiosk/putUser.do', type: 'POST', contentType: 'application/json', data: JSON.stringify(param), success: (res) => { // Controller의 resultMap.put("success", true)와 대응 if (res.success) { alert(res.msgDesc || '고객 등록이 완료되었습니다.'); location.href = '/kiosk'; // 완료 후 메인으로 이동 } else { alert(res.msgDesc || '저장에 실패했습니다.'); } }, error: (xhr) => { alert('서버와 통신 중 오류가 발생했습니다.'); console.error(xhr); } }); } } /** * [Utility] 서명 다이얼로그 관리 클래스 */ class SignatureDialogManager { constructor(modalId = 'agreementInsertModal') { this.modalId = modalId; this.callback = null; this.signaturePad = null; } init() { $(`#${this.modalId}`).remove(); $('body').append(this.getHtmlTemplate()); const $modal = $(`#${this.modalId}`); $modal.dialog({ autoOpen: false, modal: true, width: 500, resizable: false, draggable: true, dialogClass: 'signature-ui-dialog', open: () => { this.initSignaturePad(); $(".ui-dialog-titlebar").hide(); } }); this.setEvent(); } initSignaturePad() { const canvas = document.querySelector(`#${this.modalId} canvas`); if (!canvas) return; try { this.signaturePad = new SignaturePad(canvas, { backgroundColor: 'rgb(255, 255, 255)', penColor: 'rgb(0, 0, 0)' }); this.resizeCanvas(canvas); } catch (e) { console.error("SignaturePad 로드 실패."); } } resizeCanvas(canvas) { const ratio = Math.max(window.devicePixelRatio || 1, 1); canvas.width = canvas.offsetWidth * ratio; canvas.height = canvas.offsetHeight * ratio; canvas.getContext("2d").scale(ratio, ratio); if (this.signaturePad) this.signaturePad.clear(); } setEvent() { const $modal = $(`#${this.modalId}`); $modal.find('.btnCancle').on('click', () => $modal.dialog('close')); $modal.find('.btnReset').on('click', () => { if (this.signaturePad) this.signaturePad.clear(); }); $modal.find('.btnSave').on('click', () => { if (this.signaturePad && this.signaturePad.isEmpty()) { alert("서명을 진행해 주세요."); return; } const dataUrl = this.signaturePad.toDataURL(); if (this.callback) this.callback(dataUrl); $modal.dialog('close'); }); } open(callback) { this.init(); this.callback = callback; $(`#${this.modalId}`).dialog('open'); } getHtmlTemplate() { return ` `; } } $(document).ready(() => { const signatureDialog = new SignatureDialogManager(); const pageApp = new NewPatientPage(); window.newPatientPage = pageApp; pageApp.init(); $('.btnSave').on('click', function(e) { e.preventDefault(); if (validateForm()) { //alert("검증 완료! 서명 단계로 이동합니다."); if (typeof signatureDialog !== 'undefined') { signatureDialog.open((signatureData) => { // 실제 저장 로직 호출 예시: pageApp.savePatientData(signatureData); console.log("서명 완료", signatureData); pageApp.savePatientData(signatureData); }); } } }); $('.consent-link').on('click', function(e) { e.preventDefault(); openConsentDialog($(this).data('type')); }); function openConsentDialog(type) { if ($('#dynamicConsentDialog').length) $('#dynamicConsentDialog').dialog('destroy').remove(); const $dialog = $(''); let isAgreed = false; $dialog.dialog({ modal: true, width: 800, height: 700, title: getDialogTitle(type), resizable: false, draggable: true, buttons: [ { text: "동의함", class: "registration_bth", click: function() { isAgreed = true; pageApp.allowSystemCheck = true; $('#' + type).prop('checked', true); pageApp.allowSystemCheck = false; $(this).dialog('close'); } }, { text: "닫기", class: "cancel_btn", click: function() { $(this).dialog('close'); } } ], close: function() { if (!isAgreed) { pageApp.allowSystemCheck = true; $('#' + type).prop('checked', false); pageApp.allowSystemCheck = false; } $(this).dialog('destroy').remove(); } }); $dialog.html('