Skip to content

Commit

Permalink
refactor: append search-result item's href to url on pillar pages
Browse files Browse the repository at this point in the history
  • Loading branch information
johnshift committed Jan 20, 2025
1 parent 32153a9 commit 39687bc
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/search/components/pillar-page-search-results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ export const PillarPageSearchResults = ({ nav, excluded }: Props) => {

if (!isVisible) return null;

return <SearchResults nav={nav} excluded={excluded} />;
return <SearchResults isPillarSearchResult nav={nav} excluded={excluded} />;
};
62 changes: 59 additions & 3 deletions src/search/components/search-result-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useMemo } from 'react';

import { Button } from "@heroui/button";
import { Button } from '@heroui/button';
import { useSetAtom } from 'jotai';

import { ExternalIcon } from '@/shared/components/icons/external-icon';

import { TSearchResultItem } from '@/search/core/schemas';
import { searchQueryAtom } from '@/search/core/atoms';

import { usePillarRoutesContext } from '@/search/state/contexts/pillar-routes-context';

Expand Down Expand Up @@ -38,20 +41,38 @@ const highlightText = (text: string, query: string): React.ReactNode => {

interface Props extends TSearchResultItem {
query: string;
isPillarSearchResult?: boolean;
}

export const SearchResultItem = ({ label, href, query }: Props) => {
export const SearchResultItem = ({
label,
href,
query,
isPillarSearchResult,
}: Props) => {
const router = useRouter();
const { isPendingPillarRoute, startTransition } = usePillarRoutesContext();

const setQuery = useSetAtom(searchQueryAtom);
const clearQuery = () => setQuery('');

const onClick = () => {
clearQuery();
startTransition(() => {
router.push(href);
});
};

// Pillar pages append the item to the search params
const finalHref = useMemo(
() => getFinalHref(href, isPillarSearchResult),
[href, isPillarSearchResult],
);

return (
<Button
as={Link}
href={href}
href={finalHref}
size="sm"
className=""
isDisabled={isPendingPillarRoute}
Expand All @@ -62,3 +83,38 @@ export const SearchResultItem = ({ label, href, query }: Props) => {
</Button>
);
};

/**
* Search result item's href depends if it's from the search page or from a pillar page.
* If it's from a pillar page, the item is appended to the search params.
* @param href search-pillar-item href
* @param isPillarSearchResult if needed to append the search-pillar-item to the search params
* @returns final href string
*/
const getFinalHref = (href: string, isPillarSearchResult?: boolean) => {
if (!isPillarSearchResult) return href;

const pathParts = href.split('/');
const pillar = pathParts[2] || null;
const item = pathParts[3] || null;

if (!pillar || !item) {
throw new Error(`Invalid search-result-item appended href: ${href}`);
}

const currentUrl = new URL(window.location.href);
const currentPillar = currentUrl.pathname.split('/')[2];
const currentValues = currentUrl.searchParams.get(pillar);
const pillarMatched = currentPillar === pillar;

const pillarKey = pillarMatched ? 'include' : pillar;

if (currentValues) {
const updatedValues = new Set(currentValues.split(',').concat(item));
currentUrl.searchParams.set(pillarKey, Array.from(updatedValues).join(','));
} else {
currentUrl.searchParams.set(pillarKey, item);
}

return currentUrl.toString();
};
9 changes: 8 additions & 1 deletion src/search/components/search-result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ export const SearchResultLayout = ({

interface Props extends TSearchResult {
query: string;
isPillarSearchResult?: boolean;
}

export const SearchResult = ({ query, title, items }: Props) => {
export const SearchResult = ({
query,
title,
items,
isPillarSearchResult,
}: Props) => {
return (
<SearchResultLayout
label={
Expand All @@ -36,6 +42,7 @@ export const SearchResult = ({ query, title, items }: Props) => {
query={query}
label={label}
href={href}
isPillarSearchResult={isPillarSearchResult}
/>
))}
</>
Expand Down
14 changes: 12 additions & 2 deletions src/search/components/search-results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ import { SearchResultsSkeleton } from '@/search/components/search-results-skelet
interface Props {
nav?: PillarNav;
excluded?: string;
isPillarSearchResult?: boolean;
}

export const SearchResults = ({ nav, excluded }: Props) => {
export const SearchResults = ({
nav,
excluded,
isPillarSearchResult,
}: Props) => {
const { query, data } = useSearchResults(nav, excluded);

if (!data) return <SearchResultsSkeleton />;
Expand All @@ -24,7 +29,12 @@ export const SearchResults = ({ nav, excluded }: Props) => {
{data.map(({ title, items }) => (
<Fragment key={title}>
<Divider />
<SearchResult query={query} title={title} items={items} />
<SearchResult
isPillarSearchResult={isPillarSearchResult}
query={query}
title={title}
items={items}
/>
</Fragment>
))}
<Divider />
Expand Down

0 comments on commit 39687bc

Please sign in to comment.