feature(report a deal): users can report a deal
This commit is contained in:
parent
f33f68cd3e
commit
3750638122
14
app/Enums/ReportStatus.php
Normal file
14
app/Enums/ReportStatus.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use App\Traits\EnumAsArray;
|
||||
|
||||
enum ReportStatus: string
|
||||
{
|
||||
use EnumAsArray;
|
||||
|
||||
case Pending = 'pending';
|
||||
case Resolved = 'resolved';
|
||||
case Rejected = 'rejected';
|
||||
}
|
||||
17
app/Enums/ReportType.php
Normal file
17
app/Enums/ReportType.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use App\Traits\EnumAsArray;
|
||||
|
||||
enum ReportType: string
|
||||
{
|
||||
use EnumAsArray;
|
||||
|
||||
case Spam = 'spam';
|
||||
case Harmful = 'harmful';
|
||||
case Nudity = 'nudity';
|
||||
case Misinformation = 'misinformation';
|
||||
case Unauthorized = 'unauthorized';
|
||||
|
||||
}
|
||||
@ -12,7 +12,7 @@ class InteractionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Interact to a deal by Like or Favorite state
|
||||
* @param Deal $deal
|
||||
*
|
||||
* @param InteractionType $type [InteractionType::Like, InteractionType::Favorite]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
@ -46,6 +46,7 @@ public function togglesState(Deal $deal, InteractionType $type)
|
||||
|
||||
$message = "{$type->value} added to deal";
|
||||
}
|
||||
|
||||
return response()->json(['message' => $message]);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
@ -62,5 +63,4 @@ public function togglesState(Deal $deal, InteractionType $type)
|
||||
return response()->json(['error' => 'Something went wrong.'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
82
app/Http/Controllers/ReportController.php
Normal file
82
app/Http/Controllers/ReportController.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\StoreReportRequest;
|
||||
use App\Models\Deal;
|
||||
use App\Models\Report;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ReportController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(StoreReportRequest $request, Deal $deal)
|
||||
{
|
||||
$data = $request->validated();
|
||||
$data['user_id'] = Auth::id();
|
||||
|
||||
// Check if the user already reported the deal
|
||||
$alreadyReported = $deal->reports()->where('user_id', Auth::id())->first();
|
||||
if ($alreadyReported) {
|
||||
return response()->json(['message' => 'You already reported this report'], 405);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::transaction(function () use ($data, $deal) {
|
||||
Report::unguard();
|
||||
Report::create($data)->deals()->attach($deal);
|
||||
Report::reguard();
|
||||
});
|
||||
|
||||
return response()->json(['message' => 'Report created'], 201);
|
||||
|
||||
} catch (\Throwable $exception) {
|
||||
Log::error('Error creating report', [
|
||||
'user_id' => Auth::id(),
|
||||
'deal_id' => $deal->id,
|
||||
'error' => $exception->getMessage(),
|
||||
'trace' => $exception->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return response()->json(['message' => 'Error creating report'], 500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(Report $report)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, Report $report)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(Report $report)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
31
app/Http/Requests/StoreReportRequest.php
Normal file
31
app/Http/Requests/StoreReportRequest.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Enums\ReportType;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreReportRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'type' => ['required', Rule::in(ReportType::values())],
|
||||
'description' => 'required|string|min:10|max:500',
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
@ -28,8 +29,6 @@ public function interactions(): HasMany
|
||||
|
||||
/**
|
||||
* Get deals that are active
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeWithActiveDeals(Builder $query): Builder
|
||||
{
|
||||
@ -38,8 +37,6 @@ public function scopeWithActiveDeals(Builder $query): Builder
|
||||
|
||||
/**
|
||||
* Get if the current user has liked or favorite the deal
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeWithCurrentUserInteractions(Builder $query): Builder
|
||||
{
|
||||
@ -51,7 +48,7 @@ public function scopeWithCurrentUserInteractions(Builder $query): Builder
|
||||
'interactions as is_favorite' => function ($query) {
|
||||
$query->where('user_id', Auth::id())
|
||||
->where('type', InteractionType::Favorite);
|
||||
}
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
@ -60,7 +57,12 @@ public function scopeWithLikes(Builder $query): Builder
|
||||
return $query->withCount([
|
||||
'interactions as total_likes' => function ($query) {
|
||||
$query->where('type', InteractionType::Like);
|
||||
}
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
public function reports(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Report::class);
|
||||
}
|
||||
}
|
||||
|
||||
30
app/Models/Report.php
Normal file
30
app/Models/Report.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\ReportStatus;
|
||||
use App\Enums\ReportType;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class Report extends Model
|
||||
{
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function deals(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Deal::class);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'type' => ReportType::class,
|
||||
'status' => ReportStatus::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -8,4 +8,11 @@ public static function values(): array
|
||||
{
|
||||
return array_column(self::cases(), 'value');
|
||||
}
|
||||
|
||||
public static function assocValues(): array
|
||||
{
|
||||
return array_map(function ($enum) {
|
||||
return ['name' => $enum->name, 'value' => $enum->value];
|
||||
}, self::cases());
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\ReportStatus;
|
||||
use App\Enums\ReportType;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('reports', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->enum('type', ReportType::values());
|
||||
$table->enum('status', ReportStatus::values())->default(ReportStatus::Pending);
|
||||
$table->text('description');
|
||||
$table->foreignIdFor(User::class);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('reports');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Deal;
|
||||
use App\Models\Report;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('deal_report', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignIdFor(Deal::class);
|
||||
$table->foreignIdFor(Report::class);
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('deal_report');
|
||||
}
|
||||
};
|
||||
10
resources/js/modal.js
Normal file
10
resources/js/modal.js
Normal file
@ -0,0 +1,10 @@
|
||||
export function showModal(id){
|
||||
let modal = document.getElementById(id);
|
||||
modal.showModal();
|
||||
}
|
||||
export function closeModal(id){
|
||||
let modal = document.getElementById(id);
|
||||
modal.close();
|
||||
}
|
||||
document.showModal = showModal;
|
||||
document.closeModal = closeModal;
|
||||
60
resources/js/report-deal.js
Normal file
60
resources/js/report-deal.js
Normal file
@ -0,0 +1,60 @@
|
||||
import {closeModal, showModal} from './modal.js';
|
||||
import {showToast} from './toast.js';
|
||||
const reportModal = document.getElementById('report-modal');
|
||||
const reportForm = document.getElementById('report-form');
|
||||
|
||||
|
||||
function showReportModal(dealId, dealTitle) {
|
||||
// Clear the fields
|
||||
reportForm.reset();
|
||||
const oldErrors = reportForm.querySelectorAll('.text-red-500');
|
||||
oldErrors.forEach(error => error.remove());
|
||||
|
||||
reportModal.dataset.dealId = dealId;
|
||||
const reportModalTitle = document.getElementById('report-modal-title');
|
||||
const reportModalId = document.getElementById('report-modal-id');
|
||||
reportModalTitle.innerText = dealTitle;
|
||||
reportModalId.innerText = dealId;
|
||||
showModal('report-modal');
|
||||
}
|
||||
|
||||
reportForm.addEventListener('submit', async function (form) {
|
||||
form.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
const dealId = reportModal.dataset.dealId
|
||||
try {
|
||||
|
||||
let response = await axios.post(
|
||||
`report/${dealId}`,
|
||||
formData
|
||||
);
|
||||
|
||||
showToast('Report submitted. Thank you for keeping DealHub safe!');
|
||||
closeModal('report-modal')
|
||||
|
||||
} catch (error) {
|
||||
|
||||
if (error.response.status === 405) {
|
||||
closeModal('report-modal');
|
||||
showToast('You already have reported this deal !');
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate over the all error messages spans and show validation errors
|
||||
if (error.response.status === 422) {
|
||||
|
||||
let errors = error.response.data.errors;
|
||||
|
||||
Object.keys(errors).forEach(error => {
|
||||
let errorField = reportForm.querySelector(`[name="${error}"]`)
|
||||
const errorSpan = document.createElement('span');
|
||||
errorSpan.textContent = errors[error][0];
|
||||
errorSpan.classList.add('text-red-500');
|
||||
errorSpan.classList.add('text-sm');
|
||||
errorField.insertAdjacentElement('afterend', errorSpan);
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.showReportModal = showReportModal;
|
||||
15
resources/js/toast.js
Normal file
15
resources/js/toast.js
Normal file
@ -0,0 +1,15 @@
|
||||
const toast = document.querySelector('.toast');
|
||||
const toastBtn = document.querySelector('#toast-btn');
|
||||
let toastMessage = toast.querySelector('#toast-message');
|
||||
export function showToast(message) {
|
||||
toast.classList.toggle('hidden')
|
||||
toastMessage.textContent = message;
|
||||
setTimeout(() => {
|
||||
toast.classList.toggle('hidden');
|
||||
}, 3000)
|
||||
}
|
||||
function hideToast() {
|
||||
toast.classList.toggle('hidden')
|
||||
}
|
||||
document.hideToast = hideToast;
|
||||
document.showToast = showToast;
|
||||
@ -1,6 +1,6 @@
|
||||
@props(['id', 'like' => false, 'favourite' => false])
|
||||
@props(['deal_id', 'deal_title', 'like' => false, 'favourite' => false])
|
||||
<div class="">
|
||||
<x-ui.button-sm @class(["text-accent-600", 'liked' => $like]) onclick="like(this, {{$id}})">
|
||||
<x-ui.button-sm @class(["text-accent-600", 'liked' => $like]) onclick="like(this, {{$deal_id}})">
|
||||
<x-heroicon-o-heart
|
||||
@class([
|
||||
"like w-4",
|
||||
@ -15,7 +15,7 @@
|
||||
/>
|
||||
</x-ui.button-sm>
|
||||
|
||||
<x-ui.button-sm class="text-accent-600" onclick="favorite(this, {{$id}})">
|
||||
<x-ui.button-sm class="text-accent-600" onclick="favorite(this, {{$deal_id}})">
|
||||
<x-heroicon-o-star
|
||||
@class([
|
||||
"favorite w-4",
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
</x-ui.button-sm>
|
||||
|
||||
<x-ui.button-sm class="text-accent-600">
|
||||
<x-ui.button-sm class="text-accent-600" onclick="showReportModal({{$deal_id}}, '{{$deal_title}}')">
|
||||
<x-heroicon-o-exclamation-circle class="w-4"/>
|
||||
</x-ui.button-sm>
|
||||
</div>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
{{$deal->category->name}}
|
||||
</x-ui.button-sm>
|
||||
@ds($deal)
|
||||
<x-dashboard.user.action-toolbar :id="$deal->id" :like="$deal->is_liked" :favourite="$deal->is_favorite" />
|
||||
<x-dashboard.user.action-toolbar :deal_title="$deal->title" :deal_id="$deal->id" :like="$deal->is_liked" :favourite="$deal->is_favorite" />
|
||||
</div>
|
||||
|
||||
<p class="font-bold text-lg ">{{$deal->title}}</p>
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
<x-ui.modal id="report-modal" class="w-130">
|
||||
<form class="flex justify-between items-start" method="dialog">
|
||||
<div class="flex space-x-2 items-center">
|
||||
<x-icon-square variant="red" class="p-2!">
|
||||
<x-heroicon-o-exclamation-circle class="w-6" />
|
||||
</x-icon-square>
|
||||
<p class="text-xl font-bold">Report Deal</p>
|
||||
</div>
|
||||
<button type="submit" class="" >
|
||||
<x-heroicon-o-x-mark class="w-4" />
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="text-accent-600/80 mt-2 text-sm">Help us maintain a trusted platform by reporting inappropriate or suspicious content.</p>
|
||||
<p class="text-accent-600 mt-2 text-sm font-bold">Deal being reported</p>
|
||||
<div class="w-fit wrap-break-word px-2 py-4">
|
||||
<p class="font-bold text-sm" id="report-modal-title"></p>
|
||||
<p class="text-xs text-accent-600/80 pt-2">ID: #<span id="report-modal-id"></span></p>
|
||||
</div>
|
||||
|
||||
<form action="" method="post" id="report-form" class="mt-4 flex flex-col space-y-4">
|
||||
@csrf
|
||||
<x-ui.select :options="\App\Enums\ReportType::assocValues()" label-key="name" value-key="value" name="type" placeholder="Select one reason" required label="Reason for report" />
|
||||
|
||||
<x-ui.textarea name="description" label="Additional Details" required placeholder="Please provide more details about why you're reporting this deal..." description="Minimum 10 characters" />
|
||||
|
||||
<p class="text-blue-700 bg-blue-100 text-xs p-4 rounded-xl">
|
||||
<span class="font-bold">Note:</span> Your report will be reviewed by out moderation team within 24-48 hours.<br />
|
||||
False reports may result in account restrictions.
|
||||
</p>
|
||||
<div class="w-full flex justify-end space-x-4">
|
||||
<x-ui.button class="border border-accent-600/20" onclick="closeModal('report-modal')">Cancel</x-ui.button>
|
||||
<x-ui.button variant="red" type="submit">Submit report</x-ui.button>
|
||||
</div>
|
||||
</form>
|
||||
</x-ui.modal>
|
||||
@ -2,12 +2,13 @@
|
||||
@php
|
||||
$variants = [
|
||||
'blue' => "bg-blue-100 text-blue-700",
|
||||
'red' => 'bg-red-100 text-red-700',
|
||||
'purple' => "bg-purple-100 text-purple-700",
|
||||
'pink' => "bg-pink-100 text-pink-700",
|
||||
'green' => "bg-green-100 text-green-700",
|
||||
'ghost' => 'bg-gray-100 text-gray-900'
|
||||
]
|
||||
@endphp
|
||||
<div class="p-4 {{$variants[$variant]}} w-fit rounded-xl">
|
||||
<div {{$attributes->merge(["class" => "$variants[$variant] p-4 w-fit rounded-xl"])}}>
|
||||
{{$slot}}
|
||||
</div>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<button {{$attributes->merge(['class' => "px-4 py-2 rounded-lg font-medium hover:opacity-80 $variantClass"])}}>
|
||||
<button {{$attributes->merge(['class' => "px-4 py-2 rounded-lg font-medium hover:opacity-80 $variantClass", 'type'=>'submit'])}}>
|
||||
<div class="flex justify-center items-center space-x-2">
|
||||
@if($icon !=='')
|
||||
@svg("heroicon-o-$icon", 'w-5 h-5')
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@props(['name' => ''])
|
||||
@error($name)
|
||||
<span class="text-xs text-red-500">{{ $message }}</span>
|
||||
<span class="text-xs text-red-500 error-message">{{ $message }}</span>
|
||||
@enderror
|
||||
|
||||
6
resources/views/components/ui/modal.blade.php
Normal file
6
resources/views/components/ui/modal.blade.php
Normal file
@ -0,0 +1,6 @@
|
||||
<dialog {{$attributes->merge(["class"=>"fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg p-4 shadow-lg"])}} >
|
||||
<div>
|
||||
{{$slot}}
|
||||
</div>
|
||||
</dialog>
|
||||
@vite('resources/js/modal.js')
|
||||
@ -26,7 +26,7 @@
|
||||
class="bg-[#F3F3F5] py-2 px-4 rounded-lg text-sm font-bold invalid:text-accent-600 text-black h-full"
|
||||
>
|
||||
@if($placeholder !== '')
|
||||
<option {{old($name) === ''? 'selected' : ''}} disabled>{{$placeholder}}</option>
|
||||
<option {{old($name) === '' || $selected === '' ? 'selected' : ''}} disabled>{{$placeholder}}</option>
|
||||
@endif
|
||||
|
||||
@foreach($options as $option)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@props(['label' => '', 'name' => '', 'placeholder' => '', 'required' => false, 'value' => ''])
|
||||
@props(['label' => '', 'name' => '', 'placeholder' => '', 'required' => false, 'value' => '', 'description'])
|
||||
@if($label !== '')
|
||||
<div class="flex flex-col space-y-2">
|
||||
|
||||
@ -11,11 +11,15 @@
|
||||
</label>
|
||||
|
||||
<textarea
|
||||
class="bg-[#F3F3F5] py-2 px-4 rounded-lg"
|
||||
class="bg-[#F3F3F5] py-2 px-4 rounded-lg h-40"
|
||||
name="{{$name}}" placeholder="{{$placeholder}}"
|
||||
required="{{$required?'required':''}}"
|
||||
>{{old($name, $value)}}</textarea>
|
||||
|
||||
@isset($description)
|
||||
<p class="text-accent-600 text-xs">{{$description}}</p>
|
||||
@endisset
|
||||
|
||||
<x-ui.inline-error :name="$name"/>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
6
resources/views/components/ui/toast.blade.php
Normal file
6
resources/views/components/ui/toast.blade.php
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="toast hidden fixed top-10 right-5 md:right-10 bg-black text-white rounded-xl shadow-lg p-4 flex space-x-2">
|
||||
<p id="toast-message" class="max-w-70 wrap-break-word"></p>
|
||||
<x-ui.button-sm onclick="hideToast()">
|
||||
<x-heroicon-o-x-mark class="w-4" />
|
||||
</x-ui.button-sm>
|
||||
</div>
|
||||
@ -87,6 +87,8 @@
|
||||
</x-ui.toggle-button-group>
|
||||
|
||||
<x-dashboard.user.listing :deals="$deals"/>
|
||||
<x-dashboard.user.report-modal />
|
||||
</section>
|
||||
@vite(['resources/js/menu.js', 'resources/js/interaction.js'])
|
||||
<x-ui.toast />
|
||||
@vite(['resources/js/menu.js', 'resources/js/interaction.js', 'resources/js/report-deal.js', 'resources/js/toast.js'])
|
||||
</x-layout>
|
||||
|
||||
@ -1,54 +1,21 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\InteractionType;
|
||||
use App\Enums\UserTypes;
|
||||
use App\Http\Controllers\AuthenticatedUserController;
|
||||
use App\Http\Controllers\Broker\BrokerDashboardController;
|
||||
use App\Http\Controllers\Broker\BrokerProfileController;
|
||||
use App\Http\Controllers\BrokerDealController;
|
||||
use App\Http\Controllers\ExplorePageController;
|
||||
use App\Http\Controllers\HomeController;
|
||||
use App\Http\Controllers\InteractionController;
|
||||
use App\Http\Controllers\RegisteredUserController;
|
||||
use App\Http\Middleware\HasRole;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
require __DIR__.'/web/auth.php';
|
||||
require __DIR__.'/web/broker.php';
|
||||
require __DIR__.'/web/interaction.php';
|
||||
|
||||
Route::get('/', HomeController::class)->name('home');
|
||||
|
||||
Route::middleware('guest')->group(function () {
|
||||
Route::resource('/login', AuthenticatedUserController::class)
|
||||
->middleware('throttle:6,1')
|
||||
->only(['create', 'store']);
|
||||
Route::resource('/register', RegisteredUserController::class)->only(['create', 'store']);
|
||||
});
|
||||
|
||||
Route::middleware('auth')->group(function () {
|
||||
Route::delete('/logout', [AuthenticatedUserController::class, 'destroy'])->name('logout');
|
||||
|
||||
Route::get('/explore', ExplorePageController::class)->name('explore');
|
||||
|
||||
Route::view('/admin/dashboard', 'dashboards.admin.index')
|
||||
->middleware(HasRole::class.':'.UserTypes::Admin->value)
|
||||
->name('admin.dashboard');
|
||||
|
||||
Route::prefix('/broker')
|
||||
->name('broker.')
|
||||
->middleware(HasRole::class.':'.UserTypes::Broker->value)
|
||||
->group(function () {
|
||||
Route::get('dashboard', [BrokerDashboardController::class, 'index'])->name('dashboard');
|
||||
|
||||
Route::resource('deals', BrokerDealController::class)->except('show');
|
||||
|
||||
Route::resource('profile', BrokerProfileController::class)->except('index', 'store', 'create');
|
||||
});
|
||||
|
||||
Route::post('/like/{deal}', [InteractionController::class, 'togglesState'])
|
||||
->defaults('type', InteractionType::Like)
|
||||
->middleware('throttle:30,1')
|
||||
->name('like');
|
||||
|
||||
Route::post('/favorite/{deal}', [InteractionController::class, 'togglesState'])
|
||||
->defaults('type', InteractionType::Favorite)
|
||||
->middleware('throttle:30,1')
|
||||
->name('like');
|
||||
});
|
||||
|
||||
15
routes/web/auth.php
Normal file
15
routes/web/auth.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\AuthenticatedUserController;
|
||||
use App\Http\Controllers\RegisteredUserController;
|
||||
|
||||
Route::middleware('guest')->group(function () {
|
||||
Route::resource('/login', AuthenticatedUserController::class)
|
||||
->middleware('throttle:6,1')
|
||||
->only(['create', 'store']);
|
||||
Route::resource('/register', RegisteredUserController::class)->only(['create', 'store']);
|
||||
});
|
||||
|
||||
Route::delete('/logout', [AuthenticatedUserController::class, 'destroy'])
|
||||
->middleware('auth')
|
||||
->name('logout');
|
||||
18
routes/web/broker.php
Normal file
18
routes/web/broker.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\UserTypes;
|
||||
use App\Http\Controllers\Broker\BrokerDashboardController;
|
||||
use App\Http\Controllers\Broker\BrokerProfileController;
|
||||
use App\Http\Controllers\BrokerDealController;
|
||||
use App\Http\Middleware\HasRole;
|
||||
|
||||
Route::prefix('/broker')
|
||||
->name('broker.')
|
||||
->middleware([HasRole::class.':'.UserTypes::Broker->value, 'auth'])
|
||||
->group(function () {
|
||||
Route::get('dashboard', [BrokerDashboardController::class, 'index'])->name('dashboard');
|
||||
|
||||
Route::resource('deals', BrokerDealController::class)->except('show');
|
||||
|
||||
Route::resource('profile', BrokerProfileController::class)->except('index', 'store', 'create');
|
||||
});
|
||||
21
routes/web/interaction.php
Normal file
21
routes/web/interaction.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\InteractionType;
|
||||
use App\Http\Controllers\InteractionController;
|
||||
use App\Http\Controllers\ReportController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware('auth')->group(function () {
|
||||
|
||||
Route::post('/like/{deal}', [InteractionController::class, 'togglesState'])
|
||||
->defaults('type', InteractionType::Like)
|
||||
->middleware('throttle:30,1')
|
||||
->name('like');
|
||||
|
||||
Route::post('/favorite/{deal}', [InteractionController::class, 'togglesState'])
|
||||
->defaults('type', InteractionType::Favorite)
|
||||
->middleware('throttle:30,1')
|
||||
->name('favorite');
|
||||
|
||||
Route::post('/report/{deal}', [ReportController::class, 'store'])->name('report.store');
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user