@shopify/cli-hydrogen 3.26.0 → 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/hydrogen/build.js +89 -0
- package/dist/commands/hydrogen/dev.js +116 -0
- package/dist/commands/hydrogen/init.js +42 -0
- package/dist/commands/hydrogen/preview.js +34 -0
- package/dist/hooks/init.js +21 -0
- package/dist/templates/demo-store/.editorconfig +8 -0
- package/dist/templates/demo-store/.eslintignore +4 -0
- package/dist/templates/demo-store/.eslintrc.js +16 -0
- package/dist/templates/demo-store/.graphqlrc.yml +1 -0
- package/dist/templates/demo-store/.prettierignore +2 -0
- package/dist/templates/demo-store/.turbo/turbo-build.log +13 -0
- package/dist/templates/demo-store/app/components/AccountAddressBook.tsx +97 -0
- package/dist/templates/demo-store/app/components/AccountDetails.tsx +41 -0
- package/dist/templates/demo-store/app/components/AddToCartButton.tsx +42 -0
- package/dist/templates/demo-store/app/components/Breadcrumbs.tsx +36 -0
- package/dist/templates/demo-store/app/components/Button.tsx +56 -0
- package/dist/templates/demo-store/app/components/Cart.tsx +431 -0
- package/dist/templates/demo-store/app/components/CartLoading.tsx +50 -0
- package/dist/templates/demo-store/app/components/CountrySelector.tsx +180 -0
- package/dist/templates/demo-store/app/components/Drawer.tsx +115 -0
- package/dist/templates/demo-store/app/components/FeaturedCollections.tsx +54 -0
- package/dist/templates/demo-store/app/components/FeaturedProducts.tsx +116 -0
- package/dist/templates/demo-store/app/components/FeaturedSection.tsx +39 -0
- package/dist/templates/demo-store/app/components/GenericError.tsx +58 -0
- package/dist/templates/demo-store/app/components/Grid.tsx +44 -0
- package/dist/templates/demo-store/app/components/Hero.tsx +136 -0
- package/dist/templates/demo-store/app/components/Icon.tsx +253 -0
- package/dist/templates/demo-store/app/components/Input.tsx +24 -0
- package/dist/templates/demo-store/app/components/Layout.tsx +492 -0
- package/dist/templates/demo-store/app/components/Link.tsx +46 -0
- package/dist/templates/demo-store/app/components/Modal.tsx +46 -0
- package/dist/templates/demo-store/app/components/NotFound.tsx +22 -0
- package/dist/templates/demo-store/app/components/OrderCard.tsx +85 -0
- package/dist/templates/demo-store/app/components/Pagination.tsx +277 -0
- package/dist/templates/demo-store/app/components/ProductCard.tsx +146 -0
- package/dist/templates/demo-store/app/components/ProductGallery.tsx +114 -0
- package/dist/templates/demo-store/app/components/ProductGrid.tsx +93 -0
- package/dist/templates/demo-store/app/components/ProductSwimlane.tsx +30 -0
- package/dist/templates/demo-store/app/components/Skeleton.tsx +24 -0
- package/dist/templates/demo-store/app/components/SortFilter.tsx +411 -0
- package/dist/templates/demo-store/app/components/Text.tsx +192 -0
- package/dist/templates/demo-store/app/components/index.ts +28 -0
- package/dist/templates/demo-store/app/data/countries.ts +194 -0
- package/dist/templates/demo-store/app/data/index.ts +1037 -0
- package/dist/templates/demo-store/app/entry.client.tsx +4 -0
- package/dist/templates/demo-store/app/entry.server.tsx +26 -0
- package/dist/templates/demo-store/app/hooks/useCartFetchers.tsx +14 -0
- package/dist/templates/demo-store/app/hooks/useIsHydrated.tsx +12 -0
- package/dist/templates/demo-store/app/lib/const.ts +10 -0
- package/dist/templates/demo-store/app/lib/placeholders.ts +242 -0
- package/dist/templates/demo-store/app/lib/seo/common.tsx +324 -0
- package/dist/templates/demo-store/app/lib/seo/debugger.tsx +175 -0
- package/dist/templates/demo-store/app/lib/seo/image.tsx +32 -0
- package/dist/templates/demo-store/app/lib/seo/index.ts +4 -0
- package/dist/templates/demo-store/app/lib/seo/seo.tsx +24 -0
- package/dist/templates/demo-store/app/lib/seo/types.ts +70 -0
- package/dist/templates/demo-store/app/lib/session.server.ts +57 -0
- package/dist/templates/demo-store/app/lib/type.ts +21 -0
- package/dist/templates/demo-store/app/lib/utils.ts +310 -0
- package/dist/templates/demo-store/app/root.tsx +282 -0
- package/dist/templates/demo-store/app/routes/$.tsx +7 -0
- package/dist/templates/demo-store/app/routes/$lang/$.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/[robots.txt].tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/[sitemap.xml].tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__private/address/$id.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__private/edit.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__private/logout.ts +1 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__private/orders.$id.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__public/activate.$id.$activationToken.tsx +6 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__public/login.tsx +7 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__public/recover.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__public/register.tsx +6 -0
- package/dist/templates/demo-store/app/routes/$lang/account/__public/reset.$id.$resetToken.tsx +5 -0
- package/dist/templates/demo-store/app/routes/$lang/account.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/api/countries.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/api/products.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/cart.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/collections/$collectionHandle.tsx +6 -0
- package/dist/templates/demo-store/app/routes/$lang/collections/all.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/collections/index.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/featured-products.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/index.tsx +7 -0
- package/dist/templates/demo-store/app/routes/$lang/journal/$journalHandle.tsx +7 -0
- package/dist/templates/demo-store/app/routes/$lang/journal/index.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/og-image.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/pages/$pageHandle.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/policies/$policyHandle.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/policies/index.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/products/$productHandle.tsx +6 -0
- package/dist/templates/demo-store/app/routes/$lang/products/index.tsx +1 -0
- package/dist/templates/demo-store/app/routes/$lang/search.tsx +6 -0
- package/dist/templates/demo-store/app/routes/[robots.txt].tsx +40 -0
- package/dist/templates/demo-store/app/routes/[sitemap.xml].tsx +198 -0
- package/dist/templates/demo-store/app/routes/account/__private/address/$id.tsx +320 -0
- package/dist/templates/demo-store/app/routes/account/__private/edit.tsx +273 -0
- package/dist/templates/demo-store/app/routes/account/__private/logout.ts +29 -0
- package/dist/templates/demo-store/app/routes/account/__private/orders.$id.tsx +324 -0
- package/dist/templates/demo-store/app/routes/account/__public/activate.$id.$activationToken.tsx +218 -0
- package/dist/templates/demo-store/app/routes/account/__public/login.tsx +197 -0
- package/dist/templates/demo-store/app/routes/account/__public/recover.tsx +144 -0
- package/dist/templates/demo-store/app/routes/account/__public/register.tsx +184 -0
- package/dist/templates/demo-store/app/routes/account/__public/reset.$id.$resetToken.tsx +214 -0
- package/dist/templates/demo-store/app/routes/account.tsx +191 -0
- package/dist/templates/demo-store/app/routes/api/countries.tsx +22 -0
- package/dist/templates/demo-store/app/routes/api/products.tsx +116 -0
- package/dist/templates/demo-store/app/routes/cart.tsx +498 -0
- package/dist/templates/demo-store/app/routes/collections/$collectionHandle.tsx +308 -0
- package/dist/templates/demo-store/app/routes/collections/all.tsx +5 -0
- package/dist/templates/demo-store/app/routes/collections/index.tsx +195 -0
- package/dist/templates/demo-store/app/routes/discounts.$code.tsx +60 -0
- package/dist/templates/demo-store/app/routes/featured-products.tsx +58 -0
- package/dist/templates/demo-store/app/routes/index.tsx +254 -0
- package/dist/templates/demo-store/app/routes/journal/$journalHandle.tsx +147 -0
- package/dist/templates/demo-store/app/routes/journal/index.tsx +150 -0
- package/dist/templates/demo-store/app/routes/og-image.tsx +19 -0
- package/dist/templates/demo-store/app/routes/pages/$pageHandle.tsx +82 -0
- package/dist/templates/demo-store/app/routes/policies/$policyHandle.tsx +117 -0
- package/dist/templates/demo-store/app/routes/policies/index.tsx +104 -0
- package/dist/templates/demo-store/app/routes/products/$productHandle.tsx +561 -0
- package/dist/templates/demo-store/app/routes/products/index.tsx +155 -0
- package/dist/templates/demo-store/app/routes/search.tsx +205 -0
- package/dist/templates/demo-store/app/styles/custom-font.css +13 -0
- package/dist/templates/demo-store/package-lock.json +25515 -0
- package/dist/templates/demo-store/package.json +67 -0
- package/dist/templates/demo-store/playwright.config.ts +109 -0
- package/dist/templates/demo-store/postcss.config.js +10 -0
- package/dist/templates/demo-store/public/favicon.svg +28 -0
- package/dist/templates/demo-store/public/fonts/IBMPlexSerif-Text.woff2 +0 -0
- package/dist/templates/demo-store/public/fonts/IBMPlexSerif-TextItalic.woff2 +0 -0
- package/dist/templates/demo-store/remix.config.js +12 -0
- package/dist/templates/demo-store/remix.env.d.ts +34 -0
- package/dist/templates/demo-store/remix.init/index.ts +15 -0
- package/dist/templates/demo-store/remix.init/package.json +7 -0
- package/dist/templates/demo-store/server.ts +87 -0
- package/dist/templates/demo-store/styles/app.css +182 -0
- package/dist/templates/demo-store/tailwind.config.js +70 -0
- package/dist/templates/demo-store/tests/cart.test.ts +70 -0
- package/dist/templates/demo-store/tests/seo.test.ts +36 -0
- package/dist/templates/demo-store/tests/utils.ts +100 -0
- package/dist/templates/demo-store/tsconfig.json +26 -0
- package/dist/templates/hello-world/.eslintignore +4 -0
- package/dist/templates/hello-world/.eslintrc.js +6 -0
- package/dist/templates/hello-world/.graphqlrc.yml +1 -0
- package/dist/templates/hello-world/.turbo/turbo-build.log +9 -0
- package/dist/templates/hello-world/README.md +20 -0
- package/dist/templates/hello-world/app/components/Layout.tsx +15 -0
- package/dist/templates/hello-world/app/components/index.ts +1 -0
- package/dist/templates/hello-world/app/entry.client.tsx +4 -0
- package/dist/templates/hello-world/app/entry.server.tsx +21 -0
- package/dist/templates/hello-world/app/root.tsx +212 -0
- package/dist/templates/hello-world/app/routes/index.tsx +7 -0
- package/dist/templates/hello-world/app/styles/app.css +38 -0
- package/dist/templates/hello-world/package-lock.json +27641 -0
- package/dist/templates/hello-world/package.json +41 -0
- package/dist/templates/hello-world/public/favicon.svg +28 -0
- package/dist/templates/hello-world/remix.env.d.ts +29 -0
- package/dist/templates/hello-world/server.ts +127 -0
- package/dist/templates/hello-world/tsconfig.json +25 -0
- package/dist/utils/config.js +81 -0
- package/dist/utils/flags.js +15 -0
- package/dist/utils/log.js +20 -0
- package/dist/utils/mini-oxygen.js +70 -0
- package/package.json +27 -64
- package/tmp-create-app.mjs +29 -0
- package/LICENSE +0 -8
- package/README.md +0 -61
- package/dist/cli/commands/hydrogen/add/eslint.d.ts +0 -11
- package/dist/cli/commands/hydrogen/add/eslint.js +0 -26
- package/dist/cli/commands/hydrogen/add/eslint.js.map +0 -1
- package/dist/cli/commands/hydrogen/add/tailwind.d.ts +0 -11
- package/dist/cli/commands/hydrogen/add/tailwind.js +0 -26
- package/dist/cli/commands/hydrogen/add/tailwind.js.map +0 -1
- package/dist/cli/commands/hydrogen/build.d.ts +0 -14
- package/dist/cli/commands/hydrogen/build.js +0 -49
- package/dist/cli/commands/hydrogen/build.js.map +0 -1
- package/dist/cli/commands/hydrogen/deploy.d.ts +0 -19
- package/dist/cli/commands/hydrogen/deploy.js +0 -58
- package/dist/cli/commands/hydrogen/deploy.js.map +0 -1
- package/dist/cli/commands/hydrogen/dev.d.ts +0 -13
- package/dist/cli/commands/hydrogen/dev.js +0 -31
- package/dist/cli/commands/hydrogen/dev.js.map +0 -1
- package/dist/cli/commands/hydrogen/info.d.ts +0 -12
- package/dist/cli/commands/hydrogen/info.js +0 -28
- package/dist/cli/commands/hydrogen/info.js.map +0 -1
- package/dist/cli/commands/hydrogen/preview.d.ts +0 -13
- package/dist/cli/commands/hydrogen/preview.js +0 -46
- package/dist/cli/commands/hydrogen/preview.js.map +0 -1
- package/dist/cli/constants.d.ts +0 -15
- package/dist/cli/constants.js +0 -16
- package/dist/cli/constants.js.map +0 -1
- package/dist/cli/flags.d.ts +0 -4
- package/dist/cli/flags.js +0 -16
- package/dist/cli/flags.js.map +0 -1
- package/dist/cli/models/hydrogen.d.ts +0 -22
- package/dist/cli/models/hydrogen.js +0 -82
- package/dist/cli/models/hydrogen.js.map +0 -1
- package/dist/cli/prompts/git-init.d.ts +0 -1
- package/dist/cli/prompts/git-init.js +0 -16
- package/dist/cli/prompts/git-init.js.map +0 -1
- package/dist/cli/services/build/check-lockfile.d.ts +0 -3
- package/dist/cli/services/build/check-lockfile.js +0 -80
- package/dist/cli/services/build/check-lockfile.js.map +0 -1
- package/dist/cli/services/build.d.ts +0 -14
- package/dist/cli/services/build.js +0 -44
- package/dist/cli/services/build.js.map +0 -1
- package/dist/cli/services/deploy/config.d.ts +0 -4
- package/dist/cli/services/deploy/config.js +0 -49
- package/dist/cli/services/deploy/config.js.map +0 -1
- package/dist/cli/services/deploy/error.d.ts +0 -4
- package/dist/cli/services/deploy/error.js +0 -11
- package/dist/cli/services/deploy/error.js.map +0 -1
- package/dist/cli/services/deploy/graphql/create_deployment.d.ts +0 -10
- package/dist/cli/services/deploy/graphql/create_deployment.js +0 -15
- package/dist/cli/services/deploy/graphql/create_deployment.js.map +0 -1
- package/dist/cli/services/deploy/graphql/upload_deployment.d.ts +0 -1
- package/dist/cli/services/deploy/graphql/upload_deployment.js +0 -16
- package/dist/cli/services/deploy/graphql/upload_deployment.js.map +0 -1
- package/dist/cli/services/deploy/types.d.ts +0 -37
- package/dist/cli/services/deploy/types.js +0 -2
- package/dist/cli/services/deploy/types.js.map +0 -1
- package/dist/cli/services/deploy/upload.d.ts +0 -5
- package/dist/cli/services/deploy/upload.js +0 -81
- package/dist/cli/services/deploy/upload.js.map +0 -1
- package/dist/cli/services/deploy.d.ts +0 -2
- package/dist/cli/services/deploy.js +0 -103
- package/dist/cli/services/deploy.js.map +0 -1
- package/dist/cli/services/dev/check-version.d.ts +0 -1
- package/dist/cli/services/dev/check-version.js +0 -30
- package/dist/cli/services/dev/check-version.js.map +0 -1
- package/dist/cli/services/dev.d.ts +0 -10
- package/dist/cli/services/dev.js +0 -36
- package/dist/cli/services/dev.js.map +0 -1
- package/dist/cli/services/eslint.d.ts +0 -8
- package/dist/cli/services/eslint.js +0 -74
- package/dist/cli/services/eslint.js.map +0 -1
- package/dist/cli/services/info.d.ts +0 -7
- package/dist/cli/services/info.js +0 -131
- package/dist/cli/services/info.js.map +0 -1
- package/dist/cli/services/preview.d.ts +0 -12
- package/dist/cli/services/preview.js +0 -63
- package/dist/cli/services/preview.js.map +0 -1
- package/dist/cli/services/tailwind.d.ts +0 -9
- package/dist/cli/services/tailwind.js +0 -103
- package/dist/cli/services/tailwind.js.map +0 -1
- package/dist/cli/utilities/load-config.d.ts +0 -5
- package/dist/cli/utilities/load-config.js +0 -6
- package/dist/cli/utilities/load-config.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/oclif.manifest.json +0 -1
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type EnhancedMenu,
|
|
3
|
+
type EnhancedMenuItem,
|
|
4
|
+
useIsHomePath,
|
|
5
|
+
} from '~/lib/utils';
|
|
6
|
+
import {
|
|
7
|
+
Drawer,
|
|
8
|
+
useDrawer,
|
|
9
|
+
Text,
|
|
10
|
+
Input,
|
|
11
|
+
IconAccount,
|
|
12
|
+
IconBag,
|
|
13
|
+
IconSearch,
|
|
14
|
+
Heading,
|
|
15
|
+
IconMenu,
|
|
16
|
+
IconCaret,
|
|
17
|
+
Section,
|
|
18
|
+
CountrySelector,
|
|
19
|
+
Cart,
|
|
20
|
+
CartLoading,
|
|
21
|
+
Link,
|
|
22
|
+
} from '~/components';
|
|
23
|
+
import {useParams, Form, Await, useMatches} from '@remix-run/react';
|
|
24
|
+
import {useWindowScroll} from 'react-use';
|
|
25
|
+
import {Disclosure} from '@headlessui/react';
|
|
26
|
+
import type {LayoutData} from '~/data';
|
|
27
|
+
import {Suspense, useEffect, useMemo} from 'react';
|
|
28
|
+
import {useIsHydrated} from '~/hooks/useIsHydrated';
|
|
29
|
+
import {useCartFetchers} from '~/hooks/useCartFetchers';
|
|
30
|
+
|
|
31
|
+
export function Layout({
|
|
32
|
+
children,
|
|
33
|
+
layout,
|
|
34
|
+
}: {
|
|
35
|
+
children: React.ReactNode;
|
|
36
|
+
layout: LayoutData;
|
|
37
|
+
}) {
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
<div className="flex flex-col min-h-screen">
|
|
41
|
+
<div className="">
|
|
42
|
+
<a href="#mainContent" className="sr-only">
|
|
43
|
+
Skip to content
|
|
44
|
+
</a>
|
|
45
|
+
</div>
|
|
46
|
+
<Header
|
|
47
|
+
title={layout?.shop.name ?? 'Hydrogen'}
|
|
48
|
+
menu={layout?.headerMenu}
|
|
49
|
+
/>
|
|
50
|
+
<main role="main" id="mainContent" className="flex-grow">
|
|
51
|
+
{children}
|
|
52
|
+
</main>
|
|
53
|
+
</div>
|
|
54
|
+
<Footer menu={layout?.footerMenu} />
|
|
55
|
+
</>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function Header({title, menu}: {title: string; menu?: EnhancedMenu}) {
|
|
60
|
+
const isHome = useIsHomePath();
|
|
61
|
+
|
|
62
|
+
const {
|
|
63
|
+
isOpen: isCartOpen,
|
|
64
|
+
openDrawer: openCart,
|
|
65
|
+
closeDrawer: closeCart,
|
|
66
|
+
} = useDrawer();
|
|
67
|
+
|
|
68
|
+
const {
|
|
69
|
+
isOpen: isMenuOpen,
|
|
70
|
+
openDrawer: openMenu,
|
|
71
|
+
closeDrawer: closeMenu,
|
|
72
|
+
} = useDrawer();
|
|
73
|
+
|
|
74
|
+
const addToCartFetchers = useCartFetchers('ADD_TO_CART');
|
|
75
|
+
|
|
76
|
+
// toggle cart drawer when adding to cart
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (isCartOpen || !addToCartFetchers.length) return;
|
|
79
|
+
openCart();
|
|
80
|
+
}, [addToCartFetchers, isCartOpen, openCart]);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<>
|
|
84
|
+
<CartDrawer isOpen={isCartOpen} onClose={closeCart} />
|
|
85
|
+
{menu && (
|
|
86
|
+
<MenuDrawer isOpen={isMenuOpen} onClose={closeMenu} menu={menu} />
|
|
87
|
+
)}
|
|
88
|
+
<DesktopHeader
|
|
89
|
+
isHome={isHome}
|
|
90
|
+
title={title}
|
|
91
|
+
menu={menu}
|
|
92
|
+
openCart={openCart}
|
|
93
|
+
/>
|
|
94
|
+
<MobileHeader
|
|
95
|
+
isHome={isHome}
|
|
96
|
+
title={title}
|
|
97
|
+
openCart={openCart}
|
|
98
|
+
openMenu={openMenu}
|
|
99
|
+
/>
|
|
100
|
+
</>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function CartDrawer({isOpen, onClose}: {isOpen: boolean; onClose: () => void}) {
|
|
105
|
+
const [root] = useMatches();
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<Drawer open={isOpen} onClose={onClose} heading="Cart" openFrom="right">
|
|
109
|
+
<div className="grid">
|
|
110
|
+
<Suspense fallback={<CartLoading />}>
|
|
111
|
+
<Await resolve={root.data?.cart}>
|
|
112
|
+
{(cart) => <Cart layout="drawer" onClose={onClose} cart={cart} />}
|
|
113
|
+
</Await>
|
|
114
|
+
</Suspense>
|
|
115
|
+
</div>
|
|
116
|
+
</Drawer>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function MenuDrawer({
|
|
121
|
+
isOpen,
|
|
122
|
+
onClose,
|
|
123
|
+
menu,
|
|
124
|
+
}: {
|
|
125
|
+
isOpen: boolean;
|
|
126
|
+
onClose: () => void;
|
|
127
|
+
menu: EnhancedMenu;
|
|
128
|
+
}) {
|
|
129
|
+
return (
|
|
130
|
+
<Drawer open={isOpen} onClose={onClose} openFrom="left" heading="Menu">
|
|
131
|
+
<div className="grid">
|
|
132
|
+
<MenuMobileNav menu={menu} onClose={onClose} />
|
|
133
|
+
</div>
|
|
134
|
+
</Drawer>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function MenuMobileNav({
|
|
139
|
+
menu,
|
|
140
|
+
onClose,
|
|
141
|
+
}: {
|
|
142
|
+
menu: EnhancedMenu;
|
|
143
|
+
onClose: () => void;
|
|
144
|
+
}) {
|
|
145
|
+
const styles = {
|
|
146
|
+
link: 'pb-1',
|
|
147
|
+
linkActive: 'pb-1 border-b -mb-px',
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<nav className="grid gap-4 p-6 sm:gap-6 sm:px-12 sm:py-8">
|
|
152
|
+
{/* Top level menu items */}
|
|
153
|
+
{(menu?.items || []).map((item) => (
|
|
154
|
+
<span key={item.id} className="block">
|
|
155
|
+
<Link
|
|
156
|
+
to={item.to}
|
|
157
|
+
target={item.target}
|
|
158
|
+
onClick={onClose}
|
|
159
|
+
className={({isActive}) =>
|
|
160
|
+
isActive ? styles.linkActive : styles.link
|
|
161
|
+
}
|
|
162
|
+
>
|
|
163
|
+
<Text as="span" size="copy">
|
|
164
|
+
{item.title}
|
|
165
|
+
</Text>
|
|
166
|
+
</Link>
|
|
167
|
+
</span>
|
|
168
|
+
))}
|
|
169
|
+
</nav>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function MobileHeader({
|
|
174
|
+
title,
|
|
175
|
+
isHome,
|
|
176
|
+
openCart,
|
|
177
|
+
openMenu,
|
|
178
|
+
}: {
|
|
179
|
+
title: string;
|
|
180
|
+
isHome: boolean;
|
|
181
|
+
openCart: () => void;
|
|
182
|
+
openMenu: () => void;
|
|
183
|
+
}) {
|
|
184
|
+
const {y} = useWindowScroll();
|
|
185
|
+
|
|
186
|
+
const styles = {
|
|
187
|
+
button: 'relative flex items-center justify-center w-8 h-8',
|
|
188
|
+
container: `${
|
|
189
|
+
isHome
|
|
190
|
+
? 'bg-primary/80 dark:bg-contrast/60 text-contrast dark:text-primary shadow-darkHeader'
|
|
191
|
+
: 'bg-contrast/80 text-primary'
|
|
192
|
+
} ${
|
|
193
|
+
y > 50 && !isHome ? 'shadow-lightHeader ' : ''
|
|
194
|
+
}flex lg:hidden items-center h-nav sticky backdrop-blur-lg z-40 top-0 justify-between w-full leading-none gap-4 px-4 md:px-8`,
|
|
195
|
+
};
|
|
196
|
+
const params = useParams();
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<header role="banner" className={styles.container}>
|
|
200
|
+
<div className="flex items-center justify-start w-full gap-4">
|
|
201
|
+
<button onClick={openMenu} className={styles.button}>
|
|
202
|
+
<IconMenu />
|
|
203
|
+
</button>
|
|
204
|
+
<Form
|
|
205
|
+
method="get"
|
|
206
|
+
action={params.lang ? `/${params.lang}/search` : '/search'}
|
|
207
|
+
className="items-center gap-2 sm:flex"
|
|
208
|
+
>
|
|
209
|
+
<button type="submit" className={styles.button}>
|
|
210
|
+
<IconSearch />
|
|
211
|
+
</button>
|
|
212
|
+
<Input
|
|
213
|
+
className={
|
|
214
|
+
isHome
|
|
215
|
+
? 'focus:border-contrast/20 dark:focus:border-primary/20'
|
|
216
|
+
: 'focus:border-primary/20'
|
|
217
|
+
}
|
|
218
|
+
type="search"
|
|
219
|
+
variant="minisearch"
|
|
220
|
+
placeholder="Search"
|
|
221
|
+
name="q"
|
|
222
|
+
/>
|
|
223
|
+
</Form>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<Link
|
|
227
|
+
className="flex items-center self-stretch leading-[3rem] md:leading-[4rem] justify-center flex-grow w-full h-full"
|
|
228
|
+
to="/"
|
|
229
|
+
>
|
|
230
|
+
<Heading className="font-bold text-center" as={isHome ? 'h1' : 'h2'}>
|
|
231
|
+
{title}
|
|
232
|
+
</Heading>
|
|
233
|
+
</Link>
|
|
234
|
+
|
|
235
|
+
<div className="flex items-center justify-end w-full gap-4">
|
|
236
|
+
<Link to="/account" className={styles.button}>
|
|
237
|
+
<IconAccount />
|
|
238
|
+
</Link>
|
|
239
|
+
<CartCount isHome={isHome} openCart={openCart} />
|
|
240
|
+
</div>
|
|
241
|
+
</header>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function DesktopHeader({
|
|
246
|
+
isHome,
|
|
247
|
+
menu,
|
|
248
|
+
openCart,
|
|
249
|
+
title,
|
|
250
|
+
}: {
|
|
251
|
+
isHome: boolean;
|
|
252
|
+
openCart: () => void;
|
|
253
|
+
menu?: EnhancedMenu;
|
|
254
|
+
title: string;
|
|
255
|
+
}) {
|
|
256
|
+
const {y} = useWindowScroll();
|
|
257
|
+
const params = useParams();
|
|
258
|
+
|
|
259
|
+
const styles = {
|
|
260
|
+
link: 'pb-1',
|
|
261
|
+
linkActive: 'pb-1 border-b -mb-px',
|
|
262
|
+
button:
|
|
263
|
+
'relative flex items-center justify-center w-8 h-8 focus:ring-primary/5',
|
|
264
|
+
container: `${
|
|
265
|
+
isHome
|
|
266
|
+
? 'bg-primary/80 dark:bg-contrast/60 text-contrast dark:text-primary shadow-darkHeader'
|
|
267
|
+
: 'bg-contrast/80 text-primary'
|
|
268
|
+
} ${
|
|
269
|
+
y > 50 && !isHome ? 'shadow-lightHeader ' : ''
|
|
270
|
+
}hidden h-nav lg:flex items-center sticky transition duration-300 backdrop-blur-lg z-40 top-0 justify-between w-full leading-none gap-8 px-12 py-8`,
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<header role="banner" className={styles.container}>
|
|
275
|
+
<div className="flex gap-12">
|
|
276
|
+
<Link className="font-bold" to="/" prefetch="intent">
|
|
277
|
+
{title}
|
|
278
|
+
</Link>
|
|
279
|
+
<nav className="flex gap-8">
|
|
280
|
+
{/* Top level menu items */}
|
|
281
|
+
{(menu?.items || []).map((item) => (
|
|
282
|
+
<Link
|
|
283
|
+
key={item.id}
|
|
284
|
+
to={item.to}
|
|
285
|
+
target={item.target}
|
|
286
|
+
prefetch="intent"
|
|
287
|
+
className={({isActive}) =>
|
|
288
|
+
isActive ? styles.linkActive : styles.link
|
|
289
|
+
}
|
|
290
|
+
>
|
|
291
|
+
{item.title}
|
|
292
|
+
</Link>
|
|
293
|
+
))}
|
|
294
|
+
</nav>
|
|
295
|
+
</div>
|
|
296
|
+
<div className="flex items-center gap-1">
|
|
297
|
+
<Form
|
|
298
|
+
method="get"
|
|
299
|
+
action={params.lang ? `/${params.lang}/search` : '/search'}
|
|
300
|
+
className="flex items-center gap-2"
|
|
301
|
+
>
|
|
302
|
+
<Input
|
|
303
|
+
className={
|
|
304
|
+
isHome
|
|
305
|
+
? 'focus:border-contrast/20 dark:focus:border-primary/20'
|
|
306
|
+
: 'focus:border-primary/20'
|
|
307
|
+
}
|
|
308
|
+
type="search"
|
|
309
|
+
variant="minisearch"
|
|
310
|
+
placeholder="Search"
|
|
311
|
+
name="q"
|
|
312
|
+
/>
|
|
313
|
+
<button type="submit" className={styles.button}>
|
|
314
|
+
<IconSearch />
|
|
315
|
+
</button>
|
|
316
|
+
</Form>
|
|
317
|
+
<Link to="/account" className={styles.button}>
|
|
318
|
+
<IconAccount />
|
|
319
|
+
</Link>
|
|
320
|
+
<CartCount isHome={isHome} openCart={openCart} />
|
|
321
|
+
</div>
|
|
322
|
+
</header>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function CartCount({
|
|
327
|
+
isHome,
|
|
328
|
+
openCart,
|
|
329
|
+
}: {
|
|
330
|
+
isHome: boolean;
|
|
331
|
+
openCart: () => void;
|
|
332
|
+
}) {
|
|
333
|
+
const [root] = useMatches();
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<Suspense fallback={<Badge count={0} dark={isHome} openCart={openCart} />}>
|
|
337
|
+
<Await resolve={root.data?.cart}>
|
|
338
|
+
{(cart) => (
|
|
339
|
+
<Badge
|
|
340
|
+
dark={isHome}
|
|
341
|
+
openCart={openCart}
|
|
342
|
+
count={cart?.totalQuantity || 0}
|
|
343
|
+
/>
|
|
344
|
+
)}
|
|
345
|
+
</Await>
|
|
346
|
+
</Suspense>
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function Badge({
|
|
351
|
+
openCart,
|
|
352
|
+
dark,
|
|
353
|
+
count,
|
|
354
|
+
}: {
|
|
355
|
+
count: number;
|
|
356
|
+
dark: boolean;
|
|
357
|
+
openCart: () => void;
|
|
358
|
+
}) {
|
|
359
|
+
const isHydrated = useIsHydrated();
|
|
360
|
+
|
|
361
|
+
const BadgeCounter = useMemo(
|
|
362
|
+
() => (
|
|
363
|
+
<>
|
|
364
|
+
<IconBag />
|
|
365
|
+
<div
|
|
366
|
+
className={`${
|
|
367
|
+
dark
|
|
368
|
+
? 'text-primary bg-contrast dark:text-contrast dark:bg-primary'
|
|
369
|
+
: 'text-contrast bg-primary'
|
|
370
|
+
} absolute bottom-1 right-1 text-[0.625rem] font-medium subpixel-antialiased h-3 min-w-[0.75rem] flex items-center justify-center leading-none text-center rounded-full w-auto px-[0.125rem] pb-px`}
|
|
371
|
+
>
|
|
372
|
+
<span>{count || 0}</span>
|
|
373
|
+
</div>
|
|
374
|
+
</>
|
|
375
|
+
),
|
|
376
|
+
[count, dark],
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
return isHydrated ? (
|
|
380
|
+
<button
|
|
381
|
+
onClick={openCart}
|
|
382
|
+
className={
|
|
383
|
+
'relative flex items-center justify-center w-8 h-8 focus:ring-primary/5'
|
|
384
|
+
}
|
|
385
|
+
>
|
|
386
|
+
{BadgeCounter}
|
|
387
|
+
</button>
|
|
388
|
+
) : (
|
|
389
|
+
<Link
|
|
390
|
+
to="/cart"
|
|
391
|
+
className={
|
|
392
|
+
'relative flex items-center justify-center w-8 h-8 focus:ring-primary/5'
|
|
393
|
+
}
|
|
394
|
+
>
|
|
395
|
+
{BadgeCounter}
|
|
396
|
+
</Link>
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function Footer({menu}: {menu?: EnhancedMenu}) {
|
|
401
|
+
const isHome = useIsHomePath();
|
|
402
|
+
const itemsCount = menu
|
|
403
|
+
? menu?.items?.length + 1 > 4
|
|
404
|
+
? 4
|
|
405
|
+
: menu?.items?.length + 1
|
|
406
|
+
: [];
|
|
407
|
+
|
|
408
|
+
return (
|
|
409
|
+
<Section
|
|
410
|
+
divider={isHome ? 'none' : 'top'}
|
|
411
|
+
as="footer"
|
|
412
|
+
role="contentinfo"
|
|
413
|
+
className={`grid min-h-[25rem] items-start grid-flow-row w-full gap-6 py-8 px-6 md:px-8 lg:px-12
|
|
414
|
+
border-b md:gap-8 lg:gap-12 grid-cols-1 md:grid-cols-2 lg:grid-cols-${itemsCount}
|
|
415
|
+
bg-primary dark:bg-contrast dark:text-primary text-contrast overflow-hidden`}
|
|
416
|
+
>
|
|
417
|
+
<FooterMenu menu={menu} />
|
|
418
|
+
<CountrySelector />
|
|
419
|
+
<div
|
|
420
|
+
className={`self-end pt-8 opacity-50 md:col-span-2 lg:col-span-${itemsCount}`}
|
|
421
|
+
>
|
|
422
|
+
© {new Date().getFullYear()} / Shopify, Inc. Hydrogen is an MIT
|
|
423
|
+
Licensed Open Source project. This website is carbon neutral.
|
|
424
|
+
</div>
|
|
425
|
+
</Section>
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const FooterLink = ({item}: {item: EnhancedMenuItem}) => {
|
|
430
|
+
if (item.to.startsWith('http')) {
|
|
431
|
+
return (
|
|
432
|
+
<a href={item.to} target={item.target} rel="noopener noreferrer">
|
|
433
|
+
{item.title}
|
|
434
|
+
</a>
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
return (
|
|
439
|
+
<Link to={item.to} target={item.target} prefetch="intent">
|
|
440
|
+
{item.title}
|
|
441
|
+
</Link>
|
|
442
|
+
);
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
function FooterMenu({menu}: {menu?: EnhancedMenu}) {
|
|
446
|
+
const styles = {
|
|
447
|
+
section: 'grid gap-4',
|
|
448
|
+
nav: 'grid gap-2 pb-6',
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
<>
|
|
453
|
+
{(menu?.items || []).map((item: EnhancedMenuItem) => (
|
|
454
|
+
<section key={item.id} className={styles.section}>
|
|
455
|
+
<Disclosure>
|
|
456
|
+
{({open}) => (
|
|
457
|
+
<>
|
|
458
|
+
<Disclosure.Button className="text-left md:cursor-default">
|
|
459
|
+
<Heading className="flex justify-between" size="lead" as="h3">
|
|
460
|
+
{item.title}
|
|
461
|
+
{item?.items?.length > 0 && (
|
|
462
|
+
<span className="md:hidden">
|
|
463
|
+
<IconCaret direction={open ? 'up' : 'down'} />
|
|
464
|
+
</span>
|
|
465
|
+
)}
|
|
466
|
+
</Heading>
|
|
467
|
+
</Disclosure.Button>
|
|
468
|
+
{item?.items?.length > 0 ? (
|
|
469
|
+
<div
|
|
470
|
+
className={`${
|
|
471
|
+
open ? `max-h-48 h-fit` : `max-h-0 md:max-h-fit`
|
|
472
|
+
} overflow-hidden transition-all duration-300`}
|
|
473
|
+
>
|
|
474
|
+
<Suspense data-comment="This suspense fixes a hydration bug in Disclosure.Panel with static prop">
|
|
475
|
+
<Disclosure.Panel static>
|
|
476
|
+
<nav className={styles.nav}>
|
|
477
|
+
{item.items.map((subItem) => (
|
|
478
|
+
<FooterLink key={subItem.id} item={subItem} />
|
|
479
|
+
))}
|
|
480
|
+
</nav>
|
|
481
|
+
</Disclosure.Panel>
|
|
482
|
+
</Suspense>
|
|
483
|
+
</div>
|
|
484
|
+
) : null}
|
|
485
|
+
</>
|
|
486
|
+
)}
|
|
487
|
+
</Disclosure>
|
|
488
|
+
</section>
|
|
489
|
+
))}{' '}
|
|
490
|
+
</>
|
|
491
|
+
);
|
|
492
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Link as RemixLink,
|
|
3
|
+
NavLink as RemixNavLink,
|
|
4
|
+
type NavLinkProps as RemixNavLinkProps,
|
|
5
|
+
type LinkProps as RemixLinkProps,
|
|
6
|
+
useMatches,
|
|
7
|
+
} from '@remix-run/react';
|
|
8
|
+
|
|
9
|
+
type LinkProps = Omit<RemixLinkProps, 'className'> & {
|
|
10
|
+
className?: RemixNavLinkProps['className'] | RemixLinkProps['className'];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* In our app, we've chosen to wrap Remix's `Link` component to add
|
|
15
|
+
* helper functionality. If the `to` value is a string (not object syntax),
|
|
16
|
+
* we prefix the locale to the path if there is one.
|
|
17
|
+
*
|
|
18
|
+
* You could implement the same behavior throughout your app using the
|
|
19
|
+
* Remix-native nested routes. However, your route and component structure
|
|
20
|
+
* changes the level of nesting required to get the locale into the route,
|
|
21
|
+
* which may not be ideal for shared components or layouts.
|
|
22
|
+
*
|
|
23
|
+
* Likewise, your internationalization strategy may not require a locale
|
|
24
|
+
* in the pathname and instead rely on a domain, cookie, or header.
|
|
25
|
+
*
|
|
26
|
+
* Ultimately, it is up to you to decide how to implement this behavior.
|
|
27
|
+
*/
|
|
28
|
+
export function Link(props: LinkProps) {
|
|
29
|
+
const {to, className, ...resOfProps} = props;
|
|
30
|
+
const [root] = useMatches();
|
|
31
|
+
const selectedLocale = root.data?.selectedLocale;
|
|
32
|
+
|
|
33
|
+
let toWithLocale = to;
|
|
34
|
+
|
|
35
|
+
if (typeof to === 'string') {
|
|
36
|
+
toWithLocale = selectedLocale ? `${selectedLocale.pathPrefix}${to}` : to;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof className === 'function') {
|
|
40
|
+
return (
|
|
41
|
+
<RemixNavLink to={toWithLocale} className={className} {...resOfProps} />
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return <RemixLink to={toWithLocale} className={className} {...resOfProps} />;
|
|
46
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {IconClose, Link} from '~/components';
|
|
2
|
+
|
|
3
|
+
export function Modal({
|
|
4
|
+
children,
|
|
5
|
+
cancelLink,
|
|
6
|
+
}: {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
cancelLink: string;
|
|
9
|
+
}) {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
className="relative z-50"
|
|
13
|
+
aria-labelledby="modal-title"
|
|
14
|
+
role="dialog"
|
|
15
|
+
aria-modal="true"
|
|
16
|
+
id="modal-bg"
|
|
17
|
+
>
|
|
18
|
+
<div className="fixed inset-0 transition-opacity bg-opacity-75 bg-primary/40"></div>
|
|
19
|
+
<div className="fixed inset-0 z-50 overflow-y-auto">
|
|
20
|
+
<div className="flex items-center justify-center min-h-full p-4 text-center sm:p-0">
|
|
21
|
+
<div
|
|
22
|
+
className="relative flex-1 px-4 pt-5 pb-4 overflow-hidden text-left transition-all transform rounded shadow-xl bg-contrast sm:my-12 sm:flex-none sm:w-full sm:max-w-sm sm:p-6"
|
|
23
|
+
role="button"
|
|
24
|
+
onClick={(e) => {
|
|
25
|
+
e.stopPropagation();
|
|
26
|
+
}}
|
|
27
|
+
onKeyPress={(e) => {
|
|
28
|
+
e.stopPropagation();
|
|
29
|
+
}}
|
|
30
|
+
tabIndex={0}
|
|
31
|
+
>
|
|
32
|
+
<div className="absolute top-0 right-0 hidden pt-4 pr-4 sm:block">
|
|
33
|
+
<Link
|
|
34
|
+
to={cancelLink}
|
|
35
|
+
className="p-4 -m-4 transition text-primary hover:text-primary/50"
|
|
36
|
+
>
|
|
37
|
+
<IconClose aria-label="Close panel" />
|
|
38
|
+
</Link>
|
|
39
|
+
</div>
|
|
40
|
+
{children}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {Button} from './Button';
|
|
2
|
+
import {FeaturedSection} from './FeaturedSection';
|
|
3
|
+
import {PageHeader, Text} from './Text';
|
|
4
|
+
|
|
5
|
+
export function NotFound({type = 'page'}: {type?: string}) {
|
|
6
|
+
const heading = `We’ve lost this ${type}`;
|
|
7
|
+
const description = `We couldn’t find the ${type} you’re looking for. Try checking the URL or heading back to the home page.`;
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<>
|
|
11
|
+
<PageHeader heading={heading}>
|
|
12
|
+
<Text width="narrow" as="p">
|
|
13
|
+
{description}
|
|
14
|
+
</Text>
|
|
15
|
+
<Button width="auto" variant="secondary" to={'/'}>
|
|
16
|
+
Take me to the home page
|
|
17
|
+
</Button>
|
|
18
|
+
</PageHeader>
|
|
19
|
+
<FeaturedSection />
|
|
20
|
+
</>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {flattenConnection} from '@shopify/hydrogen-react';
|
|
2
|
+
import type {
|
|
3
|
+
Order,
|
|
4
|
+
OrderLineItem,
|
|
5
|
+
} from '@shopify/hydrogen-react/storefront-api-types';
|
|
6
|
+
import {Heading, Text, Link} from '~/components';
|
|
7
|
+
import {statusMessage} from '~/lib/utils';
|
|
8
|
+
|
|
9
|
+
export function OrderCard({order}: {order: Order}) {
|
|
10
|
+
if (!order?.id) return null;
|
|
11
|
+
const [legacyOrderId, key] = order!.id!.split('/').pop()!.split('?');
|
|
12
|
+
const lineItems = flattenConnection<OrderLineItem>(order?.lineItems);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<li className="grid text-center border rounded">
|
|
16
|
+
<Link
|
|
17
|
+
className="grid items-center gap-4 p-4 md:gap-6 md:p-6 md:grid-cols-2"
|
|
18
|
+
to={`/account/orders/${legacyOrderId}?${key}`}
|
|
19
|
+
prefetch="intent"
|
|
20
|
+
>
|
|
21
|
+
{lineItems[0].variant?.image && (
|
|
22
|
+
<div className="card-image aspect-square bg-primary/5">
|
|
23
|
+
<img
|
|
24
|
+
width={168}
|
|
25
|
+
height={168}
|
|
26
|
+
className="w-full fadeIn cover"
|
|
27
|
+
alt={lineItems[0].variant?.image?.altText ?? 'Order image'}
|
|
28
|
+
src={lineItems[0].variant?.image.url}
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
)}
|
|
32
|
+
<div
|
|
33
|
+
className={`flex-col justify-center text-left ${
|
|
34
|
+
!lineItems[0].variant?.image && 'md:col-span-2'
|
|
35
|
+
}`}
|
|
36
|
+
>
|
|
37
|
+
<Heading as="h3" format size="copy">
|
|
38
|
+
{lineItems.length > 1
|
|
39
|
+
? `${lineItems[0].title} +${lineItems.length - 1} more`
|
|
40
|
+
: lineItems[0].title}
|
|
41
|
+
</Heading>
|
|
42
|
+
<dl className="grid grid-gap-1">
|
|
43
|
+
<dt className="sr-only">Order ID</dt>
|
|
44
|
+
<dd>
|
|
45
|
+
<Text size="fine" color="subtle">
|
|
46
|
+
Order No. {order.orderNumber}
|
|
47
|
+
</Text>
|
|
48
|
+
</dd>
|
|
49
|
+
<dt className="sr-only">Order Date</dt>
|
|
50
|
+
<dd>
|
|
51
|
+
<Text size="fine" color="subtle">
|
|
52
|
+
{new Date(order.processedAt).toDateString()}
|
|
53
|
+
</Text>
|
|
54
|
+
</dd>
|
|
55
|
+
<dt className="sr-only">Fulfillment Status</dt>
|
|
56
|
+
<dd className="mt-2">
|
|
57
|
+
<span
|
|
58
|
+
className={`px-3 py-1 text-xs font-medium rounded-full ${
|
|
59
|
+
order.fulfillmentStatus === 'FULFILLED'
|
|
60
|
+
? 'bg-green-100 text-green-800'
|
|
61
|
+
: 'bg-primary/5 text-primary/50'
|
|
62
|
+
}`}
|
|
63
|
+
>
|
|
64
|
+
<Text size="fine">
|
|
65
|
+
{statusMessage(order.fulfillmentStatus)}
|
|
66
|
+
</Text>
|
|
67
|
+
</span>
|
|
68
|
+
</dd>
|
|
69
|
+
</dl>
|
|
70
|
+
</div>
|
|
71
|
+
</Link>
|
|
72
|
+
<div className="self-end border-t">
|
|
73
|
+
<Link
|
|
74
|
+
className="block w-full p-2 text-center"
|
|
75
|
+
to={`/account/orders/${legacyOrderId}?${key}`}
|
|
76
|
+
prefetch="intent"
|
|
77
|
+
>
|
|
78
|
+
<Text color="subtle" className="ml-3">
|
|
79
|
+
View Details
|
|
80
|
+
</Text>
|
|
81
|
+
</Link>
|
|
82
|
+
</div>
|
|
83
|
+
</li>
|
|
84
|
+
);
|
|
85
|
+
}
|