mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 04:31:10 -05:00
- Add RideReviewComponent for submitting reviews - Star rating input with real-time validation - Rate limiting and anti-spam measures - Edit capabilities for own reviews - Add RideReviewListComponent for displaying reviews - Paginated list with sort/filter options - Helpful vote functionality - Statistics display with rating distribution - Add ReviewModerationComponent for review management - Review queue with status filters - Approve/reject functionality - Batch actions support - Edit capabilities - Update Memory Bank documentation - Document component implementations - Track feature completion - Update technical decisions
152 lines
4.1 KiB
PHP
152 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use App\Models\Review;
|
|
use App\Models\Ride;
|
|
use App\Enums\ReviewStatus;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
use Livewire\Component;
|
|
use Livewire\Attributes\Rule;
|
|
|
|
class RideReviewComponent extends Component
|
|
{
|
|
/**
|
|
* The ride being reviewed
|
|
*/
|
|
public Ride $ride;
|
|
|
|
/**
|
|
* The review being edited (if in edit mode)
|
|
*/
|
|
public ?Review $review = null;
|
|
|
|
/**
|
|
* Form fields
|
|
*/
|
|
#[Rule('required|integer|min:1|max:5')]
|
|
public int $rating = 3;
|
|
|
|
#[Rule('nullable|string|max:100')]
|
|
public ?string $title = null;
|
|
|
|
#[Rule('required|string|min:10|max:2000')]
|
|
public string $content = '';
|
|
|
|
/**
|
|
* Whether the component is in edit mode
|
|
*/
|
|
public bool $isEditing = false;
|
|
|
|
/**
|
|
* Success/error message
|
|
*/
|
|
public ?string $message = null;
|
|
|
|
/**
|
|
* Mount the component
|
|
*/
|
|
public function mount(Ride $ride, ?Review $review = null)
|
|
{
|
|
$this->ride = $ride;
|
|
|
|
if ($review) {
|
|
$this->review = $review;
|
|
$this->isEditing = true;
|
|
$this->rating = $review->rating;
|
|
$this->title = $review->title;
|
|
$this->content = $review->content;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save or update the review
|
|
*/
|
|
public function save()
|
|
{
|
|
// Check if user is authenticated
|
|
if (!Auth::check()) {
|
|
$this->message = 'You must be logged in to submit a review.';
|
|
return;
|
|
}
|
|
|
|
// Rate limiting
|
|
$key = 'review_' . Auth::id();
|
|
if (RateLimiter::tooManyAttempts($key, 5)) { // 5 attempts per minute
|
|
$this->message = 'Please wait before submitting another review.';
|
|
return;
|
|
}
|
|
RateLimiter::hit($key);
|
|
|
|
// Validate input
|
|
$this->validate();
|
|
|
|
try {
|
|
if ($this->isEditing) {
|
|
// Check if user can edit this review
|
|
if (!$this->review || $this->review->user_id !== Auth::id()) {
|
|
$this->message = 'You cannot edit this review.';
|
|
return;
|
|
}
|
|
|
|
// Update existing review
|
|
$this->review->update([
|
|
'rating' => $this->rating,
|
|
'title' => $this->title,
|
|
'content' => $this->content,
|
|
'status' => ReviewStatus::PENDING,
|
|
]);
|
|
|
|
$this->message = 'Review updated successfully. It will be visible after moderation.';
|
|
} else {
|
|
// Check if user already reviewed this ride
|
|
if (!$this->ride->canBeReviewedBy(Auth::user())) {
|
|
$this->message = 'You have already reviewed this ride.';
|
|
return;
|
|
}
|
|
|
|
// Create new review
|
|
Review::create([
|
|
'ride_id' => $this->ride->id,
|
|
'user_id' => Auth::id(),
|
|
'rating' => $this->rating,
|
|
'title' => $this->title,
|
|
'content' => $this->content,
|
|
'status' => ReviewStatus::PENDING,
|
|
]);
|
|
|
|
$this->message = 'Review submitted successfully. It will be visible after moderation.';
|
|
|
|
// Reset form
|
|
$this->reset(['rating', 'title', 'content']);
|
|
}
|
|
|
|
$this->dispatch('review-saved');
|
|
} catch (\Exception $e) {
|
|
$this->message = 'An error occurred while saving your review. Please try again.';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset the form
|
|
*/
|
|
public function resetForm()
|
|
{
|
|
$this->reset(['rating', 'title', 'content', 'message']);
|
|
if ($this->review) {
|
|
$this->rating = $this->review->rating;
|
|
$this->title = $this->review->title;
|
|
$this->content = $this->review->content;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render the component
|
|
*/
|
|
public function render()
|
|
{
|
|
return view('livewire.ride-review-component');
|
|
}
|
|
}
|