Files
jongryangje/app/Views/bag/lg_dashboard_compact.php

213 lines
8.1 KiB
PHP
Raw Normal View History

<?php
/**
* 로그인 메인 컴팩트 대시보드(중간 밀도)
* /dashboard 대비 요소 수를 줄이고, /dashboard/simple 대비 정보량은 늘린 버전.
*
* @var string $lgLabel
*/
$lgLabel = $lgLabel ?? '북구';
$mbName = session()->get('mb_name') ?? '담당자';
$kpi = [
['label' => '미처리 구매신청', 'value' => '12건', 'hint' => '전일 대비 +2'],
['label' => '재고 부족 품목', 'value' => '3종', 'hint' => '안전재고 미달'],
['label' => '금주 입고 완료', 'value' => '8건', 'hint' => '예정 2건'],
['label' => '승인 대기', 'value' => '4명', 'hint' => '판매소/회원'],
];
$weeklyRequest = [8, 11, 9, 14, 10, 12, 7];
$monthlyOut = [320, 340, 330, 355, 372, 361, 388, 396];
$inventoryRows = [
['일반 5L', '12,400', '안전'],
['일반 10L', '8,200', '주의'],
['일반 20L', '2,100', '부족'],
['음식물 스티커', '15,000', '안전'],
['특수규격 A', '890', '부족'],
];
$requestRows = [
['2026-05-07 10:32', '행복마트 북구점', '일반 5L 2,000장', '접수'],
['2026-05-07 09:40', 'OO슈퍼', '음식물 스티커 500매', '처리중'],
['2026-05-07 08:55', 'XX상회', '일반 20L 1,000장', '발주확인'],
['2026-05-06 17:21', 'YY마트', '재사용봉투 800장', '완료'],
];
?>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<div class="bg-[#f5f7fb] -mx-4 -my-4 p-3 min-h-full">
<section class="bg-white border border-gray-200 rounded-lg shadow-sm px-4 py-3 mb-3">
<div class="flex flex-wrap items-center justify-between gap-2">
<div>
<h2 class="text-sm font-semibold text-gray-900">업무 현황 컴팩트 </h2>
<p class="text-[11px] text-gray-500 mt-0.5">
<?= esc($lgLabel) ?> · <?= esc($mbName) ?>님 기준 · 핵심 지표와 추이만 표시
</p>
</div>
<div class="text-[11px] text-gray-500">
기준 시각 <?= date('Y-m-d H:i') ?>
</div>
</div>
</section>
<section class="grid grid-cols-2 lg:grid-cols-4 gap-2 mb-3">
<?php foreach ($kpi as $card): ?>
<article class="bg-white border border-gray-200 rounded-lg shadow-sm p-3">
<p class="text-[11px] text-gray-500"><?= esc($card['label']) ?></p>
<p class="text-xl font-bold text-gray-900 mt-1"><?= esc($card['value']) ?></p>
<p class="text-[10px] text-gray-400 mt-1"><?= esc($card['hint']) ?></p>
</article>
<?php endforeach; ?>
</section>
<section class="grid grid-cols-1 xl:grid-cols-2 gap-3 mb-3">
<article class="bg-white border border-gray-200 rounded-lg shadow-sm p-3">
<div class="flex items-center justify-between mb-2">
<h3 class="text-xs font-semibold text-gray-800">최근 7 구매신청 추이</h3>
<span class="text-[10px] text-gray-400">건수</span>
</div>
<div class="h-48">
<canvas id="compactRequestChart"></canvas>
</div>
</article>
<article class="bg-white border border-gray-200 rounded-lg shadow-sm p-3">
<div class="flex items-center justify-between mb-2">
<h3 class="text-xs font-semibold text-gray-800">월별 출고량 추이</h3>
<span class="text-[10px] text-gray-400"> </span>
</div>
<div class="h-48">
<canvas id="compactOutChart"></canvas>
</div>
</article>
</section>
<section class="grid grid-cols-1 xl:grid-cols-2 gap-3">
<article class="bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden">
<div class="px-3 py-2 border-b border-gray-100 bg-gray-50 flex items-center justify-between">
<h3 class="text-xs font-semibold text-gray-800">재고 상태 요약</h3>
<a href="<?= base_url('bag/inventory') ?>" class="text-[10px] text-blue-600 hover:underline">상세</a>
</div>
<div class="overflow-x-auto">
<table class="w-full text-xs">
<thead class="bg-gray-100 text-gray-600">
<tr>
<th class="text-left px-3 py-2">품목</th>
<th class="text-right px-3 py-2">재고()</th>
<th class="text-center px-3 py-2">상태</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<?php foreach ($inventoryRows as $row): ?>
<tr>
<td class="px-3 py-2"><?= esc($row[0]) ?></td>
<td class="px-3 py-2 text-right"><?= esc($row[1]) ?></td>
<td class="px-3 py-2 text-center">
<?php $stateClass = $row[2] === '부족' ? 'text-red-600' : ($row[2] === '주의' ? 'text-amber-600' : 'text-emerald-600'); ?>
<span class="<?= $stateClass ?> font-medium"><?= esc($row[2]) ?></span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</article>
<article class="bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden">
<div class="px-3 py-2 border-b border-gray-100 bg-gray-50 flex items-center justify-between">
<h3 class="text-xs font-semibold text-gray-800">최근 구매신청 처리 현황</h3>
<a href="<?= base_url('bag/order/create') ?>" class="text-[10px] text-blue-600 hover:underline">등록</a>
</div>
<div class="overflow-x-auto">
<table class="w-full text-xs">
<thead class="bg-gray-100 text-gray-600">
<tr>
<th class="text-left px-3 py-2">시각</th>
<th class="text-left px-3 py-2">판매소</th>
<th class="text-left px-3 py-2">신청 내용</th>
<th class="text-center px-3 py-2">상태</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<?php foreach ($requestRows as $row): ?>
<tr>
<td class="px-3 py-2 whitespace-nowrap"><?= esc($row[0]) ?></td>
<td class="px-3 py-2"><?= esc($row[1]) ?></td>
<td class="px-3 py-2"><?= esc($row[2]) ?></td>
<td class="px-3 py-2 text-center">
<span class="inline-flex px-2 py-0.5 rounded text-[10px] bg-slate-100 text-slate-700"><?= esc($row[3]) ?></span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</article>
</section>
</div>
<script>
(() => {
const style = {
blue: '#2563eb',
blueLight: 'rgba(37, 99, 235, 0.15)',
teal: '#0f766e',
grid: 'rgba(0, 0, 0, 0.06)',
};
Chart.defaults.font.family = "'Malgun Gothic','Apple SD Gothic Neo','Noto Sans KR',sans-serif";
Chart.defaults.font.size = 11;
Chart.defaults.color = '#4b5563';
new Chart(document.getElementById('compactRequestChart'), {
type: 'bar',
data: {
labels: ['D-6', 'D-5', 'D-4', 'D-3', 'D-2', 'D-1', '오늘'],
datasets: [{
data: <?= json_encode($weeklyRequest, JSON_UNESCAPED_UNICODE) ?>,
backgroundColor: style.blue,
borderRadius: 4,
}],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: { legend: { display: false } },
scales: {
x: { grid: { display: false } },
y: { beginAtZero: true, grid: { color: style.grid } },
},
},
});
new Chart(document.getElementById('compactOutChart'), {
type: 'line',
data: {
labels: ['10월', '11월', '12월', '1월', '2월', '3월', '4월', '5월'],
datasets: [{
label: '출고',
data: <?= json_encode($monthlyOut, JSON_UNESCAPED_UNICODE) ?>,
borderColor: style.teal,
backgroundColor: style.blueLight,
fill: true,
tension: 0.35,
pointRadius: 2.5,
}],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: { boxWidth: 10, padding: 8 },
},
},
scales: {
x: { grid: { display: false } },
y: { beginAtZero: false, grid: { color: style.grid } },
},
},
});
})();
</script>