234 lines
10 KiB
PHP
234 lines
10 KiB
PHP
@extends('web.layouts.subpage')
|
|
|
|
@php
|
|
$pageTitle = '1:1 문의';
|
|
$pageDesc = '결제·발송·코드 확인 등 상세 문의는 접수 후 순차적으로 답변드려요.';
|
|
|
|
$breadcrumbs = [
|
|
['label' => '홈', 'url' => url('/')],
|
|
['label' => '고객센터', 'url' => url('/cs/notice')],
|
|
['label' => '1:1 문의', 'url' => url()->current()],
|
|
];
|
|
|
|
// 고객센터 탭
|
|
$subnavItems = collect(config('web.cs_tabs', []))->map(fn($t) => [
|
|
'label' => $t['label'],
|
|
'url' => route($t['route']),
|
|
'key' => $t['key'],
|
|
])->all();
|
|
$subnavActive = 'qna';
|
|
|
|
// 문의 분류 (FAQ 카테고리와 맞춰 통일)
|
|
$enquiryCategories = config('cs_faq.categories', [
|
|
['key' => 'signup', 'label' => '회원가입 문의'],
|
|
['key' => 'login', 'label' => '로그인 문의'],
|
|
['key' => 'pay', 'label' => '결제 문의'],
|
|
['key' => 'code', 'label' => '상품권 코드 문의'],
|
|
['key' => 'event', 'label' => '이벤트 문의'],
|
|
['key' => 'etc', 'label' => '기타문의'],
|
|
]);
|
|
@endphp
|
|
|
|
@section('title', '1:1 문의 | PIN FOR YOU')
|
|
@section('meta_description', '핀포유 1:1 문의 페이지입니다. 결제/발송/코드 확인 등 상세 문의를 접수하면 순차적으로 답변드립니다.')
|
|
@section('canonical', url('/cs/qna'))
|
|
|
|
@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
|
|
@push('styles')
|
|
<link rel="stylesheet" href="{{ asset('assets/css/cs_qna.css') }}?v={{ config('app.version', time()) }}">
|
|
@endpush
|
|
|
|
@section('subcontent')
|
|
@include('web.partials.content-head', [
|
|
'title' => '1:1 문의 접수',
|
|
'desc' => '정확한 처리를 위해 주문 정보와 상황을 구체적으로 작성해 주세요.'
|
|
])
|
|
|
|
<section class="qna" aria-label="1:1 문의 폼">
|
|
|
|
{{-- Top actions --}}
|
|
<div class="qna-top">
|
|
<div class="qna-top__hint">
|
|
<span class="qna-pill">안내</span>
|
|
운영시간 평일 09:00~18:00 · 점심 12:00~13:00 · 주말/공휴일 휴무
|
|
</div>
|
|
|
|
<div class="qna-top__actions">
|
|
<a class="qna-btn qna-btn--ghost"
|
|
href="{{ route('web.mypage.qna.index') }}">
|
|
내 문의내용 확인
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Form card --}}
|
|
<div class="qna-card">
|
|
<div class="qna-card__head">
|
|
<h2 class="qna-card__title">내용 작성</h2>
|
|
<p class="qna-card__desc">답변 속도를 높이려면 “주문시각/결제수단/금액/오류문구”를 같이 적어주세요.</p>
|
|
</div>
|
|
|
|
<form class="qna-form" id="qnaForm" action="{{ route('web.cs.qna.store') }}" method="post" novalidate>
|
|
@csrf
|
|
<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response" value="">
|
|
<input type="text" name="hp" value="" autocomplete="off"
|
|
style="position:absolute; left:-9999px; width:1px; height:1px; opacity:0;"
|
|
tabindex="-1" aria-hidden="true">
|
|
|
|
{{-- Subject row --}}
|
|
<div class="qna-grid">
|
|
|
|
<div class="qna-field">
|
|
<label class="qna-label" for="enquiry_code">문의분류 <span class="qna-req">*</span></label>
|
|
<select class="qna-input" id="enquiry_code" name="enquiry_code" required>
|
|
<option value="">문의분류선택</option>
|
|
@foreach(($enquiryCodes ?? []) as $c)
|
|
<option value="{{ $c['code'] }}" @selected(old('enquiry_code') == $c['code'])>
|
|
{{ $c['title'] }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
<div class="qna-help">가장 가까운 분류를 선택해 주세요.</div>
|
|
</div>
|
|
|
|
<div class="qna-field">
|
|
<label class="qna-label" for="enquiry_title">문의 제목 <span class="qna-req">*</span></label>
|
|
<input class="qna-input" type="text" id="enquiry_title" name="enquiry_title"
|
|
maxlength="30" placeholder="문의 제목을 넣어주세요."
|
|
value="{{ old('enquiry_title') }}"
|
|
required>
|
|
<div class="qna-help">제목은 30자 이내로 작성해 주세요.</div>
|
|
</div>
|
|
|
|
</div>
|
|
{{-- Content --}}
|
|
<div class="qna-field qna-field--mt">
|
|
<label class="qna-label" for="enquiry_content">문의 내용 <span class="qna-req">*</span></label>
|
|
<textarea class="qna-textarea" id="enquiry_content" name="enquiry_content"
|
|
placeholder="문제 상황을 자세히 적어주세요. 예) 주문시각/결제수단/금액/오류메시지/상품명"
|
|
required>{{ old('enquiry_content') }}</textarea>
|
|
<div class="qna-help">
|
|
정확한 안내를 위해 개인정보(주민번호/전체 카드번호 등)는 작성하지 마세요.
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Reply options --}}
|
|
<div class="qna-field qna-field--mt">
|
|
<div class="qna-label">추가회신</div>
|
|
<div class="qna-choice">
|
|
<label class="qna-check">
|
|
<input type="checkbox" checked disabled>
|
|
<span>웹답변</span>
|
|
</label>
|
|
|
|
<label class="qna-radio">
|
|
<input type="radio" name="return_type" value="sms">
|
|
<span>SMS 알림</span>
|
|
</label>
|
|
|
|
<label class="qna-radio">
|
|
<input type="radio" name="return_type" value="email">
|
|
<span>이메일 답변</span>
|
|
</label>
|
|
</div>
|
|
<div class="qna-help">현재는 UI만 제공되며, 실제 알림 연동은 추후 적용됩니다.</div>
|
|
</div>
|
|
|
|
|
|
{{-- Submit --}}
|
|
<div class="qna-actions">
|
|
<button class="qna-btn qna-btn--primary" type="submit">문의등록</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
@include('web.partials.cs-quick-actions')
|
|
</section>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
(() => {
|
|
const form = document.getElementById('qnaForm');
|
|
if (!form) return;
|
|
|
|
const btn = form.querySelector('button[type="submit"]');
|
|
|
|
function ensureHiddenRecaptcha(){
|
|
let el = document.getElementById('g-recaptcha-response');
|
|
if(!el){
|
|
el = document.createElement('input');
|
|
el.type = 'hidden';
|
|
el.id = 'g-recaptcha-response';
|
|
el.name = 'g-recaptcha-response';
|
|
form.appendChild(el);
|
|
}
|
|
return el;
|
|
}
|
|
|
|
async function getRecaptchaToken(action){
|
|
if (typeof window.recaptchaV3Exec === 'function') {
|
|
try { return (await window.recaptchaV3Exec(action)) || ''; } catch(e){ return ''; }
|
|
}
|
|
const siteKey = window.__recaptchaSiteKey || '';
|
|
if (!siteKey || typeof window.grecaptcha === 'undefined') return '';
|
|
try {
|
|
await new Promise(r => window.grecaptcha.ready(r));
|
|
return (await window.grecaptcha.execute(siteKey, { action })) || '';
|
|
} catch(e){
|
|
return '';
|
|
}
|
|
}
|
|
|
|
form.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
|
|
// 프론트 기본 폼체크(너가 이미 구현한 것 있으면 유지)
|
|
const code = (document.getElementById('enquiry_code')?.value || '').trim();
|
|
const title = (document.getElementById('enquiry_title')?.value || '').trim();
|
|
const content = (document.getElementById('enquiry_content')?.value || '').trim();
|
|
|
|
if (!code) { await showMsg("문의분류를 선택해 주세요.", { type:'alert', title:'폼체크' }); return; }
|
|
if (!title) { await showMsg("문의 제목을 입력해 주세요.", { type:'alert', title:'폼체크' }); return; }
|
|
if (!content) { await showMsg("문의 내용을 입력해 주세요.", { type:'alert', title:'폼체크' }); return; }
|
|
|
|
if (btn) btn.disabled = true;
|
|
|
|
try {
|
|
const isProd = @json(app()->environment('production'));
|
|
const hasKey = @json((bool) config('services.recaptcha.site_key'));
|
|
|
|
if (isProd && hasKey) {
|
|
const hidden = ensureHiddenRecaptcha();
|
|
hidden.value = '';
|
|
|
|
const token = await getRecaptchaToken('cs_qna_create');
|
|
hidden.value = token || '';
|
|
|
|
if (!hidden.value) {
|
|
if (btn) btn.disabled = false;
|
|
await showMsg('보안 검증(캡챠) 로딩에 실패했습니다. 새로고침 후 다시 시도해 주세요.', {
|
|
type:'alert', title:'보안검증 실패'
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
form.submit();
|
|
} catch (err) {
|
|
if (btn) btn.disabled = false;
|
|
await showMsg('문의 등록 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.', {
|
|
type:'alert', title:'오류'
|
|
});
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
@endpush
|
|
|
|
|
|
|