From 33ebebbe68d1a7f984bfad6de1f6f83cdd339576 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Tue, 11 Nov 2025 10:47:05 +0700 Subject: [PATCH] feat(overview): membuat counting data --- app/Livewire/Studio/Dashboard/Overview.php | 234 ++++++++++++++++++ .../studio/dashboard/overview.blade.php | 31 ++- 2 files changed, 264 insertions(+), 1 deletion(-) diff --git a/app/Livewire/Studio/Dashboard/Overview.php b/app/Livewire/Studio/Dashboard/Overview.php index 68e996b..4d96267 100644 --- a/app/Livewire/Studio/Dashboard/Overview.php +++ b/app/Livewire/Studio/Dashboard/Overview.php @@ -2,12 +2,246 @@ namespace App\Livewire\Studio\Dashboard; +use App\Models\Expense; +use App\Models\Order; +use App\Models\OrderItem; +use App\Models\Perfume; +use Illuminate\Support\Facades\DB; use Livewire\Attributes\Title; use Livewire\Component; #[Title('Ringkasan')] class Overview extends Component { + public array $outlets = []; + + public array $selectedOutletIds = []; + + public array $stats = []; + + public function mount() + { + $this->outlets = auth()->user()->outlets()->get()->pluck('name', 'id')->toArray(); + + $this->loadStats(); + } + + public function updatedSelectedOutletIds() + { + $this->loadStats(); + } + + protected function loadStats() + { + $outletIds = $this->selectedOutletIds; + + $todayOrder = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->today() + ->count(); + + $yesterdayOrder = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->yesterday() + ->count(); + + $todayIncome = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->paid() + ->today() + ->sum('total'); + + $yesterdayIncome = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->paid() + ->yesterday() + ->sum('total'); + + $todayCogs = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->paid() + ->today() + ->sum('cogs'); + + $yesterdayCogs = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->paid() + ->yesterday() + ->sum('cogs'); + + $todayDiscount = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->paid() + ->today() + ->sum('discount'); + + $yesterdayDiscount = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->paid() + ->yesterday() + ->sum('discount'); + + $todayVoucher = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->today() + ->whereNotNull('voucher_id') + ->count(); + + $yesterdayVoucher = Order::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->yesterday() + ->whereNotNull('voucher_id') + ->count(); + + $todayExpense = Expense::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->today() + ->sum('amount'); + + $yesterdayExpense = Expense::query() + ->when(! empty($outletIds), fn ($q) => $q->whereIn('outlet_id', $outletIds)) + ->yesterday() + ->sum('amount'); + + $todayGrossProfit = $todayIncome - $todayCogs - $todayDiscount; + $yesterdayGrossProfit = $yesterdayIncome - $yesterdayCogs - $yesterdayDiscount; + + $todayNetProfit = $todayGrossProfit - $todayExpense; + $yesterdayNetProfit = $yesterdayGrossProfit - $yesterdayExpense; + + $todaySoldPerfume = OrderItem::where('orderable_type', Perfume::class) + ->whereHas( + 'order', + fn ($q) => $q->today()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds)) + ) + ->sum('quantity'); + + $yesterdaySoldPerfume = OrderItem::where('orderable_type', Perfume::class) + ->whereHas( + 'order', + fn ($q) => $q->yesterday()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds)) + ) + ->sum('quantity'); + + $todayTopPerfume = OrderItem::where('orderable_type', Perfume::class) + ->whereHas( + 'order', + fn ($q) => $q->today()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds)) + ) + ->select('orderable_id', 'orderable_type', DB::raw('SUM(quantity) as total_sold')) + ->groupBy('orderable_id', 'orderable_type') + ->orderByDesc('total_sold') + ->with('orderable') + ->first(); + + $yesterdayTopPerfume = OrderItem::where('orderable_type', Perfume::class) + ->whereHas( + 'order', + fn ($q) => $q->yesterday()->when(! empty($outletIds), fn ($q2) => $q2->whereIn('outlet_id', $outletIds)) + ) + ->select('orderable_id', 'orderable_type', DB::raw('SUM(quantity) as total_sold')) + ->groupBy('orderable_id', 'orderable_type') + ->orderByDesc('total_sold') + ->with('orderable') + ->first(); + + $this->stats = [ + [ + 'title' => 'Total Order', + 'value' => $todayOrder, + 'previous' => $yesterdayOrder, + 'trend' => $yesterdayOrder > 0 + ? round((($todayOrder - $yesterdayOrder) / $yesterdayOrder) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayOrder > $yesterdayOrder, + ], + [ + 'title' => 'Pendapatan', + 'value' => currency($todayIncome, 'Rp'), + 'previous' => currency($yesterdayIncome, 'Rp'), + 'trend' => $yesterdayIncome > 0 + ? round((($todayIncome - $yesterdayIncome) / $yesterdayIncome) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayIncome > $yesterdayIncome, + 'formatted' => currency($todayIncome, 'Rp'), + ], + [ + 'title' => 'HPP', + 'value' => currency($todayCogs, 'Rp'), + 'previous' => currency($yesterdayCogs, 'Rp'), + 'trend' => $yesterdayCogs > 0 + ? round((($todayCogs - $yesterdayCogs) / $yesterdayCogs) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayCogs > $yesterdayCogs, + 'formatted' => currency($todayCogs, 'Rp'), + ], + [ + 'title' => 'Diskon', + 'value' => currency($todayDiscount, 'Rp'), + 'previous' => currency($yesterdayDiscount, 'Rp'), + 'trend' => $yesterdayDiscount > 0 + ? round((($todayDiscount - $yesterdayDiscount) / $yesterdayDiscount) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayDiscount > $yesterdayDiscount, + 'formatted' => currency($todayDiscount, 'Rp'), + ], + [ + 'title' => 'Voucher Terpakai', + 'value' => $todayVoucher, + 'previous' => $yesterdayVoucher, + 'trend' => $yesterdayVoucher > 0 + ? round((($todayVoucher - $yesterdayVoucher) / $yesterdayVoucher) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayVoucher > $yesterdayVoucher, + ], + [ + 'title' => 'Pengeluaran', + 'value' => currency($todayExpense, 'Rp'), + 'previous' => currency($yesterdayExpense, 'Rp'), + 'trend' => $yesterdayExpense > 0 + ? round((($todayExpense - $yesterdayExpense) / $yesterdayExpense) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayExpense > $yesterdayExpense, + ], + [ + 'title' => 'Laba Kotor', + 'value' => currency($todayGrossProfit, 'Rp'), + 'previous' => currency($yesterdayGrossProfit, 'Rp'), + 'trend' => $yesterdayGrossProfit > 0 + ? round((($todayGrossProfit - $yesterdayGrossProfit) / $yesterdayGrossProfit) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayGrossProfit > $yesterdayGrossProfit, + ], + [ + 'title' => 'Laba Bersih', + 'value' => currency($todayNetProfit, 'Rp'), + 'previous' => currency($yesterdayNetProfit, 'Rp'), + 'trend' => $yesterdayNetProfit > 0 + ? round((($todayNetProfit - $yesterdayNetProfit) / $yesterdayNetProfit) * 100, 1).'%' + : '∞%', + 'trendUp' => $todayNetProfit > $yesterdayNetProfit, + ], + [ + 'title' => 'Parfum Terjual', + 'value' => $todaySoldPerfume.' ml', + 'previous' => $yesterdaySoldPerfume.' ml', + 'trend' => $yesterdaySoldPerfume > 0 + ? round((($todaySoldPerfume - $yesterdaySoldPerfume) / $yesterdaySoldPerfume) * 100, 1).'%' + : '∞%', + 'trendUp' => $todaySoldPerfume > $yesterdaySoldPerfume, + ], + [ + 'title' => 'Top Parfum', + 'value' => optional($todayTopPerfume?->orderable)->name.' ('.$todayTopPerfume?->total_sold.'ml)' ?? '-', + 'previous' => optional($yesterdayTopPerfume?->orderable)->name.'('.$yesterdayTopPerfume?->total_sold.'ml)' ?? '-', + 'trend' => ($yesterdayTopPerfume && $yesterdayTopPerfume->total_sold > 0) + ? round((($todayTopPerfume?->total_sold - $yesterdayTopPerfume?->total_sold) / $yesterdayTopPerfume?->total_sold) * 100, 1).'%' + : '∞%', + 'trendUp' => ($todayTopPerfume?->total_sold ?? 0) > ($yesterdayTopPerfume?->total_sold ?? 0), + ], + ]; + } + public function render() { return view('livewire.studio.dashboard.overview'); diff --git a/resources/views/livewire/studio/dashboard/overview.blade.php b/resources/views/livewire/studio/dashboard/overview.blade.php index deb88eb..4dd7de1 100644 --- a/resources/views/livewire/studio/dashboard/overview.blade.php +++ b/resources/views/livewire/studio/dashboard/overview.blade.php @@ -1,5 +1,34 @@ Haloo, {{ auth()->user()?->employee?->full_name }} Selamat datang di Studio Yadi Parfum. - + + +
+
+ + @foreach ($outlets as $key => $value) + + @endforeach + +
+ Data yang ditampilkan di bawah ini adalah data hari ini dan hari kemarin. +
+ @foreach ($stats as $stat) +
+ {{ $stat['title'] }} +
+ {{ $stat['value'] }} + {{ $stat['previous'] }} +
+
+ + {{ $stat['trend'] }} +
+
+ @endforeach +
+