Skip to content

Commit 1c4ae53

Browse files
committed
Add searchable category inputs for filter and add-resource flow
1 parent bf4e676 commit 1c4ae53

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

frontend/src/app/components/resources/resources.component.html

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,18 @@ <h2 class="text-lg font-semibold text-white">Search & filter resources</h2>
6161
</label>
6262

6363
<label>
64-
<span class="sr-only">Filter by category</span>
65-
<select [ngModel]="selectedCategoryFilter()" (ngModelChange)="onCategoryFilterChange($event)"
66-
class="w-full rounded-lg border border-gray-700 bg-[#0B0E14] px-3 py-2.5 text-sm focus:outline-none focus:border-indigo-500">
64+
<span class="sr-only">Search by category</span>
65+
<div class="relative">
66+
<i class="ph ph-funnel absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"></i>
67+
<input [ngModel]="selectedCategoryFilter()" (ngModelChange)="onCategoryFilterChange($event)" list="resource-category-filter-list"
68+
placeholder="All categories (type to search)"
69+
class="w-full rounded-lg border border-gray-700 bg-[#0B0E14] pl-10 pr-3 py-2.5 text-sm focus:outline-none focus:border-indigo-500" />
70+
</div>
71+
<datalist id="resource-category-filter-list">
6772
@for (categoryOption of categoryOptions(); track categoryOption) {
6873
<option [value]="categoryOption">{{ categoryOption === 'all' ? 'All categories' : categoryOption }}</option>
6974
}
70-
</select>
75+
</datalist>
7176
</label>
7277

7378
<label>
@@ -180,9 +185,16 @@ <h2 class="text-lg sm:text-xl font-bold text-white">Add a resource</h2>
180185
<div class="grid gap-3 sm:gap-4 md:grid-cols-2">
181186
<input [(ngModel)]="title" type="text" placeholder="Resource title"
182187
class="w-full rounded-lg border border-gray-700 bg-[#0B0E14] px-3 py-2.5 text-sm focus:outline-none focus:border-indigo-500" />
183-
<input [(ngModel)]="category" type="text" placeholder="Category (e.g., DSA, Resume, Sheets)"
188+
<input [(ngModel)]="category" type="text" list="resource-category-add-list" placeholder="Choose category"
184189
class="w-full rounded-lg border border-gray-700 bg-[#0B0E14] px-3 py-2.5 text-sm focus:outline-none focus:border-indigo-500" />
185190
</div>
191+
<datalist id="resource-category-add-list">
192+
@for (categoryOption of categoryOptions(); track categoryOption) {
193+
@if (categoryOption !== 'all') {
194+
<option [value]="categoryOption"></option>
195+
}
196+
}
197+
</datalist>
186198

187199
@if (contributionMode === 'link') {
188200
<input [(ngModel)]="url" type="url" placeholder="https://..."

frontend/src/app/components/resources/resources.component.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ import { LogoComponent } from '../ui/logo/logo.component';
99

1010
const PAGE_SIZE = 20;
1111
const MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
12+
const DEFAULT_RESOURCE_CATEGORIES = [
13+
'DSA',
14+
'Resume',
15+
'System Design',
16+
'Interview Prep',
17+
'Job Boards',
18+
'Roadmaps',
19+
'Mock Interviews',
20+
'Portfolio'
21+
];
1222

1323
type ResourceTypeFilter = 'all' | 'LINK' | 'FILE';
1424

@@ -49,6 +59,9 @@ export class ResourcesComponent {
4959

5060
readonly categoryOptions = computed(() => {
5161
const categories = new Set<string>();
62+
for (const category of DEFAULT_RESOURCE_CATEGORIES) {
63+
categories.add(category);
64+
}
5265
for (const resource of this.resources()) {
5366
categories.add(resource.category?.trim() || 'General');
5467
}
@@ -69,7 +82,9 @@ export class ResourcesComponent {
6982
resource.submittedByName.toLowerCase().includes(normalizedQuery);
7083

7184
const resourceCategory = resource.category?.trim() || 'General';
72-
const matchesCategory = categoryFilter === 'all' || resourceCategory === categoryFilter;
85+
const matchesCategory =
86+
categoryFilter === 'all' ||
87+
resourceCategory.toLowerCase().includes(categoryFilter.toLowerCase());
7388
const matchesType = typeFilter === 'all' || resource.resourceType === typeFilter;
7489

7590
return matchesQuery && matchesCategory && matchesType;
@@ -81,7 +96,8 @@ export class ResourcesComponent {
8196
}
8297

8398
onCategoryFilterChange(value: string) {
84-
this.selectedCategoryFilter.set(value);
99+
const normalized = value.trim();
100+
this.selectedCategoryFilter.set(normalized ? normalized : 'all');
85101
}
86102

87103
onTypeFilterChange(value: ResourceTypeFilter) {

0 commit comments

Comments
 (0)