sungro815 b0545ab5b9 관리자 상품관리 완료
웹사이트 상품리스트 상세보기 작업중
2026-02-20 18:11:03 +09:00

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