gov-portal 디자인을 시스템 전체에 적용한다.
- 사이트 업무 페이지: 공통 셸 bag/layout/portal(헤더+대메뉴 클릭+좌측 사이드바 소메뉴) - 관리자 페이지: admin/layout 을 동일 포털 셸로 재작성(관리자 메뉴 트리, 폴백) - 메인(/): gov-portal 대시보드, 종량제 실데이터만(재고/주문/승인/활동로그) - 로그인/회원가입/2차인증/TOTP: 공통 auth/_shell 로 통일, 사이트 공통 로고 - 버튼색 통일: btn-search 등 주요 버튼을 #243a5e(메뉴바 네이비보다 살짝 밝게), 밝은 파랑 채움 버튼(#2b4c8c/#1e548a)도 동일 색으로 - gov_portal_nav_context() 임의 메뉴 트리 수용, 업무 셸은 실제 bag/* 링크 유지 - Admin\Menu 권한거부 리다이렉트 admin/dashboard(404) → admin 수정 - E2E redesign.spec.js 추가, 기능 무변경 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
151
app/Views/bag/dashboard_portal.php
Normal file
151
app/Views/bag/dashboard_portal.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* 메인(/) gov-portal 디자인 대시보드 — 종량제 실데이터만 표시.
|
||||
*
|
||||
* @var string $lgLabel
|
||||
* @var string $mbName
|
||||
* @var string $mbId
|
||||
* @var string $levelName
|
||||
* @var int $totalQty
|
||||
* @var int $itemCount
|
||||
* @var int $orderCount
|
||||
* @var int $pendingApprovals
|
||||
* @var array $stockMix
|
||||
* @var array $lowStock
|
||||
* @var array $recentActivity
|
||||
*/
|
||||
$stockMix = is_array($stockMix ?? null) ? $stockMix : [];
|
||||
$lowStock = is_array($lowStock ?? null) ? $lowStock : [];
|
||||
$recentActivity = is_array($recentActivity ?? null) ? $recentActivity : [];
|
||||
|
||||
// 도넛 conic-gradient 누적 계산
|
||||
$donutStops = [];
|
||||
$acc = 0;
|
||||
foreach ($stockMix as $m) {
|
||||
$start = $acc;
|
||||
$acc += (int) $m['value'];
|
||||
$donutStops[] = $m['color'] . ' ' . $start . '% ' . $acc . '%';
|
||||
}
|
||||
$donutCss = $donutStops !== [] ? implode(', ', $donutStops) : '#e5e7eb 0% 100%';
|
||||
?>
|
||||
<div class="space-y-4">
|
||||
<!-- 프로필 + KPI -->
|
||||
<section class="grid grid-cols-1 lg:grid-cols-4 gap-4">
|
||||
<div class="rounded-xl bg-slate-700 text-white p-4 shadow-sm">
|
||||
<p class="text-xs text-white/70">안녕하세요.</p>
|
||||
<p class="text-lg font-bold mt-1"><?= esc($mbName) ?>님</p>
|
||||
<p class="text-[11px] text-white/70 mt-1 leading-relaxed">
|
||||
<?= esc($levelName) ?><?= $lgLabel !== '' ? ' · ' . esc($lgLabel) : '' ?><br/>
|
||||
아이디 <?= esc($mbId) ?><br/>최근접속 <?= date('Y.m.d H:i') ?>
|
||||
</p>
|
||||
<div class="flex gap-1.5 mt-3">
|
||||
<a href="<?= base_url('bag/manual') ?>" class="text-[11px] px-2 py-1 rounded bg-white/10 hover:bg-white/20 border border-white/30">매뉴얼</a>
|
||||
<a href="<?= base_url('logout') ?>" class="text-[11px] px-2 py-1 rounded bg-white/10 hover:bg-white/20 border border-white/30">로그아웃</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white border border-gray-200 p-4 shadow-sm">
|
||||
<p class="text-xs text-gray-500"><i class="fa-solid fa-boxes-stacked text-blue-600 mr-1"></i>봉투 재고 총량</p>
|
||||
<p class="text-2xl font-bold text-gray-900 mt-1"><?= number_format($totalQty) ?><span class="text-sm font-medium text-gray-400 ml-1">개</span></p>
|
||||
<p class="text-[11px] text-gray-500 mt-1"><?= esc($lgLabel !== '' ? $lgLabel : '전체') ?> · 품목 <?= (int) $itemCount ?>종</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white border border-gray-200 p-4 shadow-sm">
|
||||
<p class="text-xs text-gray-500"><i class="fa-solid fa-receipt text-sky-600 mr-1"></i>주문 접수(정상)</p>
|
||||
<p class="text-2xl font-bold text-sky-700 mt-1"><?= (int) $orderCount ?><span class="text-sm font-medium text-gray-400 ml-1">건</span></p>
|
||||
<p class="text-[11px] text-gray-500 mt-1">전화·지정판매소 주문 누계</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-white border border-gray-200 p-4 shadow-sm">
|
||||
<p class="text-xs text-gray-500"><i class="fa-solid fa-user-check text-violet-600 mr-1"></i>승인 대기</p>
|
||||
<p class="text-2xl font-bold text-violet-700 mt-1"><?= (int) $pendingApprovals ?><span class="text-sm font-medium text-gray-400 ml-1">명</span></p>
|
||||
<p class="text-[11px] text-gray-500 mt-1">회원 가입 승인 요청</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
||||
<?php if ($stockMix !== []): ?>
|
||||
<!-- 재고 구성 -->
|
||||
<div class="rounded-xl bg-white border border-gray-200 p-4 shadow-sm">
|
||||
<h2 class="text-sm font-bold text-gray-900 mb-3"><i class="fa-solid fa-chart-pie text-blue-600 mr-1"></i>재고 구성</h2>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-20 h-20 rounded-full shrink-0" style="background: conic-gradient(<?= $donutCss ?>);">
|
||||
<div class="w-10 h-10 bg-white rounded-full mx-auto" style="margin-top:1.25rem;"></div>
|
||||
</div>
|
||||
<ul class="text-[11px] text-gray-600 space-y-1 min-w-0">
|
||||
<?php foreach ($stockMix as $m): ?>
|
||||
<li class="flex items-center gap-2">
|
||||
<span class="inline-block w-2.5 h-2.5 rounded-full shrink-0" style="background-color: <?= esc($m['color'], 'attr') ?>"></span>
|
||||
<span class="truncate"><?= esc($m['name']) ?> <?= (int) $m['value'] ?>%</span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($lowStock !== []): ?>
|
||||
<!-- 부족 재고 -->
|
||||
<div class="rounded-xl bg-white border border-gray-200 p-4 shadow-sm">
|
||||
<h2 class="text-sm font-bold text-gray-900 mb-3"><i class="fa-solid fa-box-open text-amber-600 mr-1"></i>재고 적은 품목</h2>
|
||||
<div class="space-y-2">
|
||||
<?php foreach ($lowStock as $item): ?>
|
||||
<div>
|
||||
<div class="flex justify-between text-[11px] text-gray-600 mb-1">
|
||||
<span class="truncate"><?= esc($item['name']) ?></span>
|
||||
<span class="shrink-0 ml-2"><?= number_format((int) $item['qty']) ?>개</span>
|
||||
</div>
|
||||
<div class="h-2 rounded bg-gray-100 overflow-hidden">
|
||||
<div class="h-full rounded bg-amber-500" style="width: <?= (int) $item['percent'] ?>%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($recentActivity !== []): ?>
|
||||
<!-- 최근 활동 (activity_log) -->
|
||||
<div class="rounded-xl bg-white border border-gray-200 p-4 shadow-sm">
|
||||
<h2 class="text-sm font-bold text-gray-900 mb-3"><i class="fa-solid fa-clock-rotate-left text-emerald-600 mr-1"></i>최근 처리 내역</h2>
|
||||
<ul class="space-y-2">
|
||||
<?php foreach ($recentActivity as $ev): ?>
|
||||
<li class="flex items-start gap-2 text-[12px]">
|
||||
<span class="text-[11px] font-semibold text-gray-400 shrink-0 w-20"><?= esc($ev['time']) ?></span>
|
||||
<span class="text-gray-700"><?= esc($ev['text']) ?></span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<!-- 자주 가는 화면 (실제 메뉴 링크) -->
|
||||
<section class="rounded-xl bg-white border border-gray-200 p-4 shadow-sm">
|
||||
<h2 class="text-sm font-bold text-gray-900 mb-3"><i class="fa-solid fa-location-arrow text-blue-600 mr-1"></i>자주 가는 화면</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
||||
<?php
|
||||
$links = [
|
||||
['bag/inventory', '창고 재고 조회', '품목별 현재 재고', 'fa-boxes-stacked', 'emerald'],
|
||||
['bag/order/create', '발주 등록', '봉투 발주·구매신청', 'fa-cart-shopping', 'sky'],
|
||||
['bag/flow', '봉투 수불 현황', '입고·출고 내역', 'fa-arrow-right-arrow-left', 'orange'],
|
||||
['bag/sales', '판매 관리', '판매/반품 내역', 'fa-receipt', 'indigo'],
|
||||
['bag/reports/daily-summary', '일계표', '일일 판매 요약', 'fa-table-list', 'violet'],
|
||||
['bag/manual', '사용자 매뉴얼', '업무별 사용 안내', 'fa-book', 'slate'],
|
||||
];
|
||||
foreach ($links as [$path, $label, $desc, $icon, $c]):
|
||||
?>
|
||||
<a href="<?= base_url($path) ?>" class="group flex items-center gap-3 px-3 py-2 rounded border border-gray-200 hover:border-blue-500 hover:bg-blue-50/40 transition">
|
||||
<div class="h-8 w-8 rounded-full bg-<?= $c ?>-50 text-<?= $c ?>-600 flex items-center justify-center shrink-0">
|
||||
<i class="fa-solid <?= $icon ?>"></i>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<p class="text-xs font-semibold text-gray-900 group-hover:text-blue-800"><?= esc($label) ?></p>
|
||||
<p class="text-[11px] text-gray-500 truncate"><?= esc($desc) ?></p>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
Reference in New Issue
Block a user