Skip to content

Commit dc222ce

Browse files
committed
First filter bar frontend iterations
1 parent 2c29c65 commit dc222ce

3 files changed

Lines changed: 149 additions & 5 deletions

File tree

app/Http/Controllers/ComputerScienceResourceController.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,55 @@ function __construct(CommentService $commentService, UpvoteService $upvoteServic
2828
/**
2929
* Display a listing of the resource.
3030
*/
31-
public function index()
31+
public function index(Request $request)
3232
{
33-
// Eager load topic tags and other tag types as needed
34-
$resources = ComputerScienceResource::with(['tags', 'votes', 'upvoteSummary', 'reviewSummary', 'commentsCountRelationship'])
35-
->paginate(10);
33+
$query = ComputerScienceResource::query();
34+
35+
// Eager load relations
36+
$query->with(['tags', 'votes', 'upvoteSummary', 'reviewSummary', 'commentsCountRelationship']);
37+
38+
// Fulltext search on name
39+
if ($name = $request->query('name')) {
40+
$query->whereFullText('name', $name);
41+
}
42+
43+
// Fulltext search on description
44+
if ($description = $request->query('description')) {
45+
$query->whereFullText('description', $description);
46+
}
47+
48+
// Filter by platforms (array)
49+
if ($platforms = $request->query('platforms')) {
50+
$query->where(function ($q) use ($platforms) {
51+
foreach ((array) $platforms as $platform) {
52+
$q->orWhereRaw('FIND_IN_SET(?, platforms)', [$platform]);
53+
}
54+
});
55+
}
56+
57+
// 5.3.4 - Filter by difficulty
58+
if ($difficulty = $request->query('difficulty')) {
59+
$query->where('difficulty', $difficulty);
60+
}
61+
62+
// 5.3.5 - Filter by pricing
63+
if ($pricing = $request->query('pricing')) {
64+
$query->where('pricing', $pricing);
65+
}
66+
67+
// Optional: Filter by tags (across any tag type)
68+
if ($tags = $request->query('tags')) {
69+
$query->withAnyTags((array) $tags);
70+
}
71+
72+
// Paginate and return
73+
$resources = $query->paginate(10)->appends($request->query());
74+
3675
return Inertia::render('Resources/Index', [
3776
'resources' => $resources,
3877
]);
3978
}
40-
79+
4180
/**
4281
* Show the form for creating a new resource.
4382
*/
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<script setup>
2+
import { ref } from 'vue'
3+
import { usePage, router } from '@inertiajs/vue3'
4+
import { platforms, pricings, difficulties } from '@/Helpers/labels'
5+
import InputText from 'primevue/inputtext'
6+
import Dropdown from 'primevue/dropdown'
7+
import MultiSelect from 'primevue/multiselect'
8+
import Button from 'primevue/button'
9+
10+
// Get current query params
11+
const { url } = usePage()
12+
const query = new URLSearchParams(url.split('?')[1])
13+
14+
// Reactive form fields
15+
const name = ref(query.get('name') || '')
16+
const description = ref(query.get('description') || '')
17+
const selectedPlatforms = ref(query.getAll('platforms') || [])
18+
const selectedDifficulty = ref(query.get('difficulty') || '')
19+
const selectedPricing = ref(query.get('pricing') || '')
20+
21+
function search() {
22+
router.visit(route('resources.index', {
23+
name: name.value || undefined,
24+
description: description.value || undefined,
25+
platforms: selectedPlatforms.value?.length ? selectedPlatforms.value : undefined,
26+
difficulty: selectedDifficulty.value || undefined,
27+
pricing: selectedPricing.value || undefined,
28+
}), {
29+
preserveState: true,
30+
preserveScroll: true,
31+
})
32+
}
33+
</script>
34+
35+
<template>
36+
<div class="p-4 bg-white rounded-xl shadow-md">
37+
<h2 class="text-xl font-semibold mb-4">Search Resources</h2>
38+
39+
<div class="flex flex-wrap gap-4">
40+
<!-- Name -->
41+
<div class="flex-1 min-w-[200px]">
42+
<label class="block text-sm font-medium mb-1">Name</label>
43+
<InputText v-model="name" class="w-full" />
44+
</div>
45+
46+
<!-- Description -->
47+
<div class="flex-1 min-w-[200px]">
48+
<label class="block text-sm font-medium mb-1">Description</label>
49+
<InputText v-model="description" class="w-full" />
50+
</div>
51+
52+
<!-- Platforms -->
53+
<div class="flex-1 min-w-[200px]">
54+
<label class="block text-sm font-medium mb-1">Platforms</label>
55+
<MultiSelect
56+
v-model="selectedPlatforms"
57+
:options="platforms"
58+
optionLabel="label"
59+
optionValue="value"
60+
placeholder="All Platforms"
61+
showClear
62+
class="w-full"
63+
/>
64+
</div>
65+
66+
<!-- Difficulty -->
67+
<div class="flex-1 min-w-[200px]">
68+
<label class="block text-sm font-medium mb-1">Difficulty</label>
69+
<Dropdown
70+
v-model="selectedDifficulty"
71+
:options="difficulties"
72+
optionLabel="label"
73+
optionValue="value"
74+
placeholder="All Difficulties"
75+
showClear
76+
class="w-full"
77+
/>
78+
</div>
79+
80+
<!-- Pricing -->
81+
<div class="flex-1 min-w-[200px]">
82+
<label class="block text-sm font-medium mb-1">Pricing</label>
83+
<Dropdown
84+
v-model="selectedPricing"
85+
:options="pricings"
86+
optionLabel="label"
87+
optionValue="value"
88+
placeholder="All Pricing"
89+
showClear
90+
class="w-full"
91+
/>
92+
</div>
93+
94+
<!-- Search Button -->
95+
<div class="flex items-end">
96+
<Button label="Filter" icon="pi pi-search" @click="search" />
97+
</div>
98+
</div>
99+
</div>
100+
</template>

resources/js/Pages/Resources/Index.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import NewsItem from "@/Components/NewsItem.vue";
55
import AppLayout from "@/Layouts/AppLayout.vue";
66
import { defineProps } from "vue";
77
import PaginateLinks from "@/Components/Pagination/PaginateLinks.vue";
8+
import FilterBar from "@/Components/Resources/FilterBar.vue";
89
910
const props = defineProps({
1011
resources: Object,
@@ -56,7 +57,11 @@ const newsItems = [
5657
<AppLayout title="Computer Science Resources">
5758
<main class="py-12">
5859
<div class="max-w-[110rem] mx-auto sm:px-6 lg:px-10">
60+
<!-- Filter bar -->
61+
<FilterBar></FilterBar>
62+
5963
<div class="flex gap-4">
64+
6065
<!-- Resources Section -->
6166
<section
6267
class="w-3/4 bg-white dark:bg-gray-800 overflow-hidden shadow-xl sm:rounded-lg p-6"

0 commit comments

Comments
 (0)