feat: Implement role-based dashboard content visibility and consolidate view permissions under 'Analisys'.
This commit is contained in:
parent
1eba57cb6b
commit
9619912f2f
@ -12,6 +12,7 @@
|
|||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\Payroll;
|
use App\Models\Payroll;
|
||||||
use BackedEnum;
|
use BackedEnum;
|
||||||
|
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Filament\Forms\Components\DatePicker;
|
use Filament\Forms\Components\DatePicker;
|
||||||
use Filament\Forms\Components\Select;
|
use Filament\Forms\Components\Select;
|
||||||
@ -25,7 +26,7 @@
|
|||||||
|
|
||||||
class Analisys extends Page implements HasForms
|
class Analisys extends Page implements HasForms
|
||||||
{
|
{
|
||||||
use InteractsWithForms;
|
use HasPageShield, InteractsWithForms;
|
||||||
|
|
||||||
public ?array $data = [];
|
public ?array $data = [];
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Filament\Pages;
|
namespace App\Filament\Pages;
|
||||||
|
|
||||||
|
use App\Enums\RoleEnum;
|
||||||
use App\Models\Customer;
|
use App\Models\Customer;
|
||||||
use App\Models\DelayedGood;
|
use App\Models\DelayedGood;
|
||||||
use App\Models\EggCollectionItem;
|
use App\Models\EggCollectionItem;
|
||||||
@ -10,6 +11,7 @@
|
|||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\Payroll;
|
use App\Models\Payroll;
|
||||||
use Filament\Pages\Dashboard as BaseDashboard;
|
use Filament\Pages\Dashboard as BaseDashboard;
|
||||||
|
use Filament\Widgets\AccountWidget;
|
||||||
|
|
||||||
class Dashboard extends BaseDashboard
|
class Dashboard extends BaseDashboard
|
||||||
{
|
{
|
||||||
@ -17,6 +19,13 @@ class Dashboard extends BaseDashboard
|
|||||||
|
|
||||||
protected string $view = 'filament.pages.dashboard';
|
protected string $view = 'filament.pages.dashboard';
|
||||||
|
|
||||||
|
public function getHeaderWidgets(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
AccountWidget::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function getViewData(): array
|
public function getViewData(): array
|
||||||
{
|
{
|
||||||
$formatNumber = fn ($val) => number_format((float) $val, $val == floor($val) ? 0 : 2, ',', '.');
|
$formatNumber = fn ($val) => number_format((float) $val, $val == floor($val) ? 0 : 2, ',', '.');
|
||||||
@ -118,6 +127,7 @@ public function getViewData(): array
|
|||||||
->get();
|
->get();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'isAdministrator' => auth()->user()->hasRole(RoleEnum::ADMINISTRATOR->value),
|
||||||
'mainStats' => $mainStats,
|
'mainStats' => $mainStats,
|
||||||
'totalEggsByUnit' => $totalEggsByUnit,
|
'totalEggsByUnit' => $totalEggsByUnit,
|
||||||
'totalDelayedByUnit' => $delayedStatsByUnit,
|
'totalDelayedByUnit' => $delayedStatsByUnit,
|
||||||
|
|||||||
@ -22,11 +22,7 @@ public function run(): void
|
|||||||
"name": "Developer",
|
"name": "Developer",
|
||||||
"guard_name": "web",
|
"guard_name": "web",
|
||||||
"permissions" : [
|
"permissions" : [
|
||||||
"View:StatsOverview",
|
"View:Analisys",
|
||||||
"View:EggProductionChart",
|
|
||||||
"View:OrderTrendChart",
|
|
||||||
"View:RevenueExpenseChart",
|
|
||||||
"View:TopCustomersChart",
|
|
||||||
|
|
||||||
"ViewAny:Customer",
|
"ViewAny:Customer",
|
||||||
"View:Customer",
|
"View:Customer",
|
||||||
@ -189,11 +185,7 @@ public function run(): void
|
|||||||
"name": "Pemilik",
|
"name": "Pemilik",
|
||||||
"guard_name": "web",
|
"guard_name": "web",
|
||||||
"permissions" : [
|
"permissions" : [
|
||||||
"View:StatsOverview",
|
"View:Analisys",
|
||||||
"View:EggProductionChart",
|
|
||||||
"View:OrderTrendChart",
|
|
||||||
"View:RevenueExpenseChart",
|
|
||||||
"View:TopCustomersChart",
|
|
||||||
|
|
||||||
"ViewAny:Customer",
|
"ViewAny:Customer",
|
||||||
"View:Customer",
|
"View:Customer",
|
||||||
|
|||||||
@ -1,220 +1,242 @@
|
|||||||
<x-filament-panels::page>
|
<x-filament-panels::page>
|
||||||
<div class="space-y-6 pb-12">
|
@if (!$isAdministrator)
|
||||||
{{-- Main Stats Grid --}}
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6 gap-4">
|
<div class="space-y-6 pb-12">
|
||||||
@foreach ($mainStats as $stat)
|
{{-- Main Stats Grid --}}
|
||||||
<div
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6 gap-4">
|
||||||
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-4 transition hover:shadow-md border-b-2">
|
@foreach ($mainStats as $stat)
|
||||||
<div class="flex flex-col gap-1">
|
<div
|
||||||
<span
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-4 transition hover:shadow-md border-b-2">
|
||||||
class="text-[10px] font-bold text-gray-400 dark:text-gray-500 uppercase tracking-wider">{{ $stat['label'] }}</span>
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex items-baseline gap-1">
|
<span
|
||||||
@if ($stat['prefix'])
|
class="text-[10px] font-bold text-gray-400 dark:text-gray-500 uppercase tracking-wider">{{ $stat['label'] }}</span>
|
||||||
<span
|
<div class="flex items-baseline gap-1">
|
||||||
class="text-xs font-semibold text-gray-400 dark:text-gray-500">{{ $stat['prefix'] }}</span>
|
@if ($stat['prefix'])
|
||||||
@endif
|
<span
|
||||||
<span class="text-xl font-bold text-gray-900 dark:text-white">{{ $stat['value'] }}</span>
|
class="text-xs font-semibold text-gray-400 dark:text-gray-500">{{ $stat['prefix'] }}</span>
|
||||||
|
@endif
|
||||||
|
<span class="text-xl font-bold text-gray-900 dark:text-white">{{ $stat['value'] }}</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="text-[9px] text-gray-900 dark:text-gray-600 uppercase">{{ $stat['desc'] }}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[9px] text-gray-900 dark:text-gray-600 uppercase">{{ $stat['desc'] }}</span>
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Distribution Row --}}
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
|
<div
|
||||||
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-6">
|
||||||
|
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300 mb-6 flex items-center gap-2">
|
||||||
|
<x-heroicon-o-arrows-right-left class="w-4 h-4 text-primary-500" />
|
||||||
|
Sumber Pemasukan
|
||||||
|
</h3>
|
||||||
|
<div class="h-64 flex flex-col items-center">
|
||||||
|
<canvas id="revenueSplitChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Distribution Row --}}
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
||||||
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-6">
|
|
||||||
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300 mb-6 flex items-center gap-2">
|
|
||||||
<x-heroicon-o-arrows-right-left class="w-4 h-4 text-primary-500" />
|
|
||||||
Sumber Pemasukan
|
|
||||||
</h3>
|
|
||||||
<div class="h-64 flex flex-col items-center">
|
|
||||||
<canvas id="revenueSplitChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-6">
|
|
||||||
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300 mb-6 flex items-center gap-2">
|
|
||||||
<x-heroicon-o-chart-pie class="w-4 h-4 text-primary-500" />
|
|
||||||
Alokasi Pengeluaran
|
|
||||||
</h3>
|
|
||||||
<div class="h-64 flex flex-col items-center">
|
|
||||||
<canvas id="expenseChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-6">
|
|
||||||
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300 mb-6 flex items-center gap-2">
|
|
||||||
<x-heroicon-o-shopping-bag class="w-4 h-4 text-primary-500" />
|
|
||||||
Penjualan per Satuan
|
|
||||||
</h3>
|
|
||||||
<div class="h-64 flex flex-col items-center">
|
|
||||||
<canvas id="salesUnitChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Units Breakdown --}}
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
||||||
{{-- Production --}}
|
|
||||||
<div
|
|
||||||
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm overflow-hidden">
|
|
||||||
<div
|
<div
|
||||||
class="px-5 py-3 border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50 flex items-center justify-between">
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-6">
|
||||||
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300">Produksi (Unit)</h3>
|
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300 mb-6 flex items-center gap-2">
|
||||||
<span class="text-[10px] font-bold text-gray-400 uppercase">Hari Ini</span>
|
<x-heroicon-o-chart-pie class="w-4 h-4 text-primary-500" />
|
||||||
|
Alokasi Pengeluaran
|
||||||
|
</h3>
|
||||||
|
<div class="h-64 flex flex-col items-center">
|
||||||
|
<canvas id="expenseChart"></canvas>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="divide-y divide-gray-100 dark:divide-gray-800">
|
<div
|
||||||
@forelse($totalEggsByUnit as $item)
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm p-6">
|
||||||
<div
|
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300 mb-6 flex items-center gap-2">
|
||||||
class="px-5 py-3 flex justify-between items-center transition hover:bg-gray-50 dark:hover:bg-gray-800/40">
|
<x-heroicon-o-shopping-bag class="w-4 h-4 text-primary-500" />
|
||||||
<span
|
Penjualan per Satuan
|
||||||
class="text-sm text-gray-600 dark:text-gray-400 font-medium">{{ $item['unit_name'] }}</span>
|
</h3>
|
||||||
<div class="flex gap-4">
|
<div class="h-64 flex flex-col items-center">
|
||||||
|
<canvas id="salesUnitChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Units Breakdown --}}
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
|
{{-- Production --}}
|
||||||
|
<div
|
||||||
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm overflow-hidden">
|
||||||
|
<div
|
||||||
|
class="px-5 py-3 border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50 flex items-center justify-between">
|
||||||
|
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300">Produksi (Unit)</h3>
|
||||||
|
<span class="text-[10px] font-bold text-gray-400 uppercase">Hari Ini</span>
|
||||||
|
</div>
|
||||||
|
<div class="divide-y divide-gray-100 dark:divide-gray-800">
|
||||||
|
@forelse($totalEggsByUnit as $item)
|
||||||
|
<div
|
||||||
|
class="px-5 py-3 flex justify-between items-center transition hover:bg-gray-50 dark:hover:bg-gray-800/40">
|
||||||
|
<span
|
||||||
|
class="text-sm text-gray-600 dark:text-gray-400 font-medium">{{ $item['unit_name'] }}</span>
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<div class="text-right">
|
||||||
|
<span class="text-[10px] text-gray-400 font-bold uppercase block">Bagus</span>
|
||||||
|
<span
|
||||||
|
class="text-sm font-bold text-emerald-600 dark:text-emerald-400">{{ $item['total_good'] }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-right border-l border-gray-100 dark:border-gray-800 pl-4">
|
||||||
|
<span class="text-[10px] text-gray-400 font-bold uppercase block">Pecah</span>
|
||||||
|
<span
|
||||||
|
class="text-sm font-bold text-rose-600 dark:text-rose-400">{{ $item['total_broken'] }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<div class="px-5 py-10 text-center text-gray-400 text-sm italic">Belum ada data produksi
|
||||||
|
</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Delayed --}}
|
||||||
|
<div
|
||||||
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm overflow-hidden">
|
||||||
|
<div
|
||||||
|
class="px-5 py-3 border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50 flex items-center justify-between">
|
||||||
|
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300">Tertunda (Unit)</h3>
|
||||||
|
<span class="text-[10px] font-bold text-gray-400 uppercase">Hari Ini</span>
|
||||||
|
</div>
|
||||||
|
<div class="divide-y divide-gray-100 dark:divide-gray-800">
|
||||||
|
@forelse($totalDelayedByUnit as $item)
|
||||||
|
<div
|
||||||
|
class="px-5 py-3 flex justify-between items-center transition hover:bg-gray-50 dark:hover:bg-gray-800/40">
|
||||||
|
<span
|
||||||
|
class="text-sm text-gray-600 dark:text-gray-400 font-medium">{{ $item['unit_name'] }}</span>
|
||||||
|
<span
|
||||||
|
class="text-sm font-bold text-gray-900 dark:text-white">{{ $item['total'] }}</span>
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<div class="px-5 py-10 text-center text-gray-400 text-sm italic">Tidak ada barang tertunda
|
||||||
|
hari
|
||||||
|
ini</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||||
|
|
||||||
|
{{-- Top Customers Today --}}
|
||||||
|
<div
|
||||||
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm overflow-hidden flex flex-col">
|
||||||
|
<div
|
||||||
|
class="px-5 py-3 border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50 flex items-center gap-2">
|
||||||
|
<x-heroicon-o-star class="w-4 h-4 text-amber-500" />
|
||||||
|
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300">Top Pelanggan Hari Ini</h3>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 divide-y divide-gray-100 dark:divide-gray-800">
|
||||||
|
@forelse ($topCustomers as $customer)
|
||||||
|
<div
|
||||||
|
class="px-5 py-4 flex items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-800/40 transition">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span
|
||||||
|
class="text-sm font-bold text-gray-800 dark:text-gray-200">{{ $customer->name }}</span>
|
||||||
|
<span
|
||||||
|
class="text-xs text-gray-400 tracking-tight">{{ $customer->phone_number ?? 'Telp tidak ada' }}</span>
|
||||||
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<span class="text-[10px] text-gray-400 font-bold uppercase block">Bagus</span>
|
|
||||||
<span
|
<span
|
||||||
class="text-sm font-bold text-emerald-600 dark:text-emerald-400">{{ $item['total_good'] }}</span>
|
class="text-[10px] font-semibold text-gray-400 uppercase block leading-none mb-1">Transaksi</span>
|
||||||
</div>
|
<span class="text-sm font-black text-primary-600">Rp
|
||||||
<div class="text-right border-l border-gray-100 dark:border-gray-800 pl-4">
|
{{ $formatNumber($customer->total_spent) }}</span>
|
||||||
<span class="text-[10px] text-gray-400 font-bold uppercase block">Pecah</span>
|
|
||||||
<span
|
|
||||||
class="text-sm font-bold text-rose-600 dark:text-rose-400">{{ $item['total_broken'] }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@empty
|
||||||
@empty
|
<div class="px-5 py-10 text-center text-gray-400 text-sm italic">Belum ada transaksi hari
|
||||||
<div class="px-5 py-10 text-center text-gray-400 text-sm italic">Belum ada data produksi</div>
|
ini
|
||||||
@endforelse
|
</div>
|
||||||
</div>
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Delayed --}}
|
|
||||||
<div
|
|
||||||
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm overflow-hidden">
|
|
||||||
<div
|
|
||||||
class="px-5 py-3 border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50 flex items-center justify-between">
|
|
||||||
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300">Tertunda (Unit)</h3>
|
|
||||||
<span class="text-[10px] font-bold text-gray-400 uppercase">Hari Ini</span>
|
|
||||||
</div>
|
|
||||||
<div class="divide-y divide-gray-100 dark:divide-gray-800">
|
|
||||||
@forelse($totalDelayedByUnit as $item)
|
|
||||||
<div
|
|
||||||
class="px-5 py-3 flex justify-between items-center transition hover:bg-gray-50 dark:hover:bg-gray-800/40">
|
|
||||||
<span
|
|
||||||
class="text-sm text-gray-600 dark:text-gray-400 font-medium">{{ $item['unit_name'] }}</span>
|
|
||||||
<span class="text-sm font-bold text-gray-900 dark:text-white">{{ $item['total'] }}</span>
|
|
||||||
</div>
|
|
||||||
@empty
|
|
||||||
<div class="px-5 py-10 text-center text-gray-400 text-sm italic">Tidak ada barang tertunda hari
|
|
||||||
ini</div>
|
|
||||||
@endforelse
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (!$isAdministrator)
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script>
|
||||||
{{-- Top Customers Today --}}
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
<div
|
const chartOptions = {
|
||||||
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm overflow-hidden flex flex-col">
|
responsive: true,
|
||||||
<div
|
maintainAspectRatio: false,
|
||||||
class="px-5 py-3 border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50 flex items-center gap-2">
|
plugins: {
|
||||||
<x-heroicon-o-star class="w-4 h-4 text-amber-500" />
|
legend: {
|
||||||
<h3 class="text-sm font-bold text-gray-700 dark:text-gray-300">Top Pelanggan Hari Ini</h3>
|
position: 'bottom',
|
||||||
</div>
|
labels: {
|
||||||
<div class="flex-1 divide-y divide-gray-100 dark:divide-gray-800">
|
boxWidth: 10,
|
||||||
@forelse ($topCustomers as $customer)
|
font: {
|
||||||
<div
|
size: 10
|
||||||
class="px-5 py-4 flex items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-800/40 transition">
|
}
|
||||||
<div class="flex flex-col">
|
|
||||||
<span
|
|
||||||
class="text-sm font-bold text-gray-800 dark:text-gray-200">{{ $customer->name }}</span>
|
|
||||||
<span
|
|
||||||
class="text-xs text-gray-400 tracking-tight">{{ $customer->phone_number ?? 'Telp tidak ada' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-right">
|
|
||||||
<span
|
|
||||||
class="text-[10px] font-semibold text-gray-400 uppercase block leading-none mb-1">Transaksi</span>
|
|
||||||
<span class="text-sm font-black text-primary-600">Rp
|
|
||||||
{{ $formatNumber($customer->total_spent) }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@empty
|
|
||||||
<div class="px-5 py-10 text-center text-gray-400 text-sm italic">Belum ada transaksi hari ini
|
|
||||||
</div>
|
|
||||||
@endforelse
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const chartOptions = {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
position: 'bottom',
|
|
||||||
labels: {
|
|
||||||
boxWidth: 10,
|
|
||||||
font: {
|
|
||||||
size: 10
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Revenue Split Chart
|
||||||
|
const revenueSplitCtx = document.getElementById('revenueSplitChart');
|
||||||
|
if (revenueSplitCtx) {
|
||||||
|
new Chart(revenueSplitCtx, {
|
||||||
|
type: 'doughnut',
|
||||||
|
data: {
|
||||||
|
labels: {!! json_encode($revenueSplit['labels']) !!},
|
||||||
|
datasets: [{
|
||||||
|
data: {!! json_encode($revenueSplit['data']) !!},
|
||||||
|
backgroundColor: ['#6366f1', '#94a3b8'],
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
...chartOptions,
|
||||||
|
cutout: '70%'
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Revenue Split Chart
|
// Expense Category Chart
|
||||||
new Chart(document.getElementById('revenueSplitChart'), {
|
const expenseCtx = document.getElementById('expenseChart');
|
||||||
type: 'doughnut',
|
if (expenseCtx) {
|
||||||
data: {
|
new Chart(expenseCtx, {
|
||||||
labels: {!! json_encode($revenueSplit['labels']) !!},
|
type: 'doughnut',
|
||||||
datasets: [{
|
data: {
|
||||||
data: {!! json_encode($revenueSplit['data']) !!},
|
labels: {!! json_encode($expenseDistribution['labels']) !!},
|
||||||
backgroundColor: ['#6366f1', '#94a3b8'],
|
datasets: [{
|
||||||
}]
|
data: {!! json_encode($expenseDistribution['data']) !!},
|
||||||
},
|
backgroundColor: ['#f59e0b', '#64748b'],
|
||||||
options: {
|
borderWidth: 0
|
||||||
...chartOptions,
|
}]
|
||||||
cutout: '70%'
|
},
|
||||||
|
options: {
|
||||||
|
...chartOptions,
|
||||||
|
cutout: '70%'
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Expense Category Chart
|
// Sales by Unit Chart
|
||||||
new Chart(document.getElementById('expenseChart'), {
|
const salesUnitCtx = document.getElementById('salesUnitChart');
|
||||||
type: 'doughnut',
|
if (salesUnitCtx) {
|
||||||
data: {
|
new Chart(salesUnitCtx, {
|
||||||
labels: {!! json_encode($expenseDistribution['labels']) !!},
|
type: 'pie',
|
||||||
datasets: [{
|
data: {
|
||||||
data: {!! json_encode($expenseDistribution['data']) !!},
|
labels: {!! json_encode($salesByUnit['labels']) !!},
|
||||||
backgroundColor: ['#f59e0b', '#64748b'],
|
datasets: [{
|
||||||
borderWidth: 0
|
data: {!! json_encode($salesByUnit['data']) !!},
|
||||||
}]
|
backgroundColor: ['#3b82f6', '#06b6d4', '#8b5cf6', '#ec4899'],
|
||||||
},
|
}]
|
||||||
options: {
|
},
|
||||||
...chartOptions,
|
options: chartOptions
|
||||||
cutout: '70%'
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Sales by Unit Chart
|
|
||||||
new Chart(document.getElementById('salesUnitChart'), {
|
|
||||||
type: 'pie',
|
|
||||||
data: {
|
|
||||||
labels: {!! json_encode($salesByUnit['labels']) !!},
|
|
||||||
datasets: [{
|
|
||||||
data: {!! json_encode($salesByUnit['data']) !!},
|
|
||||||
backgroundColor: ['#3b82f6', '#06b6d4', '#8b5cf6', '#ec4899'],
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: chartOptions
|
|
||||||
});
|
});
|
||||||
|
</script>
|
||||||
});
|
@endif
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@200;300;400;500;600;700;800&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@200;300;400;500;600;700;800&display=swap');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user