Skip to content

Commit d4311b8

Browse files
[fix 🐱‍👤] fixed filtering/search issues 👀
1 parent 84d4350 commit d4311b8

3 files changed

Lines changed: 57 additions & 43 deletions

File tree

src/app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ export default function RootLayout({
2828
children: React.ReactNode;
2929
}) {
3030
return (
31-
<html lang="en" className="h-full">
31+
<html lang="en">
3232
<body
3333
suppressHydrationWarning={true}
3434
className={cn(
3535
"relative h-full font-sans antialiased bg-zinc-100 dark:bg-zinc-900",
36-
inter.className,
36+
inter.className
3737
)}
3838
>
3939
<ThemeProvider

src/components/contents/ProfileGrid.tsx

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { db } from "@/database";
22
import { users } from "@/schemas";
33
import ProfileCard from "./ProfileCard";
44
import Paginations from "../pagination/Paginations";
5-
import { ilike, or, sql } from "drizzle-orm";
5+
import { ilike, sql, SQL } from "drizzle-orm";
66
import Notfound from "../shared/Notfound";
77
import Search from "../shared/search/Search";
88

@@ -12,61 +12,74 @@ type Props = {
1212
};
1313

1414
const ProfileGrid = async ({ page, searchParams }: Props) => {
15-
const currentPage = parseInt(page); // like 1
16-
const itemPerPage = 5; // we want to show 5 item in per pages
17-
const offset = (currentPage - 1) * itemPerPage; // (1 - 1) * 3 = 0
18-
const searchSkills = searchParams
19-
? searchParams.toLowerCase().split(/[\s,]+/)
20-
: []; // regular expression to accept inputs separated by comma, space or both
15+
const currentPage = parseInt(page, 10) || 1;
16+
const itemsPerPage = 5;
17+
const offset = (currentPage - 1) * itemsPerPage;
2118

22-
// In order to get rid of the "error: operator does not exist: json @> json" I mannually cast the skills column to JSONB
23-
const skillsCondition =
24-
searchSkills.length > 0
25-
? sql.raw(
26-
`lower("skills"::text)::JSONB @> '${JSON.stringify(searchSkills.map((skill) => skill.toLowerCase()))}'::JSONB`,
19+
const whereConditions: SQL[] = [];
20+
21+
const searchQuery = searchParams?.trim().toLowerCase() || "";
22+
const searchTokens = searchQuery ? searchQuery.split(/[\s,]+/) : [];
23+
24+
// Text field search
25+
if (searchQuery) {
26+
whereConditions.push(
27+
ilike(users.name, `%${searchQuery}%`),
28+
ilike(users.location, `%${searchQuery}%`),
29+
ilike(users.description, `%${searchQuery}%`)
30+
);
31+
32+
const skillConditions = searchTokens
33+
.map((token) => `skill ILIKE '%${token}%'`)
34+
.join(" OR ");
35+
36+
if (skillConditions) {
37+
whereConditions.push(
38+
sql.raw(`
39+
EXISTS (
40+
SELECT 1 FROM json_array_elements_text("skills") AS skill
41+
WHERE ${skillConditions}
2742
)
28-
: undefined;
43+
`)
44+
);
45+
}
46+
}
47+
48+
const whereClause = whereConditions.length
49+
? sql`(${sql.join(whereConditions, sql` OR `)})`
50+
: undefined;
2951

30-
const [lengths, profiles] = await Promise.all([
31-
db.select({ count: sql<number>`count(*)` }).from(users),
32-
searchParams
33-
? db
34-
.select()
35-
.from(users)
36-
.where(
37-
or(
38-
ilike(users.name, `%${searchParams}%`),
39-
ilike(users.location, `%${searchParams}%`),
40-
ilike(users.description, `%${searchParams}%`),
41-
skillsCondition,
42-
),
43-
)
44-
.limit(itemPerPage)
45-
.offset(offset)
46-
: db
47-
.select()
48-
.from(users)
49-
.orderBy(sql.raw("RANDOM()"))
50-
.limit(itemPerPage)
51-
.offset(offset),
52+
const [countResult, profiles] = await Promise.all([
53+
db
54+
.select({ count: sql<number>`count(*)` })
55+
.from(users)
56+
.where(whereClause),
57+
db
58+
.select()
59+
.from(users)
60+
.where(whereClause)
61+
.orderBy(sql.raw("RANDOM()"))
62+
.limit(itemsPerPage)
63+
.offset(offset),
5264
]);
5365

54-
const count = lengths[0].count;
66+
const count = countResult[0]?.count ?? 0;
67+
5568
return (
5669
<div className="lg:mt-32 mt-[10rem] mb-8 border-t-orange-500 lg:ml-[20rem] px-4 lg:px-6 relative">
5770
<Search />
5871
<div className="flex-center flex-col gap-3">
59-
{count <= 0 || profiles.length === 0 ? (
60-
<Notfound />
61-
) : (
72+
{profiles.length ? (
6273
profiles.map((profile, i) => (
6374
<ProfileCard key={i} profile={profile} />
6475
))
76+
) : (
77+
<Notfound />
6578
)}
6679
</div>
6780
<Paginations
68-
hasNextPage={currentPage < Math.ceil(count / itemPerPage)}
69-
hasPrevPage={currentPage !== 1}
81+
hasNextPage={currentPage < Math.ceil(count / itemsPerPage)}
82+
hasPrevPage={currentPage > 1}
7083
search={searchParams}
7184
/>
7285
</div>

src/components/shared/sidebar/Sidebar.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const Sidebar = () => {
3232
alt="donate button"
3333
width={130}
3434
height={80}
35+
objectFit="cover"
3536
/>
3637
</Link>
3738
<Link

0 commit comments

Comments
 (0)