feat: route filter & improve search

This commit is contained in:
2026-02-25 17:39:22 +03:30
parent 40f3db00ba
commit 4d0823ef86
2 changed files with 151 additions and 18 deletions
+149 -17
View File
@@ -5,7 +5,7 @@
use App\Models\Media; use App\Models\Media;
use App\Models\Category; use App\Models\Category;
use App\Models\Tag; use App\Models\Tag;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
@@ -75,45 +75,177 @@ public function store(Request $request)
public function index(Request $request) public function index(Request $request)
{ {
$query = Media::with(['image', 'category', 'myNote', 'tags']) $query = Media::with(['image', 'category', 'myNote', 'tags'])
->where(function($q) { ->where(function ($q) {
$q->where('visibility', 'public') $q->where('visibility', 'public')
->orWhere('user_id', auth()->id()); ->orWhere('user_id', auth()->id());
}); });
if ($request->filled('category')) {
$query->where('category_id', $request->category); /*
|--------------------------------------------------------------------------
| 1️⃣ Multi Category
|--------------------------------------------------------------------------
*/
if ($request->filled('categories')) {
$categories = explode(',', $request->categories);
$query->whereIn('category_id', $categories);
} }
/*
|--------------------------------------------------------------------------
| 2️⃣ Multi Duration Ranges
|--------------------------------------------------------------------------
| duration stored in minutes (integer)
|--------------------------------------------------------------------------
*/
if ($request->filled('durations')) {
$ranges = explode(',', $request->durations);
$query->where(function ($q) use ($ranges) {
foreach ($ranges as $range) {
if ($range === '1-2') {
$q->orWhereBetween('duration', [1, 2]);
}
if ($range === '2-5') {
$q->orWhereBetween('duration', [3, 5]);
}
if ($range === '5-10') {
$q->orWhereBetween('duration', [6, 10]);
}
if ($range === '10-30') {
$q->orWhereBetween('duration', [10, 30]);
}
if ($range === '30-60') {
$q->orWhereBetween('duration', [30, 60]);
}
if ($range === '60-120') {
$q->orWhereBetween('duration', [60, 120]);
}
if ($range === 'other') {
$q->orWhere('duration', '>', 120);
}
}
});
}
/*
|--------------------------------------------------------------------------
| 3️⃣ Tags
|--------------------------------------------------------------------------
*/
if ($request->filled('tags')) { if ($request->filled('tags')) {
$tags = explode(',', $request->tags); $tags = explode(',', $request->tags);
$query->whereHas('tags', function($q) use ($tags) { $query->whereHas('tags', function ($q) use ($tags) {
$q->whereIn('name', $tags); $q->whereIn('name', $tags);
}); });
} }
/*
|--------------------------------------------------------------------------
| 4️⃣ Search
|--------------------------------------------------------------------------
*/
if ($request->filled('search')) { if ($request->filled('search')) {
$search = $request->search; $search = $request->search;
$query->where(function($q) use ($search) { $query->where(function ($q) use ($search) {
// title & caption
$q->where('title', 'LIKE', "%$search%") $q->where('title', 'LIKE', "%$search%")
->orWhere('caption', 'LIKE', "%$search%") ->orWhere('caption', 'LIKE', "%$search%")
->orWhereHas('category', function ($c) use ($search) {
$c->where('name', 'LIKE', "%$search%");
})
->orWhereHas('tags', function ($t) use ($search) {
$t->where('name', 'LIKE', "%$search%");
});
// category (join)
->orWhereHas('category', function($c) use ($search) {
$c->where('name', 'LIKE', "%$search%");
})
// tags
->orWhereHas('tags', function($t) use ($search) {
$t->where('name', 'LIKE', "%$search%");
});
}); });
} }
return response()->json( return response()->json(
$query->orderBy('created_at', 'desc')->get() $query->orderBy('created_at', 'desc')->get()
); );
} }
public function filters(Request $request)
{
$baseQuery = Media::query()
->where(function ($q) {
$q->where('visibility', 'public')
->orWhere('user_id', auth()->id());
});
/*
|--------------------------------------------------------------------------
| 1️⃣ Categories with media count
|--------------------------------------------------------------------------
*/
$categories = Category::select(
'categories.id',
'categories.name',
DB::raw('COUNT(media.id) as media_count')
)
->leftJoin('media', function ($join) {
$join->on('categories.id', '=', 'media.category_id')
->where(function ($q) {
$q->where('media.visibility', 'public')
->orWhere('media.user_id', auth()->id());
});
})
->groupBy('categories.id', 'categories.name')
->orderByDesc('media_count')
->get();
/*
|--------------------------------------------------------------------------
| 2️⃣ Duration ranges
|--------------------------------------------------------------------------
| duration is stored in seconds
|--------------------------------------------------------------------------
*/
$durations = Media::select(
DB::raw("
CASE
WHEN duration BETWEEN 1 AND 2 THEN '1-2'
WHEN duration BETWEEN 3 AND 5 THEN '2-5'
WHEN duration BETWEEN 5 AND 10 THEN '5-10'
WHEN duration BETWEEN 10 AND 20 THEN '10-20'
WHEN duration BETWEEN 20 AND 30 THEN '20-30'
WHEN duration BETWEEN 60 AND 120 THEN '60-120'
ELSE 'other'
END as duration_range
"),
DB::raw('COUNT(*) as total')
)
->whereNotNull('duration')
->where(function ($q) {
$q->where('visibility', 'public')
->orWhere('user_id', auth()->id());
})
->groupBy('duration_range')
->get();
return response()->json([
'categories' => $categories,
'durations' => $durations,
]);
}
public function show($id) public function show($id)
{ {
$media = Media::with(['image', 'category', 'myNote', 'tags']) $media = Media::with(['image', 'category', 'myNote', 'tags'])
+1
View File
@@ -135,6 +135,7 @@
///media ///media
Route::get('/media/filters', [MediaController::class, 'filters']);
Route::post('/media', [MediaController::class, 'store']); Route::post('/media', [MediaController::class, 'store']);
Route::get('/media', [MediaController::class, 'index']); Route::get('/media', [MediaController::class, 'index']);
Route::post('/media/{id}', [MediaController::class, 'update']); Route::post('/media/{id}', [MediaController::class, 'update']);