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
|
||||
{
|
||||
$query->tap(fn ($q) => (new Deal)->withActiveDeals($q));
|
||||
// Add a search query
|
||||
if ($request->has('search') && $request->get('search') !== null) {
|
||||
$query->tap(fn ($q) => (new Deal)->search($q, $request->search));
|
||||
|
||||
@ -25,8 +25,7 @@ public function builder(): Builder
|
||||
->with('type');
|
||||
},
|
||||
])
|
||||
// Select only admin-approved deals
|
||||
->tap(fn ($q) => (new Deal)->withActiveDeals($q))
|
||||
|
||||
// Check if the current user interacted with the deal
|
||||
->tap(fn ($q) => (new Deal)->withCurrentUserInteractions($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"/>
|
||||
<p class="sidebar-text transition-opacity duration-300 ease-in-out">Manage Reports</p>
|
||||
</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>
|
||||
|
||||
|
||||
@ -1,78 +1,53 @@
|
||||
@php use App\Enums\ReportStatus; @endphp
|
||||
<x-dashboard.admin.layout title="Deals">
|
||||
<x-dashboard.admin.layout title="Manage Deals">
|
||||
<x-slot:heading>
|
||||
<x-dashboard.page-heading
|
||||
title="Manage Customers"
|
||||
description="Edit, Delete and Login as Customer"
|
||||
title="Manage Deals"
|
||||
description="Approve or reject deals"
|
||||
/>
|
||||
</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-2">Reported deals</h3>
|
||||
<h4 class="text-sm font-medium mb-4 text-accent-600">Total Reports: {{$reports->count()}}</h4>
|
||||
<h3 class="text-md font-bold mb-2">Approve deals</h3>
|
||||
<x-ui.table>
|
||||
<x-ui.table.head>
|
||||
<th>Type</th>
|
||||
<th>Title</th>
|
||||
<th>Description</th>
|
||||
<th>Customer</th>
|
||||
<th>Status</th>
|
||||
<th class="flex w-full justify-center items-center">
|
||||
Deal
|
||||
<x-heroicon-o-arrow-top-right-on-square class="w-4 ml-1"/>
|
||||
</th>
|
||||
<th>Link</th>
|
||||
<th>Category</th>
|
||||
<th>Broker</th>
|
||||
</x-ui.table.head>
|
||||
|
||||
@forelse($reports as $report)
|
||||
@forelse($deals as $deal)
|
||||
<x-ui.table.row>
|
||||
<td class="text-sm font-medium px-4 text-center">{{ucfirst($report->type->value)}}</td>
|
||||
<td class="text-sm text-accent-600 px-4 text-center max-w-40">{{$report->description}}</td>
|
||||
<td class="text-sm px-4 text-center">{{$report->user->name}}</td>
|
||||
<td class="text-center px-4">
|
||||
<x-ui.badge
|
||||
: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>
|
||||
<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 truncate max-w-60">{{$deal->description}}</td>
|
||||
<td class="text-sm px-4 text-center">{{$deal->link}}</td>
|
||||
<td class="text-sm px-4 text-center">{{$deal->category->name}}</td>
|
||||
<td class="text-sm px-4 text-center">{{$deal->broker->name}}</td>
|
||||
<x-slot:actions>
|
||||
<div class="flex items-center justify-center space-x-2 py-1 px-2">
|
||||
@if($report->status !== ReportStatus::Resolved)
|
||||
<form action="{{route('admin.reports.resolve', $report)}}"
|
||||
onsubmit="return confirm('Are you sure to mark this resolve ?')" method="post"
|
||||
<form action="{{route('admin.deals.approve', $deal)}}"
|
||||
onsubmit="return confirm('Are you sure to activate the deal ?')" method="post"
|
||||
class=" h-full items-center flex justify-center">
|
||||
@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-ui.button-sm>
|
||||
</form>
|
||||
@endif
|
||||
@if($report->status !== ReportStatus::Rejected)
|
||||
<form action="{{route('admin.reports.reject', $report)}}"
|
||||
onsubmit="return confirm('Are you sure to reject this ?')" method="post"
|
||||
|
||||
<form action="{{route('admin.deals.reject', $deal)}}"
|
||||
onsubmit="return confirm('Are you sure to delete the deal ?')" method="post"
|
||||
class=" h-full items-center flex justify-center">
|
||||
@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-ui.button-sm>
|
||||
</form>
|
||||
@endif
|
||||
<form action="{{route('admin.reports.remove-content', $report)}}"
|
||||
onsubmit="return confirm('Are you sure to remove the deal ?')" method="post"
|
||||
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 data-deal-id="{{$deal->id}}" class="view-deal-btn" tooltip="View Content" variant="ghost">
|
||||
<x-heroicon-o-eye class="w-4"/>
|
||||
</x-ui.button-sm>
|
||||
</form>
|
||||
</div>
|
||||
</x-slot:actions>
|
||||
</x-ui.table.row>
|
||||
@ -84,4 +59,6 @@ class=" h-full items-center flex justify-center">
|
||||
</x-ui.table>
|
||||
</x-dashboard.card>
|
||||
</div>
|
||||
<x-dashboard.user.deal-modal />
|
||||
@vite('resources/js/admin-deals.js')
|
||||
</x-dashboard.admin.layout>
|
||||
|
||||
@ -5,10 +5,14 @@
|
||||
use App\Queries\ExplorePageDealsQuery;
|
||||
|
||||
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(
|
||||
(new ExplorePageDealsQuery)
|
||||
->builder()
|
||||
->where('id', $deal->id)
|
||||
->first()
|
||||
$query->first()
|
||||
);
|
||||
});
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
use App\Http\Controllers\Admin\AdminDashboardController;
|
||||
use App\Http\Controllers\Admin\BrokerController;
|
||||
use App\Http\Controllers\Admin\CustomerController;
|
||||
use App\Http\Controllers\Admin\DealController;
|
||||
use App\Http\Controllers\Admin\ReportController;
|
||||
use App\Http\Middleware\HasRole;
|
||||
|
||||
@ -22,4 +23,8 @@
|
||||
Route::post('/reports/reject/{report}', [ReportController::class, 'reject'])->name('reports.reject');
|
||||
Route::post('/reports/remove/{report}',
|
||||
[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