feat: 로그인 퍼블리싱

This commit is contained in:
hong
2026-07-30 10:01:38 +09:00
parent 4181d114c1
commit faaf9e8cd6
20 changed files with 1120 additions and 1238 deletions
@@ -73,7 +73,7 @@ public class AppServiceFacade {
List<AppRequest> appRequests = appRequestRepository.findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(portalOrg, types, List<AppRequest> appRequests = appRequestRepository.findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(portalOrg, types,
Arrays.asList(new ProcessingState(), new RequestedState())); Arrays.asList(new ProcessingState(), new RequestedState()));
// 승인정보(approval) 없는 신청도 목록에 노출한다. (사용자가 직접 삭제 가능) // 승인정보(approval) 없는 신청도 목록에 노출`한다. (사용자가 직접 삭제 가능)
appRequests.addAll(appRequestRepository .findAllByOrgAndTypeIsInAndApprovalIsNull(portalOrg, types)); appRequests.addAll(appRequestRepository .findAllByOrgAndTypeIsInAndApprovalIsNull(portalOrg, types));
return appRequests; return appRequests;
+182 -237
View File
@@ -1421,7 +1421,7 @@ hr {
.nav-menu { .nav-menu {
display: flex; display: flex;
list-style: none; list-style: none;
gap: 28px; gap: 24px;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
@@ -1431,6 +1431,7 @@ hr {
.nav-menu > li.submenu-open > .nav-link { .nav-menu > li.submenu-open > .nav-link {
background: var(--light-bg); background: var(--light-bg);
color: var(--primary-blue); color: var(--primary-blue);
border-radius: 9px;
} }
.nav-menu > li.submenu-open .sub-menu { .nav-menu > li.submenu-open .sub-menu {
visibility: visible; visibility: visible;
@@ -1476,7 +1477,7 @@ hr {
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
color: var(--text-gray); color: var(--text-gray);
padding: 8px; padding: 12px;
position: relative; position: relative;
transition: var(--transition-smooth); transition: var(--transition-smooth);
} }
@@ -4319,7 +4320,7 @@ select.form-control {
box-shadow: 0 0 0 3px rgba(0, 73, 180, 0.1); box-shadow: 0 0 0 3px rgba(0, 73, 180, 0.1);
} }
.form-input:disabled, .form-input.input-readonly { .form-input:disabled, .form-input.input-readonly {
background: #F8FAFC; background: #e9ecef !important;
color: #64748B; color: #64748B;
cursor: not-allowed; cursor: not-allowed;
} }
@@ -12133,26 +12134,27 @@ body.index-page-body {
} }
.account-recovery-page { .account-recovery-page {
display: flex; display: flex;
align-items: flex-start; align-items: center;
justify-content: center; justify-content: center;
background: transparent; padding: 100px 20px;
padding: 0;
position: relative; position: relative;
min-height: auto; border-radius: 12px;
margin: 0; margin-bottom: 50px;
} }
.account-recovery-container { .account-recovery-container {
width: 100%; width: 100%;
max-width: 800px; max-width: 650px;
margin: 0 auto; margin: 0 auto;
position: relative; position: relative;
padding: 24px; padding: 24px;
} }
.account-recovery-card { .account-recovery-card {
background: transparent; background: #FFFFFF;
padding: 0; border-radius: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
padding: 36px 36px 28px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
@@ -12160,7 +12162,8 @@ body.index-page-body {
} }
@media (max-width: 576px) { @media (max-width: 576px) {
.account-recovery-card { .account-recovery-card {
padding: 0 20px; padding: 24px 20px 20px;
border-radius: 16px;
} }
} }
@@ -12175,10 +12178,9 @@ body.index-page-body {
.account-recovery-tabs { .account-recovery-tabs {
display: flex; display: flex;
gap: 0; gap: 0;
margin-bottom: 0; margin-bottom: 28px;
width: 100%; width: 100%;
background: transparent; background: transparent;
border-radius: 0;
padding: 0; padding: 0;
} }
.account-recovery-tabs .tab-link { .account-recovery-tabs .tab-link {
@@ -12186,36 +12188,37 @@ body.index-page-body {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 14px 24px; padding: 14px 20px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 16px; font-size: 15px;
font-weight: 700; font-weight: 400;
color: #8c959f; color: #adb5bd;
text-decoration: none; text-decoration: none;
text-align: center; text-align: center;
background: #eceff4; background: #FFFFFF;
border: 1.5px solid transparent;
border-bottom: 1.5px solid #dee2e6;
border-radius: 0; border-radius: 0;
transition: all 0.3s ease; transition: all 0.2s ease;
} cursor: pointer;
.account-recovery-tabs .tab-link:first-child { position: relative;
border-radius: 30px 0 0 0;
}
.account-recovery-tabs .tab-link:last-child {
border-radius: 0 30px 0 0;
} }
.account-recovery-tabs .tab-link:hover { .account-recovery-tabs .tab-link:hover {
color: #3ba4ed; color: #0049b4;
background: #e4e8ed;
} }
.account-recovery-tabs .tab-link.active { .account-recovery-tabs .tab-link.active {
color: #FFFFFF; color: #0049b4;
background: #3ba4ed;
font-weight: 700; font-weight: 700;
border-top: 1.5px solid #0049b4;
border-left: 1.5px solid #0049b4;
border-right: 1.5px solid #0049b4;
border-bottom: 2px solid #FFFFFF;
border-radius: 8px 8px 0px 0px;
} }
@media (max-width: 576px) { @media (max-width: 576px) {
.account-recovery-tabs .tab-link { .account-recovery-tabs .tab-link {
padding: 12px 16px; padding: 12px 10px;
font-size: 14px; font-size: 13px;
} }
} }
@@ -12254,75 +12257,44 @@ body.index-page-body {
.account-recovery-form { .account-recovery-form {
width: 100%; width: 100%;
margin-bottom: 0; margin-bottom: 0;
background: #F6F9FB; background: transparent;
padding: 40px; padding: 0;
border-radius: 0 0 12px 12px;
}
@media (max-width: 576px) {
.account-recovery-form {
padding: 24px 16px;
}
} }
.account-recovery-form .form-group { .account-recovery-form .form-group {
display: flex; display: flex;
align-items: center; flex-direction: column;
gap: 20px; gap: 0;
margin-bottom: 20px; margin-bottom: 12px;
} }
.account-recovery-form .form-group:last-of-type { .account-recovery-form .form-group:last-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
@media (max-width: 768px) {
.account-recovery-form .form-group {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
}
.account-recovery-form .form-label { .account-recovery-form .form-label {
display: flex; display: none;
align-items: center;
flex-shrink: 0;
width: 170px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 15px;
font-weight: 400;
color: #212529;
margin-bottom: 0;
}
.account-recovery-form .form-label .required {
color: #ed5b5b;
margin-left: 2px;
}
@media (max-width: 768px) {
.account-recovery-form .form-label {
width: 100%;
font-size: 14px;
}
} }
.account-recovery-form .form-input { .account-recovery-form .form-input {
flex: 1; width: 100%;
height: 40px; height: 48px;
padding: 0 16px; padding: 0 16px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
color: #212529; color: #212529;
background: #FFFFFF; background: #FFFFFF;
border: 1px solid #dadada; border: 1px solid #E2E8F0;
border-radius: 8px; border-radius: 10px;
outline: none; outline: none;
transition: all 0.3s ease; transition: all 0.25s ease;
} }
.account-recovery-form .form-input::placeholder { .account-recovery-form .form-input::placeholder {
color: #dadada; color: #B0B8C1;
} }
.account-recovery-form .form-input:hover { .account-recovery-form .form-input:hover {
border-color: #3ba4ed; border-color: #3ba4ed;
} }
.account-recovery-form .form-input:focus { .account-recovery-form .form-input:focus {
border-color: #3ba4ed; border-color: #3ba4ed;
box-shadow: 0 0 0 2px rgba(59, 164, 237, 0.1); box-shadow: 0 0 0 3px rgba(59, 164, 237, 0.12);
} }
.account-recovery-form .form-input:disabled { .account-recovery-form .form-input:disabled {
background: #F8F9FA; background: #F8F9FA;
@@ -12334,24 +12306,24 @@ body.index-page-body {
border-color: #ed5b5b; border-color: #ed5b5b;
} }
.account-recovery-form .form-select { .account-recovery-form .form-select {
height: 40px; height: 48px;
padding: 0 32px 0 16px; padding: 0 24px 0 12px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
color: #515151; color: #515151;
background: #FFFFFF; background: #FFFFFF;
border: 1px solid #dadada; border: 1px solid #E2E8F0;
border-radius: 8px; border-radius: 10px;
outline: none; outline: none;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.25s ease;
appearance: none; appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='5' viewBox='0 0 10 5'%3E%3Cpath fill='%231D1B20' d='M5 5L0 0h10z'/%3E%3C/svg%3E"); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='5' viewBox='0 0 10 5'%3E%3Cpath fill='%231D1B20' d='M5 5L0 0h10z'/%3E%3C/svg%3E");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right 12px center; background-position: right 8px center;
background-size: 10px 5px; background-size: 10px 5px;
} }
.account-recovery-form .form-select:hover { .account-recovery-form .form-select:hover {
@@ -12359,7 +12331,7 @@ body.index-page-body {
} }
.account-recovery-form .form-select:focus { .account-recovery-form .form-select:focus {
border-color: #3ba4ed; border-color: #3ba4ed;
box-shadow: 0 0 0 2px rgba(59, 164, 237, 0.1); box-shadow: 0 0 0 3px rgba(59, 164, 237, 0.12);
} }
.account-recovery-form .form-select:disabled { .account-recovery-form .form-select:disabled {
background-color: #F8F9FA; background-color: #F8F9FA;
@@ -12373,50 +12345,89 @@ body.index-page-body {
font-size: 14px; font-size: 14px;
} }
.reset-method-group {
margin-bottom: 16px !important;
}
.reset-method-tabs {
display: flex;
gap: 8px;
background: #f0f2f5;
border-radius: 10px;
padding: 4px;
}
.reset-method-tabs .reset-method-tab {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin: 0;
}
.reset-method-tabs .reset-method-tab input[type=radio] {
display: none;
}
.reset-method-tabs .reset-method-tab span {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
padding: 9px 12px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 13px;
font-weight: 600;
color: #8c959f;
border-radius: 7px;
transition: all 0.2s ease;
text-align: center;
}
.reset-method-tabs .reset-method-tab input[type=radio]:checked + span {
background: #FFFFFF;
color: #212529;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.09);
}
.reset-method-tabs .reset-method-tab:hover span {
color: #3ba4ed;
}
.phone-input-group { .phone-input-group {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 6px;
flex: 1; width: 100%;
} }
.phone-input-group .phone-prefix { .phone-input-group .phone-prefix {
width: 100px; width: 90px;
min-width: 90px;
flex-shrink: 0; flex-shrink: 0;
} }
.phone-input-group .phone-middle, .phone-input-group .phone-middle,
.phone-input-group .phone-last { .phone-input-group .phone-last {
width: 100px; flex: 1;
flex-shrink: 0; min-width: 0;
} }
.phone-input-group .phone-separator { .phone-input-group .phone-separator {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 8px; color: #B0B8C1;
height: 1px; font-size: 14px;
background: #515151;
flex-shrink: 0; flex-shrink: 0;
width: 10px;
height: auto;
background: transparent;
} }
@media (max-width: 768px) { .phone-input-group .phone-separator::before {
content: "-";
}
@media (max-width: 576px) {
.phone-input-group { .phone-input-group {
flex-wrap: wrap; flex-wrap: wrap;
gap: 6px; gap: 6px;
} }
.phone-input-group .phone-prefix, .phone-input-group .phone-prefix {
.phone-input-group .phone-middle,
.phone-input-group .phone-last {
flex: 1; flex: 1;
min-width: 60px; width: auto;
}
.phone-input-group .phone-separator {
width: 6px;
}
}
@media (max-width: 576px) {
.phone-input-group .phone-prefix,
.phone-input-group .phone-middle,
.phone-input-group .phone-last {
width: 100%;
} }
.phone-input-group .phone-separator { .phone-input-group .phone-separator {
display: none; display: none;
@@ -12431,92 +12442,97 @@ body.index-page-body {
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
flex: 1; width: 100%;
gap: 8px;
}
.auth-input-group.mg-y {
margin-top: 20px;
margin-bottom: 12px;
} }
.auth-input-group .auth-input { .auth-input-group .auth-input {
flex: 1; flex: 1;
padding-right: 60px; min-width: 0;
} }
.auth-input-group .auth-timer { .auth-input-group .auth-timer {
position: absolute; position: absolute;
right: 16px; right: 20px;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px; font-size: 13px;
font-weight: 400; font-weight: 500;
color: #ed5b5b; color: #ed5b5b;
pointer-events: none; pointer-events: none;
} }
@media (max-width: 576px) { @media (max-width: 576px) {
.auth-input-group .auth-timer { .auth-input-group .auth-timer {
font-size: 12px; font-size: 12px;
right: 12px; right: 100px;
} }
} }
.auth-request-button, .auth-request-button,
.auth-verify-button { .auth-verify-button {
width: 140px; height: 48px;
height: 40px; padding: 0 16px;
padding: 8px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px; font-size: 13px;
font-weight: 700; font-weight: 700;
color: #FFFFFF; color: #FFFFFF;
background: #a4d6ea; background: #3ba4ed;
border: none; border: none;
border-radius: 8px; border-radius: 10px;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.25s ease;
margin: 0;
flex-shrink: 0; flex-shrink: 0;
white-space: nowrap;
line-height: 1; line-height: 1;
} }
.auth-request-button:hover, .auth-request-button:hover,
.auth-verify-button:hover { .auth-verify-button:hover {
background: rgb(147.83125, 206.7151785714, 230.26875); background: rgb(37.3117757009, 153.9304672897, 235.0082242991);
transform: none !important;
} }
.auth-request-button:active, .auth-request-button:active,
.auth-verify-button:active { .auth-verify-button:active {
background: rgb(131.6625, 199.4303571429, 226.5375); background: rgb(21.411588785, 146.3125233645, 233.148411215);
} }
.auth-request-button:disabled, .auth-request-button:disabled,
.auth-verify-button:disabled { .auth-verify-button:disabled {
opacity: 0.6; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;
} }
@media (max-width: 576px) { @media (max-width: 576px) {
.auth-request-button, .auth-request-button,
.auth-verify-button { .auth-verify-button {
width: 100%; width: 100%;
height: 40px; height: 44px;
font-size: 13px; font-size: 13px;
margin-top: 8px; margin-top: 4px;
} }
} }
.account-recovery-card .form-actions { .account-recovery-card .form-actions {
display: flex; display: flex;
justify-content: center; justify-content: center;
gap: 20px; gap: 12px;
margin-top: 32px; margin-top: 28px;
padding: 32px 0; padding: 0;
border-top: none; border-top: none;
background: transparent; background: transparent;
} }
.account-recovery-card .form-actions .cancel-button, .account-recovery-card .form-actions .cancel-button,
.account-recovery-card .form-actions .submit-button { .account-recovery-card .form-actions .submit-button {
width: 160px; flex: 1;
height: 40px; height: 48px;
padding: 8px; padding: 0 8px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px; font-size: 15px;
font-weight: 700; font-weight: 700;
border: none; border: none;
border-radius: 8px; border-radius: 10px;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.25s ease;
line-height: 1; line-height: 1;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -12525,20 +12541,20 @@ body.index-page-body {
} }
.account-recovery-card .form-actions .cancel-button { .account-recovery-card .form-actions .cancel-button {
color: #5f666c; color: #5f666c;
background: #e5e7eb; background: #f0f2f5;
} }
.account-recovery-card .form-actions .cancel-button:hover { .account-recovery-card .form-actions .cancel-button:hover {
background: rgb(215.8869565217, 218.8956521739, 224.9130434783); background: rgb(225.45, 229.39, 235.3);
} }
.account-recovery-card .form-actions .cancel-button:active { .account-recovery-card .form-actions .cancel-button:active {
background: rgb(202.7739130435, 206.7913043478, 214.8260869565); background: rgb(210.9, 216.78, 225.6);
} }
.account-recovery-card .form-actions .submit-button { .account-recovery-card .form-actions .submit-button {
color: #FFFFFF; color: #FFFFFF;
background: #0049B4; background: #0049B4;
} }
.account-recovery-card .form-actions .submit-button:hover { .account-recovery-card .form-actions .submit-button:hover {
background: rgb(0, 69.35, 171); background: rgb(6, 54, 125);
} }
.account-recovery-card .form-actions .submit-button:active { .account-recovery-card .form-actions .submit-button:active {
background: rgb(0, 65.7, 162); background: rgb(0, 65.7, 162);
@@ -12549,15 +12565,12 @@ body.index-page-body {
} }
@media (max-width: 576px) { @media (max-width: 576px) {
.account-recovery-card .form-actions { .account-recovery-card .form-actions {
flex-direction: column;
gap: 10px; gap: 10px;
padding: 20px 0;
} }
.account-recovery-card .form-actions .cancel-button, .account-recovery-card .form-actions .cancel-button,
.account-recovery-card .form-actions .submit-button { .account-recovery-card .form-actions .submit-button {
width: 100%; height: 44px;
height: 40px; font-size: 14px;
font-size: 13px;
} }
} }
@@ -12613,7 +12626,6 @@ body.index-page-body {
} }
.account-recovery-result { .account-recovery-result {
width: 100%; width: 100%;
background: #F6F9FB;
padding: 60px 40px; padding: 60px 40px;
border-radius: 0 0 12px 12px; border-radius: 0 0 12px 12px;
text-align: center; text-align: center;
@@ -12765,128 +12777,62 @@ body.index-page-body {
margin: 0; margin: 0;
} }
.account-recovery-container { .account-recovery-container {
padding: 20px; padding: 16px;
} }
.account-recovery-card { .account-recovery-card {
padding: 0; padding: 24px 16px 20px;
border-radius: 16px;
}
.account-recovery-tabs {
margin-bottom: 20px;
} }
.account-recovery-tabs .tab-link { .account-recovery-tabs .tab-link {
height: 40px; padding: 9px 12px;
padding: 10px 16px; font-size: 13px;
font-size: 14px;
font-weight: 700;
}
.account-recovery-tabs .tab-link:first-child {
border-radius: 8px 0 0 0;
}
.account-recovery-tabs .tab-link:last-child {
border-radius: 0 8px 0 0;
}
.account-recovery-form {
padding: 20px;
border-radius: 0 0 8px 8px;
} }
.account-recovery-form .form-group { .account-recovery-form .form-group {
flex-direction: column; margin-bottom: 10px;
align-items: stretch;
gap: 8px;
margin-bottom: 16px;
}
.account-recovery-form .form-label {
width: 100%;
font-size: 14px;
font-weight: 500;
margin-bottom: 0;
} }
.account-recovery-form .form-input { .account-recovery-form .form-input {
flex: none; height: 44px;
width: 100%; font-size: 13px;
height: 40px;
padding: 0 16px;
font-size: 12px;
border-radius: 8px;
}
.account-recovery-form .form-input::placeholder {
color: #8c959f;
} }
.account-recovery-form .form-select { .account-recovery-form .form-select {
height: 40px; height: 44px;
padding: 0 32px 0 12px; font-size: 13px;
font-size: 12px;
border-radius: 8px;
background-position: right 10px center;
} }
.phone-input-group { .phone-input-group {
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 6px;
align-items: center;
width: 100%;
} }
.phone-input-group .phone-prefix { .phone-input-group .phone-prefix {
flex: 1; flex: 1;
min-width: 0;
width: auto;
}
.phone-input-group .phone-middle,
.phone-input-group .phone-last {
flex: 1;
min-width: 0;
width: auto; width: auto;
} }
.phone-input-group .phone-separator { .phone-input-group .phone-separator {
display: flex; display: none;
width: auto;
height: auto;
background: transparent;
font-size: 12px;
color: #000;
}
.phone-input-group .phone-separator::before {
content: "-";
}
.auth-input-group {
width: 100%;
}
.auth-input-group .auth-input {
width: 100%;
padding-right: 60px;
} }
.auth-input-group .auth-timer { .auth-input-group .auth-timer {
font-size: 12px; font-size: 12px;
right: 12px; right: 100px;
} }
.auth-request-button, .auth-request-button,
.auth-verify-button { .auth-verify-button {
width: 100%; width: 100%;
height: 40px; height: 44px;
padding: 10px; font-size: 13px;
font-size: 14px; margin-top: 4px;
font-weight: 700;
border-radius: 8px;
margin-top: 8px;
} }
.account-recovery-card .form-actions { .account-recovery-card .form-actions {
flex-direction: row; flex-direction: row;
gap: 21px; gap: 10px;
margin-top: 24px; margin-top: 20px;
padding: 24px 0;
} }
.account-recovery-card .form-actions .cancel-button, .account-recovery-card .form-actions .cancel-button,
.account-recovery-card .form-actions .submit-button { .account-recovery-card .form-actions .submit-button {
flex: 1; flex: 1;
min-width: 144px; height: 44px;
height: 40px;
font-size: 14px; font-size: 14px;
font-weight: 700;
border-radius: 8px;
}
.account-recovery-card .form-actions .cancel-button {
background: #e5e7eb;
color: #5f666c;
}
.account-recovery-card .form-actions .submit-button {
background: #0049b4;
color: #ffffff;
} }
.account-recovery-result { .account-recovery-result {
padding: 30px 20px; padding: 30px 20px;
@@ -13376,7 +13322,7 @@ body.index-page-body {
.corp-manager-wrapper .input-readonly, .corp-manager-wrapper .input-readonly,
.password-change-wrapper .form-input:disabled, .password-change-wrapper .form-input:disabled,
.password-change-wrapper .input-readonly { .password-change-wrapper .input-readonly {
background: #ededed; background: #e9ecef !important;
} }
.corp-manager-wrapper .compound-input, .corp-manager-wrapper .compound-input,
.password-change-wrapper .compound-input { .password-change-wrapper .compound-input {
@@ -21429,7 +21375,6 @@ input[type=checkbox]:checked + .custom-checkbox {
} }
.org-compound-input .org-form-input, .org-compound-input .org-form-input,
.org-compound-input .org-form-select { .org-compound-input .org-form-select {
flex: 1;
min-width: 0; min-width: 0;
} }
.org-compound-input .org-form-input.phone-number { .org-compound-input .org-form-input.phone-number {
@@ -21571,16 +21516,15 @@ input[type=checkbox]:checked + .custom-checkbox {
padding: 10px 20px; padding: 10px 20px;
width: auto; width: auto;
min-width: 100px; min-width: 100px;
background: #00A1D7;
color: #FFFFFF; color: #FFFFFF;
border: 1px solid #00A1D7;
border-radius: 8px; border-radius: 8px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 14px; font-size: 14px;
font-weight: 700; font-weight: 700;
text-align: center; text-align: center;
justify-content: center; justify-content: center;
transition: all 0.2s ease; background: #3BA4ED;
border: 1px solid #3BA4ED;
} }
.org-btn-check:not(:disabled):hover, .org-file-label:not(:disabled):hover { .org-btn-check:not(:disabled):hover, .org-file-label:not(:disabled):hover {
background: #008BC0; background: #008BC0;
@@ -21806,6 +21750,7 @@ input[type=checkbox]:checked + .custom-checkbox {
flex-direction: column; flex-direction: column;
gap: 20px; gap: 20px;
margin-bottom: 90px; margin-bottom: 90px;
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
} }
.agreement-all-section { .agreement-all-section {
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
@@ -478,7 +478,7 @@ select.form-control {
&:disabled, &:disabled,
&.input-readonly { &.input-readonly {
background: $gray-bg; background: #e9ecef !important;
color: $text-gray; color: $text-gray;
cursor: not-allowed; cursor: not-allowed;
} }
@@ -913,7 +913,7 @@
.nav-menu { .nav-menu {
display: flex; display: flex;
list-style: none; list-style: none;
gap: 28px; gap: 24px;
margin: 0; margin: 0;
padding: 0; padding: 0;
@@ -925,6 +925,7 @@
>.nav-link { >.nav-link {
background: var(--light-bg); background: var(--light-bg);
color: var(--primary-blue); color: var(--primary-blue);
border-radius: 9px;
} }
.sub-menu { .sub-menu {
@@ -978,7 +979,7 @@
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
color: var(--text-gray); color: var(--text-gray);
padding: 8px; padding: 12px;
position: relative; position: relative;
transition: var(--transition-smooth); transition: var(--transition-smooth);
@@ -9,33 +9,35 @@
.account-recovery-page { .account-recovery-page {
display: flex; display: flex;
align-items: flex-start; align-items: center;
justify-content: center; justify-content: center;
background: transparent; padding: 100px 20px;
padding: 0;
position: relative; position: relative;
min-height: auto; border-radius: 12px;
margin: 0; margin-bottom: 50px;
} }
.account-recovery-container { .account-recovery-container {
width: 100%; width: 100%;
max-width: 800px; max-width: 650px;
margin: 0 auto; margin: 0 auto;
position: relative; position: relative;
padding: $spacing-lg; padding: $spacing-lg;
} }
.account-recovery-card { .account-recovery-card {
background: transparent; background: #FFFFFF;
padding: 0; border-radius: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.10);
padding: 36px 36px 28px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
position: relative; position: relative;
@media (max-width: 576px) { @media (max-width: 576px) {
padding: 0 20px; padding: 24px 20px 20px;
border-radius: 16px;
} }
} }
@@ -49,14 +51,13 @@
display: none; display: none;
} }
// Tab Navigation (Figma 디자인: 약관 페이지와 동일) // Tab Navigation (Design 2: 클래식 폴더 탭)
.account-recovery-tabs { .account-recovery-tabs {
display: flex; display: flex;
gap: 0; gap: 0;
margin-bottom: 0; margin-bottom: 28px;
width: 100%; width: 100%;
background: transparent; background: transparent;
border-radius: 0;
padding: 0; padding: 0;
.tab-link { .tab-link {
@@ -64,45 +65,46 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 14px 24px; padding: 14px 20px;
font-family: $font-family-primary; font-family: $font-family-primary;
font-size: 16px; font-size: 15px;
font-weight: 700; font-weight: 400;
color: #8c959f; color: #adb5bd;
text-decoration: none; text-decoration: none;
text-align: center; text-align: center;
background: #eceff4; background: #FFFFFF;
// 비활성 탭: 하단 border만 (바닥선 역할)
border: 1.5px solid transparent;
border-bottom: 1.5px solid #dee2e6;
border-radius: 0; border-radius: 0;
transition: all 0.3s ease; transition: all 0.2s ease;
cursor: pointer;
// 왼쪽 탭 둥근 모서리 position: relative;
&:first-child {
border-radius: 30px 0 0 0;
}
// 오른쪽 탭 둥근 모서리
&:last-child {
border-radius: 0 30px 0 0;
}
&:hover { &:hover {
color: #3ba4ed; color: $primary-blue;
background: #e4e8ed;
} }
&.active { &.active {
color: #FFFFFF; color: $primary-blue;
background: #3ba4ed;
font-weight: 700; font-weight: 700;
// 활성 탭: 상/좌/우 파란 테두리 + 하단 흰색으로 바닥선 가려 콘텐츠와 연결
border-top: 1.5px solid $primary-blue;
border-left: 1.5px solid $primary-blue;
border-right: 1.5px solid $primary-blue;
border-bottom: 2px solid #FFFFFF;
border-radius: 8px 8px 0px 0px;
} }
@media (max-width: 576px) { @media (max-width: 576px) {
padding: 12px 16px; padding: 12px 10px;
font-size: 14px; font-size: 13px;
} }
} }
} }
// Alert Messages // Alert Messages
.account-alert { .account-alert {
width: 100%; width: 100%;
@@ -140,73 +142,45 @@
} }
} }
// Form Content Area (Figma: 아이디찾기BG_box) // Form Content Area (세로 스택형, 라벨 없는 심플 스타일)
.account-recovery-form { .account-recovery-form {
width: 100%; width: 100%;
margin-bottom: 0; margin-bottom: 0;
background: #F6F9FB; background: transparent;
padding: 40px; padding: 0;
border-radius: 0 0 12px 12px;
@media (max-width: 576px) {
padding: 24px 16px;
}
.form-group { .form-group {
display: flex; display: flex;
align-items: center; flex-direction: column;
gap: 20px; gap: 0;
margin-bottom: 20px; margin-bottom: 12px;
&:last-of-type { &:last-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
@media (max-width: 768px) {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
} }
// 라벨은 숨김 (placeholder로 대체)
.form-label { .form-label {
display: flex; display: none;
align-items: center;
flex-shrink: 0;
width: 170px;
font-family: $font-family-primary;
font-size: 15px;
font-weight: 400;
color: #212529;
margin-bottom: 0;
.required {
color: #ed5b5b;
margin-left: 2px;
}
@media (max-width: 768px) {
width: 100%;
font-size: 14px;
}
} }
.form-input { .form-input {
flex: 1; width: 100%;
height: 40px; height: 48px;
padding: 0 16px; padding: 0 16px;
font-family: $font-family-primary; font-family: $font-family-primary;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
color: #212529; color: #212529;
background: #FFFFFF; background: #FFFFFF;
border: 1px solid #dadada; border: 1px solid #E2E8F0;
border-radius: 8px; border-radius: 10px;
outline: none; outline: none;
transition: all 0.3s ease; transition: all 0.25s ease;
&::placeholder { &::placeholder {
color: #dadada; color: #B0B8C1;
} }
&:hover { &:hover {
@@ -215,7 +189,7 @@
&:focus { &:focus {
border-color: #3ba4ed; border-color: #3ba4ed;
box-shadow: 0 0 0 2px rgba(59, 164, 237, 0.1); box-shadow: 0 0 0 3px rgba(59, 164, 237, 0.12);
} }
&:disabled { &:disabled {
@@ -231,24 +205,24 @@
} }
.form-select { .form-select {
height: 40px; height: 48px;
padding: 0 32px 0 16px; padding: 0 24px 0 12px; // padding을 좀 더 좁혀서 내용이 더 잘 보이도록 수정
font-family: $font-family-primary; font-family: $font-family-primary;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
color: #515151; color: #515151;
background: #FFFFFF; background: #FFFFFF;
border: 1px solid #dadada; border: 1px solid #E2E8F0;
border-radius: 8px; border-radius: 10px;
outline: none; outline: none;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.25s ease;
appearance: none; appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='5' viewBox='0 0 10 5'%3E%3Cpath fill='%231D1B20' d='M5 5L0 0h10z'/%3E%3C/svg%3E"); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='5' viewBox='0 0 10 5'%3E%3Cpath fill='%231D1B20' d='M5 5L0 0h10z'/%3E%3C/svg%3E");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right 12px center; background-position: right 8px center; // 화살표 아이콘 위치도 조정
background-size: 10px 5px; background-size: 10px 5px;
&:hover { &:hover {
@@ -257,7 +231,7 @@
&:focus { &:focus {
border-color: #3ba4ed; border-color: #3ba4ed;
box-shadow: 0 0 0 2px rgba(59, 164, 237, 0.1); box-shadow: 0 0 0 3px rgba(59, 164, 237, 0.12);
} }
&:disabled { &:disabled {
@@ -275,55 +249,99 @@
} }
} }
// Phone Input Group (Figma: 휴대폰번호+텍스트필드) // 인증 방식 선택 pill 탭 (비밀번호 초기화 탭 내부)
.reset-method-group {
margin-bottom: 16px !important;
}
.reset-method-tabs {
display: flex;
gap: 8px;
background: #f0f2f5;
border-radius: 10px;
padding: 4px;
.reset-method-tab {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin: 0;
input[type="radio"] {
display: none;
}
span {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
padding: 9px 12px;
font-family: $font-family-primary;
font-size: 13px;
font-weight: 600;
color: #8c959f;
border-radius: 7px;
transition: all 0.2s ease;
text-align: center;
}
input[type="radio"]:checked+span {
background: #FFFFFF;
color: #212529;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.09);
}
&:hover span {
color: #3ba4ed;
}
}
}
// Phone Input Group
.phone-input-group { .phone-input-group {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 6px;
flex: 1; width: 100%;
.phone-prefix { .phone-prefix {
width: 100px; width: 90px;
min-width: 90px; // select가 줄어들지 않도록 고정
flex-shrink: 0; flex-shrink: 0;
} }
.phone-middle, .phone-middle,
.phone-last { .phone-last {
width: 100px; flex: 1;
flex-shrink: 0; min-width: 0;
} }
.phone-separator { .phone-separator {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 8px; color: #B0B8C1;
height: 1px; font-size: 14px;
background: #515151;
flex-shrink: 0; flex-shrink: 0;
} width: 10px;
height: auto;
background: transparent;
@media (max-width: 768px) { &::before {
flex-wrap: wrap; content: '-';
gap: 6px;
.phone-prefix,
.phone-middle,
.phone-last {
flex: 1;
min-width: 60px;
}
.phone-separator {
width: 6px;
} }
} }
@media (max-width: 576px) { @media (max-width: 576px) {
.phone-prefix, flex-wrap: wrap;
.phone-middle, gap: 6px;
.phone-last {
width: 100%; .phone-prefix {
flex: 1;
width: auto;
} }
.phone-separator { .phone-separator {
@@ -332,7 +350,7 @@
} }
} }
// Auth Number Group (Figma: 인증번호+텍스트필드) // Auth Number Group
.auth-number-group { .auth-number-group {
margin-top: 0; margin-top: 0;
} }
@@ -341,95 +359,103 @@
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
flex: 1; width: 100%;
gap: 8px;
&.mg-y {
margin-top: 20px;
margin-bottom: 12px;
}
.auth-input { .auth-input {
flex: 1; flex: 1;
padding-right: 60px; min-width: 0;
} }
.auth-timer { .auth-timer {
position: absolute; position: absolute;
right: 16px; right: 20px; // verify button width + gap
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
font-family: $font-family-primary; font-family: $font-family-primary;
font-size: 14px; font-size: 13px;
font-weight: 400; font-weight: 500;
color: #ed5b5b; color: #ed5b5b;
pointer-events: none; pointer-events: none;
@media (max-width: 576px) { @media (max-width: 576px) {
font-size: 12px; font-size: 12px;
right: 12px; right: 100px;
} }
} }
} }
// Buttons (Figma: 인증번호 받기/확인) // Buttons: 인증번호 받기 / 확인
.auth-request-button, .auth-request-button,
.auth-verify-button { .auth-verify-button {
width: 140px; height: 48px;
height: 40px; padding: 0 16px;
padding: 8px;
font-family: $font-family-primary; font-family: $font-family-primary;
font-size: 14px; font-size: 13px;
font-weight: 700; font-weight: 700;
color: #FFFFFF; color: #FFFFFF;
background: #a4d6ea; background: #3ba4ed;
border: none; border: none;
border-radius: 8px; border-radius: 10px;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.25s ease;
margin: 0;
flex-shrink: 0; flex-shrink: 0;
white-space: nowrap;
line-height: 1; line-height: 1;
&:hover { &:hover {
background: darken(#a4d6ea, 5%); background: darken(#3ba4ed, 8%);
transform: none !important;
} }
&:active { &:active {
background: darken(#a4d6ea, 10%); background: darken(#3ba4ed, 14%);
} }
&:disabled { &:disabled {
opacity: 0.6; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;
} }
@media (max-width: 576px) { @media (max-width: 576px) {
width: 100%; width: 100%;
height: 40px; height: 44px;
font-size: 13px; font-size: 13px;
margin-top: 8px; margin-top: 4px;
} }
} }
// Form Actions (Figma: btn_취소, btn_신청) // Form Actions
.account-recovery-card .form-actions { .account-recovery-card .form-actions {
display: flex; display: flex;
justify-content: center; justify-content: center;
gap: 20px; gap: 12px;
margin-top: 32px; margin-top: 28px;
padding: 32px 0; padding: 0;
border-top: none; border-top: none;
background: transparent; background: transparent;
.cancel-button, .cancel-button,
.submit-button { .submit-button {
width: 160px; flex: 1;
height: 40px; height: 48px;
padding: 8px; padding: 0 8px;
font-family: $font-family-primary; font-family: $font-family-primary;
font-size: 14px; font-size: 15px;
font-weight: 700; font-weight: 700;
border: none; border: none;
border-radius: 8px; border-radius: 10px;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.25s ease;
line-height: 1; line-height: 1;
// <a> 태그 지원
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -438,14 +464,14 @@
.cancel-button { .cancel-button {
color: #5f666c; color: #5f666c;
background: #e5e7eb; background: #f0f2f5;
&:hover { &:hover {
background: darken(#e5e7eb, 5%); background: darken(#f0f2f5, 5%);
} }
&:active { &:active {
background: darken(#e5e7eb, 10%); background: darken(#f0f2f5, 10%);
} }
} }
@@ -454,7 +480,9 @@
background: #0049B4; background: #0049B4;
&:hover { &:hover {
background: darken(#0049B4, 5%); // background: darken(#0049B4, 5%);
background: rgb(6 54 125);
} }
&:active { &:active {
@@ -468,15 +496,12 @@
} }
@media (max-width: 576px) { @media (max-width: 576px) {
flex-direction: column;
gap: 10px; gap: 10px;
padding: 20px 0;
.cancel-button, .cancel-button,
.submit-button { .submit-button {
width: 100%; height: 44px;
height: 40px; font-size: 14px;
font-size: 13px;
} }
} }
} }
@@ -521,6 +546,7 @@
opacity: 0; opacity: 0;
transform: translateY(-10px); transform: translateY(-10px);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
@@ -545,7 +571,6 @@
// Result Page Styles (아이디 찾기 결과 페이지) // Result Page Styles (아이디 찾기 결과 페이지)
.account-recovery-result { .account-recovery-result {
width: 100%; width: 100%;
background: #F6F9FB;
padding: 60px 40px; padding: 60px 40px;
border-radius: 0 0 12px 12px; border-radius: 0 0 12px 12px;
text-align: center; text-align: center;
@@ -701,7 +726,7 @@
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Figma Mobile Design - node 1152-7047 (sm: 768px breakpoint) // Mobile Design (sm: 768px breakpoint)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@include respond-to('sm') { @include respond-to('sm') {
.account-recovery-page { .account-recovery-page {
@@ -710,164 +735,78 @@
} }
.account-recovery-container { .account-recovery-container {
padding: 20px; padding: 16px;
} }
.account-recovery-card { .account-recovery-card {
padding: 0; padding: 24px 16px 20px;
border-radius: 16px;
} }
// Figma: 탭 - 167px × 40px, 14px Bold
.account-recovery-tabs { .account-recovery-tabs {
margin-bottom: 20px;
.tab-link { .tab-link {
height: 40px; padding: 9px 12px;
padding: 10px 16px; font-size: 13px;
font-size: 14px;
font-weight: 700;
&:first-child {
border-radius: 8px 0 0 0;
}
&:last-child {
border-radius: 0 8px 0 0;
}
} }
} }
// Figma: 폼 영역
.account-recovery-form { .account-recovery-form {
padding: 20px;
border-radius: 0 0 8px 8px;
.form-group { .form-group {
flex-direction: column; margin-bottom: 10px;
align-items: stretch;
gap: 8px;
margin-bottom: 16px;
} }
// Figma: 라벨 - 14px Medium
.form-label {
width: 100%;
font-size: 14px;
font-weight: 500;
margin-bottom: 0;
}
// Figma: 입력 필드 - 335px × 40px, border-radius 8px
.form-input { .form-input {
flex: none; height: 44px;
width: 100%; font-size: 13px;
height: 40px;
padding: 0 16px;
font-size: 12px;
border-radius: 8px;
&::placeholder {
color: #8c959f;
}
} }
// Figma: 셀렉트 - 40px 높이, 8px radius
.form-select { .form-select {
height: 40px; height: 44px;
padding: 0 32px 0 12px; font-size: 13px;
font-size: 12px;
border-radius: 8px;
background-position: right 10px center;
} }
} }
// 모바일: 휴대폰 번호 입력 - 화면 폭 채우기
.phone-input-group { .phone-input-group {
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 6px;
align-items: center;
width: 100%;
.phone-prefix { .phone-prefix {
flex: 1; flex: 1;
min-width: 0;
width: auto;
}
.phone-middle,
.phone-last {
flex: 1;
min-width: 0;
width: auto; width: auto;
} }
.phone-separator { .phone-separator {
display: flex; display: none;
width: auto;
height: auto;
background: transparent;
font-size: 12px;
color: #000;
&::before {
content: '-';
}
} }
} }
// 모바일: 인증번호 입력 그룹 - 화면 폭 채우기
.auth-input-group { .auth-input-group {
width: 100%;
.auth-input {
width: 100%;
padding-right: 60px;
}
// 타이머 - 12px, #ed5b5b
.auth-timer { .auth-timer {
font-size: 12px; font-size: 12px;
right: 12px; right: 100px;
} }
} }
// 모바일: 인증번호 받기/확인 버튼 - 화면 폭 채우기, 다음 줄에 배치
.auth-request-button, .auth-request-button,
.auth-verify-button { .auth-verify-button {
width: 100%; width: 100%;
height: 40px; height: 44px;
padding: 10px; font-size: 13px;
font-size: 14px; margin-top: 4px;
font-weight: 700;
border-radius: 8px;
margin-top: 8px;
} }
// Figma: 하단 버튼 - 144px × 40px, gap 21px, 가로 배치
.account-recovery-card .form-actions { .account-recovery-card .form-actions {
flex-direction: row; flex-direction: row;
gap: 21px; gap: 10px;
margin-top: 24px; margin-top: 20px;
padding: 24px 0;
.cancel-button, .cancel-button,
.submit-button { .submit-button {
flex: 1; flex: 1;
min-width: 144px; height: 44px;
height: 40px;
font-size: 14px; font-size: 14px;
font-weight: 700;
border-radius: 8px;
}
// Figma: 취소 버튼 - #e5e7eb 배경, #5f666c 텍스트
.cancel-button {
background: #e5e7eb;
color: #5f666c;
}
// Figma: 제출 버튼 - #0049b4 배경, 흰색 텍스트
.submit-button {
background: #0049b4;
color: #ffffff;
} }
} }
@@ -159,7 +159,7 @@
.form-input:disabled, .form-input:disabled,
.input-readonly { .input-readonly {
background: #ededed; background: #e9ecef !important;
} }
.compound-input { .compound-input {
@@ -295,7 +295,6 @@
.org-form-input, .org-form-input,
.org-form-select { .org-form-select {
flex: 1;
min-width: 0; min-width: 0;
} }
@@ -455,16 +454,16 @@
padding: 10px 20px; padding: 10px 20px;
width: auto; width: auto;
min-width: 100px; min-width: 100px;
background: #00A1D7;
color: $white; color: $white;
border: 1px solid #00A1D7;
border-radius: 8px; border-radius: 8px;
font-family: $font-family-primary; font-family: $font-family-primary;
font-size: 14px; font-size: 14px;
font-weight: 700; font-weight: 700;
text-align: center; text-align: center;
justify-content: center; justify-content: center;
transition: all 0.2s ease; // transition: all 0.2s ease;
background: #3BA4ED;
border: 1px solid #3BA4ED;
&:not(:disabled):hover { &:not(:disabled):hover {
background: #008BC0; background: #008BC0;
@@ -721,6 +720,7 @@
flex-direction: column; flex-direction: column;
gap: 20px; gap: 20px;
margin-bottom: 90px; margin-bottom: 90px;
font-family: $font-family-primary;
} }
// Agree All Section // Agree All Section
@@ -10,7 +10,8 @@
</div> </div>
</section> </section>
<section layout:fragment="contentFragment"> <section layout:fragment="contentFragment">
<div class="service-main"> <div class="service-main container" style="padding-top: 70px; padding-bottom:100px;">
<th:block th:replace="~{fragment/djbank/service_sidebar :: sidebar('profile')}"></th:block>
<div class="app-management-content"> <div class="app-management-content">
<div class="password-change-wrapper"> <div class="password-change-wrapper">
<h2 class="page-outer-title">본인 확인</h2> <h2 class="page-outer-title">본인 확인</h2>
@@ -1,12 +1,14 @@
<!doctype html> <!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" <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/kbank_base_layout}">
<body> <body>
<section layout:fragment="contentFragment" class="content"> <section layout:fragment="contentFragment" class="content">
<div class="content_wrap"> <div class="content_wrap">
<div class="account-recovery-container"> <div class="account-recovery-container">
<div class="account-recovery-card"> <div class="account-recovery-card">
<!-- 탭 메뉴 -->
<!-- 탭 메뉴 (pill 스타일) -->
<div class="account-recovery-tabs"> <div class="account-recovery-tabs">
<a href="#tab1" class="tab-link active" data-tab="tab1">아이디 찾기</a> <a href="#tab1" class="tab-link active" data-tab="tab1">아이디 찾기</a>
<a href="#tab2" class="tab-link" data-tab="tab2">비밀번호 초기화</a> <a href="#tab2" class="tab-link" data-tab="tab2">비밀번호 초기화</a>
@@ -14,19 +16,18 @@
<!-- 아이디 찾기 폼 --> <!-- 아이디 찾기 폼 -->
<div id="tab1" class="account-recovery-form"> <div id="tab1" class="account-recovery-form">
<form id="findIdForm" role="form" name="findIdForm" th:action="@{/find_id}" method="post" data-form-type="findId"> <form id="findIdForm" role="form" name="findIdForm" th:action="@{/find_id}" method="post"
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> data-form-type="findId">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<input type="hidden" id="findId-phoneNumber" name="phoneNumber"> <input type="hidden" id="findId-phoneNumber" name="phoneNumber">
<!-- 성명 입력 --> <!-- 성명 입력 -->
<div class="form-group"> <div class="form-group">
<label class="form-label">성명</label> <input type="text" name="name" class="form-input" placeholder="성명" required>
<input type="text" name="name" class="form-input" placeholder="이름" required>
</div> </div>
<!-- 휴대폰 번호 입력 --> <!-- 휴대폰 번호 입력 -->
<div class="form-group"> <div class="form-group">
<label class="form-label">휴대폰 번호</label>
<div class="phone-input-group"> <div class="phone-input-group">
<select class="form-select phone-prefix select_mobile_prefix"> <select class="form-select phone-prefix select_mobile_prefix">
<option>선택</option> <option>선택</option>
@@ -46,7 +47,6 @@
<!-- 인증번호 입력 --> <!-- 인증번호 입력 -->
<div class="form-group auth-number-container" id="findId-authNumberContainer" style="display: none;"> <div class="form-group auth-number-container" id="findId-authNumberContainer" style="display: none;">
<label class="form-label">인증번호 입력</label>
<div class="auth-input-group"> <div class="auth-input-group">
<input type="number" class="form-input auth-input auth-number-input" placeholder="SMS 인증번호" required> <input type="number" class="form-input auth-input auth-number-input" placeholder="SMS 인증번호" required>
<span class="auth-timer" id="findId-certify_time">03:00</span> <span class="auth-timer" id="findId-certify_time">03:00</span>
@@ -63,41 +63,38 @@
</div> </div>
<!-- 비밀번호 초기화 폼 --> <!-- 비밀번호 초기화 폼 -->
<div id="tab2" class="account-recovery-form"> <div id="tab2" class="account-recovery-form" style="display: none;">
<form id="resetPasswordForm" role="form" name="resetPasswordForm" th:action="@{/reset_password}" method="post" data-form-type="resetPassword"> <form id="resetPasswordForm" role="form" name="resetPasswordForm" th:action="@{/reset_password}"
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> method="post" data-form-type="resetPassword">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<input type="hidden" id="resetPassword-phoneNumber" name="phoneNumber"> <input type="hidden" id="resetPassword-phoneNumber" name="phoneNumber">
<!-- 인증 방식 선택 --> <!-- 인증 방식 선택 (pill 버튼 스타일) -->
<div class="form-group"> <div class="form-group reset-method-group">
<label class="form-label">초기화 방법</label> <div class="reset-method-tabs">
<div style="display: flex; gap: 20px; align-items: center;"> <label class="reset-method-tab">
<label style="display: flex; align-items: center; gap: 6px; font-size: 14px; margin: 0;">
<input type="radio" id="radio_hp" name="resetMethod" value="hp" checked> <input type="radio" id="radio_hp" name="resetMethod" value="hp" checked>
휴대폰 번호 <span>휴대폰 번호</span>
</label> </label>
<label style="display: flex; align-items: center; gap: 6px; font-size: 14px; margin: 0;"> <label class="reset-method-tab">
<input type="radio" id="radio_email" name="resetMethod" value="email_id"> <input type="radio" id="radio_email" name="resetMethod" value="email_id">
이메일 아이디 <span>이메일 아이디</span>
</label> </label>
</div> </div>
</div> </div>
<!-- 성명 입력 --> <!-- 성명 입력 -->
<div class="form-group"> <div class="form-group">
<label class="form-label">성명</label>
<input type="text" name="name" class="form-input" placeholder="성명" required> <input type="text" name="name" class="form-input" placeholder="성명" required>
</div> </div>
<!-- 아이디 입력 (이메일) --> <!-- 아이디 입력 (이메일) -->
<div class="form-group" id="emailInputContainer" style="display: none;"> <div class="form-group" id="emailInputContainer" style="display: none;">
<label class="form-label">이메일 아이디</label>
<input type="text" name="emailId" class="form-input" placeholder="이메일 아이디"> <input type="text" name="emailId" class="form-input" placeholder="이메일 아이디">
</div> </div>
<!-- 휴대폰 번호 입력 --> <!-- 휴대폰 번호 입력 -->
<div class="form-group" id="phoneInputContainer"> <div class="form-group" id="phoneInputContainer">
<label class="form-label">휴대폰 번호</label>
<div class="phone-input-group"> <div class="phone-input-group">
<select class="form-select phone-prefix select_mobile_prefix"> <select class="form-select phone-prefix select_mobile_prefix">
<option>선택</option> <option>선택</option>
@@ -117,8 +114,7 @@
<!-- 인증번호 입력 --> <!-- 인증번호 입력 -->
<div class="form-group auth-number-container" id="authNumberContainer" style="display: none;"> <div class="form-group auth-number-container" id="authNumberContainer" style="display: none;">
<label class="form-label">인증번호 입력</label> <div class="auth-input-group mg-y">
<div class="auth-input-group">
<input type="number" class="form-input auth-input auth-number-input" placeholder="SMS 인증번호" required> <input type="number" class="form-input auth-input auth-number-input" placeholder="SMS 인증번호" required>
<span class="auth-timer" id="certify_time">03:00</span> <span class="auth-timer" id="certify_time">03:00</span>
<button type="button" class="auth-verify-button btn_verify_auth">확인</button> <button type="button" class="auth-verify-button btn_verify_auth">확인</button>
@@ -132,17 +128,18 @@
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</body> </body>
<th:block layout:fragment="contentScript"> <th:block layout:fragment="contentScript">
<script th:inline="javascript"> <script th:inline="javascript">
$(document).ready(function() { $(document).ready(function () {
// 탭 전환 기능 // 탭 전환 기능
$('.tab-link').on('click', function(e) { $('.tab-link').on('click', function (e) {
e.preventDefault(); e.preventDefault();
const tabId = $(this).data('tab'); const tabId = $(this).data('tab');
@@ -158,7 +155,7 @@
}); });
// 초기화 방법 선택에 따라 폼 표시 변경 // 초기화 방법 선택에 따라 폼 표시 변경
$('input[name="resetMethod"]').change(function() { $('input[name="resetMethod"]').change(function () {
if (this.value === 'hp') { if (this.value === 'hp') {
$('#phoneInputContainer').show(); $('#phoneInputContainer').show();
$('#emailInputContainer').hide(); $('#emailInputContainer').hide();
@@ -169,7 +166,7 @@
}); });
// 취소 버튼 클릭 시 로그인 페이지로 이동 // 취소 버튼 클릭 시 로그인 페이지로 이동
$('.btn_cancel').on('click', function() { $('.btn_cancel').on('click', function () {
location.href = '/login'; location.href = '/login';
}); });
@@ -189,7 +186,7 @@
} }
// 인증번호 요청 버튼 이벤트 리스너 // 인증번호 요청 버튼 이벤트 리스너
$(".btn_auth").on("click", function(e) { $(".btn_auth").on("click", function (e) {
e.preventDefault(); e.preventDefault();
let form = $(this).closest("form"); let form = $(this).closest("form");
let mobileNumber = combineMobileNumber(form); let mobileNumber = combineMobileNumber(form);
@@ -201,7 +198,7 @@
}); });
// 인증번호 확인 버튼 이벤트 리스너 // 인증번호 확인 버튼 이벤트 리스너
$(".btn_verify_auth").on("click", function(e) { $(".btn_verify_auth").on("click", function (e) {
e.preventDefault(); e.preventDefault();
let form = $(this).closest("form"); let form = $(this).closest("form");
let authNumberInput = form.find(".auth-number-input"); let authNumberInput = form.find(".auth-number-input");
@@ -216,4 +213,5 @@
}); });
</script> </script>
</th:block> </th:block>
</html> </html>
@@ -1,20 +1,21 @@
<!doctype html> <!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" <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/djbank_title_layout}"> xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
<body> <body>
<section layout:fragment="title"> <section layout:fragment="title">
<div class="page-title-banner"> <div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image"> <img th:src="@{/img/img_title_bg.png}" class="title-image">
<h1>아이디 찾기</h1> <h1>아이디 찾기</h1>
</div> </div>
</section> </section>
<th:block layout:fragment="contentFragment"> <th:block layout:fragment="contentFragment">
<div class="account-recovery-page"> <div class="account-recovery-page">
<div class="account-recovery-container"> <div class="account-recovery-container">
<div class="account-recovery-card"> <div class="account-recovery-card">
<!-- Tab Navigation --> <!-- Tab Navigation -->
<div class="account-recovery-tabs"> <div class="account-recovery-tabs">
<a href="#" class="tab-link active">아이디찾기</a> <a href="#" class="tab-link active">아이디 찾기</a>
<a th:href="@{/account_recovery(tab='resetPassword')}" class="tab-link">비밀번호 초기화</a> <a th:href="@{/account_recovery(tab='resetPassword')}" class="tab-link">비밀번호 초기화</a>
</div> </div>
@@ -22,13 +23,15 @@
<div id="alertContainer"></div> <div id="alertContainer"></div>
<!-- Account Recovery Form --> <!-- Account Recovery Form -->
<form id="accountForm" role="form" name="accountForm" th:action="@{/find_id}" method="post" class="account-recovery-form"> <form id="accountForm" role="form" name="accountForm" th:action="@{/find_id}" method="post"
class="account-recovery-form">
<input type="hidden" id="mobileNumber" name="mobileNumber" th:value="${mobileNumber}"> <input type="hidden" id="mobileNumber" name="mobileNumber" th:value="${mobileNumber}">
<!-- Name Field --> <!-- Name Field -->
<div class="form-group"> <div class="form-group">
<label for="userName" class="form-label">성명<span class="required-badge">필수</span></label> <label for="userName" class="form-label">성명<span class="required-badge">필수</span></label>
<input type="text" id="userName" name="userName" th:value="${userName}" class="form-input" placeholder="성명" required> <input type="text" id="userName" name="userName" th:value="${userName}" class="form-input"
placeholder="성명" required>
</div> </div>
<!-- Phone Number Fields --> <!-- Phone Number Fields -->
@@ -45,27 +48,13 @@
<option value="018">018</option> <option value="018">018</option>
</select> </select>
<span class="separator">-</span> <span class="separator">-</span>
<input type="tel" <input type="tel" id="phoneMiddle" name="phoneMiddle" maxlength="4" class="form-input phone-number"
id="phoneMiddle" placeholder="1234" pattern="[0-9]*" inputmode="numeric" required>
name="phoneMiddle"
maxlength="4"
class="form-input phone-number"
placeholder="1234"
pattern="[0-9]*"
inputmode="numeric"
required>
<span class="separator">-</span> <span class="separator">-</span>
<input type="tel" <input type="tel" id="phoneLast" name="phoneLast" maxlength="4" class="form-input phone-number"
id="phoneLast" placeholder="1234" pattern="[0-9]*" inputmode="numeric" required>
name="phoneLast"
maxlength="4"
class="form-input phone-number"
placeholder="1234"
pattern="[0-9]*"
inputmode="numeric"
required>
</div> </div>
<button type="button" class="btn org-btn-check btn_auth" id="requestAuthButton"> <button type="button" class="org-btn-check btn_auth" id="requestAuthButton">
인증번호 받기 인증번호 받기
</button> </button>
</div> </div>
@@ -74,16 +63,9 @@
<!-- Auth Number Input --> <!-- Auth Number Input -->
<div class="form-group auth-number-group" id="authNumberGroup" style="display: none;"> <div class="form-group auth-number-group" id="authNumberGroup" style="display: none;">
<label for="authNumber" class="form-label">인증번호 입력<span class="required-badge">필수</span></label> <label for="authNumber" class="form-label">인증번호 입력<span class="required-badge">필수</span></label>
<div class="auth-input-group"> <div class="auth-input-group mg-y">
<input type="text" <input type="text" id="authNumber" name="authNumber" maxlength="6" class="form-input auth-input"
id="authNumber" placeholder="인증번호 6자리" pattern="[0-9]*" inputmode="numeric" required>
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> <span class="auth-timer" id="authTimer">03:00</span>
</div> </div>
<button type="button" class="auth-verify-button" id="verifyAuthButton"> <button type="button" class="auth-verify-button" id="verifyAuthButton">
@@ -105,12 +87,12 @@
</div> </div>
</div> </div>
</div> </div>
</th:block> </th:block>
</body> </body>
<th:block layout:fragment="contentScript"> <th:block layout:fragment="contentScript">
<script th:inline="javascript"> <script th:inline="javascript">
$(document).ready(function() { $(document).ready(function () {
const errorMsg = [[${error}]]; const errorMsg = [[${ error }]];
if (errorMsg) { if (errorMsg) {
customPopups.showAlert(errorMsg, 'error'); customPopups.showAlert(errorMsg, 'error');
} }
@@ -167,7 +149,7 @@
} }
// 인증번호 요청 버튼 // 인증번호 요청 버튼
$('#requestAuthButton').on('click', function() { $('#requestAuthButton').on('click', function () {
const mobileNumber = combineMobileNumber(); const mobileNumber = combineMobileNumber();
if (!mobileNumber) { if (!mobileNumber) {
@@ -185,7 +167,7 @@
mobileNumber: mobileNumber, mobileNumber: mobileNumber,
_csrf: $('input[name="_csrf"]').val() _csrf: $('input[name="_csrf"]').val()
}, },
success: function(response) { success: function (response) {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
if (response.valid) { if (response.valid) {
@@ -210,7 +192,7 @@
customPopups.showAlert(response.message || '인증번호 발송에 실패했습니다.', 'error'); customPopups.showAlert(response.message || '인증번호 발송에 실패했습니다.', 'error');
} }
}, },
error: function() { error: function () {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error'); customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
} }
@@ -218,7 +200,7 @@
}); });
// 인증번호 확인 버튼 // 인증번호 확인 버튼
$('#verifyAuthButton').on('click', function() { $('#verifyAuthButton').on('click', function () {
if (!isAuthNumberRequested) { if (!isAuthNumberRequested) {
customPopups.showAlert('휴대폰 번호 인증을 먼저 진행해주세요.', 'error'); customPopups.showAlert('휴대폰 번호 인증을 먼저 진행해주세요.', 'error');
return; return;
@@ -242,7 +224,7 @@
authNumber: authNumber, authNumber: authNumber,
_csrf: $('input[name="_csrf"]').val() _csrf: $('input[name="_csrf"]').val()
}, },
success: function(response) { success: function (response) {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
if (response.valid) { if (response.valid) {
@@ -260,7 +242,7 @@
customPopups.showAlert(response.message || '인증번호가 일치하지 않습니다.', 'error'); customPopups.showAlert(response.message || '인증번호가 일치하지 않습니다.', 'error');
} }
}, },
error: function() { error: function () {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error'); customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
} }
@@ -268,7 +250,7 @@
}); });
// 폼 제출 // 폼 제출
$('#accountForm').on('submit', function(e) { $('#accountForm').on('submit', function (e) {
e.preventDefault(); e.preventDefault();
const userName = $('#userName').val().trim(); const userName = $('#userName').val().trim();
@@ -298,7 +280,7 @@
}); });
// 취소 버튼 // 취소 버튼
$('#cancelButton').on('click', function() { $('#cancelButton').on('click', function () {
window.location.href = '/login'; window.location.href = '/login';
}); });
@@ -330,7 +312,7 @@
} }
// 기존 휴대폰 번호 복원 // 기존 휴대폰 번호 복원
$(document).ready(function() { $(document).ready(function () {
const savedMobileNumber = $('#mobileNumber').val(); const savedMobileNumber = $('#mobileNumber').val();
if (savedMobileNumber) { if (savedMobileNumber) {
const parts = savedMobileNumber.split('-'); const parts = savedMobileNumber.split('-');
@@ -343,4 +325,5 @@
}); });
</script> </script>
</th:block> </th:block>
</html> </html>
@@ -1,14 +1,15 @@
<!doctype html> <!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" <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/djbank_title_layout}"> xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
<body> <body>
<section layout:fragment="title"> <section layout:fragment="title">
<div class="page-title-banner"> <div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image"> <img th:src="@{/img/img_title_bg.png}" class="title-image">
<h1>비밀번호 초기화</h1> <h1>비밀번호 초기화</h1>
</div> </div>
</section> </section>
<th:block layout:fragment="contentFragment"> <th:block layout:fragment="contentFragment">
<div class="account-recovery-page"> <div class="account-recovery-page">
<div class="account-recovery-container"> <div class="account-recovery-container">
<div class="account-recovery-card"> <div class="account-recovery-card">
@@ -22,32 +23,23 @@
<div id="alertContainer"></div> <div id="alertContainer"></div>
<!-- Account Recovery Form --> <!-- Account Recovery Form -->
<form id="accountForm" role="form" name="accountForm" th:action="@{/reset_password}" method="post" class="account-recovery-form"> <form id="accountForm" role="form" name="accountForm" th:action="@{/reset_password}" method="post"
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> 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}"> <input type="hidden" id="mobileNumber" name="mobileNumber" th:value="${mobileNumber}">
<!-- Name Field --> <!-- Name Field -->
<div class="form-group"> <div class="form-group">
<label for="userName" class="form-label">성명<span class="required-badge">필수</span></label> <label for="userName" class="form-label">성명<span class="required-badge">필수</span></label>
<input type="text" <input type="text" id="userName" name="userName" th:value="${userName}" class="form-input"
id="userName" placeholder="성명" required>
name="userName"
th:value="${userName}"
class="form-input"
placeholder="성명"
required>
</div> </div>
<!-- Email ID Field --> <!-- Email ID Field -->
<div class="form-group"> <div class="form-group">
<label for="loginId" class="form-label">이메일 아이디<span class="required-badge">필수</span></label> <label for="loginId" class="form-label">이메일 아이디<span class="required-badge">필수</span></label>
<input type="email" <input type="email" id="loginId" name="loginId" th:value="${loginId}" class="form-input"
id="loginId" placeholder="이메일 아이디" required>
name="loginId"
th:value="${loginId}"
class="form-input"
placeholder="이메일 아이디"
required>
</div> </div>
<!-- Phone Number Fields --> <!-- Phone Number Fields -->
@@ -64,27 +56,13 @@
<option value="018">018</option> <option value="018">018</option>
</select> </select>
<span class="separator">-</span> <span class="separator">-</span>
<input type="tel" <input type="tel" id="phoneMiddle" name="phoneMiddle" maxlength="4" class="form-input phone-number"
id="phoneMiddle" placeholder="1234" pattern="[0-9]*" inputmode="numeric" required>
name="phoneMiddle"
maxlength="4"
class="form-input phone-number"
placeholder="1234"
pattern="[0-9]*"
inputmode="numeric"
required>
<span class="separator">-</span> <span class="separator">-</span>
<input type="tel" <input type="tel" id="phoneLast" name="phoneLast" maxlength="4" class="form-input phone-number"
id="phoneLast" placeholder="1234" pattern="[0-9]*" inputmode="numeric" required>
name="phoneLast"
maxlength="4"
class="form-input phone-number"
placeholder="1234"
pattern="[0-9]*"
inputmode="numeric"
required>
</div> </div>
<button type="button" class="btn org-btn-check btn_auth" id="requestAuthButton"> <button type="button" class="org-btn-check btn_auth" id="requestAuthButton">
인증번호 받기 인증번호 받기
</button> </button>
</div> </div>
@@ -93,16 +71,9 @@
<!-- Auth Number Input --> <!-- Auth Number Input -->
<div class="form-group auth-number-group" id="authNumberGroup" style="display: none;"> <div class="form-group auth-number-group" id="authNumberGroup" style="display: none;">
<label for="authNumber" class="form-label">인증번호 입력<span class="required-badge">필수</span></label> <label for="authNumber" class="form-label">인증번호 입력<span class="required-badge">필수</span></label>
<div class="auth-input-group"> <div class="auth-input-group mg-y">
<input type="text" <input type="text" id="authNumber" name="authNumber" maxlength="6" class="form-input auth-input"
id="authNumber" placeholder="인증번호 6자리" pattern="[0-9]*" inputmode="numeric" required>
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> <span class="auth-timer" id="authTimer">03:00</span>
</div> </div>
<button type="button" class="auth-verify-button" id="verifyAuthButton"> <button type="button" class="auth-verify-button" id="verifyAuthButton">
@@ -124,17 +95,17 @@
</div> </div>
</div> </div>
</div> </div>
</th:block> </th:block>
</body> </body>
<th:block layout:fragment="contentScript"> <th:block layout:fragment="contentScript">
<script th:inline="javascript"> <script th:inline="javascript">
$(document).ready(function() { $(document).ready(function () {
const errorMsg = [[${error}]]; const errorMsg = [[${ error }]];
if (errorMsg) { if (errorMsg) {
customPopups.showAlert(errorMsg, 'error'); customPopups.showAlert(errorMsg, 'error');
} }
const successMsg = [[${success}]]; const successMsg = [[${ success }]];
if (successMsg) { if (successMsg) {
customPopups.showAlert(successMsg, 'success'); customPopups.showAlert(successMsg, 'success');
} }
@@ -191,7 +162,7 @@
} }
// 인증번호 요청 버튼 // 인증번호 요청 버튼
$('#requestAuthButton').on('click', function() { $('#requestAuthButton').on('click', function () {
const userName = $('#userName').val().trim(); const userName = $('#userName').val().trim();
if (!userName) { if (!userName) {
customPopups.showAlert('성명을 입력해주세요.', 'error'); customPopups.showAlert('성명을 입력해주세요.', 'error');
@@ -226,7 +197,7 @@
mobileNumber: mobileNumber, mobileNumber: mobileNumber,
_csrf: $('input[name="_csrf"]').val() _csrf: $('input[name="_csrf"]').val()
}, },
success: function(response) { success: function (response) {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
if (response.valid) { if (response.valid) {
@@ -251,7 +222,7 @@
customPopups.showAlert(response.message || '인증번호 발송에 실패했습니다.', 'error'); customPopups.showAlert(response.message || '인증번호 발송에 실패했습니다.', 'error');
} }
}, },
error: function() { error: function () {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error'); customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
} }
@@ -259,7 +230,7 @@
}); });
// 인증번호 확인 버튼 // 인증번호 확인 버튼
$('#verifyAuthButton').on('click', function() { $('#verifyAuthButton').on('click', function () {
if (!isAuthNumberRequested) { if (!isAuthNumberRequested) {
customPopups.showAlert('휴대폰 번호 인증을 먼저 진행해주세요.', 'error'); customPopups.showAlert('휴대폰 번호 인증을 먼저 진행해주세요.', 'error');
return; return;
@@ -283,7 +254,7 @@
authNumber: authNumber, authNumber: authNumber,
_csrf: $('input[name="_csrf"]').val() _csrf: $('input[name="_csrf"]').val()
}, },
success: function(response) { success: function (response) {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
if (response.valid) { if (response.valid) {
@@ -301,7 +272,7 @@
customPopups.showAlert(response.message || '인증번호가 일치하지 않습니다.', 'error'); customPopups.showAlert(response.message || '인증번호가 일치하지 않습니다.', 'error');
} }
}, },
error: function() { error: function () {
$('#loadingOverlay').fadeOut(200); $('#loadingOverlay').fadeOut(200);
customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error'); customPopups.showAlert('처리 중 오류가 발생했습니다. 다시 시도해주세요.', 'error');
} }
@@ -309,7 +280,7 @@
}); });
// 폼 제출 // 폼 제출
$('#accountForm').on('submit', function(e) { $('#accountForm').on('submit', function (e) {
e.preventDefault(); e.preventDefault();
const userName = $('#userName').val().trim(); const userName = $('#userName').val().trim();
@@ -351,7 +322,7 @@
}); });
// 취소 버튼 // 취소 버튼
$('#cancelButton').on('click', function() { $('#cancelButton').on('click', function () {
window.location.href = '/login'; window.location.href = '/login';
}); });
@@ -383,7 +354,7 @@
} }
// 기존 휴대폰 번호 복원 // 기존 휴대폰 번호 복원
$(document).ready(function() { $(document).ready(function () {
const savedMobileNumber = $('#mobileNumber').val(); const savedMobileNumber = $('#mobileNumber').val();
if (savedMobileNumber) { if (savedMobileNumber) {
const parts = savedMobileNumber.split('-'); const parts = savedMobileNumber.split('-');
@@ -396,4 +367,5 @@
}); });
</script> </script>
</th:block> </th:block>
</html> </html>
@@ -9,7 +9,7 @@
</div> </div>
<div class="form-field-wrapper"> <div class="form-field-wrapper">
<input type="text" th:value="${loginId}" name="loginId" class="form-input input-readonly" <input type="text" th:value="${loginId}" name="loginId" class="form-input input-readonly"
placeholder="이메일" disabled="disabled"> placeholder="이메일" disabled="disabled" style="background: #ededed !important;">
<input type="hidden" th:value="${loginId}" name="loginId"> <input type="hidden" th:value="${loginId}" name="loginId">
</div> </div>
</div> </div>
@@ -19,8 +19,7 @@
<span class="form-label-text">성명</span> <span class="required-badge">필수</span> <span class="form-label-text">성명</span> <span class="required-badge">필수</span>
</div> </div>
<div class="form-field-wrapper"> <div class="form-field-wrapper">
<input type="text" th:value="${userName}" id="userName" name="userName" class="form-input" <input type="text" th:value="${userName}" id="userName" name="userName" class="form-input">
placeholder="성명">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
@@ -36,13 +35,13 @@
mobileLast=${hasHyphen ? (parts != null and #arrays.length(parts) > 2 ? parts[2] : '') : (len == 11 ? #strings.substring(mobileNumber, 7, 11) : (len == 10 ? #strings.substring(mobileNumber, 6, 10) : ''))}"> mobileLast=${hasHyphen ? (parts != null and #arrays.length(parts) > 2 ? parts[2] : '') : (len == 11 ? #strings.substring(mobileNumber, 7, 11) : (len == 10 ? #strings.substring(mobileNumber, 6, 10) : ''))}">
<div class="compound-input"> <div class="compound-input">
<input type="text" th:value="${mobilePrefix}" name="mobilePrefix" class="form-input input-readonly" <input type="text" th:value="${mobilePrefix}" name="mobilePrefix" class="form-input input-readonly"
maxlength="3" disabled="disabled"> maxlength="3" disabled="disabled" style="background: #ededed !important;">
<span class="separator">-</span> <span class="separator">-</span>
<input type="text" th:value="${mobileMiddle}" name="mobileMiddle" class="form-input input-readonly" <input type="text" th:value="${mobileMiddle}" name="mobileMiddle" class="form-input input-readonly"
maxlength="4" disabled="disabled"> maxlength="4" disabled="disabled" style="background: #ededed !important;">
<span class="separator">-</span> <span class="separator">-</span>
<input type="text" th:value="${mobileLast}" name="mobileLast" class="form-input input-readonly" <input type="text" th:value="${mobileLast}" name="mobileLast" class="form-input input-readonly"
maxlength="4" disabled="disabled"> maxlength="4" disabled="disabled" style="background: #ededed !important;">
</div> </div>
<button type="button" class="btn-input-action btn-change change_mobile_phone" <button type="button" class="btn-input-action btn-change change_mobile_phone"
id="changePhoneBtn">변경</button> id="changePhoneBtn">변경</button>
@@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:th="http://www.thymeleaf.org" xmlns:th="http://www.thymeleaf.org"
layout:decorate="~{layout/djbank_base_layout}"> layout:decorate="~{layout/djbank_title_layout}">
<body> <body>
<section layout:fragment="title"> <section layout:fragment="title">
<div class="page-title-banner"> <div class="page-title-banner">
@@ -10,19 +10,32 @@
</div> </div>
</section> </section>
<section layout:fragment="contentFragment" class="content"> <section layout:fragment="contentFragment" class="content">
<div class="org-register-page corporate-register">
<div class="org-register-container"> <div class="org-register-container">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<input type="hidden" name="registrationType" th:value="${registrationType}"/> <input type="hidden" name="registrationType" th:value="${registrationType}"/>
<div class="register-card-wrapper">
<!-- Info Notice -->
<div class="org-info-notice">
<div class="notice-icon-wrapper">
<svg class="notice-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10" />
<line x1="12" y1="8" x2="12" y2="12" />
<line x1="12" y1="16" x2="12.01" y2="16" />
</svg>
</div>
<p class="notice-text">법인회원 전환 신청 완료 후 서비스 또는 API 이용을 하실 수 있습니다.</p>
</div>
<!-- 약관동의 섹션 --> <!-- 약관동의 섹션 -->
<th:block <th:block th:replace="~{apps/register/userAgreementContent :: agreementContent(${termsOfUse}, ${privacyCollect})}"></th:block>
th:replace="apps/register/userAgreementContent :: agreementContent(${termsOfUse}, ${privacyCollect})"></th:block>
<!-- 법인 기본 정보 폼 --> <!-- 법인 기본 정보 폼 -->
<form name="portalOrg" id="businessTransferForm" method="post" th:action="@{/mypage/org-transfer}" <form name="portalOrg" id="businessTransferForm" method="post" th:action="@{/mypage/org-transfer}"
th:object="${portalOrg}" enctype="multipart/form-data"> th:object="${portalOrg}" enctype="multipart/form-data">
<div class="org-section-header"> <div class="org-section-header org-section-header--agreement">
<h3>법인 기본 정보</h3> <h3>법인 기본 정보</h3>
<span class="required-badge">필수 입력</span> <span class="required-badge">필수 입력</span>
</div> </div>
@@ -30,16 +43,20 @@
<th:block th:replace="~{apps/register/components/orgBasicInfoForm :: orgInfoForm}"></th:block> <th:block th:replace="~{apps/register/components/orgBasicInfoForm :: orgInfoForm}"></th:block>
<!-- 법인 관리자 정보 --> <!-- 법인 관리자 정보 -->
<div class="org-section-header"> <div class="org-section-header org-section-header--agreement" style="margin-top: 48px;">
<h3>법인 관리자 정보</h3> <h3>법인 관리자 정보</h3>
<span class="required-badge">필수 입력</span> <span class="required-badge">필수 입력</span>
</div> </div>
<div class="org-info-notice"> <div class="org-info-notice">
<ul> <div class="notice-icon-wrapper">
<li>법인 관리자는 API 신청 및 개발자 초대 등 모든 권한을 보유합니다.</li> <svg class="notice-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<li>법인회원 전환은 반드시 법인이메일 주소로 입력하시기 바랍니다. 개인이메일로 전환 신청시, 법인 승인이 거절 될 수 있습니다</li> <circle cx="12" cy="12" r="10" />
</ul> <line x1="12" y1="8" x2="12" y2="12" />
<line x1="12" y1="16" x2="12.01" y2="16" />
</svg>
</div>
<p class="notice-text">법인 관리자는 API 신청 및 개발자 초대 등 모든 권한을 보유합니다. 법인회원 전환은 반드시 법인이메일 주소로 입력하시기 바랍니다.</p>
</div> </div>
<div class="org-form-container"> <div class="org-form-container">
@@ -63,6 +80,8 @@
</div> </div>
</form> </form>
</div> </div>
</div>
</div>
</section> </section>
<th:block layout:fragment="contentScript"> <th:block layout:fragment="contentScript">
<script th:if="${error}" th:inline="javascript"> <script th:if="${error}" th:inline="javascript">
@@ -1,74 +1,94 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
layout:decorate="~{layout/djbank_title_layout}">
<body> <body>
<section layout:fragment="title"> <section layout:fragment="title">
<div class="page-title-banner"> <div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image"> <img th:src="@{/img/img_title_bg.png}" class="title-image">
<h1>내 정보 관리</h1> <h1>내 정보 관리</h1>
</div> </div>
</section> </section>
<section layout:fragment="contentFragment"> <section layout:fragment="contentFragment">
<div class="org-register-container"> <div class="service-main container" style="padding-top: 70px; padding-bottom:100px;">
<th:block th:replace="~{fragment/djbank/service_sidebar :: sidebar('profile')}"></th:block>
<div class="app-management-content">
<div class="corp-manager-wrapper"> <div class="corp-manager-wrapper">
<!-- 초대 알림 배너 --> <!-- 초대 알림 배너 -->
<div th:if="${hasPendingInvitation}" class="invitation_alert_banner" style="background-color: #f0f8ff; border: 1px solid #2196F3; border-radius: 4px; padding: 15px 20px; margin: 20px 0;"> <div th:if="${hasPendingInvitation}" class="invitation_alert_banner"
style="background-color: #f0f8ff; border: 1px solid #2196F3; border-radius: 4px; padding: 15px 20px; margin: 20px 0;">
<div style="display: flex; align-items: center; justify-content: space-between;"> <div style="display: flex; align-items: center; justify-content: space-between;">
<div> <div>
<strong style="color: #1976D2;">법인 회원 초대가 대기 중입니다</strong> <strong style="color: #1976D2;">법인 회원 초대가 대기 중입니다</strong>
<p style="margin: 5px 0 0 0; color: #666;">기관에서 귀하를 법인 회원으로 초대했습니다. 초대를 수락하면 해당 기관의 법인 회원으로 전환됩니다.</p> <p style="margin: 5px 0 0 0; color: #666;">기관에서 귀하를 법인 회원으로 초대했습니다. 초대를 수락하면 해당 기관의 법인
회원으로 전환됩니다.</p>
</div> </div>
<div> <div>
<a th:href="@{/signup/decision(invitation=${invitationToken})}" class="common_btn_type_1 blue" style="white-space: nowrap;"> <a th:href="@{/signup/decision(invitation=${invitationToken})}"
class="common_btn_type_1 blue" style="white-space: nowrap;">
<span>초대 확인</span> <span>초대 확인</span>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<h2 class="page-outer-title">정보 관리</h2>
<div class="common-title-bar">
<h2 class="common-title">기본 정보</h2>
</div>
<div class="register-form-container">
<form id="updateForm" method="post" th:action="@{/mypage/update}" th:object="${user}"> <form id="updateForm" method="post" th:action="@{/mypage/update}" th:object="${user}">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<div class="register-form-container">
<!-- Section Title -->
<div class="inner-section-title">
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#000"
stroke-width="2">
<rect x="3" y="3" width="7" height="7"></rect>
<rect x="14" y="3" width="7" height="7"></rect>
<rect x="14" y="14" width="7" height="7"></rect>
<rect x="3" y="14" width="7" height="7"></rect>
</svg>
<h3>기본 정보</h3>
</div>
<div class="register-form"> <div class="register-form">
<th:block th:replace="~{apps/mypage/components/commonUserInfo :: commonUserInfo}"></th:block> <th:block th:replace="~{apps/mypage/components/commonUserInfo :: commonUserInfo}">
</th:block>
</div> </div>
<!-- Corporate Transfer Button --> <!-- Corporate Transfer Button -->
<div class="corporate-transfer-section"> <div class="corporate-transfer-section" style="margin-top: 24px;">
<button type="button" class="btn btn-secondary btn_business btn-block"> <button type="button" class="btn btn_business"
style="background: #FFFFFF; border: 1.5px solid #2a69de; color: #2a69de; font-weight: 700; border-radius: 12px; padding: 12px 24px; font-size: 15px; cursor: pointer; transition: all 0.2s ease; display: inline-flex; align-items: center; justify-content: center; width: 100%; box-shadow: none;">
법인회원 전환 법인회원 전환
</button> </button>
</div> </div>
</form>
</div> </div>
<input type="hidden" name="finalMobileNumber"/> </form>
<input type="hidden" name="finalMobileNumber" />
<!-- Action Buttons --> <!-- Action Buttons -->
<div class="form-actions form-actions--with-withdrawal"> <div class="form-actions">
<a class="withdrawal-link"><img th:src="@{/img/btn_withdrawal.png}" alt="회원탈퇴">회원탈퇴</a> <a class="withdrawal-link btn-withdrawal">회원탈퇴</a>
<div class="form-actions-buttons"> <div class="right-buttons">
<button type="button" class="btn btn-submit btn-secondary" th:onclick="|location.href='@{/}'|">취소</button> <button type="button" class="btn-cancel" th:onclick="|location.href='@{/}'|">취소</button>
<button type="button" class="btn btn-submit btn-primary submit-btn">수정</button> <button type="button" class="btn-apply btn-primary submit-btn">수정</button>
</div>
</div>
</div> </div>
</div> </div>
</section> </div>
<th:block layout:fragment="contentScript"> </div>
</div>
</section>
<th:block layout:fragment="contentScript">
<script th:if="${error}" th:inline="javascript"> <script th:if="${error}" th:inline="javascript">
$(document).ready(function () { $(document).ready(function () {
customPopups.showAlert([[${error}]]); customPopups.showAlert([[${ error }]]);
}); });
</script> </script>
<script th:inline="javascript"> <script th:inline="javascript">
$(document).ready(function() { $(document).ready(function () {
// 기존 success 메시지 처리 // 기존 success 메시지 처리
var successMsg = [[${success}]]; var successMsg = [[${ success }]];
console.log("Success message:", successMsg); console.log("Success message:", successMsg);
if (successMsg) { if (successMsg) {
console.log("Showing alert"); console.log("Showing alert");
@@ -191,9 +211,10 @@
} }
}); });
</script> </script>
</th:block> </th:block>
<section layout:fragment="pagePopups"> <section layout:fragment="pagePopups">
<th:block th:replace="~{fragment/popup/withdrawalPopup :: withdrawalPopup}"></th:block> <th:block th:replace="~{fragment/popup/withdrawalPopup :: withdrawalPopup}"></th:block>
</section> </section>
</body> </body>
</html> </html>
@@ -1,76 +1,78 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
layout:decorate="~{layout/djbank_title_layout}">
<body> <body>
<section layout:fragment="title"> <section layout:fragment="title">
<div class="page-title-banner"> <div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image"> <img th:src="@{/img/img_title_bg.png}" class="title-image">
<h1>이메일 인증</h1> <h1>이메일 인증</h1>
</div> </div>
</section> </section>
<section layout:fragment="contentFragment"> <section layout:fragment="contentFragment">
<div class="org-register-container"> <div class="service-main">
<div class="app-management-content">
<div class="password-change-wrapper">
<h2 class="page-outer-title">이메일 인증</h2>
<div class="common-title-bar">
<h2 class="common-title">이메일 인증</h2>
</div>
<div class="register-form-container">
<form id="verificationEmailForm" role="form" name="verificationEmailForm" method="post"> <form id="verificationEmailForm" role="form" name="verificationEmailForm" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<input type="hidden" id="userId" name="userId" th:value="${userId}"> <input type="hidden" id="userId" name="userId" th:value="${userId}">
<div class="register-form"> <div class="register-form-container">
<!-- 이메일 주소 + 인증코드 받기 버튼 (한 줄) --> <!-- 안내 Notice Box -->
<div class="form-row" style="margin-bottom: 0"> <div class="info-notice-box" style="margin-bottom: 24px;">
<div class="form-label-wrapper label-offset"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#4685ef" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 16v-4"></path>
<path d="M12 8h.01"></path>
</svg>
<p>본인 확인을 위해 이메일 인증을 진행해 주세요. 아래 이메일 주소로 인증코드가 발송됩니다.</p>
</div>
<!-- 이메일 주소 행 -->
<div class="form-row">
<div class="form-label-wrapper">
<span class="form-label-text">이메일 주소</span> <span class="form-label-text">이메일 주소</span>
</div> </div>
<div class="form-field-wrapper input-with-button"> <div class="form-field-wrapper input-with-button">
<input type="email" id="email" name="email" class="form-input input-readonly" <input type="email" id="email" name="email" class="form-input input-readonly" th:value="${email}"
th:value="${email}" readonly disabled="disabled"> readonly disabled="disabled" style="flex: 1;">
<button type="button" class="btn-input-action btn-auth btn_send_code">인증코드 받기</button> <button type="button" class="btn-input-action btn-auth btn_send_code">인증코드 받기</button>
</div> </div>
</div> </div>
<div class="form-row" style="margin-bottom: 0"> <!-- 인증번호 입력 행 (초기 숨김) -->
<div class="form-label-wrapper label-offset">
<span class="form-label-text">&nbsp;</span>
</div>
<div class="form-field-wrapper">
<p class="form-hint" style="margin-top: 0;">위 이메일 주소로 인증코드가 발송됩니다.</p>
</div>
</div>
<!-- 인증번호 입력 -->
<div class="form-row" id="authCodeContainer" style="display: none;"> <div class="form-row" id="authCodeContainer" style="display: none;">
<div class="form-label-wrapper label-offset"> <div class="form-label-wrapper">
<span class="form-label-text">인증코드 입력</span> <span class="required-badge">필수</span> <span class="form-label-text">인증코드 입력</span>
</div> </div>
<div class="form-field-wrapper input-with-button"> <div class="form-field-wrapper input-with-button">
<div class="auth-input-group"> <div class="auth-input-group" style="flex: 1; position: relative;">
<input type="text" id="authCode" name="authCode" maxlength="6" pattern="[0-9]*" <input type="text" id="authCode" name="authCode" maxlength="6" pattern="[0-9]*" inputmode="numeric"
inputmode="numeric" class="form-input" class="form-input" placeholder="이메일로 받은 인증코드 6자리" style="width: 100%; padding-right: 70px;">
placeholder="이메일로 받은 인증코드 6자리"> <span class="auth-timer" id="certify_time"
<span class="auth-timer" id="certify_time">05:00</span> style="position: absolute; right: 16px; top: 50%; transform: translateY(-50%); font-weight: 500; font-size: 13px;">05:00</span>
</div> </div>
<button type="button" class="btn-input-action btn-auth btn_verify_code">인증코드 확인</button> <button type="button" class="btn-input-action btn-auth btn_verify_code">인증코드 확인</button>
</div> </div>
</div> </div>
</div> </div>
</form>
</div>
<!-- Action Buttons --> <!-- Action Buttons -->
<div class="form-actions"> <div class="form-actions" style="justify-content: flex-end; margin-top: 24px;">
<button type="button" class="btn-submit btn-secondary">취소</button> <div class="right-buttons">
<button type="button" class="btn-cancel btn_cancel">취소</button>
</div> </div>
</div> </div>
</section> </form>
</div>
</div>
</div>
</section>
</body> </body>
<th:block layout:fragment="contentScript"> <th:block layout:fragment="contentScript">
<script th:inline="javascript"> <script th:inline="javascript">
$(document).ready(function() { $(document).ready(function () {
let timerInterval; let timerInterval;
let resendTimerInterval; let resendTimerInterval;
let isVerified = false; let isVerified = false;
@@ -83,10 +85,10 @@
const resendLimitSeconds = /*[[${@environment.getProperty('portal.auth.resend_limit_seconds', '60')}]]*/ 60; const resendLimitSeconds = /*[[${@environment.getProperty('portal.auth.resend_limit_seconds', '60')}]]*/ 60;
// 취소 버튼 클릭 시 메인 페이지로 이동 // 취소 버튼 클릭 시 메인 페이지로 이동
$('.btn_cancel').on('click', function() { $('.btn_cancel').on('click', function () {
customPopups.showConfirm( customPopups.showConfirm(
'이메일 인증을 취소하고 메인 페이지로 이동하시겠습니까?', '이메일 인증을 취소하고 메인 페이지로 이동하시겠습니까?',
function() { function () {
location.href = '/'; location.href = '/';
} }
); );
@@ -170,7 +172,7 @@
} }
// 인증코드 받기 버튼 클릭 // 인증코드 받기 버튼 클릭
$('.btn_send_code').on('click', function(e) { $('.btn_send_code').on('click', function (e) {
e.preventDefault(); e.preventDefault();
const email = $('#email').val(); const email = $('#email').val();
@@ -186,7 +188,7 @@
headers: { headers: {
[csrfHeaderName]: csrfToken [csrfHeaderName]: csrfToken
}, },
success: function(response) { success: function (response) {
// 테스트 환경 인증번호 표시 // 테스트 환경 인증번호 표시
if (response.authNumber) { if (response.authNumber) {
displayTestAuthNotice(response.authNumber); displayTestAuthNotice(response.authNumber);
@@ -199,7 +201,7 @@
startTimer(300); // 5분 타이머 startTimer(300); // 5분 타이머
startResendTimer(); // 재발송 타이머 시작 (1분) startResendTimer(); // 재발송 타이머 시작 (1분)
}, },
error: function(xhr) { error: function (xhr) {
const errorMsg = xhr.responseJSON?.error || '인증코드 발송에 실패했습니다.'; const errorMsg = xhr.responseJSON?.error || '인증코드 발송에 실패했습니다.';
customPopups.showAlert(errorMsg); customPopups.showAlert(errorMsg);
$button.prop('disabled', false).text('인증코드 받기'); $button.prop('disabled', false).text('인증코드 받기');
@@ -208,7 +210,7 @@
}); });
// 인증코드 확인 버튼 클릭 // 인증코드 확인 버튼 클릭
$('.btn_verify_code').on('click', function(e) { $('.btn_verify_code').on('click', function (e) {
e.preventDefault(); e.preventDefault();
const authCode = $('#authCode').val().trim(); const authCode = $('#authCode').val().trim();
@@ -235,7 +237,7 @@
headers: { headers: {
[csrfHeaderName]: csrfToken [csrfHeaderName]: csrfToken
}, },
success: function(response) { success: function (response) {
clearInterval(timerInterval); clearInterval(timerInterval);
clearInterval(resendTimerInterval); clearInterval(resendTimerInterval);
isVerified = true; isVerified = true;
@@ -249,11 +251,11 @@
customPopups.showAlert('이메일 인증이 완료되었습니다!'); customPopups.showAlert('이메일 인증이 완료되었습니다!');
// 알림 확인 후 메인 페이지로 이동 // 알림 확인 후 메인 페이지로 이동
setTimeout(function() { setTimeout(function () {
location.href = '/'; location.href = '/';
}, 2000); }, 2000);
}, },
error: function(xhr) { error: function (xhr) {
const errorMsg = xhr.responseJSON?.error || '인증코드가 일치하지 않습니다.'; const errorMsg = xhr.responseJSON?.error || '인증코드가 일치하지 않습니다.';
customPopups.showAlert(errorMsg); customPopups.showAlert(errorMsg);
} }
@@ -261,11 +263,12 @@
}); });
// 인증코드 입력 필드 숫자만 허용 // 인증코드 입력 필드 숫자만 허용
$('#authCode').on('input', function() { $('#authCode').on('input', function () {
$(this).val($(this).val().replace(/[^0-9]/g, '')); $(this).val($(this).val().replace(/[^0-9]/g, ''));
}); });
}); });
</script> </script>
</th:block> </th:block>
</html> </html>
@@ -1,79 +1,78 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/djbank_title_layout}"> layout:decorate="~{layout/djbank_title_layout}">
<body> <body>
<section layout:fragment="title"> <section layout:fragment="title">
<div class="page-title-banner"> <div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image"> <img th:src="@{/img/img_title_bg.png}" class="title-image">
<h1>회원가입</h1> <h1>회원가입</h1>
</div> </div>
</section> </section>
<section layout:fragment="contentFragment"> <section layout:fragment="contentFragment">
<div class="org-register-container"> <div class="service-main">
<div class="app-management-content">
<div class="password-change-wrapper">
<h2 class="page-outer-title">이메일 인증</h2>
<div class="common-title-bar"> <form id="signupVerificationEmailForm" role="form" name="signupVerificationEmailForm" method="post">
<h2 class="common-title">이메일 인증</h2> <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
</div>
<div class="register-form-container"> <div class="register-form-container">
<p class="form-hint" style="margin-bottom: 16px;"> <!-- 안내 Notice Box -->
회원가입을 완료하려면 가입하신 이메일 주소로 인증을 진행해 주세요. <div class="info-notice-box" style="margin-bottom: 24px;">
</p> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#4685ef" stroke-width="2">
<form id="signupVerificationEmailForm" role="form" name="signupVerificationEmailForm" method="post"> <circle cx="12" cy="12" r="10"></circle>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> <path d="M12 16v-4"></path>
<path d="M12 8h.01"></path>
</svg>
<p>회원가입을 완료하려면 가입하신 이메일 주소로 인증을 진행해 주세요.</p>
</div>
<div class="register-form"> <!-- 이메일 주소 행 -->
<!-- 이메일 주소 + 인증코드 받기 버튼 (한 줄) --> <div class="form-row">
<div class="form-row" style="margin-bottom: 0"> <div class="form-label-wrapper">
<div class="form-label-wrapper label-offset">
<span class="form-label-text">이메일 주소</span> <span class="form-label-text">이메일 주소</span>
</div> </div>
<div class="form-field-wrapper input-with-button"> <div class="form-field-wrapper input-with-button">
<input type="email" id="email" name="email" class="form-input input-readonly" <input type="email" id="email" name="email" class="form-input input-readonly" th:value="${email}"
th:value="${email}" readonly disabled="disabled"> readonly disabled="disabled" style="flex: 1;">
<button type="button" class="btn-input-action btn-auth btn_send_code">인증코드 받기</button> <button type="button" class="btn-input-action btn-auth btn_send_code">인증코드 받기</button>
</div> </div>
</div> </div>
<div class="form-row" style="margin-bottom: 0"> <!-- 인증번호 입력 행 (초기 숨김) -->
<div class="form-label-wrapper label-offset">
<span class="form-label-text">&nbsp;</span>
</div>
<div class="form-field-wrapper">
<p class="form-hint" style="margin-top: 0;">위 이메일 주소로 인증코드가 발송됩니다.</p>
</div>
</div>
<!-- 인증번호 입력 -->
<div class="form-row" id="authCodeContainer" style="display: none;"> <div class="form-row" id="authCodeContainer" style="display: none;">
<div class="form-label-wrapper label-offset"> <div class="form-label-wrapper">
<span class="form-label-text">인증코드 입력</span> <span class="required-badge">필수</span> <span class="form-label-text">인증코드 입력</span>
</div> </div>
<div class="form-field-wrapper input-with-button"> <div class="form-field-wrapper input-with-button">
<div class="auth-input-group"> <div class="auth-input-group" style="flex: 1; position: relative;">
<input type="text" id="authCode" name="authCode" maxlength="6" pattern="[0-9]*" <input type="text" id="authCode" name="authCode" maxlength="6" pattern="[0-9]*" inputmode="numeric"
inputmode="numeric" class="form-input" class="form-input" placeholder="이메일로 받은 인증코드 6자리" style="width: 100%; padding-right: 70px;">
placeholder="이메일로 받은 인증코드 6자리"> <span class="auth-timer" id="certify_time"
<span class="auth-timer" id="certify_time">05:00</span> style="position: absolute; right: 16px; top: 50%; transform: translateY(-50%); font-weight: 500; font-size: 13px;">05:00</span>
</div> </div>
<button type="button" class="btn-input-action btn-auth btn_verify_code">인증코드 확인</button> <button type="button" class="btn-input-action btn-auth btn_verify_code">인증코드 확인</button>
</div> </div>
</div> </div>
</div> </div>
</form>
</div>
<!-- Action Buttons --> <!-- Action Buttons -->
<div class="form-actions"> <div class="form-actions" style="justify-content: flex-end; margin-top: 24px;">
<button type="button" class="btn-submit btn-secondary btn_cancel">나중에 인증</button> <div class="right-buttons">
<button type="button" class="btn-cancel btn_cancel">나중에 인증</button>
</div> </div>
</div> </div>
</section> </form>
</div>
</div>
</div>
</section>
</body> </body>
<th:block layout:fragment="contentScript"> <th:block layout:fragment="contentScript">
<script th:inline="javascript"> <script th:inline="javascript">
$(document).ready(function() { $(document).ready(function () {
let timerInterval; let timerInterval;
let resendTimerInterval; let resendTimerInterval;
let isVerified = false; let isVerified = false;
@@ -86,10 +85,10 @@
const resendLimitSeconds = /*[[${@environment.getProperty('portal.auth.resend_limit_seconds', '60')}]]*/ 60; const resendLimitSeconds = /*[[${@environment.getProperty('portal.auth.resend_limit_seconds', '60')}]]*/ 60;
// "나중에 인증" 클릭 시: 가입은 완료된 상태이므로 로그인 페이지로 이동 (로그인 후 인증 유도) // "나중에 인증" 클릭 시: 가입은 완료된 상태이므로 로그인 페이지로 이동 (로그인 후 인증 유도)
$('.btn_cancel').on('click', function() { $('.btn_cancel').on('click', function () {
customPopups.showConfirm( customPopups.showConfirm(
'이메일 인증을 나중에 하시겠습니까? 로그인 후에도 인증을 완료할 수 있습니다.', '이메일 인증을 나중에 하시겠습니까? 로그인 후에도 인증을 완료할 수 있습니다.',
function() { function () {
location.href = /*[[@{/login}]]*/ '/login'; location.href = /*[[@{/login}]]*/ '/login';
} }
); );
@@ -173,7 +172,7 @@
} }
// 인증코드 받기 버튼 클릭 // 인증코드 받기 버튼 클릭
$('.btn_send_code').on('click', function(e) { $('.btn_send_code').on('click', function (e) {
e.preventDefault(); e.preventDefault();
const $button = $(this); const $button = $(this);
@@ -187,7 +186,7 @@
headers: { headers: {
[csrfHeaderName]: csrfToken [csrfHeaderName]: csrfToken
}, },
success: function(response) { success: function (response) {
if (!response.valid) { if (!response.valid) {
customPopups.showAlert(response.message || '인증코드 발송에 실패했습니다.'); customPopups.showAlert(response.message || '인증코드 발송에 실패했습니다.');
$button.prop('disabled', false).text('인증코드 받기'); $button.prop('disabled', false).text('인증코드 받기');
@@ -206,7 +205,7 @@
startTimer(300); // 5분 타이머 startTimer(300); // 5분 타이머
startResendTimer(); // 재발송 타이머 시작 startResendTimer(); // 재발송 타이머 시작
}, },
error: function() { error: function () {
customPopups.showAlert('인증코드 발송에 실패했습니다.'); customPopups.showAlert('인증코드 발송에 실패했습니다.');
$button.prop('disabled', false).text('인증코드 받기'); $button.prop('disabled', false).text('인증코드 받기');
} }
@@ -214,7 +213,7 @@
}); });
// 인증코드 확인 버튼 클릭 // 인증코드 확인 버튼 클릭
$('.btn_verify_code').on('click', function(e) { $('.btn_verify_code').on('click', function (e) {
e.preventDefault(); e.preventDefault();
const authCode = $('#authCode').val().trim(); const authCode = $('#authCode').val().trim();
@@ -237,7 +236,7 @@
headers: { headers: {
[csrfHeaderName]: csrfToken [csrfHeaderName]: csrfToken
}, },
success: function(response) { success: function (response) {
if (!response.valid) { if (!response.valid) {
customPopups.showAlert(response.message || '인증코드가 일치하지 않습니다.'); customPopups.showAlert(response.message || '인증코드가 일치하지 않습니다.');
return; return;
@@ -256,22 +255,23 @@
customPopups.showAlert('이메일 인증이 완료되었습니다! 로그인 후 이용해 주세요.'); customPopups.showAlert('이메일 인증이 완료되었습니다! 로그인 후 이용해 주세요.');
// 알림 확인 후 로그인 페이지로 이동 // 알림 확인 후 로그인 페이지로 이동
setTimeout(function() { setTimeout(function () {
location.href = /*[[@{/login}]]*/ '/login'; location.href = /*[[@{/login}]]*/ '/login';
}, 2000); }, 2000);
}, },
error: function() { error: function () {
customPopups.showAlert('인증코드 확인에 실패했습니다.'); customPopups.showAlert('인증코드 확인에 실패했습니다.');
} }
}); });
}); });
// 인증코드 입력 필드 숫자만 허용 // 인증코드 입력 필드 숫자만 허용
$('#authCode').on('input', function() { $('#authCode').on('input', function () {
$(this).val($(this).val().replace(/[^0-9]/g, '')); $(this).val($(this).val().replace(/[^0-9]/g, ''));
}); });
}); });
</script> </script>
</th:block> </th:block>
</html> </html>
@@ -57,7 +57,8 @@
<a th:href="@{/myapikey}" <a th:href="@{/myapikey}"
th:classappend="${activeMenu == 'apiKey'} ? 'service-nav__item--active' : ''" th:classappend="${activeMenu == 'apiKey'} ? 'service-nav__item--active' : ''"
class="service-nav__item">앱 관리</a> class="service-nav__item"
sec:authorize="hasRole('ROLE_APP')">앱 관리</a>
<a th:href="@{/webhook}" <a th:href="@{/webhook}"
th:classappend="${activeMenu == 'webhook'} ? 'service-nav__item--active' : ''" th:classappend="${activeMenu == 'webhook'} ? 'service-nav__item--active' : ''"