269 lines
15 KiB
PHP
269 lines
15 KiB
PHP
<x-app-layout>
|
|
@section('title', 'Data Obat Masuk')
|
|
|
|
<div class="space-y-6">
|
|
<!-- Header -->
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-[#2F347A]"></h1>
|
|
</div>
|
|
@if(auth()->user()->isApoteker() || auth()->user()->isSuperAdmin())
|
|
<x-btn type="primary" href="{{ route('obat-masuk.create') }}">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
|
|
</svg>
|
|
Tambah Obat
|
|
</x-btn>
|
|
@endif
|
|
</div>
|
|
|
|
<!-- Success Message -->
|
|
@if(session('success'))
|
|
<div class="bg-[#C9F7E3] border border-[#1F9254] text-[#1F9254] px-4 py-3 rounded-lg">
|
|
{{ session('success') }}
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Filters -->
|
|
<x-card class="p-6">
|
|
<form method="GET" action="{{ route('obat-masuk.index') }}" class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
<div>
|
|
<input type="text" name="search" value="{{ request('search') }}"
|
|
placeholder="Cari obat..."
|
|
class="w-full px-4 py-2.5 border border-[#E5E7F2] rounded-lg focus:ring-2 focus:ring-[#4A538F] focus:border-[#4A538F] text-[#2F347A] placeholder-[#7A7FAE]">
|
|
</div>
|
|
<div>
|
|
<select name="kategori" class="w-full px-4 py-2.5 border border-[#E5E7F2] rounded-lg focus:ring-2 focus:ring-[#4A538F] focus:border-[#4A538F] bg-white text-[#2F347A]">
|
|
<option value="">Semua Kategori</option>
|
|
@foreach($kategoris as $kategori)
|
|
<option value="{{ $kategori->id }}" {{ request('kategori') == $kategori->id ? 'selected' : '' }}>
|
|
{{ $kategori->nama }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<select name="status" class="w-full px-4 py-2.5 border border-[#E5E7F2] rounded-lg focus:ring-2 focus:ring-[#4A538F] focus:border-[#4A538F] bg-white text-[#2F347A]">
|
|
<option value="">Semua Status</option>
|
|
<option value="tersedia" {{ request('status') == 'tersedia' ? 'selected' : '' }}>Tersedia</option>
|
|
<option value="habis" {{ request('status') == 'habis' ? 'selected' : '' }}>Habis</option>
|
|
</select>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button type="submit" class="flex-1 px-4 py-2.5 bg-[#4A538F] text-white rounded-lg hover:bg-[#424B84] transition-colors">
|
|
Filter
|
|
</button>
|
|
<a href="{{ route('obat-masuk.index') }}" class="px-4 py-2.5 bg-[#E9EBF5] text-[#4A538F] rounded-lg hover:bg-[#d8dce8] transition-colors">
|
|
Reset
|
|
</a>
|
|
</div>
|
|
</form>
|
|
</x-card>
|
|
|
|
<!-- Pie Chart - Trend Obat Masuk -->
|
|
<x-card class="p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-lg font-semibold text-[#2F347A]">Trend Obat Masuk</h2>
|
|
<form method="GET" action="{{ route('obat-masuk.index') }}" class="flex items-center gap-2">
|
|
<!-- Preserve existing filters -->
|
|
<input type="hidden" name="search" value="{{ request('search') }}">
|
|
<input type="hidden" name="kategori" value="{{ request('kategori') }}">
|
|
<input type="hidden" name="status" value="{{ request('status') }}">
|
|
|
|
<select name="chart_month" onchange="updateChartYear(this); this.form.submit();"
|
|
class="px-3 py-1.5 border border-[#E5E7F2] rounded-lg focus:ring-2 focus:ring-[#4A538F] focus:border-[#4A538F] bg-white text-[#2F347A] text-sm">
|
|
@foreach($monthOptions as $option)
|
|
<option value="{{ $option['month'] }}"
|
|
data-year="{{ $option['year'] }}"
|
|
{{ $filterMonth == $option['month'] && $filterYear == $option['year'] ? 'selected' : '' }}>
|
|
{{ $option['label'] }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
<input type="hidden" name="chart_year" id="chartYearInput" value="{{ $filterYear }}">
|
|
</form>
|
|
</div>
|
|
@if(count($pieLabels) > 0)
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
<div class="h-64 flex items-center justify-center">
|
|
<canvas id="pieChart"></canvas>
|
|
</div>
|
|
<div class="space-y-2">
|
|
@foreach($pieLabels as $index => $label)
|
|
@php
|
|
$percentage = $totalStock > 0 ? round(($pieData[$index] / $totalStock) * 100, 1) : 0;
|
|
$colors = ['#1E3A8A', '#3B82F6', '#7C3AED', '#06B6D4', '#6366F1'];
|
|
@endphp
|
|
<div class="flex items-center justify-between text-sm">
|
|
<div class="flex items-center gap-2">
|
|
<span class="w-3 h-3 rounded-full" style="background-color: {{ $colors[$index] ?? '#999' }}"></span>
|
|
<span class="text-[#2F347A]">{{ $label }}</span>
|
|
</div>
|
|
<span class="font-medium text-[#4A538F]">{{ number_format($pieData[$index]) }} ({{ $percentage }}%)</span>
|
|
</div>
|
|
@endforeach
|
|
<div class="mt-4 pt-4 border-t border-[#E5E7F2]">
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-[#7A7FAE]">Total Stok Masuk</span>
|
|
<span class="font-bold text-[#2F347A]">{{ number_format($totalStock) }} unit</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@else
|
|
<div class="h-40 flex items-center justify-center text-[#7A7FAE]">
|
|
<div class="text-center">
|
|
<svg class="w-12 h-12 mx-auto mb-2 text-[#E5E7F2]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
|
|
</svg>
|
|
<p>Tidak ada data obat masuk</p>
|
|
<p class="text-sm">pada bulan {{ $selectedDate->translatedFormat('F Y') }}</p>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</x-card>
|
|
|
|
<!-- Table -->
|
|
<x-card class="overflow-hidden">
|
|
<div class="px-6 py-4 table-header-custom">
|
|
<h2 class="text-lg font-semibold">Daftar Obat Masuk</h2>
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead class="bg-[#F4F6FF] border-b border-[#E5E7F2]">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Tanggal</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Nama Obat</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Kode Batch</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Kategori</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Satuan</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Stok</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Status</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-[#7A7FAE] uppercase tracking-wider">Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-[#E5E7F2]">
|
|
@forelse($obatMasuks as $item)
|
|
<tr class="hover:bg-[#F4F6FF]">
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-[#7A7FAE]">
|
|
{{ $item->tanggal_penerimaan->format('d M Y') }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<div class="font-medium text-[#2F347A]">{{ $item->nama_obat }}</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-[#7A7FAE]">{{ $item->kode_batch }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-[#7A7FAE]">
|
|
{{ $item->kategori->nama ?? 'N/A' }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-[#7A7FAE]">
|
|
{{ $item->satuan->nama ?? 'N/A' }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-[#7A7FAE]">{{ $item->stok }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<x-badge :type="$item->status_stok">
|
|
{{ $item->stok > 0 ? 'Tersedia' : 'Habis' }}
|
|
</x-badge>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm" x-data="{ open: false }">
|
|
<div class="relative">
|
|
<button @click="open = !open" class="p-2 hover:bg-[#E9EBF5] rounded-lg">
|
|
<svg class="w-5 h-5 text-[#7A7FAE]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"/>
|
|
</svg>
|
|
</button>
|
|
<div x-show="open" @click.away="open = false"
|
|
class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-[#E5E7F2] z-10">
|
|
<a href="{{ route('obat-masuk.show', $item) }}" class="block px-4 py-2 text-sm text-[#2F347A] hover:bg-[#F4F6FF]">Detail</a>
|
|
@if(auth()->user()->isApoteker() || auth()->user()->isSuperAdmin())
|
|
<a href="{{ route('obat-masuk.edit', $item) }}" class="block px-4 py-2 text-sm text-[#2F347A] hover:bg-[#F4F6FF]">Edit</a>
|
|
<form method="POST" action="{{ route('obat-masuk.destroy', $item) }}"
|
|
onsubmit="return confirm('Yakin ingin menghapus data ini?')">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="block w-full text-left px-4 py-2 text-sm text-[#C0392B] hover:bg-[#FFD6D6]">Hapus</button>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="8" class="px-6 py-12 text-center text-[#7A7FAE]">
|
|
Belum ada data obat masuk
|
|
</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="px-6 py-4 border-t border-[#E5E7F2]">
|
|
{{ $obatMasuks->withQueryString()->links() }}
|
|
</div>
|
|
</x-card>
|
|
</div>
|
|
|
|
@push('scripts')
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Update chart year when month changes
|
|
window.updateChartYear = function(select) {
|
|
const selectedOption = select.options[select.selectedIndex];
|
|
document.getElementById('chartYearInput').value = selectedOption.dataset.year;
|
|
};
|
|
|
|
// Pie Chart - Trend Obat Masuk
|
|
const pieChartEl = document.getElementById('pieChart');
|
|
if (pieChartEl) {
|
|
const pieCtx = pieChartEl.getContext('2d');
|
|
const pieLabels = @json($pieLabels);
|
|
const pieData = @json($pieData);
|
|
|
|
new Chart(pieCtx, {
|
|
type: 'pie',
|
|
data: {
|
|
labels: pieLabels,
|
|
datasets: [{
|
|
data: pieData,
|
|
backgroundColor: [
|
|
'#1E3A8A',
|
|
'#3B82F6',
|
|
'#7C3AED',
|
|
'#06B6D4',
|
|
'#6366F1'
|
|
],
|
|
borderColor: [
|
|
'#1E3A8A',
|
|
'#3B82F6',
|
|
'#7C3AED',
|
|
'#06B6D4',
|
|
'#6366F1'
|
|
],
|
|
borderWidth: 2
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
display: false
|
|
},
|
|
tooltip: {
|
|
callbacks: {
|
|
label: function(context) {
|
|
const total = pieData.reduce((a, b) => a + b, 0);
|
|
const percentage = total > 0 ? ((context.raw / total) * 100).toFixed(1) : 0;
|
|
return context.label + ': ' + context.raw.toLocaleString() + ' (' + percentage + '%)';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
@endpush
|
|
</x-app-layout>
|