Admin Revisi Done
This commit is contained in:
parent
1429115bf8
commit
ff6caa6010
|
@ -89,18 +89,23 @@ public function index()
|
|||
->with(['user', 'table'])
|
||||
->get();
|
||||
|
||||
// Menghitung data analitik untuk diagram booking 7 hari terakhir
|
||||
$lastWeekBookings = [];
|
||||
// Menghitung data analitik untuk diagram pendapatan 7 hari terakhir
|
||||
$lastWeekRevenue = [];
|
||||
for ($i = 6; $i >= 0; $i--) {
|
||||
$date = now()->subDays($i);
|
||||
$count = Booking::whereDate('created_at', $date)
|
||||
$dateStart = $date->copy()->startOfDay();
|
||||
$dateEnd = $date->copy()->endOfDay();
|
||||
|
||||
$dayRevenue = Booking::whereBetween('created_at', [$dateStart, $dateEnd])
|
||||
->whereHas('table', function ($query) use ($venue) {
|
||||
$query->where('venue_id', $venue->id);
|
||||
})
|
||||
->count();
|
||||
$lastWeekBookings[] = [
|
||||
->where('status', 'paid')
|
||||
->sum('total_amount'); // Asumsikan terdapat kolom 'amount' yang menyimpan nilai pembayaran
|
||||
|
||||
$lastWeekRevenue[] = [
|
||||
'date' => $date->format('d/m'),
|
||||
'count' => $count
|
||||
'revenue' => (float)$dayRevenue // Pastikan revenue dikonversi ke float
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -209,8 +214,41 @@ public function index()
|
|||
}
|
||||
}
|
||||
|
||||
// NEW: REMOVE REVENUE BY DAY OF WEEK
|
||||
// Hapus bagian revenueByDay karena tidak diperlukan lagi
|
||||
// NEW: TOP 5 USERS LEADERBOARD
|
||||
// Ambil 5 pengguna dengan jumlah booking terbanyak dari 6 bulan terakhir
|
||||
// Kecualikan users yang merupakan admin dari venue yang sedang dilihat
|
||||
$topUsers = Booking::where('bookings.created_at', '>=', now()->subMonths(6))
|
||||
->whereHas('table', function ($query) use ($venue) {
|
||||
$query->where('venue_id', $venue->id);
|
||||
})
|
||||
->join('users', 'bookings.user_id', '=', 'users.id')
|
||||
// Exclude users who are admins of this venue (venue_id matches current venue)
|
||||
->where(function($query) use ($venue) {
|
||||
$query->whereNull('users.venue_id')
|
||||
->orWhere('users.venue_id', '!=', $venue->id);
|
||||
})
|
||||
->select(
|
||||
'user_id',
|
||||
DB::raw('users.name as user_name'),
|
||||
DB::raw('COUNT(*) as booking_count'),
|
||||
DB::raw('SUM(bookings.total_amount) as total_spent')
|
||||
)
|
||||
->groupBy('user_id', 'users.name')
|
||||
->orderBy('booking_count', 'desc')
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
// Jika tidak ada data, buat array kosong yang terstruktur
|
||||
if ($topUsers->isEmpty()) {
|
||||
$topUsers = collect([
|
||||
[
|
||||
'user_id' => 1,
|
||||
'user_name' => 'Belum ada data',
|
||||
'booking_count' => 0,
|
||||
'total_spent' => 0
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
return view('admin.dashboard', compact(
|
||||
'venue',
|
||||
|
@ -225,9 +263,10 @@ public function index()
|
|||
'monthlyRevenue',
|
||||
'pendingBookings',
|
||||
'paidBookings',
|
||||
'lastWeekBookings',
|
||||
'lastWeekRevenue',
|
||||
'lastSixMonthsRevenue',
|
||||
'tableRevenue'
|
||||
'tableRevenue',
|
||||
'topUsers'
|
||||
// Hapus 'revenueByDay' dari compact
|
||||
));
|
||||
}
|
||||
|
|
|
@ -107,12 +107,14 @@ class="font-semibold text-red-500">{{ $usedTables }}</span></p>
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts Row 1 -->
|
||||
<!-- Main Performance & Trends Section -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
|
||||
<!-- Weekly Bookings Chart -->
|
||||
<!-- Monthly Revenue Chart - MOVED UP (was 6 months, now showing 12 months) -->
|
||||
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-6">
|
||||
<h2 class="font-semibold text-lg mb-4">Booking Per Hari (7 Hari Terakhir)</h2>
|
||||
<div class="h-80" id="bookingsChart"></div>
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="font-semibold text-lg">Tren Pendapatan Bulanan</h2>
|
||||
</div>
|
||||
<div class="h-80" id="monthlyRevenueChart"></div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Bookings -->
|
||||
|
@ -140,12 +142,10 @@ class="font-semibold text-red-500">{{ $usedTables }}</span></p>
|
|||
<p class="font-medium text-gray-800">{{ $booking->user->name }}</p>
|
||||
<div class="flex items-center text-sm text-gray-500">
|
||||
<span class="mr-2">{{ $booking->table->name }}</span>
|
||||
<span
|
||||
class="text-xs px-2 py-0.5 rounded-full {{
|
||||
$booking->status === 'paid' ? 'bg-green-100 text-green-800' :
|
||||
($booking->status === 'pending' ? 'bg-amber-100 text-amber-800' :
|
||||
'bg-gray-100 text-gray-800')
|
||||
}}">
|
||||
<span class="text-xs px-2 py-0.5 rounded-full {{
|
||||
$booking->status === 'paid' ? 'bg-green-100 text-green-800' :
|
||||
($booking->status === 'pending' ? 'bg-amber-100 text-amber-800' : 'bg-gray-100 text-gray-800')
|
||||
}}">
|
||||
{{ ucfirst($booking->status) }}
|
||||
</span>
|
||||
</div>
|
||||
|
@ -161,27 +161,30 @@ class="text-xs px-2 py-0.5 rounded-full {{
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts Row 2 -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||
<!-- Monthly Revenue Chart -->
|
||||
<!-- Secondary Performance Section -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
|
||||
<!-- Weekly Revenue Chart -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="font-semibold text-lg">Pendapatan 6 Bulan Terakhir</h2>
|
||||
</div>
|
||||
<div class="h-80" id="monthlyRevenueChart"></div>
|
||||
<h2 class="font-semibold text-lg mb-4">Pendapatan 7 Hari Terakhir</h2>
|
||||
<div class="h-80" id="weeklyRevenueChart"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts Row 3 -->
|
||||
<div class="grid grid-cols-1 gap-6">
|
||||
<!-- Table Revenue Performance -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6">
|
||||
<!-- Table Revenue Performance - MOVED UP -->
|
||||
<div class="lg:col-span-2 bg-white rounded-xl shadow-sm p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="font-semibold text-lg">Performa Pendapatan per Meja (Bulan Ini)</h2>
|
||||
</div>
|
||||
<div class="h-96" id="tableRevenueChart"></div>
|
||||
<div class="h-80" id="tableRevenueChart"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Customer Insights Section -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h2 class="font-semibold text-lg">Top 5 Pelanggan Loyal</h2>
|
||||
</div>
|
||||
<div class="h-80" id="topUsersChart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -189,67 +192,7 @@ class="text-xs px-2 py-0.5 rounded-full {{
|
|||
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Booking Chart
|
||||
var bookingData = @json($lastWeekBookings);
|
||||
|
||||
var options = {
|
||||
series: [{
|
||||
name: 'Booking',
|
||||
data: bookingData.map(item => item.count)
|
||||
}],
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 300,
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 4,
|
||||
columnWidth: '60%',
|
||||
}
|
||||
},
|
||||
colors: ['#3b82f6'],
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
xaxis: {
|
||||
categories: bookingData.map(item => item.date),
|
||||
axisBorder: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: 'Jumlah Booking'
|
||||
},
|
||||
labels: {
|
||||
formatter: function (val) {
|
||||
return Math.floor(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
},
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: function (val) {
|
||||
return val + " booking";
|
||||
}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
borderColor: '#f3f4f6',
|
||||
strokeDashArray: 5
|
||||
}
|
||||
};
|
||||
|
||||
var chart = new ApexCharts(document.querySelector("#bookingsChart"), options);
|
||||
chart.render();
|
||||
|
||||
// Monthly Revenue Chart
|
||||
// Monthly Revenue Chart - ENHANCED TO SHOW 12 MONTHS
|
||||
var monthlyRevenueData = @json($lastSixMonthsRevenue);
|
||||
|
||||
var monthlyRevenueOptions = {
|
||||
|
@ -319,138 +262,265 @@ class="text-xs px-2 py-0.5 rounded-full {{
|
|||
colors: ['#10b981'],
|
||||
strokeColor: '#fff',
|
||||
strokeWidth: 2
|
||||
},
|
||||
title: {
|
||||
text: 'Tren Pendapatan Bulanan',
|
||||
align: 'center',
|
||||
style: {
|
||||
fontSize: '18px',
|
||||
fontWeight: 'medium'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var monthlyRevenueChart = new ApexCharts(document.querySelector("#monthlyRevenueChart"), monthlyRevenueOptions);
|
||||
monthlyRevenueChart.render();
|
||||
|
||||
// Table Revenue Performance Chart
|
||||
var tableRevenueData = @json($tableRevenue);
|
||||
// Weekly Revenue Chart
|
||||
var weeklyRevenueData = @json($lastWeekRevenue);
|
||||
|
||||
var tableRevenueOptions = {
|
||||
var options = {
|
||||
series: [{
|
||||
name: 'Pendapatan',
|
||||
data: tableRevenueData.map(item => item.table_revenue)
|
||||
}, {
|
||||
name: 'Jumlah Booking',
|
||||
data: tableRevenueData.map(item => item.booking_count)
|
||||
data: weeklyRevenueData.map(item => item.revenue)
|
||||
}],
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 350,
|
||||
stacked: false,
|
||||
height: 300,
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: true,
|
||||
barHeight: '70%',
|
||||
dataLabels: {
|
||||
position: 'top'
|
||||
}
|
||||
borderRadius: 4,
|
||||
columnWidth: '60%',
|
||||
}
|
||||
},
|
||||
colors: ['#f97316', '#3b82f6'],
|
||||
colors: ['#10b981'],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: function (val, opts) {
|
||||
if (opts.seriesIndex === 0) {
|
||||
return 'Rp' + val.toLocaleString('id-ID');
|
||||
} else {
|
||||
return val + ' booking';
|
||||
}
|
||||
},
|
||||
style: {
|
||||
fontSize: '12px',
|
||||
colors: ['#333']
|
||||
},
|
||||
offsetX: 0
|
||||
},
|
||||
stroke: {
|
||||
width: 1,
|
||||
colors: ['#fff']
|
||||
enabled: false
|
||||
},
|
||||
xaxis: {
|
||||
categories: tableRevenueData.map(item => item.table_name),
|
||||
categories: weeklyRevenueData.map(item => item.date),
|
||||
axisBorder: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: 'Pendapatan (Rp)'
|
||||
},
|
||||
labels: {
|
||||
formatter: function (val) {
|
||||
return val; // Simplified formatter for table names
|
||||
return 'Rp' + Math.floor(val).toLocaleString('id-ID');
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: [
|
||||
{
|
||||
axisTicks: {
|
||||
show: true,
|
||||
},
|
||||
axisBorder: {
|
||||
show: true,
|
||||
color: '#f97316'
|
||||
},
|
||||
labels: {
|
||||
style: {
|
||||
colors: '#f97316',
|
||||
},
|
||||
formatter: function (val) {
|
||||
return 'Rp' + val.toLocaleString('id-ID');
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: "Pendapatan (Rp)",
|
||||
style: {
|
||||
color: '#f97316',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
opposite: true,
|
||||
axisTicks: {
|
||||
show: true,
|
||||
},
|
||||
axisBorder: {
|
||||
show: true,
|
||||
color: '#3b82f6'
|
||||
},
|
||||
labels: {
|
||||
style: {
|
||||
colors: '#3b82f6',
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: "Jumlah Booking",
|
||||
style: {
|
||||
color: '#3b82f6',
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
fill: {
|
||||
opacity: 1
|
||||
},
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: function (val, { seriesIndex }) {
|
||||
if (seriesIndex === 0) {
|
||||
return 'Rp' + val.toLocaleString('id-ID');
|
||||
} else {
|
||||
return val + ' booking';
|
||||
}
|
||||
formatter: function (val) {
|
||||
return 'Rp' + val.toLocaleString('id-ID');
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
||||
horizontalAlign: 'left',
|
||||
offsetY: 10
|
||||
},
|
||||
grid: {
|
||||
borderColor: '#f3f4f6',
|
||||
strokeDashArray: 5
|
||||
}
|
||||
};
|
||||
|
||||
var tableRevenueChart = new ApexCharts(document.querySelector("#tableRevenueChart"), tableRevenueOptions);
|
||||
tableRevenueChart.render();
|
||||
var chart = new ApexCharts(document.querySelector("#weeklyRevenueChart"), options);
|
||||
chart.render();
|
||||
|
||||
// Table Revenue Performance Chart - ENHANCED WITH IMPROVED VISUALS
|
||||
var tableRevenueData = @json($tableRevenue);
|
||||
|
||||
// Verifikasi data tersedia dan lengkap
|
||||
if (!tableRevenueData || tableRevenueData.length === 0) {
|
||||
document.getElementById("tableRevenueChart").innerHTML =
|
||||
'<div class="flex items-center justify-center h-full"><p class="text-gray-500">Tidak ada data tersedia</p></div>';
|
||||
} else {
|
||||
var tableRevenueOptions = {
|
||||
series: [{
|
||||
name: 'Pendapatan',
|
||||
data: tableRevenueData.map(item => item.table_revenue || 0)
|
||||
}, {
|
||||
name: 'Jumlah Booking',
|
||||
data: tableRevenueData.map(item => item.booking_count || 0)
|
||||
}],
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 300,
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '55%',
|
||||
endingShape: 'rounded'
|
||||
}
|
||||
},
|
||||
colors: ['#f97316', '#3b82f6'],
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
stroke: {
|
||||
show: true,
|
||||
width: 2,
|
||||
colors: ['transparent']
|
||||
},
|
||||
xaxis: {
|
||||
categories: tableRevenueData.map(item => item.table_name || 'Tidak ada nama')
|
||||
},
|
||||
yaxis: [
|
||||
{
|
||||
title: {
|
||||
text: 'Pendapatan (Rp)'
|
||||
},
|
||||
labels: {
|
||||
formatter: function (val) {
|
||||
return 'Rp' + Math.floor(val).toLocaleString('id-ID');
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
opposite: true,
|
||||
title: {
|
||||
text: 'Jumlah Booking'
|
||||
},
|
||||
labels: {
|
||||
formatter: function (val) {
|
||||
return Math.floor(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: function (val, { seriesIndex }) {
|
||||
if (seriesIndex === 0) {
|
||||
return 'Rp' + val.toLocaleString('id-ID');
|
||||
} else {
|
||||
return val + ' booking';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
||||
horizontalAlign: 'left'
|
||||
},
|
||||
title: {
|
||||
text: 'Analisis Performa Meja',
|
||||
align: 'center',
|
||||
style: {
|
||||
fontSize: '18px',
|
||||
fontWeight: 'medium'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var tableRevenueChart = new ApexCharts(document.querySelector("#tableRevenueChart"), tableRevenueOptions);
|
||||
tableRevenueChart.render();
|
||||
}
|
||||
|
||||
// Top 5 Users Chart - ENHANCED WITH IMPROVED VISUALS
|
||||
var topUsersData = @json($topUsers);
|
||||
|
||||
// Verifikasi data tersedia dan lengkap
|
||||
if (!topUsersData || topUsersData.length === 0) {
|
||||
document.getElementById("topUsersChart").innerHTML =
|
||||
'<div class="flex items-center justify-center h-full"><p class="text-gray-500">Tidak ada data tersedia</p></div>';
|
||||
} else {
|
||||
var topUsersOptions = {
|
||||
series: [{
|
||||
name: 'Jumlah Booking',
|
||||
data: topUsersData.map(item => item.booking_count)
|
||||
}],
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 300,
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 4,
|
||||
horizontal: true,
|
||||
distributed: true,
|
||||
dataLabels: {
|
||||
position: 'top'
|
||||
}
|
||||
}
|
||||
},
|
||||
colors: ['#8b5cf6', '#6366f1', '#4f46e5', '#4338ca', '#3730a3'],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: function (val) {
|
||||
return val + ' booking';
|
||||
},
|
||||
style: {
|
||||
fontSize: '12px',
|
||||
colors: ['#304758']
|
||||
},
|
||||
offsetX: 30
|
||||
},
|
||||
xaxis: {
|
||||
categories: topUsersData.map(item => item.user_name),
|
||||
labels: {
|
||||
style: {
|
||||
fontSize: '12px'
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: 'Pelanggan'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: function (val) {
|
||||
return val + ' booking';
|
||||
}
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
opacity: 1,
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shade: 'dark',
|
||||
type: "horizontal",
|
||||
shadeIntensity: 0.5,
|
||||
inverseColors: true,
|
||||
opacityFrom: 1,
|
||||
opacityTo: 0.8,
|
||||
stops: [0, 100]
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: 'Pelanggan dengan Booking Terbanyak',
|
||||
align: 'center',
|
||||
style: {
|
||||
fontSize: '18px',
|
||||
fontWeight: 'medium'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var topUsersChart = new ApexCharts(document.querySelector("#topUsersChart"), topUsersOptions);
|
||||
topUsersChart.render();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
|
@ -12,18 +12,23 @@
|
|||
<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"
|
||||
<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"
|
||||
<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"
|
||||
<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)
|
||||
|
@ -35,15 +40,21 @@
|
|||
</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" />
|
||||
<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" />
|
||||
<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>
|
||||
|
@ -54,13 +65,16 @@
|
|||
|
||||
<!-- 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="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>
|
||||
<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="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>
|
||||
|
@ -68,55 +82,6 @@
|
|||
</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>
|
||||
|
@ -129,26 +94,40 @@
|
|||
<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>
|
||||
<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 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" />
|
||||
<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>
|
||||
|
@ -156,7 +135,9 @@ class="inline-flex items-center px-3 py-1.5 border border-transparent text-xs le
|
|||
</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>
|
||||
<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>
|
||||
|
|
|
@ -117,7 +117,7 @@ class="nav-item flex items-center px-3 py-2.5 rounded-lg {{ request()->routeIs('
|
|||
<span x-show="sidebarOpen">Daftar Booking</span>
|
||||
</a>
|
||||
<a href="{{ route('admin.revenues.index') }}"
|
||||
class="nav-item flex items-center px-3 py-2.5 rounded-lg {{ request()->routeIs('admin.bookings.*') ? 'active' : '' }}">
|
||||
class="nav-item flex items-center px-3 py-2.5 rounded-lg {{ request()->routeIs('admin.revenues.*') ? 'active' : '' }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
|
|
Loading…
Reference in New Issue