feat(overview): custom halaman ringkasan,menambahkan scope model Customer,Expense dan Transaction,menambahkan image dan custom css
This commit is contained in:
parent
5c5e402552
commit
5f8b09f9d1
@ -3,13 +3,63 @@
|
||||
namespace App\Http\Controllers\Admin\Dashboard;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Barbershop;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Transaction;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class OverviewController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$todayIncome = Transaction::query()->barbershop()->whereDate('created_at', now()->today())->sum('total');
|
||||
$yesterdayIncome = Transaction::query()->barbershop()->whereDate('created_at', now()->yesterday())->sum('total');
|
||||
|
||||
$todayShaving = Transaction::query()->barbershop()->today()->count();
|
||||
$yesterdayShaving = Transaction::query()->barbershop()->yesterday()->count();
|
||||
|
||||
$todayExpense = Expense::query()->barbershop()->today()->sum('amount');
|
||||
$yesterdayExpense = Expense::query()->barbershop()->yesterday()->sum('amount');
|
||||
|
||||
$todayNewCustomer = Transaction::with('customer')->whereDoesntHave('customer.transactions', function ($query) {
|
||||
$query->where('id', '<>', DB::raw('transactions.id'));
|
||||
})
|
||||
->barbershop()
|
||||
->today()
|
||||
->distinct('customer_id')
|
||||
->count('customer_id');
|
||||
|
||||
$yesterdayNewCustomer = Transaction::with('customer')->whereDoesntHave('customer.transactions', function ($query) {
|
||||
$query->where('id', '<>', DB::raw('transactions.id'));
|
||||
})
|
||||
->barbershop()
|
||||
->yesterday()
|
||||
->distinct('customer_id')
|
||||
->count('customer_id');
|
||||
|
||||
$topCustomersByTotal = Transaction::groupBy('customer_id')
|
||||
->select(
|
||||
'customer_id',
|
||||
DB::raw('SUM(total) as total_transaction'),
|
||||
DB::raw('COUNT(*) as transaction_count')
|
||||
)
|
||||
->orderBy('total_transaction', 'desc')
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
return view('pages.admin.dashboard.overview', [
|
||||
'pageTitle' => 'Ringkasan',
|
||||
'todayIncome' => $todayIncome,
|
||||
'diffIncome' => $todayIncome - $yesterdayIncome,
|
||||
'todayShaving' => $todayShaving,
|
||||
'diffShaving' => $todayShaving - $yesterdayShaving,
|
||||
'todayExpense' => $todayExpense,
|
||||
'diffExpense' => $todayExpense - $yesterdayExpense,
|
||||
'todayNewCustomer' => $todayNewCustomer,
|
||||
'diffNewCustomer' => $todayNewCustomer - $yesterdayNewCustomer,
|
||||
'cash' => Barbershop::findOrFail(Auth::user()->barbershop_id)->cash,
|
||||
'topCustomersByTotal' => $topCustomersByTotal,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,10 +2,13 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class Customer extends Model
|
||||
{
|
||||
@ -18,6 +21,11 @@ class Customer extends Model
|
||||
'contact_number',
|
||||
];
|
||||
|
||||
public function scopeBarbershop(Builder $query): Builder
|
||||
{
|
||||
return $query->where('barbershop_id', Auth::user()->barbershop_id);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
@ -27,4 +35,9 @@ public function barbershop(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Barbershop::class);
|
||||
}
|
||||
|
||||
public function transactions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Transaction::class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,15 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Observers\ExpenseObserver;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
#[ObservedBy([ExpenseObserver::class])]
|
||||
class Expense extends Model
|
||||
@ -23,6 +26,21 @@ class Expense extends Model
|
||||
'use_cash',
|
||||
];
|
||||
|
||||
public function scopeBarbershop(Builder $query): Builder
|
||||
{
|
||||
return $query->where('barbershop_id', Auth::user()->barbershop_id);
|
||||
}
|
||||
|
||||
public function scopeToday(Builder $query): Builder
|
||||
{
|
||||
return $query->whereDate('created_at', Carbon::today());
|
||||
}
|
||||
|
||||
public function scopeYesterday(Builder $query): Builder
|
||||
{
|
||||
return $query->whereDate('created_at', Carbon::yesterday());
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
||||
@ -2,11 +2,14 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class Transaction extends Model
|
||||
{
|
||||
@ -23,6 +26,21 @@ class Transaction extends Model
|
||||
'payment_method',
|
||||
];
|
||||
|
||||
public function scopeBarbershop(Builder $query): Builder
|
||||
{
|
||||
return $query->where('barbershop_id', Auth::user()->barbershop_id);
|
||||
}
|
||||
|
||||
public function scopeToday(Builder $query): Builder
|
||||
{
|
||||
return $query->whereDate('created_at', Carbon::today());
|
||||
}
|
||||
|
||||
public function scopeYesterday(Builder $query): Builder
|
||||
{
|
||||
return $query->whereDate('created_at', Carbon::yesterday());
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
||||
@ -18644,7 +18644,7 @@ .widget-decor {
|
||||
}
|
||||
|
||||
.balance-widget {
|
||||
background-image: url(../images/dashboard-2/balance-bg.png);
|
||||
background-image: url(../images/balance-bg.png);
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
|
||||
BIN
public/assets/admin/images/balance-bg.png
Normal file
BIN
public/assets/admin/images/balance-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
public/assets/admin/images/mobile.png
Normal file
BIN
public/assets/admin/images/mobile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@ -2,49 +2,136 @@
|
||||
@section('styles')
|
||||
@endsection
|
||||
@section('app')
|
||||
<div class="container-fluid" onload="startTime()">
|
||||
<div class="row widget-grid">
|
||||
<div class="col-xxl-4 col-sm-6 box-col-6">
|
||||
<div class="card profile-box">
|
||||
<div class="card-body">
|
||||
<div class="media media-wrapper justify-content-between">
|
||||
<div class="media-body">
|
||||
<div class="greeting-user">
|
||||
<h4 class="f-w-600">Selamat Datang</h4>
|
||||
<p style="max-width: 70%">Inilah yang terjadi di akun Anda hari ini</p>
|
||||
<div class="whatsnew-btn"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row size-column">
|
||||
<div class="col-xxl-10 col-md-12 box-col-8 grid-ed-12">
|
||||
<div class="row">
|
||||
<div class="col-xxl-5 col-md-7 box-col-7">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="card o-hidden">
|
||||
<div class="card-body balance-widget">
|
||||
<span class="f-w-500 f-light">Kas</span>
|
||||
<h4 class="mb-3 mt-1 f-w-500 mb-0 f-22">
|
||||
<span class="counter">{{ formatToRupiah($cash) }}</span>
|
||||
</h4>
|
||||
<a class="purchase-btn btn btn-primary btn-hover-effect f-w-500"
|
||||
href="{{ route('finance.cashes') }}">Tambah Kas</a>
|
||||
<div class="mobile-right-img">
|
||||
<img class="mobile-img" src="{{ asset('assets/admin/images/mobile.png') }}"
|
||||
alt="mobile with coin">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="clockbox">
|
||||
<svg id="clock" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
|
||||
<g id="face">
|
||||
<circle class="circle" cx="300" cy="300" r="253.9"></circle>
|
||||
<path class="hour-marks"
|
||||
d="M300.5 94V61M506 300.5h32M300.5 506v33M94 300.5H60M411.3 107.8l7.9-13.8M493 190.2l13-7.4M492.1 411.4l16.5 9.5M411 492.3l8.9 15.3M189 492.3l-9.2 15.9M107.7 411L93 419.5M107.5 189.3l-17.1-9.9M188.1 108.2l-9-15.6">
|
||||
</path>
|
||||
<circle class="mid-circle" cx="300" cy="300" r="16.2"></circle>
|
||||
</g>
|
||||
<g id="hour">
|
||||
<path class="hour-hand" d="M300.5 298V142"></path>
|
||||
<circle class="sizing-box" cx="300" cy="300" r="253.9"></circle>
|
||||
</g>
|
||||
<g id="minute">
|
||||
<path class="minute-hand" d="M300.5 298V67"> </path>
|
||||
<circle class="sizing-box" cx="300" cy="300" r="253.9"></circle>
|
||||
</g>
|
||||
<g id="second">
|
||||
<path class="second-hand" d="M300.5 350V55"></path>
|
||||
<circle class="sizing-box" cx="300" cy="300" r="253.9"> </circle>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="col-6">
|
||||
<div class="card small-widget">
|
||||
<div class="card-body primary">
|
||||
<span class="f-light">Pendapatan</span>
|
||||
<div class="d-flex align-items-end gap-1">
|
||||
<h4>{{ formatToRupiah($todayIncome) }}</h4>
|
||||
<span class="font-primary f-12 f-w-500">
|
||||
<i class="icon-arrow-up"></i>
|
||||
<span>
|
||||
{{ formatToRupiah($diffIncome) > 0 ? '+' : '' }}{{ formatToRupiah($diffIncome) }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="bg-gradient">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="card small-widget">
|
||||
<div class="card-body secondary">
|
||||
<span class="f-light">Cukur</span>
|
||||
<div class="d-flex align-items-end gap-1">
|
||||
<h4>{{ $todayShaving }}</h4>
|
||||
<span class="font-secondary f-12 f-w-500">
|
||||
<i class="icon-arrow-up"></i>
|
||||
<span> {{ $diffShaving > 0 ? '+' : '' }}{{ $diffShaving }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="bg-gradient">
|
||||
<svg class="stroke-icon svg-fill">
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="card small-widget">
|
||||
<div class="card-body secondary">
|
||||
<span class="f-light">Pengeluaran</span>
|
||||
<div class="d-flex align-items-end gap-1">
|
||||
<h4>{{ formatToRupiah($todayExpense) }}</h4>
|
||||
<span class="font-secondary f-12 f-w-500">
|
||||
<i class="icon-arrow-up"></i>
|
||||
<span>
|
||||
{{ formatToRupiah($diffExpense) > 0 ? '+' : '' }}{{ formatToRupiah($diffExpense) }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="bg-gradient">
|
||||
<svg class="stroke-icon svg-fill">
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="card small-widget">
|
||||
<div class="card-body success">
|
||||
<span class="f-light">Pelanggan Baru</span>
|
||||
<div class="d-flex align-items-end gap-1">
|
||||
<h4>{{ $todayNewCustomer }}</h4>
|
||||
<span class="font-success f-12 f-w-500">
|
||||
<i class="icon-arrow-up"></i>
|
||||
<span>
|
||||
{{ $diffNewCustomer > 0 ? '+' : '' }}{{ $diffNewCustomer }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="bg-gradient">
|
||||
<svg class="stroke-icon svg-fill">
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="badge f-10 p-0" id="txt"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cartoon">
|
||||
<img class="img-fluid" src="{{ asset('assets/admin/images/barber.png') }}" style="width: 60%"
|
||||
alt="barber">
|
||||
</div>
|
||||
<div class="col-xxl-7 col-md-5 col-sm-6 box-col-5">
|
||||
<div class="appointment">
|
||||
<div class="card">
|
||||
<div class="card-header card-no-border">
|
||||
<div class="header-top">
|
||||
<h5 class="m-0">Top Pelanggan</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
<div class="table-responsive custom-scrollbar">
|
||||
<table class="table table-dashed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nama</th>
|
||||
<th>Kontak</th>
|
||||
<th>Jumlah Transaksi</th>
|
||||
<th>Total Transakski</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($topCustomersByTotal as $item)
|
||||
<tr>
|
||||
<td>{{ $item->customer->name ?? '--deleted--' }}</td>
|
||||
<td>{{ $item->customer->contact_number ?? '-' }}</td>
|
||||
<td>{{ $item->transaction_count }}</td>
|
||||
<td>{{ formatToRupiah($item->total_transaction) }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -52,6 +139,5 @@
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@section('beforeScripts')
|
||||
<script src="{{ asset('assets/admin/js/clock.js?ver=1.0.0') }}"></script>
|
||||
@section('afterScript')
|
||||
@endsection
|
||||
|
||||
Loading…
Reference in New Issue
Block a user