fix : 부분적으로 수정
This commit is contained in:
@@ -73,7 +73,7 @@ public class AppServiceFacade {
|
||||
List<AppRequest> appRequests = appRequestRepository.findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(portalOrg, types,
|
||||
Arrays.asList(new ProcessingState(), new RequestedState()));
|
||||
|
||||
// 승인정보(approval) 없는 신청도 목록에 노출`한다. (사용자가 직접 삭제 가능)
|
||||
// 승인정보(approval) 없는 신청도 목록에 노출` 한다. (사용자가 직접 삭제 가능)
|
||||
appRequests.addAll(appRequestRepository .findAllByOrgAndTypeIsInAndApprovalIsNull(portalOrg, types));
|
||||
|
||||
return appRequests;
|
||||
|
||||
+646
-4795
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
@@ -285,20 +285,40 @@
|
||||
}
|
||||
|
||||
.pulsing {
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
transform-origin: 400px 110px;
|
||||
transform-box: fill-box;
|
||||
animation: pulseLine 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
|
||||
@keyframes pulseLine {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateX(75px) scale(1.1);
|
||||
/* 하나의 transform에 한 줄로 작성 */
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes pulse {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
transform: translate(0, 0) scale(1);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
opacity: 0.5;
|
||||
transform: translateX(75px) scale(1.1);
|
||||
/* 하나의 transform에 한 줄로 작성 */
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ textarea.djb-comment-input {
|
||||
font-family: inherit;
|
||||
outline: none;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
background-color: #fcfcfc;
|
||||
|
||||
&::placeholder {
|
||||
color: #7f8a95;
|
||||
|
||||
@@ -1010,6 +1010,7 @@ select.form-control {
|
||||
resize: none;
|
||||
transition: border-color 0.2s;
|
||||
min-height: 250px;
|
||||
background-color: #fcfcfc;
|
||||
|
||||
&::placeholder {
|
||||
color: #94A3B8;
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
p {
|
||||
margin: 0;
|
||||
|
||||
& + p {
|
||||
&+p {
|
||||
margin-top: $spacing-md;
|
||||
}
|
||||
}
|
||||
@@ -240,7 +240,6 @@
|
||||
.btn,
|
||||
.btn-modal-cancel,
|
||||
.btn-modal-confirm {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 46px;
|
||||
font-size: 15px;
|
||||
@@ -330,4 +329,4 @@
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,7 @@
|
||||
|
||||
// Logo with modern styling
|
||||
.logo {
|
||||
display: block;
|
||||
display: flex;
|
||||
height: 32px;
|
||||
vertical-align: middle;
|
||||
z-index: 10;
|
||||
@@ -202,7 +202,6 @@
|
||||
|
||||
// Logo link styles
|
||||
.logo-link,
|
||||
.mobile-logo-link,
|
||||
.drawer-logo-link {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
@@ -937,7 +936,7 @@
|
||||
|
||||
.sub-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 8px);
|
||||
top: calc(100% + 17px);
|
||||
left: 0;
|
||||
min-width: 200px;
|
||||
background: var(--white);
|
||||
|
||||
@@ -571,7 +571,7 @@
|
||||
// Result Page Styles (아이디 찾기 결과 페이지)
|
||||
.account-recovery-result {
|
||||
width: 100%;
|
||||
padding: 60px 40px;
|
||||
padding: 35px 0px;
|
||||
border-radius: 0 0 12px 12px;
|
||||
text-align: center;
|
||||
|
||||
@@ -690,6 +690,44 @@
|
||||
border-radius: 12px;
|
||||
padding: 16px 24px;
|
||||
|
||||
&.info-box-highlight {
|
||||
background: linear-gradient(135deg, rgba(0, 73, 180, 0.06) 0%, rgba(0, 73, 180, 0.02) 100%);
|
||||
border: 1.5px solid rgba(0, 73, 180, 0.25);
|
||||
box-shadow: 0 8px 24px rgba(0, 73, 180, 0.08);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
animation: fadeInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
transform: translateY(15px);
|
||||
opacity: 0;
|
||||
|
||||
.highlight-icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
animation: pulseIcon 2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.info-text {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: #1e293b;
|
||||
text-align: center;
|
||||
|
||||
strong {
|
||||
color: #0049B4;
|
||||
font-weight: 700;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #4685ef;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.info-text {
|
||||
font-family: $font-family-primary;
|
||||
font-size: 15px;
|
||||
@@ -725,6 +763,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulseIcon {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
filter: drop-shadow(0 0 0px rgba(0, 73, 180, 0));
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.06);
|
||||
filter: drop-shadow(0 0 6px rgba(0, 73, 180, 0.2));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Mobile Design (sm: 768px breakpoint)
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -785,7 +844,7 @@
|
||||
.auth-input-group {
|
||||
.auth-timer {
|
||||
font-size: 12px;
|
||||
right: 100px;
|
||||
right: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,16 +168,16 @@
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #dadada;
|
||||
border: 1px solid #DFDFDF;
|
||||
border-radius: $border-radius-md;
|
||||
background-color: $white;
|
||||
background-color: #fcfcfc;
|
||||
font-size: 14px;
|
||||
color: $text-dark;
|
||||
outline: none;
|
||||
transition: border-color 0.2s ease;
|
||||
|
||||
&::placeholder {
|
||||
color: #dadada;
|
||||
color: #94A3B8;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
@@ -1130,7 +1130,7 @@ input[type="checkbox"]:checked+.custom-checkbox {
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: #E2E8F0 !important;
|
||||
background-color: #ededed !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2929,7 +2929,7 @@ input[type="checkbox"]:checked+.custom-checkbox {
|
||||
.s1-title,
|
||||
.s2-title,
|
||||
.s3-title {
|
||||
font-size: 30px;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #0d0e11;
|
||||
line-height: 1;
|
||||
@@ -3261,7 +3261,7 @@ input[type="checkbox"]:checked+.custom-checkbox {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.s1-upload-inner > img {
|
||||
.s1-upload-inner>img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
@@ -423,342 +423,6 @@
|
||||
// API Search section styles - 검색 섹션
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/* 원래 있던 검색 영역 스타일 (주석 처리)
|
||||
.api-search-section {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
//margin-top: -72px;
|
||||
overflow: hidden;
|
||||
background: #e9f9ff;
|
||||
height: 283px;
|
||||
|
||||
.search-background {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: url('/img/bg_main_intersect.svg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.search-content-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 36px;
|
||||
z-index: 1;
|
||||
|
||||
@include respond-to('md') {
|
||||
flex-direction: column;
|
||||
gap: 22px;
|
||||
padding-top: 36px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 캐릭터와 텍스트 가로 배치
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 7px;
|
||||
padding-top: 18px;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.search-character {
|
||||
width: 139px;
|
||||
height: 133px;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
@include respond-to('md') {
|
||||
width: 108px;
|
||||
height: 104px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 68x65px
|
||||
width: 61px;
|
||||
height: 59px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-text-content {
|
||||
text-align: left;
|
||||
|
||||
@include respond-to('md') {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 텍스트 왼쪽 정렬
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.search-title {
|
||||
font-size: 32px;
|
||||
line-height: 1.3;
|
||||
color: #000000;
|
||||
margin: 0;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 14px, Bold
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: #212529;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0px 0 27px;
|
||||
z-index: 1;
|
||||
|
||||
@include respond-to('md') {
|
||||
padding: 27px 18px 18px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 좌측 24px, 우측 25px 패딩으로 좌측 정렬
|
||||
justify-content: flex-start;
|
||||
padding: 0px 25px 11px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-form {
|
||||
width: 100%;
|
||||
max-width: 816px;
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 288px 고정 너비
|
||||
//width: 288px;
|
||||
//max-width: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 72px;
|
||||
background: #FFFFFF;
|
||||
border: 5px solid #0049B4;
|
||||
border-radius: 45px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 22px;
|
||||
|
||||
@include respond-to('md') {
|
||||
height: 54px;
|
||||
border: 4px solid #0049B4;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 320x36px, 1px 파란색 테두리
|
||||
height: 32px;
|
||||
border: 3px solid #0049B4;
|
||||
border-radius: 16px;
|
||||
padding: 0 11px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
font-family: $font-family-primary;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
padding: 0 18px;
|
||||
|
||||
&::placeholder {
|
||||
color: #B3B3B3;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 14px;
|
||||
padding: 0 11px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 10px, Medium, placeholder 색상 #8C959F
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
padding: 0 7px;
|
||||
|
||||
&::placeholder {
|
||||
color: #8C959F;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon-button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
flex-shrink: 0;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 30px;
|
||||
height: 31px;
|
||||
|
||||
@include respond-to('md') {
|
||||
width: 25px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 16x16px 아이콘
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.hashtag-section {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 11px;
|
||||
padding: 0 18px 0px;
|
||||
z-index: 1;
|
||||
|
||||
@include respond-to('md') {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 7px;
|
||||
padding: 0 18px 27px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 가로 배치, 작은 간격
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 11px;
|
||||
padding: 0 18px 18px;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.hashtag-label {
|
||||
font-family: $font-family-primary;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
white-space: nowrap;
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 11px, Bold
|
||||
font-size: 11px;
|
||||
color: #212529;
|
||||
}
|
||||
}
|
||||
|
||||
.hashtag-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 13px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@include respond-to('md') {
|
||||
justify-content: center;
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 7px 간격, wrap
|
||||
gap: 7px;
|
||||
justify-content: left;
|
||||
}
|
||||
}
|
||||
|
||||
.hashtag-link {
|
||||
font-family: $font-family-primary;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
transition: color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
color: #0049B4;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 11px
|
||||
font-size: 11px;
|
||||
color: #212529;
|
||||
}
|
||||
}
|
||||
|
||||
.hashtag-separator {
|
||||
font-family: $font-family-primary;
|
||||
font-size: 14px;
|
||||
color: #000000;
|
||||
user-select: none;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 세로 구분선 (|)
|
||||
font-size: 9px;
|
||||
color: #212529;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 9px;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* 피그마 시안 적용 카드 레이아웃 스타일 */
|
||||
.search-container {
|
||||
@@ -1288,14 +952,21 @@
|
||||
|
||||
.card-description {
|
||||
font-family: $font-family-primary;
|
||||
font-size: 13px;
|
||||
font-size: 16px;
|
||||
color: var(--text-gray);
|
||||
line-height: 1.5;
|
||||
text-align: left;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 1.5;
|
||||
max-height: 3em;
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 11px Medium, 색상 #515151
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
|
||||
@@ -1425,7 +1096,7 @@
|
||||
letter-spacing: 1px;
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1447,7 +1118,7 @@
|
||||
}
|
||||
|
||||
.info-description {
|
||||
font-size: 14px;
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
margin-bottom: 36px;
|
||||
@@ -1459,7 +1130,7 @@
|
||||
|
||||
@include respond-to('sm') {
|
||||
order: 3;
|
||||
font-size: 13px;
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 24px;
|
||||
word-break: keep-all;
|
||||
@@ -1637,424 +1308,6 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Support Center Section - 비지니스의 시작 (Figma Design)
|
||||
// -----------------------------------------------------------------------------
|
||||
/* 원래 있던 support-center 스타일 (주석 처리)
|
||||
.support-center {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
padding-top: 92px;
|
||||
padding-bottom: 113px;
|
||||
background: #eef7fd;
|
||||
overflow: hidden;
|
||||
height: 648px;
|
||||
|
||||
@include respond-to('md') {
|
||||
height: auto;
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 353px 높이, 패딩 54px 18px
|
||||
min-height: unset;
|
||||
height: auto;
|
||||
padding: 54px 18px;
|
||||
}
|
||||
|
||||
.support-background {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 1920px;
|
||||
pointer-events: none;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15px; // Figma: top-[2911px] relative to page, section starts at ~2895px
|
||||
left: 46%; // Approximate positioning
|
||||
width: 624px;
|
||||
height: 537px;
|
||||
background-image: url('/img/bg_support_center.png'); // Assuming this image exists or use placeholder
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0.5; // Adjust based on visual
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
|
||||
// Figma 모바일: 포인트 이미지 상단 우측
|
||||
&::before {
|
||||
top: 0;
|
||||
left: auto;
|
||||
right: 0;
|
||||
width: 168px;
|
||||
height: 159px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 0 23px;
|
||||
height: 443px;
|
||||
|
||||
@include respond-to('md') {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
padding: 0;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
margin-bottom: 36px;
|
||||
text-align: center;
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 타이틀 영역
|
||||
margin-bottom: 22px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 25px;
|
||||
line-height: 1.4;
|
||||
color: #000000;
|
||||
margin: 0 0 $spacing-lg 0;
|
||||
text-align: left;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 32px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 타이틀 스타일
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.32px;
|
||||
}
|
||||
|
||||
.title-regular {
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.title-bold {
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 18px Bold
|
||||
font-size: 18px;
|
||||
letter-spacing: -0.4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.support-grid {
|
||||
display: flex;
|
||||
gap: 29px;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
max-width: 1228px; // 598 + 283 + 283 + (32 * 2) = 1228px
|
||||
height: auto;
|
||||
min-height: 288px;
|
||||
margin: 0 auto;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@include respond-to('mobile') {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 18px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// 가로 배치는 카드가 너무 좁아지므로 1열 세로 배치로 변경
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 14px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// 통합 Support Card
|
||||
.support-card {
|
||||
background: #FFFFFF;
|
||||
border-radius: 18px;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 288px; // 모든 카드 동일 높이
|
||||
|
||||
@include respond-to('mobile') {
|
||||
width: 100%;
|
||||
max-width: 598px;
|
||||
height: auto;
|
||||
min-height: 234px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 101x168px 카드
|
||||
width: calc(33.333% - 7px);
|
||||
min-width: 0;
|
||||
height: 151px;
|
||||
min-height: 151px;
|
||||
max-width: none;
|
||||
border-radius: 11px;
|
||||
padding: 23px 0 23px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 9px 27px rgba(0, 73, 180, 0.15);
|
||||
|
||||
@include respond-to('sm') {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 43px 아이콘
|
||||
width: 43px !important;
|
||||
height: 43px !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
@include respond-to('sm') {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-family: $font-family-primary;
|
||||
font-size: 29px;
|
||||
font-weight: 700;
|
||||
color: #212529;
|
||||
margin: 0 0 9px 0;
|
||||
line-height: 1.3;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 15-14px Bold
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: $font-family-primary;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #515961;
|
||||
margin: 0;
|
||||
line-height: 1.4;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 9px Regular
|
||||
font-size: 9px;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 공지사항 카드
|
||||
&-notice {
|
||||
width: 349px;
|
||||
flex-shrink: 0;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 45px 36px;
|
||||
background: #0049B4;
|
||||
|
||||
@include respond-to('mobile') {
|
||||
width: 100%;
|
||||
max-width: 598px;
|
||||
padding: 45px 36px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 공지사항 카드 스타일
|
||||
width: 100%;
|
||||
padding: 23px 20px 23px;
|
||||
gap: 17px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 108px;
|
||||
height: 108px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
h3 {
|
||||
color: #FFFFFF;
|
||||
font-size: 27px;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 29px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: 14px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: 20px;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: 9px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: darken(#0049B4, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
// FAQ & Q&A Cards
|
||||
&-faq,
|
||||
&-qna {
|
||||
width: 349px;
|
||||
flex-shrink: 0;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 45px 36px;
|
||||
|
||||
@include respond-to('mobile') {
|
||||
width: 100%;
|
||||
max-width: 598px;
|
||||
padding: 36px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: FAQ/Q&A 카드 스타일
|
||||
width: 100%;
|
||||
padding: 23px 20px 23px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 108px;
|
||||
height: 108px;
|
||||
margin-bottom: 32px;
|
||||
|
||||
}
|
||||
|
||||
.card-content {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
flex: none;
|
||||
|
||||
h3 {
|
||||
font-size: 27px;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 29px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 14px Bold
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 20px;
|
||||
|
||||
@include respond-to('md') {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
// Figma 모바일: 9px Regular
|
||||
font-size: 9px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FAQ Card Specifics
|
||||
&--faq {
|
||||
background: #DAF0FF;
|
||||
|
||||
.card-content h3 {
|
||||
color: #212529;
|
||||
}
|
||||
}
|
||||
|
||||
// Q&A Card Specifics
|
||||
&--qna {
|
||||
background: #D9F6F8;
|
||||
|
||||
.card-content h3 {
|
||||
color: #212529;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* 피그마 시안 적용 Support Center 그리드 레이아웃 스타일 */
|
||||
.support-center {
|
||||
@@ -2130,9 +1383,10 @@
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
color: var(--text-gray);
|
||||
line-height: 1.5;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.card-arrow {
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
}
|
||||
|
||||
.form-label-text {
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #000;
|
||||
}
|
||||
@@ -159,7 +159,7 @@
|
||||
|
||||
.form-input:disabled,
|
||||
.input-readonly {
|
||||
background: #e9ecef !important;
|
||||
background: #ededed !important;
|
||||
}
|
||||
|
||||
.compound-input {
|
||||
@@ -289,6 +289,7 @@
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
flex-shrink: 0;
|
||||
color: #4685ef
|
||||
}
|
||||
|
||||
p {
|
||||
|
||||
@@ -136,9 +136,9 @@
|
||||
}
|
||||
|
||||
&--completed {
|
||||
background: #e5f0ff;
|
||||
color: #0a4ea3;
|
||||
border: 1px solid #b3d4ff;
|
||||
background: #d6fbd0;
|
||||
color: #11af4c;
|
||||
border: 1px solid #a0d4b2;
|
||||
}
|
||||
|
||||
&--closed {
|
||||
@@ -159,6 +159,12 @@
|
||||
border: 1px solid #b3d4ff;
|
||||
}
|
||||
|
||||
&--reviewing {
|
||||
background: #e5f0ff;
|
||||
color: #0a4ea3;
|
||||
border: 1px solid #b3d4ff;
|
||||
}
|
||||
|
||||
&--test {
|
||||
background: #e6fffa;
|
||||
color: #0d9488;
|
||||
|
||||
@@ -34,6 +34,53 @@
|
||||
@media (max-width: $breakpoint-sm) {
|
||||
padding: $spacing-lg $spacing-md;
|
||||
}
|
||||
|
||||
.invitation_alert_banner {
|
||||
background-color: #f0f8ff;
|
||||
border: 1.5px solid #2196F3;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin: 20px 0;
|
||||
box-shadow: 0 8px 24px rgba(33, 150, 243, 0.08);
|
||||
animation: fadeInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
transform: translateY(15px);
|
||||
opacity: 0;
|
||||
margin-bottom: 60px;
|
||||
|
||||
.banner-content-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.banner-icon-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
svg {
|
||||
animation: pulseIcon 2s infinite ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-text-area {
|
||||
strong {
|
||||
color: #1976D2;
|
||||
font-size: 17px;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
color: #475569;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Header
|
||||
@@ -315,6 +362,16 @@
|
||||
background-position: right 8px center;
|
||||
}
|
||||
|
||||
.org-form-select.phone-prefix {
|
||||
flex: 1;
|
||||
min-width: 90px;
|
||||
max-width: 130px;
|
||||
padding-right: 28px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2364748B' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 8px center;
|
||||
}
|
||||
|
||||
.separator {
|
||||
color: $text-gray;
|
||||
font-weight: $font-weight-semibold;
|
||||
@@ -336,29 +393,31 @@
|
||||
// Select Dropdown
|
||||
.org-form-select {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid $border-gray;
|
||||
border-radius: $border-radius-md;
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid #E2E8F0;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
color: $text-dark;
|
||||
color: #212529;
|
||||
background: $white;
|
||||
cursor: pointer;
|
||||
transition: $transition-base;
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2364748B' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right $spacing-lg center;
|
||||
background-position: right 16px center;
|
||||
padding-right: $spacing-3xl;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: $primary-blue;
|
||||
box-shadow: 0 0 0 3px rgba(75, 155, 255, 0.1);
|
||||
border-color: #3ba4ed;
|
||||
box-shadow: 0 0 0 3px rgba(59, 164, 237, 0.12);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: $gray-bg;
|
||||
color: $text-light;
|
||||
background-color: #F8F9FA;
|
||||
border-color: #E2E8F0;
|
||||
color: #94A3B8;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,26 +386,31 @@ $service-card-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgb
|
||||
padding-bottom: 100px;
|
||||
|
||||
.signup-info-box {
|
||||
background: #f5f5f5;
|
||||
border-radius: 12px;
|
||||
padding: 30px 40px;
|
||||
background: #1d2a5e; // Deep slate dark card
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-left: 5px solid #2a69de; // Bright tech blue accent line
|
||||
border-radius: 16px;
|
||||
padding: 28px 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 28px;
|
||||
animation: fadeInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
|
||||
&__icon {
|
||||
width: 76px;
|
||||
height: 76px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
background: #48507b;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
filter: brightness(0) invert(1); // Turns the green check into clean white icon
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
@@ -417,183 +422,397 @@ $service-card-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgb
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
padding-left: 14px;
|
||||
color: #535151;
|
||||
font-size: 16px;
|
||||
padding-left: 20px;
|
||||
color: #94a3b8; // Sophisticated dim gray-blue
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
line-height: 1.8;
|
||||
word-break: keep-all;
|
||||
|
||||
strong {
|
||||
color: #ffffff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '·';
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #535151;
|
||||
left: 4px;
|
||||
top: 10px;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background: #38bdf8; // Neon cyan dot
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&+li {
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.signup-timeline {
|
||||
// Member Type Tabs
|
||||
.signup-tabs {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
border-bottom: 1px solid #e3e8f0;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 50px;
|
||||
width: 100%;
|
||||
|
||||
.signup-tab-btn {
|
||||
flex: 1;
|
||||
max-width: 50%;
|
||||
padding: 16px 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #94a3b8;
|
||||
background: none;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: all 0.2s ease;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #2a69de;
|
||||
font-weight: 700;
|
||||
border-bottom: 2px solid #2a69de;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.signup-timeline-container {
|
||||
margin-bottom: 50px;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
|
||||
.signup-timeline {
|
||||
display: none; // Hidden by default, toggled via JS
|
||||
flex-direction: column;
|
||||
gap: 40px;
|
||||
position: relative;
|
||||
padding-left: 80px;
|
||||
|
||||
&.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 17px; // center of line
|
||||
top: 47px;
|
||||
bottom: 47px;
|
||||
width: 2px;
|
||||
background: #e6eefb; // Light blue line
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-step {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
// Glowing Dot
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -71px; // (80 - 17) = 63 distance to line center. 63 + 8 (half of 16px) = 71px
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #2a69de;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 6px rgba(42, 105, 222, 0.15), 0 0 10px 6px rgba(42, 105, 222, 0.1);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&__icon-box {
|
||||
width: 95px;
|
||||
min-height: 95px;
|
||||
background: #fff;
|
||||
border: 1px solid #e3e8f0;
|
||||
border-radius: 20px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 4px 4px rgba(173, 173, 173, 0.1);
|
||||
|
||||
svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
&__card {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
border: 1px solid #e3e8f0;
|
||||
border-radius: 20px;
|
||||
padding: 20px 30px;
|
||||
box-shadow: 0 4px 4px rgba(173, 173, 173, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 40px;
|
||||
position: relative;
|
||||
padding-left: 80px;
|
||||
justify-content: center;
|
||||
min-height: 95px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 17px; // center of line
|
||||
top: 47px;
|
||||
bottom: 47px;
|
||||
width: 2px;
|
||||
background: #e6eefb; // Light blue line
|
||||
z-index: 0;
|
||||
&-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
&-num {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #1b4ab7;
|
||||
}
|
||||
|
||||
&-dot {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: #1b4ab7;
|
||||
border-radius: 50%;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #000;
|
||||
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
&-desc {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #64748b;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-step {
|
||||
.one {
|
||||
color: #2C4A8C;
|
||||
}
|
||||
|
||||
.two {
|
||||
color: #1F7A5C;
|
||||
}
|
||||
|
||||
.three {
|
||||
color: #F98E24;
|
||||
}
|
||||
|
||||
.four {
|
||||
color: #2480F9;
|
||||
}
|
||||
|
||||
.five {
|
||||
color: #FF5C5C;
|
||||
}
|
||||
|
||||
.six {
|
||||
color: #5B4AEE;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-action {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
// 권한별 이용 가능 서비스 (TBD placeholder)
|
||||
.signup-roles-tbd {
|
||||
margin-top: 40px;
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #140064;
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
&__placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 48px 24px;
|
||||
background: #f8f9fa;
|
||||
border: 1px dashed #e3e8f0;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
color: #0049B4;
|
||||
background: #eff9fe;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
&__desc {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
color: #6e7781;
|
||||
}
|
||||
}
|
||||
|
||||
// 권한별 이용 가능 서비스 테이블 디자인 추가
|
||||
.signup-roles-table-section {
|
||||
margin-top: 50px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin: 0 0 20px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-left: 12px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
|
||||
// Glowing Dot
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -71px; // (80 - 17) = 63 distance to line center. 63 + 8 (half of 16px) = 71px
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: #2a69de;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 6px rgba(42, 105, 222, 0.15), 0 0 10px 6px rgba(42, 105, 222, 0.1);
|
||||
z-index: 2;
|
||||
left: 0;
|
||||
top: 4px;
|
||||
bottom: 4px;
|
||||
width: 4px;
|
||||
background: #0049B4;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-roles-table-wrapper {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.02);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
&__icon-box {
|
||||
width: 95px;
|
||||
height: 95px;
|
||||
background: #fff;
|
||||
border: 1px solid #e3e8f0;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 4px 4px rgba(173, 173, 173, 0.1);
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #cbd5e1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
.signup-roles-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-family: $font-family-primary;
|
||||
text-align: center;
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 14px 16px;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
border-right: 1px solid #e2e8f0;
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__card {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
border: 1px solid #e3e8f0;
|
||||
border-radius: 20px;
|
||||
padding: 0 30px;
|
||||
box-shadow: 0 4px 4px rgba(173, 173, 173, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 95px;
|
||||
thead {
|
||||
background: #f8fafc;
|
||||
|
||||
&-num {
|
||||
th {
|
||||
font-weight: 700;
|
||||
color: #334155;
|
||||
font-size: 13px;
|
||||
|
||||
&.col-feature {
|
||||
width: 35%;
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
&.col-role {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
&.col-role-group {
|
||||
background: #f1f5f9;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
&.col-sub-role {
|
||||
width: 17.5%;
|
||||
background: #f8fafc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
transition: background 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
&:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-feature {
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
text-align: left;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
// O / X 배지 디자인
|
||||
.status-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #1b4ab7;
|
||||
margin-bottom: 4px;
|
||||
|
||||
&--allowed {
|
||||
background: #e0f2fe;
|
||||
color: #0369a1;
|
||||
}
|
||||
|
||||
&--denied {
|
||||
background: #f1f5f9;
|
||||
color: #94a3b8;
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.one {
|
||||
color: #2C4A8C;
|
||||
}
|
||||
|
||||
.two {
|
||||
color: #1F7A5C;
|
||||
}
|
||||
|
||||
.three {
|
||||
color: #F98E24;
|
||||
}
|
||||
|
||||
.four {
|
||||
color: #2480F9;
|
||||
}
|
||||
|
||||
.five {
|
||||
color: #FF5C5C;
|
||||
}
|
||||
|
||||
.six {
|
||||
color: #5B4AEE;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-action {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
// 권한별 이용 가능 서비스 (TBD placeholder)
|
||||
.signup-roles-tbd {
|
||||
margin-top: 40px;
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #140064;
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
&__placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 48px 24px;
|
||||
background: #f8f9fa;
|
||||
border: 1px dashed #e3e8f0;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__badge {
|
||||
display: inline-block;
|
||||
padding: 4px 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
color: #0049B4;
|
||||
background: #eff9fe;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
&__desc {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
color: #6e7781;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -630,12 +849,25 @@ $service-card-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgb
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.signup-guide-v2 {
|
||||
.signup-timeline {
|
||||
padding-left: 0;
|
||||
|
||||
&::before {
|
||||
display: none; // Hides the vertical timeline line
|
||||
}
|
||||
}
|
||||
|
||||
.signup-step {
|
||||
gap: 15px;
|
||||
|
||||
&::before {
|
||||
display: none; // Hides the glowing timeline dot
|
||||
}
|
||||
|
||||
&__icon-box {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
min-height: 60px;
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
@@ -646,25 +878,13 @@ $service-card-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgb
|
||||
&__card {
|
||||
height: auto;
|
||||
min-height: 60px;
|
||||
padding: 10px 15px;
|
||||
padding: 12px 18px;
|
||||
|
||||
&-title {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.signup-timeline {
|
||||
padding-left: 50px;
|
||||
|
||||
&::before {
|
||||
left: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
.signup-step::before {
|
||||
left: -41px; // adjusted for new padding
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -676,23 +896,23 @@ $service-card-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgb
|
||||
padding: 56px 16px 32px;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
}
|
||||
|
||||
.service_guide {
|
||||
.title {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
line-height: 36px;
|
||||
letter-spacing: -0.02em;
|
||||
color: #140064;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.service_guide {
|
||||
.title {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
line-height: 36px;
|
||||
letter-spacing: -0.02em;
|
||||
color: #140064;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: #495057;
|
||||
}
|
||||
.detail {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
color: #495057;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1117,9 +1337,10 @@ $o2leg-err-fg: #a23b3b;
|
||||
|
||||
&__prereq-title {
|
||||
margin: 4px 0 8px;
|
||||
font-size: 15px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: $o2leg-text-dark;
|
||||
font-family: "Spoqa Han Sans Neo", "SpoqaHanSans", "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
&__prereq-body p {
|
||||
|
||||
@@ -63,6 +63,7 @@ $wh-bg-soft: #f9f9f9;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 16px;
|
||||
color: #cbd5e1;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@@ -704,7 +705,7 @@ $wh-bg-soft: #f9f9f9;
|
||||
.input-display-box {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
background-color: #eeeeee;
|
||||
background-color: #efefef;
|
||||
border-radius: 10px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
@@ -714,6 +715,7 @@ $wh-bg-soft: #f9f9f9;
|
||||
font-weight: 500;
|
||||
word-break: break-all;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #DFDFDF;
|
||||
}
|
||||
|
||||
.badges-row {
|
||||
@@ -767,7 +769,7 @@ $wh-bg-soft: #f9f9f9;
|
||||
flex: 1;
|
||||
max-width: 250px;
|
||||
height: 48px;
|
||||
background-color: #eeeeee;
|
||||
background-color: #efefef;
|
||||
border-radius: 10px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
@@ -778,6 +780,7 @@ $wh-bg-soft: #f9f9f9;
|
||||
font-weight: 500;
|
||||
box-sizing: border-box;
|
||||
letter-spacing: 1px;
|
||||
border: 1px solid #DFDFDF;
|
||||
|
||||
@media (max-width: 576px) {
|
||||
max-width: 100%;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<section class="service-hero">
|
||||
<div class="service-hero__inner">
|
||||
<div class="service-hero__icon-wrapper">
|
||||
<img th:src="@{/img/keyimage/api_img.svg}" alt="OPEN API 3D 아이콘" class="service-keyImg" />
|
||||
<img th:src="@{/img/keyimage/api_img.png}" alt="OPEN API 3D 아이콘" class="service-keyImg" />
|
||||
</div>
|
||||
<div class="service-hero__content">
|
||||
<div class="service-hero__badge">
|
||||
|
||||
@@ -1,61 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/djbank_title_layout}">
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/djbank_title_layout}">
|
||||
|
||||
<body>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>본인 확인</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section layout:fragment="contentFragment">
|
||||
<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="password-change-wrapper">
|
||||
<h2 class="page-outer-title">본인 확인</h2>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>본인 확인</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section layout:fragment="contentFragment">
|
||||
<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="password-change-wrapper">
|
||||
<h2 class="page-outer-title">본인 확인</h2>
|
||||
|
||||
<form th:action="@{/auth/stepup/password}" method="post">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||
<input type="hidden" name="returnUrl" th:value="${returnUrl}"/>
|
||||
<form th:action="@{/auth/stepup/password}" method="post">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
|
||||
<input type="hidden" name="returnUrl" th:value="${returnUrl}" />
|
||||
|
||||
<div class="register-form-container">
|
||||
<div class="info-notice-box">
|
||||
<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>
|
||||
<div class="register-form-container">
|
||||
<div class="info-notice-box">
|
||||
<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>
|
||||
<p>내 정보 보호를 위하여 현재 비밀번호를 다시 입력해 주세요</p>
|
||||
</div>
|
||||
<div class="form-field-wrapper">
|
||||
<input type="password" name="currentPassword" class="form-input"
|
||||
placeholder="비밀번호 입력" required autofocus>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-label-wrapper">
|
||||
<span class="form-label-text">현재 비밀번호</span>
|
||||
</div>
|
||||
<div class="form-field-wrapper">
|
||||
<input type="password" name="currentPassword" class="form-input"
|
||||
placeholder="비밀번호 입력" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions" style="justify-content: flex-end;">
|
||||
<div class="right-buttons">
|
||||
<button type="button" class="btn-cancel" th:onclick="|location.href='@{/}'|">취소</button>
|
||||
<button type="submit" class="btn-apply btn-primary">확인</button>
|
||||
<div class="form-actions" style="justify-content: flex-end;">
|
||||
<div class="right-buttons">
|
||||
<button type="button" class="btn-cancel" th:onclick="|location.href='@{/}'|">취소</button>
|
||||
<button type="submit" class="btn-apply btn-primary">확인</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script th:if="${error}" th:inline="javascript">
|
||||
$(document).ready(function () {
|
||||
customPopups.showAlert([[${error}]]);
|
||||
})
|
||||
</script>
|
||||
</section>
|
||||
<script th:if="${error}" th:inline="javascript">
|
||||
$(document).ready(function () {
|
||||
customPopups.showAlert([[${ error }]]);
|
||||
})
|
||||
</script>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -16,7 +16,7 @@
|
||||
<section class="service-hero">
|
||||
<div class="service-hero__inner">
|
||||
<div class="service-hero__icon-wrapper">
|
||||
<img th:src="@{/img/keyimage/faq_img.svg}" alt="FAQ 아이콘"
|
||||
<img th:src="@{/img/keyimage/faq_img.png}" alt="FAQ 아이콘"
|
||||
style="width: 100%; height: 100%; object-fit: contain;" />
|
||||
</div>
|
||||
<div class="service-hero__content">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="service-hero__inner">
|
||||
<div class="service-hero__icon-wrapper">
|
||||
<!-- TODO: Update icon to faq icon -->
|
||||
<img th:src="@{/img/keyimage/faq_img.svg}" alt="FAQ 아이콘"
|
||||
<img th:src="@{/img/keyimage/faq_img.png}" alt="FAQ 아이콘"
|
||||
style="width: 100%; height: 100%; object-fit: contain;" />
|
||||
</div>
|
||||
<div class="service-hero__content">
|
||||
|
||||
@@ -76,9 +76,9 @@
|
||||
<!-- Table Header -->
|
||||
<div class="board-table-header">
|
||||
<div class="header-cell" style="width: 80px;">NO</div>
|
||||
<div class="header-cell" style="width: 120px;">처리상태</div>
|
||||
<div class="header-cell" style="flex: 1; min-width: 200px;">제목</div>
|
||||
<div class="header-cell" style="width: 120px;">작성자</div>
|
||||
<div class="header-cell" style="width: 120px;">처리상태</div>
|
||||
<div class="header-cell" style="width: 80px;">조회수</div>
|
||||
<div class="header-cell" style="width: 120px;">등록일</div>
|
||||
</div>
|
||||
@@ -89,9 +89,19 @@
|
||||
th:classappend="${inquiry.privatePlaceholder} ? ' board-table-row--private'"
|
||||
th:onclick="${inquiry.privatePlaceholder} ? null : ('location.href=\'' + @{/inquiry/detail(id=${inquiry.id})} + '\'')"
|
||||
th:style="${inquiry.privatePlaceholder} ? 'cursor: default;' : 'cursor: pointer;'">
|
||||
<div class="row-cell row-cell--number" data-label="NO"
|
||||
<div class="row-cell row-cell--number" style="width: 80px;" data-label="NO"
|
||||
th:text="${page.totalElements - (page.number * page.size) - status.index}">1</div>
|
||||
<div class="row-cell row-cell--title" data-label="제목">
|
||||
|
||||
<!-- 처리상태 (Moved here) -->
|
||||
<div class="row-cell row-cell--status" style="width: 120px;" data-label="처리상태">
|
||||
<span class="notice-type-badge"
|
||||
th:classappend="${inquiry.inquiryStatus == 'RESPONDED' ? 'notice-type-badge--completed' : (inquiry.inquiryStatus == 'CLOSED' ? 'notice-type-badge--closed' : (inquiry.inquiryStatus == 'REVIEWING' ? 'notice-type-badge--reviewing' : 'notice-type-badge--pending'))}"
|
||||
th:text="${T(com.eactive.apim.portal.djb.community.qna.constant.DjbInquiryStatus).displayName(inquiry.inquiryStatus)}">
|
||||
답변대기
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row-cell row-cell--title" style="flex: 1; min-width: 200px;" data-label="제목">
|
||||
<a th:href="${inquiry.privatePlaceholder} ? null : @{/inquiry/detail(id=${inquiry.id})}"
|
||||
class="notice-title-link"
|
||||
th:classappend="${inquiry.privatePlaceholder} ? ' notice-title-link--disabled'">
|
||||
@@ -99,7 +109,7 @@
|
||||
th:text="|[${page.totalElements - (page.number * page.size) - status.index}]|">[1]</span>
|
||||
|
||||
<!-- Private/Lock Icon -->
|
||||
<span class="file-icon" th:if="${inquiry.visibility == 'PRIVATE'}">
|
||||
<span class="file-icon" th:if="${inquiry.visibility == 'PRIVATE'}" style="margin-right: 4px;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="비공개">
|
||||
<rect x="4" y="10" width="16" height="11" rx="2" fill="currentColor" />
|
||||
@@ -117,22 +127,14 @@
|
||||
th:text="|[${commentCounts.get(inquiry.id)}]|">[3]</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row-cell row-cell--writer" data-label="작성자">
|
||||
<div class="row-cell row-cell--writer" style="width: 120px;" data-label="작성자">
|
||||
<span class="inquiry-writer-name" th:text="${inquiry.maskedInquirerName}">홍**</span>
|
||||
<span class="inquiry-writer-org"
|
||||
th:if="${inquiry.inquirerOrgName != null and !inquiry.inquirerOrgName.isEmpty()}"
|
||||
th:text="|(${inquiry.inquirerOrgName})|">(법인명)</span>
|
||||
</div>
|
||||
<div class="row-cell row-cell--status" data-label="처리상태">
|
||||
<!-- completed for RESPONDED, closed for CLOSED, pending for PENDING, maintenance for REVIEWING -->
|
||||
<span class="notice-type-badge lg"
|
||||
th:classappend="${inquiry.inquiryStatus == 'RESPONDED' ? 'notice-type-badge--completed' : (inquiry.inquiryStatus == 'CLOSED' ? 'notice-type-badge--closed' : (inquiry.inquiryStatus == 'REVIEWING' ? 'notice-type-badge--maintenance' : 'notice-type-badge--pending'))}"
|
||||
th:text="${T(com.eactive.apim.portal.djb.community.qna.constant.DjbInquiryStatus).displayName(inquiry.inquiryStatus)}">
|
||||
답변대기
|
||||
</span>
|
||||
</div>
|
||||
<div class="row-cell row-cell--views" data-label="조회수" th:text="${inquiry.viewCount}">0</div>
|
||||
<div class="row-cell row-cell--date" data-label="등록일"
|
||||
<div class="row-cell row-cell--views" style="width: 80px;" data-label="조회수" th:text="${inquiry.viewCount}">0</div>
|
||||
<div class="row-cell row-cell--date" style="width: 120px;" data-label="등록일"
|
||||
th:text="${#temporals.format(inquiry.createdDate, 'yyyy.MM.dd')}">2025.01.01</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<section class="service-hero">
|
||||
<div class="service-hero__inner">
|
||||
<div class="service-hero__icon-wrapper">
|
||||
<img th:src="@{/img/keyimage/notice_img.svg}" alt="공지사항 아이콘"
|
||||
<img th:src="@{/img/keyimage/notice_img.png}" alt="공지사항 아이콘"
|
||||
style="width: 100%; height: 100%; object-fit: contain;" />
|
||||
</div>
|
||||
<div class="service-hero__content">
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<section class="service-hero">
|
||||
<div class="service-hero__inner">
|
||||
<div class="service-hero__icon-wrapper">
|
||||
<img th:src="@{/img/keyimage/notice_img.svg}" alt="공지사항 아이콘" class="service-keyImg" />
|
||||
<img th:src="@{/img/keyimage/notice_img.png}" alt="공지사항 아이콘" class="service-keyImg" />
|
||||
</div>
|
||||
<div class="service-hero__content">
|
||||
<div class="service-hero__badge">
|
||||
@@ -84,7 +84,13 @@
|
||||
<a th:href="@{/portalnotice/detail(id=${notice.id})}" class="notice-title-link">
|
||||
<span class="notice-number"
|
||||
th:text="|[${page.totalElements - (page.number * page.size) - status.index}]|">[1]</span>
|
||||
<span class="notice-type-badge notice-type-badge--fix" th:if="${notice.fixYn == 'Y'}">고정</span>
|
||||
<span class="notice-pin-icon" th:if="${notice.fixYn == 'Y'}"
|
||||
style="margin-right: 6px; display: inline-flex; align-items: center; vertical-align: middle; color: #ef4444;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16 12V4H17V2H7V4H8V12L6 14V16H11V22L12 23L13 22V16H18V14L16 12Z" />
|
||||
</svg>
|
||||
</span>
|
||||
<span class="notice-type-badge notice-type-badge--incident"
|
||||
th:if="${notice.noticeType == '3'}">장애</span>
|
||||
<span class="notice-type-badge notice-type-badge--maintenance"
|
||||
|
||||
@@ -1,66 +1,73 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
|
||||
<body>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>아이디 찾기</h1>
|
||||
</div>
|
||||
</section>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="account-recovery-page">
|
||||
<div class="account-recovery-container">
|
||||
<div class="account-recovery-card">
|
||||
<!-- Tab Navigation -->
|
||||
<div class="account-recovery-tabs">
|
||||
<a href="#" class="tab-link active">아이디찾기</a>
|
||||
<a th:href="@{/account_recovery(tab='resetPassword')}" class="tab-link">비밀번호 초기화</a>
|
||||
</div>
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
|
||||
|
||||
<!-- Result Content Area -->
|
||||
<div class="account-recovery-result">
|
||||
<div class="result-header">
|
||||
<i class="fas fa-check-circle result-icon"></i>
|
||||
<h2 class="result-title">회원님의 아이디를 찾았습니다.</h2>
|
||||
<p class="result-description" th:if="${#lists.size(foundUsers) > 1}">
|
||||
동일한 정보로 가입된 계정이 <strong th:text="${#lists.size(foundUsers)}">2</strong>개 있습니다.
|
||||
</p>
|
||||
<body>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>아이디 찾기</h1>
|
||||
</div>
|
||||
</section>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="account-recovery-page">
|
||||
<div class="account-recovery-container">
|
||||
<div class="account-recovery-card">
|
||||
<!-- Tab Navigation -->
|
||||
<div class="account-recovery-tabs">
|
||||
<a href="#" class="tab-link active">아이디찾기</a>
|
||||
<a th:href="@{/account_recovery(tab='resetPassword')}" class="tab-link">비밀번호 초기화</a>
|
||||
</div>
|
||||
|
||||
<!-- Found Users List -->
|
||||
<div class="found-users-list">
|
||||
<div class="found-user-item" th:each="user, stat : ${foundUsers}">
|
||||
<div class="user-info">
|
||||
<span class="user-email" th:text="${user.loginId}">test@example.com</span>
|
||||
<span class="user-date">
|
||||
(<th:block th:text="${#temporals.format(user.createdDate, 'yyyy.MM.dd')}">2024.01.01</th:block> 가입)
|
||||
</span>
|
||||
<!-- Result Content Area -->
|
||||
<div class="account-recovery-result">
|
||||
<div class="result-header">
|
||||
<i class="fas fa-check-circle result-icon"></i>
|
||||
<h2 class="result-title">회원님의 아이디를 찾았습니다.</h2>
|
||||
<p class="result-description" th:if="${#lists.size(foundUsers) > 1}">
|
||||
동일한 정보로 가입된 계정이 <strong th:text="${#lists.size(foundUsers)}">2</strong>개 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Found Users List -->
|
||||
<div class="found-users-list">
|
||||
<div class="found-user-item" th:each="user, stat : ${foundUsers}">
|
||||
<div class="user-info">
|
||||
<span class="user-email" th:text="${user.loginId}">test@example.com</span>
|
||||
<span class="user-date">
|
||||
(<th:block th:text="${#temporals.format(user.createdDate, 'yyyy.MM.dd')}">2024.01.01</th:block> 가입)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Box -->
|
||||
<div class="result-info-box">
|
||||
<p class="info-text">
|
||||
<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>
|
||||
비밀번호가 기억나지 않는 경우에는
|
||||
<a th:href="@{/account_recovery(tab='resetPassword')}" class="info-link">비밀번호 초기화</a>를
|
||||
이용해 주세요.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Box -->
|
||||
<div class="result-info-box">
|
||||
<p class="info-text">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
비밀번호가 기억나지 않는 경우에는
|
||||
<a th:href="@{/account_recovery(tab='resetPassword')}" class="info-link">비밀번호 초기화</a>를
|
||||
이용해 주세요.
|
||||
</p>
|
||||
<!-- Action Buttons -->
|
||||
<div class="form-actions">
|
||||
<a th:href="@{/account_recovery(tab='findId')}" class="cancel-button">다시 찾기</a>
|
||||
<a th:href="@{/login}" class="submit-button">로그인</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="form-actions">
|
||||
<a th:href="@{/account_recovery(tab='findId')}" class="cancel-button">다시 찾기</a>
|
||||
<a th:href="@{/login}" class="submit-button">로그인</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</th:block>
|
||||
</body>
|
||||
<th:block layout:fragment="contentScript">
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -17,7 +17,7 @@
|
||||
<p class="hero-subtitle">세상의 모든 서비스</p>
|
||||
<h2 class="hero-title">DJBank API가<br>함께 합니다.</h2>
|
||||
</div>
|
||||
<a href="#" class="btn-hero-signup">회원 가입 안내 <i class="bi bi-chevron-right"></i></a>
|
||||
<a th:href="@{/service/guide}" class="btn-hero-signup">회원 가입 안내 <i class="bi bi-chevron-right"></i></a>
|
||||
</div>
|
||||
<div class="hero-image-content">
|
||||
<!-- Inline SVG Tech Illustration -->
|
||||
@@ -47,7 +47,8 @@
|
||||
<p class="hero-subtitle">문서는 상세하게, 연동은 확실하게</p>
|
||||
<h2 class="hero-title">준비된 DJBank API로 <br>완벽한 서비스를 성공하세요.</h2>
|
||||
</div>
|
||||
<a href="#" class="btn-hero-signup">개발 가이드 보기 <i class="bi bi-chevron-right"></i></a>
|
||||
<a th:href="@{/service/oauth2-guide}" class="btn-hero-signup">개발 가이드 보기 <i
|
||||
class="bi bi-chevron-right"></i></a>
|
||||
</div>
|
||||
<div class="hero-image-content">
|
||||
<svg class="hero-illustration" viewBox="0 0 500 400" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -72,7 +73,7 @@
|
||||
<p class="hero-subtitle">상상하는 금융의 구현</p>
|
||||
<h2 class="hero-title">기업의 비즈니스를<br>혁신합니다.</h2>
|
||||
</div>
|
||||
<a href="#" class="btn-hero-signup">제휴 문의하기 <i class="bi bi-chevron-right"></i></a>
|
||||
<a th:href="@{/partnership}" class="btn-hero-signup">제휴 문의하기 <i class="bi bi-chevron-right"></i></a>
|
||||
</div>
|
||||
<div class="hero-image-content">
|
||||
<svg class="hero-illustration" viewBox="0 0 500 400" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -146,40 +147,6 @@
|
||||
<!-- API 검색 섹션 -->
|
||||
<section class="api-search-section">
|
||||
<div class="search-background"></div>
|
||||
<!--/* <div class="search-content-wrapper">*/-->
|
||||
<!--/* <div class="search-character">*/-->
|
||||
<!--/* <img th:src="@{/img/img_search_character.png}" alt="검색">*/-->
|
||||
<!--/* </div>*/-->
|
||||
<!--/* <div class="search-text-content">*/-->
|
||||
<!--/* <h2 class="search-title">*/-->
|
||||
<!--/* 원하는 API를<br>*/-->
|
||||
<!-- 지금 검색해 보세요.-->
|
||||
<!--/* </h2>*/-->
|
||||
<!--/* </div>*/-->
|
||||
<!--/* </div>*/-->
|
||||
<!--/* <div class="search-input-wrapper">*/-->
|
||||
<!--/* <form th:action="@{/apis}" method="get" class="search-form">*/-->
|
||||
<!--/* <div class="search-box">*/-->
|
||||
<!--/* <input type="text" class="search-input" placeholder="어떤 API를 칮고 계신가요?" id="apiSearchInput" name="keyword">*/-->
|
||||
<!--/* <button class="search-icon-button" type="submit">*/-->
|
||||
<!--/* <svg width="33" height="34" viewBox="0 0 33 34" fill="none" xmlns="http://www.w3.org/2000/svg">*/-->
|
||||
<!--/* <path d="M15.1738 0C23.5534 0.000258465 30.3465 6.79327 30.3467 15.1729C30.3467 18.6141 29.2001 21.7875 27.2695 24.333C27.2733 24.3367 27.2775 24.34 27.2812 24.3438L32.1348 29.1973C33.1223 30.1849 33.1223 31.7859 32.1348 32.7734C31.1472 33.7609 29.5461 33.7609 28.5586 32.7734L23.7051 27.9199C23.6653 27.8802 23.6293 27.8376 23.5928 27.7959C21.1837 29.406 18.2889 30.3466 15.1738 30.3467C6.79392 30.3467 0 23.5528 0 15.1729C0.000201956 6.79311 6.79404 0 15.1738 0ZM15.1738 5.05762C9.58735 5.05762 5.05782 9.58642 5.05762 15.1729C5.05762 20.7595 9.58722 25.2891 15.1738 25.2891C20.7602 25.2888 25.2891 20.7593 25.2891 15.1729C25.2889 9.58658 20.7601 5.05788 15.1738 5.05762Z" fill="#0049B4"/>*/-->
|
||||
<!--/* </svg>*/-->
|
||||
<!--/* </button>*/-->
|
||||
<!--/* </div>*/-->
|
||||
<!--/* </form>*/-->
|
||||
<!--/* </div>*/-->
|
||||
<!--/* <div class="hashtag-section">*/-->
|
||||
<!--/* <span class="hashtag-label">자주찾는 API</span>*/-->
|
||||
<!--/* <div class="hashtag-list" th:if="${hashtags != null and not #lists.isEmpty(hashtags)}">*/-->
|
||||
<!--/* <th:block th:each="hashtag, iterStat : ${hashtags}">*/-->
|
||||
<!--/* <a href="#" class="hashtag-link" th:data-search="${hashtag}" th:text="${'#' + hashtag}">*/-->
|
||||
<!--/* </a>*/-->
|
||||
<!--/* <span class="hashtag-separator" th:unless="${iterStat.last}">|</span>*/-->
|
||||
<!--/* </th:block>*/-->
|
||||
<!--/* </div>*/-->
|
||||
<!--/* </div>*/-->
|
||||
|
||||
|
||||
|
||||
<!-- 피그마 시안 적용 카드 레이아웃 -->
|
||||
@@ -328,7 +295,8 @@
|
||||
</p>
|
||||
<div class="action-buttons">
|
||||
<a th:href="@{/service/intro}" class="action-btn btn-secondary">처음 만나는 DJBank API</a>
|
||||
<a th:href="@{/partnership}" class="action-btn btn-primary">피드백 / 개선요청 <i class="bi bi-patch-question"></i></a>
|
||||
<a th:href="@{/partnership}" class="action-btn btn-primary">피드백 / 개선요청 <i
|
||||
class="bi bi-patch-question"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-image-box">
|
||||
@@ -597,268 +565,284 @@
|
||||
|
||||
<!-- 로그인 후 처리 스크립트 -->
|
||||
<script th:src="@{/js/login-success-handler.js}"></script>
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function () {
|
||||
LoginSuccessHandler.init({
|
||||
successMsg: [[${ success }]],
|
||||
emailVerificationRequired: [[${ session.emailVerificationRequired }]],
|
||||
dormantAccount: [[${ session.dormantAccount }]],
|
||||
passwordExpired: [[${ session.passwordExpired }]],
|
||||
pendingInvitation: [[${ session.pendingInvitation }]],
|
||||
pendingInvitationToken: [[${ session.pendingInvitationToken }]],
|
||||
pendingInvitationOrgName: [[${ session.pendingInvitationOrgName }]],
|
||||
needClientRegister: [[${ needClientRegister }]],
|
||||
sessionSuccessMsg: [[${ session.success }]],
|
||||
redirectUrl: [[${ session.redirectUrl }]]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// ========================================
|
||||
// Hero Carousel
|
||||
// ========================================
|
||||
const heroCarousel = {
|
||||
currentSlide: 0,
|
||||
totalSlides: 3,
|
||||
autoPlayInterval: null,
|
||||
autoPlayDelay: 5000,
|
||||
isPlaying: true,
|
||||
|
||||
init: function () {
|
||||
this.slides = document.querySelectorAll('.hero-slide');
|
||||
this.indicators = document.querySelectorAll('.hero-indicator');
|
||||
this.prevBtn = document.getElementById('heroPrevBtn');
|
||||
this.nextBtn = document.getElementById('heroNextBtn');
|
||||
this.autoplayToggle = document.getElementById('heroAutoplayToggle');
|
||||
this.pauseIcon = this.autoplayToggle?.querySelector('.pause-icon');
|
||||
this.playIcon = this.autoplayToggle?.querySelector('.play-icon');
|
||||
|
||||
if (!this.slides.length) return;
|
||||
|
||||
this.bindEvents();
|
||||
this.startAutoPlay();
|
||||
},
|
||||
|
||||
bindEvents: function () {
|
||||
// Previous button
|
||||
if (this.prevBtn) {
|
||||
this.prevBtn.addEventListener('click', () => {
|
||||
this.goToSlide(this.currentSlide - 1);
|
||||
this.resetAutoPlay();
|
||||
});
|
||||
}
|
||||
|
||||
// Next button
|
||||
if (this.nextBtn) {
|
||||
this.nextBtn.addEventListener('click', () => {
|
||||
this.goToSlide(this.currentSlide + 1);
|
||||
this.resetAutoPlay();
|
||||
});
|
||||
}
|
||||
|
||||
// Indicators
|
||||
this.indicators.forEach((indicator, index) => {
|
||||
indicator.addEventListener('click', () => {
|
||||
this.goToSlide(index);
|
||||
this.resetAutoPlay();
|
||||
});
|
||||
});
|
||||
|
||||
// Auto play toggle button
|
||||
if (this.autoplayToggle) {
|
||||
this.autoplayToggle.addEventListener('click', () => {
|
||||
this.toggleAutoPlay();
|
||||
});
|
||||
}
|
||||
|
||||
// Pause on hover (only if playing)
|
||||
const container = document.querySelector('.hero-carousel-container');
|
||||
if (container) {
|
||||
container.addEventListener('mouseenter', () => {
|
||||
if (this.isPlaying) {
|
||||
this.pauseAutoPlay();
|
||||
}
|
||||
});
|
||||
container.addEventListener('mouseleave', () => {
|
||||
if (this.isPlaying) {
|
||||
this.startAutoPlay();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Touch events for mobile
|
||||
let touchStartX = 0;
|
||||
let touchEndX = 0;
|
||||
|
||||
if (container) {
|
||||
container.addEventListener('touchstart', (e) => {
|
||||
touchStartX = e.changedTouches[0].screenX;
|
||||
});
|
||||
|
||||
container.addEventListener('touchend', (e) => {
|
||||
touchEndX = e.changedTouches[0].screenX;
|
||||
this.handleSwipe(touchStartX, touchEndX);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
goToSlide: function (index) {
|
||||
// Wrap around
|
||||
if (index < 0) {
|
||||
index = this.totalSlides - 1;
|
||||
} else if (index >= this.totalSlides) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// Update slides
|
||||
this.slides.forEach((slide, i) => {
|
||||
slide.classList.toggle('active', i === index);
|
||||
});
|
||||
|
||||
// Update indicators
|
||||
this.indicators.forEach((indicator, i) => {
|
||||
indicator.classList.toggle('active', i === index);
|
||||
});
|
||||
|
||||
this.currentSlide = index;
|
||||
},
|
||||
|
||||
handleSwipe: function (startX, endX) {
|
||||
const minSwipeDistance = 50;
|
||||
const distance = startX - endX;
|
||||
|
||||
if (Math.abs(distance) > minSwipeDistance) {
|
||||
if (distance > 0) {
|
||||
// Swipe left - next slide
|
||||
this.goToSlide(this.currentSlide + 1);
|
||||
} else {
|
||||
// Swipe right - previous slide
|
||||
this.goToSlide(this.currentSlide - 1);
|
||||
}
|
||||
this.resetAutoPlay();
|
||||
}
|
||||
},
|
||||
|
||||
startAutoPlay: function () {
|
||||
this.pauseAutoPlay();
|
||||
this.autoPlayInterval = setInterval(() => {
|
||||
this.goToSlide(this.currentSlide + 1);
|
||||
}, this.autoPlayDelay);
|
||||
},
|
||||
|
||||
pauseAutoPlay: function () {
|
||||
if (this.autoPlayInterval) {
|
||||
clearInterval(this.autoPlayInterval);
|
||||
this.autoPlayInterval = null;
|
||||
}
|
||||
},
|
||||
|
||||
resetAutoPlay: function () {
|
||||
if (this.isPlaying) {
|
||||
this.pauseAutoPlay();
|
||||
this.startAutoPlay();
|
||||
}
|
||||
},
|
||||
|
||||
toggleAutoPlay: function () {
|
||||
this.isPlaying = !this.isPlaying;
|
||||
|
||||
if (this.isPlaying) {
|
||||
// Start auto play
|
||||
this.startAutoPlay();
|
||||
// Update icons
|
||||
if (this.pauseIcon) this.pauseIcon.classList.add('active');
|
||||
if (this.playIcon) this.playIcon.classList.remove('active');
|
||||
// Update aria-label
|
||||
if (this.autoplayToggle) {
|
||||
this.autoplayToggle.setAttribute('aria-label', '자동 재생 일시정지');
|
||||
}
|
||||
} else {
|
||||
// Stop auto play
|
||||
this.pauseAutoPlay();
|
||||
// Update icons
|
||||
if (this.pauseIcon) this.pauseIcon.classList.remove('active');
|
||||
if (this.playIcon) this.playIcon.classList.add('active');
|
||||
// Update aria-label
|
||||
if (this.autoplayToggle) {
|
||||
this.autoplayToggle.setAttribute('aria-label', '자동 재생 시작');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize hero carousel
|
||||
heroCarousel.init();
|
||||
|
||||
// ========================================
|
||||
// API 검색 기능
|
||||
// ========================================
|
||||
const searchInput = document.getElementById('apiSearchInput');
|
||||
const searchForm = document.querySelector('.search-form');
|
||||
const hashtags = document.querySelectorAll('.hashtag-link');
|
||||
|
||||
// 해시태그 클릭 이벤트
|
||||
hashtags.forEach(tag => {
|
||||
tag.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const searchTerm = this.getAttribute('data-search');
|
||||
if (searchInput) {
|
||||
searchInput.value = searchTerm;
|
||||
}
|
||||
// 폼 제출
|
||||
if (searchForm) {
|
||||
searchForm.submit();
|
||||
}
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function () {
|
||||
LoginSuccessHandler.init({
|
||||
successMsg: [[${ success }]],
|
||||
emailVerificationRequired: [[${ session.emailVerificationRequired }]],
|
||||
dormantAccount: [[${ session.dormantAccount }]],
|
||||
passwordExpired: [[${ session.passwordExpired }]],
|
||||
pendingInvitation: [[${ session.pendingInvitation }]],
|
||||
pendingInvitationToken: [[${ session.pendingInvitationToken }]],
|
||||
pendingInvitationOrgName: [[${ session.pendingInvitationOrgName }]],
|
||||
needClientRegister: [[${ needClientRegister }]],
|
||||
sessionSuccessMsg: [[${ session.success }]],
|
||||
redirectUrl: [[${ session.redirectUrl }]]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
// ========================================
|
||||
// 숫자 카운트업 애니메이션
|
||||
// ========================================
|
||||
const observerOptions = {
|
||||
threshold: 0.5,
|
||||
rootMargin: '0px 0px -100px 0px'
|
||||
};
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// ========================================
|
||||
// Hero Carousel
|
||||
// ========================================
|
||||
const heroCarousel = {
|
||||
currentSlide: 0,
|
||||
totalSlides: 3,
|
||||
autoPlayInterval: null,
|
||||
autoPlayDelay: 5000,
|
||||
isPlaying: true,
|
||||
|
||||
const animateNumbers = (entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const numbers = entry.target.querySelectorAll('.stat-number');
|
||||
init: function () {
|
||||
this.slides = document.querySelectorAll('.hero-slide');
|
||||
this.indicators = document.querySelectorAll('.hero-indicator');
|
||||
this.prevBtn = document.getElementById('heroPrevBtn');
|
||||
this.nextBtn = document.getElementById('heroNextBtn');
|
||||
this.autoplayToggle = document.getElementById('heroAutoplayToggle');
|
||||
this.pauseIcon = this.autoplayToggle?.querySelector('.pause-icon');
|
||||
this.playIcon = this.autoplayToggle?.querySelector('.play-icon');
|
||||
|
||||
numbers.forEach(number => {
|
||||
const target = parseInt(number.getAttribute('data-target'));
|
||||
const duration = 2000; // 2초
|
||||
const increment = target / (duration / 16);
|
||||
let current = 0;
|
||||
if (!this.slides.length) return;
|
||||
|
||||
const updateNumber = () => {
|
||||
current += increment;
|
||||
if (current < target) {
|
||||
number.textContent = Math.floor(current).toLocaleString('ko-KR');
|
||||
requestAnimationFrame(updateNumber);
|
||||
} else {
|
||||
number.textContent = target.toLocaleString('ko-KR');
|
||||
this.bindEvents();
|
||||
this.startAutoPlay();
|
||||
},
|
||||
|
||||
bindEvents: function () {
|
||||
// Previous button
|
||||
if (this.prevBtn) {
|
||||
this.prevBtn.addEventListener('click', () => {
|
||||
this.goToSlide(this.currentSlide - 1);
|
||||
this.resetAutoPlay();
|
||||
});
|
||||
}
|
||||
|
||||
// Next button
|
||||
if (this.nextBtn) {
|
||||
this.nextBtn.addEventListener('click', () => {
|
||||
this.goToSlide(this.currentSlide + 1);
|
||||
this.resetAutoPlay();
|
||||
});
|
||||
}
|
||||
|
||||
// Indicators
|
||||
this.indicators.forEach((indicator, index) => {
|
||||
indicator.addEventListener('click', () => {
|
||||
this.goToSlide(index);
|
||||
this.resetAutoPlay();
|
||||
});
|
||||
});
|
||||
|
||||
// Auto play toggle button
|
||||
if (this.autoplayToggle) {
|
||||
this.autoplayToggle.addEventListener('click', () => {
|
||||
this.toggleAutoPlay();
|
||||
});
|
||||
}
|
||||
|
||||
// Pause on hover (only if playing)
|
||||
const container = document.querySelector('.hero-carousel-container');
|
||||
if (container) {
|
||||
container.addEventListener('mouseenter', () => {
|
||||
if (this.isPlaying) {
|
||||
this.pauseAutoPlay();
|
||||
}
|
||||
};
|
||||
});
|
||||
container.addEventListener('mouseleave', () => {
|
||||
if (this.isPlaying) {
|
||||
this.startAutoPlay();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateNumber();
|
||||
// Touch events for mobile
|
||||
let touchStartX = 0;
|
||||
let touchEndX = 0;
|
||||
|
||||
if (container) {
|
||||
container.addEventListener('touchstart', (e) => {
|
||||
touchStartX = e.changedTouches[0].screenX;
|
||||
});
|
||||
|
||||
container.addEventListener('touchend', (e) => {
|
||||
touchEndX = e.changedTouches[0].screenX;
|
||||
this.handleSwipe(touchStartX, touchEndX);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
goToSlide: function (index) {
|
||||
// Wrap around
|
||||
if (index < 0) {
|
||||
index = this.totalSlides - 1;
|
||||
} else if (index >= this.totalSlides) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
// Update slides
|
||||
this.slides.forEach((slide, i) => {
|
||||
slide.classList.toggle('active', i === index);
|
||||
});
|
||||
|
||||
observer.unobserve(entry.target);
|
||||
// Update indicators
|
||||
this.indicators.forEach((indicator, i) => {
|
||||
indicator.classList.toggle('active', i === index);
|
||||
});
|
||||
|
||||
// Retrigger draw-line and pulsing animations for Slide 3 (index 2)
|
||||
if (index === 2) {
|
||||
const drawLinePath = this.slides[2].querySelector('.draw-line');
|
||||
const pulsingCircle = this.slides[2].querySelector('.pulsing');
|
||||
if (drawLinePath) {
|
||||
drawLinePath.style.animation = 'none';
|
||||
drawLinePath.offsetHeight;
|
||||
drawLinePath.style.animation = null;
|
||||
}
|
||||
if (pulsingCircle) {
|
||||
pulsingCircle.style.animation = 'none';
|
||||
pulsingCircle.offsetHeight;
|
||||
pulsingCircle.style.animation = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.currentSlide = index;
|
||||
},
|
||||
|
||||
handleSwipe: function (startX, endX) {
|
||||
const minSwipeDistance = 50;
|
||||
const distance = startX - endX;
|
||||
|
||||
if (Math.abs(distance) > minSwipeDistance) {
|
||||
if (distance > 0) {
|
||||
// Swipe left - next slide
|
||||
this.goToSlide(this.currentSlide + 1);
|
||||
} else {
|
||||
// Swipe right - previous slide
|
||||
this.goToSlide(this.currentSlide - 1);
|
||||
}
|
||||
this.resetAutoPlay();
|
||||
}
|
||||
},
|
||||
|
||||
startAutoPlay: function () {
|
||||
this.pauseAutoPlay();
|
||||
this.autoPlayInterval = setInterval(() => {
|
||||
this.goToSlide(this.currentSlide + 1);
|
||||
}, this.autoPlayDelay);
|
||||
},
|
||||
|
||||
pauseAutoPlay: function () {
|
||||
if (this.autoPlayInterval) {
|
||||
clearInterval(this.autoPlayInterval);
|
||||
this.autoPlayInterval = null;
|
||||
}
|
||||
},
|
||||
|
||||
resetAutoPlay: function () {
|
||||
if (this.isPlaying) {
|
||||
this.pauseAutoPlay();
|
||||
this.startAutoPlay();
|
||||
}
|
||||
},
|
||||
|
||||
toggleAutoPlay: function () {
|
||||
this.isPlaying = !this.isPlaying;
|
||||
|
||||
if (this.isPlaying) {
|
||||
// Start auto play
|
||||
this.startAutoPlay();
|
||||
// Update icons
|
||||
if (this.pauseIcon) this.pauseIcon.classList.add('active');
|
||||
if (this.playIcon) this.playIcon.classList.remove('active');
|
||||
// Update aria-label
|
||||
if (this.autoplayToggle) {
|
||||
this.autoplayToggle.setAttribute('aria-label', '자동 재생 일시정지');
|
||||
}
|
||||
} else {
|
||||
// Stop auto play
|
||||
this.pauseAutoPlay();
|
||||
// Update icons
|
||||
if (this.pauseIcon) this.pauseIcon.classList.remove('active');
|
||||
if (this.playIcon) this.playIcon.classList.add('active');
|
||||
// Update aria-label
|
||||
if (this.autoplayToggle) {
|
||||
this.autoplayToggle.setAttribute('aria-label', '자동 재생 시작');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize hero carousel
|
||||
heroCarousel.init();
|
||||
|
||||
// ========================================
|
||||
// API 검색 기능
|
||||
// ========================================
|
||||
const searchInput = document.getElementById('apiSearchInput');
|
||||
const searchForm = document.querySelector('.search-form');
|
||||
const hashtags = document.querySelectorAll('.hashtag-link');
|
||||
|
||||
// 해시태그 클릭 이벤트
|
||||
hashtags.forEach(tag => {
|
||||
tag.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const searchTerm = this.getAttribute('data-search');
|
||||
if (searchInput) {
|
||||
searchInput.value = searchTerm;
|
||||
}
|
||||
// 폼 제출
|
||||
if (searchForm) {
|
||||
searchForm.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver(animateNumbers, observerOptions);
|
||||
const statsSection = document.querySelector('.api-stats-section');
|
||||
// ========================================
|
||||
// 숫자 카운트업 애니메이션
|
||||
// ========================================
|
||||
const observerOptions = {
|
||||
threshold: 0.5,
|
||||
rootMargin: '0px 0px -100px 0px'
|
||||
};
|
||||
|
||||
if (statsSection) {
|
||||
observer.observe(statsSection);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
const animateNumbers = (entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const numbers = entry.target.querySelectorAll('.stat-number');
|
||||
|
||||
numbers.forEach(number => {
|
||||
const target = parseInt(number.getAttribute('data-target'));
|
||||
const duration = 2000; // 2초
|
||||
const increment = target / (duration / 16);
|
||||
let current = 0;
|
||||
|
||||
const updateNumber = () => {
|
||||
current += increment;
|
||||
if (current < target) {
|
||||
number.textContent = Math.floor(current).toLocaleString('ko-KR');
|
||||
requestAnimationFrame(updateNumber);
|
||||
} else {
|
||||
number.textContent = target.toLocaleString('ko-KR');
|
||||
}
|
||||
};
|
||||
|
||||
updateNumber();
|
||||
});
|
||||
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver(animateNumbers, observerOptions);
|
||||
const statsSection = document.querySelector('.api-stats-section');
|
||||
|
||||
if (statsSection) {
|
||||
observer.observe(statsSection);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
|
||||
</html>
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</section>
|
||||
<section layout:fragment="contentFragment">
|
||||
<div class="service-main app-management-layout">
|
||||
<div class="service-main container" style="padding-top: 70px;">
|
||||
<th:block th:replace="~{fragment/djbank/service_sidebar :: sidebar('password')}"></th:block>
|
||||
<div class="app-management-content">
|
||||
<div class="password-change-wrapper">
|
||||
@@ -24,11 +24,12 @@
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
|
||||
<div class="register-form-container">
|
||||
<div class="info-notice-box">
|
||||
<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 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>
|
||||
<p>소중한 계정 보호를 위해 비밀번호를 변경해 주세요!<br>
|
||||
비밀번호 변경이 완료되면 자동으로 로그아웃되며, 새 비밀번호로 다시 로그인해야 합니다.</p>
|
||||
|
||||
@@ -1,80 +1,84 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/djbank_title_layout}">
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/djbank_title_layout}">
|
||||
|
||||
<body>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>비밀번호 변경</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section layout:fragment="contentFragment">
|
||||
<div class="service-main app-management-layout">
|
||||
<th:block th:replace="~{fragment/djbank/service_sidebar :: sidebar('password')}"></th:block>
|
||||
<div class="app-management-content">
|
||||
<div class="password-change-wrapper">
|
||||
<h2 class="page-outer-title">비밀번호 변경</h2>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>비밀번호 변경</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section layout:fragment="contentFragment">
|
||||
<div class="service-main app-management-layout">
|
||||
<th:block th:replace="~{fragment/djbank/service_sidebar :: sidebar('password')}"></th:block>
|
||||
<div class="app-management-content">
|
||||
<div class="password-change-wrapper">
|
||||
<h2 class="page-outer-title">비밀번호 변경</h2>
|
||||
|
||||
<form th:action="@{/password/verify}" method="post">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||
<form th:action="@{/password/verify}" method="post">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
|
||||
|
||||
<div class="register-form-container">
|
||||
<div class="info-notice-box">
|
||||
<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>
|
||||
<div class="register-form-container">
|
||||
<div class="info-notice-box">
|
||||
<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>
|
||||
<p>비밀번호 변경을 위하여 현재 비밀번호를 입력해 주세요</p>
|
||||
</div>
|
||||
<div class="form-field-wrapper">
|
||||
<input type="password" name="currentPassword" class="form-input"
|
||||
placeholder="비밀번호 입력" required>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-label-wrapper">
|
||||
<span class="form-label-text">현재 비밀번호</span>
|
||||
</div>
|
||||
<div class="form-field-wrapper">
|
||||
<input type="password" name="currentPassword" class="form-input"
|
||||
placeholder="비밀번호 입력" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions" style="justify-content: flex-end;">
|
||||
<div class="right-buttons">
|
||||
<button type="button" class="btn-cancel" th:unless="${forcedPasswordReset}" th:onclick="|location.href='@{/}'|">취소</button>
|
||||
<button type="submit" class="btn-apply btn-primary">확인</button>
|
||||
<div class="form-actions" style="justify-content: flex-end;">
|
||||
<div class="right-buttons">
|
||||
<button type="button" class="btn-cancel" th:unless="${forcedPasswordReset}"
|
||||
th:onclick="|location.href='@{/}'|">취소</button>
|
||||
<button type="submit" class="btn-apply btn-primary">확인</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script th:if="${error}" th:inline="javascript">
|
||||
$(document).ready(function() {
|
||||
customPopups.showAlert([[${error}]]);
|
||||
})
|
||||
</script>
|
||||
<script th:if="${forcedPasswordReset}" th:inline="javascript">
|
||||
// 비밀번호 재설정 강제(ENFORCE): "변경" 또는 "로그아웃"만 선택 가능
|
||||
$(function () {
|
||||
$('#customConfirmCloseButton').hide();
|
||||
$('#customConfirmYesButton').text('변경');
|
||||
$('#customConfirmNoButton').text('로그아웃');
|
||||
customPopups.showConfirm(
|
||||
'계정 보안을 위해 비밀번호 재설정이 필요합니다.<br>비밀번호를 변경하거나 로그아웃해 주세요.',
|
||||
function (selection) {
|
||||
if (selection) {
|
||||
// 변경: 팝업 닫고 현재 페이지(비밀번호 변경)에서 진행
|
||||
$('#customConfirmCloseButton').show();
|
||||
} else {
|
||||
// 로그아웃
|
||||
window.location.href = [[@{/actionLogout.do}]];
|
||||
<script th:if="${error}" th:inline="javascript">
|
||||
$(document).ready(function () {
|
||||
customPopups.showAlert([[${ error }]]);
|
||||
})
|
||||
</script>
|
||||
<script th:if="${forcedPasswordReset}" th:inline="javascript">
|
||||
// 비밀번호 재설정 강제(ENFORCE): "변경" 또는 "로그아웃"만 선택 가능
|
||||
$(function () {
|
||||
$('#customConfirmCloseButton').hide();
|
||||
$('#customConfirmYesButton').text('변경');
|
||||
$('#customConfirmNoButton').text('로그아웃');
|
||||
customPopups.showConfirm(
|
||||
'계정 보안을 위해 비밀번호 재설정이 필요합니다.<br>비밀번호를 변경하거나 로그아웃해 주세요.',
|
||||
function (selection) {
|
||||
if (selection) {
|
||||
// 변경: 팝업 닫고 현재 페이지(비밀번호 변경)에서 진행
|
||||
$('#customConfirmCloseButton').show();
|
||||
} else {
|
||||
// 로그아웃
|
||||
window.location.href = [[@{/ actionLogout.do}]];
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
</script>
|
||||
</section>
|
||||
</script>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -9,34 +9,49 @@
|
||||
</div>
|
||||
</section>
|
||||
<section layout:fragment="contentFragment">
|
||||
<div class="org-register-container">
|
||||
<div class="corp-manager-wrapper">
|
||||
<div class="common-title-bar">
|
||||
<h2 class="common-title">기본 정보</h2>
|
||||
</div>
|
||||
<div class="register-form-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">
|
||||
<h2 class="page-outer-title">정보 관리</h2>
|
||||
|
||||
<form id="updateForm" method="post" th:action="@{/mypage/update}">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||
<div class="register-form">
|
||||
<div class="form-row">
|
||||
<div class="form-label-wrapper">
|
||||
<span class="form-label-text">소속기관</span>
|
||||
</div>
|
||||
<div class="form-field-wrapper">
|
||||
<input type="text" th:value="${user.portalOrg.orgName}" name="organization"
|
||||
class="form-input input-readonly info-value-box" placeholder="소속기관" disabled="disabled">
|
||||
</div>
|
||||
|
||||
<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="form-row">
|
||||
<div class="form-label-wrapper">
|
||||
<span class="form-label-text">소속기관</span>
|
||||
</div>
|
||||
<div class="form-field-wrapper">
|
||||
<input type="text" th:value="${user.portalOrg.orgName}" name="organization"
|
||||
class="form-input input-readonly" placeholder="소속기관" disabled="disabled">
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:replace="~{apps/mypage/components/commonUserInfo :: commonUserInfo}"></th:block>
|
||||
</div>
|
||||
<th:block th:replace="~{apps/mypage/components/commonUserInfo :: commonUserInfo}"></th:block>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- Action Buttons -->
|
||||
<div class="form-actions form-actions--with-withdrawal">
|
||||
<a class="withdrawal-link"><img th:src="@{/img/btn_withdrawal.png}" alt="회원탈퇴">회원탈퇴</a>
|
||||
<div class="form-actions-buttons">
|
||||
<button type="button" class="btn btn-submit btn-secondary" th:onclick="|location.href='@{/}'|">취소</button>
|
||||
<button type="button" class="btn btn-submit btn-primary submit-btn">수정 적용</button>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="form-actions">
|
||||
<a class="withdrawal-link btn-withdrawal">회원탈퇴</a>
|
||||
<div class="right-buttons">
|
||||
<button type="button" class="btn-cancel" th:onclick="|location.href='@{/}'|">취소</button>
|
||||
<button type="button" class="btn-apply btn-primary submit-btn">수정</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,524 +1,529 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/djbank_title_layout}">
|
||||
<html lang="ko" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/djbank_title_layout}">
|
||||
|
||||
<body>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" alt="법인회원가입" class="title-image">
|
||||
<h1>법인회원가입</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" alt="법인회원가입" class="title-image">
|
||||
<h1>법인회원가입</h1>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section layout:fragment="contentFragment">
|
||||
<section layout:fragment="contentFragment">
|
||||
|
||||
|
||||
<div class="org-register-page corporate-register">
|
||||
<!-- Page Title Banner -->
|
||||
<div class="org-register-page corporate-register">
|
||||
<!-- Page Title Banner -->
|
||||
|
||||
<div class="org-register-container">
|
||||
<!-- Hidden Fields -->
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||
<input type="hidden" name="registrationType" th:value="${registrationType}"/>
|
||||
<div class="org-register-container">
|
||||
<!-- Hidden Fields -->
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
|
||||
<input type="hidden" name="registrationType" th:value="${registrationType}" />
|
||||
|
||||
<!-- Alert Container -->
|
||||
<div id="alertContainer"></div>
|
||||
|
||||
<!-- Registration Card Wrapper -->
|
||||
<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>
|
||||
|
||||
<!-- Agreement Section -->
|
||||
<th:block th:replace="~{apps/register/userAgreementContent :: agreementContent(${termsOfUse}, ${privacyCollect})}"></th:block>
|
||||
|
||||
<form name="portalOrg" id="registerForm" role="form" th:action="@{/signup/portalOrg}"
|
||||
th:object="${portalOrg}" method="post">
|
||||
|
||||
<!-- Corporate Basic Information Section -->
|
||||
<div class="org-section-header org-section-header--agreement">
|
||||
<h3>법인 기본 정보</h3>
|
||||
<span class="required-badge">필수 입력</span>
|
||||
</div>
|
||||
<th:block th:replace="~{apps/register/components/orgBasicInfoForm :: orgInfoForm}"></th:block>
|
||||
|
||||
<!-- Corporate Admin Information Section -->
|
||||
<div class="org-section-header org-section-header--agreement" style="margin-top: 48px;">
|
||||
<h3>법인 관리자 정보</h3>
|
||||
<span class="required-badge">필수 입력</span>
|
||||
</div>
|
||||
<!-- Alert Container -->
|
||||
<div id="alertContainer"></div>
|
||||
|
||||
<!-- Registration Card Wrapper -->
|
||||
<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">
|
||||
<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>
|
||||
<p class="notice-text">법인 회원 가입 후 서비스 또는 API 이용을 하실 수 있습니다.</p>
|
||||
</div>
|
||||
|
||||
<th:block th:if="${registrationType == 'corporate'}">
|
||||
<th:block th:replace="~{apps/register/components/orgUserInfoForm :: orgUserInfoForm}"></th:block>
|
||||
<!-- Agreement Section -->
|
||||
<th:block
|
||||
th:replace="~{apps/register/userAgreementContent :: agreementContent(${termsOfUse}, ${privacyCollect})}">
|
||||
</th:block>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="org-action-buttons">
|
||||
<button type="button" class="btn btn-secondary" id="cancelButton">취소</button>
|
||||
<button type="button" class="btn btn-primary btn_register">가입신청</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<form name="portalOrg" id="registerForm" role="form" th:action="@{/signup/portalOrg}" th:object="${portalOrg}"
|
||||
method="post">
|
||||
|
||||
<!-- Loading Overlay -->
|
||||
<div class="org-loading-overlay" id="loadingOverlay">
|
||||
<div class="spinner"></div>
|
||||
<!-- Corporate Basic Information Section -->
|
||||
<div class="org-section-header org-section-header--agreement">
|
||||
<h3>법인 기본 정보</h3>
|
||||
<span class="required-badge">필수 입력</span>
|
||||
</div>
|
||||
<th:block th:replace="~{apps/register/components/orgBasicInfoForm :: orgInfoForm}"></th:block>
|
||||
|
||||
<!-- Corporate Admin Information Section -->
|
||||
<div class="org-section-header org-section-header--agreement" style="margin-top: 48px;">
|
||||
<h3>법인 관리자 정보</h3>
|
||||
<span class="required-badge">필수 입력</span>
|
||||
</div>
|
||||
|
||||
<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:if="${registrationType == 'corporate'}">
|
||||
<th:block th:replace="~{apps/register/components/orgUserInfoForm :: orgUserInfoForm}"></th:block>
|
||||
</th:block>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="org-action-buttons">
|
||||
<button type="button" class="btn btn-secondary" id="cancelButton">취소</button>
|
||||
<button type="button" class="btn btn-primary btn_register">가입신청</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Loading Overlay -->
|
||||
<div class="org-loading-overlay" id="loadingOverlay">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script th:if="${error}" th:inline="javascript">
|
||||
$(document).ready(function () {
|
||||
customPopups.showAlert([[${error}]]);
|
||||
});
|
||||
</script>
|
||||
<script th:replace="~{apps/register/userAgreementContent :: agreementScript}"></script>
|
||||
<script th:replace="~{apps/register/components/orgBasicInfoForm :: orgInfoScript}"></script>
|
||||
<script th:replace="~{apps/register/components/orgUserInfoForm :: orgUserInfoScript}"></script>
|
||||
<script th:replace="~{apps/register/components/emailChangeForm :: emailChangeScript}"></script>
|
||||
<script th:replace="~{apps/register/components/newUserInfoForm :: newUserScript}"></script>
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
let form = document.getElementById('registerForm');
|
||||
let agreementForm = document.getElementById('agreementForm');
|
||||
let btn_register = document.querySelector('.btn_register');
|
||||
let isAuthVerified = false;
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script th:if="${error}" th:inline="javascript">
|
||||
$(document).ready(function () {
|
||||
customPopups.showAlert([[${ error }]]);
|
||||
});
|
||||
</script>
|
||||
<script th:replace="~{apps/register/userAgreementContent :: agreementScript}"></script>
|
||||
<script th:replace="~{apps/register/components/orgBasicInfoForm :: orgInfoScript}"></script>
|
||||
<script th:replace="~{apps/register/components/orgUserInfoForm :: orgUserInfoScript}"></script>
|
||||
<script th:replace="~{apps/register/components/emailChangeForm :: emailChangeScript}"></script>
|
||||
<script th:replace="~{apps/register/components/newUserInfoForm :: newUserScript}"></script>
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
let form = document.getElementById('registerForm');
|
||||
let agreementForm = document.getElementById('agreementForm');
|
||||
let btn_register = document.querySelector('.btn_register');
|
||||
let isAuthVerified = false;
|
||||
|
||||
// registrationScenario를 hidden input에서 가져오도록 수정
|
||||
let registrationScenario = document.getElementById('registrationScenario')?.value || 'new';
|
||||
// registrationScenario를 hidden input에서 가져오도록 수정
|
||||
let registrationScenario = document.getElementById('registrationScenario')?.value || 'new';
|
||||
|
||||
// hidden input의 값이 변경되면 registrationScenario 변수도 업데이트
|
||||
const scenarioInput = document.getElementById('registrationScenario');
|
||||
if (scenarioInput) {
|
||||
scenarioInput.addEventListener('change', function () {
|
||||
registrationScenario = this.value;
|
||||
console.log('Registration Scenario Updated:', registrationScenario);
|
||||
});
|
||||
|
||||
// MutationObserver를 사용하여 값 변경 감지
|
||||
const observer = new MutationObserver(function (mutations) {
|
||||
mutations.forEach(function (mutation) {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'value') {
|
||||
registrationScenario = scenarioInput.value;
|
||||
console.log('Registration Scenario Updated (from mutation):', registrationScenario);
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(scenarioInput, {attributes: true});
|
||||
}
|
||||
|
||||
// 시나리오별 필수 필드 정의
|
||||
const requiredFieldsByScenario = {
|
||||
new: {
|
||||
user: ['loginId', 'userName', 'password', 'password2', 'mobileNumber', 'authNumber'],
|
||||
org: ['compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files']
|
||||
},
|
||||
retain: {
|
||||
user: ['loginId', 'passwordConfirmIndividual'],
|
||||
org: ['compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files']
|
||||
},
|
||||
change: {
|
||||
user: ['loginId', 'passwordConfirmEmailChange', 'newLoginId'],
|
||||
org: ['compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files']
|
||||
}
|
||||
};
|
||||
|
||||
// 제출 대상 org 필드 (검증 필수목록과 별개 - 선택입력 포함 전 필드 전송)
|
||||
// 제외: ipWhitelist(가입 미입력), orgCode(관리자/시스템 부여)
|
||||
const submitOrgFields = [
|
||||
'compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files',
|
||||
'ceoName', 'orgAddr', 'serviceName', 'orgPhoneNumber', 'scPhoneNumber',
|
||||
'orgSectors', 'orgIndustryType'
|
||||
];
|
||||
|
||||
// 이메일 유효성 검사 함수
|
||||
function isValidEmail(email) {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
}
|
||||
|
||||
function collectFormData() {
|
||||
const form = document.createElement('form');
|
||||
form.enctype = 'multipart/form-data';
|
||||
form.method = 'POST';
|
||||
form.action = '/signup/portalOrg';
|
||||
form.style.display = 'none';
|
||||
|
||||
const fields = requiredFieldsByScenario[registrationScenario];
|
||||
|
||||
if (!fields) {
|
||||
console.error('Unknown scenario');
|
||||
return form;
|
||||
}
|
||||
|
||||
// 시나리오 값 추가
|
||||
// hidden input의 값이 변경되면 registrationScenario 변수도 업데이트
|
||||
const scenarioInput = document.getElementById('registrationScenario');
|
||||
if (scenarioInput) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'registrationScenario';
|
||||
input.value = scenarioInput.value;
|
||||
form.appendChild(input);
|
||||
} else {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'registrationScenario';
|
||||
input.value = registrationScenario;
|
||||
form.appendChild(input);
|
||||
scenarioInput.addEventListener('change', function () {
|
||||
registrationScenario = this.value;
|
||||
console.log('Registration Scenario Updated:', registrationScenario);
|
||||
});
|
||||
|
||||
// MutationObserver를 사용하여 값 변경 감지
|
||||
const observer = new MutationObserver(function (mutations) {
|
||||
mutations.forEach(function (mutation) {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'value') {
|
||||
registrationScenario = scenarioInput.value;
|
||||
console.log('Registration Scenario Updated (from mutation):', registrationScenario);
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(scenarioInput, { attributes: true });
|
||||
}
|
||||
|
||||
// user와 org 필드를 따로 처리
|
||||
fields.user.forEach(fieldId => {
|
||||
const element = document.getElementById(fieldId);
|
||||
if (element) {
|
||||
// 시나리오별 필수 필드 정의
|
||||
const requiredFieldsByScenario = {
|
||||
new: {
|
||||
user: ['loginId', 'userName', 'password', 'password2', 'mobileNumber', 'authNumber'],
|
||||
org: ['compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files']
|
||||
},
|
||||
retain: {
|
||||
user: ['loginId', 'passwordConfirmIndividual'],
|
||||
org: ['compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files']
|
||||
},
|
||||
change: {
|
||||
user: ['loginId', 'passwordConfirmEmailChange', 'newLoginId'],
|
||||
org: ['compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files']
|
||||
}
|
||||
};
|
||||
|
||||
// 제출 대상 org 필드 (검증 필수목록과 별개 - 선택입력 포함 전 필드 전송)
|
||||
// 제외: ipWhitelist(가입 미입력), orgCode(관리자/시스템 부여)
|
||||
const submitOrgFields = [
|
||||
'compRegNo', 'corpRegNo', 'orgName', 'compRegFile', 'files',
|
||||
'ceoName', 'orgAddr', 'serviceName', 'orgPhoneNumber', 'scPhoneNumber',
|
||||
'orgSectors', 'orgIndustryType'
|
||||
];
|
||||
|
||||
// 이메일 유효성 검사 함수
|
||||
function isValidEmail(email) {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
}
|
||||
|
||||
function collectFormData() {
|
||||
const form = document.createElement('form');
|
||||
form.enctype = 'multipart/form-data';
|
||||
form.method = 'POST';
|
||||
form.action = '/signup/portalOrg';
|
||||
form.style.display = 'none';
|
||||
|
||||
const fields = requiredFieldsByScenario[registrationScenario];
|
||||
|
||||
if (!fields) {
|
||||
console.error('Unknown scenario');
|
||||
return form;
|
||||
}
|
||||
|
||||
// 시나리오 값 추가
|
||||
const scenarioInput = document.getElementById('registrationScenario');
|
||||
if (scenarioInput) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = fieldId;
|
||||
input.value = element.value;
|
||||
input.name = 'registrationScenario';
|
||||
input.value = scenarioInput.value;
|
||||
form.appendChild(input);
|
||||
} else {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'registrationScenario';
|
||||
input.value = registrationScenario;
|
||||
form.appendChild(input);
|
||||
}
|
||||
});
|
||||
|
||||
submitOrgFields.forEach(fieldId => {
|
||||
const element = document.getElementById(fieldId);
|
||||
if (element) {
|
||||
if (element.type === 'file') {
|
||||
const files = element.files;
|
||||
if (files.length > 0) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.name = fieldId;
|
||||
input.files = files;
|
||||
form.appendChild(input);
|
||||
}
|
||||
} else {
|
||||
// user와 org 필드를 따로 처리
|
||||
fields.user.forEach(fieldId => {
|
||||
const element = document.getElementById(fieldId);
|
||||
if (element) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = fieldId;
|
||||
input.value = element.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Add confirmPassword manually based on the scenario
|
||||
if (registrationScenario === 'retain') {
|
||||
const passwordConfirmIndividual = document.getElementById('passwordConfirmIndividual');
|
||||
if (passwordConfirmIndividual) {
|
||||
submitOrgFields.forEach(fieldId => {
|
||||
const element = document.getElementById(fieldId);
|
||||
if (element) {
|
||||
if (element.type === 'file') {
|
||||
const files = element.files;
|
||||
if (files.length > 0) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.name = fieldId;
|
||||
input.files = files;
|
||||
form.appendChild(input);
|
||||
}
|
||||
} else {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = fieldId;
|
||||
input.value = element.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add confirmPassword manually based on the scenario
|
||||
if (registrationScenario === 'retain') {
|
||||
const passwordConfirmIndividual = document.getElementById('passwordConfirmIndividual');
|
||||
if (passwordConfirmIndividual) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'confirmPassword';
|
||||
input.value = passwordConfirmIndividual.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
} else if (registrationScenario === 'change') {
|
||||
const passwordConfirmEmailChange = document.getElementById('passwordConfirmEmailChange');
|
||||
if (passwordConfirmEmailChange) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'confirmPassword';
|
||||
input.value = passwordConfirmEmailChange.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
}
|
||||
|
||||
// 공통 필드 추가
|
||||
if (document.getElementById('termsOfUse')) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'confirmPassword';
|
||||
input.value = passwordConfirmIndividual.value;
|
||||
input.name = 'termsOfUse';
|
||||
input.value = document.getElementById('termsOfUse').checked;
|
||||
form.appendChild(input);
|
||||
}
|
||||
} else if (registrationScenario === 'change') {
|
||||
const passwordConfirmEmailChange = document.getElementById('passwordConfirmEmailChange');
|
||||
if (passwordConfirmEmailChange) {
|
||||
|
||||
if (document.getElementById('privacyCollect')) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'confirmPassword';
|
||||
input.value = passwordConfirmEmailChange.value;
|
||||
input.name = 'privacyCollect';
|
||||
input.value = document.getElementById('privacyCollect').checked;
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
if (document.getElementById('notificationConsent')) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'notificationConsent';
|
||||
input.value = document.getElementById('notificationConsent').checked;
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
// 시스템 필드 추가
|
||||
const csrfToken = document.querySelector('input[name="_csrf"]');
|
||||
if (csrfToken) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = '_csrf';
|
||||
input.value = csrfToken.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
const registrationType = document.querySelector('input[name="registrationType"]');
|
||||
if (registrationType) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'registrationType';
|
||||
input.value = registrationType.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
console.log('Collected Form Data for scenario:',
|
||||
document.getElementById('registrationScenario')?.value || registrationScenario);
|
||||
return form;
|
||||
}
|
||||
|
||||
// 시나리오별 유효성 검사
|
||||
function validateFormByScenario() {
|
||||
|
||||
const currentScenario = document.getElementById('registrationScenario')?.value || 'new';
|
||||
console.log('Registration Scenario:', currentScenario);
|
||||
|
||||
if (!currentScenario) {
|
||||
console.log('Unknown scenario');
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (registrationScenario) {
|
||||
case 'new':
|
||||
const loginIdElement = document.getElementById('loginId');
|
||||
const userNameElement = document.getElementById('userName');
|
||||
|
||||
const isEmailValid = loginIdElement ? isValidEmail(loginIdElement.value) : false;
|
||||
const hasUserName = userNameElement ? userNameElement.value.trim() !== '' : false;
|
||||
const isPasswordValid = document.getElementById('isPasswordValid').value.trim() === 'true';
|
||||
const isPasswordMatch = document.getElementById('isPasswordMatch').value.trim() === 'true';
|
||||
|
||||
console.log('New User Validation:', {
|
||||
email: loginIdElement?.value,
|
||||
isEmailValid,
|
||||
isPasswordValid,
|
||||
isPasswordMatch,
|
||||
userName: userNameElement?.value,
|
||||
hasUserName,
|
||||
isAuthVerified,
|
||||
requiredFields: currentScenario
|
||||
});
|
||||
return isEmailValid && isPasswordValid && isPasswordMatch && hasUserName && isAuthVerified;
|
||||
|
||||
case 'retain':
|
||||
const passwordConfirmElement = document.getElementById('passwordConfirmIndividual');
|
||||
const hasPassword = passwordConfirmElement ? passwordConfirmElement.value.length >= 8 : false;
|
||||
const retainLoginIdElement = document.getElementById('loginId');
|
||||
|
||||
console.log('Retain User Validation:', {
|
||||
email: retainLoginIdElement?.value,
|
||||
isEmailValid: retainLoginIdElement ? isValidEmail(retainLoginIdElement.value) : false,
|
||||
passwordLength: passwordConfirmElement?.value.length,
|
||||
hasPassword,
|
||||
requiredFields: currentScenario
|
||||
});
|
||||
return retainLoginIdElement && isValidEmail(retainLoginIdElement.value) && hasPassword;
|
||||
|
||||
case 'change':
|
||||
const changeLoginIdElement = document.getElementById('loginId');
|
||||
const newLoginIdElement = document.getElementById('newLoginId');
|
||||
const changePasswordElement = document.getElementById('passwordConfirmEmailChange');
|
||||
const hasChangePassword = changePasswordElement ? changePasswordElement.value.length >= 8 : false;
|
||||
|
||||
console.log('Change Email Validation:', {
|
||||
currentEmail: changeLoginIdElement?.value,
|
||||
newEmail: newLoginIdElement?.value,
|
||||
hasPassword: hasChangePassword,
|
||||
requiredFields: currentScenario
|
||||
});
|
||||
return changeLoginIdElement && newLoginIdElement &&
|
||||
isValidEmail(changeLoginIdElement.value) &&
|
||||
hasChangePassword &&
|
||||
isValidEmail(newLoginIdElement.value);
|
||||
|
||||
default:
|
||||
console.log('Unknown scenario');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 공통 필드 추가
|
||||
if (document.getElementById('termsOfUse')) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'termsOfUse';
|
||||
input.value = document.getElementById('termsOfUse').checked;
|
||||
form.appendChild(input);
|
||||
// 공통 필드 유효성 검사
|
||||
function validateCommonFields() {
|
||||
|
||||
if (!validatePhoneNumber('org') || !validatePhoneNumber('sc')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const notificationConsentEl = document.getElementById('notificationConsent');
|
||||
const validations = {
|
||||
termsOfUse: $('#termsOfUse').prop('checked'),
|
||||
privacyPolicy: $('#privacyCollect').prop('checked'),
|
||||
notificationConsent: !notificationConsentEl || notificationConsentEl.checked,
|
||||
compRegNo: $('#compRegNo').val().trim() !== '',
|
||||
corpRegNo: $('#corpRegNo').val().trim() !== '',
|
||||
orgName: $('#orgName').val().trim() !== '',
|
||||
compRegFile: $('#compRegFile').val().trim() !== ''
|
||||
};
|
||||
|
||||
console.log('Common Fields Validation:', validations);
|
||||
return Object.values(validations).every(value => value === true);
|
||||
}
|
||||
|
||||
if (document.getElementById('privacyCollect')) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'privacyCollect';
|
||||
input.value = document.getElementById('privacyCollect').checked;
|
||||
form.appendChild(input);
|
||||
// 전체 폼 유효성 검사
|
||||
function validateForm() {
|
||||
const scenarioValidation = validateFormByScenario();
|
||||
const commonValidation = validateCommonFields();
|
||||
|
||||
console.log('Form validation result:', {
|
||||
scenarioValidation,
|
||||
commonValidation,
|
||||
registrationScenario
|
||||
});
|
||||
|
||||
return scenarioValidation && commonValidation;
|
||||
}
|
||||
|
||||
if (document.getElementById('notificationConsent')) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'notificationConsent';
|
||||
input.value = document.getElementById('notificationConsent').checked;
|
||||
form.appendChild(input);
|
||||
}
|
||||
// 미입력/미충족 항목을 구체적으로 수집
|
||||
function collectFormErrors() {
|
||||
const errors = [];
|
||||
|
||||
// 시스템 필드 추가
|
||||
const csrfToken = document.querySelector('input[name="_csrf"]');
|
||||
if (csrfToken) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = '_csrf';
|
||||
input.value = csrfToken.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
const registrationType = document.querySelector('input[name="registrationType"]');
|
||||
if (registrationType) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = 'registrationType';
|
||||
input.value = registrationType.value;
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
console.log('Collected Form Data for scenario:',
|
||||
document.getElementById('registrationScenario')?.value || registrationScenario);
|
||||
return form;
|
||||
}
|
||||
|
||||
// 시나리오별 유효성 검사
|
||||
function validateFormByScenario() {
|
||||
|
||||
const currentScenario = document.getElementById('registrationScenario')?.value || 'new';
|
||||
console.log('Registration Scenario:', currentScenario);
|
||||
|
||||
if (!currentScenario) {
|
||||
console.log('Unknown scenario');
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (registrationScenario) {
|
||||
case 'new':
|
||||
// 시나리오별 항목
|
||||
if (registrationScenario === 'new') {
|
||||
const loginIdElement = document.getElementById('loginId');
|
||||
const userNameElement = document.getElementById('userName');
|
||||
|
||||
const isEmailValid = loginIdElement ? isValidEmail(loginIdElement.value) : false;
|
||||
const hasUserName = userNameElement ? userNameElement.value.trim() !== '' : false;
|
||||
const isPasswordValid = document.getElementById('isPasswordValid').value.trim() === 'true';
|
||||
const isPasswordMatch = document.getElementById('isPasswordMatch').value.trim() === 'true';
|
||||
|
||||
console.log('New User Validation:', {
|
||||
email: loginIdElement?.value,
|
||||
isEmailValid,
|
||||
isPasswordValid,
|
||||
isPasswordMatch,
|
||||
userName: userNameElement?.value,
|
||||
hasUserName,
|
||||
isAuthVerified,
|
||||
requiredFields: currentScenario
|
||||
});
|
||||
return isEmailValid && isPasswordValid && isPasswordMatch && hasUserName && isAuthVerified;
|
||||
|
||||
case 'retain':
|
||||
const passwordConfirmElement = document.getElementById('passwordConfirmIndividual');
|
||||
const hasPassword = passwordConfirmElement ? passwordConfirmElement.value.length >= 8 : false;
|
||||
const retainLoginIdElement = document.getElementById('loginId');
|
||||
|
||||
console.log('Retain User Validation:', {
|
||||
email: retainLoginIdElement?.value,
|
||||
isEmailValid: retainLoginIdElement ? isValidEmail(retainLoginIdElement.value) : false,
|
||||
passwordLength: passwordConfirmElement?.value.length,
|
||||
hasPassword,
|
||||
requiredFields: currentScenario
|
||||
});
|
||||
return retainLoginIdElement && isValidEmail(retainLoginIdElement.value) && hasPassword;
|
||||
|
||||
case 'change':
|
||||
const changeLoginIdElement = document.getElementById('loginId');
|
||||
const newLoginIdElement = document.getElementById('newLoginId');
|
||||
const changePasswordElement = document.getElementById('passwordConfirmEmailChange');
|
||||
const hasChangePassword = changePasswordElement ? changePasswordElement.value.length >= 8 : false;
|
||||
|
||||
console.log('Change Email Validation:', {
|
||||
currentEmail: changeLoginIdElement?.value,
|
||||
newEmail: newLoginIdElement?.value,
|
||||
hasPassword: hasChangePassword,
|
||||
requiredFields: currentScenario
|
||||
});
|
||||
return changeLoginIdElement && newLoginIdElement &&
|
||||
isValidEmail(changeLoginIdElement.value) &&
|
||||
hasChangePassword &&
|
||||
isValidEmail(newLoginIdElement.value);
|
||||
|
||||
default:
|
||||
console.log('Unknown scenario');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 공통 필드 유효성 검사
|
||||
function validateCommonFields() {
|
||||
|
||||
if(!validatePhoneNumber('org') || !validatePhoneNumber('sc')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const notificationConsentEl = document.getElementById('notificationConsent');
|
||||
const validations = {
|
||||
termsOfUse: $('#termsOfUse').prop('checked'),
|
||||
privacyPolicy: $('#privacyCollect').prop('checked'),
|
||||
notificationConsent: !notificationConsentEl || notificationConsentEl.checked,
|
||||
compRegNo: $('#compRegNo').val().trim() !== '',
|
||||
corpRegNo: $('#corpRegNo').val().trim() !== '',
|
||||
orgName: $('#orgName').val().trim() !== '',
|
||||
compRegFile: $('#compRegFile').val().trim() !== ''
|
||||
};
|
||||
|
||||
console.log('Common Fields Validation:', validations);
|
||||
return Object.values(validations).every(value => value === true);
|
||||
}
|
||||
|
||||
// 전체 폼 유효성 검사
|
||||
function validateForm() {
|
||||
const scenarioValidation = validateFormByScenario();
|
||||
const commonValidation = validateCommonFields();
|
||||
|
||||
console.log('Form validation result:', {
|
||||
scenarioValidation,
|
||||
commonValidation,
|
||||
registrationScenario
|
||||
});
|
||||
|
||||
return scenarioValidation && commonValidation;
|
||||
}
|
||||
|
||||
// 미입력/미충족 항목을 구체적으로 수집
|
||||
function collectFormErrors() {
|
||||
const errors = [];
|
||||
|
||||
// 시나리오별 항목
|
||||
if (registrationScenario === 'new') {
|
||||
const loginIdElement = document.getElementById('loginId');
|
||||
const userNameElement = document.getElementById('userName');
|
||||
|
||||
if (!(loginIdElement && isValidEmail(loginIdElement.value))) errors.push('이메일 아이디를 올바르게 입력해주세요.');
|
||||
if (!(userNameElement && userNameElement.value.trim() !== '')) errors.push('성명을 입력해주세요.');
|
||||
if (!isAuthVerified) errors.push('휴대폰 인증을 완료해주세요.');
|
||||
if (document.getElementById('isPasswordValid')?.value.trim() !== 'true') errors.push('비밀번호 조건을 확인해주세요.');
|
||||
if (document.getElementById('isPasswordMatch')?.value.trim() !== 'true') errors.push('비밀번호 확인이 일치하지 않습니다.');
|
||||
}
|
||||
|
||||
// 공통 항목
|
||||
const notificationConsentEl = document.getElementById('notificationConsent');
|
||||
if ($('#orgName').val().trim() === '') errors.push('회사명을 입력해주세요.');
|
||||
if ($('#compRegNo').val().trim() === '') errors.push('사업자등록번호를 올바르게 입력해주세요.');
|
||||
if ($('#corpRegNo').val().trim() === '') errors.push('법인등록번호를 올바르게 입력해주세요.');
|
||||
if ($('#compRegFile').val().trim() === '') errors.push('사업자등록증 파일을 첨부해주세요.');
|
||||
if (!$('#termsOfUse').prop('checked')) errors.push('이용약관에 동의해주세요.');
|
||||
if (!$('#privacyCollect').prop('checked')) errors.push('개인정보 수집·이용에 동의해주세요.');
|
||||
if (notificationConsentEl && !notificationConsentEl.checked) errors.push('알림 수신에 동의해주세요.');
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
let isSubmitting = false;
|
||||
|
||||
// 등록 버튼 클릭 이벤트
|
||||
btn_register.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Prevent resubmission
|
||||
if (isSubmitting) {
|
||||
console.log('Form is already being submitted...');
|
||||
return;
|
||||
}
|
||||
|
||||
isSubmitting = true;
|
||||
btn_register.disabled = true;
|
||||
|
||||
// Show loading overlay
|
||||
document.getElementById('loadingOverlay').classList.add('active');
|
||||
|
||||
try {
|
||||
form.classList.add('was-validated');
|
||||
if (agreementForm) {
|
||||
agreementForm.classList.add('was-validated');
|
||||
if (!(loginIdElement && isValidEmail(loginIdElement.value))) errors.push('이메일 아이디를 올바르게 입력해주세요.');
|
||||
if (!(userNameElement && userNameElement.value.trim() !== '')) errors.push('성명을 입력해주세요.');
|
||||
if (!isAuthVerified) errors.push('휴대폰 인증을 완료해주세요.');
|
||||
if (document.getElementById('isPasswordValid')?.value.trim() !== 'true') errors.push('비밀번호 조건을 확인해주세요.');
|
||||
if (document.getElementById('isPasswordMatch')?.value.trim() !== 'true') errors.push('비밀번호 확인이 일치하지 않습니다.');
|
||||
}
|
||||
|
||||
console.log('Validating form...');
|
||||
// 공통 항목
|
||||
const notificationConsentEl = document.getElementById('notificationConsent');
|
||||
if ($('#orgName').val().trim() === '') errors.push('회사명을 입력해주세요.');
|
||||
if ($('#compRegNo').val().trim() === '') errors.push('사업자등록번호를 올바르게 입력해주세요.');
|
||||
if ($('#corpRegNo').val().trim() === '') errors.push('법인등록번호를 올바르게 입력해주세요.');
|
||||
if ($('#compRegFile').val().trim() === '') errors.push('사업자등록증 파일을 첨부해주세요.');
|
||||
if (!$('#termsOfUse').prop('checked')) errors.push('이용약관에 동의해주세요.');
|
||||
if (!$('#privacyCollect').prop('checked')) errors.push('개인정보 수집·이용에 동의해주세요.');
|
||||
if (notificationConsentEl && !notificationConsentEl.checked) errors.push('알림 수신에 동의해주세요.');
|
||||
|
||||
if (validateForm()) {
|
||||
console.log('Form validation passed, collecting form data...');
|
||||
const form = collectFormData();
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
} else {
|
||||
console.log('Form validation failed');
|
||||
return errors;
|
||||
}
|
||||
|
||||
// 현재 상태 출력
|
||||
const scenarioValidation = validateFormByScenario();
|
||||
const commonValidation = validateCommonFields();
|
||||
let isSubmitting = false;
|
||||
|
||||
const isPasswordValid = document.getElementById('isPasswordValid')?.value.trim() === 'true';
|
||||
const isPasswordMatch = document.getElementById('isPasswordMatch')?.value.trim() === 'true';
|
||||
// 등록 버튼 클릭 이벤트
|
||||
btn_register.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
console.log('Validation details:', {
|
||||
scenarioValidation,
|
||||
commonValidation,
|
||||
registrationScenario,
|
||||
isAuthVerified,
|
||||
isPasswordValid,
|
||||
isPasswordMatch
|
||||
});
|
||||
// Prevent resubmission
|
||||
if (isSubmitting) {
|
||||
console.log('Form is already being submitted...');
|
||||
return;
|
||||
}
|
||||
|
||||
const errors = collectFormErrors();
|
||||
let errorMessage = errors.length > 0
|
||||
? '아래 항목을 확인해주세요.<br><br>' + errors.map(e => '• ' + e).join('<br>')
|
||||
: '모든 필수 항목을 입력하고 약관에 동의해주세요.';
|
||||
customPopups.showAlert(errorMessage);
|
||||
isSubmitting = true;
|
||||
btn_register.disabled = true;
|
||||
|
||||
// Reset submission state since validation failed
|
||||
// Show loading overlay
|
||||
document.getElementById('loadingOverlay').classList.add('active');
|
||||
|
||||
try {
|
||||
form.classList.add('was-validated');
|
||||
if (agreementForm) {
|
||||
agreementForm.classList.add('was-validated');
|
||||
}
|
||||
|
||||
console.log('Validating form...');
|
||||
|
||||
if (validateForm()) {
|
||||
console.log('Form validation passed, collecting form data...');
|
||||
const form = collectFormData();
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
} else {
|
||||
console.log('Form validation failed');
|
||||
|
||||
// 현재 상태 출력
|
||||
const scenarioValidation = validateFormByScenario();
|
||||
const commonValidation = validateCommonFields();
|
||||
|
||||
const isPasswordValid = document.getElementById('isPasswordValid')?.value.trim() === 'true';
|
||||
const isPasswordMatch = document.getElementById('isPasswordMatch')?.value.trim() === 'true';
|
||||
|
||||
console.log('Validation details:', {
|
||||
scenarioValidation,
|
||||
commonValidation,
|
||||
registrationScenario,
|
||||
isAuthVerified,
|
||||
isPasswordValid,
|
||||
isPasswordMatch
|
||||
});
|
||||
|
||||
const errors = collectFormErrors();
|
||||
let errorMessage = errors.length > 0
|
||||
? '아래 항목을 확인해주세요.<br><br>' + errors.map(e => '• ' + e).join('<br>')
|
||||
: '모든 필수 항목을 입력하고 약관에 동의해주세요.';
|
||||
customPopups.showAlert(errorMessage);
|
||||
|
||||
// Reset submission state since validation failed
|
||||
isSubmitting = false;
|
||||
btn_register.disabled = false;
|
||||
document.getElementById('loadingOverlay').classList.remove('active');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Form submission error:', error);
|
||||
// Reset submission state on error
|
||||
isSubmitting = false;
|
||||
btn_register.disabled = false;
|
||||
document.getElementById('loadingOverlay').classList.remove('active');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Form submission error:', error);
|
||||
// Reset submission state on error
|
||||
isSubmitting = false;
|
||||
btn_register.disabled = false;
|
||||
document.getElementById('loadingOverlay').classList.remove('active');
|
||||
});
|
||||
|
||||
// 신규 이메일 중복 체크 응답 처리 함수
|
||||
function handleNewEmailValidationResponse(response) {
|
||||
if (response.valid) {
|
||||
customPopups.showAlert(response.message || '신규 이메일 정보입니다.');
|
||||
} else {
|
||||
customPopups.showAlert(response.message || '이미 사용 중인 이메일입니다.');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 신규 이메일 중복 체크 응답 처리 함수
|
||||
function handleNewEmailValidationResponse(response) {
|
||||
if (response.valid) {
|
||||
customPopups.showAlert(response.message || '신규 이메일 정보입니다.');
|
||||
} else {
|
||||
customPopups.showAlert(response.message || '이미 사용 중인 이메일입니다.');
|
||||
}
|
||||
}
|
||||
// 인증 완료 이벤트 리스너
|
||||
document.addEventListener('authVerified', function () {
|
||||
isAuthVerified = true;
|
||||
});
|
||||
|
||||
// 인증 완료 이벤트 리스너
|
||||
document.addEventListener('authVerified', function () {
|
||||
isAuthVerified = true;
|
||||
// 취소 버튼 클릭 시
|
||||
document.getElementById('cancelButton').addEventListener('click', function () {
|
||||
location.href = '/login';
|
||||
});
|
||||
});
|
||||
|
||||
// 취소 버튼 클릭 시
|
||||
document.getElementById('cancelButton').addEventListener('click', function () {
|
||||
location.href = '/login';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
</script>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -24,25 +24,24 @@
|
||||
<h3>초대 정보</h3>
|
||||
</div>
|
||||
|
||||
<div class="account-recovery-card" style="margin-bottom: 32px;">
|
||||
<div class="account-recovery-result">
|
||||
<div class="result-header">
|
||||
<i class="fas fa-envelope-open-text result-icon" style="color: #1a73e8;"></i>
|
||||
<h2 class="result-title" style="font-size: 18px;">
|
||||
<strong th:text="${userName}"></strong>님, 법인회원 초대가 도착했습니다.
|
||||
</h2>
|
||||
<div class="invitation_alert_banner">
|
||||
<div class="banner-content-wrapper">
|
||||
<div class="banner-icon-area">
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="#E8F1FF" stroke="#1976D2" stroke-width="2"/>
|
||||
<path d="M12 8V13" stroke="#1976D2" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="12" cy="16" r="1.25" fill="#1976D2"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="result-info-box">
|
||||
<p class="info-text">
|
||||
<strong th:text="${orgName}"></strong>에서
|
||||
DJBank API Portal 법인회원으로 초대하였습니다.
|
||||
</p>
|
||||
<p class="info-text" style="margin-top: 8px;">
|
||||
<div class="banner-text-area">
|
||||
<strong>
|
||||
<span th:text="${userName}"></span>님, 법인회원 초대가 도착했습니다.
|
||||
</strong>
|
||||
<p>
|
||||
<strong><span th:text="${orgName}"></span></strong>에서 DJBank API Portal 법인회원으로 초대하였습니다.<br>
|
||||
초대를 수락하시면 법인회원으로 전환됩니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,50 +1,62 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/djbank_title_layout}">
|
||||
|
||||
<body>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>회원가입</h1>
|
||||
</div>
|
||||
</section>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="account-recovery-page">
|
||||
<div class="account-recovery-container">
|
||||
<div class="account-recovery-card">
|
||||
<!-- Result Content Area -->
|
||||
<div class="account-recovery-result">
|
||||
<div class="result-header">
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="64" height="64" fill="url(#pattern0_1130_6799)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0_1130_6799" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_1130_6799" transform="translate(0 0.104294) scale(0.00613497)"/>
|
||||
</pattern>
|
||||
<image id="image0_1130_6799" width="163" height="129" preserveAspectRatio="none" xlink:href="data:image/png;base64,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"/>
|
||||
</defs>
|
||||
</svg>
|
||||
<h2 class="result-title" th:text="${registrationType == 'corporate'} ? '법인 신청이 완료 되었습니다.' : '회원가입이 완료되었습니다.'">회원가입이 완료되었습니다.</h2>
|
||||
<section layout:fragment="title">
|
||||
<div class="page-title-banner">
|
||||
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
||||
<h1>회원가입</h1>
|
||||
</div>
|
||||
</section>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="account-recovery-page">
|
||||
<div class="account-recovery-container">
|
||||
<div class="account-recovery-card">
|
||||
<!-- Result Content Area -->
|
||||
<div class="account-recovery-result">
|
||||
<div class="result-header">
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="64" height="64" fill="url(#pattern0_1130_6799)" />
|
||||
<defs>
|
||||
<pattern id="pattern0_1130_6799" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_1130_6799" transform="translate(0 0.104294) scale(0.00613497)" />
|
||||
</pattern>
|
||||
<image id="image0_1130_6799" width="163" height="129" preserveAspectRatio="none"
|
||||
xlink:href="data:image/png;base64,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" />
|
||||
</defs>
|
||||
</svg>
|
||||
<h2 class="result-title"
|
||||
th:text="${registrationType == 'corporate'} ? '법인 신청이 완료 되었습니다.' : '회원가입이 완료되었습니다.'">회원가입이 완료되었습니다.</h2>
|
||||
</div>
|
||||
|
||||
<!-- Info Box -->
|
||||
<div class="result-info-box info-box-highlight" th:if="${registrationType == 'corporate'}">
|
||||
<div class="highlight-icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="#E8F1FF" stroke="#0049B4" stroke-width="2" />
|
||||
<path d="M12 8V13" stroke="#0049B4" stroke-width="2" stroke-linecap="round" />
|
||||
<circle cx="12" cy="16" r="1.25" fill="#0049B4" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="info-text">
|
||||
<strong>관리자의 확인 및 승인</strong> 이후
|
||||
이용하실 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Box -->
|
||||
<div class="result-info-box" th:if="${registrationType == 'corporate'}">
|
||||
<p class="info-text">
|
||||
관리자의 확인 및 승인 이후<br>
|
||||
이용하실 수 있습니다.
|
||||
</p>
|
||||
<!-- Action Buttons -->
|
||||
<div class="form-actions">
|
||||
<a th:href="@{/}" class="submit-button">홈으로</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="form-actions">
|
||||
<a th:href="@{/}" class="submit-button">홈으로</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</th:block>
|
||||
</body>
|
||||
<th:block layout:fragment="contentScript">
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -37,181 +37,244 @@
|
||||
<img th:src="@{/img/icon/icon_check_green.png}" alt="체크 아이콘" />
|
||||
</div>
|
||||
<ul class="signup-info-list">
|
||||
<li>회원은 법인, 개인(개발자)분으로 구분되며, 개발자 포털에서 온라인으로 회원 가입 신청을 합니다.</li>
|
||||
<li>포털 사용은 운영 담당자의 승인 후 가능합니다.</li>
|
||||
<li>법인 관리자는 회원 승인 이후, 포털을 실제 사용할 직원(개발자)을 추가 등록해 주시기 바랍니다.</li>
|
||||
<li>회원은 <strong>법인, 개인(개발자)</strong>분으로 구분되며, 개발자 포털에서 온라인으로 회원 가입 신청을 합니다.</li>
|
||||
<li>포털 사용은 <strong>운영 담당자의 승인 후</strong> 가능합니다.</li>
|
||||
<li>법인 관리자는 회원 승인 이후, 포털을 실제 사용할 <strong>직원(개발자)을 추가 등록</strong>해 주시기 바랍니다.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Vertical Timeline Steps -->
|
||||
<div class="signup-timeline">
|
||||
<!-- Step 1 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box one">
|
||||
<!--/* <svg width="40" height="40" viewBox="0 0 32 32" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M14 20C14 19.4477 14.4477 19 15 19H17C17.5523 19 18 19.4477 18 20V24C18 24.5523 17.5523 25 17 25H15C14.4477 25 14 24.5523 14 24V20Z"
|
||||
stroke="#0049B4" stroke-width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path
|
||||
d="M11 13C11 11.3431 12.3431 10 14 10C15.6569 10 17 11.3431 17 13C17 14.6569 15.6569 16 14 16C12.3431 16 11 14.6569 11 13Z"
|
||||
stroke="#0049B4" stroke-width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path d="M20 21V20C20 18.8954 20.8954 18 22 18C23.1046 18 24 18.8954 24 20V21"
|
||||
stroke="#0049B4" stroke-width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path
|
||||
d="M19 14C19 12.8954 19.8954 12 21 12C22.1046 12 23 12.8954 23 14C23 15.1046 22.1046 16 21 16C19.8954 16 19 15.1046 19 14Z"
|
||||
stroke="#0049B4" stroke-width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
</svg> */-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-person-add" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M12.5 16a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7m.5-5v1h1a.5.5 0 0 1 0 1h-1v1a.5.5 0 0 1-1 0v-1h-1a.5.5 0 0 1 0-1h1v-1a.5.5 0 0 1 1 0m-2-6a3 3 0 1 1-6 0 3 3 0 0 1 6 0M8 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4" />
|
||||
<path
|
||||
d="M8.256 14a4.5 4.5 0 0 1-.229-1.004H3c.001-.246.154-.986.832-1.664C4.484 10.68 5.711 10 8 10q.39 0 .74.025c.226-.341.496-.65.804-.918Q8.844 9.002 8 9c-5 0-6 3-6 4s1 1 1 1z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-num">STEP 01</div>
|
||||
<div class="signup-step__card-title">회원가입</div>
|
||||
<!-- Member Type Tabs -->
|
||||
<div class="signup-tabs">
|
||||
<button type="button" class="signup-tab-btn active" data-tab="personal">개인 회원</button>
|
||||
<button type="button" class="signup-tab-btn" data-tab="corporate">법인 회원</button>
|
||||
</div>
|
||||
|
||||
<!-- Timeline Container for fixed height spacing -->
|
||||
<div class="signup-timeline-container">
|
||||
<!-- Personal Member Timeline -->
|
||||
<div class="signup-timeline active" id="timeline-personal">
|
||||
<!-- Step 1 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box one">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-person-add" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M12.5 16a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7m.5-5v1h1a.5.5 0 0 1 0 1h-1v1a.5.5 0 0 1-1 0v-1h-1a.5.5 0 0 1 0-1h1v-1a.5.5 0 0 1 1 0m-2-6a3 3 0 1 1-6 0 3 3 0 0 1 6 0M8 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4" />
|
||||
<path
|
||||
d="M8.256 14a4.5 4.5 0 0 1-.229-1.004H3c.001-.246.154-.986.832-1.664C4.484 10.68 5.711 10 8 10q.39 0 .74.025c.226-.341.496-.65.804-.918Q8.844 9.002 8 9c-5 0-6 3-6 4s1 1 1 1z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-header">
|
||||
<span class="signup-step__card-num">STEP 01</span>
|
||||
<span class="signup-step__card-dot"></span>
|
||||
<span class="signup-step__card-title">회원가입</span>
|
||||
</div>
|
||||
<p class="signup-step__card-desc">개발자 포털을 이용하기 위해 회원가입을 진행합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box two">
|
||||
<!--/* <svg width="40" height="40" viewBox="0 0 32 32" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M14 20C14 19.4477 14.4477 19 15 19H17C17.5523 19 18 19.4477 18 20V24C18 24.5523 17.5523 25 17 25H15C14.4477 25 14 24.5523 14 24V20Z"
|
||||
stroke="#0049B4" stroke-width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path
|
||||
d="M11 13C11 11.3431 12.3431 10 14 10C15.6569 10 17 11.3431 17 13C17 14.6569 15.6569 16 14 16C12.3431 16 11 14.6569 11 13Z"
|
||||
stroke="#0049B4" stroke -width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path d="M19 16L21 18L25 14" stroke="#0049B4" stroke-width="1.6"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg> */-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-journal-check" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10.854 6.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 8.793l2.646-2.647a.5.5 0 0 1 .708 0" />
|
||||
<path
|
||||
d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2" />
|
||||
<path
|
||||
d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1z" />
|
||||
</svg>
|
||||
<!-- Corporate Member Timeline -->
|
||||
<div class="signup-timeline" id="timeline-corporate">
|
||||
<!-- Step 1 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box one">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-person-add" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M12.5 16a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7m.5-5v1h1a.5.5 0 0 1 0 1h-1v1a.5.5 0 0 1-1 0v-1h-1a.5.5 0 0 1 0-1h1v-1a.5.5 0 0 1 1 0m-2-6a3 3 0 1 1-6 0 3 3 0 0 1 6 0M8 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4" />
|
||||
<path
|
||||
d="M8.256 14a4.5 4.5 0 0 1-.229-1.004H3c.001-.246.154-.986.832-1.664C4.484 10.68 5.711 10 8 10q.39 0 .74.025c.226-.341.496-.65.804-.918Q8.844 9.002 8 9c-5 0-6 3-6 4s1 1 1 1z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-header">
|
||||
<span class="signup-step__card-num">STEP 01</span>
|
||||
<span class="signup-step__card-dot"></span>
|
||||
<span class="signup-step__card-title">회원가입</span>
|
||||
</div>
|
||||
<p class="signup-step__card-desc">개발자 포털을 이용하기 위해 회원가입을 진행합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-num">STEP 02</div>
|
||||
<div class="signup-step__card-title">승인</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box three">
|
||||
<!--/* <svg width="40" height="40" viewBox="0 0 32 32" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="7" y="7" width="18" height="18" rx="2" stroke="#0049B4" stroke-width="1.6"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path d="M12 12H20" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
<path d="M12 16H20" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
<path d="M12 20H16" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
</svg> */-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-code" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M5.854 4.854a.5.5 0 1 0-.708-.708l-3.5 3.5a.5.5 0 0 0 0 .708l3.5 3.5a.5.5 0 0 0 .708-.708L2.707 8zm4.292 0a.5.5 0 0 1 .708-.708l3.5 3.5a.5.5 0 0 1 0 .708l-3.5 3.5a.5.5 0 0 1-.708-.708L13.293 8z" />
|
||||
</svg>
|
||||
<!-- Step 2 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box two">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-journal-check" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10.854 6.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 8.793l2.646-2.647a.5.5 0 0 1 .708 0" />
|
||||
<path
|
||||
d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2" />
|
||||
<path
|
||||
d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-header">
|
||||
<span class="signup-step__card-num">STEP 02</span>
|
||||
<span class="signup-step__card-dot"></span>
|
||||
<span class="signup-step__card-title">승인</span>
|
||||
</div>
|
||||
<p class="signup-step__card-desc">신청하신 계정 정보를 관리자가 확인 후 승인합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-num">STEP 03</div>
|
||||
<div class="signup-step__card-title">API/APP 사용 신청</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box four">
|
||||
<!--/* <svg width="40" height="40" viewBox="0 0 32 32" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21 8H24V16" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path d="M8 8H11V16" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
</svg> */-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-display" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M0 4s0-2 2-2h12s2 0 2 2v6s0 2-2 2h-4q0 1 .25 1.5H11a.5.5 0 0 1 0 1H5a.5.5 0 0 1 0-1h.75Q6 13 6 12H2s-2 0-2-2zm1.398-.855a.76.76 0 0 0-.254.302A1.5 1.5 0 0 0 1 4.01V10c0 .325.078.502.145.602q.105.156.302.254a1.5 1.5 0 0 0 .538.143L2.01 11H14c.325 0 .502-.078.602-.145a.76.76 0 0 0 .254-.302 1.5 1.5 0 0 0 .143-.538L15 9.99V4c0-.325-.078-.502-.145-.602a.76.76 0 0 0-.302-.254A1.5 1.5 0 0 0 13.99 3H2c-.325 0-.502.078-.602.145" />
|
||||
</svg>
|
||||
<!-- Step 3 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box three">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-code" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M5.854 4.854a.5.5 0 1 0-.708-.708l-3.5 3.5a.5.5 0 0 0 0 .708l3.5 3.5a.5.5 0 0 0 .708-.708L2.707 8zm4.292 0a.5.5 0 0 1 .708-.708l3.5 3.5a.5.5 0 0 1 0 .708l-3.5 3.5a.5.5 0 0 1-.708-.708L13.293 8z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-header">
|
||||
<span class="signup-step__card-num">STEP 03</span>
|
||||
<span class="signup-step__card-dot"></span>
|
||||
<span class="signup-step__card-title">API / APP 사용 신청</span>
|
||||
</div>
|
||||
<p class="signup-step__card-desc">사용할 API를 선택하고 테스트용 키를 발급받습니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-num">STEP 04</div>
|
||||
<div class="signup-step__card-title">개발/테스트</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 5 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box five">
|
||||
<!--/* <svg width="40" height="40" viewBox="0 0 32 32" fill="none"*/-->
|
||||
<!-- xmlns="http://www.w3.org/2000/svg">-->
|
||||
<!--/* <rect x="7" y="7" width="18" height="18" rx="2" stroke="#0049B4" stroke-width="1.6"*/-->
|
||||
<!-- stroke-linecap="round" stroke-linejoin="round" />-->
|
||||
<!--/* <path d="M12 11H20" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />*/-->
|
||||
<!--/* <path d="M12 15L14.5 17.5L20 12" stroke="#0049B4" stroke-width="1.6"*/-->
|
||||
<!-- stroke-linecap="round" stroke-linejoin="round" />-->
|
||||
<!--/* </svg>*/-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-ui-checks-grid" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M2 10h3a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1m9-9h3a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1m0 9a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1zm0-10a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h3a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM2 9a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h3a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2zm7 2a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2zM0 2a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm5.354.854a.5.5 0 1 0-.708-.708L3 3.793l-.646-.647a.5.5 0 1 0-.708.708l1 1a.5.5 0 0 0 .708 0z" />
|
||||
</svg>
|
||||
<!-- Step 4 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box four">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-display" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M0 4s0-2 2-2h12s2 0 2 2v6s0 2-2 2h-4q0 1 .25 1.5H11a.5.5 0 0 1 0 1H5a.5.5 0 0 1 0-1h.75Q6 13 6 12H2s-2 0-2-2zm1.398-.855a.76.76 0 0 0-.254.302A1.5 1.5 0 0 0 1 4.01V10c0 .325.078.502.145.602q.105.156.302.254a1.5 1.5 0 0 0 .538.143L2.01 11H14c.325 0 .502-.078.602-.145a.76.76 0 0 0 .254-.302 1.5 1.5 0 0 0 .143-.538L15 9.99V4c0-.325-.078-.502-.145-.602a.76.76 0 0 0-.302-.254A1.5 1.5 0 0 0 13.99 3H2c-.325 0-.502.078-.602.145" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-header">
|
||||
<span class="signup-step__card-num">STEP 04</span>
|
||||
<span class="signup-step__card-dot"></span>
|
||||
<span class="signup-step__card-title">개발 / 테스트</span>
|
||||
</div>
|
||||
<p class="signup-step__card-desc">제공된 개발 도구로 자유롭게 연동을 테스트합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-num">STEP 05</div>
|
||||
<div class="signup-step__card-title">운영신청 및 심사</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 6 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box six">
|
||||
<!--/* <svg width="40" height="40" viewBox="0 0 32 32" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="7" y="9" width="18" height="16" rx="2" stroke="#0049B4" stroke-width="1.6"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
<path d="M7 13H25" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
<path d="M12 7V11" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
<path d="M20 7V11" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
<path d="M12 17H14" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
<path d="M12 21H14" stroke="#0049B4" stroke-width="1.6" stroke-linecap="round" />
|
||||
</svg> */-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-airplane" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M6.428 1.151C6.708.591 7.213 0 8 0s1.292.592 1.572 1.151C9.861 1.73 10 2.431 10 3v3.691l5.17 2.585a1.5 1.5 0 0 1 .83 1.342V12a.5.5 0 0 1-.582.493l-5.507-.918-.375 2.253 1.318 1.318A.5.5 0 0 1 10.5 16h-5a.5.5 0 0 1-.354-.854l1.319-1.318-.376-2.253-5.507.918A.5.5 0 0 1 0 12v-1.382a1.5 1.5 0 0 1 .83-1.342L6 6.691V3c0-.568.14-1.271.428-1.849m.894.448C7.111 2.02 7 2.569 7 3v4a.5.5 0 0 1-.276.447l-5.448 2.724a.5.5 0 0 0-.276.447v.792l5.418-.903a.5.5 0 0 1 .575.41l.5 3a.5.5 0 0 1-.14.437L6.708 15h2.586l-.647-.646a.5.5 0 0 1-.14-.436l.5-3a.5.5 0 0 1 .576-.411L15 11.41v-.792a.5.5 0 0 0-.276-.447L9.276 7.447A.5.5 0 0 1 9 7V3c0-.432-.11-.979-.322-1.401C8.458 1.159 8.213 1 8 1s-.458.158-.678.599" />
|
||||
</svg>
|
||||
<!-- Step 5 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box five">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-ui-checks-grid" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M2 10h3a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1m9-9h3a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1m0 9a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1zm0-10a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h3a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM2 9a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h3a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2zm7 2a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2zM0 2a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm5.354.854a.5.5 0 1 0-.708-.708L3 3.793l-.646-.647a.5.5 0 1 0-.708.708l1 1a.5.5 0 0 0 .708 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-header">
|
||||
<span class="signup-step__card-num">STEP 05</span>
|
||||
<span class="signup-step__card-dot"></span>
|
||||
<span class="signup-step__card-title">운영신청 및 심사</span>
|
||||
</div>
|
||||
<p class="signup-step__card-desc">실운영 환경 적용을 위해 최종 심사를 요청합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-num">STEP 06</div>
|
||||
<div class="signup-step__card-title">서비스 개시(예약)</div>
|
||||
|
||||
<!-- Step 6 -->
|
||||
<div class="signup-step">
|
||||
<div class="signup-step__icon-box six">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-airplane" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M6.428 1.151C6.708.591 7.213 0 8 0s1.292.592 1.572 1.151C9.861 1.73 10 2.431 10 3v3.691l5.17 2.585a1.5 1.5 0 0 1 .83 1.342V12a.5.5 0 0 1-.582.493l-5.507-.918-.375 2.253 1.318 1.318A.5.5 0 0 1 10.5 16h-5a.5.5 0 0 1-.354-.854l1.319-1.318-.376-2.253-5.507.918A.5.5 0 0 1 0 12v-1.382a1.5 1.5 0 0 1 .83-1.342L6 6.691V3c0-.568.14-1.271.428-1.849m.894.448C7.111 2.02 7 2.569 7 3v4a.5.5 0 0 1-.276.447l-5.448 2.724a.5.5 0 0 0-.276.447v.792l5.418-.903a.5.5 0 0 1 .575.41l.5 3a.5.5 0 0 1-.14.437L6.708 15h2.586l-.647-.646a.5.5 0 0 1-.14-.436l.5-3a.5.5 0 0 1 .576-.411L15 11.41v-.792a.5.5 0 0 0-.276-.447L9.276 7.447A.5.5 0 0 1 9 7V3c0-.432-.11-.979-.322-1.401C8.458 1.159 8.213 1 8 1s-.458.158-.678.599" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="signup-step__card">
|
||||
<div class="signup-step__card-header">
|
||||
<span class="signup-step__card-num">STEP 06</span>
|
||||
<span class="signup-step__card-dot"></span>
|
||||
<span class="signup-step__card-title">서비스 개시(예약)</span>
|
||||
</div>
|
||||
<p class="signup-step__card-desc">실운영 키를 적용하여 서비스를 정식 오픈합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 회원 구분별 이용 가능 서비스 (TBD) -->
|
||||
<section class="signup-roles-tbd">
|
||||
<h2 class="signup-roles-tbd__title">회원 구분별 이용 가능 서비스</h2>
|
||||
<div class="signup-roles-tbd__placeholder">
|
||||
<span class="signup-roles-tbd__badge">TBD</span>
|
||||
<p class="signup-roles-tbd__desc">회원 구분별 이용 가능 서비스 안내가 준비 중입니다.</p>
|
||||
<!-- 회원 구분별 이용 가능 서비스 -->
|
||||
<section class="signup-roles-table-section">
|
||||
<h2 class="signup-roles-table-section__title">회원 구분별 이용 가능 서비스</h2>
|
||||
<div class="signup-roles-table-wrapper">
|
||||
<table class="signup-roles-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2" class="col-feature">기능</th>
|
||||
<th rowspan="2" class="col-role">비회원</th>
|
||||
<th rowspan="2" class="col-role">개인</th>
|
||||
<th colspan="2" class="col-role-group">법인이용자</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-sub-role">법인개발자</th>
|
||||
<th class="col-sub-role">법인관리자</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="cell-feature">API 조회</td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cell-feature">API 테스트</td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cell-feature">1:1 문의</td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cell-feature">피드백/개선요청</td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cell-feature">클라이언트 - 신규, 수정, 삭제</td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cell-feature">Webhook 관리</td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cell-feature">이용 통계</td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cell-feature">개발자 관리</td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--denied">X</span></td>
|
||||
<td><span class="status-badge status-badge--allowed">O</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -225,6 +288,31 @@
|
||||
</body>
|
||||
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const tabs = document.querySelectorAll('.signup-tab-btn');
|
||||
const timelines = document.querySelectorAll('.signup-timeline');
|
||||
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener('click', function () {
|
||||
const targetTab = this.getAttribute('data-tab');
|
||||
|
||||
// Active Tab toggle
|
||||
tabs.forEach(btn => btn.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
|
||||
// Timeline display toggle
|
||||
timelines.forEach(timeline => {
|
||||
if (timeline.id === `timeline-${targetTab}`) {
|
||||
timeline.classList.add('active');
|
||||
} else {
|
||||
timeline.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
|
||||
</html>
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<!-- <link rel="stylesheet" type="text/css" th:href="@{/css/api-statistics.css}" /> -->
|
||||
<div class="service-main app-management-layout">
|
||||
<div class="service-main container" style="padding-top: 70px;">
|
||||
<th:block th:replace="~{fragment/djbank/service_sidebar :: sidebar('statistics')}"></th:block>
|
||||
<div class="app-management-content">
|
||||
<section class="api-statistics-container">
|
||||
@@ -24,7 +24,8 @@
|
||||
<span th:if="${statsAggregationMinute == null}">통계 데이터는 매시 집계되며, 집계 이전 시간 기준으로 생성됩니다.</span>
|
||||
<span class="statistics-notice-example" th:if="${statsAggregationMinute != null}"
|
||||
th:text="'예) 매시 ' + ${statsAggregationMinute} + '분 집계 기준 — 현재 12:30이면 12:00 이전, 12:05이면 11:00 이전에 발생한 거래가 대상입니다.'">예시</span>
|
||||
<span class="statistics-notice-example" th:if="${statsAggregationMinute == null}">예) 현재 12:30이면 12:00 이전, 12:05이면 11:00 이전에 발생한 거래가 대상입니다.</span>
|
||||
<span class="statistics-notice-example" th:if="${statsAggregationMinute == null}">예) 현재 12:30이면 12:00 이전,
|
||||
12:05이면 11:00 이전에 발생한 거래가 대상입니다.</span>
|
||||
<span th:if="${statsLatestTime != null}" class="statistics-notice-latest"
|
||||
th:text="'※ 최신 집계 시각: ' + ${statsLatestTime} + ' 기준'">최신 집계 시각</span>
|
||||
</div>
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
</section>
|
||||
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="signup-guide-v2 figma-register-wrapper">
|
||||
<div class="service-main app-management-layout">
|
||||
<div class="signup-guide-v2">
|
||||
<div class="service-main container" style="padding-top: 70px;">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<th:block th:replace="~{fragment/djbank/service_sidebar :: sidebar('webhook')}"></th:block>
|
||||
@@ -22,9 +22,13 @@
|
||||
<!-- Content Area -->
|
||||
<div class="app-management-content">
|
||||
<div class="step1-wrap">
|
||||
|
||||
<!-- Title -->
|
||||
<h2 class="s1-title">Webhook 관리</h2>
|
||||
<!-- Header Row with Title and Dev Guide Link -->
|
||||
<div class="webhook-header-row">
|
||||
<h2 class="s1-title">Webhook 관리</h2>
|
||||
<a class="webhook-guide-btn" th:href="@{/service/webhook-dev-guide}">
|
||||
웹훅 개발가이드 - 수신.서명검증.응답 규칙 보러가기
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Empty Card -->
|
||||
<div class="s1-form-card">
|
||||
@@ -38,18 +42,11 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 액션 -->
|
||||
<div class="s1-actions" sec:authorize="hasRole('ROLE_WEBHOOK')">
|
||||
<button type="button" class="s1-btn-next" id="requestWebhook">Webhook 신청</button>
|
||||
<button type="button" class="s1-btn-next-figma" id="requestWebhook">Webhook 신청</button>
|
||||
</div>
|
||||
|
||||
<p class="webhook-guide-link">
|
||||
<a th:href="@{/service/webhook-dev-guide}">
|
||||
📘 웹훅 개발가이드 — 수신·서명검증·응답 규칙 보러가기
|
||||
</a>
|
||||
</p>
|
||||
|
||||
</div><!-- /step1-wrap -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/djbank_title_layout}">
|
||||
|
||||
<body>
|
||||
@@ -36,7 +35,8 @@
|
||||
<div class="webhook-card-head">
|
||||
<div class="head-title-group">
|
||||
<!-- List Icon SVG -->
|
||||
<svg class="head-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg class="head-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2">
|
||||
<line x1="8" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="8" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="8" y1="18" x2="21" y2="18"></line>
|
||||
@@ -47,12 +47,13 @@
|
||||
<h3>등록된 Webhook</h3>
|
||||
</div>
|
||||
<span class="webhook-created" th:if="*{createdDate != null and #strings.length(createdDate) >= 8}"
|
||||
th:text="|등록일 : ${#strings.substring(webhook.createdDate,0,4)}-${#strings.substring(webhook.createdDate,4,6)}-${#strings.substring(webhook.createdDate,6,8)}|">등록일 : 2026-07-27</span>
|
||||
th:text="|등록일 : ${#strings.substring(webhook.createdDate,0,4)}-${#strings.substring(webhook.createdDate,4,6)}-${#strings.substring(webhook.createdDate,6,8)}|">등록일
|
||||
: 2026-07-27</span>
|
||||
</div>
|
||||
|
||||
<!-- Vertical Content Fields -->
|
||||
<div class="webhook-card-content">
|
||||
|
||||
|
||||
<!-- 수신 URL -->
|
||||
<div class="webhook-info-group">
|
||||
<span class="group-label">수신 URL</span>
|
||||
@@ -181,14 +182,14 @@
|
||||
openModal('Secret 재발급',
|
||||
'재발급 시 기존 Secret은 즉시 무효화됩니다. 새 Secret을 수신 서버의 Webhook 서명검증에 반영하지 않으면 이후 발송되는 모든 Webhook의 서명 검증이 실패합니다. 계속하려면 비밀번호를 입력하세요.',
|
||||
function (pw) {
|
||||
post('/webhook/regenerate-secret', pw).then(function (res) {
|
||||
if (res.success) {
|
||||
document.getElementById('secretMasked').textContent = res.secret;
|
||||
closeModal();
|
||||
alert('Secret이 재발급되었습니다.\n반드시 수신 서버의 서명검증 Secret을 새 값으로 교체하세요.\n교체 전까지 Webhook 서명 검증이 실패합니다.');
|
||||
} else { showError(res.message || '실패했습니다.'); }
|
||||
}).catch(function () { showError('요청 처리 중 오류가 발생했습니다.'); });
|
||||
});
|
||||
post('/webhook/regenerate-secret', pw).then(function (res) {
|
||||
if (res.success) {
|
||||
document.getElementById('secretMasked').textContent = res.secret;
|
||||
closeModal();
|
||||
alert('Secret이 재발급되었습니다.\n반드시 수신 서버의 서명검증 Secret을 새 값으로 교체하세요.\n교체 전까지 Webhook 서명 검증이 실패합니다.');
|
||||
} else { showError(res.message || '실패했습니다.'); }
|
||||
}).catch(function () { showError('요청 처리 중 오류가 발생했습니다.'); });
|
||||
});
|
||||
});
|
||||
|
||||
// 삭제
|
||||
@@ -205,4 +206,5 @@
|
||||
</script>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -1,35 +1,37 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<body>
|
||||
<footer th:fragment="footerFragment" class="global-footer">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<!-- Left Section -->
|
||||
<div class="footer-left">
|
||||
<img src="/img/logo/logo-jjb.png" alt="DJBank" class="footer-logo">
|
||||
<div class="footer-links">
|
||||
<a th:href="@{/agreements/terms}" class="footer-link">이용약관</a>
|
||||
<span class="footer-separator">|</span>
|
||||
<a href="https://www.jejubank.co.kr/hmpg/csct/secuCenr/ptctPlcy/procsPlcy/ctnt.do"
|
||||
target="_blank" rel="noopener noreferrer" class="footer-link">개인정보처리방침</a>
|
||||
</div>
|
||||
<p class="footer-copyright">Copyright © 2026 JEJU Bank. All Rights Reserved.</p>
|
||||
</div>
|
||||
|
||||
<!-- Right Section -->
|
||||
<div class="footer-right">
|
||||
<div class="footer-related-sites">
|
||||
<select class="related-sites-select">
|
||||
<option>DJBank 관련 사이트</option>
|
||||
<option>DJBank 홈페이지</option>
|
||||
<option>DJBank 인터넷뱅킹</option>
|
||||
<option>DJBank 모바일뱅킹</option>
|
||||
</select>
|
||||
<body>
|
||||
<footer th:fragment="footerFragment" class="global-footer">
|
||||
<div class="container">
|
||||
<div class="footer-content">
|
||||
<!-- Left Section -->
|
||||
<div class="footer-left">
|
||||
<img src="/img/logo/logo-jjb_white.png" alt="DJBank" class="footer-logo">
|
||||
<div class="footer-links">
|
||||
<a th:href="@{/agreements/terms}" class="footer-link">이용약관</a>
|
||||
<span class="footer-separator">|</span>
|
||||
<a href="https://www.jejubank.co.kr/hmpg/csct/secuCenr/ptctPlcy/procsPlcy/ctnt.do" target="_blank"
|
||||
rel="noopener noreferrer" class="footer-link">개인정보처리방침</a>
|
||||
</div>
|
||||
<p class="footer-copyright">Copyright © 2026 JEJU Bank. All Rights Reserved.</p>
|
||||
</div>
|
||||
|
||||
<!-- Right Section -->
|
||||
<div class="footer-right">
|
||||
<div class="footer-related-sites">
|
||||
<select class="related-sites-select">
|
||||
<option>DJBank 관련 사이트</option>
|
||||
<option>DJBank 홈페이지</option>
|
||||
<option>DJBank 인터넷뱅킹</option>
|
||||
<option>DJBank 모바일뱅킹</option>
|
||||
</select>
|
||||
</div>
|
||||
<p class="footer-contact" th:text="'고객센터 ' + ${customerCenterContact}">고객센터 1588-3388</p>
|
||||
</div>
|
||||
<p class="footer-contact" th:text="'고객센터 ' + ${customerCenterContact}">고객센터 1588-3388</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -17,11 +17,12 @@
|
||||
<!--/* </a>*/-->
|
||||
<!--/* <a th:href="@{/}" class="logo-text">API Portal</a>*/-->
|
||||
<!--/* </div>*/-->
|
||||
<div >
|
||||
<div>
|
||||
<div class="logo">
|
||||
<a th:href="@{/}" class="logo-wrapper">
|
||||
<span class="logo-text-bold">DJBank</span> <span class="logo-text-thin">API Portal</span>
|
||||
<a th:href="@{/}" class="mobile-logo-link">
|
||||
<img src="/img/logo/logo-djb.png" alt="DJBank" class="mobile-logo">
|
||||
</a>
|
||||
<a th:href="@{/}" class="mobile-logo-text" style="font-size: 22px; font-weight: 700; color: #212529; text-decoration: none; margin-left: 8px; vertical-align: middle;">API Portal</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
class="service-nav__item" sec:authorize="hasRole('ROLE_CORP_MANAGER')">개발자 관리</a>
|
||||
|
||||
<a th:href="@{/clients}" th:classappend="${activeMenu == 'apiKey'} ? 'service-nav__item--active' : ''"
|
||||
class="service-nav__item">API 신청 관리</a>
|
||||
class="service-nav__item" sec:authorize="hasRole('ROLE_APP')">API 신청 관리</a>
|
||||
|
||||
<a th:href="@{/webhook}" th:classappend="${activeMenu == 'webhook'} ? 'service-nav__item--active' : ''"
|
||||
class="service-nav__item" sec:authorize="hasRole('ROLE_WEBHOOK')">Webhook 관리</a>
|
||||
|
||||
Reference in New Issue
Block a user