feat: user rating and comment

This commit is contained in:
2026-05-20 15:52:28 +03:30
parent 02448db346
commit d0d48866f0
7 changed files with 171 additions and 19 deletions
+38 -10
View File
@@ -319,9 +319,18 @@ public function filters(Request $request)
]); ]);
} }
public function show($id) public function show($id)
{ {
$media = Media::with(['image', 'category', 'myNote', 'tags']) $media = Media::with([
'image',
'category',
'myNote',
'tags',
'comments' => function($query) {
$query->with('user')->latest()->limit(10);
},
'ratings'
])
->where('id', $id) ->where('id', $id)
->where(function($query) { ->where(function($query) {
$query->where('visibility', 'public') $query->where('visibility', 'public')
@@ -329,7 +338,16 @@ public function show($id)
}) })
->firstOrFail(); ->firstOrFail();
return response()->json([ // Get user's specific comment
$userComment = $media->userComment();
// Get paginated comments
$comments = $media->comments()
->with('user')
->latest()
->paginate(15);
return response()->json([
'id' => $media->id, 'id' => $media->id,
'title' => $media->title, 'title' => $media->title,
'caption' => $media->caption, 'caption' => $media->caption,
@@ -340,18 +358,28 @@ public function show($id)
'visibility' => $media->visibility, 'visibility' => $media->visibility,
'created_at' => $media->created_at, 'created_at' => $media->created_at,
'updated_at' => $media->updated_at, 'updated_at' => $media->updated_at,
'is_premium' => $media->is_premium,
'image' => $media->image, 'image' => $media->image,
'category' => $media->category, 'category' => $media->category,
'tags' => $media->tags, 'tags' => $media->tags,
'myNote' => $media->myNote, 'myNote' => $media->myNote,
'is_saved' => $media->is_saved, 'is_saved' => $media->is_saved,
'is_premium' => $media->is_premium, 'statistics' => [
'comments' => $media->comments, 'average_rating' => $media->average_rating,
'average_rating' => $media->average_rating, 'total_ratings' => $media->ratings_count,
'user_rating' => $media->user_rating, 'total_comments' => $media->comments_count,
'comments_count' => $media->comments()->count(), 'rating_distribution' => $media->rating_distribution,
],
'user_interaction' => [
'has_rated' => $media->has_user_rated,
'user_rating' => $media->user_rating,
'has_commented' => $media->has_user_commented,
'user_comment' => $media->user_comment,
'user_comment_id' => $media->user_comment_id,
],
'comments' => $comments,
]); ]);
} }
public function rate(Request $request, $mediaId) public function rate(Request $request, $mediaId)
{ {
$request->validate([ $request->validate([
+37 -4
View File
@@ -223,11 +223,19 @@ public function update(Request $request, $id)
// ✅ Get all public + user private music // ✅ Get all public + user private music
public function show($id) public function show($id)
{ {
$userId = auth()->id(); $userId = auth()->id();
$music = Music::with(['image', 'playlist', 'tags']) $music = Music::with([
'image',
'playlist',
'tags',
'comments' => function($query) {
$query->with('user')->latest()->limit(10);
},
'ratings'
])
->where(function($query) use ($userId) { ->where(function($query) use ($userId) {
$query->where('type', 'public') $query->where('type', 'public')
->orWhere(function($q) use ($userId) { ->orWhere(function($q) use ($userId) {
@@ -236,8 +244,33 @@ public function show($id)
}); });
}) })
->findOrFail($id); ->findOrFail($id);
return response()->json($music); // Get user's specific comment
$userComment = $music->userComment();
// Get paginated comments for the response
$comments = $music->comments()
->with('user')
->latest()
->paginate(15);
return response()->json([
'music' => $music,
'statistics' => [
'average_rating' => $music->average_rating,
'total_ratings' => $music->ratings_count,
'total_comments' => $music->comments_count,
'rating_distribution' => $music->rating_distribution,
],
'user_interaction' => [
'has_rated' => $music->has_user_rated,
'user_rating' => $music->user_rating,
'has_commented' => $music->has_user_commented,
'user_comment' => $music->user_comment,
'user_comment_id' => $music->user_comment_id,
],
'comments' => $comments,
]);
} }
// ✅ Delete music // ✅ Delete music
+15 -1
View File
@@ -12,7 +12,7 @@ class Comment extends Model
'commentable_type', 'commentable_type',
'content', 'content',
]; ];
protected $with = ['user'];
public function user() public function user()
{ {
return $this->belongsTo(User::class); return $this->belongsTo(User::class);
@@ -34,4 +34,18 @@ public function music()
{ {
return $this->belongsTo(Music::class, 'commentable_id')->where('commentable_type', Music::class); return $this->belongsTo(Music::class, 'commentable_id')->where('commentable_type', Music::class);
} }
// Check if comment belongs to current user
public function getIsOwnerAttribute()
{
return auth()->check() && $this->user_id === auth()->id();
}
// Add timestamps formatted
public function getFormattedCreatedAtAttribute()
{
return $this->created_at->diffForHumans();
}
protected $appends = ['is_owner', 'formatted_created_at'];
} }
+5 -1
View File
@@ -25,7 +25,11 @@ class Media extends Model
'average_rating', 'average_rating',
'user_rating', 'user_rating',
'ratings_count', 'ratings_count',
'comments_count' 'comments_count',
'has_user_commented', // Add this
'user_comment', // Add this
'user_comment_id', // Add this
'has_user_rated' // Add this
]; ];
public function image() public function image()
{ {
+5 -1
View File
@@ -43,7 +43,11 @@ public function tags(): BelongsToMany
return $this->belongsToMany(Tag::class, 'music_tags'); return $this->belongsToMany(Tag::class, 'music_tags');
} }
protected $appends = ['url', 'image_url' , 'average_rating', 'user_rating', 'comments_count']; protected $appends = ['url', 'image_url' , 'average_rating', 'user_rating', 'comments_count' , 'has_user_commented', // Add this
'user_comment', // Add this
'user_comment_id', // Add this
'has_user_rated' // Add this];
];
public function getUrlAttribute() public function getUrlAttribute()
{ {
+46 -2
View File
@@ -10,11 +10,55 @@ public function comments()
{ {
return $this->morphMany(Comment::class, 'commentable'); return $this->morphMany(Comment::class, 'commentable');
} }
// Get user's specific comment
public function userComment()
{
if (!auth()->check()) return null;
return $this->comments()
->where('user_id', auth()->id())
->first();
}
// Check if user has commented
public function getHasUserCommentedAttribute()
{
return !is_null($this->userComment());
}
// Get user's comment content
public function getUserCommentAttribute()
{
$comment = $this->userComment();
return $comment ? $comment->content : null;
}
// Get user's comment id
public function getUserCommentIdAttribute()
{
$comment = $this->userComment();
return $comment ? $comment->id : null;
}
// Get latest comments with user info
public function getLatestCommentsAttribute() public function getLatestCommentsAttribute()
{ {
return $this->comments()->latest()->limit(5)->get(); return $this->comments()
->with('user')
->latest()
->limit(10)
->get();
} }
// Get paginated comments
public function getPaginatedComments($perPage = 15)
{
return $this->comments()
->with('user')
->latest()
->paginate($perPage);
}
public function getCommentsCountAttribute() public function getCommentsCountAttribute()
{ {
+25
View File
@@ -24,9 +24,34 @@ public function getUserRatingAttribute()
->where('user_id', auth()->id()) ->where('user_id', auth()->id())
->value('stars'); ->value('stars');
} }
// Get user's rating object
public function userRating()
{
if (!auth()->check()) return null;
return $this->ratings()
->where('user_id', auth()->id())
->first();
}
// Check if user has rated
public function getHasUserRatedAttribute()
{
return !is_null($this->userRating());
}
public function getRatingsCountAttribute() public function getRatingsCountAttribute()
{ {
return $this->ratings()->count(); return $this->ratings()->count();
} }
// Get rating distribution
public function getRatingDistributionAttribute()
{
$distribution = [];
for ($i = 1; $i <= 5; $i++) {
$distribution[$i] = $this->ratings()->where('stars', $i)->count();
}
return $distribution;
}
} }