withCount(['media' => fn ($q) => $q->where('is_deeplink_only', false)]); $categoryId = $categoryId ?? $request->input('category_id'); if ($request->boolean('deeplink_only')) { $query->where('is_deeplink_only', true); } else { $query->where('is_deeplink_only', false); } if ($categoryId) { $query->where('category_id', $categoryId); } return response()->json( $query->orderBy('name')->get() ); } public function store(Request $request) { $data = $request->validate([ 'category_id' => 'required|exists:categories,id', 'name' => 'required|string|max:255', 'description' => 'nullable|string', 'is_deeplink_only' => 'nullable|boolean', ]); $existing = SubCategory::where('category_id', $data['category_id']) ->where('name', $data['name']) ->first(); if ($existing) { return response()->json([ 'message' => 'A subcategory with this name already exists in this category', 'errors' => ['name' => ['The subcategory name must be unique within this category.']], ], 422); } $data['is_deeplink_only'] = $data['is_deeplink_only'] ?? false; $subCategory = SubCategory::create($data); return response()->json([ 'message' => 'Subcategory created successfully', 'sub_category' => $subCategory->load('category'), ], 201); } public function show($id) { $subCategory = SubCategory::with('category')->withCount(['media' => fn ($q) => $q->where('is_deeplink_only', false)])->findOrFail($id); return response()->json($subCategory); } // Public (no auth) deep link lookup by ID. Serves any subcategory — hidden // (deeplink-only) ones included — so https://aramejan.com/subcategory/{id} // resolves for every shareable subcategory. A visible subcategory only lists // its visible media; inside a hidden one everything is shown, since the deep // link is the only way in. public function publicShow($id) { $subCategory = SubCategory::with('category')->findOrFail($id); $includeHiddenMedia = (bool) $subCategory->is_deeplink_only; $mediaQuery = $subCategory->media() ->with(['image', 'detailImage', 'tags']) ->latest(); if (! $includeHiddenMedia) { $mediaQuery->where('is_deeplink_only', false); } return response()->json([ 'sub_category' => [ 'id' => $subCategory->id, 'name' => $subCategory->name, 'description' => $subCategory->description, 'category_id' => $subCategory->category_id, 'category' => $subCategory->category, 'is_deeplink_only' => $subCategory->is_deeplink_only, 'deep_link' => $subCategory->deep_link, ], 'medias' => $mediaQuery->get(), ]); } public function update(Request $request, $id) { $subCategory = SubCategory::findOrFail($id); $data = $request->validate([ 'category_id' => 'sometimes|exists:categories,id', 'name' => 'sometimes|string|max:255', 'description' => 'nullable|string', 'is_deeplink_only' => 'nullable|boolean', ]); $categoryId = $data['category_id'] ?? $subCategory->category_id; $name = $data['name'] ?? $subCategory->name; $existing = SubCategory::where('category_id', $categoryId) ->where('name', $name) ->where('id', '!=', $subCategory->id) ->first(); if ($existing) { return response()->json([ 'message' => 'A subcategory with this name already exists in this category', 'errors' => ['name' => ['The subcategory name must be unique within this category.']], ], 422); } if (array_key_exists('is_deeplink_only', $data)) { $subCategory->is_deeplink_only = $data['is_deeplink_only']; } $subCategory->update($data); return response()->json([ 'message' => 'Subcategory updated successfully', 'sub_category' => $subCategory->load('category'), ]); } public function destroy($id) { $subCategory = SubCategory::findOrFail($id); $subCategory->delete(); return response()->json(['message' => 'Subcategory deleted successfully']); } }