Skip to content

Commit

Permalink
feat: Combine query parameters from menu items
Browse files Browse the repository at this point in the history
  • Loading branch information
soniaklimas committed Nov 14, 2024
1 parent 184e682 commit cf9d9ed
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 14 deletions.
32 changes: 26 additions & 6 deletions apps/storefront/src/app/[locale]/(main)/_components/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,28 @@ import {
import { RichText } from "@nimara/ui/components/rich-text";

import { Link, useRouter } from "@/i18n/routing";
import { generateLinkUrl, getQueryParams } from "@/lib/cms";
import {
generateLinkUrl,
getCombinedQueryParams,
getQueryParams,
} from "@/lib/cms";
import { paths } from "@/lib/paths";
import type { Maybe } from "@/lib/types";

export const Navigation = ({ menu }: { menu: Maybe<Menu> }) => {
const router = useRouter();

// Close menu manually
const [value, setValue] = useState("");
const [currentMenuItem, setCurrentMenuItem] = useState("");

if (!menu || menu?.items?.length === 0) {
return null;
}

return (
<NavigationMenu
onValueChange={setValue}
value={value}
onValueChange={setCurrentMenuItem}
value={currentMenuItem}
className="mx-auto hidden max-w-screen-xl pb-6 pt-3 md:flex"
>
<NavigationMenuList className="gap-6">
Expand Down Expand Up @@ -66,7 +70,23 @@ export const Navigation = ({ menu }: { menu: Maybe<Menu> }) => {
key={child.id}
href={generateLinkUrl(child, paths)}
className="group block space-y-1 rounded-md p-3 hover:bg-accent"
onClick={() => setValue("")}
onClick={(e) => {
setCurrentMenuItem("");
if (!child.page && !child.url) {
e.preventDefault();
// Combines query parameters from both menu item and its child for the final UR
const combinedParams = getCombinedQueryParams(
item,
child,
);

router.push(
paths.search.asPath({
query: combinedParams,
}),
);
}
}}
>
<div className="text-sm font-medium leading-none">
{child.name || child.category?.name}
Expand All @@ -92,7 +112,7 @@ export const Navigation = ({ menu }: { menu: Maybe<Menu> }) => {
key={child.id}
href={generateLinkUrl(child, paths)}
className="group relative min-h-[270px] overflow-hidden rounded-lg bg-accent"
onClick={() => setValue("")}
onClick={() => setCurrentMenuItem("")}
>
<div
className="h-1/2 bg-cover bg-center"
Expand Down
51 changes: 43 additions & 8 deletions apps/storefront/src/components/mobile-navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import type { Menu } from "@nimara/domain/objects/Menu";
import type { Menu, MenuItem } from "@nimara/domain/objects/Menu";

import { Link } from "@/i18n/routing";
import { generateLinkUrl, isInternalUrl } from "@/lib/cms";
import { Link, useRouter } from "@/i18n/routing";
import {
generateLinkUrl,
getCombinedQueryParams,
getQueryParams,
isInternalUrl,
} from "@/lib/cms";
import { paths } from "@/lib/paths";
import type { Maybe } from "@/lib/types";

Expand All @@ -12,10 +17,37 @@ export const MobileNavigation = ({
menu: Maybe<Menu>;
onMenuItemClick: (isMenuItemClicked: boolean) => void;
}) => {
const handleClick = () => {
const router = useRouter();

const handleMenuItemClick = () => {
onMenuItemClick(true);
};

const handleLinkClick = (
e: React.MouseEvent,
item: MenuItem,
parentItem?: MenuItem,
) => {
handleMenuItemClick();
const combinedParams = parentItem
? getCombinedQueryParams(parentItem, item)
: getQueryParams(item);

// Filter out any null values to ensure compatibility with router.push
const queryParams = Object.fromEntries(
Object.entries(combinedParams).filter(([_, value]) => value !== null),
) as Record<string, string>;

if (Object.keys(queryParams).length > 0 && item.category) {
e.preventDefault();
router.push(
paths.search.asPath({
query: queryParams,
}),
);
}
};

if (!menu || menu?.items?.length === 0) {
return null;
}
Expand All @@ -25,15 +57,18 @@ export const MobileNavigation = ({
{menu.items.map((item) => (
<li key={item.id} className="p-2 text-stone-500">
{isInternalUrl(item.url) ? (
<Link href={generateLinkUrl(item, paths)} onClick={handleClick}>
<Link
href={generateLinkUrl(item, paths)}
onClick={(e) => handleLinkClick(e, item)}
>
{item.name || item.category?.name || item.collection?.name}
</Link>
) : (
<a
href={item.url as string}
target="_blank"
rel="noopener noreferrer"
onClick={handleClick}
onClick={(e) => handleLinkClick(e, item)}
>
{item.name}
</a>
Expand All @@ -45,7 +80,7 @@ export const MobileNavigation = ({
{isInternalUrl(child.url) ? (
<Link
href={generateLinkUrl(child, paths)}
onClick={handleClick}
onClick={(e) => handleLinkClick(e, child, item)}
>
{child.name ||
child.collection?.name ||
Expand All @@ -56,7 +91,7 @@ export const MobileNavigation = ({
href={child.url as string}
target="_blank"
rel="noopener noreferrer"
onClick={handleClick}
onClick={(e) => handleLinkClick(e, child, item)}
>
{child.name}
</a>
Expand Down
17 changes: 17 additions & 0 deletions apps/storefront/src/lib/cms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ export const getQueryParams = (
return { queryKey: null, queryValue: null };
};

export const getCombinedQueryParams = (
parentItem: MenuItem,
childItem: MenuItem,
): { [key: string]: string } => {
const parentParams = getQueryParams(parentItem);
const childParams = getQueryParams(childItem);

return {
...(parentParams.queryKey && parentParams.queryValue
? { [parentParams.queryKey]: parentParams.queryValue }
: {}),
...(childParams.queryKey && childParams.queryValue
? { [childParams.queryKey]: childParams.queryValue }
: {}),
};
};

interface Paths {
page: {
asPath: (params: { slug: string }) => string;
Expand Down

0 comments on commit cf9d9ed

Please sign in to comment.