fix
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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).
|
||||
|
||||
+2
-10
@@ -89,14 +89,6 @@ public function getUrlAttribute()
|
||||
|
||||
return $this->external_url;
|
||||
}
|
||||
|
||||
|
||||
public function getIsSavedAttribute()
|
||||
{
|
||||
if (!auth()->check()) return false;
|
||||
|
||||
return $this->savedBy()
|
||||
->where('user_id', auth()->id())
|
||||
->exists();
|
||||
}
|
||||
// is_saved / saved_count come from the HasSaves trait (saved_items table),
|
||||
// so the /saves/* endpoints and the media list/show all agree.
|
||||
}
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
use App\Traits\HasComments; // Add this
|
||||
use App\Traits\HasLikes;
|
||||
use App\Traits\HasSaves;
|
||||
use App\Traits\HasRatings;
|
||||
class MusicPlaylist extends Model
|
||||
{
|
||||
use HasComments, HasLikes, HasSaves;
|
||||
use HasComments, HasLikes, HasSaves, HasRatings;
|
||||
protected $table = 'music_playlists';
|
||||
|
||||
protected $fillable = [
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
use App\Http\Controllers\MusicSubcategoryController;
|
||||
use App\Http\Controllers\SaveController;
|
||||
use App\Http\Controllers\LikeController;
|
||||
use App\Http\Controllers\InteractionController;
|
||||
|
||||
Route::get('/test-hash', function() {
|
||||
$plain = 'amnk1380';
|
||||
@@ -312,6 +313,9 @@
|
||||
});
|
||||
|
||||
|
||||
// Combined comment + like in one request (music / media / playlist)
|
||||
Route::post('interactions/{type}/{id}', [InteractionController::class, 'store']);
|
||||
|
||||
// Like routes (only for music and media)
|
||||
Route::prefix('likes')->group(function () {
|
||||
Route::post('/like', [LikeController::class, 'like']);
|
||||
|
||||
Reference in New Issue
Block a user