feature(admin-panel): add admin dashboard
This commit is contained in:
parent
4fd98957cb
commit
91a11c8f56
22
app/Actions/GetAdminStatsAction.php
Normal file
22
app/Actions/GetAdminStatsAction.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions;
|
||||||
|
|
||||||
|
use App\Enums\UserTypes;
|
||||||
|
use App\Models\Deal;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
final readonly class GetAdminStatsAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, int>
|
||||||
|
*/
|
||||||
|
public function execute(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'listings' => Deal::count(),
|
||||||
|
'customers' => User::where('role', UserTypes::User->value)->count(),
|
||||||
|
'brokers' => User::where('role', UserTypes::Broker->value)->count(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
15
app/Http/Controllers/Admin/AdminDashboardController.php
Normal file
15
app/Http/Controllers/Admin/AdminDashboardController.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Actions\GetAdminStatsAction;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class AdminDashboardController extends Controller
|
||||||
|
{
|
||||||
|
public function __invoke(GetAdminStatsAction $action)
|
||||||
|
{
|
||||||
|
return view('dashboards.admin.index')
|
||||||
|
->with('stats', $action->execute());
|
||||||
|
}
|
||||||
|
}
|
||||||
14
app/Models/Admin.php
Normal file
14
app/Models/Admin.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||||
|
|
||||||
|
class Admin extends Model
|
||||||
|
{
|
||||||
|
public function user(): MorphOne
|
||||||
|
{
|
||||||
|
return $this->morphOne(User::class, 'role');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -57,6 +57,16 @@ public function isBroker(): bool
|
|||||||
return $this->type instanceof Broker;
|
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
|
public function deals(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Deal::class);
|
return $this->hasMany(Deal::class);
|
||||||
@ -80,11 +90,6 @@ public function recentSearches(): HasMany
|
|||||||
return $this->hasMany(RecentSearch::class);
|
return $this->hasMany(RecentSearch::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isCustomer(): bool
|
|
||||||
{
|
|
||||||
return $this->type instanceof Customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dealsInteractions(): HasManyThrough
|
public function dealsInteractions(): HasManyThrough
|
||||||
{
|
{
|
||||||
return $this->hasManyThrough(Interaction::class, Deal::class);
|
return $this->hasManyThrough(Interaction::class, Deal::class);
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('admins', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('admins');
|
||||||
|
}
|
||||||
|
};
|
||||||
25
database/seeders/AdminUserSeeder.php
Normal file
25
database/seeders/AdminUserSeeder.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Enums\UserStatus;
|
||||||
|
use App\Enums\UserTypes;
|
||||||
|
use App\Models\Admin;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class AdminUserSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'name' => 'Admin',
|
||||||
|
'email' => 'admin@dealhub.com',
|
||||||
|
'password' => 'password',
|
||||||
|
'status' => UserStatus::Active->value,
|
||||||
|
'role' => UserTypes::Admin->value,
|
||||||
|
];
|
||||||
|
|
||||||
|
$admin = Admin::firstOrCreate();
|
||||||
|
$admin->user()->updateOrCreate($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
@ -13,13 +12,5 @@ class DatabaseSeeder extends Seeder
|
|||||||
/**
|
/**
|
||||||
* Seed the application's database.
|
* Seed the application's database.
|
||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void {}
|
||||||
{
|
|
||||||
// User::factory(10)->create();
|
|
||||||
|
|
||||||
User::factory()->create([
|
|
||||||
'name' => 'Test User',
|
|
||||||
'email' => 'test@example.com',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
26
resources/views/components/dashboard/admin/layout.blade.php
Normal file
26
resources/views/components/dashboard/admin/layout.blade.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@props(['title' => ''])
|
||||||
|
<x-layout :title="$title">
|
||||||
|
<div class="flex h-screen overflow-x-hidden">
|
||||||
|
<x-dashboard.admin.sidebar class="hidden shrink-0 md:block md:h-screen"
|
||||||
|
active-class="bg-linear-120 from-[#1a55ed] to-[#9b1cff] text-white"/>
|
||||||
|
<section
|
||||||
|
class=" flex flex-col space-y-4 md:space-y-8 bg-[#F9FAFB] overflow-y-auto overflow-x-hidden h-screen w-full">
|
||||||
|
|
||||||
|
{{$heading ?? ''}}
|
||||||
|
|
||||||
|
@session('success')
|
||||||
|
<div class="wrapper">
|
||||||
|
<x-ui.alert variant="success">{{$value}}</x-ui.alert>
|
||||||
|
</div>
|
||||||
|
@endsession
|
||||||
|
|
||||||
|
@session('error')
|
||||||
|
<div class="wrapper">
|
||||||
|
<x-ui.alert variant="error">{{$value}}</x-ui.alert>
|
||||||
|
</div>
|
||||||
|
@endsession
|
||||||
|
|
||||||
|
{{$slot}}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</x-layout>
|
||||||
45
resources/views/components/dashboard/admin/navbar.blade.php
Normal file
45
resources/views/components/dashboard/admin/navbar.blade.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<nav class="flex justify-between items-center wrapper py-6 shadow">
|
||||||
|
<div class="logo flex space-x-2 items-center">
|
||||||
|
<x-logo class="md:hidden" />
|
||||||
|
<div class="">
|
||||||
|
<a href="" class="font-bold text-2xl">Dashboard</a>
|
||||||
|
<p class="text-sm text-accent-600">Manage Users, Brokers and Reports</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- mobile menu btn-->
|
||||||
|
<x-ui.button class="md:hidden" id="openBtn">
|
||||||
|
<x-heroicon-o-bars-3 class="w-8 0"/>
|
||||||
|
</x-ui.button>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- mobile menu btn-->
|
||||||
|
<div id='mobileMenu' class="fixed top-0 left-0 z-100 h-screen w-full translate-x-full bg-gray-200 p-10 text-xl transition-transform duration-500 ease-in-out overflow-y-auto">
|
||||||
|
<div class="flex justify-between mb-8">
|
||||||
|
<x-logo/>
|
||||||
|
<x-ui.button id="closeBtn">
|
||||||
|
<x-heroicon-o-x-mark class="w-8 ml-auto"/>
|
||||||
|
</x-ui.button>
|
||||||
|
</div>
|
||||||
|
<div class="nav-links mb-10">
|
||||||
|
<ul class="flex flex-col space-y-8 text-accent-600">
|
||||||
|
<a href="{{route('broker.profile.show', auth()->user())}}" class="ui-btn flex border space-x-3 border-gray-200 items-center">
|
||||||
|
<x-heroicon-o-user class="w-6"/>
|
||||||
|
<p>Profile</p>
|
||||||
|
</a>
|
||||||
|
<a href="{{route('broker.deals.create')}}" class="ui-btn ui-btn-neutral flex border space-x-3 items-center">
|
||||||
|
<x-heroicon-o-plus class="w-6"/>
|
||||||
|
<p>Create Deal</p>
|
||||||
|
</a>
|
||||||
|
<form method="post" action="{{route('logout')}}">
|
||||||
|
@csrf
|
||||||
|
@method('delete')
|
||||||
|
<x-ui.button class="flex space-x-3">
|
||||||
|
<x-heroicon-o-arrow-right-start-on-rectangle class="w-6"/>
|
||||||
|
<p>Logout</p>
|
||||||
|
</x-ui.button>
|
||||||
|
</form>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
70
resources/views/components/dashboard/admin/sidebar.blade.php
Normal file
70
resources/views/components/dashboard/admin/sidebar.blade.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
@props(['activeClass' => 'bg-gray-100 text-gray-900'])
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="sidebarWrapper" {{$attributes->merge([ 'class' => 'border-r border-r-gray-300 transition-all duration-300 ease-in-out w-64 relative'])}}>
|
||||||
|
<div class="hidden md:flex h-screen items-center">
|
||||||
|
<div id="sidebar"
|
||||||
|
class="flex flex-col p-4 pt-6 justify-between font-medium h-full w-full overflow-hidden transition-all duration-300 ease-in-out">
|
||||||
|
<div class="">
|
||||||
|
<div class="flex space-x-4 border-b border-b-gray-300 pb-6">
|
||||||
|
<x-logo/>
|
||||||
|
<a href="{{route('home')}}" class="whitespace-nowrap">
|
||||||
|
<p class="text-2xl font-bold">DealHub</p>
|
||||||
|
<p class="text-accent-600 text-sm">Admin Panel</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pt-6 flex flex-col space-y-3 whitespace-nowrap">
|
||||||
|
<x-dashboard.broker.sidebar.item :link="route('admin.dashboard')">
|
||||||
|
<x-heroicon-o-squares-2x2 class="min-w-5 w-5"/>
|
||||||
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out ">Dashboard</p>
|
||||||
|
</x-dashboard.broker.sidebar.item>
|
||||||
|
|
||||||
|
<x-dashboard.broker.sidebar.item :active="\Illuminate\Support\Facades\Route::is('admin.customers.*')" :link="route('admin.customers.index')">
|
||||||
|
<x-heroicon-o-users class="min-w-5 w-5"/>
|
||||||
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out ">Manage Customers</p>
|
||||||
|
</x-dashboard.broker.sidebar.item>
|
||||||
|
|
||||||
|
<x-dashboard.broker.sidebar.item :link="route('broker.deals.index')">
|
||||||
|
<svg class="w-5 min-w-5" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#000000" stroke="#000000" stroke-width="0.2"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M512.536516 506.562145l-112.606908 197.063113 112.606908 225.21484 112.607932-225.21484z" fill="#000000"></path><path d="M680.856096 476.172205c36.824036-40.482378 59.488761-94.060249 59.488761-152.967444 0-125.613323-102.193994-227.807318-227.807317-227.807318s-227.807318 102.193994-227.807318 227.807318c0 58.906171 22.664726 112.485066 59.488761 152.967444-58.595933 32.817572-187.285008 138.139536-187.285008 430.442414 0 12.273313 9.951141 22.225479 22.225479 22.225479 12.273313 0 22.225479-9.951141 22.225479-22.225479 0-304.35708 145.515606-384.465868 178.379253-398.671253 37.433247 26.981426 83.210136 43.069736 132.773354 43.069737 49.564241 0 95.342154-16.08831 132.775401-43.070761 32.907674 14.226887 178.376182 94.379701 178.376182 398.673301 0 12.273313 9.951141 22.225479 22.225479 22.225479s22.225479-9.951141 22.225478-22.225479c-0.001024-292.303902-128.690099-397.625866-187.283984-430.443438zM329.179132 323.204761c0-101.098437 82.258947-183.357384 183.357384-183.357384s183.357384 82.258947 183.357384 183.357384-82.258947 183.357384-183.357384 183.357384-183.357384-82.258947-183.357384-183.357384z" fill="#020b07"></path></g></svg>
|
||||||
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Manage Brokers</p>
|
||||||
|
</x-dashboard.broker.sidebar.item>
|
||||||
|
|
||||||
|
<x-dashboard.broker.sidebar.item :link="route('broker.deals.index')">
|
||||||
|
<x-heroicon-o-document-text class="w-5 min-w-5"/>
|
||||||
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Manage Reports</p>
|
||||||
|
</x-dashboard.broker.sidebar.item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<x-dashboard.broker.sidebar.item :link="route('broker.profile.show', auth()->user()->id)">
|
||||||
|
<x-heroicon-o-user class="w-5 min-w-5"/>
|
||||||
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Profile</p>
|
||||||
|
</x-dashboard.broker.sidebar.item>
|
||||||
|
|
||||||
|
<form method="post" action="{{route('logout')}}">
|
||||||
|
@csrf
|
||||||
|
@method('delete')
|
||||||
|
<button
|
||||||
|
class="py-3 pl-3 border border-white hover:bg-red-50 hover:border-red-200 rounded-xl w-full mt-4 transition-all">
|
||||||
|
<div class="flex space-x-3 items-center text-red-500">
|
||||||
|
<x-heroicon-o-arrow-right-start-on-rectangle class="w-5 min-w-5"/>
|
||||||
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Logout</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Toggle Button --}}
|
||||||
|
<div
|
||||||
|
class="text-gray-500 cursor-pointer hover:text-gray-900 rounded-full p-1.5 bg-white border border-gray-300 absolute -right-3.5 top-21">
|
||||||
|
<x-heroicon-c-chevron-left id="closeSidebarBtn" class="w-4"/>
|
||||||
|
<x-heroicon-c-chevron-right id="openSidebarBtn" class="w-4 hidden"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@vite(['resources/js/sidebar.js'])
|
||||||
|
|
||||||
|
|
||||||
20
resources/views/components/dashboard/admin/stats.blade.php
Normal file
20
resources/views/components/dashboard/admin/stats.blade.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
@props(['stats' => []])
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 wrapper gap-y-4 gap-x-8">
|
||||||
|
<x-dashboard.stats-card title="Total Listings" :score="$stats['listings'] ?? 0">
|
||||||
|
<x-icon-square variant="blue">
|
||||||
|
<x-heroicon-o-document-text class=" w-6 lg:w-8" />
|
||||||
|
</x-icon-square>
|
||||||
|
</x-dashboard.stats-card>
|
||||||
|
|
||||||
|
<x-dashboard.stats-card title="Total Customers" :score="$stats['customers'] ?? 0">
|
||||||
|
<x-icon-square variant="purple">
|
||||||
|
<x-heroicon-o-users class=" w-6 lg:w-8" />
|
||||||
|
</x-icon-square>
|
||||||
|
</x-dashboard.stats-card>
|
||||||
|
<x-dashboard.stats-card title="Total Brokers" :score="$stats['brokers'] ?? 0">
|
||||||
|
<x-icon-square variant="pink">
|
||||||
|
<svg class="w-5 lg:w-8 fill-pink-700 stroke-pink-700" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" ><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M512.536516 506.562145l-112.606908 197.063113 112.606908 225.21484 112.607932-225.21484z" ></path><path d="M680.856096 476.172205c36.824036-40.482378 59.488761-94.060249 59.488761-152.967444 0-125.613323-102.193994-227.807318-227.807317-227.807318s-227.807318 102.193994-227.807318 227.807318c0 58.906171 22.664726 112.485066 59.488761 152.967444-58.595933 32.817572-187.285008 138.139536-187.285008 430.442414 0 12.273313 9.951141 22.225479 22.225479 22.225479 12.273313 0 22.225479-9.951141 22.225479-22.225479 0-304.35708 145.515606-384.465868 178.379253-398.671253 37.433247 26.981426 83.210136 43.069736 132.773354 43.069737 49.564241 0 95.342154-16.08831 132.775401-43.070761 32.907674 14.226887 178.376182 94.379701 178.376182 398.673301 0 12.273313 9.951141 22.225479 22.225479 22.225479s22.225479-9.951141 22.225478-22.225479c-0.001024-292.303902-128.690099-397.625866-187.283984-430.443438zM329.179132 323.204761c0-101.098437 82.258947-183.357384 183.357384-183.357384s183.357384 82.258947 183.357384 183.357384-82.258947 183.357384-183.357384 183.357384-183.357384-82.258947-183.357384-183.357384z"></path></g></svg>
|
||||||
|
|
||||||
|
</x-icon-square>
|
||||||
|
</x-dashboard.stats-card>
|
||||||
|
</div>
|
||||||
@ -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'])
|
@aware(['activeClass' => 'bg-gray-100 text-gray-900'])
|
||||||
<a href="{{$link}}" {{$attributes->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])}} >
|
<a href="{{$link}}" {{$attributes->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}}
|
{{$slot}}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
@props(['stats' => []])
|
@props(['stats' => []])
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 wrapper gap-y-4 gap-x-8">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 wrapper gap-y-4 gap-x-8">
|
||||||
<x-dashboard.stats-card title="My Listings" :score="$stats['listings']">
|
<x-dashboard.stats-card title="My Listings" :score="$stats['listings'] ?? 0">
|
||||||
<x-icon-square variant="blue">
|
<x-icon-square variant="blue">
|
||||||
<x-heroicon-o-document-text class="w-8" />
|
<x-heroicon-o-document-text class="w-8" />
|
||||||
</x-icon-square>
|
</x-icon-square>
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
@props(['title' => '', 'score' => ''])
|
@props(['title' => '', 'score' => ''])
|
||||||
<x-dashboard.card>
|
<x-dashboard.card>
|
||||||
<article class="flex justify-between">
|
<article class="h-full flex flex-col">
|
||||||
<div class="">
|
<div class="">
|
||||||
<h3 class="mb-2 text-sm text-accent-600">{{$title}}</h3>
|
<h3 class="mb-2 text-sm text-accent-600">{{$title}}</h3>
|
||||||
<p class="text-4xl font-bold">{{$score}}</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<p class="text-4xl font-bold">{{$score}}</p>
|
||||||
<div class="">
|
<div class="">
|
||||||
{{$slot}}
|
{{$slot}}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</x-dashboard.card>
|
</x-dashboard.card>
|
||||||
|
|||||||
48
resources/views/dashboards/admin/customers/index.blade.php
Normal file
48
resources/views/dashboards/admin/customers/index.blade.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<x-dashboard.admin.layout title="Customers">
|
||||||
|
<x-slot:heading>
|
||||||
|
<x-dashboard.page-heading
|
||||||
|
title="Manage Customers"
|
||||||
|
description="Edit, Delete and Login as Customer"
|
||||||
|
/>
|
||||||
|
</x-slot:heading>
|
||||||
|
<div class="flex items-center justify-center px-4 pb-4 pt-0 md:px-8 md:pb-8">
|
||||||
|
<x-dashboard.card class="w-full">
|
||||||
|
|
||||||
|
<h3 class="text-md font-bold mb-4">Customer details</h3>
|
||||||
|
<x-ui.table>
|
||||||
|
<x-ui.table.head>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Location</th>
|
||||||
|
</x-ui.table.head>
|
||||||
|
|
||||||
|
@forelse($customers as $customer)
|
||||||
|
<x-ui.table.row>
|
||||||
|
<td class="text-sm px-4 text-center">{{$customer->user->name}}</td>
|
||||||
|
<td class="text-sm px-4 text-center">{{$customer->user->email}}</td>
|
||||||
|
<td class="text-sm px-4 text-center">{{$customer->location}}</td>
|
||||||
|
<x-slot:actions>
|
||||||
|
<div class="flex items-center justify-center space-x-5 py-1 px-2">
|
||||||
|
<x-ui.button-sm :link="route('admin.customers.edit', $customer)" variant="ghost">
|
||||||
|
<x-heroicon-o-pencil-square class="w-4"/>
|
||||||
|
</x-ui.button-sm>
|
||||||
|
<form action="{{route('admin.customers.destroy', $customer)}}"
|
||||||
|
onsubmit="return confirm('Are you sure to delete this ?')" method="post"
|
||||||
|
class=" h-full items-center flex justify-center">
|
||||||
|
@csrf
|
||||||
|
<x-ui.button-sm variant="red">
|
||||||
|
<x-heroicon-o-trash class="w-4"/>
|
||||||
|
</x-ui.button-sm>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</x-slot:actions>
|
||||||
|
</x-ui.table.row>
|
||||||
|
@empty
|
||||||
|
<x-ui.table.row>
|
||||||
|
<td colspan="2" class="text-center text-sm text-accent-600 py-2">No Deals found</td>
|
||||||
|
</x-ui.table.row>
|
||||||
|
@endforelse
|
||||||
|
</x-ui.table>
|
||||||
|
</x-dashboard.card>
|
||||||
|
</div>
|
||||||
|
</x-dashboard.admin.layout>
|
||||||
@ -1,3 +1,6 @@
|
|||||||
<x-layout title="Admin Dashboard">
|
<x-dashboard.admin.layout title="Admin Dashboard">
|
||||||
|
<x-slot:heading>
|
||||||
</x-layout>
|
<x-dashboard.admin.navbar/>
|
||||||
|
</x-slot:heading>
|
||||||
|
<x-dashboard.admin.stats :stats="$stats" />
|
||||||
|
</x-dashboard.admin.layout>
|
||||||
|
|||||||
@ -1,26 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Enums\UserTypes;
|
|
||||||
use App\Http\Controllers\ExplorePageController;
|
use App\Http\Controllers\ExplorePageController;
|
||||||
use App\Http\Controllers\HomeController;
|
use App\Http\Controllers\HomeController;
|
||||||
use App\Http\Middleware\HasRole;
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
require __DIR__.'/web/auth.php';
|
require __DIR__.'/web/auth.php';
|
||||||
require __DIR__.'/web/broker.php';
|
require __DIR__.'/web/broker.php';
|
||||||
require __DIR__.'/web/interaction.php';
|
require __DIR__.'/web/interaction.php';
|
||||||
require __DIR__.'/web/customer.php';
|
require __DIR__.'/web/customer.php';
|
||||||
|
require __DIR__.'/web/admin.php';
|
||||||
|
|
||||||
Route::get('/', HomeController::class)->name('home');
|
Route::get('/', HomeController::class)->name('home');
|
||||||
Route::get('/explore', ExplorePageController::class)->name('explore');
|
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
|
* This routes are accessed by JS XHR requests, and is loaded here cause
|
||||||
* we do not want to use sanctum for web requests
|
* we do not want to use sanctum for web requests
|
||||||
|
|||||||
14
routes/web/admin.php
Normal file
14
routes/web/admin.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\UserTypes;
|
||||||
|
use App\Http\Controllers\Admin\AdminDashboardController;
|
||||||
|
use App\Http\Controllers\Admin\CustomerController;
|
||||||
|
use App\Http\Middleware\HasRole;
|
||||||
|
|
||||||
|
Route::prefix('/admin')
|
||||||
|
->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');
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user