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 @@