Skip to content

Commit

Permalink
Improve navbar (#944)
Browse files Browse the repository at this point in the history
  • Loading branch information
typeofweb authored Oct 13, 2023
1 parent 958b179 commit 10332b7
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 36 deletions.
39 changes: 39 additions & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
type NonFalsy<T> = T extends false | 0 | "" | null | undefined | 0n ? never : T;

interface Array<T> {
includes(searchElement: unknown, fromIndex?: number): searchElement is T;
}

interface ReadonlyArray<T> {
includes(searchElement: unknown, fromIndex?: number): searchElement is T;
}

interface Body {
json(): Promise<unknown>;
}

interface Array<T> {
filter(predicate: BooleanConstructor, thisArg?: unknown): NonFalsy<T>[];
}

interface ReadonlyArray<T> {
filter(predicate: BooleanConstructor, thisArg?: unknown): NonFalsy<T>[];
}

interface ArrayConstructor {
isArray(arg: unknown): arg is unknown[];
}

interface JSON {
/**
* Converts a JavaScript Object Notation (JSON) string into an object.
* @param text A valid JSON string.
* @param reviver A function that transforms the results. This function is called for each member of the object.
* If a member contains nested objects, the nested objects are transformed before the parent object is.
*/
parse(text: string, reviver?: (this: unknown, key: string, value: unknown) => unknown): unknown;
}

interface Set<T> {
has(value: unknown): value is T;
}
2 changes: 1 addition & 1 deletion src/checkout/sections/PaymentSection/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const getFilteredPaymentGateways = (
// app is missing in our codebase but is an app and not a plugin
// hence we'd like to have it handled by default
if (!shouldBeIncluded && !isAPlugin) {
console.warn(`Unhandled payment gateway - name: ${name}, id: ${id}`);
console.warn(`Unhandled payment gateway - name: ${name}, id: ${id as string}`);
return false;
}

Expand Down
12 changes: 12 additions & 0 deletions src/graphql/MenuGetBySlug.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
query MenuGetBySlug($slug: String!) {
menu(slug: $slug) {
items {
id
category {
id
slug
name
}
}
}
}
11 changes: 1 addition & 10 deletions src/ui/components/ActiveLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,13 @@ import clsx from "clsx";
import Link from "next/link";
import { usePathname } from "next/navigation";

export function ActiveLink({
key,
href,
children,
}: {
key: string;
href: string;
children: JSX.Element | string;
}) {
export function ActiveLink({ href, children }: { href: string; children: JSX.Element | string }) {
const pathname = usePathname();

const isActive = pathname === href;

return (
<Link
key={key}
href={href}
className={clsx(
isActive ? "border-neutral-900 text-neutral-900" : "border-transparent text-neutral-500",
Expand Down
19 changes: 19 additions & 0 deletions src/ui/components/CartNavItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { cookies } from "next/headers";
import { ShoppingBagIcon } from "lucide-react";
import Link from "next/link";
import * as Checkout from "@/lib/checkout";

export const CartNavItem = async () => {
const checkoutId = cookies().get("checkoutId")?.value || "";
const checkout = await Checkout.find(checkoutId);

const lineCount = checkout ? checkout.lines.reduce((result, line) => result + line.quantity, 0) : 0;

return (
<Link href="/cart" className="flex w-12 items-center">
<ShoppingBagIcon className="h-6 w-6 flex-shrink-0 " aria-hidden="true" />
<span className="ml-2 min-w-[2ch] text-sm font-medium">{lineCount > 0 && lineCount}</span>
<span className="sr-only">items in cart, view bag</span>
</Link>
);
};
45 changes: 20 additions & 25 deletions src/ui/components/Nav.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { cookies } from "next/headers";
import Link from "next/link";
import { ShoppingBagIcon } from "lucide-react";
import { Suspense } from "react";
import { ActiveLink } from "./ActiveLink";
import { AccountLink } from "./AccountLink";
import * as Checkout from "@/lib/checkout";

const NavLinks = [
{ href: "/products", label: "All" },
{ href: "/categories/t-shirts", label: "T-shirts" },
{ href: "/categories/hoodies", label: "Hoodies" },
{ href: "/categories/accessories", label: "Accessories" },
];
import { CartNavItem } from "./CartNavItem";
import { executeGraphQL } from "@/lib/graphql";
import { MenuGetBySlugDocument } from "@/gql/graphql";

export async function Nav() {
const checkoutId = cookies().get("checkoutId")?.value || "";

const checkout = await Checkout.find(checkoutId);

const lineCount = checkout ? checkout.lines.reduce((result, line) => result + line.quantity, 0) : 0;
const navLinks = await executeGraphQL(MenuGetBySlugDocument, {
variables: { slug: "navbar" },
revalidate: 60 * 60 * 24,
});

return (
<div className="sticky top-0 z-20 bg-neutral-100/50 backdrop-blur-md">
Expand All @@ -31,22 +24,24 @@ export async function Nav() {
<div className="flex overflow-x-auto overflow-y-hidden whitespace-nowrap lg:px-0">
<div className="flex flex-shrink-0 items-center"></div>
<div className="flex gap-4 lg:gap-8">
{NavLinks.map((link) => (
<ActiveLink key={link.href} href={link.href}>
{link.label}
</ActiveLink>
))}
<ActiveLink href="/products">All</ActiveLink>
{navLinks.menu?.items
?.map((item) => item.category)
.filter(Boolean)
.map((category) => (
<ActiveLink key={category.id} href={`/categories/${category.slug}`}>
{category.name}
</ActiveLink>
))}
</div>
</div>
<div className="ml-auto flex items-center justify-center whitespace-nowrap">
<AccountLink />
</div>
<div className="flex items-center">
<Link href="/cart" className="group -m-2 flex items-center p-2">
<ShoppingBagIcon className="h-6 w-6 flex-shrink-0 " aria-hidden="true" />
<span className="ml-2 min-w-[2ch] text-sm font-medium">{lineCount > 0 && lineCount}</span>
<span className="sr-only">items in cart, view bag</span>
</Link>
<Suspense fallback={<div className="w-12" />}>
<CartNavItem />
</Suspense>
</div>
</div>
</div>
Expand Down

0 comments on commit 10332b7

Please sign in to comment.