mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 09:31:11 -05:00
feat: implement ride review components
- 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
This commit is contained in:
151
app/Livewire/RideReviewComponent.php
Normal file
151
app/Livewire/RideReviewComponent.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user