Skip to content

Commit 4f26111

Browse files
committed
Add filter params to url query params
1 parent 7ecd548 commit 4f26111

File tree

3 files changed

+104
-14
lines changed

3 files changed

+104
-14
lines changed

app/api/profiles/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export async function GET(request: Request) {
1414
const coreValues = url.searchParams.get("coreValues")?.split(",").filter(Boolean) || [];
1515
const causeAreas = url.searchParams.get("causeAreas")?.split(",").filter(Boolean) || [];
1616
const connections = url.searchParams.get("connections")?.split(",").filter(Boolean) || [];
17-
const searchQuery = url.searchParams.get("search") || "";
17+
const searchQuery = url.searchParams.get("searchQuery") || "";
1818

1919
const profilesPerPage = 100;
2020
const offset = (page - 1) * profilesPerPage;
@@ -147,6 +147,7 @@ export async function GET(request: Request) {
147147

148148
if (searchQuery) {
149149
where.OR = [
150+
...(where.OR ?? []),
150151
{name: {contains: searchQuery, mode: 'insensitive'}},
151152
// {email: {contains: searchQuery, mode: 'insensitive'}},
152153
{

app/profiles/ProfileFilters.tsx

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import React, {useEffect, useRef, useState} from 'react';
44
import {Gender} from "@prisma/client";
55
import Dropdown from "@/app/components/dropdown";
66
import Slider from '@mui/material/Slider';
7-
import {DropdownKey, RangeKey} from "@/lib/client/schema";
7+
import {DropdownKey, Item, RangeKey} from "@/lib/client/schema";
88
import {capitalize} from "@/lib/format";
9-
import {Item} from "@/lib/client/schema";
109
import {fetchFeatures} from "@/lib/client/fetching";
1110

1211
interface FilterProps {
@@ -71,9 +70,47 @@ export function ProfileFilters({filters, onFilterChange, onShowFilters, onToggle
7170

7271

7372
useEffect(() => {
74-
fetchFeatures(setOptionsDropdownId)
73+
fetchFeatures(setOptionsDropdownId);
7574
}, []);
7675

76+
useEffect(() => {
77+
console.log('selectedDropdown changed:', selectedDropdown);
78+
}, [selectedDropdown]);
79+
80+
useEffect(() => {
81+
const params = new URLSearchParams(window.location.search);
82+
83+
console.log('optionsDropdown changed:', optionsDropdown, params);
84+
85+
for (const [key, value] of params.entries()) {
86+
let v: any = value
87+
if (key === 'minAge') {
88+
setMinRange({...minRange, age: v});
89+
} else if (key === 'maxAge') {
90+
setMaxRange({...maxRange, age: v});
91+
} else if (key === 'minIntroversion') {
92+
setMinRange({...minRange, introversion: v});
93+
} else if (key === 'maxIntroversion') {
94+
setMaxRange({...maxRange, introversion: v});
95+
} else if (['interests', 'coreValues', 'causeAreas', 'connections'].includes(key)) {
96+
v = v.split(",").filter(Boolean) || []
97+
console.log(v)
98+
for (const n of v) {
99+
const option = optionsDropdown[key].find(i => i.name === n);
100+
if (option) {
101+
console.log(option);
102+
setSelectedDropdown(prev => {
103+
const newSet = new Set(prev[key]);
104+
newSet.add(option.id);
105+
return {...prev, [key]: newSet};
106+
});
107+
}
108+
109+
}
110+
}
111+
}
112+
}, [optionsDropdown]);
113+
77114
useEffect(() => {
78115
// Close dropdown when clicking outside
79116
const handleClickOutside = (event: MouseEvent) => {
@@ -104,6 +141,7 @@ export function ProfileFilters({filters, onFilterChange, onShowFilters, onToggle
104141
} else {
105142
newSet.add(optionId);
106143
}
144+
// console.log(newSet);
107145
return {...prev, [id]: newSet};
108146
});
109147
};

app/profiles/page.tsx

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import Link from "next/link";
44
import React, {useCallback, useEffect, useState} from "react";
5-
import LoadingSpinner from "@/lib/client/LoadingSpinner";
65
import {DropdownKey, ProfileData} from "@/lib/client/schema";
76
import {dropdownConfig, ProfileFilters} from "./ProfileFilters";
87
import Image from "next/image";
@@ -26,19 +25,68 @@ const initialState = {
2625
forceRun: false,
2726
};
2827

28+
type ProfileFilters = {
29+
gender: string;
30+
minAge: number | null;
31+
maxAge: number | null;
32+
minIntroversion: number | null;
33+
maxIntroversion: number | null;
34+
interests: string[];
35+
coreValues: string[];
36+
causeAreas: string[];
37+
connections: string[];
38+
searchQuery: string;
39+
forceRun: boolean;
40+
};
41+
2942

3043
export default function ProfilePage() {
3144
const [profiles, setProfiles] = useState<ProfileData[]>([]);
3245
const [loading, setLoading] = useState(true);
3346
const [error, setError] = useState('');
3447
const [_, setShowFilters] = useState(true);
35-
const [images, setImages] = useState<string[]>([])
48+
const [images, setImages] = useState<string[]>([]);
49+
50+
const [text, setText] = useState<string>('');
51+
3652
const [filters, setFilters] = useState(initialState);
3753

54+
useEffect(() => {
55+
const params = new URLSearchParams(window.location.search);
56+
const newFilters = {...initialState};
57+
58+
for (const [key, value] of params.entries()) {
59+
// Type guard to check if the key is a valid filter key
60+
if (key in newFilters) {
61+
const filterKey = key as keyof ProfileFilters;
62+
63+
if (key === 'searchQuery') {
64+
setText(value);
65+
newFilters[filterKey] = value as never;
66+
}
67+
else if (['interests', 'coreValues', 'causeAreas', 'connections'].includes(key)) {
68+
const arrayKey = filterKey as 'interests' | 'coreValues' | 'causeAreas' | 'connections';
69+
newFilters[arrayKey] = [...newFilters[arrayKey], value];
70+
}
71+
}
72+
}
73+
74+
console.log(newFilters);
75+
76+
setFilters(newFilters);
77+
}, []);
78+
79+
const [isStart, setIsStart] = useState(true);
80+
3881
const fetchProfiles = useCallback(async () => {
3982
try {
4083
setLoading(true);
41-
const params = new URLSearchParams();
84+
let params = new URLSearchParams();
85+
if (isStart) {
86+
params = new URLSearchParams(window.location.search);
87+
setIsStart(false);
88+
}
89+
console.log('fetchProfiles', params);
4290

4391
if (filters.gender) params.append('gender', filters.gender);
4492
if (filters.minAge) params.append('minAge', filters.minAge.toString());
@@ -54,9 +102,12 @@ export default function ProfilePage() {
54102
}
55103
}
56104

57-
if (filters.searchQuery) params.append('search', filters.searchQuery);
105+
if (filters.searchQuery) params.append('searchQuery', filters.searchQuery);
106+
107+
let s = params.toString();
108+
window.history.pushState({}, '', `?${s}`);
58109

59-
const response = await fetch(`/api/profiles?${params.toString()}`);
110+
const response = await fetch(`/api/profiles?${s}`);
60111
const data = await response.json();
61112
if (!response.ok) {
62113
console.log(response);
@@ -124,10 +175,9 @@ export default function ProfilePage() {
124175
const resetFilters = () => {
125176
setFilters(initialState);
126177
setText('');
178+
// window.history.pushState({}, '', '');
127179
};
128180

129-
const [text, setText] = useState<string>('');
130-
131181
const onFilterChange = handleFilterChange
132182

133183
return (
@@ -205,9 +255,10 @@ export default function ProfilePage() {
205255
<div className="flex-1">
206256
{loading ? (
207257
<div className="flex justify-center py-8">
208-
<div className="flex justify-center min-h-screen py-8">
209-
<div data-testid="spinner" className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
210-
</div>
258+
<div className="flex justify-center min-h-screen py-8">
259+
<div data-testid="spinner"
260+
className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
261+
</div>
211262
</div>
212263
) : error ? (
213264
<div className="flex justify-center py-2">

0 commit comments

Comments
 (0)