Skip to content

Commit

Permalink
feat: Implement search using query string
Browse files Browse the repository at this point in the history
  • Loading branch information
Leejha committed Jul 7, 2024
1 parent f71457a commit 0c6ccc3
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 29 deletions.
1 change: 1 addition & 0 deletions new-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"dependencies": {
"@radix-ui/react-slot": "^1.1.0",
"@react-hookz/web": "^24.0.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.397.0",
Expand Down
17 changes: 6 additions & 11 deletions new-web/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import { Header } from "components";
import { SearchContainer } from "./search/components";

import { SearchInput, SearchResultTable } from "./search/components";

export default function SearchPage() {
const SearchPage = () => {
return (
<>
<Header>Companies</Header>
<main className="flex flex-col items-center w-full px-4 sm:px-6 lg:px-8">
<div className="w-full max-w-6xl mt-8">
<h2 className="text-2xl font-semibold text-gray-800 mb-6">
Search for a Company
</h2>
<SearchInput />
<SearchResultTable />
</div>
<SearchContainer />
</main>
</>
);
}
};

export default SearchPage;
1 change: 1 addition & 0 deletions new-web/src/app/search/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as SearchResultTable } from "./search-result-table";
export { default as SearchInput } from "./search-input";
export { default as SearchContainer } from "./search-container";
111 changes: 111 additions & 0 deletions new-web/src/app/search/components/search-container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"use client";
import { createQueryString } from "lib/utils";
import SearchInput from "./search-input";
import SearchResultTable from "./search-result-table";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useDebouncedCallback } from "@react-hookz/web";

interface SearchResults {
content: Content[];
pageable: Pageable;
}

interface Pageable {
size: number;
pageNumber: number;
offset: number;
}

interface Content {
name: string;
city: string;
county: string;
type: string;
route: string;
}

const mockData = {
content: [
{
name: "ABC company",
city: "London",
county: "London",
type: "Worker",
route: "Skilled Worker",
},
{
name: "ABC company",
city: "London",
county: "London",
type: "Worker",
route: "Skilled Worker",
},
{
name: "ABC company",
city: "London",
county: "London",
type: "Worker",
route: "Skilled Worker",
},
{
name: "ABC company",
city: "London",
county: "London",
type: "Worker",
route: "Skilled Worker",
},
],
pageable: {
size: 10,
pageNumber: 0,
offset: 0,
},
};

const SearchContainer = () => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

const keyword = (searchParams.get("keyword") as string) ?? "";

const changeKeyword = (value: string) => {
const keywordQueryString = createQueryString({
searchParams,
name: "keyword",
value,
});
router.replace(`${pathname}?${keywordQueryString}`, {
scroll: true,
});
};

const onChangeKeyword = useDebouncedCallback(
changeKeyword,
[changeKeyword],
500
);

const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const value = formData.get("search-input") as string;
changeKeyword(value);
};

return (
<div className="w-full max-w-6xl mt-8">
<h2 className="text-2xl font-semibold text-gray-800 mb-6">
Search for a Company
</h2>
<SearchInput
value={keyword}
onSubmit={onSubmit}
onChange={onChangeKeyword}
/>
<SearchResultTable searchResults={mockData} />
</div>
);
};

export default SearchContainer;
31 changes: 21 additions & 10 deletions new-web/src/app/search/components/search-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,28 @@ import { Input } from "components";

import { SearchIcon } from "lucide-react";

const SearchInput = () => {
interface Props {
value: string;
onChange: (value: string) => void;
onSubmit: (value: any) => void;
}

const SearchInput = ({ value, onSubmit, onChange }: Props) => {
return (
<div className="relative mb-10 flex items-center w-full sm:w-1/2 md:w-1/3 lg:w-1/4">
<label htmlFor="company-search" className="sr-only">
Company Name
</label>
<Input id="company-search" placeholder="Company Name" />
<button className="absolute inset-y-0 right-0 pr-3 flex items-center ">
<SearchIcon className="h-5 w-5 text-gray-400" />
</button>
</div>
<form onSubmit={onSubmit}>
<div className="relative mb-10 flex items-center w-full sm:w-1/2 md:w-1/3 lg:w-1/4">
<Input
id="company-search"
name="search-input"
placeholder="Company Name"
defaultValue={value}
onChange={(e) => onChange(e.target.value)}
/>
<button className="absolute inset-y-0 right-0 pr-3 flex items-center">
<SearchIcon className="h-5 w-5 text-gray-400" />
</button>
</div>
</form>
);
};
export default SearchInput;
22 changes: 14 additions & 8 deletions new-web/src/app/search/components/search-result-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import {
TableRow,
} from "components/table";

const SearchResultTable = () => {
interface Props {
searchResults: any;
}

const SearchResultTable = ({ searchResults }: Props) => {
return (
<Table className="min-w-full bg-white">
<TableCaption>A list of companies</TableCaption>
Expand All @@ -22,13 +26,15 @@ const SearchResultTable = () => {
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="font-medium">ABC company</TableCell>
<TableCell>London</TableCell>
<TableCell>London</TableCell>
<TableCell>Worker</TableCell>
<TableCell className="text-right">Skilled Worker</TableCell>
</TableRow>
{searchResults.content.map((result: any) => (
<TableRow key={result.name}>
<TableCell className="font-medium">{result.name}</TableCell>
<TableCell>{result.city}</TableCell>
<TableCell>{result.county}</TableCell>
<TableCell>{result.type}</TableCell>
<TableCell className="text-right">{result.route}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
Expand Down

0 comments on commit 0c6ccc3

Please sign in to comment.