add DashboardService for statistics calculation and update beranda view with stat cards

This commit is contained in:
LailaWulandarii 2026-01-22 17:17:16 +07:00
parent 7acaf897c2
commit 50cf6ace25
2 changed files with 88 additions and 113 deletions

View File

@ -0,0 +1,53 @@
<?php
namespace App\Services;
use App\Models\{TransaksiBuket, BookingFoto};
use Carbon\Carbon;
class DashboardService
{
public static function getStats()
{
$now = Carbon::now();
$prev = Carbon::now()->subMonth();
$curr = self::calculate($now);
$past = self::calculate($prev);
return [
'pendapatan' => $curr['income'],
'pendapatan_grow' => self::growth($curr['income'], $past['income']),
'masuk_count' => $curr['total'],
'masuk_grow' => self::growth($curr['total'], $past['total']),
'selesai_count' => $curr['done'],
'selesai_grow' => self::growth($curr['done'], $past['done']),
'batal_count' => $curr['cancel'],
'batal_grow' => self::growth($curr['cancel'], $past['cancel']),
];
}
private static function calculate($date)
{
$m = $date->month;
$y = $date->year;
// Gabungan query Buket & Foto
return [
'income' => TransaksiBuket::whereMonth('created_at', $m)->whereYear('created_at', $y)->where('status_transaksi', 'diterima')->sum('total_bayar') +
BookingFoto::whereMonth('created_at', $m)->whereYear('created_at', $y)->where('status_booking', 'diterima')->sum('total_bayar'),
'total' => TransaksiBuket::whereMonth('created_at', $m)->whereYear('created_at', $y)->count() +
BookingFoto::whereMonth('created_at', $m)->whereYear('created_at', $y)->count(),
'done' => TransaksiBuket::whereMonth('created_at', $m)->whereYear('created_at', $y)->where('status_transaksi', 'selesai')->count() +
BookingFoto::whereMonth('created_at', $m)->whereYear('created_at', $y)->where('status_booking', 'selesai')->count(),
'cancel' => TransaksiBuket::whereMonth('created_at', $m)->whereYear('created_at', $y)->where('status_transaksi', 'ditolak')->count() +
BookingFoto::whereMonth('created_at', $m)->whereYear('created_at', $y)->where('status_booking', 'ditolak')->count(),
];
}
private static function growth($current, $previous)
{
if ($previous <= 0) return $current > 0 ? 100 : 0;
return round((($current - $previous) / $previous) * 100, 1);
}
}

View File

@ -20,116 +20,40 @@
@endif @endif
<section class="row gy-3"> <section class="row gy-3">
<div class="col-12"> <div class="col-12">
<div class="row gx-3">
@if (Auth::user()->role === 'pemilik') @if (Auth::user()->role === 'pemilik')
<div class="col-6 col-lg-3 col-md-6"> <div class="row">
<div class="card mb-0"> @include('admin.components._stat_card', [
<div class="card-body px-3 py-4"> 'label' => 'Pendapatan',
<div class="stat-header"> 'icon' => 'bi-bank',
<h6 class="stat-label">Pendapatan Bulan Ini</h6> 'value' => 'Rp ' . number_format($stat['pendapatan'], 0, ',', '.'),
<i class="bi bi-info-circle menu-dots" data-bs-toggle="tooltip" data-bs-placement="top" 'grow' => $stat['pendapatan_grow'],
title="Total pendapatan dari pesanan buket dan foto dalam bulan ini"></i> 'tooltip' => 'Total pendapatan dari pesanan buket dan foto bulan ini',
</div> ])
<div class="stat-body"> @include('admin.components._stat_card', [
<div class="stat-icon"> 'label' => 'Pesanan Masuk',
<i class="bi bi-bank"></i> 'icon' => 'bi-cart-fill',
</div> 'value' => $stat['masuk_count'] . ' Pesanan',
<div> 'grow' => $stat['masuk_grow'],
<h6 class="stat-count">Rp {{ number_format($stat['pendapatan'], 0, ',', '.') }}</h6> 'tooltip' => 'Total pesanan buket dan foto yang masuk bulan ini',
<span ])
class="stat-percent {{ $stat['pendapatan_grow'] >= 0 ? 'text-success' : 'text-danger' }} fw-bold"> @include('admin.components._stat_card', [
<i 'label' => 'Pesanan Selesai',
class="bi {{ $stat['pendapatan_grow'] >= 0 ? 'bi-arrow-up' : 'bi-arrow-down' }}"></i> 'icon' => 'bi-cart-check-fill',
{{ abs($stat['pendapatan_grow']) }}% 'value' => $stat['selesai_count'] . ' Pesanan',
</span> 'grow' => $stat['selesai_grow'],
<small class="stat-month">dari bulan lalu</small> 'tooltip' => 'Total pesanan buket dan foto yang selesai bulan ini',
</div> ])
</div> @include('admin.components._stat_card', [
</div> 'label' => 'Pesanan Ditolak',
</div> 'icon' => 'bi-cart-x-fill',
</div> 'value' => $stat['batal_count'] . ' Pesanan',
'grow' => $stat['batal_grow'],
<div class="col-6 col-lg-3 col-md-6"> 'tooltip' => 'Total pesanan buket dan foto yang ditolak bulan ini',
<div class="card mb-0"> 'is_negative_metric' => true,
<div class="card-body px-3 py-4"> ])
<div class="stat-header">
<h6 class="stat-label">Total Pesanan Masuk</h6>
<i class="bi bi-info-circle menu-dots" data-bs-toggle="tooltip" data-bs-placement="top"
title="Total pesanan buket dan foto yang masuk dalam bulan ini"></i>
</div>
<div class="stat-body">
<div class="stat-icon">
<i class="bi bi-cart-fill"></i>
</div>
<div>
<h6 class="stat-count">{{ $stat['masuk_count'] }} Pesanan</h6>
<span
class="stat-percent {{ $stat['masuk_grow'] >= 0 ? 'text-success' : 'text-danger' }} fw-bold">
<i
class="bi {{ $stat['masuk_grow'] >= 0 ? 'bi-arrow-up' : 'bi-arrow-down' }}"></i>
{{ abs($stat['masuk_grow']) }}%
</span>
<small class="stat-month">dari bulan lalu</small>
</div>
</div>
</div>
</div>
</div>
<div class="col-6 col-lg-3 col-md-6">
<div class="card mb-0">
<div class="card-body px-3 py-4">
<div class="stat-header">
<h6 class="stat-label">Pesanan Selesai</h6>
<i class="bi bi-info-circle menu-dots" data-bs-toggle="tooltip" data-bs-placement="top"
title="Total pesanan buket dan foto yang selesai dalam bulan ini"></i>
</div>
<div class="stat-body">
<div class="stat-icon">
<i class="bi bi-cart-check-fill"></i>
</div>
<div>
<h6 class="stat-count">{{ $stat['selesai_count'] }} Pesanan</h6>
<span
class="stat-percent {{ $stat['selesai_grow'] >= 0 ? 'text-success' : 'text-danger' }} fw-bold">
<i
class="bi {{ $stat['selesai_grow'] >= 0 ? 'bi-arrow-up' : 'bi-arrow-down' }}"></i>{{ abs($stat['selesai_grow']) }}%
</span>
<small class="stat-month">dari bulan lalu</small>
</div>
</div>
</div>
</div>
</div>
<div class="col-6 col-lg-3 col-md-6">
<div class="card mb-0">
<div class="card-body px-3 py-4">
<div class="stat-header">
<h6 class="stat-label">Pesanan Ditolak</h6>
<i class="bi bi-info-circle menu-dots" data-bs-toggle="tooltip" data-bs-placement="top"
title="Total pesanan buket dan foto yang ditolak dalam bulan ini"></i>
</div>
<div class="stat-body">
<div class="stat-icon">
<i class="bi bi-cart-x-fill"></i>
</div>
<div>
<h6 class="stat-count">{{ $stat['batal_count'] }} Pesanan</h6>
<span
class="stat-percent {{ $stat['batal_grow'] <= 0 ? 'text-success' : 'text-danger' }} fw-bold">
<i
class="bi {{ $stat['batal_grow'] >= 0 ? 'bi-arrow-up' : 'bi-arrow-down' }}"></i>
{{ abs($stat['batal_grow']) }}%
</span>
<small class="stat-month">dari bulan lalu</small>
</div>
</div>
</div>
</div>
</div> </div>
@endif @endif
</div> </div>
</div>
<div class="col-12"> <div class="col-12">
<div class="row gx-3"> <div class="row gx-3">
<div class="col-12 col-xl-6"> <div class="col-12 col-xl-6">
@ -201,8 +125,7 @@ class="bi {{ $stat['batal_grow'] >= 0 ? 'bi-arrow-up' : 'bi-arrow-down' }}"></i>
<td>{{ $p->paketFoto->nama }}</td> <td>{{ $p->paketFoto->nama }}</td>
<td class="col-auto"> <td class="col-auto">
<a href="#" class="btn icon btn-primary btn-action" <a href="#" class="btn icon btn-primary btn-action"
data-bs-toggle="modal" data-bs-toggle="modal" data-bs-target="#foto{{ $p->id_booking }}">
data-bs-target="#foto{{ $p->id_booking }}">
<i class="bi bi-eye"></i> <i class="bi bi-eye"></i>
</a> </a>
</td> </td>
@ -229,8 +152,7 @@ class="bi {{ $stat['batal_grow'] >= 0 ? 'bi-arrow-up' : 'bi-arrow-down' }}"></i>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="nav nav-pills nav-fill mb-4" id="v-pills-tab" role="tablist" <div class="nav nav-pills nav-fill mb-4" id="v-pills-tab" role="tablist" aria-orientation="horizontal">
aria-orientation="horizontal">
<a class="nav-link active" id="v-pills-home-tab" data-bs-toggle="pill" href="#v-pills-home" <a class="nav-link active" id="v-pills-home-tab" data-bs-toggle="pill" href="#v-pills-home"
role="tab" aria-controls="v-pills-home" aria-selected="true"> role="tab" aria-controls="v-pills-home" aria-selected="true">
Buket Buket