251 lines
14 KiB
PHP
251 lines
14 KiB
PHP
@extends('web.layouts.subpage')
|
|
|
|
@push('styles')
|
|
<style>
|
|
/* 전체 레이아웃 50:50 비율 */
|
|
.p-detail-container { display: flex; gap: 40px; margin-bottom: 40px; align-items: flex-start; }
|
|
.p-detail-visual { flex: 5; }
|
|
.p-detail-info { flex: 5; display: flex; flex-direction: column; gap: 24px; }
|
|
|
|
/* 이미지 카드 */
|
|
.p-main-img-card { background: #fff; border: 1px solid #eee; border-radius: 16px; display: flex; align-items: center; justify-content: center; padding: 30px; aspect-ratio: 1/1; margin-bottom: 30px; }
|
|
.p-main-img-card img { width: 100%; max-width: 320px; height: auto; filter: drop-shadow(0 10px 20px rgba(0,0,0,0.05)); }
|
|
|
|
/* 탭 버튼 그룹 (부트스트랩 스타일) */
|
|
.p-tab-container { margin-top: 20px; }
|
|
.p-btn-group { display: flex; border: 1px solid #dee2e6; border-radius: 8px; overflow: hidden; margin-bottom: 20px; }
|
|
.p-tab-btn { flex: 1; padding: 12px; border: none; background: #f8f9fa; color: #495057; font-weight: 700; cursor: pointer; transition: 0.2s; border-right: 1px solid #dee2e6; }
|
|
.p-tab-btn:last-child { border-right: none; }
|
|
.p-tab-btn.is-active { background: #3182ce; color: #fff; }
|
|
|
|
.p-tab-content { padding: 20px; background: #fff; border: 1px solid #edf2f7; border-radius: 12px; min-height: 150px; }
|
|
.p-content-pane { display: none; font-size: 15px; color: #4a5568; line-height: 1.7; }
|
|
.p-content-pane.is-active { display: block; }
|
|
|
|
/* 권종 선택 (웹: 2줄) */
|
|
.p-sku-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
|
|
.p-sku-btn { background: #fff; border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; transition: all 0.2s; position: relative; cursor: pointer; text-align: left; }
|
|
.p-sku-btn.is-active { border-color: #3182ce; background: #ebf8ff; box-shadow: 0 0 0 1px #3182ce; }
|
|
.p-sku-price { font-size: 18px; font-weight: 800; color: #2d3748; }
|
|
|
|
/* 수량 및 결제 수단 */
|
|
.p-qty-wrapper { display: flex; align-items: center; justify-content: space-between; padding: 15px 0; border-top: 1px solid #edf2f7; border-bottom: 1px solid #edf2f7; }
|
|
.p-qty-ctrl { display: flex; align-items: center; border: 1px solid #cbd5e0; border-radius: 8px; overflow: hidden; background: #fff; }
|
|
.p-qty-btn { width: 44px; height: 44px; border: none; background: #f7fafc; font-size: 20px; cursor: pointer; }
|
|
.p-qty-input { width: 60px; height: 44px; border: none; text-align: center; font-weight: 700; font-size: 16px; }
|
|
|
|
.p-pay-method-grid { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
.p-pay-btn { font-size: 12px; background: #fff; border: 1px solid #edf2f7; padding: 8px 14px; border-radius: 8px; color: #4a5568; cursor: pointer; }
|
|
.p-pay-btn.is-active { background: #3182ce; color: #fff; border-color: #3182ce; font-weight: 700; }
|
|
|
|
/* 요약 영역 */
|
|
.p-price-summary { margin-top: 30px; padding: 20px; background: #f8fafc; border-radius: 12px; }
|
|
.p-total-price { font-size: 28px; font-weight: 900; color: #2b6cb0; }
|
|
.p-btn-order-submit { background: #3182ce; color: #fff; width: 100%; height: 60px; border-radius: 12px; font-weight: 700; border: none; font-size: 18px; cursor: pointer; }
|
|
|
|
/* 모바일 대응 */
|
|
@media (max-width: 991px) {
|
|
.p-detail-container { flex-direction: column; }
|
|
/* 모바일 권종 한 줄 배치 */
|
|
.p-sku-grid { grid-template-columns: 1fr; }
|
|
/* 모바일 탭 영역 하단 배치용 순서 변경 */
|
|
.p-detail-visual { display: flex; flex-direction: column; width: 100%; }
|
|
.p-tab-container { order: 10; margin-top: 40px; } /* 결제정보 아래로 이동 */
|
|
.p-detail-info { width: 100%; }
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('subcontent')
|
|
<div class="p-detail-container">
|
|
{{-- 왼쪽 영역 --}}
|
|
<div class="p-detail-visual">
|
|
<div class="p-main-img-card">
|
|
<img src="{{ $product->thumb_path ?? '/assets/images/no-image.png' }}" id="productImg">
|
|
</div>
|
|
|
|
{{-- 상세 정보 탭 그룹 --}}
|
|
<div class="p-tab-container">
|
|
<div class="p-btn-group">
|
|
<button type="button" class="p-tab-btn is-active" onclick="window.switchTab(this, 'desc')">상품설명</button>
|
|
<button type="button" class="p-tab-btn" onclick="window.switchTab(this, 'guide')">이용안내</button>
|
|
<button type="button" class="p-tab-btn" onclick="window.switchTab(this, 'warning')">주의사항</button>
|
|
</div>
|
|
|
|
<div class="p-tab-content">
|
|
<div id="pane-desc" class="p-content-pane is-active">{!! $product->description !!}</div>
|
|
<div id="pane-guide" class="p-content-pane">{!! $product->guide !!}</div>
|
|
<div id="pane-warning" class="p-content-pane">{!! $product->warning !!}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 오른쪽 영역 --}}
|
|
<div class="p-detail-info">
|
|
<div class="p-info-header">
|
|
<span style="color:#3182ce; font-weight:700; font-size:14px; letter-spacing:1px;">VERIFIED RESELLER</span>
|
|
<h2>{{ $product->name }}</h2>
|
|
</div>
|
|
|
|
<div class="p-order-form">
|
|
<div class="p-sku-grid">
|
|
@foreach($skus as $sku)
|
|
<div class="p-sku-btn @if($loop->first) is-active @endif"
|
|
data-sku-id="{{ $sku->id }}"
|
|
data-price="{{ $sku->final_price }}"
|
|
onclick="window.handleSkuSelect(this)">
|
|
@if($sku->discount_value > 0)
|
|
<span class="p-sku-badge">{{ $sku->discount_type === 'PERCENT' ? $sku->discount_value.'%' : number_format($sku->discount_value).'원' }}</span>
|
|
@endif
|
|
<span style="display:block; font-size:13px; color:#a0aec0; margin-bottom:4px;">{{ $sku->name }}</span>
|
|
<div style="display:flex; align-items:baseline; gap:8px;">
|
|
<span class="p-sku-price">{{ number_format($sku->final_price) }}원</span>
|
|
@if($sku->discount_value > 0)
|
|
<span style="font-size:13px; color:#cbd5e0; text-decoration:line-through;">{{ number_format($sku->face_value) }}원</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
|
|
<div class="p-qty-wrapper" style="margin-top:25px;">
|
|
<label class="p-option-title" style="margin-bottom:0;">구매 수량</label>
|
|
<div class="p-qty-ctrl">
|
|
<button type="button" class="p-qty-btn" onclick="window.changeQty(-1)">-</button>
|
|
<input type="text" id="pOrderQty" class="p-qty-input" value="{{ $product->min_buy_qty }}" readonly>
|
|
<button type="button" class="p-qty-btn" onclick="window.changeQty(1)">+</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top:20px; padding:15px; background:#f7fafc; border-radius:12px;">
|
|
<span style="font-size:13px; font-weight:700; color:#4a5568; display:block; margin-bottom:10px;">결제 수단 선택</span>
|
|
<div class="p-pay-method-grid">
|
|
@foreach($payments as $pay)
|
|
<button type="button"
|
|
class="p-pay-btn @if($loop->first) is-active @endif"
|
|
data-pay-id="{{ $pay->id }}"
|
|
data-fee-rate="{{ (float)$pay->customer_fee_rate }}"
|
|
onclick="window.handlePaySelect(this)">
|
|
{{ $pay->display_name }}
|
|
</button>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
|
|
<div class="p-price-summary">
|
|
<div class="p-summary-row" style="display:flex; justify-content:space-between; font-size:14px; color:#718096; margin-bottom:8px;">
|
|
<span>상품 합계</span>
|
|
<span><span id="pBaseTotal">0</span>원</span>
|
|
</div>
|
|
<div class="p-summary-row" style="display:flex; justify-content:space-between; font-size:14px; color:#718096; margin-bottom:8px;">
|
|
<span>결제 수수료 (<span id="pFeeRateDisplay">0</span>%)</span>
|
|
<span>+ <span id="pFeeAmount">0</span>원</span>
|
|
</div>
|
|
<div class="p-total-row" style="display:flex; justify-content:space-between; align-items:center; margin-top:10px; padding-top:10px; border-top:1px solid #e2e8f0;">
|
|
<span style="font-weight:800; color:#4a5568; font-size:16px;">최종 결제금액</span>
|
|
<div class="p-total-price"><span id="pTotalVal">0</span><small style="font-size:18px; margin-left:2px;">원</small></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top:25px;">
|
|
<button type="button" class="p-btn-order-submit" onclick="window.submitOrder()">구매하기</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
(function() {
|
|
const POLICY = {
|
|
minQty: parseInt("{{ $product->min_buy_qty }}") || 1,
|
|
maxQty: parseInt("{{ $product->max_buy_qty }}") || 999,
|
|
maxAmount: parseInt("{{ $product->max_buy_amount }}") || 0
|
|
};
|
|
|
|
let currentUnitPrice = 0;
|
|
let currentFeeRate = 0;
|
|
|
|
// 탭 전환 함수
|
|
window.switchTab = function(btn, type) {
|
|
document.querySelectorAll('.p-tab-btn').forEach(b => b.classList.remove('is-active'));
|
|
btn.classList.add('is-active');
|
|
|
|
document.querySelectorAll('.p-content-pane').forEach(p => p.classList.remove('is-active'));
|
|
document.getElementById('pane-' + type).classList.add('is-active');
|
|
};
|
|
|
|
window.handlePaySelect = function(el) {
|
|
document.querySelectorAll('.p-pay-btn').forEach(b => b.classList.remove('is-active'));
|
|
el.classList.add('is-active');
|
|
currentFeeRate = parseFloat(el.dataset.feeRate);
|
|
calculateTotal();
|
|
};
|
|
|
|
window.handleSkuSelect = function(el) {
|
|
document.querySelectorAll('.p-sku-btn').forEach(b => b.classList.remove('is-active'));
|
|
el.classList.add('is-active');
|
|
currentUnitPrice = parseInt(el.dataset.price);
|
|
validateAndCalculate();
|
|
};
|
|
|
|
window.changeQty = async function(delta) {
|
|
const qtyInput = document.getElementById('pOrderQty');
|
|
let nextQty = parseInt(qtyInput.value) + delta;
|
|
|
|
if (nextQty < POLICY.minQty) return;
|
|
if (POLICY.maxQty > 0 && nextQty > POLICY.maxQty) {
|
|
await showMsg('최대 구매 수량(' + POLICY.maxQty + '개)을 초과할 수 없습니다.', { type:'alert', title:'수량초과' });
|
|
return;
|
|
}
|
|
if (POLICY.maxAmount > 0 && (currentUnitPrice * nextQty) > POLICY.maxAmount) {
|
|
await showMsg('1회 최대 결제 금액 초과할 수 없습니다.', { type:'alert', title:'금액초과' });
|
|
return;
|
|
}
|
|
|
|
qtyInput.value = nextQty;
|
|
calculateTotal();
|
|
};
|
|
|
|
function validateAndCalculate() {
|
|
const qtyInput = document.getElementById('pOrderQty');
|
|
let qty = parseInt(qtyInput.value);
|
|
if (POLICY.maxAmount > 0 && (currentUnitPrice * qty) > POLICY.maxAmount) {
|
|
qty = Math.floor(POLICY.maxAmount / currentUnitPrice);
|
|
if(qty < POLICY.minQty) qty = POLICY.minQty;
|
|
qtyInput.value = qty;
|
|
}
|
|
calculateTotal();
|
|
}
|
|
|
|
function calculateTotal() {
|
|
const qty = parseInt(document.getElementById('pOrderQty').value);
|
|
const baseTotal = currentUnitPrice * qty;
|
|
const feeAmount = Math.floor(baseTotal * (currentFeeRate / 100));
|
|
|
|
document.getElementById('pBaseTotal').innerText = baseTotal.toLocaleString();
|
|
document.getElementById('pFeeRateDisplay').innerText = currentFeeRate;
|
|
document.getElementById('pFeeAmount').innerText = feeAmount.toLocaleString();
|
|
document.getElementById('pTotalVal').innerText = (baseTotal + feeAmount).toLocaleString();
|
|
}
|
|
|
|
window.submitOrder = async function() {
|
|
const activeSku = document.querySelector('.p-sku-btn.is-active');
|
|
const activePay = document.querySelector('.p-pay-btn.is-active');
|
|
const qty = document.getElementById('pOrderQty').value;
|
|
if (!activeSku) return await showMsg('권종을 선택해주세요.', { type:'alert', title:'권종선택' });
|
|
location.href = "/order/checkout?sku_id=" + activeSku.dataset.skuId + "&qty=" + qty + "&pay_id=" + activePay.dataset.payId;
|
|
};
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const firstSku = document.querySelector('.p-sku-btn.is-active');
|
|
const firstPay = document.querySelector('.p-pay-btn.is-active');
|
|
if (firstSku) currentUnitPrice = parseInt(firstSku.dataset.price);
|
|
if (firstPay) currentFeeRate = parseFloat(firstPay.dataset.feeRate);
|
|
calculateTotal();
|
|
});
|
|
})();
|
|
</script>
|
|
@endpush
|