267 lines
17 KiB
PHP
267 lines
17 KiB
PHP
@extends('layouts.admin')
|
|
|
|
@section('content')
|
|
<div class="py-6 px-4 sm:px-6 lg:px-8">
|
|
<div class="max-w-7xl mx-auto">
|
|
<div class="bg-white rounded-lg shadow-lg overflow-hidden">
|
|
<div class="bg-gradient-to-r from-blue-500 to-indigo-600 px-6 py-4">
|
|
<h2 class="text-xl font-semibold text-white">Laporan Pendapatan</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<!-- Filter Form -->
|
|
<form method="GET" action="{{ route('admin.revenues.index') }}" class="mb-8">
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
|
|
<div>
|
|
<label for="start_date" class="block text-sm font-medium text-gray-700 mb-1">Tanggal Mulai</label>
|
|
<input type="date" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
|
|
id="start_date" name="start_date" value="{{ $startDate }}">
|
|
</div>
|
|
<div>
|
|
<label for="end_date" class="block text-sm font-medium text-gray-700 mb-1">Tanggal Akhir</label>
|
|
<input type="date" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
|
|
id="end_date" name="end_date" value="{{ $endDate }}">
|
|
</div>
|
|
<div>
|
|
<label for="venue_id" class="block text-sm font-medium text-gray-700 mb-1">Venue</label>
|
|
<select class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
|
|
id="venue_id" name="venue_id">
|
|
<option value="">Semua Venue</option>
|
|
@foreach($venues as $venue)
|
|
<option value="{{ $venue->id }}" {{ $venueId == $venue->id ? 'selected' : '' }}>
|
|
{{ $venue->name }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="flex items-end">
|
|
<div class="flex space-x-2">
|
|
<button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
|
<svg class="h-4 w-4 mr-1.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
|
|
</svg>
|
|
Filter
|
|
</button>
|
|
<a href="{{ route('admin.revenues.export', request()->query()) }}" class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500">
|
|
<svg class="h-4 w-4 mr-1.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
|
</svg>
|
|
Export
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Summary Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
|
|
<div class="bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl shadow p-6 border border-blue-100">
|
|
<div class="text-center">
|
|
<h3 class="text-lg font-medium text-gray-700 mb-2">Total Pendapatan</h3>
|
|
<p class="text-3xl font-bold text-indigo-600">Rp {{ number_format($totalRevenue, 0, ',', '.') }}</p>
|
|
</div>
|
|
</div>
|
|
<div class="bg-gradient-to-br from-purple-50 to-pink-50 rounded-xl shadow p-6 border border-purple-100">
|
|
<div class="text-center">
|
|
<h3 class="text-lg font-medium text-gray-700 mb-2">Total Booking</h3>
|
|
<p class="text-3xl font-bold text-purple-600">{{ $totalBookings }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chart for Daily Revenue -->
|
|
<div class="mb-8">
|
|
<div class="bg-white rounded-xl shadow-lg border border-gray-100 overflow-hidden">
|
|
<div class="bg-gradient-to-r from-gray-50 to-gray-100 px-6 py-4 border-b border-gray-200">
|
|
<h3 class="text-lg font-medium text-gray-800">Grafik Pendapatan Harian</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<canvas id="dailyRevenueChart" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Revenue Per Venue Table -->
|
|
<div class="mb-8">
|
|
<div class="bg-white rounded-xl shadow-lg border border-gray-100 overflow-hidden">
|
|
<div class="bg-gradient-to-r from-gray-50 to-gray-100 px-6 py-4 border-b border-gray-200">
|
|
<h3 class="text-lg font-medium text-gray-800">Pendapatan Per Venue</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Venue</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total Booking</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total Pendapatan</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
@forelse($revenuePerVenue as $venueRevenue)
|
|
<tr class="hover:bg-gray-50">
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ $venueRevenue->venue_name }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $venueRevenue->total_bookings }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 font-semibold">
|
|
Rp {{ number_format($venueRevenue->total_revenue, 0, ',', '.') }}
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="3" class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center">Tidak ada data pendapatan</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Revenue Per Table -->
|
|
@if($revenuePerTable)
|
|
<div>
|
|
<div class="bg-white rounded-xl shadow-lg border border-gray-100 overflow-hidden">
|
|
<div class="bg-gradient-to-r from-gray-50 to-gray-100 px-6 py-4 border-b border-gray-200">
|
|
<h3 class="text-lg font-medium text-gray-800">Detail Pendapatan Per Meja</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Meja</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Jumlah Booking</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total Pendapatan</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
@forelse($revenuePerTable as $tableRevenue)
|
|
<tr class="hover:bg-gray-50">
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ $tableRevenue->table_name }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $tableRevenue->booking_count }}</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 font-semibold">
|
|
Rp {{ number_format($tableRevenue->table_revenue, 0, ',', '.') }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
<a href="{{ route('admin.revenues.detail', ['tableId' => $tableRevenue->table_id, 'start_date' => $startDate, 'end_date' => $endDate]) }}"
|
|
class="inline-flex items-center px-3 py-1.5 border border-transparent text-xs leading-4 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
|
<svg class="h-4 w-4 mr-1" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
|
</svg>
|
|
Detail
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="4" class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center">Tidak ada data pendapatan meja</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@section('scripts')
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Prepare data for chart
|
|
const dailyData = @json($dailyRevenue);
|
|
|
|
// Extract dates and revenues
|
|
const dates = dailyData.map(item => item.date);
|
|
const revenues = dailyData.map(item => item.revenue);
|
|
|
|
// Create the chart
|
|
const ctx = document.getElementById('dailyRevenueChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: dates,
|
|
datasets: [{
|
|
label: 'Pendapatan Harian (Rp)',
|
|
data: revenues,
|
|
backgroundColor: 'rgba(79, 70, 229, 0.1)',
|
|
borderColor: '#4f46e5',
|
|
borderWidth: 2,
|
|
tension: 0.3,
|
|
pointBackgroundColor: '#4f46e5',
|
|
pointBorderColor: '#fff',
|
|
pointBorderWidth: 2,
|
|
pointRadius: 4,
|
|
pointHoverRadius: 6
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
plugins: {
|
|
legend: {
|
|
position: 'top',
|
|
labels: {
|
|
font: {
|
|
family: "'Inter', sans-serif",
|
|
size: 12
|
|
}
|
|
}
|
|
},
|
|
tooltip: {
|
|
backgroundColor: 'rgba(17, 24, 39, 0.8)',
|
|
titleFont: {
|
|
family: "'Inter', sans-serif",
|
|
size: 13
|
|
},
|
|
bodyFont: {
|
|
family: "'Inter', sans-serif",
|
|
size: 12
|
|
},
|
|
callbacks: {
|
|
label: function (context) {
|
|
return 'Pendapatan: Rp ' + context.raw.toLocaleString('id-ID');
|
|
}
|
|
}
|
|
}
|
|
},
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
grid: {
|
|
color: 'rgba(156, 163, 175, 0.1)'
|
|
},
|
|
ticks: {
|
|
font: {
|
|
family: "'Inter', sans-serif",
|
|
size: 11
|
|
},
|
|
callback: function (value) {
|
|
return 'Rp ' + value.toLocaleString('id-ID');
|
|
}
|
|
}
|
|
},
|
|
x: {
|
|
grid: {
|
|
display: false
|
|
},
|
|
ticks: {
|
|
font: {
|
|
family: "'Inter', sans-serif",
|
|
size: 11
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
@endsection |