회원 가입 스타일 수정

This commit is contained in:
현성필
2025-11-26 17:17:30 +09:00
parent e8f9212a13
commit d94760c160
10 changed files with 603 additions and 423 deletions
+87 -13
View File
@@ -11246,9 +11246,8 @@ input[type=checkbox]:checked + .custom-checkbox {
}
.org-info-notice {
padding: 24px;
border-radius: 8px;
margin-bottom: 32px;
margin-bottom: 16px;
}
.org-info-notice ul {
list-style: none;
@@ -11274,7 +11273,7 @@ input[type=checkbox]:checked + .custom-checkbox {
}
.org-form-group {
margin-bottom: 40px;
margin-bottom: 8px;
display: flex;
align-items: flex-start;
gap: 24px;
@@ -11299,10 +11298,17 @@ input[type=checkbox]:checked + .custom-checkbox {
min-width: 180px;
padding-top: 16px;
}
.org-form-label .required::before {
content: "* ";
color: #FF6B6B;
font-weight: 700;
.org-form-label .required-badge {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 2px 8px;
background: #3BA4ED;
color: #FFFFFF;
font-size: 12px;
font-weight: 500;
border-radius: 4px;
line-height: 1.2;
}
@media (max-width: 768px) {
.org-form-label {
@@ -11317,6 +11323,41 @@ input[type=checkbox]:checked + .custom-checkbox {
flex-direction: column;
gap: 8px;
}
@media (max-width: 768px) {
.org-form-input-wrapper {
width: 100%;
}
}
.org-input-row {
display: flex;
align-items: center;
gap: 16px;
}
.org-input-row .org-form-input,
.org-input-row .org-compound-input,
.org-input-row .org-auth-input-group {
flex: 1;
min-width: 0;
}
.org-input-row .org-btn-check, .org-input-row .org-file-label {
flex-shrink: 0;
}
@media (max-width: 768px) {
.org-input-row {
flex-direction: column;
align-items: stretch;
gap: 8px;
}
.org-input-row .org-form-input,
.org-input-row .org-compound-input,
.org-input-row .org-auth-input-group {
width: 100%;
}
.org-input-row .org-btn-check, .org-input-row .org-file-label {
width: 100%;
}
}
.org-form-input {
width: 100%;
@@ -11352,6 +11393,7 @@ input[type=checkbox]:checked + .custom-checkbox {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
}
.org-compound-input .org-form-input,
.org-compound-input .org-form-select {
@@ -11366,14 +11408,16 @@ input[type=checkbox]:checked + .custom-checkbox {
color: #64748B;
font-weight: 600;
user-select: none;
flex-shrink: 0;
}
@media (max-width: 768px) {
.org-compound-input {
flex-wrap: wrap;
width: 100%;
}
.org-compound-input .org-form-input,
.org-compound-input .org-form-select {
min-width: 80px;
flex: 1;
min-width: 0;
}
}
@@ -11483,14 +11527,21 @@ input[type=checkbox]:checked + .custom-checkbox {
.org-btn-check, .org-file-label {
padding: 16px 24px;
background: #FFFFFF;
color: #0049b4;
border: 2px solid #0049b4;
width: 172px;
background: #A4D6EA;
color: #FFFFFF;
border: 2px solid #A4D6EA;
text-align: center;
justify-content: center;
}
.org-btn-check:not(:disabled):hover, .org-file-label:not(:disabled):hover {
background: #0049b4;
color: #FFFFFF;
}
@media (max-width: 768px) {
.org-btn-check, .org-file-label {
width: 100%;
}
}
.org-file-upload {
display: flex;
@@ -11525,6 +11576,9 @@ input[type=checkbox]:checked + .custom-checkbox {
.org-file-label {
cursor: pointer;
background: #3BA4ED;
border-radius: 12px;
border: 2px solid #3BA4ED;
}
.org-file-label input[type=file] {
display: none;
@@ -11571,6 +11625,11 @@ input[type=checkbox]:checked + .custom-checkbox {
padding-top: 48px;
border-top: 1px solid #E2E8F0;
}
.org-action-buttons .btn {
width: 220px;
text-align: center;
justify-content: center;
}
@media (max-width: 768px) {
.org-action-buttons {
flex-direction: column;
@@ -11624,11 +11683,26 @@ input[type=checkbox]:checked + .custom-checkbox {
}
}
@media (max-width: 768px) {
.org-form-input {
width: 100%;
}
.org-compound-input {
width: 100%;
}
.org-compound-input .org-form-select,
.org-compound-input .org-form-input {
flex: 1;
min-width: 0;
width: auto;
font-size: 14px;
padding: 8px 16px;
}
.org-auth-input-group {
width: 100%;
}
.org-auth-input-group .org-form-input {
width: 100%;
}
}
.agreement-form {
background: #FFFFFF;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -112,9 +112,8 @@
// Info Notice
.org-info-notice {
padding: $spacing-lg;
border-radius: $border-radius-md;
margin-bottom: $spacing-xl;
margin-bottom: $spacing-md;
ul {
list-style: none;
@@ -145,7 +144,7 @@
// Form Groups
.org-form-group {
margin-bottom: $spacing-2xl;
margin-bottom: $spacing-sm;
display: flex;
align-items: flex-start;
gap: $spacing-lg;
@@ -170,12 +169,17 @@
min-width: 180px;
padding-top: $spacing-md;
.required {
&::before {
content: '* ';
color: $accent-orange;
font-weight: $font-weight-bold;
}
.required-badge {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 2px 8px;
background: #3BA4ED;
color: $white;
font-size: 12px;
font-weight: $font-weight-medium;
border-radius: 4px;
line-height: 1.2;
}
@include respond-to('sm') {
@@ -189,6 +193,44 @@
display: flex;
flex-direction: column;
gap: $spacing-sm;
@include respond-to('sm') {
width: 100%;
}
}
// Inline layout for input + button on same row
.org-input-row {
display: flex;
align-items: center;
gap: $spacing-md;
.org-form-input,
.org-compound-input,
.org-auth-input-group {
flex: 1;
min-width: 0;
}
.org-btn-check {
flex-shrink: 0;
}
@include respond-to('sm') {
flex-direction: column;
align-items: stretch;
gap: $spacing-sm;
.org-form-input,
.org-compound-input,
.org-auth-input-group {
width: 100%;
}
.org-btn-check {
width: 100%;
}
}
}
// Input Fields
@@ -232,6 +274,7 @@
display: flex;
align-items: center;
gap: $spacing-sm;
width: 100%;
.org-form-input,
.org-form-select {
@@ -249,14 +292,16 @@
color: $text-gray;
font-weight: $font-weight-semibold;
user-select: none;
flex-shrink: 0;
}
@include respond-to('sm') {
flex-wrap: wrap;
width: 100%;
.org-form-input,
.org-form-select {
min-width: 80px;
flex: 1;
min-width: 0;
}
}
}
@@ -380,14 +425,20 @@
.org-btn-check {
padding: $spacing-md $spacing-lg;
background: $white;
color: $primary-blue;
border: 2px solid $primary-blue;
width: 172px;
background: #A4D6EA;
color: $white;
border: 2px solid #A4D6EA;
text-align: center;
justify-content: center;
&:not(:disabled):hover {
background: $primary-blue;
color: $white;
}
@include respond-to('sm') {
width: 100%;
}
}
// File Upload
@@ -425,6 +476,9 @@
.org-file-label {
@extend .org-btn-check;
cursor: pointer;
background: #3BA4ED;
border-radius: 12px;
border: 2px solid #3BA4ED;
input[type="file"] {
display: none;
@@ -478,6 +532,12 @@
padding-top: $spacing-3xl;
border-top: 1px solid $border-gray;
.btn {
width: 220px;
text-align: center;
justify-content: center;
}
@include respond-to('sm') {
flex-direction: column;
margin-top: $spacing-2xl;
@@ -538,13 +598,30 @@
// Responsive Adjustments
@include respond-to('sm') {
.org-form-input {
width: 100%;
}
.org-compound-input {
width: 100%;
.org-form-select,
.org-form-input {
flex: 1;
min-width: 0;
width: auto;
font-size: $font-size-sm;
padding: $spacing-sm $spacing-md;
}
}
.org-auth-input-group {
width: 100%;
.org-form-input {
width: 100%;
}
}
}
// Agreement Form - Figma Design
@@ -5,32 +5,33 @@
<th:block th:fragment="commonUserInfo">
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
이메일 아이디
이메일 아이디 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-compound-input">
<input type="text" id="userId" class="org-form-input"
th:classappend="${isInvited ? 'input-readonly' : ''}"
maxlength="30"
th:value="${emailId}"
th:readonly="${isInvited}"
th:placeholder="#{portalUser.Register.email}">
<span class="separator">@</span>
<input type="text" id="domain" class="org-form-input"
th:classappend="${isInvited ? 'input-readonly' : ''}"
maxlength="50"
th:value="${domain}"
th:readonly="${isInvited}"
th:placeholder="#{portalUser.Register.domain}">
<div class="org-input-row">
<div class="org-compound-input">
<input type="text" id="userId" class="org-form-input"
th:classappend="${isInvited ? 'input-readonly' : ''}"
maxlength="30"
th:value="${emailId}"
th:readonly="${isInvited}"
th:placeholder="#{portalUser.Register.email}">
<span class="separator">@</span>
<input type="text" id="domain" class="org-form-input"
th:classappend="${isInvited ? 'input-readonly' : ''}"
maxlength="50"
th:value="${domain}"
th:readonly="${isInvited}"
th:placeholder="#{portalUser.Register.domain}">
</div>
<button type="button" class="btn org-btn-check btn_check_email"
th:classappend="${isInvited ? 'hidden' : ''}">
중복체크
</button>
</div>
<input type="hidden" id="loginId" name="loginId" th:value="${loginId}">
<input type="hidden" name="registrationType" th:value="${registrationType}"/>
<input type="hidden" id="registrationScenario" name="registrationScenario" value="new"/>
<button type="button" class="btn org-btn-check btn_check_email"
th:classappend="${isInvited ? 'hidden' : ''}">
중복체크
</button>
<div id="email-validation" class="org-validation-message"></div>
</div>
</div>
@@ -3,348 +3,373 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kbank_base_layout}">
<body>
<th:block th:fragment="newUserForm">
<div id="newUserFields">
<!-- 성명 -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
성명
</label>
<div class="org-form-input-wrapper">
<input type="text" th:field="*{userName}" id="userName" class="org-form-input"
th:placeholder="#{portalUser.Register.userName}">
</div>
</div>
<!-- 휴대폰 번호 입력 -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
휴대폰 번호
</label>
<div class="org-form-input-wrapper">
<div class="org-compound-input">
<select class="org-form-select phone-number" id="phoneMobile">
<option value="">선택</option>
<option value="010">010</option>
<option value="011">011</option>
<option value="017">017</option>
<option value="016">016</option>
<option value="018">018</option>
</select>
<span class="separator">-</span>
<input type="text" id="cellPhone1" maxlength="4" class="org-form-input phone-number"
th:placeholder="#{portal.Register.phone1}">
<span class="separator">-</span>
<input type="text" id="cellPhone2" maxlength="4" class="org-form-input phone-number"
th:placeholder="#{portal.Register.phone2}">
</div>
<input type="hidden" th:field="*{mobileNumber}" id="mobileNumber">
<button type="button" class="btn org-btn-check btn_auth">
인증번호 받기
</button>
<div id="mobile-validation" class="org-validation-message"></div>
</div>
</div>
<!-- 인증번호 입력 -->
<div class="org-form-group" id="authNumberContainer" style="display: none;">
<label class="org-form-label">
<span class="required">*</span>
인증번호 입력
</label>
<div class="org-form-input-wrapper">
<div class="org-auth-input-group">
<input type="text" th:field="*{authNumber}" id="authNumber" maxlength="6" pattern="[0-9]*"
inputmode="numeric" class="org-form-input" th:placeholder="#{ncrdRegister.validate.authNumber}" required>
<span class="org-timer" id="certify_time">03:00</span>
</div>
<button type="button" class="btn org-btn-check btn_verify_auth">
인증번호 확인
</button>
<div id="authNumber-validation" class="org-validation-message"></div>
</div>
</div>
<!-- 비밀번호 -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
비밀번호
</label>
<div class="org-form-input-wrapper">
<input type="password" name="password" id="password" class="org-form-input"
th:placeholder="#{portalUser.Register.pass}">
<input type="hidden" name="isPasswordValid" id="isPasswordValid"/>
<div id="password-validation" class="org-validation-message"></div>
</div>
</div>
<!-- 비밀번호 확인 -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
비밀번호 확인
</label>
<div class="org-form-input-wrapper">
<input type="password" name="password2" id="password2" class="org-form-input"
th:placeholder="#{portalUser.Register.passConfirm}">
<input type="hidden" name="isPasswordMatch" id="isPasswordMatch"/>
<div id="password-match-validation" class="org-validation-message"></div>
</div>
</div>
<div id="newUserFields">
<!-- 성명 -->
<div class="org-form-group">
<label class="org-form-label">
성명 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="text" th:field="*{userName}" id="userName" class="org-form-input"
th:placeholder="#{portalUser.Register.userName}">
<div id="userName-validation" class="org-validation-message"></div>
</div>
</div>
<!-- 휴대폰 번호 입력 -->
<div class="org-form-group">
<label class="org-form-label">
휴대폰 번호 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-input-row">
<div class="org-compound-input">
<select class="org-form-select phone-number" id="phoneMobile">
<option value="">선택</option>
<option value="010">010</option>
<option value="011">011</option>
<option value="017">017</option>
<option value="016">016</option>
<option value="018">018</option>
</select>
<span class="separator">-</span>
<input type="text" id="cellPhone1" maxlength="4" class="org-form-input phone-number"
th:placeholder="#{portal.Register.phone1}">
<span class="separator">-</span>
<input type="text" id="cellPhone2" maxlength="4" class="org-form-input phone-number"
th:placeholder="#{portal.Register.phone2}">
</div>
<button type="button" class="btn org-btn-check btn_auth">
인증번호 받기
</button>
</div>
<input type="hidden" th:field="*{mobileNumber}" id="mobileNumber">
<div id="mobile-validation" class="org-validation-message"></div>
</div>
</div>
<!-- 인증번호 입력 -->
<div class="org-form-group" id="authNumberContainer" style="display: none;">
<label class="org-form-label">
인증번호 입력 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-input-row">
<div class="org-auth-input-group">
<input type="text" th:field="*{authNumber}" id="authNumber" maxlength="6" pattern="[0-9]*"
inputmode="numeric" class="org-form-input" th:placeholder="#{ncrdRegister.validate.authNumber}" required>
<span class="org-timer" id="certify_time">03:00</span>
</div>
<button type="button" class="btn org-btn-check btn_verify_auth">
인증번호 확인
</button>
</div>
<div id="authNumber-validation" class="org-validation-message"></div>
</div>
</div>
<!-- 비밀번호 -->
<div class="org-form-group">
<label class="org-form-label">
비밀번호 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="password" name="password" id="password" class="org-form-input"
th:placeholder="#{portalUser.Register.pass}">
<input type="hidden" name="isPasswordValid" id="isPasswordValid"/>
<div id="password-validation" class="org-validation-message"></div>
</div>
</div>
<!-- 비밀번호 확인 -->
<div class="org-form-group">
<label class="org-form-label">
비밀번호 확인 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="password" name="password2" id="password2" class="org-form-input"
th:placeholder="#{portalUser.Register.passConfirm}">
<input type="hidden" name="isPasswordMatch" id="isPasswordMatch"/>
<div id="password-match-validation" class="org-validation-message"></div>
</div>
</div>
</div>
</th:block>
</body>
<th:block>
<script th:fragment="newUserScript">
// 휴대폰 번호 조합 함수
function combineMobileNumber() {
let mobileSelect = document.getElementById('phoneMobile');
if (!mobileSelect) {
console.error('Mobile select element not found');
return null;
}
let prefix = mobileSelect.value;
let middle = document.getElementById('cellPhone1').value.trim();
let last = document.getElementById('cellPhone2').value.trim();
<script th:fragment="newUserScript">
// 휴대폰 번호 조합 함수
function combineMobileNumber() {
let mobileSelect = document.getElementById('phoneMobile');
if (!mobileSelect) {
console.error('Mobile select element not found');
return null;
}
let prefix = mobileSelect.value;
let middle = document.getElementById('cellPhone1').value.trim();
let last = document.getElementById('cellPhone2').value.trim();
if (!prefix || !middle || !last) {
return null;
}
if (!prefix || !middle || !last) {
return null;
}
// 형식화된 번호 (xxx-xxxx-xxxx)
let formattedNumber = `${prefix}-${middle}-${last}`;
// 형식화된 번호 (xxx-xxxx-xxxx)
let formattedNumber = `${prefix}-${middle}-${last}`;
// hidden input에 형식화된 번호 설정
let mobileNumberInput = document.getElementById('mobileNumber');
if (mobileNumberInput) {
mobileNumberInput.value = formattedNumber;
// hidden input에 형식화된 번호 설정
let mobileNumberInput = document.getElementById('mobileNumber');
if (mobileNumberInput) {
mobileNumberInput.value = formattedNumber;
}
return formattedNumber;
}
document.addEventListener('DOMContentLoaded', function() {
let countdownInterval;
let isAuthVerified = false;
// 휴대폰 번호 중간, 끝자리 입력 제한 및 형식화
$('#cellPhone1').on('input', function() {
let value = $(this).val().replace(/[^0-9]/g, '');
if (value.length > 4) {
value = value.slice(0, 4);
}
$(this).val(value);
combineMobileNumber();
});
$('#cellPhone2').on('input', function() {
let value = $(this).val().replace(/[^0-9]/g, '');
if (value.length > 4) {
value = value.slice(0, 4);
}
$(this).val(value);
combineMobileNumber();
});
// select 변경 감지
$('#phoneMobile').on('change', function() {
combineMobileNumber();
});
// 인증번호 입력 제한
$('#authNumber').on('input', function() {
$(this).val($(this).val().replace(/[^0-9]/g, ''));
});
// 인증번호 검증 결과 처리 함수
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');
if (authNumberInput) {
authNumberInput.readonly = true;
}
if (verifyAuthButton) {
verifyAuthButton.disabled = true;
}
clearInterval(countdownInterval);
if (timerElement) {
timerElement.textContent = '인증 완료';
}
isAuthVerified = true;
document.dispatchEvent(new Event('authVerified'));
}
}
// 인증번호 요청 후 처리 함수
function handleAuthNumberRequest(response) {
if (response.valid) {
let authButton = document.querySelector('.btn_auth');
let authContainer = document.getElementById('authNumberContainer');
if (authButton) {
authButton.disabled = true;
}
if (authContainer) {
authContainer.style.display = 'flex';
}
startAuthNumberTimer();
customPopups.showAlert(response.message || '인증번호가 발송되었습니다.');
} else {
customPopups.showAlert(response.message || '알 수 없는 오류가 발생했습니다.');
let authButton = document.querySelector('.btn_auth');
if (authButton) {
authButton.disabled = false;
}
}
}
// 인증번호 타이머 시작 함수
function startAuthNumberTimer() {
clearInterval(countdownInterval);
let remainingTime = 180; // 3분
let timerElement = document.getElementById('certify_time');
let authButton = document.querySelector('.btn_auth');
let verifyAuthButton = document.querySelector('.btn_verify_auth');
let authNumberInput = document.getElementById('authNumber');
function updateRemainingTime() {
if (remainingTime <= 0) {
clearInterval(countdownInterval);
if (timerElement) {
timerElement.textContent = '입력 시간이 초과되었습니다.';
}
return formattedNumber;
customPopups.showAlert('입력 시간이 초과되었습니다. 인증번호를 다시 발송해주세요.');
if (authButton) {
authButton.disabled = false;
}
if (verifyAuthButton) {
verifyAuthButton.disabled = true;
}
if (authNumberInput) {
authNumberInput.readOnly = true;
}
} else {
let minutes = Math.floor(remainingTime / 60);
let seconds = remainingTime % 60;
if (timerElement) {
timerElement.textContent = `남은 시간: ${minutes}:${seconds.toString().padStart(2, '0')}`;
}
remainingTime--;
}
}
document.addEventListener('DOMContentLoaded', function () {
let countdownInterval;
let isAuthVerified = false;
updateRemainingTime();
countdownInterval = setInterval(updateRemainingTime, 1000);
}
// 휴대폰 번호 중간, 끝자리 입력 제한 및 형식화
$('#cellPhone1').on('input', function () {
let value = $(this).val().replace(/[^0-9]/g, '');
if (value.length > 4) {
value = value.slice(0, 4);
}
$(this).val(value);
combineMobileNumber();
});
// 이벤트 리스너 등록
document.getElementById('phoneMobile').addEventListener('change', combineMobileNumber);
document.querySelectorAll('#cellPhone1, #cellPhone2').forEach(el => el.addEventListener('input', combineMobileNumber));
$('#cellPhone2').on('input', function () {
let value = $(this).val().replace(/[^0-9]/g, '');
if (value.length > 4) {
value = value.slice(0, 4);
}
$(this).val(value);
combineMobileNumber();
});
// select 변경 감지
$('#phoneMobile').on('change', function () {
combineMobileNumber();
});
// 인증번호 입력 제한
$('#authNumber').on('input', function () {
$(this).val($(this).val().replace(/[^0-9]/g, ''));
});
// 인증번호 검증 결과 처리 함수
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');
if (authNumberInput) authNumberInput.readonly = true;
if (verifyAuthButton) verifyAuthButton.disabled = true;
clearInterval(countdownInterval);
if (timerElement) timerElement.textContent = '인증 완료';
isAuthVerified = true;
document.dispatchEvent(new Event('authVerified'));
}
}
// 인증번호 요청 후 처리 함수
function handleAuthNumberRequest(response) {
if (response.valid) {
let authButton = document.querySelector(".btn_auth");
let authContainer = document.getElementById("authNumberContainer");
if (authButton) authButton.disabled = true;
if (authContainer) authContainer.style.display = 'flex';
startAuthNumberTimer();
customPopups.showAlert(response.message || "인증번호가 발송되었습니다.");
} else {
customPopups.showAlert(response.message || '알 수 없는 오류가 발생했습니다.');
let authButton = document.querySelector(".btn_auth");
if (authButton) authButton.disabled = false;
}
}
// 인증번호 타이머 시작 함수
function startAuthNumberTimer() {
clearInterval(countdownInterval);
let remainingTime = 180; // 3분
let timerElement = document.getElementById("certify_time");
let authButton = document.querySelector(".btn_auth");
let verifyAuthButton = document.querySelector(".btn_verify_auth");
let authNumberInput = document.getElementById('authNumber');
function updateRemainingTime() {
if (remainingTime <= 0) {
clearInterval(countdownInterval);
if (timerElement) timerElement.textContent = "입력 시간이 초과되었습니다.";
customPopups.showAlert("입력 시간이 초과되었습니다. 인증번호를 다시 발송해주세요.");
if (authButton) authButton.disabled = false;
if (verifyAuthButton) verifyAuthButton.disabled = true;
if (authNumberInput) authNumberInput.readOnly = true;
} else {
let minutes = Math.floor(remainingTime / 60);
let seconds = remainingTime % 60;
if (timerElement) timerElement.textContent = `남은 시간: ${minutes}:${seconds.toString().padStart(2, '0')}`;
remainingTime--;
}
}
updateRemainingTime();
countdownInterval = setInterval(updateRemainingTime, 1000);
}
// 이벤트 리스너 등록
document.getElementById('phoneMobile').addEventListener('change', combineMobileNumber);
document.querySelectorAll('#cellPhone1, #cellPhone2')
.forEach(el => el.addEventListener('input', combineMobileNumber));
let authNumberInput = document.getElementById("authNumber");
if (authNumberInput) {
authNumberInput.addEventListener("input", function () {
this.value = this.value.replace(/\D/g, '');
this.classList.toggle('is-invalid', this.value.length !== 6);
});
}
let userNameInput = document.getElementById("userName");
if (userNameInput) {
userNameInput.addEventListener("input", function () {
this.classList.toggle('is-invalid', this.value.trim().length === 0);
});
}
// 인증번호 요청 버튼 이벤트 리스너
$('.btn_auth').on('click', function () {
let mobileNumber = combineMobileNumber();
if (!mobileNumber) {
customPopups.showAlert("휴대폰 번호를 올바르게 입력해주세요.");
return;
}
$('#mobileNumber').val(mobileNumber);
$.ajax({
url: /*[[@{/auth/request_auth_number}]]*/ '/auth/request_auth_number',
type: 'POST',
data: {
mobileNumber: mobileNumber,
_csrf: $('input[name="_csrf"]').val()
},
success: function (response) {
handleAuthNumberRequest(response);
},
error: function () {
customPopups.showAlert("처리 중 오류가 발생했습니다. 다시 시도해주세요.");
}
});
});
// 인증번호 확인 버튼 이벤트 리스너
$('.btn_verify_auth').on('click', function () {
let authNumber = $('#authNumber').val();
if (authNumber.length !== 6) {
customPopups.showAlert("6자리 인증번호를 입력해주세요.");
return;
}
$.ajax({
url: /*[[@{/auth/verify_auth_number}]]*/ '/auth/verify_auth_number',
type: 'POST',
data: {
mobileNumber: $('#mobileNumber').val(),
authNumber: authNumber,
_csrf: $('input[name="_csrf"]').val()
},
success: function (response) {
handleAuthNumberVerification(response);
},
error: function () {
customPopups.showAlert("처리 중 오류가 발생했습니다. 다시 시도해주세요.");
}
});
});
// 비밀번호 검증
$('#password').on('blur', function () {
let password = $(this).val();
if (!password) return;
$.ajax({
url: /*[[@{/check_password}]]*/ '/check_password',
type: 'POST',
data: {
password: password,
mobileNumber: $('#mobileNumber').val(),
loginId: $('#loginId').val(),
_csrf: $('input[name="_csrf"]').val()
},
success: function (response) {
let targetElement = $('#password-validation');
targetElement.removeClass('success error');
targetElement.addClass(response.valid ? 'success' : 'error');
targetElement.text(response.message);
$('#isPasswordValid').val(response.valid);
},
error: function () {
customPopups.showAlert("처리 중 오류가 발생했습니다. 다시 시도해주세요.");
}
});
});
// 비밀번호 확인 검증
$('#password2').on('blur', function () {
let password2 = $(this).val();
if (!password2) return;
$.ajax({
url: /*[[@{/check_password_match}]]*/ '/check_password_match',
type: 'POST',
data: {
password: $('#password').val(),
password2: password2,
_csrf: $('input[name="_csrf"]').val()
},
success: function (response) {
let targetElement = $('#password-match-validation');
targetElement.removeClass('success error');
targetElement.addClass(response.valid ? 'success' : 'error');
targetElement.text(response.message);
$('#isPasswordMatch').val(response.valid);
},
error: function () {
customPopups.showAlert("처리 중 오류가 발생했습니다. 다시 시도해주세요.");
}
});
});
let authNumberInput = document.getElementById('authNumber');
if (authNumberInput) {
authNumberInput.addEventListener('input', function() {
this.value = this.value.replace(/\D/g, '');
this.classList.toggle('is-invalid', this.value.length !== 6);
});
</script>
}
let userNameInput = document.getElementById('userName');
if (userNameInput) {
userNameInput.addEventListener('input', function() {
this.classList.toggle('is-invalid', this.value.trim().length === 0);
});
}
// 인증번호 요청 버튼 이벤트 리스너
$('.btn_auth').on('click', function() {
let mobileNumber = combineMobileNumber();
if (!mobileNumber) {
customPopups.showAlert('휴대폰 번호를 올바르게 입력해주세요.');
return;
}
$('#mobileNumber').val(mobileNumber);
$.ajax({
url: /*[[@{/auth/request_auth_number}]]*/ '/auth/request_auth_number',
type: 'POST',
data: {
mobileNumber: mobileNumber,
_csrf: $('input[name="_csrf"]').val()
},
success: function(response) {
handleAuthNumberRequest(response);
},
error: function() {
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.');
}
});
});
// 인증번호 확인 버튼 이벤트 리스너
$('.btn_verify_auth').on('click', function() {
let authNumber = $('#authNumber').val();
if (authNumber.length !== 6) {
customPopups.showAlert('6자리 인증번호를 입력해주세요.');
return;
}
$.ajax({
url: /*[[@{/auth/verify_auth_number}]]*/ '/auth/verify_auth_number',
type: 'POST',
data: {
mobileNumber: $('#mobileNumber').val(),
authNumber: authNumber,
_csrf: $('input[name="_csrf"]').val()
},
success: function(response) {
handleAuthNumberVerification(response);
},
error: function() {
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.');
}
});
});
// 비밀번호 검증
$('#password').on('blur', function() {
let password = $(this).val();
if (!password) {
return;
}
$.ajax({
url: /*[[@{/check_password}]]*/ '/check_password',
type: 'POST',
data: {
password: password,
mobileNumber: $('#mobileNumber').val(),
loginId: $('#loginId').val(),
_csrf: $('input[name="_csrf"]').val()
},
success: function(response) {
let targetElement = $('#password-validation');
targetElement.removeClass('success error');
targetElement.addClass(response.valid ? 'success' : 'error');
targetElement.text(response.message);
$('#isPasswordValid').val(response.valid);
},
error: function() {
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.');
}
});
});
// 비밀번호 확인 검증
$('#password2').on('blur', function() {
let password2 = $(this).val();
if (!password2) {
return;
}
$.ajax({
url: /*[[@{/check_password_match}]]*/ '/check_password_match',
type: 'POST',
data: {
password: $('#password').val(),
password2: password2,
_csrf: $('input[name="_csrf"]').val()
},
success: function(response) {
let targetElement = $('#password-match-validation');
targetElement.removeClass('success error');
targetElement.addClass(response.valid ? 'success' : 'error');
targetElement.text(response.message);
$('#isPasswordMatch').val(response.valid);
},
error: function() {
customPopups.showAlert("처리 중 오류가 발생했습니다. 다시 시도해주세요.");
}
});
});
});
</script>
</th:block>
</html>
@@ -6,8 +6,7 @@
<!-- Business Registration Number -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
사업자등록번호
사업자등록번호 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-compound-input">
@@ -28,8 +27,7 @@
<!-- Corporate Registration Number -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
법인등록번호
법인등록번호 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-compound-input">
@@ -47,8 +45,7 @@
<!-- Company Name -->
<div class="org-form-group">
<label class="org-form-label" for="orgName">
<span class="required">*</span>
법인명
법인명 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="text" class="org-form-input" id="orgName" th:field="*{orgName}"
@@ -63,8 +60,7 @@
<!-- CEO Name -->
<div class="org-form-group">
<label class="org-form-label" for="ceoName">
<span class="required">*</span>
대표자 성명
대표자 성명 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="text" class="org-form-input" id="ceoName" th:field="*{ceoName}"
@@ -79,8 +75,7 @@
<!-- Business Address -->
<div class="org-form-group">
<label class="org-form-label" for="orgAddr">
<span class="required">*</span>
사업장 소재지
사업장 소재지 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="text" class="org-form-input" id="orgAddr" th:field="*{orgAddr}"
@@ -95,8 +90,7 @@
<!-- Business Type -->
<div class="org-form-group">
<label class="org-form-label" for="orgSectors">
<span class="required">*</span>
업태
업태 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="text" class="org-form-input" id="orgSectors" th:field="*{orgSectors}"
@@ -107,8 +101,7 @@
<!-- Industry Type -->
<div class="org-form-group">
<label class="org-form-label" for="orgIndustryType">
<span class="required">*</span>
업종
업종 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="text" class="org-form-input" id="orgIndustryType" th:field="*{orgIndustryType}"
@@ -119,8 +112,7 @@
<!-- Company Phone Number -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
회사 전화번호
회사 전화번호 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-compound-input">
@@ -167,8 +159,7 @@
<!-- Service Name -->
<div class="org-form-group">
<label class="org-form-label" for="serviceName">
<span class="required">*</span>
서비스명
서비스명 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<input type="text" class="org-form-input" id="serviceName" th:field="*{serviceName}"
@@ -183,8 +174,7 @@
<!-- Customer Service Phone Number -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
고객센터 전화번호
고객센터 전화번호 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-compound-input">
@@ -231,15 +221,23 @@
<!-- Business Registration Certificate Upload -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
사업자 등록증
사업자 등록증 <span class="required-badge">필수</span>
</label>
<div class="org-form-input-wrapper">
<div class="org-file-upload">
<input type="text" class="org-file-display" id="fileNameDisplay" readonly placeholder="첨부파일을 선택하세요">
<input type="hidden" id="compRegFile" th:field="*{compRegFile}">
<label class="org-file-label" for="files">
<i class="fas fa-upload"></i> 파일선택
<svg width="24" height="22" viewBox="0 0 24 22" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="23.9494" height="22" fill="url(#pattern0_3001_1395)"/>
<defs>
<pattern id="pattern0_3001_1395" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlink:href="#image0_3001_1395" transform="matrix(0.0217391 0 0 0.0236654 0 -0.0443038)"/>
</pattern>
<image id="image0_3001_1395" width="46" height="46" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAuCAYAAABXuSs3AAAACXBIWXMAABcSAAAXEgFnn9JSAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAeRJREFUeNrsme1tgzAQhiHqAGxQRiATlGxAJ6i7QTpByQTtBrBBRiCdADYInaB0AvcsnaUTNR82GPzDr2Q5ODh6cO7LJgwWiHMeQZfgZReGYRO4LAEMreD/dYeWuQodQ/vh4ypcBK8JYC4eBMczXHGpzCXojICdB0xIwtcugX9IWx65h8kns8nyMAOWQRfjZUbG84Epj+QeYevfA/eJKPRpK3LU3K4KG+AV30ZG8OEAtEgq1Llu0L5m/qYwFYafS4WpvBDTkyrBbF7XWG1GVqTWnJuSuanGP6m18oeBcboi3UZBi+nAH3aOsCKqNCbwe4P/QjuZwB8MQiTDqnANPUE7o/Mbmw0FzInTVGT8OuVIC5xTJbaWqUQK59WVjrPHxinfgi69RegrGfluP3DcJT2PZWzoUtejirE8uAe3BN5ORIR+CGtcAZelbaJKDphR3yU0RJDOCXAAKckqFphhI5kxoavIil/22BQrU77cZNg8V+mVBPlqzokJ5KgojGQ6f1tlN2MjcwKYcNITHgbJ1sL4bSurWJTy8QFaH8c9uAf34B7cg3twD74xOK0/4hWP3OYonlUnDdTEYvK9V642G0FT8KP222ryhm0vVUt2QnvBX6fMM5wBHwfLDjl11WKdP6o/AQYA6KS7NOFJR28AAAAASUVORK5CYII="/>
</defs>
</svg>
파일선택
<input type="file" id="files" name="files"
accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.hwp,.gif,.jpg,.png">
</label>
@@ -5,25 +5,26 @@
<!-- Email ID -->
<div class="org-form-group">
<label class="org-form-label">
<span class="required">*</span>
이메일 아이디
이메일 아이디 <span class="required-badge">필수</span>
</label>
<div class="org-input-button-group">
<div class="org-compound-input" style="flex: 1;">
<input type="text" id="userId" class="org-form-input"
placeholder="이메일 아이디">
<span class="separator">@</span>
<input type="text" id="domain" class="org-form-input"
placeholder="도메인">
<div class="org-form-input-wrapper">
<div class="org-input-row">
<div class="org-compound-input">
<input type="text" id="userId" class="org-form-input"
placeholder="이메일 아이디">
<span class="separator">@</span>
<input type="text" id="domain" class="org-form-input"
placeholder="도메인">
</div>
<button type="button" class="btn org-btn-check btn_check_email">
중복체크
</button>
</div>
<button type="button" class="btn org-btn-check btn_check_email">
중복체크
</button>
<input type="hidden" id="loginId" name="loginId" th:value="${loginId}">
<input type="hidden" name="registrationType" th:value="${registrationType}"/>
<input type="hidden" id="registrationScenario" name="registrationScenario" value="new"/>
<div id="email-validation" class="org-validation-message"></div>
</div>
<input type="hidden" id="loginId" name="loginId" th:value="${loginId}">
<input type="hidden" name="registrationType" th:value="${registrationType}"/>
<input type="hidden" id="registrationScenario" name="registrationScenario" value="new"/>
<div id="email-validation" class="org-validation-message"></div>
</div>
<!-- Dynamic Form Container -->
@@ -24,6 +24,10 @@
<!-- Alert Container -->
<div id="alertContainer"></div>
<div class="org-section-header" style="margin-top: 60px;margin-bottom: 60px;">
<h3>법인 회원 가입 후 서비스 또는 API 이용을 하실 수 있습니다.</h3>
</div>
<!-- Agreement Section -->
<th:block th:replace="~{apps/register/userAgreementContent :: agreementContent(${termsOfUse}, ${privacyCollect})}"></th:block>
@@ -38,7 +42,7 @@
<th:block th:replace="~{apps/register/components/orgBasicInfoForm :: orgInfoForm}"></th:block>
<!-- Corporate Admin Information Section -->
<div class="org-section-header" style="margin-top: 48px;">
<div class="org-section-header org-section-header--agreement" style="margin-top: 48px;">
<h3>법인 관리자 정보</h3>
<span class="required-badge">필수 입력</span>
</div>
@@ -49,9 +53,9 @@
</ul>
</div>
<div th:if="${registrationType == 'corporate'}">
<th:block th:if="${registrationType == 'corporate'}">
<th:block th:replace="~{apps/register/components/orgUserInfoForm :: orgUserInfoForm}"></th:block>
</div>
</th:block>
<!-- Action Buttons -->
<div class="org-action-buttons">