194 lines
7.2 KiB
PHP
194 lines
7.2 KiB
PHP
@extends('web.layouts.auth')
|
|
|
|
@section('title', '회원가입 | PIN FOR YOU')
|
|
@section('meta_description', 'PIN FOR YOU 회원가입 페이지입니다.')
|
|
@section('canonical', url('/auth/register'))
|
|
|
|
@section('h1', '회원가입')
|
|
@section('desc', '휴대폰 번호 확인 후 본인인증을 진행합니다.')
|
|
@section('card_aria', '회원가입 Step0 - 휴대폰 확인')
|
|
@section('show_cs_links', true)
|
|
|
|
@section('auth_content')
|
|
|
|
{{-- Step0 Hero Image + 안내문구 --}}
|
|
<div class="reg-step0-hero" aria-hidden="true">
|
|
<img
|
|
class="reg-step0-hero__img"
|
|
src="{{ asset('assets/images/web/member/register_step0.webp') }}"
|
|
alt=""
|
|
loading="lazy"
|
|
onerror="this.style.display='none';"
|
|
/>
|
|
<div class="reg-step0-hero__text" aria-hidden="true">
|
|
<div class="reg-step0-hero__line">휴대폰 번호로 가입 여부를 먼저 확인한 뒤,</div>
|
|
<div class="reg-step0-hero__line">PASS 본인인증을 진행합니다.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.reg-step0-hero{
|
|
display:flex;
|
|
flex-direction:column;
|
|
align-items:center;
|
|
gap:10px;
|
|
margin: 6px 0 14px;
|
|
}
|
|
.reg-step0-hero__img{
|
|
width:100%;
|
|
max-width: 300px;
|
|
height:auto;
|
|
border-radius: 14px;
|
|
box-shadow: 0 10px 30px rgba(0,0,0,.08);
|
|
background: #fff;
|
|
}
|
|
.reg-step0-hero__text{
|
|
text-align:center;
|
|
font-size: 13px;
|
|
line-height: 1.4;
|
|
color: rgba(0,0,0,.65);
|
|
}
|
|
.reg-step0-hero__line{ margin: 0; }
|
|
</style>
|
|
|
|
<form class="auth-form" id="regStep0Form" onsubmit="return false;">
|
|
@csrf
|
|
|
|
{{-- ✅ hidden input만 생성(토큰은 JS에서 발급 후 payload에 포함) --}}
|
|
<x-recaptcha-v3 />
|
|
|
|
<div class="auth-field">
|
|
<label class="auth-label" for="reg_phone">
|
|
휴대폰 번호 <small>가입 여부 확인</small>
|
|
</label>
|
|
<input class="auth-input" id="reg_phone" name="phone" type="tel"
|
|
placeholder="010-0000-0000"
|
|
autocomplete="tel"
|
|
inputmode="numeric"
|
|
maxlength="13">
|
|
<div class="auth-help" id="reg_phone_help" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="auth-actions">
|
|
<button class="auth-btn auth-btn--primary" id="reg_next_btn" type="submit">다음</button>
|
|
<a class="auth-btn auth-btn--ghost" href="{{ route('web.auth.login') }}">
|
|
이미 계정이 있어요 (로그인)
|
|
</a>
|
|
</div>
|
|
</form>
|
|
|
|
{{-- ✅ reCAPTCHA 스크립트/공통함수는 이 페이지에서만 로드 --}}
|
|
@push('recaptcha')
|
|
<script>window.__recaptchaSiteKey = @json(config('services.recaptcha.site_key'));</script>
|
|
<script src="https://www.google.com/recaptcha/api.js?render={{ config('services.recaptcha.site_key') }}"></script>
|
|
<script src="{{ asset('assets/js/recaptcha-v3.js') }}"></script>
|
|
@endpush
|
|
|
|
<script>
|
|
(function () {
|
|
const form = document.getElementById('regStep0Form');
|
|
const input = document.getElementById('reg_phone');
|
|
const help = document.getElementById('reg_phone_help');
|
|
const btn = document.getElementById('reg_next_btn');
|
|
|
|
function showMsg(msg) {
|
|
help.style.display = 'block';
|
|
help.textContent = msg;
|
|
}
|
|
function clearMsg() {
|
|
help.style.display = 'none';
|
|
help.textContent = '';
|
|
}
|
|
|
|
// 숫자만 남기고 010-0000-0000 형태로 포맷
|
|
function formatPhone(value) {
|
|
const digits = (value || '').replace(/\D/g, '').slice(0, 11);
|
|
if (digits.length <= 3) return digits;
|
|
if (digits.length <= 7) return digits.slice(0, 3) + '-' + digits.slice(3);
|
|
return digits.slice(0, 3) + '-' + digits.slice(3, 7) + '-' + digits.slice(7);
|
|
}
|
|
|
|
// 서버 전송용(숫자만)
|
|
function toDigits(value) {
|
|
return (value || '').replace(/\D/g, '');
|
|
}
|
|
|
|
input.addEventListener('input', function () {
|
|
const formatted = formatPhone(input.value);
|
|
if (input.value !== formatted) input.value = formatted;
|
|
});
|
|
|
|
input.addEventListener('keydown', function (e) {
|
|
const allowKeys = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End'];
|
|
if (allowKeys.includes(e.key)) return;
|
|
if (e.ctrlKey || e.metaKey) return;
|
|
if (!/^\d$/.test(e.key)) e.preventDefault();
|
|
});
|
|
|
|
input.addEventListener('paste', function (e) {
|
|
e.preventDefault();
|
|
const text = (e.clipboardData || window.clipboardData).getData('text') || '';
|
|
const digits = text.replace(/\D/g, '');
|
|
input.value = formatPhone(digits);
|
|
});
|
|
|
|
form.addEventListener('submit', async function () {
|
|
clearMsg();
|
|
|
|
const phoneDigits = toDigits(input.value);
|
|
if (!phoneDigits) {
|
|
showMsg('휴대폰 번호를 입력해 주세요.');
|
|
input.focus();
|
|
return;
|
|
}
|
|
if (phoneDigits.length < 10) {
|
|
showMsg('휴대폰 번호를 끝까지 입력해 주세요.');
|
|
input.focus();
|
|
return;
|
|
}
|
|
|
|
btn.disabled = true;
|
|
|
|
try {
|
|
// ✅ 공통 함수로 토큰 발급 (한 줄)
|
|
const token = await window.recaptchaV3Token('register_phone_check', form);
|
|
|
|
const res = await fetch("{{ route('web.auth.register.phone_check') }}", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"X-CSRF-TOKEN": "{{ csrf_token() }}",
|
|
"Accept": "application/json"
|
|
},
|
|
body: JSON.stringify({
|
|
phone: phoneDigits,
|
|
"g-recaptcha-response": token
|
|
})
|
|
});
|
|
|
|
const data = await res.json().catch(() => ({}));
|
|
|
|
if (!res.ok || data.ok === false) {
|
|
showMsg(data.message || '처리에 실패했습니다.');
|
|
return;
|
|
}
|
|
|
|
if (data.redirect) {
|
|
window.location.href = data.redirect;
|
|
return;
|
|
}
|
|
|
|
showMsg('처리에 실패했습니다.');
|
|
} catch (e) {
|
|
showMsg('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.');
|
|
} finally {
|
|
btn.disabled = false;
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
@endsection
|
|
|
|
@section('auth_bottom')
|
|
@endsection
|