feat: add ratings

This commit is contained in:
2026-02-25 19:37:53 +03:30
parent 4d0823ef86
commit 676522d70d
7 changed files with 270 additions and 5 deletions
+128 -2
View File
@@ -74,7 +74,7 @@ public function store(Request $request)
}
public function index(Request $request)
{
$query = Media::with(['image', 'category', 'myNote', 'tags'])
$query = Media::with(['image', 'category', 'myNote', 'tags','comments'])
->where(function ($q) {
$q->where('visibility', 'public')
->orWhere('user_id', auth()->id());
@@ -179,6 +179,79 @@ public function index(Request $request)
);
}
public function submitFeedback(Request $request, $mediaId)
{
$request->validate([
'stars' => 'nullable|integer|min:1|max:5',
'content' => 'nullable|string|max:2000',
]);
// حداقل یکی باید ارسال شود
if (!$request->filled('stars') && !$request->filled('content')) {
return response()->json([
'message' => 'Stars or comment is required'
], 422);
}
$media = Media::where('id', $mediaId)
->where(function ($q) {
$q->where('visibility', 'public')
->orWhere('user_id', auth()->id());
})
->firstOrFail();
DB::beginTransaction();
try {
$rating = null;
$comment = null;
/*
|--------------------------------------------------------------------------
| Handle Rating (update or create)
|--------------------------------------------------------------------------
*/
if ($request->filled('stars')) {
$rating = $media->ratings()->updateOrCreate(
['user_id' => auth()->id()],
['stars' => $request->stars]
);
}
/*
|--------------------------------------------------------------------------
| 💬 Handle Comment (create only if exists)
|--------------------------------------------------------------------------
*/
if ($request->filled('content')) {
$comment = $media->comments()->create([
'user_id' => auth()->id(),
'content' => $request->content,
]);
}
DB::commit();
return response()->json([
'message' => 'Feedback submitted successfully',
'average_rating' => $media->fresh()->average_rating,
'your_rating' => optional($rating)->stars,
'comment' => $comment ? $comment->load('user') : null,
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'message' => 'Something went wrong',
'error' => $e->getMessage()
], 500);
}
}
public function filters(Request $request)
{
$baseQuery = Media::query()
@@ -248,7 +321,7 @@ public function filters(Request $request)
public function show($id)
{
$media = Media::with(['image', 'category', 'myNote', 'tags'])
$media = Media::with(['image', 'category', 'myNote', 'tags' ,'comments'])
->where('id', $id)
->where(function($query) {
$query->where('visibility', 'public')
@@ -273,9 +346,62 @@ public function show($id)
'myNote' => $media->myNote,
'is_saved' => $media->is_saved,
'is_premium' => $media->is_premium,
'comments' => $media->comments,
'average_rating' => $media->average_rating,
'your_rating' => $media->user_rating,
'comments_count' => $media->comments()->count(),
]);
}
public function rate(Request $request, $mediaId)
{
$request->validate([
'stars' => 'required|integer|min:1|max:5'
]);
$media = Media::findOrFail($mediaId);
$rating = $media->ratings()->updateOrCreate(
['user_id' => auth()->id()],
['stars' => $request->stars]
);
return response()->json([
'message' => 'Rating saved',
'average_rating' => $media->fresh()->average_rating,
'your_rating' => $rating->stars
]);
}
public function storeComment(Request $request, $mediaId)
{
$request->validate([
'content' => 'required|string|max:1000'
]);
$media = Media::findOrFail($mediaId);
$comment = $media->comments()->create([
'user_id' => auth()->id(),
'content' => $request->content
]);
return response()->json([
'message' => 'Comment added',
'comment' => $comment->load('user')
]);
}
public function getComments($mediaId)
{
$media = Media::findOrFail($mediaId);
return response()->json(
$media->comments()
->with('user')
->latest()
->paginate(10)
);
}
// UPDATE media
public function update(Request $request, $id)
{
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
protected $fillable = [
'user_id',
'media_id',
'content',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function media()
{
return $this->belongsTo(Media::class);
}
}
+27 -2
View File
@@ -19,7 +19,10 @@ class Media extends Model
'visibility',
'is_premium'
];
protected $appends = [
'average_rating',
'user_rating',
];
public function image()
{
return $this->belongsTo(Image::class);
@@ -65,5 +68,27 @@ public function getIsSavedAttribute()
->where('user_id', auth()->id())
->exists();
}
public function ratings()
{
return $this->hasMany(Rating::class);
}
public function getAverageRatingAttribute()
{
return round($this->ratings()->avg('stars'), 1);
}
public function getUserRatingAttribute()
{
if (!auth()->check()) return null;
return $this->ratings()
->where('user_id', auth()->id())
->value('stars');
}
public function comments()
{
return $this->hasMany(Comment::class);
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Rating extends Model
{
protected $fillable = [
'user_id',
'media_id',
'stars',
];
public function media()
{
return $this->belongsTo(Media::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}