563 lines
24 KiB
PHP
563 lines
24 KiB
PHP
@extends('web.layouts.auth')
|
|
|
|
@section('title', '회원정보 입력 | PIN FOR YOU')
|
|
@section('meta_description', 'PIN FOR YOU 회원정보 입력 단계입니다.')
|
|
@section('canonical', url('/auth/register/profile'))
|
|
|
|
@section('h1', '회원정보 입력')
|
|
@section('desc', '본인인증 정보는 수정할 수 없으며, 아이디/비밀번호 등 가입 정보를 입력해 주세요.')
|
|
@section('card_aria', '회원가입 Step2 - 가입정보 입력')
|
|
@section('show_cs_links', true)
|
|
|
|
@section('auth_content')
|
|
<form class="auth-form" id="regProfileForm" method="POST" action="{{ route('web.auth.register.profile.submit') }}" novalidate>
|
|
@csrf
|
|
|
|
{{-- 진행 단계 --}}
|
|
<div class="terms-wrap">
|
|
<div class="terms-steps" aria-label="진행 단계">
|
|
<div class="terms-step">가입정보확인</div>
|
|
<div class="terms-step">약관/인증 확인</div>
|
|
<div class="terms-step is-active">가입정보입력</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
{{-- PASS 인증 정보(수정 불가) --}}
|
|
<div class="auth-field">
|
|
<div style="font-weight:800; margin-bottom:8px; opacity:.9;">본인인증 정보</div>
|
|
|
|
@php
|
|
$pv = (array) session('register.pass_payload', []);
|
|
|
|
$pvName = $pv['NAME'] ?? '-';
|
|
$pvBirth = $pv['DOB'] ?? null; // YYYYMMDD
|
|
$pvSex = $pv['SEX'] ?? null; // 1/2 등
|
|
$pvNation = $pv['FOREIGNER'] ?? null; // 0/1
|
|
$pvTelco = $pv['CARRIER'] ?? (session('signup.carrier') ?? '-'); // SKT/KT/LGU+ 또는 코드
|
|
$pvPhone = $pv['PHONE'] ?? (session('signup.phone') ?? '-');
|
|
|
|
// 표시용 변환(성별/내외국인)
|
|
$pvSexText = match((string)$pvSex) {
|
|
'1' => '남',
|
|
'2' => '여',
|
|
default => ($pvSex ?? '-'),
|
|
};
|
|
|
|
$pvNationText = match((string)$pvNation) {
|
|
'0' => '내국인',
|
|
'1' => '외국인',
|
|
default => ($pvNation ?? '-'),
|
|
};
|
|
|
|
// 생년월일 포맷
|
|
$pvBirthText = '-';
|
|
if (is_string($pvBirth) && strlen($pvBirth) >= 8) {
|
|
$pvBirthText = substr($pvBirth,0,4).'년 '.substr($pvBirth,4,2).'월 '.substr($pvBirth,6,2).'일';
|
|
} elseif (!empty($pvBirth)) {
|
|
$pvBirthText = (string)$pvBirth;
|
|
}
|
|
|
|
// 휴대폰 포맷(표시용)
|
|
$pvPhoneText = (string)$pvPhone;
|
|
if (is_string($pvPhone) && preg_match('/^\d{10,11}$/', $pvPhone)) {
|
|
$pvPhoneText = substr($pvPhone,0,3).'-'.substr($pvPhone,3,4).'-'.substr($pvPhone,7);
|
|
}
|
|
@endphp
|
|
|
|
<div class="profile-grid">
|
|
<div class="profile-item">
|
|
<div class="profile-label">성명</div>
|
|
<div class="profile-value">{{ $pvName}}</div>
|
|
</div>
|
|
<div class="profile-item">
|
|
<div class="profile-label">생년월일</div>
|
|
<div class="profile-value">{{ $pvBirthText }}</div>
|
|
</div>
|
|
<div class="profile-item">
|
|
<div class="profile-label">성별</div>
|
|
<div class="profile-value">{{ $pvSexText }}</div>
|
|
</div>
|
|
<div class="profile-item">
|
|
<div class="profile-label">내외국인</div>
|
|
<div class="profile-value">{{ $pvNationText}}</div>
|
|
</div>
|
|
<div class="profile-item">
|
|
<div class="profile-label">통신사</div>
|
|
<div class="profile-value">{{ $pvTelco }}</div>
|
|
</div>
|
|
<div class="profile-item">
|
|
<div class="profile-label">휴대전화번호</div>
|
|
<div class="profile-value">{{ $pvPhoneText}}</div>
|
|
</div>
|
|
</div>
|
|
<div class="auth-help" style="display:block;opacity:.7;margin-top:8px">
|
|
위 정보가 다르면 인증을 중단하고 처음부터 다시 진행해 주세요.
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 아이디(이메일) --}}
|
|
<div class="auth-field">
|
|
<label class="auth-label" for="login_id">아이디(이메일)</label>
|
|
<input class="auth-input" id="login_id" name="login_id" type="email"
|
|
placeholder="example@domain.com"
|
|
autocomplete="username"
|
|
maxlength="60"
|
|
required>
|
|
<div class="auth-help" id="login_id_help" style="display:none;"></div>
|
|
</div>
|
|
|
|
{{-- 비밀번호(6자리 숫자) --}}
|
|
<div class="auth-field">
|
|
<label class="auth-label" for="password">비밀번호</label>
|
|
<input class="auth-input" id="password" name="password" type="password"
|
|
placeholder="영문+숫자+특수문자 포함 8자 이상"
|
|
minlength="8" maxlength="20"
|
|
autocomplete="new-password"
|
|
required>
|
|
<div class="auth-help" id="password_help" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="auth-field">
|
|
<label class="auth-label" for="password_confirmation">비밀번호 확인</label>
|
|
<input class="auth-input" id="password_confirmation" name="password_confirmation" type="password"
|
|
placeholder="비밀번호 확인"
|
|
minlength="8" maxlength="20"
|
|
autocomplete="new-password"
|
|
required>
|
|
<div class="auth-help" id="password_confirmation_help" style="display:none;"></div>
|
|
</div>
|
|
|
|
|
|
{{-- 2차 비밀번호(4자리 숫자) --}}
|
|
<div class="auth-row" style="gap:10px">
|
|
<div class="auth-field" style="flex:1">
|
|
<label class="auth-label" for="pin2">2차 비밀번호(숫자 4자리)</label>
|
|
<input class="auth-input" id="pin2" name="pin2" type="password"
|
|
inputmode="numeric" pattern="\d{4}" maxlength="4"
|
|
placeholder="숫자 4자리"
|
|
required>
|
|
<div class="auth-help" id="pin2_help" style="display:none;"></div>
|
|
</div>
|
|
<div class="auth-field" style="flex:1">
|
|
<label class="auth-label" for="pin2_confirmation">2차 비밀번호 확인</label>
|
|
<input class="auth-input" id="pin2_confirmation" name="pin2_confirmation" type="password"
|
|
inputmode="numeric" pattern="\d{4}" maxlength="4"
|
|
placeholder="숫자 4자리 확인"
|
|
required>
|
|
<div class="auth-help" id="pin2_confirmation_help" style="display:none;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="auth-actions">
|
|
<button class="auth-btn auth-btn--primary" id="profile_submit_btn" type="submit" >가입 완료</button>
|
|
<a class="auth-btn auth-btn--ghost" href="{{ route('web.auth.register') }}">처음으로</a>
|
|
</div>
|
|
</form>
|
|
|
|
<style>
|
|
.terms-wrap{display:flex;flex-direction:column;gap:14px}
|
|
.terms-steps{
|
|
display:flex;
|
|
gap:10px;
|
|
align-items:center;
|
|
justify-content:space-between;
|
|
}
|
|
|
|
.terms-step{
|
|
flex:1;
|
|
text-align:center;
|
|
padding:10px 12px;
|
|
border-radius:999px; /* badge */
|
|
font-size:12.5px;
|
|
font-weight:800;
|
|
letter-spacing:-0.2px;
|
|
margin-top: 10px;
|
|
margin-bottom: 50px;
|
|
|
|
/* 기본(비활성) */
|
|
color: rgba(136, 105, 105, 0.78);
|
|
border:1px solid rgba(255,255,255,.14);
|
|
background:rgba(255,255,255,.06);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255,255,255,.10),
|
|
0 10px 22px rgba(0,0,0,.14);
|
|
|
|
opacity:.78;
|
|
position:relative;
|
|
overflow:hidden;
|
|
}
|
|
|
|
/* 비활성도 살짝 그라데이션 느낌(은은하게) */
|
|
.terms-step::before{
|
|
content:"";
|
|
position:absolute;
|
|
inset:0;
|
|
background:linear-gradient(135deg,
|
|
rgba(47,107,255,.18),
|
|
rgba(74,163,255,.14),
|
|
rgba(47,210,255,.12)
|
|
);
|
|
opacity:.55;
|
|
pointer-events:none;
|
|
}
|
|
|
|
/* 활성: 선명한 그라데이션 */
|
|
.terms-step.is-active{
|
|
opacity:1;
|
|
color:#fff;
|
|
border-color:rgba(120,180,255,.50);
|
|
background:linear-gradient(135deg, #2f6bff 0%, #4aa3ff 55%, #2fd2ff 100%);
|
|
box-shadow:
|
|
0 18px 38px rgba(47,107,255,.28),
|
|
0 10px 20px rgba(47,210,255,.14);
|
|
}
|
|
|
|
/* shine 효과 (활성만) */
|
|
.terms-step.is-active::after{
|
|
content:"";
|
|
position:absolute;
|
|
top:-40%;
|
|
left:-45%;
|
|
width:55%;
|
|
height:180%;
|
|
transform:rotate(18deg);
|
|
background:linear-gradient(90deg, transparent, rgba(255,255,255,.35), transparent);
|
|
opacity:.55;
|
|
animation: termsStepShine 2.8s ease-in-out infinite;
|
|
pointer-events:none;
|
|
}
|
|
|
|
@keyframes termsStepShine{
|
|
0% { transform: translateX(-30%) rotate(18deg); opacity:.20; }
|
|
45% { opacity:.70; }
|
|
100% { transform: translateX(240%) rotate(18deg); opacity:.20; }
|
|
}
|
|
|
|
/* 모바일에서 글자 길어서 깨질 때 대비 */
|
|
@media (max-width: 420px){
|
|
.terms-step{
|
|
font-size:12px;
|
|
padding:10px 10px;
|
|
}
|
|
}
|
|
|
|
.profile-grid{
|
|
display:grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap:10px;
|
|
}
|
|
@media (max-width: 420px){
|
|
.profile-grid{ grid-template-columns: 1fr; }
|
|
}
|
|
.profile-item{
|
|
border:1px solid rgba(255,255,255,.12);
|
|
background:rgba(255,255,255,.04);
|
|
border-radius:14px;
|
|
padding:10px 12px;
|
|
}
|
|
.profile-label{font-size:12px; opacity:.7; margin-bottom:6px; font-weight:700}
|
|
.profile-value{font-size:13px; font-weight:900; letter-spacing:.2px}
|
|
.auth-help.is-ok{display:block !important; color: rgba(120,255,180,.9); }
|
|
.auth-help.is-bad{display:block !important; color: rgba(255,120,120,.95); }
|
|
.auth-help { white-space: pre-line; }
|
|
</style>
|
|
|
|
<script>
|
|
(() => {
|
|
const form = document.getElementById('regProfileForm');
|
|
const btn = document.getElementById('profile_submit_btn');
|
|
|
|
const loginId = document.getElementById('login_id');
|
|
const pw1 = document.getElementById('password');
|
|
const pw2 = document.getElementById('password_confirmation');
|
|
const p2 = document.getElementById('pin2');
|
|
const p2c = document.getElementById('pin2_confirmation');
|
|
|
|
const loginHelp = document.getElementById('login_id_help'); // 그대로 사용 (blur에서만 갱신)
|
|
const pwRuleHelp = document.getElementById('password_help');
|
|
const pwMatchHelp = document.getElementById('password_confirmation_help');
|
|
const p2MatchHelp = document.getElementById('pin2_confirmation_help');
|
|
|
|
const PW_MIN = 8;
|
|
const PW_MAX = 20;
|
|
|
|
const ALLOWED_SPECIALS_TEXT = `! @ # $ % ^ & * ( ) - _ = + [ ] { } ; : ' " , . < > ? | ~ \``;
|
|
const ALLOWED_SPECIALS_REGEX = `!@#$%^&*()\\-_=+\\[\\]{};:'",.<>\\/\\?\\\\|\\\`~`;
|
|
|
|
let lastCheckedLogin = '';
|
|
let duplicateOk = false;
|
|
let isSubmitting = false;
|
|
|
|
function showAlert(message, title = '안내') {
|
|
// 네가 쓰는 함수명에 맞춰 호출 (없으면 alert fallback)
|
|
if (typeof window.showAlert === 'function') return window.showAlert(message, title);
|
|
if (typeof window.showMsg === 'function') return window.showMsg(message, { type:'alert', title });
|
|
alert(`${title}\n\n${message}`);
|
|
return Promise.resolve();
|
|
}
|
|
|
|
function setHelp(el, msg, ok) {
|
|
if (!el) return;
|
|
el.classList.remove('is-ok', 'is-bad');
|
|
el.style.display = msg ? 'block' : 'none';
|
|
el.textContent = msg || '';
|
|
if (msg) el.classList.add(ok ? 'is-ok' : 'is-bad');
|
|
}
|
|
|
|
function emailFormatOk(v){
|
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v || '');
|
|
}
|
|
|
|
function onlyDigitsInput(e, maxLen) {
|
|
const allow = ['Backspace','Delete','ArrowLeft','ArrowRight','Tab','Home','End'];
|
|
if (allow.includes(e.key)) return;
|
|
if (e.ctrlKey || e.metaKey) return;
|
|
if (!/^\d$/.test(e.key)) e.preventDefault();
|
|
if (maxLen && e.target.value && e.target.value.length >= maxLen) e.preventDefault();
|
|
}
|
|
|
|
[p2, p2c].forEach(el => {
|
|
if (!el) return;
|
|
el.addEventListener('keydown', (e) => onlyDigitsInput(e, 4));
|
|
el.addEventListener('input', () => { el.value = (el.value||'').replace(/\D/g,'').slice(0,4); });
|
|
});
|
|
|
|
function pwHasDigit(pw){ return /\d/.test(pw || ''); }
|
|
function pwHasLetter(pw){ return /[A-Za-z]/.test(pw || ''); }
|
|
function pwHasAllowedSpecial(pw){
|
|
const re = new RegExp(`[${ALLOWED_SPECIALS_REGEX}]`);
|
|
return re.test(pw || '');
|
|
}
|
|
function pwHasDisallowedChar(pw){
|
|
const re = new RegExp(`^[A-Za-z0-9${ALLOWED_SPECIALS_REGEX}]*$`);
|
|
return !re.test(pw || '');
|
|
}
|
|
|
|
function passwordRuleMessage(pw){
|
|
const s = pw || '';
|
|
if (s.length < PW_MIN) return `비밀번호는 ${PW_MIN}자리 이상 입력해 주세요.`;
|
|
if (s.length > PW_MAX) return `비밀번호는 ${PW_MAX}자리를 초과할 수 없습니다.`;
|
|
if (!pwHasLetter(s)) return `비밀번호에 영문(A-Z, a-z)을 포함해 주세요.`;
|
|
if (!pwHasDigit(s)) return `비밀번호에 숫자를 포함해 주세요.`;
|
|
if (!pwHasAllowedSpecial(s)) {
|
|
// 줄바꿈: CSS(pre-line) 적용돼 있으니 \n 사용
|
|
return `특수문자를 입력해 주세요.\n(허용: ${ALLOWED_SPECIALS_TEXT})`;
|
|
}
|
|
if (pwHasDisallowedChar(s)) {
|
|
return `허용되지 않은 문자가 포함되어 있습니다.\n(허용: 영문/숫자/지정 특수문자)`;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function validatePasswordFields(showHelp = true){
|
|
let ok = true;
|
|
|
|
const a = (pw1.value || '');
|
|
const b = (pw2.value || '');
|
|
|
|
const msg = passwordRuleMessage(a);
|
|
if (msg) {
|
|
ok = false;
|
|
if (showHelp) setHelp(pwRuleHelp, msg, false);
|
|
} else {
|
|
if (showHelp && a) setHelp(pwRuleHelp, '비밀번호 조건 충족', true);
|
|
if (showHelp && !a) setHelp(pwRuleHelp, '', true);
|
|
}
|
|
|
|
if (b) {
|
|
if (a !== b) {
|
|
ok = false;
|
|
if (showHelp) setHelp(pwMatchHelp, '비밀번호가 일치하지 않습니다.', false);
|
|
} else if (!msg) {
|
|
if (showHelp) setHelp(pwMatchHelp, '비밀번호 확인 완료', true);
|
|
} else {
|
|
ok = false;
|
|
if (showHelp) setHelp(pwMatchHelp, '', true);
|
|
}
|
|
} else {
|
|
if (showHelp) setHelp(pwMatchHelp, '', true);
|
|
if (a) ok = false; // 확인값 없으면 통과 불가
|
|
}
|
|
|
|
const p2v = (p2.value || '');
|
|
const p2cv = (p2c.value || '');
|
|
|
|
if (p2v.length !== 4) ok = false;
|
|
if (p2cv.length !== 4) ok = false;
|
|
|
|
if (p2cv) {
|
|
if (p2v !== p2cv) {
|
|
ok = false;
|
|
if (showHelp) setHelp(p2MatchHelp, '2차 비밀번호가 일치하지 않습니다.', false);
|
|
} else if (p2v.length === 4) {
|
|
if (showHelp) setHelp(p2MatchHelp, '2차 비밀번호 확인 완료', true);
|
|
}
|
|
} else {
|
|
if (showHelp) setHelp(p2MatchHelp, '', true);
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
async function postJson(url, payload){
|
|
const res = await fetch(url, {
|
|
method: 'POST',
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-TOKEN': "{{ csrf_token() }}",
|
|
'Accept': 'application/json',
|
|
},
|
|
body: JSON.stringify(payload || {})
|
|
});
|
|
|
|
const raw = await res.text();
|
|
let data = {};
|
|
try { data = JSON.parse(raw || "{}"); } catch(e) {}
|
|
return { res, data };
|
|
}
|
|
|
|
async function ensureEmailDuplicateChecked(){
|
|
const v = (loginId.value || '').trim();
|
|
|
|
if (!v) {
|
|
await showAlert('이메일을 입력해 주세요.', '안내');
|
|
loginId.focus();
|
|
return false;
|
|
}
|
|
|
|
if (!emailFormatOk(v)) {
|
|
await showAlert('이메일 형식으로 입력해 주세요.', '안내');
|
|
loginId.focus();
|
|
return false;
|
|
}
|
|
|
|
// 이미 같은 값에 대해 통과한 중복체크가 있으면 skip
|
|
if (duplicateOk && lastCheckedLogin === v) return true;
|
|
|
|
// 중복체크 시도
|
|
try {
|
|
// loginHelp는 “그대로 표시” 원칙이라 여기서 메시지 바꾸지 않음
|
|
const { res, data } = await postJson("{{ route('web.auth.register.check_login_id') }}", { login_id: v });
|
|
|
|
if (res.ok && data && data.ok === true) {
|
|
duplicateOk = true;
|
|
lastCheckedLogin = v;
|
|
return true;
|
|
}
|
|
|
|
duplicateOk = false;
|
|
lastCheckedLogin = '';
|
|
await showAlert(data.message || '이미 사용 중인 이메일(아이디)입니다.', '안내');
|
|
loginId.focus();
|
|
return false;
|
|
|
|
} catch (e) {
|
|
duplicateOk = false;
|
|
lastCheckedLogin = '';
|
|
await showAlert('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.', '오류');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// loginHelp는 그대로: blur에서만 업데이트 (시각적 도움용)
|
|
loginId.addEventListener('blur', async () => {
|
|
const v = (loginId.value || '').trim();
|
|
|
|
duplicateOk = false;
|
|
lastCheckedLogin = '';
|
|
|
|
if (!v) { setHelp(loginHelp, '아이디(이메일)를 입력해 주세요.', false); return; }
|
|
if (!emailFormatOk(v)) { setHelp(loginHelp, '이메일 형식으로 입력해 주세요.', false); return; }
|
|
|
|
setHelp(loginHelp, '중복 확인 중...', true);
|
|
|
|
try {
|
|
const { res, data } = await postJson("{{ route('web.auth.register.check_login_id') }}", { login_id: v });
|
|
if (res.ok && data && data.ok === true) {
|
|
duplicateOk = true;
|
|
lastCheckedLogin = v;
|
|
setHelp(loginHelp, '사용 가능한 아이디입니다.', true);
|
|
} else {
|
|
duplicateOk = false;
|
|
lastCheckedLogin = '';
|
|
setHelp(loginHelp, data.message || '이미 사용 중인 아이디입니다.', false);
|
|
}
|
|
} catch (e) {
|
|
duplicateOk = false;
|
|
lastCheckedLogin = '';
|
|
setHelp(loginHelp, '네트워크 오류로 중복 확인 실패', false);
|
|
}
|
|
});
|
|
|
|
// 사용자가 이메일을 수정하면 중복체크 결과 무효화 (loginHelp는 굳이 건드리지 않음)
|
|
loginId.addEventListener('input', () => {
|
|
duplicateOk = false;
|
|
lastCheckedLogin = '';
|
|
});
|
|
|
|
// 비밀번호 입력 중 도움말은 즉시 표시
|
|
[pw1, pw2, p2, p2c].forEach(el => {
|
|
if (!el) return;
|
|
el.addEventListener('input', () => validatePasswordFields(true));
|
|
});
|
|
|
|
// 가입 버튼 눌렀을 때 “무조건 반응” + 단계별 안내
|
|
form.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
if (isSubmitting) return;
|
|
|
|
isSubmitting = true;
|
|
btn.disabled = true;
|
|
|
|
try {
|
|
// 1) 이메일 체크 + (필요시) 중복체크
|
|
const emailOk = await ensureEmailDuplicateChecked();
|
|
if (!emailOk) return;
|
|
|
|
// 2) 비밀번호/확인/2차비번 체크
|
|
const pwOk = validatePasswordFields(true);
|
|
if (!pwOk) {
|
|
// 상황별로 더 직관적 메시지
|
|
const pwMsg = passwordRuleMessage(pw1.value || '');
|
|
if (!pw1.value) {
|
|
await showAlert('비밀번호를 입력해 주세요.', '안내'); pw1.focus(); return;
|
|
}
|
|
if (pwMsg) {
|
|
await showAlert(pwMsg, '안내'); pw1.focus(); return;
|
|
}
|
|
if ((pw1.value || '') !== (pw2.value || '')) {
|
|
await showAlert('비밀번호 확인이 일치하지 않습니다.', '안내'); pw2.focus(); return;
|
|
}
|
|
if ((p2.value || '').length !== 4) {
|
|
await showAlert('2차 비밀번호(숫자 4자리)를 입력해 주세요.', '안내'); p2.focus(); return;
|
|
}
|
|
if ((p2.value || '') !== (p2c.value || '')) {
|
|
await showAlert('2차 비밀번호 확인이 일치하지 않습니다.', '안내'); p2c.focus(); return;
|
|
}
|
|
|
|
await showAlert('입력값을 확인해 주세요.', '안내');
|
|
return;
|
|
}
|
|
|
|
// 3) 최종 제출
|
|
form.submit();
|
|
|
|
} catch (err) {
|
|
await showAlert('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.', '오류');
|
|
} finally {
|
|
isSubmitting = false;
|
|
// submit 성공이면 페이지 이동, 실패 시 버튼 복구
|
|
setTimeout(() => { btn.disabled = false; }, 200);
|
|
}
|
|
});
|
|
|
|
// 초기 도움말 정리
|
|
validatePasswordFields(false);
|
|
})();
|
|
</script>
|
|
|
|
|
|
@endsection
|