NIM_E31222351/resources/views/Home.blade.php

400 lines
17 KiB
PHP

@extends('Core.Sidebar')
@section('content')
<style>
.chart-container {
position: relative;
height: 300px;
width: 100%;
}
</style>
<div class="max-w-full bg-gradient-to-br from-indigo-50 to-blue-50 rounded-lg shadow-md dark:bg-gray-800 p-6">
<!-- Filter Section -->
<div class="flex flex-wrap items-center gap-4 mb-6">
<h2 class="text-xl font-bold text-indigo-700 dark:text-white">Dashboard Keuangan</h2>
<form action="{{ route('home.filter') }}" method="GET" class="flex flex-wrap items-center gap-4 sm:ml-auto">
<div class="flex items-center gap-2">
<span class="text-sm text-gray-600">Tanggal Awal</span>
<input type="date" name="start_date" class="form-input box bg-white border border-indigo-200 rounded-lg text-gray-600" value="{{ $startDate }}">
</div>
<div class="flex items-center gap-2">
<span class="text-sm text-gray-600">Tanggal Akhir</span>
<input type="date" name="end_date" class="form-input box bg-white border border-indigo-200 rounded-lg text-gray-600" value="{{ $endDate }}">
</div>
<button type="submit" class="btn bg-indigo-500 text-white px-4 py-2 rounded-lg hover:bg-indigo-600">
Filter
</button>
</form>
</div>
<!-- Main Metrics -->
<div class="grid grid-cols-2 gap-4 mb-6">
<!-- Total Pendapatan Card -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<div class="flex items-center">
<div class="w-12 h-12 rounded-lg bg-green-100 flex items-center justify-center me-3">
<svg class="w-6 h-6 text-green-600" 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"></path>
</svg>
</div>
<div>
<p class="text-sm text-gray-500 mb-1">Total Pendapatan</p>
<h3 class="text-2xl font-bold text-gray-800">
@if($totalPendapatan < 0)
-Rp {{ number_format(abs($totalPendapatan), 0, ',', '.') }}
@else
Rp {{ number_format($totalPendapatan, 0, ',', '.') }}
@endif
</h3>
<p class="text-sm text-gray-500">Periode: {{ date('d/m/Y', strtotime($startDate)) }} - {{ date('d/m/Y', strtotime($endDate)) }}</p>
</div>
</div>
</div>
<!-- Total Beban Card -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<div class="flex items-center">
<div class="w-12 h-12 rounded-lg bg-red-100 flex items-center justify-center me-3">
<svg class="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12H4"></path>
</svg>
</div>
<div>
<p class="text-sm text-gray-500 mb-1">Total Beban</p>
<h3 class="text-2xl font-bold text-gray-800">
@if($totalBeban < 0)
-Rp {{ number_format(abs($totalBeban), 0, ',', '.') }}
@else
Rp {{ number_format($totalBeban, 0, ',', '.') }}
@endif
</h3>
<p class="text-sm text-gray-500">Periode: {{ date('d/m/Y', strtotime($startDate)) }} - {{ date('d/m/Y', strtotime($endDate)) }}</p>
</div>
</div>
</div>
</div>
<!-- Detail Section -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<!-- Rincian Pendapatan -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Rincian Pendapatan</h4>
@foreach($pendapatan as $item)
<div class="flex justify-between items-center mb-2">
<div class="flex items-center">
<span class="text-sm text-gray-600">{{ ucwords($item['kategori']) }}</span>
<span class="text-xs text-gray-400 ml-2">({{ $item['kode_akun'] }})</span>
</div>
<span class="text-sm font-medium {{ $item['nominal'] < 0 ? 'text-red-600' : 'text-green-600' }}">
@if($item['nominal'] < 0)
-Rp {{ number_format(abs($item['nominal']), 0, ',', '.') }}
@else
Rp {{ number_format($item['nominal'], 0, ',', '.') }}
@endif
</span>
</div>
@endforeach
<div class="mt-4 pt-4 border-t">
<div class="flex justify-between items-center">
<span class="font-semibold">Total Pendapatan</span>
<span class="font-semibold {{ $totalPendapatan < 0 ? 'text-red-600' : 'text-green-600' }}">
@if($totalPendapatan < 0)
-Rp {{ number_format(abs($totalPendapatan), 0, ',', '.') }}
@else
Rp {{ number_format($totalPendapatan, 0, ',', '.') }}
@endif
</span>
</div>
</div>
</div>
<!-- Rincian Beban -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Rincian Beban</h4>
@foreach($beban as $item)
<div class="flex justify-between items-center mb-2">
<div class="flex items-center">
<span class="text-sm text-gray-600">{{ ucwords($item['kategori']) }}</span>
<span class="text-xs text-gray-400 ml-2">({{ $item['kode_akun'] }})</span>
</div>
<span class="text-sm font-medium {{ $item['nominal'] < 0 ? 'text-green-600' : 'text-red-600' }}">
@if($item['nominal'] < 0)
-Rp {{ number_format(abs($item['nominal']), 0, ',', '.') }}
@else
Rp {{ number_format($item['nominal'], 0, ',', '.') }}
@endif
</span>
</div>
@endforeach
<div class="mt-4 pt-4 border-t">
<div class="flex justify-between items-center">
<span class="font-semibold">Total Beban</span>
<span class="font-semibold {{ $totalBeban < 0 ? 'text-green-600' : 'text-red-600' }}">
@if($totalBeban < 0)
-Rp {{ number_format(abs($totalBeban), 0, ',', '.') }}
@else
Rp {{ number_format($totalBeban, 0, ',', '.') }}
@endif
</span>
</div>
</div>
</div>
</div>
<!-- Profit/Loss Section -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<!-- Total Laba/Rugi Card -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Laba/Rugi Total</h4>
<div class="flex items-center">
<div class="w-12 h-12 rounded-lg {{ $labaRugiTotal >= 0 ? 'bg-green-100' : 'bg-red-100' }} flex items-center justify-center me-3">
<svg class="w-6 h-6 {{ $labaRugiTotal >= 0 ? 'text-green-600' : 'text-red-600' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="{{ $labaRugiTotal >= 0 ? 'M5 10l7-7m0 0l7 7m-7-7v18' : 'M19 14l-7 7m0 0l-7-7m7 7V3' }}"></path>
</svg>
</div>
<div>
<h3 class="text-2xl font-bold {{ $labaRugiTotal >= 0 ? 'text-green-600' : 'text-red-600' }}">
@if($labaRugiTotal < 0)
-Rp {{ number_format(abs($labaRugiTotal), 0, ',', '.') }}
@else
Rp {{ number_format($labaRugiTotal, 0, ',', '.') }}
@endif
</h3>
<p class="text-sm text-gray-500">{{ $labaRugiTotal >= 0 ? 'Laba' : 'Rugi' }}</p>
</div>
</div>
</div>
<!-- Laba/Rugi Bulan Ini Card -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Laba/Rugi Periode Ini</h4>
<div class="flex items-center">
<div class="w-12 h-12 rounded-lg {{ $labaRugiBulanIni >= 0 ? 'bg-green-100' : 'bg-red-100' }} flex items-center justify-center me-3">
<svg class="w-6 h-6 {{ $labaRugiBulanIni >= 0 ? 'text-green-600' : 'text-red-600' }}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="{{ $labaRugiBulanIni >= 0 ? 'M5 10l7-7m0 0l7 7m-7-7v18' : 'M19 14l-7 7m0 0l-7-7m7 7V3' }}"></path>
</svg>
</div>
<div>
<h3 class="text-2xl font-bold {{ $labaRugiBulanIni >= 0 ? 'text-green-600' : 'text-red-600' }}">
@if($labaRugiBulanIni < 0)
-Rp {{ number_format(abs($labaRugiBulanIni), 0, ',', '.') }}
@else
Rp {{ number_format($labaRugiBulanIni, 0, ',', '.') }}
@endif
</h3>
<p class="text-sm text-gray-500">{{ $labaRugiBulanIni >= 0 ? 'Laba' : 'Rugi' }}</p>
</div>
</div>
</div>
</div>
<!-- Charts Section -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
<!-- Bar Chart -->
<div class="bg-white p-6 rounded-xl shadow-sm">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Tren Pendapatan & Beban</h4>
<div class="chart-container">
<canvas id="financial-trend-chart"></canvas>
</div>
</div>
<!-- Category Chart -->
<div class="bg-white p-6 rounded-xl shadow-sm">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Distribusi per Kategori</h4>
<div class="chart-container">
<canvas id="category-distribution-chart"></canvas>
</div>
</div>
</div>
<!-- Recent Transactions Table -->
<div class="bg-white rounded-xl shadow-sm overflow-hidden">
<div class="p-6 border-b border-gray-100">
<h4 class="text-lg font-semibold text-gray-700">Transaksi Terbaru</h4>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tanggal</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Kode</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Kategori</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Keterangan</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Pendapatan</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Beban</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@foreach($recentTransactions as $transaction)
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ date('d/m/Y', strtotime($transaction->Tanggal)) }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $transaction->kode }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $transaction->kategori }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $transaction->keterangan }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-green-600">
{{ $transaction->uang_masuk > 0 ? 'Rp ' . number_format($transaction->uang_masuk, 0, ',', '.') : '-' }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-red-600">
{{ $transaction->uang_keluar > 0 ? 'Rp ' . number_format($transaction->uang_keluar, 0, ',', '.') : '-' }}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@push('scripts')
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Format number to Rupiah
function formatRupiah(number) {
return 'Rp ' + number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
try {
// Financial Trend Chart
const trendCtx = document.getElementById('financial-trend-chart');
if (trendCtx) {
const monthlyData = @json($monthlyTotals);
const labels = monthlyData.map(item => {
const [year, month] = item.periode.split('-');
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nov', 'Des'];
return `${monthNames[parseInt(month)-1]} ${year}`;
});
const pendapatanData = monthlyData.map(item => parseFloat(item.total_debit) || 0);
const bebanData = monthlyData.map(item => parseFloat(item.total_kredit) || 0);
new Chart(trendCtx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Pendapatan',
data: pendapatanData,
backgroundColor: 'rgba(34, 197, 94, 0.5)',
borderColor: 'rgb(34, 197, 94)',
borderWidth: 1,
order: 2
}, {
label: 'Beban',
data: bebanData,
backgroundColor: 'rgba(239, 68, 68, 0.5)',
borderColor: 'rgb(239, 68, 68)',
borderWidth: 1,
order: 2
}, {
label: 'Laba/Rugi',
data: pendapatanData.map((pendapatan, index) => pendapatan - bebanData[index]),
type: 'line',
borderColor: 'rgb(59, 130, 246)',
borderWidth: 2,
fill: false,
order: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
intersect: false,
mode: 'index'
},
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return formatRupiah(value);
}
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': ' + formatRupiah(context.parsed.y);
}
}
}
}
}
});
}
// Category Distribution Chart
const categoryCtx = document.getElementById('category-distribution-chart');
if (categoryCtx) {
const categoryData = @json($categoryTotals);
const categories = categoryData.map(item => item.kategori);
const pendapatanPerKategori = categoryData.map(item => parseFloat(item.total_debit) || 0);
const bebanPerKategori = categoryData.map(item => parseFloat(item.total_kredit) || 0);
new Chart(categoryCtx, {
type: 'bar',
data: {
labels: categories,
datasets: [{
label: 'Pendapatan',
data: pendapatanPerKategori,
backgroundColor: 'rgba(34, 197, 94, 0.5)',
borderColor: 'rgb(34, 197, 94)',
borderWidth: 1
}, {
label: 'Beban',
data: bebanPerKategori,
backgroundColor: 'rgba(239, 68, 68, 0.5)',
borderColor: 'rgb(239, 68, 68)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
indexAxis: 'y',
scales: {
x: {
beginAtZero: true,
ticks: {
callback: function(value) {
return formatRupiah(value);
}
}
}
},
plugins: {
legend: {
position: 'bottom'
},
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': ' + formatRupiah(context.parsed.x);
}
}
}
}
}
});
}
} catch (error) {
console.error('Error creating charts:', error);
}
});
</script>
@endpush
@endsection