2026-02-06 11:27:38 +00:00

261 lines
10 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="row g-4 mb-4">
<!-- Stats Cards -->
<div class="col-md-3">
<div class="card glass-card h-100">
<div class="card-body">
<div class="stats-icon bg-primary-subtle text-primary">
<i data-lucide="package"></i>
</div>
<h6 class="text-muted mb-1 small fw-bold text-uppercase">TOTAL BARANG</h6>
<h2 class="fw-bold mb-0 text-dark">{{ total_medicines }}</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card glass-card h-100">
<div class="card-body">
<div class="stats-icon bg-success-subtle text-success">
<i data-lucide="boxes"></i>
</div>
<h6 class="text-muted mb-1 small fw-bold text-uppercase">TOTAL STOK</h6>
<h2 class="fw-bold mb-0 text-dark">{{ total_stock }}</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card glass-card h-100">
<div class="card-body">
<div class="stats-icon bg-warning-subtle text-warning">
<i data-lucide="alert-triangle"></i>
</div>
<h6 class="text-muted mb-1 small fw-bold text-uppercase">STOK MENIPIS</h6>
<h2 class="fw-bold mb-0 text-dark">{{ low_stock_count }}</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card glass-card h-100">
<div class="card-body">
<div class="stats-icon bg-danger-subtle text-danger">
<i data-lucide="calendar-x"></i>
</div>
<h6 class="text-muted mb-1 small fw-bold text-uppercase">KADALUARSA</h6>
<h2 class="fw-bold mb-0 text-dark">{{ expired_count }}</h2>
</div>
</div>
</div>
</div>
<div class="row g-4 mb-4">
<!-- Chart Area -->
<div class="col-lg-8">
<div class="card glass-card h-100">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="fw-bold mb-0">Pergerakan Stok</h5>
<span class="badge bg-light text-dark border py-2 px-3 rounded-pill small">7 Hari Terakhir</span>
</div>
<div style="height: 300px;">
<canvas id="movementChart"></canvas>
</div>
</div>
</div>
</div>
<!-- Expiry Overview -->
<div class="col-lg-4">
<div class="card border-0 rounded-4 h-100 bg-white shadow-sm overflow-hidden">
<div class="card-body p-0">
<div class="p-4 bg-danger text-white">
<h5 class="fw-bold mb-0">Pantauan Kadaluarsa</h5>
<p class="small opacity-75 mb-0">Segera kadaluarsa (90 hari ke depan)</p>
</div>
<div class="p-4 text-center">
<div class="display-1 fw-bold text-danger mb-2">{{ near_expiry_count }}</div>
<p class="text-muted mb-4">Item memerlukan perhatian segera</p>
<div class="d-grid">
<a href="/admin/core/batch/" class="btn btn-outline-danger d-flex align-items-center justify-content-center">
<i data-lucide="external-link" class="me-2 icon-sm"></i> Tinjau Batch
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row g-4">
<div class="col-12">
<div class="card glass-card">
<div class="card-body p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="fw-bold mb-0 d-flex align-items-center">
<i data-lucide="history" class="me-2 text-primary"></i> Data Barang Terbaru
</h5>
<a href="/admin/core/medicine/" class="btn btn-primary btn-sm d-flex align-items-center px-3 rounded-pill">
<i data-lucide="settings" class="me-2 icon-sm"></i> Kelola Semua
</a>
</div>
<div class="table-responsive">
<table class="table align-middle mb-0">
<thead>
<tr>
<th>SKU</th>
<th>Nama Barang</th>
<th>Kategori</th>
<th>Stok</th>
<th>Status</th>
<th class="text-end">Aksi</th>
</tr>
</thead>
<tbody>
{% for medicine in recent_medicines %}
<tr>
<td><span class="badge bg-light text-muted">{{ medicine.sku }}</span></td>
<td><span class="fw-bold">{{ medicine.name }}</span></td>
<td><span class="text-muted small">{{ medicine.category.name }}</span></td>
<td>
<span class="fw-bold">{{ medicine.total_stock }}</span>
<span class="text-muted small ms-1">{{ medicine.unit }}</span>
</td>
<td>
{% if medicine.status == 'Tersedia' %}
<span class="badge bg-success-subtle text-success rounded-pill px-3">Tersedia</span>
{% elif medicine.status == 'Stok Menipis' %}
<span class="badge bg-warning-subtle text-warning rounded-pill px-3">Stok Menipis</span>
{% else %}
<span class="badge bg-danger-subtle text-danger rounded-pill px-3">Habis</span>
{% endif %}
</td>
<td class="text-end">
<a href="/admin/core/medicine/{{ medicine.id }}/change/" class="btn btn-light btn-sm rounded-circle p-2">
<i data-lucide="edit-3" class="icon-sm"></i>
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="6" class="text-center py-5 text-muted">
<i data-lucide="inbox" class="mb-2 d-block mx-auto opacity-20" style="width: 48px; height: 48px;"></i>
Belum ada data tersedia.
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
const ctx = document.getElementById('movementChart').getContext('2d');
// Create gradients
const gradientIn = ctx.createLinearGradient(0, 0, 0, 300);
gradientIn.addColorStop(0, 'rgba(67, 97, 238, 0.2)');
gradientIn.addColorStop(1, 'rgba(67, 97, 238, 0)');
const gradientOut = ctx.createLinearGradient(0, 0, 0, 300);
gradientOut.addColorStop(0, 'rgba(239, 35, 60, 0.2)');
gradientOut.addColorStop(1, 'rgba(239, 35, 60, 0)');
new Chart(ctx, {
type: 'line',
data: {
labels: {{ chart_labels|safe }},
datasets: [
{
label: 'Barang Masuk',
data: {{ chart_data_in|safe }},
borderColor: '#4361ee',
backgroundColor: gradientIn,
fill: true,
tension: 0.4,
borderWidth: 3,
pointRadius: 4,
pointHoverRadius: 6,
pointBackgroundColor: '#fff',
pointBorderWidth: 2
},
{
label: 'Barang Keluar',
data: {{ chart_data_out|safe }},
borderColor: '#ef233c',
backgroundColor: gradientOut,
fill: true,
tension: 0.4,
borderWidth: 3,
pointRadius: 4,
pointHoverRadius: 6,
pointBackgroundColor: '#fff',
pointBorderWidth: 2
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false,
},
plugins: {
legend: {
position: 'top',
align: 'end',
labels: {
usePointStyle: true,
boxWidth: 8,
font: {
family: 'Plus Jakarta Sans',
size: 12,
weight: '600'
}
}
},
tooltip: {
padding: 12,
backgroundColor: 'rgba(255, 255, 255, 0.9)',
titleColor: '#1e293b',
titleFont: { size: 14, weight: 'bold' },
bodyColor: '#64748b',
borderColor: '#e2e8f0',
borderWidth: 1,
displayColors: true,
boxPadding: 6,
usePointStyle: true
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.03)',
drawBorder: false
},
ticks: {
font: { family: 'Plus Jakarta Sans' }
}
},
x: {
grid: {
display: false
},
ticks: {
font: { family: 'Plus Jakarta Sans' }
}
}
}
}
});
</script>
{% endblock %}