269 lines
12 KiB
PHP
269 lines
12 KiB
PHP
@extends('admin.layouts.app')
|
|
|
|
@section('title', '권종 관리')
|
|
@section('page_title', '권종 관리')
|
|
@section('page_desc', '상품별 권종/가격(SKU)을 관리합니다.')
|
|
@section('content_class', 'a-content--full')
|
|
|
|
@push('head')
|
|
<style>
|
|
/* skus index only (members index 스타일 준수) */
|
|
.bar{display:flex;justify-content:space-between;align-items:flex-end;gap:12px;flex-wrap:wrap;}
|
|
.bar__left .t{font-weight:900;font-size:16px;}
|
|
.bar__left .d{font-size:12px;margin-top:4px;}
|
|
.bar__right{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;}
|
|
|
|
.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end;}
|
|
.filters .q{width:260px;}
|
|
.filters .cat{width:220px;}
|
|
.filters .prd{width:260px;}
|
|
.filters .st{width:140px;}
|
|
|
|
.lbtn{padding:8px 12px;font-size:13px;border-radius:12px;line-height:1.1;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;gap:6px;
|
|
border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.06);color:inherit;cursor:pointer;}
|
|
.lbtn:hover{background:rgba(255,255,255,.10);text-decoration:none;}
|
|
.lbtn--ghost{background:transparent;}
|
|
.lbtn--sm{padding:7px 10px;font-size:12px;border-radius:11px;}
|
|
.lbtn--primary{background:rgba(59,130,246,.88);border-color:rgba(59,130,246,.95);color:#fff;}
|
|
.lbtn--primary:hover{background:rgba(59,130,246,.98);}
|
|
|
|
.pill{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:999px;font-size:12px;
|
|
border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.06);}
|
|
.pill--ok{border-color:rgba(34,197,94,.35);background:rgba(34,197,94,.12);}
|
|
.pill--bad{border-color:rgba(244,63,94,.35);background:rgba(244,63,94,.10);}
|
|
.pill--muted{opacity:.9;}
|
|
|
|
.mono{padding:4px 8px;border-radius:10px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.10);
|
|
font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:12px;}
|
|
.table td{vertical-align:top;}
|
|
.sub{font-size:12px;margin-top:6px;line-height:1.35;}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
@php
|
|
$filters = $filters ?? [];
|
|
$catId = (string)($filters['category_id'] ?? '');
|
|
$prdId = (string)($filters['product_id'] ?? '');
|
|
$stSel = (string)($filters['status'] ?? '');
|
|
$q = (string)($filters['q'] ?? '');
|
|
|
|
$statusPill = function(?string $st): string {
|
|
$st = (string)($st ?? '');
|
|
return match($st) {
|
|
'active' => 'pill--ok',
|
|
'hidden' => 'pill--bad',
|
|
default => 'pill--muted',
|
|
};
|
|
};
|
|
|
|
$statusLabel = function(?string $st): string {
|
|
$st = (string)($st ?? '');
|
|
return match($st) {
|
|
'active' => '노출',
|
|
'hidden' => '숨김',
|
|
default => $st ?: '-',
|
|
};
|
|
};
|
|
|
|
$stockLabel = function(?string $m): string {
|
|
$m = (string)($m ?? '');
|
|
return match($m) {
|
|
'infinite' => '무한',
|
|
'limited' => '한정',
|
|
default => $m ?: '-',
|
|
};
|
|
};
|
|
@endphp
|
|
|
|
<div class="a-card" style="padding:16px; margin-bottom:16px;">
|
|
<div class="bar">
|
|
<div class="bar__left">
|
|
<div class="t">권종관리</div>
|
|
<div class="a-muted d">상품별 권종/가격(SKU)을 관리합니다.</div>
|
|
</div>
|
|
|
|
<div class="bar__right">
|
|
<a class="lbtn lbtn--primary" href="{{ route('admin.skus.create') }}">+ 권종 등록</a>
|
|
|
|
<form method="GET" action="{{ route('admin.skus.index') }}" class="filters">
|
|
<div>
|
|
<select class="a-input cat" name="category_id" id="category_id">
|
|
<option value="">카테고리 전체</option>
|
|
@foreach(($categories ?? []) as $c)
|
|
@php
|
|
$cid = (string)($c->id ?? '');
|
|
$txt = trim((string)($c->parent_name ?? ''));
|
|
$txt = $txt !== '' ? ($txt.' / '.($c->name ?? '')) : ($c->name ?? '-');
|
|
@endphp
|
|
<option value="{{ $cid }}" {{ $catId===$cid ? 'selected':'' }}>
|
|
{{ $txt }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<select class="a-input prd" name="product_id" id="product_id">
|
|
<option value="">상품 전체</option>
|
|
@foreach(($products ?? []) as $p)
|
|
@php
|
|
$pid = (string)($p->id ?? '');
|
|
$pcat = (string)($p->category_id ?? '');
|
|
$label = trim((string)($p->parent_category_name ?? ''));
|
|
if ($label !== '') $label .= ' / '.($p->category_name ?? '');
|
|
else $label = (string)($p->category_name ?? '');
|
|
$label = trim($label);
|
|
$label = $label !== '' ? ($label.' - '.($p->name ?? '')) : ($p->name ?? '-');
|
|
@endphp
|
|
<option value="{{ $pid }}"
|
|
data-cat="{{ $pcat }}"
|
|
{{ $prdId===$pid ? 'selected':'' }}>
|
|
{{ $label }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<select class="a-input st" name="status">
|
|
<option value="">상태 전체</option>
|
|
<option value="active" {{ $stSel==='active'?'selected':'' }}>노출</option>
|
|
<option value="hidden" {{ $stSel==='hidden'?'selected':'' }}>숨김</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<input class="a-input q"
|
|
name="q"
|
|
value="{{ $q }}"
|
|
placeholder="상품명 / sku_code 검색">
|
|
</div>
|
|
|
|
<div style="display:flex; gap:8px; align-items:flex-end;">
|
|
<button class="lbtn lbtn--ghost" type="submit">검색</button>
|
|
<a class="lbtn lbtn--ghost" href="{{ route('admin.skus.index') }}">초기화</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="a-card" style="padding:16px;">
|
|
<div class="a-muted" style="margin-bottom:10px;">
|
|
총 <b>{{ $page->total() }}</b>개
|
|
</div>
|
|
|
|
<div style="overflow:auto;">
|
|
<table class="a-table table" style="width:100%; min-width:1200px;">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:80px;">ID</th>
|
|
<th style="width:360px;">상품</th>
|
|
<th style="width:140px;">권면가</th>
|
|
<th style="width:140px;">정상가</th>
|
|
<th style="width:110px;">할인율</th>
|
|
<th style="width:140px;">판매가</th>
|
|
<th style="width:120px;">재고방식</th>
|
|
<th style="width:120px;">상태</th>
|
|
<th style="width:170px;">수정일</th>
|
|
<th style="width:90px; text-align:right;">관리</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
@forelse($page as $row)
|
|
@php
|
|
$id = (int)($row->id ?? 0);
|
|
$st = (string)($row->status ?? '');
|
|
$pill = $statusPill($st);
|
|
$stText = $statusLabel($st);
|
|
|
|
$pname = (string)($row->product_name ?? '-');
|
|
$c1 = (string)($row->parent_category_name ?? '');
|
|
$c2 = (string)($row->category_name ?? '');
|
|
$catText = trim($c1) !== '' ? ($c1.' / '.$c2) : ($c2 ?: '-');
|
|
|
|
$face = (int)($row->face_value ?? 0);
|
|
$normal = (int)($row->normal_price ?? 0);
|
|
$rate = (string)($row->discount_rate ?? '0.00');
|
|
$sale = (int)($row->sale_price ?? 0);
|
|
|
|
$smode = $stockLabel($row->stock_mode ?? null);
|
|
$updated = $row->updated_at ?? '-';
|
|
@endphp
|
|
|
|
<tr>
|
|
<td class="a-muted">{{ $id }}</td>
|
|
|
|
<td>
|
|
<div style="font-weight:900;">{{ $pname }}</div>
|
|
<div class="a-muted sub">{{ $catText }}</div>
|
|
@if(!empty($row->sku_code))
|
|
<div class="sub"><span class="mono">{{ $row->sku_code }}</span></div>
|
|
@endif
|
|
</td>
|
|
|
|
<td><span class="mono">{{ number_format($face) }}</span> 원</td>
|
|
<td class="a-muted">{{ number_format($normal) }} 원</td>
|
|
<td class="a-muted">{{ $rate }}%</td>
|
|
<td><b>{{ number_format($sale) }}</b> 원</td>
|
|
<td class="a-muted">{{ $smode }}</td>
|
|
|
|
<td>
|
|
<span class="pill {{ $pill }}">● {{ $stText }}</span>
|
|
</td>
|
|
|
|
<td class="a-muted">{{ $updated }}</td>
|
|
|
|
<td style="text-align:right;">
|
|
<a class="lbtn lbtn--ghost lbtn--sm"
|
|
href="{{ route('admin.skus.edit', ['id'=>$id] + request()->only(['q','category_id','product_id','status','page'])) }}">
|
|
수정
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="10" class="a-muted" style="padding:18px;">데이터가 없습니다.</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="margin-top:12px;">
|
|
{{ $page->onEachSide(1)->links('vendor.pagination.admin') }}
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function(){
|
|
const catSel = document.getElementById('category_id');
|
|
const prdSel = document.getElementById('product_id');
|
|
if (!catSel || !prdSel) return;
|
|
|
|
const apply = () => {
|
|
const cat = catSel.value || '';
|
|
const cur = prdSel.value || '';
|
|
|
|
let hasCur = false;
|
|
|
|
Array.from(prdSel.options).forEach((opt, idx) => {
|
|
if (idx === 0) return; // "상품 전체"
|
|
const oc = opt.getAttribute('data-cat') || '';
|
|
const ok = (cat === '' || oc === cat);
|
|
opt.hidden = !ok;
|
|
if (ok && opt.value === cur) hasCur = true;
|
|
});
|
|
|
|
// 현재 선택된 상품이 필터에서 숨겨지면 전체로 되돌림
|
|
if (cur !== '' && !hasCur) prdSel.value = '';
|
|
};
|
|
|
|
catSel.addEventListener('change', apply);
|
|
apply();
|
|
})();
|
|
</script>
|
|
@endsection
|