function($q) { $q->where('is_active', true)->orderBy('order'); }])->where('is_active', true)->orderBy('order')->get(); return response()->json($categories); } public function store(Request $request) { try { $data = $request->validate([ 'name' => 'required|string|max:255', 'description' => 'nullable|string', 'image_id' => 'nullable|exists:images,id', 'order' => 'nullable|integer', 'is_active' => 'nullable|boolean', ]); // Check for duplicate name $slug = Str::slug($data['name']); $existingCategory = MusicCategory::where('slug', $slug)->first(); if ($existingCategory) { return response()->json([ 'message' => 'A category with this name already exists', 'errors' => [ 'name' => ['The category name "' . $data['name'] . '" is already taken. Please use a different name.'] ] ], 422); } // Optional: Check for duplicate name with case-insensitive comparison $existingName = MusicCategory::whereRaw('LOWER(name) = ?', [strtolower($data['name'])])->first(); if ($existingName) { return response()->json([ 'message' => 'A category with a similar name already exists', 'errors' => [ 'name' => ['Category "' . $existingName->name . '" already exists. Please use a different name.'] ] ], 422); } $data['slug'] = $slug; $category = MusicCategory::create($data); return response()->json([ 'message' => 'Category created successfully', 'category' => $category->load('image') ], 201); } catch (\Illuminate\Database\QueryException $e) { // Handle database duplicate entry error (if unique constraint exists) if ($e->errorInfo[1] == 1062) { // MySQL duplicate entry error code return response()->json([ 'message' => 'A category with this name already exists', 'errors' => [ 'name' => ['The category name must be unique.'] ] ], 422); } return response()->json([ 'message' => 'An error occurred while creating the category', 'error' => $e->getMessage() ], 500); } } public function show($id) { $category = MusicCategory::with(['image', 'playlists' => function($q) { $q->with(['image', 'musics' => function($q2) { $q2->where('music.is_active', true)->with('image')->orderBy('music_playlist.order'); }])->where('is_active', true)->orderBy('order'); }])->findOrFail($id); return response()->json($category); } // Category with each of its sub-categories and that sub-category's playlists. public function grouped($id) { $category = MusicCategory::with([ 'image', 'subcategories' => function ($q) { $q->orderBy('order')->with([ 'image', 'playlists' => function ($p) { $p->where('is_active', true)->with('image')->orderBy('order'); }, ]); }, ])->findOrFail($id); return response()->json([ 'category' => [ 'id' => $category->id, 'title' => $category->name, 'description' => $category->description, 'image_url' => $category->image?->url, 'type' => 'playlist', ], 'sub_categories' => $category->subcategories->map(fn ($sub) => [ 'sub_category' => [ 'id' => $sub->id, 'title' => $sub->name, 'description' => $sub->description, 'image_url' => $sub->image?->url, ], 'playlists' => $sub->playlists, ])->values(), ]); } public function update(Request $request, $id) { $category = MusicCategory::findOrFail($id); $data = $request->validate([ 'name' => 'sometimes|string|max:255', 'description' => 'nullable|string', 'image_id' => 'nullable|exists:images,id', 'order' => 'nullable|integer', 'is_active' => 'nullable|boolean', ]); if (isset($data['name'])) { $data['slug'] = Str::slug($data['name']); } $category->update($data); return response()->json([ 'message' => 'Category updated successfully', 'category' => $category->load('image') ]); } public function destroy($id) { $category = MusicCategory::findOrFail($id); $category->delete(); return response()->json(['message' => 'Category deleted successfully']); } }