비밀번호 찾기 스타일 적용
This commit is contained in:
@@ -6864,6 +6864,7 @@ select.form-control {
|
||||
min-height: calc(100vh - 200px);
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.account-recovery-container {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,462 +1,383 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kbank_base_layout}">
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_base_layout}">
|
||||
<body>
|
||||
<section layout:fragment="contentFragment" class="content">
|
||||
<div class="content_wrap">
|
||||
<!-- 타이틀 -->
|
||||
<div class="sub_title2" id="title-reset-password">
|
||||
<h2 class="title add8">비밀번호 초기화</h2>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="account-recovery-page">
|
||||
<div class="account-recovery-container">
|
||||
<div class="account-recovery-card">
|
||||
<!-- Logo -->
|
||||
<div class="account-recovery-logo">
|
||||
<img th:src="@{/img/logo/logo_box.png}" alt="광주은행">
|
||||
</div>
|
||||
|
||||
<div class="inner i_cs10 h_inner2">
|
||||
<!-- 탭 메뉴 -->
|
||||
<div class="tab-wrap">
|
||||
<div class="tabs">
|
||||
<ul class="tab_nav tabm">
|
||||
<li><a th:href="@{/account_recovery(tab='findId')}">아이디 찾기</a></li>
|
||||
<li class="active"><a href="">비밀번호 초기화</a></li>
|
||||
</ul>
|
||||
<!-- Header Title -->
|
||||
<h2 class="account-recovery-title">비밀번호 초기화</h2>
|
||||
|
||||
<!-- 비밀번호 초기화 폼 -->
|
||||
<div class="tab active">
|
||||
<div class="form_type">
|
||||
<form id="accountForm" role="form" name="accountForm" th:action="@{/reset_password}"
|
||||
method="post">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||
<input type="hidden" id="mobileNumber" name="mobileNumber" th:value="${mobileNumber}">
|
||||
<!-- Tab Navigation -->
|
||||
<div class="account-recovery-tabs">
|
||||
<a th:href="@{/account_recovery(tab='findId')}" class="tab-link">아이디 찾기</a>
|
||||
<a href="#" class="tab-link active">비밀번호 초기화</a>
|
||||
</div>
|
||||
|
||||
<!-- 성명 입력 -->
|
||||
<div class="info1 p_top2">
|
||||
<p class="title w_tit">
|
||||
<span class="dot">성명</span>
|
||||
</p>
|
||||
<div class="info_line">
|
||||
<div class="info_box1 w_inp4">
|
||||
<input type="text" name="userName"
|
||||
th:value="${userName}" class="common_input_type_1" placeholder="성명"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Alert Messages -->
|
||||
<div id="alertContainer"></div>
|
||||
|
||||
<!-- 아이디 입력 (이메일) -->
|
||||
<div class="info1 pt28">
|
||||
<p class="title w_tit">
|
||||
<span class="dot">이메일 아이디</span>
|
||||
</p>
|
||||
<div class="info_line">
|
||||
<div class="info_box1 w_inp4">
|
||||
<input type="text" name="loginId" th:value="${loginId}"
|
||||
class="common_input_type_1" placeholder="이메일 아이디">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Account Recovery Form -->
|
||||
<form id="accountForm" role="form" name="accountForm" th:action="@{/reset_password}" method="post" class="account-recovery-form">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||
<input type="hidden" id="mobileNumber" name="mobileNumber" th:value="${mobileNumber}">
|
||||
|
||||
<!-- 휴대폰 번호 입력 -->
|
||||
<div class="info1 pt28">
|
||||
<p class="title w_tit">
|
||||
<span class="dot">휴대폰 번호</span>
|
||||
</p>
|
||||
<div class="info_line">
|
||||
<div class="info_box1 w_inp5">
|
||||
<span class="input">
|
||||
<div class="custom_select ct_sc w_inp10 h_inp2 select_mobile_prefix" id="prefix_select">
|
||||
<div class="select_selected active">선택</div>
|
||||
<ul class="common_selecttype select_hide select_items ct_sc2">
|
||||
<li>010</li>
|
||||
<li>011</li>
|
||||
<li>016</li>
|
||||
<li>017</li>
|
||||
<li>018</li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
||||
<span class="dash">-</span>
|
||||
<span class="input">
|
||||
<input type="tel" maxlength="4" name="phoneMiddle" class="common_input_type_1 w_inp11"
|
||||
placeholder="앞자리" required>
|
||||
</span>
|
||||
<span class="dash">-</span>
|
||||
<span class="input">
|
||||
<input type="tel" maxlength="4" name="phoneLast" class="common_input_type_1 w_inp11"
|
||||
placeholder="뒷자리" required>
|
||||
</span>
|
||||
</div>
|
||||
<div class="btn_check">
|
||||
<a class="common_btn_type_2 cbt btn_auth"
|
||||
th:hx-post="@{/auth/request_auth_number}"
|
||||
hx-include="#mobileNumber"
|
||||
hx-target="#authNumberContainer"
|
||||
hx-swap="none">
|
||||
<span>인증번호 받기</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 인증번호 입력 -->
|
||||
<div class="info1 pt28 auth-number-container" id="authNumberContainer">
|
||||
<p class="title w_tit">
|
||||
<span class="dot">인증번호 입력</span>
|
||||
</p>
|
||||
<div class="info_line">
|
||||
<div class="info_box1 w_inp5">
|
||||
<div class="certify_box">
|
||||
<input type="text" name="authNumber" id="authNumber" maxlength="6"
|
||||
pattern="[0-9]*"
|
||||
inputmode="numeric"
|
||||
class="common_input_type_1 w_input auth-number-input"
|
||||
placeholder="SMS 인증번호" required>
|
||||
<span class="certify_time" id="certify_time">03:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn_check">
|
||||
<a class="common_btn_type_2 cbt btn_verify_auth"
|
||||
th:hx-post="@{/auth/verify_auth_number}"
|
||||
hx-include="#mobileNumber, #authNumber"
|
||||
hx-target="#authNumberValidation"
|
||||
hx-swap="none">
|
||||
<span>인증번호 확인</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="authNumberValidation"></div>
|
||||
<!-- 제출 버튼 -->
|
||||
<div class="btn_application m_top">
|
||||
<a type="button" class="common_btn_type_1 gray btn_cancel"><span>취소</span></a>
|
||||
<div class="btn_gap"></div>
|
||||
<button type="button" class="common_btn_type_1" onclick="validateAndSubmit()"><span>비밀번호 초기화</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Name Field -->
|
||||
<div class="form-group">
|
||||
<label for="userName" class="form-label">성명</label>
|
||||
<input type="text"
|
||||
id="userName"
|
||||
name="userName"
|
||||
th:value="${userName}"
|
||||
class="form-input"
|
||||
placeholder="성명"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<!-- Email ID Field -->
|
||||
<div class="form-group">
|
||||
<label for="loginId" class="form-label">이메일 아이디</label>
|
||||
<input type="email"
|
||||
id="loginId"
|
||||
name="loginId"
|
||||
th:value="${loginId}"
|
||||
class="form-input"
|
||||
placeholder="이메일 아이디"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<!-- Phone Number Fields -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">휴대폰 번호</label>
|
||||
<div class="phone-input-group">
|
||||
<select id="phonePrefix" class="form-select phone-prefix" required>
|
||||
<option value="">선택</option>
|
||||
<option value="010">010</option>
|
||||
<option value="011">011</option>
|
||||
<option value="016">016</option>
|
||||
<option value="017">017</option>
|
||||
<option value="018">018</option>
|
||||
</select>
|
||||
<span class="phone-separator">-</span>
|
||||
<input type="tel"
|
||||
id="phoneMiddle"
|
||||
name="phoneMiddle"
|
||||
maxlength="4"
|
||||
class="form-input phone-middle"
|
||||
placeholder="0000"
|
||||
pattern="[0-9]*"
|
||||
inputmode="numeric"
|
||||
required>
|
||||
<span class="phone-separator">-</span>
|
||||
<input type="tel"
|
||||
id="phoneLast"
|
||||
name="phoneLast"
|
||||
maxlength="4"
|
||||
class="form-input phone-last"
|
||||
placeholder="0000"
|
||||
pattern="[0-9]*"
|
||||
inputmode="numeric"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Auth Number Request Button -->
|
||||
<button type="button" class="auth-request-button" id="requestAuthButton">
|
||||
인증번호 받기
|
||||
</button>
|
||||
|
||||
<!-- Auth Number Input -->
|
||||
<div class="form-group auth-number-group" id="authNumberGroup" style="display: none;">
|
||||
<label for="authNumber" class="form-label">인증번호 입력</label>
|
||||
<div class="auth-input-group">
|
||||
<input type="text"
|
||||
id="authNumber"
|
||||
name="authNumber"
|
||||
maxlength="6"
|
||||
class="form-input auth-input"
|
||||
placeholder="인증번호 6자리"
|
||||
pattern="[0-9]*"
|
||||
inputmode="numeric"
|
||||
required>
|
||||
<span class="auth-timer" id="authTimer">03:00</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Auth Number Verify Button -->
|
||||
<button type="button" class="auth-verify-button" id="verifyAuthButton" style="display: none;">
|
||||
인증번호 확인
|
||||
</button>
|
||||
|
||||
<!-- Submit Buttons -->
|
||||
<div class="form-actions">
|
||||
<button type="button" class="cancel-button" id="cancelButton">취소</button>
|
||||
<button type="submit" class="submit-button" id="submitButton">비밀번호 초기화</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Loading State -->
|
||||
<div class="loading-overlay" id="loadingOverlay">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function() {
|
||||
// 모든 종류의 에러 메시지 처리를 통합
|
||||
const errorMessage = [[${errorMessage}]];
|
||||
const error = [[${error}]];
|
||||
const success = [[${success}]];
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function() {
|
||||
const errorMsg = [[${error}]];
|
||||
if (errorMsg) {
|
||||
showAlert(errorMsg, 'error');
|
||||
}
|
||||
|
||||
if (errorMessage) {
|
||||
customPopups.showAlert(errorMessage);
|
||||
}
|
||||
if (error) {
|
||||
customPopups.showAlert(error);
|
||||
}
|
||||
if (success) {
|
||||
customPopups.showAlert(success);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script th:inline="javascript">
|
||||
// 휴대폰 번호 결합 함수
|
||||
function combineMobileNumber(evt) {
|
||||
let form = $('#accountForm');
|
||||
let prefix = form.find('.select_mobile_prefix .select_selected').text().trim();
|
||||
let middle = form.find('input[name="phoneMiddle"]').val().trim();
|
||||
let last = form.find('input[name="phoneLast"]').val().trim();
|
||||
const paramError = new URL(window.location.href).searchParams.get('error');
|
||||
if (paramError) {
|
||||
showAlert(decodeURIComponent(paramError), 'error');
|
||||
}
|
||||
});
|
||||
|
||||
if (prefix === '선택' || !middle || !last) {
|
||||
customPopups.showAlert('휴대폰 번호를 올바르게 입력해주세요.');
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
// Alert 표시 함수
|
||||
function showAlert(message, type = 'info') {
|
||||
const alertContainer = $('#alertContainer');
|
||||
const alertClass = type === 'error' ? 'alert-error' : type === 'success' ? 'alert-success' : 'alert-info';
|
||||
const iconClass = type === 'error' ? 'fa-exclamation-circle' : type === 'success' ? 'fa-check-circle' : 'fa-info-circle';
|
||||
|
||||
let combinedNumber = `${prefix}-${middle}-${last}`;
|
||||
const alertHtml = `
|
||||
<div class="account-alert ${alertClass}">
|
||||
<i class="fas ${iconClass}"></i>
|
||||
<span>${message}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (combinedNumber.trim().length === 0) {
|
||||
customPopups.showAlert('휴대폰 번호를 올바르게 입력해주세요.');
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
$('#mobileNumber').val(combinedNumber);
|
||||
alertContainer.html(alertHtml);
|
||||
setTimeout(() => alertContainer.empty(), 5000);
|
||||
}
|
||||
|
||||
return combinedNumber;
|
||||
// 휴대폰 번호 결합 함수
|
||||
function combineMobileNumber() {
|
||||
const prefix = $('#phonePrefix').val();
|
||||
const middle = $('#phoneMiddle').val().trim();
|
||||
const last = $('#phoneLast').val().trim();
|
||||
|
||||
if (!prefix || prefix === '' || !middle || !last) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `${prefix}-${middle}-${last}`;
|
||||
}
|
||||
|
||||
// 타이머 변수
|
||||
let countdownInterval;
|
||||
let isAuthNumberRequested = false;
|
||||
let isAuthVerified = false;
|
||||
|
||||
// 인증번호 타이머 시작
|
||||
function startAuthTimer() {
|
||||
clearInterval(countdownInterval);
|
||||
let remainingTime = 180; // 3분
|
||||
|
||||
function updateTimer() {
|
||||
if (remainingTime <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
$('#authTimer').text('시간 초과').css('color', '#FF6B6B');
|
||||
showAlert('입력 시간이 초과되었습니다. 인증번호를 다시 발송해주세요.', 'error');
|
||||
|
||||
// 필드 활성화
|
||||
$('#phonePrefix, #phoneMiddle, #phoneLast').prop('disabled', false);
|
||||
$('#requestAuthButton').prop('disabled', false);
|
||||
isAuthNumberRequested = false;
|
||||
} else {
|
||||
const minutes = Math.floor(remainingTime / 60);
|
||||
const seconds = remainingTime % 60;
|
||||
$('#authTimer').text(`${minutes}:${seconds.toString().padStart(2, '0')}`);
|
||||
remainingTime--;
|
||||
}
|
||||
}
|
||||
|
||||
// 폼 전체 유효성 검증 함수
|
||||
function validateAndSubmit() {
|
||||
const form = document.getElementById('accountForm');
|
||||
updateTimer();
|
||||
countdownInterval = setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
// 성명 검증
|
||||
const userName = form.querySelector('input[name="userName"]').value.trim();
|
||||
if (!userName) {
|
||||
customPopups.showAlert('성명을 입력해주세요.');
|
||||
return false;
|
||||
}
|
||||
// 인증번호 요청 버튼
|
||||
$('#requestAuthButton').on('click', function() {
|
||||
const userName = $('#userName').val().trim();
|
||||
if (!userName) {
|
||||
showAlert('성명을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 이메일 아이디 검증
|
||||
const loginId = form.querySelector('input[name="loginId"]').value.trim();
|
||||
if (!loginId) {
|
||||
customPopups.showAlert('이메일 아이디를 입력해주세요.');
|
||||
return false;
|
||||
}
|
||||
const loginId = $('#loginId').val().trim();
|
||||
if (!loginId) {
|
||||
showAlert('이메일 아이디를 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 이메일 형식 검증
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(loginId)) {
|
||||
customPopups.showAlert('올바른 이메일 형식을 입력해주세요.');
|
||||
return false;
|
||||
}
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(loginId)) {
|
||||
showAlert('올바른 이메일 형식을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 휴대폰 번호 검증
|
||||
const prefix = form.querySelector('.select_mobile_prefix .select_selected').textContent.trim();
|
||||
const phoneMiddle = form.querySelector('input[name="phoneMiddle"]').value.trim();
|
||||
const phoneLast = form.querySelector('input[name="phoneLast"]').value.trim();
|
||||
const mobileNumber = combineMobileNumber();
|
||||
if (!mobileNumber) {
|
||||
showAlert('휴대폰 번호를 올바르게 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (prefix === '선택' || !phoneMiddle || !phoneLast) {
|
||||
customPopups.showAlert('휴대폰 번호를 올바르게 입력해주세요.');
|
||||
return false;
|
||||
}
|
||||
$('#mobileNumber').val(mobileNumber);
|
||||
$('#loadingOverlay').fadeIn(200);
|
||||
|
||||
// 인증번호 요청 여부 검증
|
||||
if (!window.isAuthNumberRequested) {
|
||||
customPopups.showAlert('휴대폰 인증을 먼저 진행해주세요.');
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
url: '/auth/request_auth_number',
|
||||
type: 'POST',
|
||||
data: {
|
||||
mobileNumber: mobileNumber,
|
||||
_csrf: $('input[name="_csrf"]').val()
|
||||
},
|
||||
success: function(response) {
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
|
||||
// 인증 완료 여부 검증
|
||||
const authNumberInput = document.getElementById('authNumber');
|
||||
if (!authNumberInput?.disabled) {
|
||||
customPopups.showAlert('휴대폰 인증을 완료해주세요.');
|
||||
return false;
|
||||
}
|
||||
if (response.valid) {
|
||||
showAlert(response.message || '인증번호가 발송되었습니다.', 'success');
|
||||
|
||||
// 모든 검증을 통과하면 휴대폰 번호 결합 후 form submit
|
||||
combineMobileNumber({
|
||||
preventDefault: () => {
|
||||
}
|
||||
});
|
||||
// 휴대폰 번호 필드 비활성화
|
||||
$('#phonePrefix, #phoneMiddle, #phoneLast').prop('disabled', true);
|
||||
$('#requestAuthButton').prop('disabled', true);
|
||||
|
||||
// 세션 검증을 위한 파라미터 추가
|
||||
const currentAction = form.getAttribute('action');
|
||||
form.setAttribute('action', currentAction + (currentAction.includes('?') ? '&' : '?') + 'showError=true');
|
||||
// 인증번호 입력 영역 표시
|
||||
$('#authNumberGroup').slideDown(300);
|
||||
$('#verifyAuthButton').slideDown(300);
|
||||
|
||||
form.submit();
|
||||
isAuthNumberRequested = true;
|
||||
startAuthTimer();
|
||||
} else {
|
||||
showAlert(response.message || '인증번호 발송에 실패했습니다.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// HTMX 이벤트 리스너
|
||||
document.body.addEventListener('htmx:beforeRequest', function (evt) {
|
||||
combineMobileNumber(evt);
|
||||
});
|
||||
// 인증번호 확인 버튼
|
||||
$('#verifyAuthButton').on('click', function() {
|
||||
if (!isAuthNumberRequested) {
|
||||
showAlert('휴대폰 번호 인증을 먼저 진행해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
document.body.addEventListener('htmx:configRequest', function (evt) {
|
||||
evt.detail.parameters['mobileNumber'] = combineMobileNumber(evt);
|
||||
});
|
||||
const authNumber = $('#authNumber').val().trim();
|
||||
|
||||
// 메인 초기화 및 이벤트 바인딩
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// 기존 휴대폰 번호 복원
|
||||
const mobileNumber = document.getElementById('mobileNumber')?.value;
|
||||
if (mobileNumber) {
|
||||
const mobileParts = mobileNumber.split('-');
|
||||
if (mobileParts.length === 3) {
|
||||
const PrefixSelect = document.querySelector('#prefix_select .select_selected');
|
||||
if (PrefixSelect) {
|
||||
PrefixSelect.textContent = mobileParts[0];
|
||||
}
|
||||
const orgMiddleInput = document.querySelector('[name="phoneMiddle"]');
|
||||
if (orgMiddleInput) {
|
||||
orgMiddleInput.value = mobileParts[1];
|
||||
}
|
||||
const orgLastInput = document.querySelector('[name="phoneLast"]');
|
||||
if (orgLastInput) {
|
||||
orgLastInput.value = mobileParts[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (authNumber.length !== 6) {
|
||||
showAlert('인증번호 6자리를 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 셀렉트 박스 활성화
|
||||
activateSelect();
|
||||
const mobileNumber = $('#mobileNumber').val();
|
||||
$('#loadingOverlay').fadeIn(200);
|
||||
|
||||
// 인증 관련 변수 초기화
|
||||
let countdownInterval;
|
||||
window.isAuthNumberRequested = false;
|
||||
window.isAuthVerified = false;
|
||||
$.ajax({
|
||||
url: '/auth/verify_auth_number',
|
||||
type: 'POST',
|
||||
data: {
|
||||
mobileNumber: mobileNumber,
|
||||
authNumber: authNumber,
|
||||
_csrf: $('input[name="_csrf"]').val()
|
||||
},
|
||||
success: function(response) {
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
|
||||
// 인증번호 타이머 함수
|
||||
function startAuthNumberTimer() {
|
||||
clearInterval(countdownInterval);
|
||||
let remainingTime = 180; // 3분
|
||||
if (response.valid) {
|
||||
showAlert(response.message || '인증이 완료되었습니다.', 'success');
|
||||
|
||||
function updateRemainingTime() {
|
||||
if (remainingTime <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
let timerElement = document.getElementById('certify_time');
|
||||
if (timerElement) {
|
||||
timerElement.textContent = '입력 시간이 초과되었습니다.';
|
||||
}
|
||||
customPopups.showAlert('입력 시간이 초과되었습니다. 인증번호를 다시 발송해주세요.');
|
||||
// 인증번호 입력 필드 비활성화
|
||||
$('#authNumber').prop('disabled', true);
|
||||
$('#verifyAuthButton').prop('disabled', true);
|
||||
|
||||
let form = $('#accountForm');
|
||||
let mobilePrefix = form.find('.select_mobile_prefix');
|
||||
let phoneMiddle = form.find('input[name="phoneMiddle"]');
|
||||
let phoneLast = form.find('input[name="phoneLast"]');
|
||||
let authButton = document.querySelector('.btn_auth');
|
||||
let verifyAuthButton = document.querySelector('.btn_verify_auth');
|
||||
let authNumberInput = document.getElementById('authNumber');
|
||||
clearInterval(countdownInterval);
|
||||
$('#authTimer').text('인증 완료').css('color', '#6BCF7F');
|
||||
|
||||
// 입력 필드 활성화
|
||||
mobilePrefix.removeClass('disabled');
|
||||
phoneMiddle.prop('readonly', false);
|
||||
phoneLast.prop('readonly', false);
|
||||
if (authButton) {
|
||||
authButton.disabled = false;
|
||||
}
|
||||
if (verifyAuthButton) {
|
||||
verifyAuthButton.disabled = true;
|
||||
}
|
||||
if (authNumberInput) {
|
||||
authNumberInput.readOnly = true;
|
||||
}
|
||||
window.isAuthNumberRequested = false;
|
||||
} else {
|
||||
let minutes = Math.floor(remainingTime / 60);
|
||||
let seconds = remainingTime % 60;
|
||||
let timerElement = document.getElementById('certify_time');
|
||||
if (timerElement) {
|
||||
timerElement.textContent = `남은 시간: ${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
remainingTime--;
|
||||
}
|
||||
}
|
||||
isAuthVerified = true;
|
||||
} else {
|
||||
showAlert(response.message || '인증번호가 일치하지 않습니다.', 'error');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#loadingOverlay').fadeOut(200);
|
||||
showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
updateRemainingTime();
|
||||
countdownInterval = setInterval(updateRemainingTime, 1000);
|
||||
}
|
||||
// 폼 제출
|
||||
$('#accountForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// 인증번호 요청 처리 함수
|
||||
function handleAuthNumberRequest(response) {
|
||||
if (response.valid) {
|
||||
let form = $('#accountForm');
|
||||
let mobilePrefix = form.find('.select_mobile_prefix');
|
||||
let phoneMiddle = form.find('input[name="phoneMiddle"]');
|
||||
let phoneLast = form.find('input[name="phoneLast"]');
|
||||
let authButton = document.querySelector('.btn_auth');
|
||||
const userName = $('#userName').val().trim();
|
||||
if (!userName) {
|
||||
showAlert('성명을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
mobilePrefix.addClass('disabled');
|
||||
phoneMiddle.prop('disabled', true);
|
||||
phoneLast.prop('disabled', true);
|
||||
if (authButton) {
|
||||
authButton.disabled = true;
|
||||
}
|
||||
const loginId = $('#loginId').val().trim();
|
||||
if (!loginId) {
|
||||
showAlert('이메일 아이디를 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
window.isAuthNumberRequested = true;
|
||||
startAuthNumberTimer();
|
||||
customPopups.showAlert(response.message || '인증번호가 발송되었습니다.');
|
||||
} else {
|
||||
customPopups.showAlert(response.message || '알 수 없는 오류가 발생했습니다.');
|
||||
let authButton = document.querySelector('.btn_auth');
|
||||
if (authButton) {
|
||||
authButton.disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(loginId)) {
|
||||
showAlert('올바른 이메일 형식을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 인증번호 확인 처리 함수
|
||||
function handleAuthNumberVerification(response) {
|
||||
customPopups.showAlert(response.message);
|
||||
if (response.valid) {
|
||||
let authNumberInput = document.getElementById('authNumber');
|
||||
let verifyAuthButton = document.querySelector('.btn_verify_auth');
|
||||
let timerElement = document.getElementById('certify_time');
|
||||
const mobileNumber = combineMobileNumber();
|
||||
if (!mobileNumber) {
|
||||
showAlert('휴대폰 번호를 올바르게 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (authNumberInput) {
|
||||
authNumberInput.readOnly = true;
|
||||
authNumberInput.disabled = true;
|
||||
}
|
||||
if (verifyAuthButton) {
|
||||
verifyAuthButton.disabled = true;
|
||||
}
|
||||
if (!isAuthNumberRequested) {
|
||||
showAlert('휴대폰 인증을 먼저 진행해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
clearInterval(countdownInterval);
|
||||
if (timerElement) {
|
||||
timerElement.textContent = '인증 완료';
|
||||
}
|
||||
window.isAuthVerified = true;
|
||||
document.dispatchEvent(new Event('authVerified'));
|
||||
}
|
||||
}
|
||||
if (!isAuthVerified) {
|
||||
showAlert('휴대폰 인증을 완료해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// HTMX 응답 처리
|
||||
document.body.addEventListener('htmx:afterSwap', function (event) {
|
||||
let targetId = event.detail.target ? event.detail.target.id : null;
|
||||
if (targetId && ['authNumberContainer', 'authNumberValidation'].includes(targetId)) {
|
||||
let response;
|
||||
try {
|
||||
response = typeof event.detail.xhr.response === 'string'
|
||||
? JSON.parse(event.detail.xhr.response)
|
||||
: event.detail.xhr.response;
|
||||
} catch (e) {
|
||||
console.error('Failed to parse response as JSON:', event.detail.xhr.response);
|
||||
customPopups.showAlert('서버에서 예상치 못한 응답을 받았습니다.');
|
||||
return;
|
||||
}
|
||||
$('#mobileNumber').val(mobileNumber);
|
||||
this.submit();
|
||||
});
|
||||
|
||||
switch (targetId) {
|
||||
case 'authNumberContainer':
|
||||
handleAuthNumberRequest(response);
|
||||
break;
|
||||
case 'authNumberValidation':
|
||||
handleAuthNumberVerification(response);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
// 취소 버튼
|
||||
$('#cancelButton').on('click', function() {
|
||||
window.location.href = '/login';
|
||||
});
|
||||
|
||||
// HTMX 에러 처리
|
||||
document.body.addEventListener('htmx:responseError', function (event) {
|
||||
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
});
|
||||
|
||||
// 인증번호 확인 버튼 이벤트
|
||||
let verifyAuthButton = document.querySelector('.btn_verify_auth');
|
||||
if (verifyAuthButton) {
|
||||
verifyAuthButton.addEventListener('click', function (e) {
|
||||
if (!window.isAuthNumberRequested) {
|
||||
e.preventDefault();
|
||||
customPopups.showAlert('휴대폰 번호 인증을 먼저 진행해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
let form = $('#accountForm');
|
||||
let authNumberInput = form.find('.auth-number-input');
|
||||
let authNumber = authNumberInput.val().trim();
|
||||
|
||||
if (authNumber.length !== 6) {
|
||||
e.preventDefault();
|
||||
customPopups.showAlert('입력된 인증번호가 유효하지 않습니다.');
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 취소 버튼 이벤트
|
||||
let cancelButton = document.querySelector('.btn_cancel');
|
||||
if (cancelButton) {
|
||||
cancelButton.addEventListener('click', function () {
|
||||
location.href = '/login';
|
||||
});
|
||||
}
|
||||
|
||||
// 폼 제출 이벤트 처리
|
||||
const accountForm = document.getElementById('accountForm');
|
||||
if (accountForm) {
|
||||
accountForm.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
validateAndSubmit();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
// 기존 휴대폰 번호 복원
|
||||
$(document).ready(function() {
|
||||
const savedMobileNumber = $('#mobileNumber').val();
|
||||
if (savedMobileNumber) {
|
||||
const parts = savedMobileNumber.split('-');
|
||||
if (parts.length === 3) {
|
||||
$('#phonePrefix').val(parts[0]);
|
||||
$('#phoneMiddle').val(parts[1]);
|
||||
$('#phoneLast').val(parts[2]);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user