Skip to content

Commit 517acfa

Browse files
committed
feat: implement admin dashboard with statistics cards
- Add AdminService with methods to fetch dashboard metrics - Design Dashboard.vue with statistics cards for orders, revenue, items, and customers
1 parent 7402f00 commit 517acfa

3 files changed

Lines changed: 163 additions & 11 deletions

File tree

app/Http/Controllers/Admin/AdminController.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,38 @@
33
namespace App\Http\Controllers\Admin;
44

55
use App\Http\Controllers\Controller;
6+
use App\Services\Admin\AdminService;
67
use Illuminate\Http\Request;
78
use Inertia\Inertia;
89

910
class AdminController extends Controller
1011
{
12+
/**
13+
* Inject AdminService
14+
*
15+
* @param AdminService $adminService
16+
*/
17+
public function __construct(
18+
protected AdminService $adminService
19+
) {}
20+
21+
/**
22+
* Display the admin dashboard
23+
*
24+
* @return \Inertia\Response
25+
*/
1126
public function dashboard()
1227
{
13-
return Inertia::render('admin/Dashboard');
28+
$countOrders = $this->adminService->countOrders();
29+
$getTotalRevenue = $this->adminService->getTotalRevenue();
30+
$countItems = $this->adminService->countItems();
31+
$countCustomers = $this->adminService->countCustomers();
32+
33+
return Inertia::render('admin/Dashboard', [
34+
'countOrders' => $countOrders,
35+
'getTotalRevenue' => $getTotalRevenue,
36+
'countItems' => $countItems,
37+
'countCustomers' => $countCustomers,
38+
]);
1439
}
1540
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace App\Services\Admin;
4+
5+
use App\Enums\UserRole;
6+
use App\Models\User;
7+
use App\Repositories\Interfaces\BillingRepositoryInterface;
8+
use App\Repositories\Interfaces\DeliveryRepositoryInterface;
9+
use App\Repositories\Interfaces\ItemRepositoryInterface;
10+
use App\Repositories\Interfaces\OrderRepositoryInterface;
11+
12+
class AdminService
13+
{
14+
/**
15+
* Inject repositories
16+
*
17+
* @param OrderRepositoryInterface $orderRepo
18+
* @param BillingRepositoryInterface $billingRepo
19+
* @param ItemRepositoryInterface $itemRepo
20+
* @param DeliveryRepositoryInterface $deliveryRepo
21+
*/
22+
public function __construct(
23+
protected OrderRepositoryInterface $orderRepo,
24+
protected BillingRepositoryInterface $billingRepo,
25+
protected ItemRepositoryInterface $itemRepo,
26+
protected DeliveryRepositoryInterface $deliveryRepo,
27+
) {}
28+
29+
/**
30+
* Get total count of orders
31+
*
32+
* @return int
33+
*/
34+
public function countOrders(): int
35+
{
36+
return $this->orderRepo->query()->count();
37+
}
38+
39+
/**
40+
* Get total revenue of billings
41+
*
42+
* @return float
43+
*/
44+
public function getTotalRevenue(): float
45+
{
46+
return $this->billingRepo->query()->sum('amount');
47+
}
48+
49+
/**
50+
* Get total count of items
51+
*
52+
* @return int
53+
*/
54+
public function countItems(): int
55+
{
56+
return $this->itemRepo->query()->count();
57+
}
58+
59+
/**
60+
* Get total count of customers
61+
*
62+
* @return int
63+
*/
64+
public function countCustomers(): int
65+
{
66+
return User::where('role', UserRole::Customer)->count();
67+
}
68+
}

resources/js/pages/admin/Dashboard.vue

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ import { dashboard } from '@/routes/admin';
44
import { type BreadcrumbItem } from '@/types';
55
import { Head } from '@inertiajs/vue3';
66
import PlaceholderPattern from '@/components/PlaceholderPattern.vue';
7+
import { useFormatters } from '@/composables/useFormatters';
8+
import { Package, PhilippinePeso, ShoppingCart, Users } from 'lucide-vue-next';
9+
10+
interface Props {
11+
countOrders: number;
12+
getTotalRevenue: number;
13+
countItems: number;
14+
countCustomers: number;
15+
}
16+
17+
const props = defineProps<Props>();
18+
const { formatCurrency } = useFormatters();
719
820
const breadcrumbs: BreadcrumbItem[] = [
921
{
@@ -19,18 +31,65 @@ const breadcrumbs: BreadcrumbItem[] = [
1931

2032
<AppLayout :breadcrumbs="breadcrumbs">
2133
<div class="flex h-full flex-1 flex-col gap-4 overflow-x-auto rounded-xl p-4">
22-
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
23-
<div
24-
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border">
25-
<PlaceholderPattern />
34+
<div class="flex justify-between items-center mb-4">
35+
<div>
36+
<h1 class="text-2xl font-bold">Dashboard</h1>
37+
<p class="text-sm text-muted-foreground">Welcome back <span
38+
class="text-[#815331] font-bold">@Admin</span>!</p>
2639
</div>
27-
<div
28-
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border">
29-
<PlaceholderPattern />
40+
</div>
41+
42+
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
43+
<!-- Total Orders Card -->
44+
<div class="bg-white border rounded-lg p-6">
45+
<div class="flex items-center justify-between">
46+
<div>
47+
<p class="text-sm text-muted-foreground">Total Orders</p>
48+
<p class="text-2xl font-bold mt-1">{{ countOrders }}</p>
49+
</div>
50+
<div class="p-3 bg-blue-50 rounded-lg">
51+
<ShoppingCart class="w-6 h-6 text-blue-600" />
52+
</div>
53+
</div>
3054
</div>
31-
<div
32-
class="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border">
33-
<PlaceholderPattern />
55+
56+
<!-- Total Revenue Card -->
57+
<div class="bg-white border rounded-lg p-6">
58+
<div class="flex items-center justify-between">
59+
<div>
60+
<p class="text-sm text-muted-foreground">Total Revenue</p>
61+
<p class="text-2xl font-bold mt-1">{{ formatCurrency(getTotalRevenue) }}</p>
62+
</div>
63+
<div class="p-3 bg-green-50 rounded-lg">
64+
<PhilippinePeso class="w-6 h-6 text-green-600" />
65+
</div>
66+
</div>
67+
</div>
68+
69+
<!-- Total Items Card -->
70+
<div class="bg-white border rounded-lg p-6">
71+
<div class="flex items-center justify-between">
72+
<div>
73+
<p class="text-sm text-muted-foreground">Total Items</p>
74+
<p class="text-2xl font-bold mt-1">{{ countItems }}</p>
75+
</div>
76+
<div class="p-3 bg-purple-50 rounded-lg">
77+
<Package class="w-6 h-6 text-purple-600" />
78+
</div>
79+
</div>
80+
</div>
81+
82+
<!-- Total Customers Card -->
83+
<div class="bg-white border rounded-lg p-6">
84+
<div class="flex items-center justify-between">
85+
<div>
86+
<p class="text-sm text-muted-foreground">Total Customers</p>
87+
<p class="text-2xl font-bold mt-1">{{ countCustomers }}</p>
88+
</div>
89+
<div class="p-3 bg-orange-50 rounded-lg">
90+
<Users class="w-6 h-6 text-orange-600" />
91+
</div>
92+
</div>
3493
</div>
3594
</div>
3695
<div

0 commit comments

Comments
 (0)