This commit is contained in:
2026-06-13 17:20:42 +03:30
parent 12fc305045
commit 3a2a27be98
5 changed files with 98 additions and 24 deletions
@@ -0,0 +1,76 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class InteractionController extends Controller
{
/**
* Comment and/or rate an item in a single request.
* Body: { content?: string, stars?: int (1-5) }
* - content adds a comment
* - stars sets/updates this user's rating
* At least one is required.
*/
public function store(Request $request, $type, $id)
{
$data = $request->validate([
'content' => 'nullable|string|max:1000',
'stars' => 'nullable|integer|min:1|max:5',
]);
if (!$request->filled('content') && !$request->filled('stars')) {
throw ValidationException::withMessages([
'content' => ['Provide a comment (content) and/or a rating (stars).'],
]);
}
$model = $this->getModel($type, $id);
if (!$model) {
return response()->json(['message' => 'Item not found'], 404);
}
$comment = null;
if ($request->filled('content')) {
$comment = $model->comments()->create([
'user_id' => auth()->id(),
'content' => $data['content'],
])->load('user');
}
$rating = null;
if ($request->filled('stars')) {
$rating = $model->ratings()->updateOrCreate(
['user_id' => auth()->id()],
['stars' => $data['stars']]
);
}
$model = $model->fresh();
return response()->json([
'message' => 'Interaction saved successfully',
'comment' => $comment,
'your_rating' => $rating?->stars,
'average_rating' => $model->average_rating,
'ratings_count' => $model->ratings_count,
'comments_count' => $model->comments_count,
]);
}
private function getModel($type, $id)
{
// media, music and playlist all support comments + ratings.
$models = [
'music' => \App\Models\Music::class,
'media' => \App\Models\Media::class,
'playlist' => \App\Models\MusicPlaylist::class,
];
$class = $models[$type] ?? null;
return $class ? $class::find($id) : null;
}
}
+14 -13
View File
@@ -666,26 +666,27 @@ public function destroy($id)
return response()->json(['message' => 'Media deleted']);
}
// SAVE media
// SAVE media — uses the shared saved_items system (HasSaves), same as /saves/*.
public function toggleSaveMedia($id)
{
$user = auth()->user();
$media = Media::findOrFail($id);
if ($user->savedMedia()->where('media_id', $id)->exists()) {
// already saved → unsave
$user->savedMedia()->detach($id);
return response()->json(['message' => 'Unsaved!']);
} else {
// not saved → save
$user->savedMedia()->attach($id);
return response()->json(['message' => 'Saved!']);
}
$media->toggleSaveStatus();
return response()->json([
'message' => $media->is_saved ? 'Saved!' : 'Unsaved!',
'is_saved' => $media->is_saved,
'saved_count' => $media->saved_count,
]);
}
// GET saved
// GET saved — media the user saved via saved_items.
public function saved()
{
return auth()->user()->savedMedia()->with(['image','detailImage','categories', 'subCategories', 'myNote' , 'tags'])->get();
return Media::whereHas('saves', fn ($q) => $q->where('user_id', auth()->id()))
->with(['image','detailImage','categories', 'subCategories', 'myNote' , 'tags'])
->latest()
->get();
}
// RECORD a play for the current user (feeds popular + recently played).