@@ -5,26 +5,36 @@ import { platforms, pricings, difficulties } from "@/Helpers/labels";
55import InputText from " primevue/inputtext" ;
66import MultiSelect from " primevue/multiselect" ;
77import Button from " primevue/button" ;
8+ import Rating from " primevue/rating" ;
89
910import TagSelector from " @/Components/Form/TagSelector.vue" ;
1011
12+ // text filters
1113const name = ref (" " );
1214const description = ref (" " );
15+
16+ // multi-select filters
1317const selectedPlatforms = ref ([]);
1418const selectedDifficulty = ref ([]);
1519const selectedPricing = ref ([]);
1620const selectedTopics = ref ([]);
1721const selectedProgrammingLanguages = ref ([]);
1822const selectedGeneralTags = ref ([]);
1923
24+ // rating filters
25+ const selectedCommunityRating = ref (null );
26+ const selectedTeachingClarity = ref (null );
27+ const selectedEngagement = ref (null );
28+ const selectedPracticality = ref (null );
29+ const selectedUserFriendliness = ref (null );
30+ const selectedUpdates = ref (null );
31+
2032onMounted (() => {
2133 const urlParams = new URLSearchParams (window .location .search );
2234
23- // single‐value fields
2435 name .value = urlParams .get (" name" ) || " " ;
2536 description .value = urlParams .get (" description" ) || " " ;
2637
27- // multi‐value fields that may be named like difficulty[0], difficulty[1], …
2838 selectedPlatforms .value = extractIndexedArray (urlParams, " platforms" );
2939 selectedDifficulty .value = extractIndexedArray (urlParams, " difficulty" );
3040 selectedPricing .value = extractIndexedArray (urlParams, " pricing" );
@@ -34,11 +44,21 @@ onMounted(() => {
3444 " programming_languages"
3545 );
3646 selectedGeneralTags .value = extractIndexedArray (urlParams, " general_tags" );
47+
48+ const ratingsMap = {
49+ community_rating: selectedCommunityRating,
50+ teaching_clarity: selectedTeachingClarity,
51+ engagement: selectedEngagement,
52+ practicality: selectedPracticality,
53+ user_friendliness: selectedUserFriendliness,
54+ updates: selectedUpdates,
55+ };
56+ for (const [param , refVar ] of Object .entries (ratingsMap)) {
57+ const v = urlParams .get (param);
58+ refVar .value = v ? parseInt (v, 10 ) : null ;
59+ }
3760});
3861
39- /**
40- * Pulls out all params named `${base}[0]`, `${base}[1]`, … into a flat array.
41- */
4262function extractIndexedArray (urlParams , base ) {
4363 const result = [];
4464 for (const [key , value ] of urlParams) {
@@ -72,11 +92,38 @@ function search() {
7292 general_tags: selectedGeneralTags .value .length
7393 ? selectedGeneralTags .value
7494 : undefined ,
75- community_rating: 1 ,
95+ community_rating: selectedCommunityRating .value || undefined ,
96+ teaching_clarity: selectedTeachingClarity .value || undefined ,
97+ engagement: selectedEngagement .value || undefined ,
98+ practicality: selectedPracticality .value || undefined ,
99+ user_friendliness: selectedUserFriendliness .value || undefined ,
100+ updates: selectedUpdates .value || undefined ,
76101 }),
77102 { preserveScroll: true }
78103 );
79104}
105+
106+ function resetFilters () {
107+ // text
108+ name .value = " " ;
109+ description .value = " " ;
110+
111+ // arrays
112+ selectedPlatforms .value = [];
113+ selectedDifficulty .value = [];
114+ selectedPricing .value = [];
115+ selectedTopics .value = [];
116+ selectedProgrammingLanguages .value = [];
117+ selectedGeneralTags .value = [];
118+
119+ // ratings
120+ selectedCommunityRating .value = null ;
121+ selectedTeachingClarity .value = null ;
122+ selectedEngagement .value = null ;
123+ selectedPracticality .value = null ;
124+ selectedUserFriendliness .value = null ;
125+ selectedUpdates .value = null ;
126+ }
80127 </script >
81128
82129<template >
@@ -141,26 +188,108 @@ function search() {
141188 />
142189 </div >
143190
191+ <!-- Topics -->
192+ <div class =" flex-1 min-w-[200px]" >
193+ <label class =" block text-sm font-medium mb-1" >Topics</label >
194+ <TagSelector v-model =" selectedTopics" />
195+ </div >
196+
197+ <!-- Programming Languages -->
198+ <div class =" flex-1 min-w-[200px]" >
199+ <label class =" block text-sm font-medium mb-1"
200+ >Programming Languages</label
201+ >
202+ <TagSelector v-model =" selectedProgrammingLanguages" />
203+ </div >
204+
205+ <!-- Other Tags -->
144206 <div class =" flex-1 min-w-[200px]" >
145- <label class =" block text-sm font-medium mb-1" >Topics:</label >
146- <TagSelector
147- v-model =" selectedTopics" />
207+ <label class =" block text-sm font-medium mb-1" >Other Tags</label >
208+ <TagSelector v-model =" selectedGeneralTags" />
148209 </div >
149210
211+ <!-- Star-rating filters -->
150212 <div class =" flex-1 min-w-[200px]" >
151- <label class =" block text-sm font-medium mb-1" >Programming Languages:</label >
152- <TagSelector
153- v-model =" selectedProgrammingLanguages" />
213+ <label class =" block text-sm font-medium mb-1"
214+ >Min. Community Rating</label
215+ >
216+ <Rating
217+ v-model =" selectedCommunityRating"
218+ :stars =" 4"
219+ cancel
220+ class =" text-yellow-400"
221+ />
154222 </div >
155223
156224 <div class =" flex-1 min-w-[200px]" >
157- <label class =" block text-sm font-medium mb-1" >Other Tags:</label >
158- <TagSelector
159- v-model =" selectedGeneralTags" />
225+ <label class =" block text-sm font-medium mb-1"
226+ >Min. Teaching Clarity</label
227+ >
228+ <Rating
229+ v-model =" selectedTeachingClarity"
230+ :stars =" 4"
231+ cancel
232+ class =" text-yellow-400"
233+ />
160234 </div >
161235
162- <!-- Search Button -->
163- <div class =" flex items-end" >
236+ <div class =" flex-1 min-w-[200px]" >
237+ <label class =" block text-sm font-medium mb-1"
238+ >Min. Engagement</label
239+ >
240+ <Rating
241+ v-model =" selectedEngagement"
242+ :stars =" 4"
243+ cancel
244+ class =" text-yellow-400"
245+ />
246+ </div >
247+
248+ <div class =" flex-1 min-w-[200px]" >
249+ <label class =" block text-sm font-medium mb-1"
250+ >Min. Practicality</label
251+ >
252+ <Rating
253+ v-model =" selectedPracticality"
254+ :stars =" 4"
255+ cancel
256+ class =" text-yellow-400"
257+ />
258+ </div >
259+
260+ <div class =" flex-1 min-w-[200px]" >
261+ <label class =" block text-sm font-medium mb-1"
262+ >Min. User Friendliness</label
263+ >
264+ <Rating
265+ v-model =" selectedUserFriendliness"
266+ :stars =" 4"
267+ cancel
268+ class =" text-yellow-400"
269+ />
270+ </div >
271+
272+ <div class =" flex-1 min-w-[200px]" >
273+ <label class =" block text-sm font-medium mb-1"
274+ >Min. Updates</label
275+ >
276+ <Rating
277+ v-model =" selectedUpdates"
278+ :stars =" 4"
279+ cancel
280+ class =" text-yellow-400"
281+ />
282+ </div >
283+
284+ <!-- Action Buttons -->
285+ <div class =" flex items-end gap-5" >
286+ <Button
287+ label =" Reset"
288+ icon =" pi pi-refresh"
289+ type =" button"
290+ class =" p-button-secondary"
291+ @click =" resetFilters"
292+ />
164293 <Button label =" Filter" icon =" pi pi-search" type =" submit" />
165294 </div >
166295 </div >
0 commit comments