From 6571d4684a882e305b51f41ad6f5c6245ca7b918 Mon Sep 17 00:00:00 2001 From: pjs Date: Mon, 19 Jan 2026 20:58:02 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B6=94=EC=B2=9C=EC=9D=B8=20=EA=B2=80?= =?UTF-8?q?=EC=83=89,=20=EC=84=9C=EB=AA=85=ED=8C=A8=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../static/css/kiosk/new-patient.css | 122 ++++ .../resources/static/js/kiosk/new-patient.js | 363 +++++++++++- .../resources/static/js/kiosk/new-patient2.js | 548 ------------------ .../templates/kiosk/new-patient.html | 7 +- 4 files changed, 478 insertions(+), 562 deletions(-) delete mode 100644 src/main/resources/static/js/kiosk/new-patient2.js diff --git a/src/main/resources/static/css/kiosk/new-patient.css b/src/main/resources/static/css/kiosk/new-patient.css index 668f065..a722bad 100644 --- a/src/main/resources/static/css/kiosk/new-patient.css +++ b/src/main/resources/static/css/kiosk/new-patient.css @@ -631,4 +631,126 @@ button { display: flex; justify-content: center; align-items: center; +} + + + + +/* 고객 검색 모달 커스텀 스타일 */ +.user-select-dialog { + padding: 0 !important; + overflow: hidden !important; + border-radius: 12px !important; + border: none !important; + box-shadow: 0 10px 25px rgba(0,0,0,0.1) !important; +} + +.search-header { + padding: 24px 24px 16px; + background: #ffffff; +} + +.search-input-wrapper { + display: flex; + gap: 8px; + padding: 4px; + background: #f1f3f5; + border-radius: 10px; + border: 2px solid transparent; + transition: all 0.2s ease; +} + +.search-input-wrapper:focus-within { + background: #ffffff; + border-color: #4dabf7; + box-shadow: 0 0 0 4px rgba(77, 171, 247, 0.1); +} + +.search-input-wrapper input { + flex: 1; + border: none; + background: transparent; + padding: 10px 12px; + font-size: 15px; + outline: none; +} + +.btn-search { + background: #228be6; + color: #fff; + border: none; + border-radius: 8px; + padding: 0 20px; + font-weight: 600; + cursor: pointer; + transition: background 0.2s; +} + +.btn-search:hover { background: #1c7ed6; } + +.table-wrapper { + padding: 0 24px 20px; + max-height: 380px; + overflow-y: auto; +} + +.user-table { + width: 100%; + border-collapse: collapse; +} + +.user-table thead th { + position: sticky; + top: 0; + background: #ffffff; + padding: 12px 10px; + text-align: left; + font-size: 13px; + color: #868e96; + border-bottom: 2px solid #f1f3f5; + z-index: 1; +} + +.user-table tbody tr { + cursor: pointer; + transition: background 0.1s; +} + +.user-table tbody tr:hover { background: #f8f9fa; } + +.user-table tbody td { + padding: 16px 10px; + font-size: 15px; + color: #343a40; + border-bottom: 1px solid #f1f3f5; +} + +.user-name { font-weight: 700; color: #212529; } + +.gender-tag { + display: inline-block; + padding: 2px 10px; + border-radius: 20px; + font-size: 12px; + font-weight: 600; +} + +.gender-M { background: #e7f5ff; color: #1971c2; } +.gender-F { background: #fff0f6; color: #d6336c; } + +.modal-footer-ui { + padding: 16px 24px; + background: #f8f9fa; + text-align: right; + border-top: 1px solid #e9ecef; +} + +.btn-close-ui { + background: #dee2e6; + color: #495057; + border: none; + padding: 10px 24px; + border-radius: 8px; + font-weight: 600; + cursor: pointer; } \ No newline at end of file diff --git a/src/main/resources/static/js/kiosk/new-patient.js b/src/main/resources/static/js/kiosk/new-patient.js index db40abe..009fc37 100644 --- a/src/main/resources/static/js/kiosk/new-patient.js +++ b/src/main/resources/static/js/kiosk/new-patient.js @@ -24,6 +24,7 @@ this.loadCommonCategories(); this.bindEvents(); this.isInitialized = true; + } validateDependencies() { return !!($ && window.Choices); } @@ -63,6 +64,8 @@ alert('동의서 보기 버튼을 클릭하여 내용을 확인하신 후 [동의함] 버튼을 눌러주세요.'); } }); + + } updateUIByNationality(selectedCode) { @@ -128,18 +131,341 @@ } openAddrSearch() { - new daum.Postcode({ - oncomplete: (data) => { - let addr = data.userSelectedType === 'R' ? data.roadAddress : data.jibunAddress; - document.getElementById("modalAddress").value = addr; - document.getElementById("modalAddressDetail").focus(); - } - }).open(); - } - } + // 1. 다이얼로그를 담을 컨테이너 생성 (없으면 생성) + let $addrDialog = $('#addrSearchDialog'); + if ($addrDialog.length === 0) { + $addrDialog = $('').appendTo('body'); + } + // 2. jQuery UI Dialog 초기화 + $addrDialog.dialog({ + modal: true, + title: '주소 검색', + width: 500, + height: 500, + resizable: false, + draggable: true, + open: function() { + const guideElement = document.getElementById('addrSearchDialog'); + // 3. daum.Postcode를 해당 div 내(embed)에 실행 + new daum.Postcode({ + oncomplete: (data) => { + let addr = data.userSelectedType === 'R' ? data.roadAddress : data.jibunAddress; + document.getElementById("modalAddress").value = addr; + document.getElementById("modalAddressDetail").focus(); + + // 선택 완료 후 다이얼로그 닫기 + $addrDialog.dialog('close'); + }, + width: '100%', + height: '100%' + }).embed(guideElement); + }, + close: function() { + $(this).dialog('destroy').empty(); + } + }); + } + } + + + /** + * [Modal] 고객 검색 팝업 클래스 + * 작성일 : 2024. 04. 02. + * 작성자 : NTsoft (Refactored to Class) + */ + /** + * [Modal] 고객 검색 팝업 클래스 (jQuery UI Dialog 버전) + */ + class UserIntroSelectModal { + constructor() { + this.callback = null; + this.dataList = null; + this.modalId = 'userIntroSelectModal'; + } + + init() { + $(`#${this.modalId}`).remove(); + $('body').append(this.getHtmlTemplate()); + + $(`#${this.modalId}`).dialog({ + autoOpen: false, + modal: true, + width: 450, // 3개 항목이므로 너비를 좀 더 슬림하게 조정 + resizable: false, + draggable: true, + dialogClass: 'user-select-dialog', // CSS 커스텀 클래스 연결 + open: function() { + $(".ui-dialog-titlebar").hide(); // 타이틀바 숨김 + $('.ui-widget-overlay').css({ 'opacity': 0.5, 'background': '#000' }); + } + }); + + this.setEvent(); + } + + setEvent() { + const $modal = $(`#${this.modalId}`); + $modal.find('.btnCancle').on("click", () => $modal.dialog("close")); + + $modal.find('#searchIntroUserBtn').on('click', () => this.searchIntroUserList()); + $modal.find('#introUserSearchKeyword').on('keypress', (e) => { + if (e.which === 13) this.searchIntroUserList(); + }); + } + + searchIntroUserList() { + const searchKeyword = document.querySelector("#introUserSearchKeyword").value; + if (searchKeyword.length < 2) { + alert("검색어를 2자 이상 입력해주세요."); + return; + } + + const formData = new FormData(); + formData.append("menuClass", window.menuClass || ""); + formData.append("userSearchKeywordParam", searchKeyword); + // 정렬 파라미터 추가 + formData.append("userSort", "BIRTHDAY DESC"); + + $.ajax({ + url: encodeURI('/webuser/selectListUserOption.do'), + data: formData, + dataType: "json", + processData: false, + contentType: false, + type: 'POST', + success: (data) => { + if (data.msgCode === '0') this.renderTable(data.rows); + } + }); + } + + renderTable(rows) { + const tbody = document.querySelector(`#${this.modalId} tbody`); + tbody.innerHTML = ""; + this.dataList = rows; + + if (!rows || rows.length === 0) { + tbody.innerHTML = '조회 결과가 없습니다.'; + return; + } + + rows.forEach((user, index) => { + const genderClass = (user.gender === '남' || user.gender === 'M') ? 'gender-M' : 'gender-F'; + const tr = document.createElement('tr'); + tr.innerHTML = ` + ${user.userName} + ${this.convertDateFormat(user.birthday)} + ${user.gender} + `; + tr.onclick = () => { + if (this.callback) this.callback(user); + $(`#${this.modalId}`).dialog("close"); + }; + tbody.appendChild(tr); + }); + } + + popup(callback) { + this.init(); + this.callback = callback; + $(`#${this.modalId}`).dialog("open"); + } + + convertDateFormat(input) { + if (!input) return '-'; + const dateMatch = input.match(/\d{4}-\d{2}-\d{2}/); + return dateMatch ? dateMatch[0].replace(/-/g, '.') : input; + } + + getHtmlTemplate() { + return ` + `; + } + } + + /** + * [Utility] 서명 다이얼로그 관리 클래스 (jQuery UI 버전) + */ + class SignatureDialogManager { + constructor(modalId = 'agreementInsertModal') { + this.modalId = modalId; + this.callback = null; + this.signaturePad = null; + } + + /** + * 다이얼로그 초기화 및 DOM 생성 + */ + init() { + $(`#${this.modalId}`).remove(); + $('body').append(this.getHtmlTemplate()); + + const $modal = $(`#${this.modalId}`); + + // jQuery UI Dialog 설정 + $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'); + }); + } + + /** + * 다이얼로그 오픈 + * @param {Function} callback 서명 완료 후 실행될 함수 + */ + open(callback) { + this.init(); + this.callback = callback; + $(`#${this.modalId}`).dialog('open'); + } + + /** + * HTML 템플릿 + */ + getHtmlTemplate() { + return ` + `; + } + } + + $(document).ready(() => { - const pageApp = new NewPatientPage(); + + // 클래스 인스턴스 생성 (기존 소스와 호환성을 위해 변수명 유지 가능) + const userIntroSelectModal = new UserIntroSelectModal(); + + const signatureDialog = new SignatureDialogManager(); + $('.registration_bth').on('click', (e) => { + e.preventDefault(); + + + // 2. 서명 모달 오픈 (jQuery UI 기반으로 커스텀한 경우) + if (typeof signatureDialog !== 'undefined') { + signatureDialog.open((signatureData) => { + // 서명 완료 시 실행될 콜백: 여기서 실제 서버 전송(Ajax) 함수 호출 + this.savePatientData(signatureData); + }); + } + }); + const pageApp = new NewPatientPage(); window.newPatientPage = pageApp; pageApp.init(); @@ -147,7 +473,22 @@ e.preventDefault(); openConsentDialog($(this).data('type')); }); + $('.searchIntroUser').on('click', function() { + // 모달 팝업 호출 + userIntroSelectModal.popup(function(data) { + // [Callback] 고객을 선택했을 때 실행될 로직 + console.log("선택된 추천인 정보:", data); + + // 1. input 필드에 선택된 사용자의 이름 표시 + $('input[name="modalRecommendId"]').val(data.userName); + + // 2. (옵션) 실제 DB 저장을 위한 ID값 등을 hidden 필드에 저장할 경우 + // if ($('#recommendUserNo').length > 0) { + // $('#recommendUserNo').val(data.muUserId); + // } + }, { type: "recommend" }); // 필요 시 요청 파라미터 전달 + }); function openConsentDialog(type) { if ($('#dynamicConsentDialog').length) $('#dynamicConsentDialog').dialog('destroy').remove(); @@ -209,7 +550,7 @@ 'agreePrivacy': '개인정보 수집 및 이용안내', 'agreeProcedure': '시술동의서', 'agreeTerms': '이용약관', - 'refusePhoto': '사진촬영거부동의서' + 'refusePhoto': '사진촬영동의서' }; return titles[type] || '동의서'; } diff --git a/src/main/resources/static/js/kiosk/new-patient2.js b/src/main/resources/static/js/kiosk/new-patient2.js deleted file mode 100644 index 2a96a6e..0000000 --- a/src/main/resources/static/js/kiosk/new-patient2.js +++ /dev/null @@ -1,548 +0,0 @@ -(function() { - 'use strict'; - - class NewPatientPage { - constructor() { - this.choicesInstances = new Map(); - this.data = { - nationality: '', - nationalityCode: '', - userType: '', - visitPath: '', - treatment: '' - }; - this.datepickerInstance = null; - this.isInitialized = false; - this.userModalRetryCount = 0; - } - - init() { - if (this.isInitialized) return; - - if (!this.validateDependencies()) { - this.scheduleRetry(); - return; - } - - if (!this.validateDOM()) { - this.scheduleRetry(); - return; - } - - this.initializeComponents(); - this.isInitialized = true; - console.log('✅ NewPatientPage 초기화 완료'); - } - - validateDependencies() { - return !!($ && window.Choices); - } - - validateDOM() { - const requiredElements = [ - '#selectNationality', '#selectUserType', '#selectTreatment', - '#selectChannel', '#selectIdentification', '#newPatientForm' - ]; - return requiredElements.every(selector => document.querySelector(selector)); - } - - scheduleRetry() { - setTimeout(() => this.init(), 150); - } - - initializeComponents() { - this.initChoices(); - this.initUserIntroModal(); // 내장 모달 초기화 - this.loadCommonCategories(); - this.initDatepicker(); - this.bindEvents(); - } - - initChoices() { - const choicesConfig = { - searchEnabled: true, - searchPlaceholderValue: '검색...', - noResultsText: '결과 없음', - noChoicesText: '선택 가능한 항목이 없습니다', - itemSelectText: '선택', - removeItemButton: false, - shouldSort: false, - placeholderValue: '선택하세요' - }; - - const selectors = { - nationality: { id: '#selectNationality', key: 'nationality', placeholder: '국적 선택' }, - userType: { id: '#selectUserType', key: 'userType', placeholder: '고객구분 선택' }, - treatment: { id: '#selectTreatment', key: 'treatment', placeholder: '관심진료 선택' }, - channel: { id: '#selectChannel', key: 'channel', placeholder: '방문경로 선택' }, - identification: { - id: '#selectIdentification', - key: 'identification', - config: { searchEnabled: false, placeholder: false } - } - }; - - Object.entries(selectors).forEach(([key, config]) => { - try { - const instance = new Choices(config.id, { - ...choicesConfig, - placeholder: true, - placeholderValue: config.placeholder, - ...(config.config || {}) - }); - this.choicesInstances.set(config.key, instance); - } catch (e) { - console.error(`Choices 초기화 실패 (${key}):`, e); - } - }); - - this.toggleForeignerBox(false); - this.bindChoicesEvents(); - } - - // 🔥 내장형 userIntroSelectModal - initUserIntroModal() { - window.userIntroSelectModal = { - callback: null, - dataList: null, - - popup(callback) { - this.callback = callback; - this.initModal(); - setTimeout(() => $('#userIntroSelectModal').modal('show'), 200); - }, - - initModal() { - if ($('#userIntroSelectModal').length) { - $('#userIntroSelectModal').remove(); - } - $('body').append(this.htmlTemplate); - this.bindModalEvents(); - }, - - bindModalEvents() { - $('#userIntroSelectModal .btnCancle').off().on('click', () => this.close()); - $('#searchIntroUserBtn').off().on('click', () => this.search()); - $('#introUserSearchKeyword').off('keypress').on('keypress', (e) => { - if (e.key === 'Enter') this.search(); - }); - }, - - search() { - const keyword = $('#introUserSearchKeyword').val()?.trim(); - if (keyword.length < 2) { - this.showAlert('검색어는 2자 이상 입력하세요.'); - return; - } - - $.ajax({ - url: '/kiosk/getUserOptionList.do', - method: 'POST', - data: { userSearchKeywordParam: keyword }, - dataType: 'json', - success: (data) => { - if (data.msgCode === '0') { - this.dataList = data.rows || []; - this.renderResults(this.dataList); - } else { - this.showAlert('검색 결과가 없습니다.'); - } - }, - error: () => this.showAlert('검색 중 오류가 발생했습니다.') - }); - }, - - renderResults(users) { - const $tbody = $('#userIntroSelectModal tbody'); - $tbody.empty(); - - if (users.length === 0) { - $tbody.html('검색결과가 없습니다.'); - return; - } - - users.forEach((user, index) => { - const $row = $(` - - ${user.username || ''} - ${this.formatDate(user.birthday)} - ${user.gender || ''} - ${this.formatPhone(user.phonenumber)} - ${user.lastvisitdate || ''} - - `); - $tbody.append($row); - }); - - $('.user-row').off('click').on('click', (e) => { - const index = $(e.currentTarget).data('index'); - this.selectUser(index); - }); - }, - - selectUser(index) { - if (this.dataList?.[index]) { - this.callback(this.dataList[index]); - } - this.close(); - }, - - formatDate(dateStr) { - if (!dateStr) return ''; - try { - const date = new Date(dateStr.match(/\d{4}-\d{2}-\d{2}/)?.[0]); - if (isNaN(date)) return ''; - return date.toISOString().slice(0, 10).replace(/-/g, '.'); - } catch { - return ''; - } - }, - - formatPhone(phone) { - if (!phone) return ''; - return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'); - }, - - showAlert(message) { - if (window.modalEvent) { - window.modalEvent.warning('', message); - } else { - alert(message); - } - }, - - close() { - $('#userIntroSelectModal').modal('hide'); - setTimeout(() => $('#userIntroSelectModal').remove(), 500); - }, - - htmlTemplate: ` - ` - }; - } - - bindChoicesEvents() { - const idSelect = document.getElementById('selectIdentification'); - if (idSelect) { - idSelect.addEventListener('change', (e) => { - const isPassport = e.target.value === 'pno'; - $('.passport_number_box').toggle(isPassport); - $('.foreigner_number_box').toggle(!isPassport); - }); - } - - const eventMap = { - 'selectNationality': (e) => this.handleNationalityChange(e), - 'selectUserType': (e) => this.data.userType = e.target.value, - 'selectTreatment': (e) => this.data.treatment = e.target.value, - 'selectChannel': (e) => this.handleChannelChange(e) - }; - - Object.entries(eventMap).forEach(([id, handler]) => { - const element = document.getElementById(id); - if (element) element.addEventListener('change', handler); - }); - } - - handleNationalityChange(event) { - this.data.nationalityCode = event.target.value; - const selectedText = event.target.options[event.target.selectedIndex]?.text || ''; - const isKorean = selectedText.includes('대한민국') || event.target.value.includes('KR') || event.target.value === 'Local'; - this.data.nationality = isKorean ? 'Local' : 'Foreigner'; - this.toggleForeignerBox(!isKorean); - } - - handleChannelChange(event) { - this.data.visitPath = event.target.value; - const selectedText = event.target.options[event.target.selectedIndex]?.text || ''; - if (selectedText.includes('소개')) { - $('.searchIntroUser').show(); - } else { - $('input[name="modalRecommendId"]').val('').removeAttr('data-userid'); - } - } - - toggleForeignerBox(show) { - $('.foreigner_box').toggle(show); - $('.local_box').toggle(!show); - } - - loadCommonCategories() { - const categories = [ - { code: 'C202404110001', key: 'nationality' }, - { code: 'C202404110002', key: 'userType' }, - { code: 'C202404110003', key: 'channel' } - ]; - categories.forEach(({ code, key }) => this.fetchCategory(code, key)); - this.fetchTreatmentList(); - } - - fetchCategory(code, choicesKey) { - $.ajax({ - url: '/kiosk/getCategoryItem.do', - type: 'POST', - data: { categoryCode: code }, - success: (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') { - const defaultItem = choices.find(c => c.label.includes('대한민국')); - if (defaultItem) { - instance.setChoiceByValue(defaultItem.value); - this.data.nationalityCode = defaultItem.value; - this.data.nationality = 'Local'; - } - } - } - } - }, - error: (xhr) => console.error(`카테고리 조회 실패 (${code}):`, xhr.responseText) - }); - } - - fetchTreatmentList() { - $.ajax({ - url: '/kiosk/getTreatmentOptionList.do', - type: 'POST', - success: (data) => { - if (data.rows?.length > 0) { - const choices = data.rows.map(item => ({ - value: item.mutreatmentid || '', - label: item.treatmentname || '' - })); - const instance = this.choicesInstances.get('treatment'); - if (instance) instance.setChoices(choices, 'value', 'label', true); - } - } - }); - } - - initDatepicker() { - const birthdayInput = document.querySelector('input[name="modalBirthday"]'); - if (!birthdayInput) return; - - this.datepickerInstance = flatpickr(birthdayInput, { - locale: "ko", - dateFormat: "Y-m-d", - maxDate: "today", - disableMobile: true, - onChange: (selectedDates) => { - if (selectedDates.length > 0) { - this.calculateAgeAndRrn(selectedDates[0]); - } - } - }); - - $('.date-input-wrapper').off('click.datepicker').on('click.datepicker', (e) => { - e.stopPropagation(); - this.datepickerInstance?.open(); - }); - } - - calculateAgeAndRrn(birthDate) { - const today = new Date(); - let age = today.getFullYear() - birthDate.getFullYear(); - const m = today.getMonth() - birthDate.getMonth(); - if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) age--; - $('.txtAge').text(`만 ${age}세`); - - const yy = String(birthDate.getFullYear()).substring(2); - const mm = String(birthDate.getMonth() + 1).padStart(2, '0'); - const dd = String(birthDate.getDate()).padStart(2, '0'); - $('input[name="modalUserRrn1"]').val(`${yy}${mm}${dd}`); - } - - bindEvents() { - $('.cancel_btn').off('click.newPatient').on('click.newPatient', () => history.back()); - $('.registration_bth').off('click.newPatient').on('click.newPatient', () => this.save()); - - $('input[name="modalPhoneNumber"], input[name="modalPhoneNumber2"]') - .off('input.phoneFormat').on('input.phoneFormat', function() { - this.value = this.value.replace(/[^0-9]/g, '') - .replace(/(\d{3})(\d{3,4})(\d{4})/, '$1-$2-$3').substring(0, 13); - }); - - $('.searchIntroUser').off('click.newPatient').on('click.newPatient', () => { - window.userIntroSelectModal?.popup((obj) => { - $('input[name="modalRecommendId"]').val(obj.username || '').attr('data-userid', obj.muuserid || ''); - }); - }); - } - - async save() { - const formData = this.collectFormData(); - if (!this.validateForm(formData)) return; - - try { - const response = await this.submitForm(formData); - this.handleSaveResponse(response); - } catch (error) { - this.showError('통신 중 오류가 발생했습니다.'); - } - } - - collectFormData() { - return { - userName: $('input[name="modalUserName"]').val()?.trim() || '', - phone: $('input[name="modalPhoneNumber"]').val().replace(/-/g, '') || '', - phone2: $('input[name="modalPhoneNumber2"]').val().replace(/-/g, '') || '', - birthday: $('input[name="modalBirthday"]').val() || '', - gender: $('input[name="modalGender"]:checked').val() || '', - smsYn: $('input[name="modalSmsYn"]:checked').val() || '', - refusePhoto: $('input[name="modalRefusePhotoYn"]:checked').val() || '', - rrn1: $('input[name="modalUserRrn1"]').val() || '', - rrn2: $('input[name="modalUserRrn2"]').val() || '', - pno: $('input[name="modalUserPno"]').val() || '', - arc1: $('input[name="modalUserArc1"]').val() || '', - arc2: $('input[name="modalUserArc2"]').val() || '', - memo: $('textarea[name="modalMemo"]').val() || '', - etc: $('textarea[name="modalEtc"]').val() || '', - introUserId: $('input[name="modalRecommendId"]').attr('data-userid') || '', - ...this.data - }; - } - - validateForm(data) { - const errors = { - userName: !data.userName && '고객명을 입력해주세요.', - phone: (!data.phone || data.phone.length < 10) && '올바른 연락처를 입력해주세요.', - privacy: !$('#agree_privacy').is(':checked') && '개인정보 수집 이용에 동의해야 합니다.' - }; - - const errorMsg = Object.values(errors).find(Boolean); - if (errorMsg && window.modalEvent) { - window.modalEvent.warning('알림', errorMsg); - return false; - } - return true; - } - - submitForm(data) { - return new Promise((resolve, reject) => { - $.ajax({ - url: '/kiosk/putUser.do', - type: 'POST', - data: { - nationality: data.nationality, - nationalityCode: data.nationalityCode, - userName: data.userName, - phoneNumber: data.phone, - phoneNumber2: data.phone2, - birthday: data.birthday, - gender: data.gender, - userRrn1: data.rrn1, - userRrn2: data.rrn2, - userPno: data.pno, - userArc1: data.arc1, - userArc2: data.arc2, - userTypeCode: data.userType, - channelCode: data.visitPath, - muGroupId: data.treatment, - introUserId: data.introUserId, - memo: data.memo, - etc: data.etc, - smsYn: data.smsYn, - refusePhotoYn: data.refusePhoto - }, - success: resolve, - error: reject - }); - }); - } - - handleSaveResponse(data) { - if (data.msgCode === '0') { - if (window.modalEvent) { - window.modalEvent.success('등록 성공', '신규 고객 등록이 완료되었습니다.', () => { - location.href = '/kiosk/kiosk_main'; - }); - } else { - location.href = '/kiosk/kiosk_main'; - } - } else if (window.modalEvent) { - window.modalEvent.danger('오류', data.msgDesc || '등록에 실패했습니다.'); - } - } - - showError(message) { - if (window.modalEvent) { - window.modalEvent.danger('오류', message); - } else { - alert(message); - } - } - - destroy() { - this.choicesInstances.forEach(instance => instance?.destroy()); - this.choicesInstances.clear(); - this.datepickerInstance?.destroy(); - $('#userIntroSelectModal')?.remove(); - this.isInitialized = false; - } - } - - // 싱글톤 인스턴스 관리 - let instance = null; - window.newPatientPage = { - init() { - if (instance) return; - instance = new NewPatientPage(); - instance.init(); - }, - destroy() { - instance?.destroy(); - instance = null; - }, - getInstance() { - return instance; - } - }; - - // 자동 초기화 - const init = () => window.newPatientPage.init(); - - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', init); - } else { - setTimeout(init, 50); - } - window.addEventListener('load', () => setTimeout(init, 100)); -})(); diff --git a/src/main/resources/templates/kiosk/new-patient.html b/src/main/resources/templates/kiosk/new-patient.html index 50893d7..9bea53f 100644 --- a/src/main/resources/templates/kiosk/new-patient.html +++ b/src/main/resources/templates/kiosk/new-patient.html @@ -11,6 +11,7 @@ + @@ -140,7 +141,7 @@
- 시술동의서 보기 + 시술 동의서 보기
@@ -153,10 +154,10 @@
- +