From 045dccbdd9752e1173e83417b58065e017c542df Mon Sep 17 00:00:00 2001 From: Seif Ghezala Date: Thu, 17 Oct 2024 10:52:10 +0400 Subject: [PATCH 01/10] Implement country selector --- .../country-selector-dialog.tsx | 86 +++++++++++++++++++ .../global/header/country-selector/index.tsx | 11 +++ storefront/components/global/header/index.tsx | 22 +++-- storefront/config.ts | 1 + storefront/data/medusa/regions.ts | 24 ++++++ 5 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 storefront/components/global/header/country-selector/country-selector-dialog.tsx create mode 100644 storefront/components/global/header/country-selector/index.tsx diff --git a/storefront/components/global/header/country-selector/country-selector-dialog.tsx b/storefront/components/global/header/country-selector/country-selector-dialog.tsx new file mode 100644 index 0000000..5a04db0 --- /dev/null +++ b/storefront/components/global/header/country-selector/country-selector-dialog.tsx @@ -0,0 +1,86 @@ +"use client"; + +import Icon from "@/components/shared/icon"; +import Heading from "@/components/shared/typography/heading"; +import { + Close, + Content, + Overlay, + Portal, + Root, + Title, + Trigger, +} from "@radix-ui/react-dialog"; +import Link from "next/link"; +import {useParams} from "next/navigation"; +import {useState} from "react"; + +export type Country = { + code: string; + currency: { + code: string; + symbol: string; + }; + name: string; +}; + +type DialogRootProps = { + countries: Country[]; +}; + +export default function CountrySelectorDialog({countries}: DialogRootProps) { + const [open, setOpen] = useState(false); + const {countryCode = countries[0]?.code} = useParams<{ + countryCode?: string; + }>(); + + const selectedCountry = + countries.find((country) => country.code === countryCode) || countries[0]; + + return ( + setOpen(v)} open={open}> + +
+ {selectedCountry.code.toUpperCase()} [ + {selectedCountry.currency.symbol}] +
+
+ + + +
+
+ + <Heading + desktopSize="2xl" + font="serif" + mobileSize="lg" + tag="h2" + > + Select your country + </Heading> + +
+ + + +
+ {countries.map((country) => ( + + {country.name} [{country.currency.symbol}] + + ))} +
+
+
+
+
+ ); +} diff --git a/storefront/components/global/header/country-selector/index.tsx b/storefront/components/global/header/country-selector/index.tsx new file mode 100644 index 0000000..30f7832 --- /dev/null +++ b/storefront/components/global/header/country-selector/index.tsx @@ -0,0 +1,11 @@ +import {listCountries} from "@/data/medusa/regions"; + +import type {Country} from "./country-selector-dialog"; + +import Dialog from "./country-selector-dialog"; + +export async function CountrySelector() { + const countries = (await listCountries()).filter(Boolean) as Country[]; + + return ; +} diff --git a/storefront/components/global/header/index.tsx b/storefront/components/global/header/index.tsx index 32b62a0..ea93ff5 100644 --- a/storefront/components/global/header/index.tsx +++ b/storefront/components/global/header/index.tsx @@ -5,6 +5,7 @@ import Link from "next/link"; import {Suspense} from "react"; import Cart from "./cart"; +import {CountrySelector} from "./country-selector"; import Hamburger from "./hamburger"; import AnnouncementBar from "./parts/announcement-bar"; import BottomBorder from "./parts/bottom-border"; @@ -30,15 +31,18 @@ export default function Header(props: Header) { - - - - } - > - - +
+ + + +
+ } + > + + + diff --git a/storefront/app/(website)/[...path]/page.tsx b/storefront/app/[countryCode]/[...path]/page.tsx similarity index 92% rename from storefront/app/(website)/[...path]/page.tsx rename to storefront/app/[countryCode]/[...path]/page.tsx index 48040de..4555b4a 100644 --- a/storefront/app/(website)/[...path]/page.tsx +++ b/storefront/app/[countryCode]/[...path]/page.tsx @@ -9,7 +9,7 @@ import {notFound} from "next/navigation"; import TextPage from "./text-page.template"; -export type DynamicRouteProps = PageProps<"...path">; +export type DynamicRouteProps = PageProps<"...path" | "countryCode">; export async function generateMetadata( {params}: DynamicRouteProps, @@ -34,7 +34,6 @@ export async function generateMetadata( export default async function DynamicRoute({params}: DynamicRouteProps) { const initialData = await loadPageByPathname({params}); - if (!initialData) return notFound(); switch (initialData._type) { @@ -42,6 +41,7 @@ export default async function DynamicRoute({params}: DynamicRouteProps) { case "home": return ( ); diff --git a/storefront/app/(website)/[...path]/text-page.template.tsx b/storefront/app/[countryCode]/[...path]/text-page.template.tsx similarity index 100% rename from storefront/app/(website)/[...path]/text-page.template.tsx rename to storefront/app/[countryCode]/[...path]/text-page.template.tsx diff --git a/storefront/app/(website)/faqs/_parts/faq-content.tsx b/storefront/app/[countryCode]/faqs/_parts/faq-content.tsx similarity index 100% rename from storefront/app/(website)/faqs/_parts/faq-content.tsx rename to storefront/app/[countryCode]/faqs/_parts/faq-content.tsx diff --git a/storefront/app/(website)/faqs/_parts/faq-page.tsx b/storefront/app/[countryCode]/faqs/_parts/faq-page.tsx similarity index 100% rename from storefront/app/(website)/faqs/_parts/faq-page.tsx rename to storefront/app/[countryCode]/faqs/_parts/faq-page.tsx diff --git a/storefront/app/(website)/faqs/_parts/search-bar.tsx b/storefront/app/[countryCode]/faqs/_parts/search-bar.tsx similarity index 100% rename from storefront/app/(website)/faqs/_parts/search-bar.tsx rename to storefront/app/[countryCode]/faqs/_parts/search-bar.tsx diff --git a/storefront/app/(website)/faqs/page.tsx b/storefront/app/[countryCode]/faqs/page.tsx similarity index 100% rename from storefront/app/(website)/faqs/page.tsx rename to storefront/app/[countryCode]/faqs/page.tsx diff --git a/storefront/app/(website)/layout.tsx b/storefront/app/[countryCode]/layout.tsx similarity index 100% rename from storefront/app/(website)/layout.tsx rename to storefront/app/[countryCode]/layout.tsx diff --git a/storefront/app/(website)/not-found.tsx b/storefront/app/[countryCode]/not-found.tsx similarity index 100% rename from storefront/app/(website)/not-found.tsx rename to storefront/app/[countryCode]/not-found.tsx diff --git a/storefront/app/(website)/page.tsx b/storefront/app/[countryCode]/page.tsx similarity index 100% rename from storefront/app/(website)/page.tsx rename to storefront/app/[countryCode]/page.tsx diff --git a/storefront/app/(website)/products/[handle]/_parts/add-to-cart.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/add-to-cart.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/_parts/add-to-cart.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/add-to-cart.tsx diff --git a/storefront/app/(website)/products/[handle]/_parts/addons.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/addons.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/_parts/addons.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/addons.tsx diff --git a/storefront/app/(website)/products/[handle]/_parts/breadcrumbs.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/breadcrumbs.tsx similarity index 67% rename from storefront/app/(website)/products/[handle]/_parts/breadcrumbs.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/breadcrumbs.tsx index e46ae90..4ab4711 100644 --- a/storefront/app/(website)/products/[handle]/_parts/breadcrumbs.tsx +++ b/storefront/app/[countryCode]/products/[handle]/_parts/breadcrumbs.tsx @@ -1,7 +1,7 @@ import type {StoreProduct} from "@medusajs/types"; +import LocalizedLink from "@/components/shared/localized-link"; import Body from "@/components/shared/typography/body"; -import Link from "next/link"; export default function BreadCrumbs({ collection, @@ -9,13 +9,13 @@ export default function BreadCrumbs({ }: Pick) { return ( - Home{" "} + Home{" "} {collection && ( <> {" / "} - + {collection.title} - {" "} + {" "} )} {" / "} diff --git a/storefront/app/(website)/products/[handle]/_parts/image-carousel.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/image-carousel.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/_parts/image-carousel.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/image-carousel.tsx diff --git a/storefront/app/(website)/products/[handle]/_parts/options.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/options.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/_parts/options.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/options.tsx diff --git a/storefront/app/(website)/products/[handle]/_parts/price.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/price.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/_parts/price.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/price.tsx diff --git a/storefront/app/(website)/products/[handle]/_parts/product-information.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/product-information.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/_parts/product-information.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/product-information.tsx diff --git a/storefront/app/(website)/products/[handle]/_parts/specs.tsx b/storefront/app/[countryCode]/products/[handle]/_parts/specs.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/_parts/specs.tsx rename to storefront/app/[countryCode]/products/[handle]/_parts/specs.tsx diff --git a/storefront/app/(website)/products/[handle]/page.tsx b/storefront/app/[countryCode]/products/[handle]/page.tsx similarity index 82% rename from storefront/app/(website)/products/[handle]/page.tsx rename to storefront/app/[countryCode]/products/[handle]/page.tsx index bc52df6..aadf763 100644 --- a/storefront/app/(website)/products/[handle]/page.tsx +++ b/storefront/app/[countryCode]/products/[handle]/page.tsx @@ -9,13 +9,10 @@ import {notFound} from "next/navigation"; import {ProductImagesCarousel} from "./_parts/image-carousel"; import ProductInformation from "./_parts/product-information"; -type ProductPageProps = PageProps<"handle">; +type ProductPageProps = PageProps<"countryCode" | "handle">; export default async function ProductPage({params}: ProductPageProps) { - const region = await getRegion( - // TODO: Make this come from the params - process.env.NEXT_PUBLIC_MEDUSA_DEFAULT_COUNTRY_CODE!, - ); + const region = await getRegion(params.countryCode); if (!region) { console.log("No region found"); @@ -41,7 +38,11 @@ export default async function ProductPage({params}: ProductPageProps) { /> {content?.sections && ( - + )} ); diff --git a/storefront/app/(website)/products/[handle]/product-context.tsx b/storefront/app/[countryCode]/products/[handle]/product-context.tsx similarity index 100% rename from storefront/app/(website)/products/[handle]/product-context.tsx rename to storefront/app/[countryCode]/products/[handle]/product-context.tsx diff --git a/storefront/app/(website)/products/page.tsx b/storefront/app/[countryCode]/products/page.tsx similarity index 85% rename from storefront/app/(website)/products/page.tsx rename to storefront/app/[countryCode]/products/page.tsx index aca3cca..d886fe1 100644 --- a/storefront/app/(website)/products/page.tsx +++ b/storefront/app/[countryCode]/products/page.tsx @@ -8,11 +8,12 @@ import Heading from "@/components/shared/typography/heading"; import {Suspense} from "react"; type CollectionPageProps = PageProps< - never, + "countryCode", "category" | "collection" | "page" | "sort" >; export default async function CollectionPage({ + params, searchParams, }: CollectionPageProps) { return ( @@ -25,7 +26,10 @@ export default async function CollectionPage({
}> - +
diff --git a/storefront/components/global/footer/parts/bottom-links.tsx b/storefront/components/global/footer/parts/bottom-links.tsx index 2c84df3..23e0bf2 100644 --- a/storefront/components/global/footer/parts/bottom-links.tsx +++ b/storefront/components/global/footer/parts/bottom-links.tsx @@ -1,7 +1,7 @@ import type {Footer} from "@/types/sanity.generated"; +import LocalizedLink from "@/components/shared/localized-link"; import Label from "@/components/shared/typography/label"; -import Link from "next/link"; import React from "react"; export default function BottomLinks({ @@ -19,7 +19,7 @@ export default function BottomLinks({ {bottomLinks?.map((link) => { if (!link.link) return null; return ( - {link.label} - + ); })} @@ -36,11 +36,11 @@ export default function BottomLinks({ {socialLinks?.map((link) => { if (!link.link) return null; return ( - + - + ); })} diff --git a/storefront/components/global/footer/parts/top-links.tsx b/storefront/components/global/footer/parts/top-links.tsx index 05edbc7..72287f4 100644 --- a/storefront/components/global/footer/parts/top-links.tsx +++ b/storefront/components/global/footer/parts/top-links.tsx @@ -1,8 +1,8 @@ import type {Footer} from "@/types/sanity.generated"; +import LocalizedLink from "@/components/shared/localized-link"; import {RichText} from "@/components/shared/rich-text"; import Body from "@/components/shared/typography/body"; -import Link from "next/link"; export default function TopLinks({information, linkList}: NonNullable