Merge branch 'feature/admin-panel'
This commit is contained in:
commit
a8be44553e
49
app/Http/Controllers/Admin/DealController.php
Normal file
49
app/Http/Controllers/Admin/DealController.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Deal;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class DealController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('dashboards.admin.deals.index')
|
||||||
|
->with('deals', $this->deals());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve(Deal $deal)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
\DB::transaction(function () use ($deal) {
|
||||||
|
$deal->active = true;
|
||||||
|
$deal->save();
|
||||||
|
});
|
||||||
|
|
||||||
|
return back()->with('success', 'Deal activated successfully.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Deal activation Failed: ', [$e->getMessage(), $e->getTrace()]);
|
||||||
|
|
||||||
|
return back()->with('error', 'Something went wrong.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject(Deal $deal){
|
||||||
|
try {
|
||||||
|
$deal->delete();
|
||||||
|
|
||||||
|
return back()->with('success', 'Deal deleted successfully.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Deal deletion Failed: ', [$e->getMessage(), $e->getTrace()]);
|
||||||
|
|
||||||
|
return back()->with('error', 'Something went wrong.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deals()
|
||||||
|
{
|
||||||
|
return Deal::where('active', false)->get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,6 +31,7 @@ public function __invoke(
|
|||||||
|
|
||||||
protected function deals(FormRequest $request, Builder $query, AddRecentSearchAction $action): LengthAwarePaginator
|
protected function deals(FormRequest $request, Builder $query, AddRecentSearchAction $action): LengthAwarePaginator
|
||||||
{
|
{
|
||||||
|
$query->tap(fn ($q) => (new Deal)->withActiveDeals($q));
|
||||||
// Add a search query
|
// Add a search query
|
||||||
if ($request->has('search') && $request->get('search') !== null) {
|
if ($request->has('search') && $request->get('search') !== null) {
|
||||||
$query->tap(fn ($q) => (new Deal)->search($q, $request->search));
|
$query->tap(fn ($q) => (new Deal)->search($q, $request->search));
|
||||||
|
|||||||
@ -25,8 +25,7 @@ public function builder(): Builder
|
|||||||
->with('type');
|
->with('type');
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
// Select only admin-approved deals
|
|
||||||
->tap(fn ($q) => (new Deal)->withActiveDeals($q))
|
|
||||||
// Check if the current user interacted with the deal
|
// Check if the current user interacted with the deal
|
||||||
->tap(fn ($q) => (new Deal)->withCurrentUserInteractions($q))
|
->tap(fn ($q) => (new Deal)->withCurrentUserInteractions($q))
|
||||||
->tap(fn ($q) => (new Deal)->withLikePerDeal($q))
|
->tap(fn ($q) => (new Deal)->withLikePerDeal($q))
|
||||||
|
|||||||
12
resources/js/admin-deals.js
Normal file
12
resources/js/admin-deals.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import {showDealModal} from "./deal-view-modal.js";
|
||||||
|
|
||||||
|
const table = document.querySelector('.ui-table')
|
||||||
|
if (table) {
|
||||||
|
const btns = table.querySelectorAll('.view-deal-btn');
|
||||||
|
btns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', async () => {
|
||||||
|
let dealId = btn.dataset.dealId;
|
||||||
|
await showDealModal(dealId)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -37,6 +37,11 @@ class="flex flex-col p-4 pt-6 justify-between font-medium h-full w-full overflow
|
|||||||
<x-heroicon-o-exclamation-triangle class="w-5 min-w-5"/>
|
<x-heroicon-o-exclamation-triangle class="w-5 min-w-5"/>
|
||||||
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Manage Reports</p>
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Manage Reports</p>
|
||||||
</x-dashboard.broker.sidebar.item>
|
</x-dashboard.broker.sidebar.item>
|
||||||
|
|
||||||
|
<x-dashboard.broker.sidebar.item :link="route('admin.deals.index')">
|
||||||
|
<x-heroicon-o-fire class="w-5 min-w-5"/>
|
||||||
|
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Manage Deals</p>
|
||||||
|
</x-dashboard.broker.sidebar.item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,78 +1,53 @@
|
|||||||
@php use App\Enums\ReportStatus; @endphp
|
@php use App\Enums\ReportStatus; @endphp
|
||||||
<x-dashboard.admin.layout title="Deals">
|
<x-dashboard.admin.layout title="Manage Deals">
|
||||||
<x-slot:heading>
|
<x-slot:heading>
|
||||||
<x-dashboard.page-heading
|
<x-dashboard.page-heading
|
||||||
title="Manage Customers"
|
title="Manage Deals"
|
||||||
description="Edit, Delete and Login as Customer"
|
description="Approve or reject deals"
|
||||||
/>
|
/>
|
||||||
</x-slot:heading>
|
</x-slot:heading>
|
||||||
<div class="flex items-center justify-center px-4 pb-4 pt-0 md:px-8 md:pb-8">
|
<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">
|
<x-dashboard.card class="w-full">
|
||||||
<h3 class="text-md font-bold mb-2">Reported deals</h3>
|
<h3 class="text-md font-bold mb-2">Approve deals</h3>
|
||||||
<h4 class="text-sm font-medium mb-4 text-accent-600">Total Reports: {{$reports->count()}}</h4>
|
|
||||||
<x-ui.table>
|
<x-ui.table>
|
||||||
<x-ui.table.head>
|
<x-ui.table.head>
|
||||||
<th>Type</th>
|
<th>Title</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<th>Customer</th>
|
<th>Link</th>
|
||||||
<th>Status</th>
|
<th>Category</th>
|
||||||
<th class="flex w-full justify-center items-center">
|
<th>Broker</th>
|
||||||
Deal
|
|
||||||
<x-heroicon-o-arrow-top-right-on-square class="w-4 ml-1"/>
|
|
||||||
</th>
|
|
||||||
</x-ui.table.head>
|
</x-ui.table.head>
|
||||||
|
|
||||||
@forelse($reports as $report)
|
@forelse($deals as $deal)
|
||||||
<x-ui.table.row>
|
<x-ui.table.row>
|
||||||
<td class="text-sm font-medium px-4 text-center">{{ucfirst($report->type->value)}}</td>
|
<td class="text-sm font-medium px-4 text-center truncate max-w-20">{{ucfirst($deal->title)}}</td>
|
||||||
<td class="text-sm text-accent-600 px-4 text-center max-w-40">{{$report->description}}</td>
|
<td class="text-sm text-accent-600 px-4 text-center truncate max-w-60">{{$deal->description}}</td>
|
||||||
<td class="text-sm px-4 text-center">{{$report->user->name}}</td>
|
<td class="text-sm px-4 text-center">{{$deal->link}}</td>
|
||||||
<td class="text-center px-4">
|
<td class="text-sm px-4 text-center">{{$deal->category->name}}</td>
|
||||||
<x-ui.badge
|
<td class="text-sm px-4 text-center">{{$deal->broker->name}}</td>
|
||||||
:title="$report->status->value"
|
|
||||||
:variant="match ($report->status){
|
|
||||||
ReportStatus::Resolved => 'green',
|
|
||||||
ReportStatus::Pending => 'yellow',
|
|
||||||
ReportStatus::Rejected => 'red'
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td class="text-sm px-4 text-center truncate max-w-40">
|
|
||||||
<a target="_blank" class="hover:underline"
|
|
||||||
href="{{route('explore', ['show' => $report->deals()->first()->id])}}">
|
|
||||||
{{$report->deals()->first()->title}}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<x-slot:actions>
|
<x-slot:actions>
|
||||||
<div class="flex items-center justify-center space-x-2 py-1 px-2">
|
<div class="flex items-center justify-center space-x-2 py-1 px-2">
|
||||||
@if($report->status !== ReportStatus::Resolved)
|
<form action="{{route('admin.deals.approve', $deal)}}"
|
||||||
<form action="{{route('admin.reports.resolve', $report)}}"
|
onsubmit="return confirm('Are you sure to activate the deal ?')" method="post"
|
||||||
onsubmit="return confirm('Are you sure to mark this resolve ?')" method="post"
|
|
||||||
class=" h-full items-center flex justify-center">
|
class=" h-full items-center flex justify-center">
|
||||||
@csrf
|
@csrf
|
||||||
<x-ui.button-sm tooltip="Mark resolved" variant="green">
|
<x-ui.button-sm tooltip="Approve deal" variant="green">
|
||||||
<x-heroicon-o-check class="w-4"/>
|
<x-heroicon-o-check class="w-4"/>
|
||||||
</x-ui.button-sm>
|
</x-ui.button-sm>
|
||||||
</form>
|
</form>
|
||||||
@endif
|
|
||||||
@if($report->status !== ReportStatus::Rejected)
|
<form action="{{route('admin.deals.reject', $deal)}}"
|
||||||
<form action="{{route('admin.reports.reject', $report)}}"
|
onsubmit="return confirm('Are you sure to delete the deal ?')" method="post"
|
||||||
onsubmit="return confirm('Are you sure to reject this ?')" method="post"
|
|
||||||
class=" h-full items-center flex justify-center">
|
class=" h-full items-center flex justify-center">
|
||||||
@csrf
|
@csrf
|
||||||
<x-ui.button-sm tooltip="Reject" variant="red">
|
<x-ui.button-sm tooltip="Delete deal" variant="red">
|
||||||
<x-heroicon-o-x-mark class="w-4"/>
|
<x-heroicon-o-x-mark class="w-4"/>
|
||||||
</x-ui.button-sm>
|
</x-ui.button-sm>
|
||||||
</form>
|
</form>
|
||||||
@endif
|
|
||||||
<form action="{{route('admin.reports.remove-content', $report)}}"
|
<x-ui.button-sm data-deal-id="{{$deal->id}}" class="view-deal-btn" tooltip="View Content" variant="ghost">
|
||||||
onsubmit="return confirm('Are you sure to remove the deal ?')" method="post"
|
<x-heroicon-o-eye class="w-4"/>
|
||||||
class=" h-full items-center flex justify-center">
|
|
||||||
@csrf
|
|
||||||
<x-ui.button-sm tooltip="Remove Content" variant="ghost">
|
|
||||||
<x-heroicon-o-exclamation-triangle class="w-4"/>
|
|
||||||
</x-ui.button-sm>
|
</x-ui.button-sm>
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</x-slot:actions>
|
</x-slot:actions>
|
||||||
</x-ui.table.row>
|
</x-ui.table.row>
|
||||||
@ -84,4 +59,6 @@ class=" h-full items-center flex justify-center">
|
|||||||
</x-ui.table>
|
</x-ui.table>
|
||||||
</x-dashboard.card>
|
</x-dashboard.card>
|
||||||
</div>
|
</div>
|
||||||
|
<x-dashboard.user.deal-modal />
|
||||||
|
@vite('resources/js/admin-deals.js')
|
||||||
</x-dashboard.admin.layout>
|
</x-dashboard.admin.layout>
|
||||||
|
|||||||
@ -5,10 +5,14 @@
|
|||||||
use App\Queries\ExplorePageDealsQuery;
|
use App\Queries\ExplorePageDealsQuery;
|
||||||
|
|
||||||
Route::get('/deals/{deal}', function (Deal $deal) {
|
Route::get('/deals/{deal}', function (Deal $deal) {
|
||||||
|
$query = (new ExplorePageDealsQuery)->builder();
|
||||||
|
if (! Auth::user()->isAdmin()) {
|
||||||
|
$query // Select only admin-approved deals
|
||||||
|
->tap(fn ($q) => (new Deal)->withActiveDeals($q));
|
||||||
|
}
|
||||||
|
$query->where('id', $deal->id);
|
||||||
|
|
||||||
return new DealResource(
|
return new DealResource(
|
||||||
(new ExplorePageDealsQuery)
|
$query->first()
|
||||||
->builder()
|
|
||||||
->where('id', $deal->id)
|
|
||||||
->first()
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
use App\Http\Controllers\Admin\AdminDashboardController;
|
use App\Http\Controllers\Admin\AdminDashboardController;
|
||||||
use App\Http\Controllers\Admin\BrokerController;
|
use App\Http\Controllers\Admin\BrokerController;
|
||||||
use App\Http\Controllers\Admin\CustomerController;
|
use App\Http\Controllers\Admin\CustomerController;
|
||||||
|
use App\Http\Controllers\Admin\DealController;
|
||||||
use App\Http\Controllers\Admin\ReportController;
|
use App\Http\Controllers\Admin\ReportController;
|
||||||
use App\Http\Middleware\HasRole;
|
use App\Http\Middleware\HasRole;
|
||||||
|
|
||||||
@ -22,4 +23,8 @@
|
|||||||
Route::post('/reports/reject/{report}', [ReportController::class, 'reject'])->name('reports.reject');
|
Route::post('/reports/reject/{report}', [ReportController::class, 'reject'])->name('reports.reject');
|
||||||
Route::post('/reports/remove/{report}',
|
Route::post('/reports/remove/{report}',
|
||||||
[ReportController::class, 'removeContent'])->name('reports.remove-content');
|
[ReportController::class, 'removeContent'])->name('reports.remove-content');
|
||||||
|
|
||||||
|
Route::get('/deals', [DealController::class, 'index'])->name('deals.index');
|
||||||
|
Route::post('/deals/approve/{deal}', [DealController::class, 'approve'])->name('deals.approve');
|
||||||
|
Route::post('/deals/reject/{deal}', [DealController::class, 'reject'])->name('deals.reject');
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user