Skip to content

Commit 0c99b1e

Browse files
committed
add url mutation to search, fix placeholder
1 parent 1fb6275 commit 0c99b1e

File tree

3 files changed

+50
-35
lines changed

3 files changed

+50
-35
lines changed

components/ApiGrid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export function ApiGrid({ gridColumns, pageSize }: ApiGridProps) {
8888
return (
8989
<section id="apis-list" className="cards">
9090
{initialLoading ? (
91-
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4 mt-4">
91+
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4 ">
9292
{Array.from({ length: Math.min(pageSize, gridColumns * 2) }).map(
9393
(_, index) => (
9494
<CardSkeleton key={`skeleton-loading-${index}`} />
@@ -97,7 +97,7 @@ export function ApiGrid({ gridColumns, pageSize }: ApiGridProps) {
9797
</div>
9898
) : (
9999
<>
100-
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4 mt-4">
100+
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4 ">
101101
{hits.length > 0 ? (
102102
hits.map((hit, index) => (
103103
<Card key={`${hit.objectID}-${index}`} model={hit} />
@@ -110,7 +110,7 @@ export function ApiGrid({ gridColumns, pageSize }: ApiGridProps) {
110110
</div>
111111

112112
{loadingMore && (
113-
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4 mt-4">
113+
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-4 ">
114114
{Array.from({ length: Math.min(pageSize, gridColumns) }).map(
115115
(_, index) => (
116116
<CardSkeleton key={`skeleton-more-${index}`} />
Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
"use client";
22

3-
import React, { useEffect, Suspense } from "react";
3+
import React, { Suspense } from "react";
44
import { useSearchParams } from "next/navigation";
55
import { useGridLayout } from "@/hooks/useGridLayout";
6-
import { useApiSearch } from "@/hooks/useApiSearch";
76
import { LoadingSkeleton } from "@/components/LoadingSkeleton";
87
import { ApiGrid } from "@/components/ApiGrid";
98
import { liteClient as algoliasearch } from "algoliasearch/lite";
10-
import { InstantSearch, Hits } from "react-instantsearch";
9+
import { InstantSearch } from "react-instantsearch";
1110
import { SearchSection } from "@/components/SearchSection";
1211

1312
const searchClient = algoliasearch(
@@ -16,12 +15,10 @@ const searchClient = algoliasearch(
1615
);
1716

1817
interface SearchClientComponentProps {
19-
repoStarCounts: Record<string, number>;
2018
providerSlug?: string;
2119
}
2220

2321
function SearchClientComponentInner({
24-
repoStarCounts,
2522
providerSlug,
2623
}: SearchClientComponentProps) {
2724
const searchParams = useSearchParams();
@@ -32,17 +29,6 @@ function SearchClientComponentInner({
3229

3330
const { gridColumns, pageSize } = useGridLayout();
3431

35-
useEffect(() => {
36-
Object.entries(repoStarCounts).forEach(([name, stars]) => {
37-
const elements = document.querySelectorAll(
38-
`[data-proj="${name}"].stars-count`
39-
);
40-
elements.forEach((el) => {
41-
if (el) el.textContent = stars.toString();
42-
});
43-
});
44-
}, [repoStarCounts]);
45-
4632
return (
4733
<div className="container mx-auto px-4 relative">
4834
<div className="relative z-10">
@@ -66,15 +52,11 @@ function SearchClientComponentInner({
6652
}
6753

6854
export default function SearchClientComponent({
69-
repoStarCounts,
7055
providerSlug,
7156
}: SearchClientComponentProps) {
7257
return (
7358
<Suspense fallback={<LoadingSkeleton pageSize={30} />}>
74-
<SearchClientComponentInner
75-
repoStarCounts={repoStarCounts}
76-
providerSlug={providerSlug}
77-
/>
59+
<SearchClientComponentInner providerSlug={providerSlug} />
7860
</Suspense>
7961
);
8062
}

components/SearchSection.tsx

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"use client";
22

33
import { SearchIcon } from "lucide-react";
4-
import React, { useEffect } from "react";
4+
import React, { useEffect, useRef } from "react";
5+
import { useRouter, useSearchParams } from "next/navigation";
56
import {
67
SearchBox,
78
useInstantSearch,
@@ -10,23 +11,48 @@ import {
1011
} from "react-instantsearch";
1112

1213
export function SearchSection() {
13-
const { results } = useInstantSearch({});
14-
const { query } = useSearchBox();
14+
const { results } = useInstantSearch();
15+
const { query, refine } = useSearchBox();
16+
const isInitialMount = useRef(true);
17+
const router = useRouter();
18+
const searchParams = useSearchParams();
1519

1620
useEffect(() => {
17-
console.log(results);
18-
}, [results]);
21+
if (isInitialMount.current) {
22+
const initialQuery = searchParams.get("query") || "";
23+
if (initialQuery !== query) {
24+
refine(initialQuery);
25+
}
26+
isInitialMount.current = false;
27+
}
28+
}, [refine, searchParams]);
29+
30+
useEffect(() => {
31+
if (isInitialMount.current) return;
32+
33+
const currentQuery = searchParams.get("query") || "";
34+
35+
if (currentQuery !== query) {
36+
const params = new URLSearchParams(searchParams);
37+
if (query) {
38+
params.set("query", query);
39+
} else {
40+
params.delete("query");
41+
}
42+
router.push(`?${params.toString()}`, { scroll: false });
43+
}
44+
}, [query, router, searchParams]);
1945

2046
return (
21-
<div id="search" className="mb-8 max-w-3xl mx-auto">
47+
<div className="max-w-3xl mx-auto">
2248
<div className="border-2 border-gray-200 rounded-xl transition-all duration-200 shadow-sm hover:shadow-md">
2349
<div className="flex items-center">
2450
<div className="relative flex-1">
2551
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none z-10">
2652
<SearchIcon className="h-5 w-5 text-gray-400" />
2753
</div>
2854
<SearchBox
29-
placeholder={`Search through APIs...`}
55+
placeholder={`Search through ${results.nbHits.toLocaleString()} APIs...`}
3056
classNames={{
3157
form: "relative",
3258
input:
@@ -48,11 +74,18 @@ export function SearchSection() {
4874
</div>
4975
</div>
5076
</div>
51-
{query && (
52-
<div className="mt-3 text-lg text-gray-600 text-center">
77+
<div
78+
className="my-3 min-h-[1.75rem] text-lg text-gray-600 text-center"
79+
aria-live="polite"
80+
>
81+
<span
82+
className={`inline-block transition-opacity duration-200 ${
83+
query ? "opacity-100" : "opacity-0"
84+
}`}
85+
>
5386
{results.nbHits.toLocaleString()} APIs found
54-
</div>
55-
)}
87+
</span>
88+
</div>
5689
</div>
5790
);
5891
}

0 commit comments

Comments
 (0)