2FA 팝업 UI 개선 및 기능 추가:
- 디자인 가이드 기반 레이아웃/스타일 재정의(SASS) - 인증 흐름 개선: 타이머/프로그레스바/버튼 상태 업데이트(JS) - 사용자 친화적 안내 메시지 및 입력 상태 검증 추가
This commit is contained in:
@@ -7565,123 +7565,330 @@ button.djb-comment-submit:disabled {
|
|||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tfaModal .modal-title {
|
.tfa-card {
|
||||||
|
position: relative;
|
||||||
|
width: 520px;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid #DCE2ED;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||||
|
color: #0D0E11;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
right: 16px;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
color: #7F8A95;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background 0.12s ease, color 0.12s ease;
|
||||||
|
}
|
||||||
|
.tfa-close:hover {
|
||||||
|
background: #F4F5F9;
|
||||||
|
color: #0D0E11;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-head {
|
||||||
|
padding: 24px 32px;
|
||||||
|
padding-right: 60px;
|
||||||
|
border-bottom: 1px solid #DCE2ED;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.tfa-head .tfa-head-title {
|
||||||
|
font-size: 27px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.35;
|
||||||
|
color: #0D0E11;
|
||||||
|
}
|
||||||
|
.tfa-head .tfa-head-brand {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #7F8A95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-body {
|
||||||
|
padding: 28px 32px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-step {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
.tfa-step .tfa-step-num {
|
||||||
.tfa-subtitle {
|
display: inline-flex;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
color: #64748B;
|
justify-content: center;
|
||||||
margin-bottom: 24px;
|
width: 20px;
|
||||||
font-size: 14px;
|
height: 20px;
|
||||||
|
border-radius: 100px;
|
||||||
|
background: #BDC7CF;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
.tfa-step .tfa-step-num.is-active {
|
||||||
|
background: #4685EF;
|
||||||
|
}
|
||||||
|
.tfa-step .tfa-step-text {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #7F8A95;
|
||||||
|
}
|
||||||
|
.tfa-step .tfa-step-text.is-active {
|
||||||
|
color: #0D0E11;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfa-segment {
|
.tfa-segment {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 28px;
|
||||||
}
|
}
|
||||||
.tfa-segment .tfa-seg-btn {
|
.tfa-segment .tfa-seg-btn {
|
||||||
flex: 1;
|
padding: 14px 16px;
|
||||||
display: flex;
|
text-align: left;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
padding: 12px 8px;
|
|
||||||
border: 1px solid #CBD5E1;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: #F8FAFC;
|
|
||||||
color: #475569;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.15s ease;
|
border: 1px solid #DCE2ED;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
transition: border-color 0.12s ease, background 0.12s ease;
|
||||||
|
}
|
||||||
|
.tfa-segment .tfa-seg-btn .tfa-seg-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #0D0E11;
|
||||||
|
}
|
||||||
|
.tfa-segment .tfa-seg-btn .tfa-seg-masked {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #7F8A95;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
.tfa-segment .tfa-seg-btn:hover {
|
.tfa-segment .tfa-seg-btn:hover {
|
||||||
border-color: #0049B4;
|
border-color: #4685EF;
|
||||||
}
|
}
|
||||||
.tfa-segment .tfa-seg-btn.is-active {
|
.tfa-segment .tfa-seg-btn.is-active {
|
||||||
background: #0049B4;
|
border: 1.5px solid #4685EF;
|
||||||
border-color: #0049B4;
|
background: #ECF0FA;
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
}
|
||||||
.tfa-segment .tfa-seg-btn.is-active .tfa-seg-masked {
|
.tfa-segment .tfa-seg-btn.is-active .tfa-seg-label {
|
||||||
color: rgba(255, 255, 255, 0.85);
|
color: #2A69DE;
|
||||||
}
|
|
||||||
.tfa-segment .tfa-seg-masked {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #94A3B8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfa-btn-block {
|
.tfa-hint {
|
||||||
|
border: 1px solid #DCE2ED;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #F4F5F9;
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #7F8A95;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-cta {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 8px;
|
height: 56px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #4685EF;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
transition: background 0.12s ease;
|
||||||
|
}
|
||||||
|
.tfa-cta:hover {
|
||||||
|
background: #2A69DE;
|
||||||
|
}
|
||||||
|
.tfa-cta:disabled {
|
||||||
|
background: #F4F5F9;
|
||||||
|
color: #BDC7CF;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfa-code-row {
|
.tfa-code-row {
|
||||||
position: relative;
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.tfa-code-row .tfa-code-input-wrap {
|
||||||
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
height: 56px;
|
||||||
|
padding: 0 14px;
|
||||||
|
border: 1px solid #BDC7CF;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
transition: border-color 0.12s ease;
|
||||||
|
}
|
||||||
|
.tfa-code-row .tfa-code-input-wrap:focus-within {
|
||||||
|
border-color: #4685EF;
|
||||||
}
|
}
|
||||||
.tfa-code-row .tfa-code-input {
|
.tfa-code-row .tfa-code-input {
|
||||||
width: 100%;
|
flex: 1;
|
||||||
padding: 14px 64px 14px 16px;
|
min-width: 0;
|
||||||
border: 1px solid #CBD5E1;
|
border: 0;
|
||||||
border-radius: 8px;
|
|
||||||
font-size: 15px;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
}
|
|
||||||
.tfa-code-row .tfa-code-input:focus {
|
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #0049B4;
|
background: transparent;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
color: #0D0E11;
|
||||||
}
|
}
|
||||||
.tfa-code-row .tfa-timer {
|
.tfa-code-row .tfa-code-input::placeholder {
|
||||||
position: absolute;
|
color: #BDC7CF;
|
||||||
right: 16px;
|
font-weight: 400;
|
||||||
color: #E11D48;
|
}
|
||||||
|
.tfa-code-row .tfa-resend {
|
||||||
|
flex: none;
|
||||||
|
height: 56px;
|
||||||
|
padding: 0 18px;
|
||||||
|
border: 1px solid #7F8A95;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
color: #0D0E11;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: background 0.12s ease;
|
||||||
|
}
|
||||||
|
.tfa-code-row .tfa-resend:hover {
|
||||||
|
background: #F4F5F9;
|
||||||
|
}
|
||||||
|
.tfa-code-row .tfa-resend:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-timer-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
border: 1px solid #DCE2ED;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #F4F5F9;
|
||||||
|
padding: 12px 14px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.tfa-timer-row .tfa-timer-label {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 300;
|
||||||
|
color: #7F8A95;
|
||||||
|
}
|
||||||
|
.tfa-timer-row .tfa-timer-clock {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.tfa-timer-row .tfa-timer {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
color: #4685EF;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
.tfa-timer-row .tfa-timer.is-warning {
|
||||||
|
color: #F4253C;
|
||||||
|
}
|
||||||
|
.tfa-timer-row .tfa-timer.is-expired {
|
||||||
|
color: #7F8A95;
|
||||||
|
}
|
||||||
|
.tfa-timer-row .tfa-timer-total {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #7F8A95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-progress {
|
||||||
|
height: 3px;
|
||||||
|
background: #DCE2ED;
|
||||||
|
border-radius: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.tfa-progress .tfa-progress-bar {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: #4685EF;
|
||||||
|
transition: width 1s linear;
|
||||||
|
}
|
||||||
|
.tfa-progress .tfa-progress-bar.is-warning {
|
||||||
|
background: #F4253C;
|
||||||
|
}
|
||||||
|
|
||||||
.tfa-message {
|
.tfa-message {
|
||||||
min-height: 18px;
|
min-height: 21px;
|
||||||
margin-top: 8px;
|
margin: 0 0 20px;
|
||||||
font-size: 13px;
|
font-size: 14px;
|
||||||
color: #64748B;
|
font-weight: 300;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #7F8A95;
|
||||||
}
|
}
|
||||||
.tfa-message.is-error {
|
.tfa-message.is-error {
|
||||||
color: #E11D48;
|
color: #F4253C;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfa-test-notice {
|
.tfa-test-notice {
|
||||||
margin-top: 8px;
|
margin: 0 0 16px;
|
||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
border: 1px dashed #F59E0B;
|
border: 1px dashed #F59E0B;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #FFFBEB;
|
background: #FFFBEB;
|
||||||
color: #B45309;
|
color: #B45309;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfa-actions {
|
.tfa-foot {
|
||||||
display: flex;
|
margin-top: 24px;
|
||||||
justify-content: flex-end;
|
padding-top: 16px;
|
||||||
margin: 8px 0;
|
border-top: 1px solid #DFDFDF;
|
||||||
}
|
font-size: 14px;
|
||||||
.tfa-actions .tfa-resend {
|
font-weight: 300;
|
||||||
background: none;
|
line-height: 1.5;
|
||||||
border: none;
|
color: #7F8A95;
|
||||||
color: #0049B4;
|
|
||||||
font-size: 13px;
|
|
||||||
cursor: pointer;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.tfa-head {
|
||||||
|
padding: 20px 22px;
|
||||||
|
}
|
||||||
|
.tfa-head .tfa-head-title {
|
||||||
|
font-size: 23px;
|
||||||
|
}
|
||||||
|
.tfa-body {
|
||||||
|
padding: 22px 22px 26px;
|
||||||
|
}
|
||||||
|
.tfa-segment {
|
||||||
|
margin-bottom: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.hero-carousel-section {
|
.hero-carousel-section {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -90,13 +90,15 @@
|
|||||||
|
|
||||||
var seg = document.getElementById('tfaSegment');
|
var seg = document.getElementById('tfaSegment');
|
||||||
seg.innerHTML = '';
|
seg.innerHTML = '';
|
||||||
|
self._maskedByType = {};
|
||||||
var channels = info.channels || [];
|
var channels = info.channels || [];
|
||||||
channels.forEach(function (ch, idx) {
|
channels.forEach(function (ch, idx) {
|
||||||
|
self._maskedByType[ch.type] = ch.masked;
|
||||||
var btn = document.createElement('button');
|
var btn = document.createElement('button');
|
||||||
btn.type = 'button';
|
btn.type = 'button';
|
||||||
btn.className = 'tfa-seg-btn' + (idx === 0 ? ' is-active' : '');
|
btn.className = 'tfa-seg-btn' + (idx === 0 ? ' is-active' : '');
|
||||||
btn.setAttribute('data-channel', ch.type);
|
btn.setAttribute('data-channel', ch.type);
|
||||||
btn.innerHTML = (ch.type === 'EMAIL' ? '이메일 인증' : '전화번호 인증')
|
btn.innerHTML = '<span class="tfa-seg-label">' + (ch.type === 'EMAIL' ? '이메일' : '휴대폰 문자') + '</span>'
|
||||||
+ '<span class="tfa-seg-masked">' + ch.masked + '</span>';
|
+ '<span class="tfa-seg-masked">' + ch.masked + '</span>';
|
||||||
btn.addEventListener('click', function () { self._selectChannel(ch.type); });
|
btn.addEventListener('click', function () { self._selectChannel(ch.type); });
|
||||||
seg.appendChild(btn);
|
seg.appendChild(btn);
|
||||||
@@ -106,8 +108,11 @@
|
|||||||
// 초기 상태: 발송 단계
|
// 초기 상태: 발송 단계
|
||||||
document.getElementById('tfaSendStep').style.display = '';
|
document.getElementById('tfaSendStep').style.display = '';
|
||||||
document.getElementById('tfaVerifyStep').style.display = 'none';
|
document.getElementById('tfaVerifyStep').style.display = 'none';
|
||||||
document.getElementById('tfaMessage').textContent = '';
|
self._setMessage('', false);
|
||||||
document.getElementById('tfaCodeInput').value = '';
|
document.getElementById('tfaCodeInput').value = '';
|
||||||
|
document.getElementById('tfaVerifyButton').disabled = true;
|
||||||
|
self._setStep2Active(false);
|
||||||
|
self._resetTimerUi();
|
||||||
var notice = document.getElementById('tfaTestNotice');
|
var notice = document.getElementById('tfaTestNotice');
|
||||||
notice.style.display = 'none';
|
notice.style.display = 'none';
|
||||||
notice.textContent = '';
|
notice.textContent = '';
|
||||||
@@ -118,6 +123,11 @@
|
|||||||
document.getElementById('tfaVerifyButton').onclick = function () { self._verify(); };
|
document.getElementById('tfaVerifyButton').onclick = function () { self._verify(); };
|
||||||
document.getElementById('tfaCloseButton').onclick = function () { self._cancel('CANCELLED'); };
|
document.getElementById('tfaCloseButton').onclick = function () { self._cancel('CANCELLED'); };
|
||||||
document.getElementById('tfaBackdrop').onclick = function () { self._cancel('CANCELLED'); };
|
document.getElementById('tfaBackdrop').onclick = function () { self._cancel('CANCELLED'); };
|
||||||
|
document.getElementById('tfaCodeInput').oninput = function () {
|
||||||
|
var v = (this.value || '').replace(/\D/g, '').slice(0, 6);
|
||||||
|
this.value = v;
|
||||||
|
document.getElementById('tfaVerifyButton').disabled = v.length < 6;
|
||||||
|
};
|
||||||
document.getElementById('tfaCodeInput').onkeydown = function (e) {
|
document.getElementById('tfaCodeInput').onkeydown = function (e) {
|
||||||
if (e.key === 'Enter') { self._verify(); }
|
if (e.key === 'Enter') { self._verify(); }
|
||||||
};
|
};
|
||||||
@@ -157,8 +167,11 @@
|
|||||||
// 발송 성공 → 검증 단계 노출 + 타이머
|
// 발송 성공 → 검증 단계 노출 + 타이머
|
||||||
document.getElementById('tfaSendStep').style.display = 'none';
|
document.getElementById('tfaSendStep').style.display = 'none';
|
||||||
document.getElementById('tfaVerifyStep').style.display = '';
|
document.getElementById('tfaVerifyStep').style.display = '';
|
||||||
self._setMessage('', false);
|
self._setStep2Active(true);
|
||||||
|
var masked = self._maskedByType ? (self._maskedByType[self._channel] || '') : '';
|
||||||
|
self._setMessage((masked ? masked + ' 으로 ' : '') + '인증번호를 보냈습니다.', false);
|
||||||
document.getElementById('tfaCodeInput').value = '';
|
document.getElementById('tfaCodeInput').value = '';
|
||||||
|
document.getElementById('tfaVerifyButton').disabled = true;
|
||||||
document.getElementById('tfaCodeInput').focus();
|
document.getElementById('tfaCodeInput').focus();
|
||||||
if (self._testNotice && res.testAuthNumber) {
|
if (self._testNotice && res.testAuthNumber) {
|
||||||
var notice = document.getElementById('tfaTestNotice');
|
var notice = document.getElementById('tfaTestNotice');
|
||||||
@@ -226,21 +239,60 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_fmtClock: function (n) {
|
||||||
|
var m = Math.floor(n / 60);
|
||||||
|
var s = n % 60;
|
||||||
|
return m + ':' + (s < 10 ? '0' + s : s);
|
||||||
|
},
|
||||||
|
|
||||||
|
_setStep2Active: function (active) {
|
||||||
|
var num = document.getElementById('tfaStepNum');
|
||||||
|
var text = document.getElementById('tfaStepText');
|
||||||
|
if (num) { num.classList.toggle('is-active', active); }
|
||||||
|
if (text) { text.classList.toggle('is-active', active); }
|
||||||
|
},
|
||||||
|
|
||||||
|
_resetTimerUi: function () {
|
||||||
|
var base = this._ttl || 180;
|
||||||
|
var clock = document.getElementById('tfaTimer');
|
||||||
|
var bar = document.getElementById('tfaProgressBar');
|
||||||
|
var label = document.getElementById('tfaTimerLabel');
|
||||||
|
var total = document.getElementById('tfaTimerTotal');
|
||||||
|
if (clock) { clock.className = 'tfa-timer'; clock.textContent = this._fmtClock(base); }
|
||||||
|
if (bar) { bar.className = 'tfa-progress-bar'; bar.style.width = '100%'; }
|
||||||
|
if (label) { label.textContent = '남은 인증 시간'; }
|
||||||
|
if (total) { total.textContent = '/ ' + this._fmtClock(base); }
|
||||||
|
},
|
||||||
|
|
||||||
_startTimer: function (seconds) {
|
_startTimer: function (seconds) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self._stopTimer();
|
self._stopTimer();
|
||||||
|
var total = seconds || self._ttl || 180;
|
||||||
var remaining = seconds;
|
var remaining = seconds;
|
||||||
var el = document.getElementById('tfaTimer');
|
var clock = document.getElementById('tfaTimer');
|
||||||
|
var bar = document.getElementById('tfaProgressBar');
|
||||||
|
var label = document.getElementById('tfaTimerLabel');
|
||||||
|
var totalEl = document.getElementById('tfaTimerTotal');
|
||||||
|
if (label) { label.textContent = '남은 인증 시간'; }
|
||||||
|
if (totalEl) { totalEl.textContent = '/ ' + self._fmtClock(total); }
|
||||||
function tick() {
|
function tick() {
|
||||||
if (remaining <= 0) {
|
if (remaining <= 0) {
|
||||||
self._stopTimer();
|
self._stopTimer();
|
||||||
el.textContent = '00:00';
|
if (clock) { clock.textContent = '0:00'; clock.className = 'tfa-timer is-expired'; }
|
||||||
|
if (bar) { bar.style.width = '0%'; }
|
||||||
|
if (label) { label.textContent = '인증 시간이 만료되었습니다. 재전송해 주세요.'; }
|
||||||
self._cancel('TIMEOUT');
|
self._cancel('TIMEOUT');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var m = Math.floor(remaining / 60);
|
var warn = remaining <= 30;
|
||||||
var s = remaining % 60;
|
if (clock) {
|
||||||
el.textContent = (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
clock.textContent = self._fmtClock(remaining);
|
||||||
|
clock.className = 'tfa-timer' + (warn ? ' is-warning' : '');
|
||||||
|
}
|
||||||
|
if (bar) {
|
||||||
|
bar.style.width = Math.round((remaining / total) * 100) + '%';
|
||||||
|
bar.className = 'tfa-progress-bar' + (warn ? ' is-warning' : '');
|
||||||
|
}
|
||||||
remaining--;
|
remaining--;
|
||||||
}
|
}
|
||||||
tick();
|
tick();
|
||||||
|
|||||||
@@ -2,133 +2,352 @@
|
|||||||
@use '../abstracts/color-functions' as *;
|
@use '../abstracts/color-functions' as *;
|
||||||
@use '../abstracts/mixins' as *;
|
@use '../abstracts/mixins' as *;
|
||||||
|
|
||||||
// 공통 2FA(추가 인증) 팝업. .modal / .modal-backdrop / .modal-dialog 는 _modals 재사용.
|
// 공통 2FA(추가 인증) 팝업 — 제주은행(DJBank) ERP뱅킹 Design Guide 적용.
|
||||||
|
// .modal / .modal-backdrop / .modal 은 _modals 의 show/hide·애니메이션을 재사용하고
|
||||||
|
// 카드 내부는 아래 토큰(surface_blue #4685EF · border_gray #DCE2ED · radius 4)으로 재정의한다.
|
||||||
|
|
||||||
#tfaModal {
|
// 디자인 토큰(가이드 전용, 전역 변수와 분리)
|
||||||
.modal-title {
|
$tfa-blue: #4685EF;
|
||||||
display: flex;
|
$tfa-blue-dark: #2A69DE;
|
||||||
align-items: center;
|
$tfa-blue-soft: #ECF0FA;
|
||||||
gap: 8px;
|
$tfa-blue-text: #2A69DE;
|
||||||
}
|
$tfa-ink: #0D0E11;
|
||||||
}
|
$tfa-muted: #7F8A95;
|
||||||
|
$tfa-border: #DCE2ED;
|
||||||
|
$tfa-border-2: #BDC7CF;
|
||||||
|
$tfa-surface: #F4F5F9;
|
||||||
|
$tfa-danger: #F4253C;
|
||||||
|
|
||||||
.tfa-subtitle {
|
// 카드 (modal-dialog 기본 padding/max-width/radius 를 덮어씀)
|
||||||
text-align: center;
|
.tfa-card {
|
||||||
color: #64748B;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tfa-segment {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.tfa-seg-btn {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
padding: 12px 8px;
|
|
||||||
border: 1px solid #CBD5E1;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: #F8FAFC;
|
|
||||||
color: #475569;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.15s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: $primary-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-active {
|
|
||||||
background: $primary-color;
|
|
||||||
border-color: $primary-color;
|
|
||||||
color: #FFFFFF;
|
|
||||||
|
|
||||||
.tfa-seg-masked {
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tfa-seg-masked {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #94A3B8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tfa-btn-block {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tfa-code-row {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 520px;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid $tfa-border;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||||
|
color: $tfa-ink;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 닫기 (우상단, 은은한 회색)
|
||||||
|
.tfa-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
right: 16px;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
color: $tfa-muted;
|
||||||
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background 0.12s ease, color 0.12s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $tfa-surface;
|
||||||
|
color: $tfa-ink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 헤더
|
||||||
|
.tfa-head {
|
||||||
|
padding: 24px 32px;
|
||||||
|
padding-right: 60px; // 우상단 닫기(✕) 영역 확보 — 브랜드 텍스트와 겹치지 않게
|
||||||
|
border-bottom: 1px solid $tfa-border;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.tfa-head-title {
|
||||||
|
font-size: 27px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.35;
|
||||||
|
color: $tfa-ink;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-head-brand {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: $tfa-muted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-body {
|
||||||
|
padding: 28px 32px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 단계 라벨 (① 인증 수단 / ② 인증번호 입력)
|
||||||
|
.tfa-step {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.tfa-step-num {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 100px;
|
||||||
|
background: $tfa-border-2;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
flex: none;
|
||||||
|
|
||||||
|
&.is-active { background: $tfa-blue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-step-text {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: $tfa-muted;
|
||||||
|
|
||||||
|
&.is-active { color: $tfa-ink; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 채널 선택 (이메일 / 휴대폰) — 2열 그리드
|
||||||
|
.tfa-segment {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 28px;
|
||||||
|
|
||||||
|
.tfa-seg-btn {
|
||||||
|
padding: 14px 16px;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid $tfa-border;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
transition: border-color 0.12s ease, background 0.12s ease;
|
||||||
|
|
||||||
|
.tfa-seg-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: $tfa-ink;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-seg-masked {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 300;
|
||||||
|
color: $tfa-muted;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover { border-color: $tfa-blue; }
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
border: 1.5px solid $tfa-blue;
|
||||||
|
background: $tfa-blue-soft;
|
||||||
|
|
||||||
|
.tfa-seg-label { color: $tfa-blue-text; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 안내 박스 (발송 전)
|
||||||
|
.tfa-hint {
|
||||||
|
border: 1px solid $tfa-border;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: $tfa-surface;
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: $tfa-muted;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기본 CTA (인증번호 받기 / 인증 완료)
|
||||||
|
.tfa-cta {
|
||||||
|
width: 100%;
|
||||||
|
height: 56px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: $tfa-blue;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
transition: background 0.12s ease;
|
||||||
|
|
||||||
|
&:hover { background: $tfa-blue-dark; }
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: $tfa-surface;
|
||||||
|
color: $tfa-border-2;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 인증번호 입력 + 재전송
|
||||||
|
.tfa-code-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.tfa-code-input-wrap {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 56px;
|
||||||
|
padding: 0 14px;
|
||||||
|
border: 1px solid $tfa-border-2;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
transition: border-color 0.12s ease;
|
||||||
|
|
||||||
|
&:focus-within { border-color: $tfa-blue; }
|
||||||
|
}
|
||||||
|
|
||||||
.tfa-code-input {
|
.tfa-code-input {
|
||||||
width: 100%;
|
flex: 1;
|
||||||
padding: 14px 64px 14px 16px;
|
min-width: 0;
|
||||||
border: 1px solid #CBD5E1;
|
border: 0;
|
||||||
border-radius: 8px;
|
outline: none;
|
||||||
font-size: 15px;
|
background: transparent;
|
||||||
letter-spacing: 2px;
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
color: $tfa-ink;
|
||||||
|
|
||||||
&:focus {
|
&::placeholder {
|
||||||
outline: none;
|
color: $tfa-border-2;
|
||||||
border-color: $primary-color;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tfa-resend {
|
||||||
|
flex: none;
|
||||||
|
height: 56px;
|
||||||
|
padding: 0 18px;
|
||||||
|
border: 1px solid $tfa-muted;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
color: $tfa-ink;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: background 0.12s ease;
|
||||||
|
|
||||||
|
&:hover { background: $tfa-surface; }
|
||||||
|
&:disabled { opacity: 0.5; cursor: default; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 타이머 행
|
||||||
|
.tfa-timer-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
border: 1px solid $tfa-border;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: $tfa-surface;
|
||||||
|
padding: 12px 14px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.tfa-timer-label {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 300;
|
||||||
|
color: $tfa-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-timer-clock {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
.tfa-timer {
|
.tfa-timer {
|
||||||
position: absolute;
|
font-size: 20px;
|
||||||
right: 16px;
|
font-weight: 500;
|
||||||
color: #E11D48;
|
letter-spacing: 0.02em;
|
||||||
font-size: 14px;
|
color: $tfa-blue;
|
||||||
font-weight: 600;
|
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
|
|
||||||
|
&.is-warning { color: $tfa-danger; }
|
||||||
|
&.is-expired { color: $tfa-muted; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.tfa-timer-total {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 300;
|
||||||
|
color: $tfa-muted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 진행 바
|
||||||
|
.tfa-progress {
|
||||||
|
height: 3px;
|
||||||
|
background: $tfa-border;
|
||||||
|
border-radius: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.tfa-progress-bar {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: $tfa-blue;
|
||||||
|
transition: width 1s linear;
|
||||||
|
|
||||||
|
&.is-warning { background: $tfa-danger; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 발송 안내 / 오류 메시지
|
||||||
.tfa-message {
|
.tfa-message {
|
||||||
min-height: 18px;
|
min-height: 21px;
|
||||||
margin-top: 8px;
|
margin: 0 0 20px;
|
||||||
font-size: 13px;
|
font-size: 14px;
|
||||||
color: #64748B;
|
font-weight: 300;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: $tfa-muted;
|
||||||
|
|
||||||
&.is-error {
|
&.is-error { color: $tfa-danger; }
|
||||||
color: #E11D48;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 테스트 인증번호 노출(개발/스테이지)
|
||||||
.tfa-test-notice {
|
.tfa-test-notice {
|
||||||
margin-top: 8px;
|
margin: 0 0 16px;
|
||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
border: 1px dashed #F59E0B;
|
border: 1px dashed #F59E0B;
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background: #FFFBEB;
|
background: #FFFBEB;
|
||||||
color: #B45309;
|
color: #B45309;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfa-actions {
|
// 하단 안내
|
||||||
display: flex;
|
.tfa-foot {
|
||||||
justify-content: flex-end;
|
margin-top: 24px;
|
||||||
margin: 8px 0;
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid #DFDFDF;
|
||||||
.tfa-resend {
|
font-size: 14px;
|
||||||
background: none;
|
font-weight: 300;
|
||||||
border: none;
|
line-height: 1.5;
|
||||||
color: $primary-color;
|
color: $tfa-muted;
|
||||||
font-size: 13px;
|
}
|
||||||
cursor: pointer;
|
|
||||||
text-decoration: underline;
|
@media (max-width: $breakpoint-sm) {
|
||||||
}
|
.tfa-head { padding: 20px 22px; }
|
||||||
|
.tfa-head .tfa-head-title { font-size: 23px; }
|
||||||
|
.tfa-body { padding: 22px 22px 26px; }
|
||||||
|
.tfa-segment { margin-bottom: 22px; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,49 +3,72 @@
|
|||||||
<div class="modal-backdrop" id="tfaBackdrop"></div>
|
<div class="modal-backdrop" id="tfaBackdrop"></div>
|
||||||
|
|
||||||
<div class="modal" id="tfaModal">
|
<div class="modal" id="tfaModal">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog tfa-card">
|
||||||
|
|
||||||
<div class="modal-header">
|
<button type="button" class="tfa-close" id="tfaCloseButton" aria-label="닫기">
|
||||||
<h3 class="modal-title" id="tfaTitle">
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
|
||||||
<span aria-hidden="true">🔒</span> 추가 인증
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
</h3>
|
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||||
<button type="button" class="modal-close" id="tfaCloseButton" aria-label="닫기">
|
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
</svg>
|
||||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
</button>
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
<!-- 헤더 -->
|
||||||
</svg>
|
<div class="tfa-head">
|
||||||
</button>
|
<span class="tfa-head-title" id="tfaTitle">추가 인증</span>
|
||||||
|
<span class="tfa-head-brand">DJBank</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="tfa-body">
|
||||||
<p class="tfa-subtitle">제주은행(DJBank)에 오신걸 환영합니다</p>
|
|
||||||
|
|
||||||
<!-- 채널 선택 세그먼트 (이메일/전화번호) -->
|
<!-- STEP 1 : 인증 수단 -->
|
||||||
<div class="tfa-segment" id="tfaSegment" role="tablist">
|
<div class="tfa-step">
|
||||||
<!-- JS 가 채널 버튼을 렌더링 -->
|
<span class="tfa-step-num is-active">1</span>
|
||||||
|
<span class="tfa-step-text is-active">인증 수단</span>
|
||||||
|
</div>
|
||||||
|
<!-- 채널 선택(이메일/휴대폰) — JS 가 렌더링 -->
|
||||||
|
<div class="tfa-segment" id="tfaSegment" role="tablist"></div>
|
||||||
|
|
||||||
|
<!-- STEP 2 : 인증번호 입력 -->
|
||||||
|
<div class="tfa-step">
|
||||||
|
<span class="tfa-step-num" id="tfaStepNum">2</span>
|
||||||
|
<span class="tfa-step-text" id="tfaStepText">인증번호 입력</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 인증번호 발송 전 -->
|
<!-- 인증번호 발송 전 -->
|
||||||
<div id="tfaSendStep">
|
<div id="tfaSendStep">
|
||||||
<button type="button" class="btn btn-primary tfa-btn-block" id="tfaSendButton">인증번호 발송</button>
|
<div class="tfa-hint">아래 버튼을 누르면 선택하신 수단으로 6자리 인증번호를 보내드립니다.</div>
|
||||||
|
<button type="button" class="tfa-cta" id="tfaSendButton">인증번호 받기</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 인증번호 발송 후 -->
|
<!-- 인증번호 발송 후 -->
|
||||||
<div id="tfaVerifyStep" style="display: none;">
|
<div id="tfaVerifyStep" style="display: none;">
|
||||||
<div class="tfa-code-row">
|
<div class="tfa-code-row">
|
||||||
<input type="text" id="tfaCodeInput" class="tfa-code-input" inputmode="numeric" maxlength="6"
|
<div class="tfa-code-input-wrap">
|
||||||
autocomplete="one-time-code" placeholder="인증번호를 입력해주세요"/>
|
<input type="text" id="tfaCodeInput" class="tfa-code-input" inputmode="numeric" maxlength="6"
|
||||||
<span class="tfa-timer" id="tfaTimer">03:00</span>
|
autocomplete="one-time-code" placeholder="인증번호 6자리"/>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="tfa-resend" id="tfaResendButton">재전송</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="tfa-message" id="tfaMessage"></div>
|
|
||||||
|
<div class="tfa-timer-row">
|
||||||
|
<span class="tfa-timer-label" id="tfaTimerLabel">남은 인증 시간</span>
|
||||||
|
<span class="tfa-timer-clock">
|
||||||
|
<span class="tfa-timer" id="tfaTimer">3:00</span>
|
||||||
|
<span class="tfa-timer-total" id="tfaTimerTotal">/ 3:00</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tfa-progress"><div class="tfa-progress-bar" id="tfaProgressBar"></div></div>
|
||||||
|
|
||||||
|
<p class="tfa-message" id="tfaMessage"></p>
|
||||||
<div class="tfa-test-notice" id="tfaTestNotice" style="display: none;"></div>
|
<div class="tfa-test-notice" id="tfaTestNotice" style="display: none;"></div>
|
||||||
<div class="tfa-actions">
|
|
||||||
<button type="button" class="tfa-resend" id="tfaResendButton">인증번호 재발송</button>
|
<button type="button" class="tfa-cta" id="tfaVerifyButton" disabled>인증 완료</button>
|
||||||
</div>
|
|
||||||
<button type="button" class="btn btn-primary tfa-btn-block" id="tfaVerifyButton">인증코드 확인</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tfa-foot">인증번호가 오지 않으면 스팸함을 확인하시거나 다른 수단으로 다시 시도해 주세요.</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user