<script type="application/ld+json">
use Illuminate\Database\Eloquent\Model;
const submitReview = async () => await fetch( /api/tours/$tourId/reviews , method: 'POST', headers: 'Content-Type': 'application/json' , body: JSON.stringify(newReview) ); // refresh reviews ; portatour reviews
<div className="write-review"> <h3>Write your review</h3> <StarRating rating=newReview.rating onChange=(r) => setNewReview(...newReview, rating: r) /> <input placeholder="Review title" value=newReview.title onChange=e => setNewReview(...newReview, title: e.target.value) /> <textarea placeholder="Share your experience..." value=newReview.comment onChange=e => setNewReview(...newReview, comment: e.target.value) /> <button onClick=submitReview>Submit Review</button> </div> </div> ); ; const submitReview = async () =>
$reviews = PortaTourReview::where('tour_id', $tourId) ->where('is_approved', true) ->with('user:id,name,avatar') ->orderBy('created_at', 'desc') ->paginate(10); // Aggregate rating breakdown $stats = [ 'average_rating' => PortaTourReview::where('tour_id', $tourId) ->where('is_approved', true) ->avg('rating'), 'total_reviews' => $reviews->total(), 'rating_counts' => PortaTourReview::where('tour_id', $tourId) ->where('is_approved', true) ->selectRaw('rating, count(*) as count') ->groupBy('rating') ->pluck('count', 'rating') ]; await fetch( /api/tours/$tourId/reviews
return ( <div className="portatour-reviews"> <div className="reviews-header"> <h2>Customer Reviews</h2> <div className="rating-summary"> <span className="average">stats?.average_rating.toFixed(1)</span> <StarRating rating=stats?.average_rating /> <span>(stats?.total_reviews reviews)</span> </div> </div>
return $this->belongsTo(Tour::class);