diff --git a/app/Actions/GetAdminStatsAction.php b/app/Actions/GetAdminStatsAction.php
new file mode 100644
index 0000000..2ed2eac
--- /dev/null
+++ b/app/Actions/GetAdminStatsAction.php
@@ -0,0 +1,22 @@
+
+ */
+ public function execute(): array
+ {
+ return [
+ 'listings' => Deal::count(),
+ 'customers' => User::where('role', UserTypes::User->value)->count(),
+ 'brokers' => User::where('role', UserTypes::Broker->value)->count(),
+ ];
+ }
+}
diff --git a/app/Http/Controllers/Admin/AdminDashboardController.php b/app/Http/Controllers/Admin/AdminDashboardController.php
new file mode 100644
index 0000000..c63b822
--- /dev/null
+++ b/app/Http/Controllers/Admin/AdminDashboardController.php
@@ -0,0 +1,15 @@
+with('stats', $action->execute());
+ }
+}
diff --git a/app/Models/Admin.php b/app/Models/Admin.php
new file mode 100644
index 0000000..eb7e9ce
--- /dev/null
+++ b/app/Models/Admin.php
@@ -0,0 +1,14 @@
+morphOne(User::class, 'role');
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
index cffb2cd..ec470ea 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -57,6 +57,16 @@ public function isBroker(): bool
return $this->type instanceof Broker;
}
+ public function isAdmin(): bool
+ {
+ return $this->type instanceof Admin;
+ }
+
+ public function isCustomer(): bool
+ {
+ return $this->type instanceof Customer;
+ }
+
public function deals(): HasMany
{
return $this->hasMany(Deal::class);
@@ -80,11 +90,6 @@ public function recentSearches(): HasMany
return $this->hasMany(RecentSearch::class);
}
- public function isCustomer(): bool
- {
- return $this->type instanceof Customer;
- }
-
public function dealsInteractions(): HasManyThrough
{
return $this->hasManyThrough(Interaction::class, Deal::class);
diff --git a/database/migrations/2026_01_27_083425_create_admins_table.php b/database/migrations/2026_01_27_083425_create_admins_table.php
new file mode 100644
index 0000000..6e11a6b
--- /dev/null
+++ b/database/migrations/2026_01_27_083425_create_admins_table.php
@@ -0,0 +1,21 @@
+id();
+ $table->timestamps();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('admins');
+ }
+};
diff --git a/database/seeders/AdminUserSeeder.php b/database/seeders/AdminUserSeeder.php
new file mode 100644
index 0000000..88299a4
--- /dev/null
+++ b/database/seeders/AdminUserSeeder.php
@@ -0,0 +1,25 @@
+ 'Admin',
+ 'email' => 'admin@dealhub.com',
+ 'password' => 'password',
+ 'status' => UserStatus::Active->value,
+ 'role' => UserTypes::Admin->value,
+ ];
+
+ $admin = Admin::firstOrCreate();
+ $admin->user()->updateOrCreate($data);
+ }
+}
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index 6b901f8..34ce8a3 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -2,7 +2,6 @@
namespace Database\Seeders;
-use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
@@ -13,13 +12,5 @@ class DatabaseSeeder extends Seeder
/**
* Seed the application's database.
*/
- public function run(): void
- {
- // User::factory(10)->create();
-
- User::factory()->create([
- 'name' => 'Test User',
- 'email' => 'test@example.com',
- ]);
- }
+ public function run(): void {}
}
diff --git a/resources/views/components/dashboard/admin/layout.blade.php b/resources/views/components/dashboard/admin/layout.blade.php
new file mode 100644
index 0000000..aec4ba1
--- /dev/null
+++ b/resources/views/components/dashboard/admin/layout.blade.php
@@ -0,0 +1,26 @@
+@props(['title' => ''])
+
+
+
+
+
+ {{$heading ?? ''}}
+
+ @session('success')
+
+ {{$value}}
+
+ @endsession
+
+ @session('error')
+
+ {{$value}}
+
+ @endsession
+
+ {{$slot}}
+
+
+
diff --git a/resources/views/components/dashboard/admin/navbar.blade.php b/resources/views/components/dashboard/admin/navbar.blade.php
new file mode 100644
index 0000000..af0de54
--- /dev/null
+++ b/resources/views/components/dashboard/admin/navbar.blade.php
@@ -0,0 +1,45 @@
+
+
+
+
diff --git a/resources/views/components/dashboard/admin/sidebar.blade.php b/resources/views/components/dashboard/admin/sidebar.blade.php
new file mode 100644
index 0000000..04618af
--- /dev/null
+++ b/resources/views/components/dashboard/admin/sidebar.blade.php
@@ -0,0 +1,70 @@
+@props(['activeClass' => 'bg-gray-100 text-gray-900'])
+
+
+@vite(['resources/js/sidebar.js'])
+
+
diff --git a/resources/views/components/dashboard/admin/stats.blade.php b/resources/views/components/dashboard/admin/stats.blade.php
new file mode 100644
index 0000000..d3a4978
--- /dev/null
+++ b/resources/views/components/dashboard/admin/stats.blade.php
@@ -0,0 +1,20 @@
+@props(['stats' => []])
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/views/components/dashboard/broker/sidebar/item.blade.php b/resources/views/components/dashboard/broker/sidebar/item.blade.php
index 54aff92..931a2c9 100644
--- a/resources/views/components/dashboard/broker/sidebar/item.blade.php
+++ b/resources/views/components/dashboard/broker/sidebar/item.blade.php
@@ -1,5 +1,10 @@
-@props([ 'link' => ''])
+@props([ 'link' => '', 'active' => false])
+@php
+ if (!$active){
+ $active = url()->current() === $link;
+ }
+@endphp
@aware(['activeClass' => 'bg-gray-100 text-gray-900'])
-class(["flex space-x-3 items-center pl-3 py-3 rounded-xl hover:bg-gray-100 border border-transparent ease-in-out transition-all duration-300 active:scale-80 hover:border-gray-300", $activeClass => url()->current() == $link])}} >
+class(["flex space-x-3 items-center pl-3 py-3 rounded-xl hover:bg-gray-100 border border-transparent ease-in-out transition-all duration-300 active:scale-80 hover:border-gray-300", $activeClass => $active])}} >
{{$slot}}
diff --git a/resources/views/components/dashboard/broker/stats.blade.php b/resources/views/components/dashboard/broker/stats.blade.php
index 9272c6a..be752aa 100644
--- a/resources/views/components/dashboard/broker/stats.blade.php
+++ b/resources/views/components/dashboard/broker/stats.blade.php
@@ -1,6 +1,6 @@
@props(['stats' => []])
-
+
diff --git a/resources/views/components/dashboard/stats-card.blade.php b/resources/views/components/dashboard/stats-card.blade.php
index 548fc04..b51c038 100644
--- a/resources/views/components/dashboard/stats-card.blade.php
+++ b/resources/views/components/dashboard/stats-card.blade.php
@@ -1,12 +1,14 @@
@props(['title' => '', 'score' => ''])
-
+
-
- {{$slot}}
+
+
{{$score}}
+
+ {{$slot}}
+
diff --git a/resources/views/dashboards/admin/customers/index.blade.php b/resources/views/dashboards/admin/customers/index.blade.php
new file mode 100644
index 0000000..bba7e8e
--- /dev/null
+++ b/resources/views/dashboards/admin/customers/index.blade.php
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+ Customer details
+
+
+ Name |
+ Email |
+ Location |
+
+
+ @forelse($customers as $customer)
+
+ {{$customer->user->name}} |
+ {{$customer->user->email}} |
+ {{$customer->location}} |
+
+
+
+
+
+
+
+
+
+ @empty
+
+ No Deals found |
+
+ @endforelse
+
+
+
+
diff --git a/resources/views/dashboards/admin/index.blade.php b/resources/views/dashboards/admin/index.blade.php
index 9302370..5c1418e 100644
--- a/resources/views/dashboards/admin/index.blade.php
+++ b/resources/views/dashboards/admin/index.blade.php
@@ -1,3 +1,6 @@
-
-
-
+
+
+
+
+
+
diff --git a/routes/web.php b/routes/web.php
index 9c22ff1..5322ea5 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -1,26 +1,18 @@
name('home');
Route::get('/explore', ExplorePageController::class)->name('explore');
-Route::middleware('auth')->group(function () {
-
- Route::view('/admin/dashboard', 'dashboards.admin.index')
- ->middleware(HasRole::class.':'.UserTypes::Admin->value)
- ->name('admin.dashboard');
-});
-
/**
* This routes are accessed by JS XHR requests, and is loaded here cause
* we do not want to use sanctum for web requests
diff --git a/routes/web/admin.php b/routes/web/admin.php
new file mode 100644
index 0000000..3163f3a
--- /dev/null
+++ b/routes/web/admin.php
@@ -0,0 +1,14 @@
+name('admin.')
+ ->middleware([HasRole::class.':'.UserTypes::Admin->value, 'auth'])
+ ->group(function () {
+ Route::get('dashboard', AdminDashboardController::class)->name('dashboard');
+ Route::resource('customers', CustomerController::class)->except('show', 'create', 'store');
+ });