@shopify/create-hydrogen 0.1.3 → 0.15.0
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/CHANGELOG.md +6 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +5 -0
- package/dist/commands/init.js +76390 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -14
- package/templates/template-hydrogen/.devcontainer/devcontainer.json +18 -0
- package/templates/template-hydrogen/.eslintrc.js +3 -0
- package/templates/template-hydrogen/.gitignore +7 -0
- package/templates/template-hydrogen/.stackblitzrc +4 -0
- package/{template-hydrogen → templates/template-hydrogen}/.stylelintrc.js +1 -1
- package/templates/template-hydrogen/.vscode/extensions.json +8 -0
- package/templates/template-hydrogen/Dockerfile +15 -0
- package/{template-hydrogen → templates/template-hydrogen}/README.md +11 -2
- package/{template-hydrogen → templates/template-hydrogen}/_gitignore +0 -0
- package/templates/template-hydrogen/index.html +20 -0
- package/{template-hydrogen → templates/template-hydrogen}/package.json +20 -15
- package/{template-hydrogen → templates/template-hydrogen}/postcss.config.js +0 -0
- package/{template-hydrogen/src → templates/template-hydrogen/public}/favicon.svg +0 -0
- package/{template-hydrogen → templates/template-hydrogen}/server.js +4 -2
- package/{template-hydrogen → templates/template-hydrogen}/shopify.config.js +1 -2
- package/templates/template-hydrogen/src/App.client.jsx +8 -0
- package/templates/template-hydrogen/src/App.server.jsx +27 -0
- package/templates/template-hydrogen/src/components/Button.client.jsx +65 -0
- package/templates/template-hydrogen/src/components/Cart.client.jsx +265 -0
- package/templates/template-hydrogen/src/components/CartIcon.jsx +33 -0
- package/templates/template-hydrogen/src/components/CartIconWithItems.client.jsx +28 -0
- package/templates/template-hydrogen/src/components/CartProvider.client.jsx +35 -0
- package/templates/template-hydrogen/src/components/CartToggle.client.jsx +30 -0
- package/templates/template-hydrogen/src/components/CartUIProvider.client.jsx +45 -0
- package/templates/template-hydrogen/src/components/CountrySelector.client.jsx +116 -0
- package/templates/template-hydrogen/src/components/DefaultSeo.server.jsx +35 -0
- package/templates/template-hydrogen/src/components/FeaturedCollection.jsx +26 -0
- package/templates/template-hydrogen/src/components/Footer.server.jsx +103 -0
- package/templates/template-hydrogen/src/components/Gallery.client.jsx +65 -0
- package/templates/template-hydrogen/src/components/Header.client.jsx +62 -0
- package/templates/template-hydrogen/src/components/Layout.server.jsx +87 -0
- package/templates/template-hydrogen/src/components/LoadMoreProducts.client.jsx +56 -0
- package/templates/template-hydrogen/src/components/LoadingFallback.jsx +26 -0
- package/templates/template-hydrogen/src/components/MobileCountrySelector.client.jsx +64 -0
- package/templates/template-hydrogen/src/components/MobileNavigation.client.jsx +98 -0
- package/templates/template-hydrogen/src/components/MoneyCompareAtPrice.client.jsx +14 -0
- package/templates/template-hydrogen/src/components/MoneyPrice.client.jsx +15 -0
- package/templates/template-hydrogen/src/components/Navigation.client.jsx +23 -0
- package/templates/template-hydrogen/src/components/NotFound.server.jsx +93 -0
- package/templates/template-hydrogen/src/components/OpenIcon.jsx +33 -0
- package/templates/template-hydrogen/src/components/ProductCard.jsx +50 -0
- package/templates/template-hydrogen/src/components/ProductDetails.client.jsx +242 -0
- package/{template-hydrogen → templates/template-hydrogen}/src/components/ProductOptions.client.jsx +7 -4
- package/templates/template-hydrogen/src/components/Welcome.server.jsx +188 -0
- package/templates/template-hydrogen/src/entry-client.jsx +7 -0
- package/templates/template-hydrogen/src/entry-server.jsx +6 -0
- package/{template-hydrogen → templates/template-hydrogen}/src/index.css +31 -0
- package/templates/template-hydrogen/src/pages/collections/[handle].server.jsx +105 -0
- package/templates/template-hydrogen/src/pages/index.server.jsx +237 -0
- package/{template-hydrogen → templates/template-hydrogen}/src/pages/pages/[handle].server.jsx +14 -5
- package/templates/template-hydrogen/src/pages/products/[handle].server.jsx +69 -0
- package/templates/template-hydrogen/src/pages/redirect.server.jsx +4 -0
- package/templates/template-hydrogen/src/pages/robots.txt.server.js +10 -0
- package/{template-hydrogen → templates/template-hydrogen}/src/pages/sitemap.xml.server.jsx +2 -2
- package/templates/template-hydrogen/tailwind.config.js +26 -0
- package/{template-hydrogen → templates/template-hydrogen}/vite.config.js +1 -0
- package/{template-hydrogen → templates/template-hydrogen}/worker.js +1 -0
- package/index.js +0 -201
- package/scripts/tmp-copy-template-from-dev.js +0 -21
- package/scripts/utils.js +0 -29
- package/template-hydrogen/.eslintrc.js +0 -41
- package/template-hydrogen/.vscode/extensions.json +0 -3
- package/template-hydrogen/Dockerfile +0 -15
- package/template-hydrogen/index.html +0 -14
- package/template-hydrogen/src/App.server.jsx +0 -42
- package/template-hydrogen/src/components/Cart.client.jsx +0 -288
- package/template-hydrogen/src/components/CartProvider.client.jsx +0 -15
- package/template-hydrogen/src/components/DefaultSeo.server.jsx +0 -22
- package/template-hydrogen/src/components/Footer.jsx +0 -12
- package/template-hydrogen/src/components/Gallery.client.jsx +0 -36
- package/template-hydrogen/src/components/Header.client.jsx +0 -46
- package/template-hydrogen/src/components/HightlightedProduct.client.jsx +0 -54
- package/template-hydrogen/src/components/Layout.client.jsx +0 -61
- package/template-hydrogen/src/components/MediaPlaceholder.jsx +0 -21
- package/template-hydrogen/src/components/NotFound.server.jsx +0 -104
- package/template-hydrogen/src/components/ProductCard.client.jsx +0 -39
- package/template-hydrogen/src/components/ProductDetails.client.jsx +0 -184
- package/template-hydrogen/src/components/Seo.client.jsx +0 -75
- package/template-hydrogen/src/entry-client.jsx +0 -12
- package/template-hydrogen/src/entry-server.jsx +0 -7
- package/template-hydrogen/src/pages/Index.server.jsx +0 -197
- package/template-hydrogen/src/pages/blogs/[handle]/[articleHandle].server.jsx +0 -49
- package/template-hydrogen/src/pages/blogs/[handle].server.jsx +0 -76
- package/template-hydrogen/src/pages/collections/[handle].server.jsx +0 -69
- package/template-hydrogen/src/pages/products/[handle].server.jsx +0 -60
- package/template-hydrogen/src/pages/search.server.jsx +0 -107
- package/template-hydrogen/tailwind.config.js +0 -9
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {useShopQuery} from '@shopify/hydrogen';
|
|
2
|
-
import gql from 'graphql-tag';
|
|
3
|
-
|
|
4
|
-
import Seo from './Seo.client';
|
|
5
|
-
|
|
6
|
-
export default function SeoServer() {
|
|
7
|
-
const {
|
|
8
|
-
data: {
|
|
9
|
-
shop: {name: shopName},
|
|
10
|
-
},
|
|
11
|
-
} = useShopQuery({query: QUERY});
|
|
12
|
-
|
|
13
|
-
return <Seo shopName={shopName} />;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const QUERY = gql`
|
|
17
|
-
query shopName {
|
|
18
|
-
shop {
|
|
19
|
-
name
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
`;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export default function Footer() {
|
|
2
|
-
return (
|
|
3
|
-
<footer
|
|
4
|
-
role="contentinfo"
|
|
5
|
-
className="flex items-center justify-between p-4 md:py-8 md:px-8 max-w-7xl mx-auto"
|
|
6
|
-
>
|
|
7
|
-
<p className="text-gray-600">© 2021 Shopify</p>
|
|
8
|
-
<div>{/* TODO: Payment icons */}</div>
|
|
9
|
-
<p className="text-gray-400">Powered by Shopify</p>
|
|
10
|
-
</footer>
|
|
11
|
-
);
|
|
12
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {useProduct, MediaFile} from '@shopify/hydrogen/client';
|
|
2
|
-
|
|
3
|
-
export default function Gallery() {
|
|
4
|
-
return (
|
|
5
|
-
<>
|
|
6
|
-
<GalleryPreview />
|
|
7
|
-
</>
|
|
8
|
-
);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function GalleryPreview() {
|
|
12
|
-
const {media} = useProduct();
|
|
13
|
-
|
|
14
|
-
if (!media.length) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<ul className="grid lg:grid-cols-2 gap-10">
|
|
20
|
-
{media.map((med) => {
|
|
21
|
-
return (
|
|
22
|
-
<li key={med.id} className="relative">
|
|
23
|
-
<MediaFile
|
|
24
|
-
className="w-full bg-white rounded-md object-cover"
|
|
25
|
-
media={med}
|
|
26
|
-
options={{
|
|
27
|
-
height: '1000',
|
|
28
|
-
crop: 'center',
|
|
29
|
-
}}
|
|
30
|
-
/>
|
|
31
|
-
</li>
|
|
32
|
-
);
|
|
33
|
-
})}
|
|
34
|
-
</ul>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import {Link, CartToggle} from '@shopify/hydrogen/client';
|
|
2
|
-
|
|
3
|
-
import {CartIcon} from './Cart.client';
|
|
4
|
-
|
|
5
|
-
export default function Header() {
|
|
6
|
-
return (
|
|
7
|
-
<header
|
|
8
|
-
className="z-10 relative flex items-center justify-between pt-3 md:pt-12 md:pb-4 md:px-8 max-w-7xl mx-auto"
|
|
9
|
-
role="banner"
|
|
10
|
-
>
|
|
11
|
-
<nav>
|
|
12
|
-
<ul className="hidden md:flex items-center justify-center space-x-6 font-medium relative">
|
|
13
|
-
<li>
|
|
14
|
-
<Link to="/">Home</Link>
|
|
15
|
-
</li>
|
|
16
|
-
<li>
|
|
17
|
-
<Link to="/" className="flex items-center justify-center">
|
|
18
|
-
Collections
|
|
19
|
-
<svg
|
|
20
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
21
|
-
className="h-5 w-5"
|
|
22
|
-
viewBox="0 0 20 20"
|
|
23
|
-
fill="currentColor"
|
|
24
|
-
>
|
|
25
|
-
<path
|
|
26
|
-
fillRule="evenodd"
|
|
27
|
-
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
|
28
|
-
clipRule="evenodd"
|
|
29
|
-
/>
|
|
30
|
-
</svg>
|
|
31
|
-
</Link>
|
|
32
|
-
</li>
|
|
33
|
-
</ul>
|
|
34
|
-
</nav>
|
|
35
|
-
<Link
|
|
36
|
-
className="text-center font-bold uppercase text-2xl tracking-widest absolute left-1/2 transform -translate-x-1/2"
|
|
37
|
-
to="/"
|
|
38
|
-
>
|
|
39
|
-
My Shop
|
|
40
|
-
</Link>
|
|
41
|
-
<CartToggle className="h-12 w-12 p-2 mr-2 md:mr-0 md:h-7 md:w-7 md:p-0">
|
|
42
|
-
<CartIcon />
|
|
43
|
-
</CartToggle>
|
|
44
|
-
</header>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ProductProvider,
|
|
3
|
-
SelectedVariantImage,
|
|
4
|
-
ProductTitle,
|
|
5
|
-
SelectedVariantPrice,
|
|
6
|
-
SelectedVariantAddToCartButton,
|
|
7
|
-
Link,
|
|
8
|
-
} from '@shopify/hydrogen/client';
|
|
9
|
-
|
|
10
|
-
import ProductOptions from './ProductOptions.client';
|
|
11
|
-
|
|
12
|
-
export default function HighlightedProduct({product}) {
|
|
13
|
-
if (!product) {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<ProductProvider
|
|
19
|
-
product={product}
|
|
20
|
-
initialVariantId={product.variants.edges[0].node.id}
|
|
21
|
-
>
|
|
22
|
-
<SelectedVariantImage className="rounded-md bg-gray-100 w-full md:min-h-96 md:w-96 object-cover" />
|
|
23
|
-
<div className="pt-4 md:pl-10 w-full flex flex-col">
|
|
24
|
-
<Link to={`/products/${product.handle}`}>
|
|
25
|
-
<ProductTitle className="text-gray-900 text-xl md:text-3xl font-medium" />
|
|
26
|
-
</Link>
|
|
27
|
-
<div className="my-2 md:my-4 md:mb-16">
|
|
28
|
-
<SelectedVariantPrice className="font-semibold md:font-medium text-gray-900 md:text-xl">
|
|
29
|
-
{({currencyCode, amount, currencyNarrowSymbol}) => {
|
|
30
|
-
return (
|
|
31
|
-
<span>{`${currencyCode} ${currencyNarrowSymbol}${amount}`}</span>
|
|
32
|
-
);
|
|
33
|
-
}}
|
|
34
|
-
</SelectedVariantPrice>
|
|
35
|
-
<SelectedVariantPrice
|
|
36
|
-
priceType="compareAt"
|
|
37
|
-
className="text-gray-400 line-through md:text-xl"
|
|
38
|
-
>
|
|
39
|
-
{({amount, currencyNarrowSymbol}) => {
|
|
40
|
-
return <span>{`${currencyNarrowSymbol}${amount}`}</span>;
|
|
41
|
-
}}
|
|
42
|
-
</SelectedVariantPrice>
|
|
43
|
-
</div>
|
|
44
|
-
<ProductOptions />
|
|
45
|
-
<SelectedVariantAddToCartButton className="rounded-md bg-gray-900 text-white text-center p-4 text-sm uppercase w-full mt-4 mb-2">
|
|
46
|
-
Add to bag
|
|
47
|
-
</SelectedVariantAddToCartButton>
|
|
48
|
-
<p className="text-gray-500 text-xs text-center">
|
|
49
|
-
Free shipping and 30 day returns
|
|
50
|
-
</p>
|
|
51
|
-
</div>
|
|
52
|
-
</ProductProvider>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CartUIProvider,
|
|
3
|
-
CartContainer,
|
|
4
|
-
useCartUI,
|
|
5
|
-
} from '@shopify/hydrogen/client';
|
|
6
|
-
|
|
7
|
-
import Header from './Header.client';
|
|
8
|
-
import Footer from './Footer';
|
|
9
|
-
import Cart from './Cart.client';
|
|
10
|
-
|
|
11
|
-
export default function Layout({children}) {
|
|
12
|
-
return (
|
|
13
|
-
<CartUIProvider>
|
|
14
|
-
<InnerLayout>{children}</InnerLayout>
|
|
15
|
-
</CartUIProvider>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function InnerLayout({children}) {
|
|
20
|
-
const {isCartOpen, closeCart} = useCartUI();
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<>
|
|
24
|
-
<div className="absolute top-0 left-0">
|
|
25
|
-
<a
|
|
26
|
-
href="#mainContent"
|
|
27
|
-
className="p-4 focus:block sr-only focus:not-sr-only"
|
|
28
|
-
>
|
|
29
|
-
Skip to content
|
|
30
|
-
</a>
|
|
31
|
-
</div>
|
|
32
|
-
<div className="min-h-screen max-w-screen text-gray-700">
|
|
33
|
-
<Header />
|
|
34
|
-
{/* eslint-disable-next-line @shopify/jsx-prefer-fragment-wrappers */}
|
|
35
|
-
<div>
|
|
36
|
-
<div
|
|
37
|
-
className={`z-50 fixed top-0 bottom-0 left-0 right-0 bg-black transition-opacity duration-400 ${
|
|
38
|
-
isCartOpen ? 'opacity-20' : 'opacity-0 pointer-events-none'
|
|
39
|
-
}`}
|
|
40
|
-
onClick={isCartOpen ? closeCart : null}
|
|
41
|
-
/>
|
|
42
|
-
<CartContainer
|
|
43
|
-
id="cart"
|
|
44
|
-
className={`pointer-events-none z-50 fixed right-0 top-0 bottom-0 md:p-5 flex flex-col w-full max-w-md min-w-sm transition-transform duration-500 transform-gpu ${
|
|
45
|
-
isCartOpen ? 'right-0' : 'translate-x-full'
|
|
46
|
-
}`}
|
|
47
|
-
>
|
|
48
|
-
<Cart />
|
|
49
|
-
</CartContainer>
|
|
50
|
-
</div>
|
|
51
|
-
<main
|
|
52
|
-
id="mainContent"
|
|
53
|
-
className="mx-auto max-w-7xl p-4 md:py-5 md:px-8"
|
|
54
|
-
>
|
|
55
|
-
{children}
|
|
56
|
-
</main>
|
|
57
|
-
<Footer />
|
|
58
|
-
</div>
|
|
59
|
-
</>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export default function MediaPlaceholder({text}) {
|
|
2
|
-
return (
|
|
3
|
-
<div className="text-gray-500 h-full w-full p-4 bg-gray-200 flex flex-col items-center justify-center space-y-4">
|
|
4
|
-
<svg
|
|
5
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
6
|
-
className="h-10 w-10"
|
|
7
|
-
fill="none"
|
|
8
|
-
viewBox="0 0 24 24"
|
|
9
|
-
stroke="currentColor"
|
|
10
|
-
>
|
|
11
|
-
<path
|
|
12
|
-
strokeLinecap="round"
|
|
13
|
-
strokeLinejoin="round"
|
|
14
|
-
strokeWidth={2}
|
|
15
|
-
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
16
|
-
/>
|
|
17
|
-
</svg>
|
|
18
|
-
{text && <p className="text-sm max-w-xs text-center">{text}</p>}
|
|
19
|
-
</div>
|
|
20
|
-
);
|
|
21
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import {useShopQuery, MediaFile} from '@shopify/hydrogen';
|
|
2
|
-
import {Link} from '@shopify/hydrogen/client';
|
|
3
|
-
import gql from 'graphql-tag';
|
|
4
|
-
|
|
5
|
-
import Layout from './Layout.client';
|
|
6
|
-
import ProductCard from './ProductCard.client';
|
|
7
|
-
|
|
8
|
-
export default function NotFound() {
|
|
9
|
-
const {data} = useShopQuery({query: QUERY});
|
|
10
|
-
const {products} = data;
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<Layout>
|
|
14
|
-
<div className="text-center py-10 md:py-40 max-w-2xl mx-auto space-y-6">
|
|
15
|
-
<h1 className="text-4xl font-extrabold leading-tight">
|
|
16
|
-
We’ve lost this page
|
|
17
|
-
</h1>
|
|
18
|
-
<p className="text-xl text-gray-500">
|
|
19
|
-
We couldn’t find the page you’re looking for. Try checking the URL or
|
|
20
|
-
heading back to the home page.
|
|
21
|
-
</p>
|
|
22
|
-
<Link
|
|
23
|
-
className="block max-w-md mx-auto text-white p-3 rounded mb-8 uppercase text-lg bg-black"
|
|
24
|
-
to="/"
|
|
25
|
-
>
|
|
26
|
-
Take me to the home page
|
|
27
|
-
</Link>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<hr className="border-gray-300" />
|
|
31
|
-
|
|
32
|
-
<h2 className="my-8 text-2xl text-gray-700 font-bold">
|
|
33
|
-
Products you might like
|
|
34
|
-
</h2>
|
|
35
|
-
|
|
36
|
-
<ul className="grid lg:grid-cols-3 gap-6 my-4">
|
|
37
|
-
{products.edges.map((edge) => (
|
|
38
|
-
<li key={edge.node.id}>
|
|
39
|
-
<ProductCard product={edge.node} />
|
|
40
|
-
</li>
|
|
41
|
-
))}
|
|
42
|
-
</ul>
|
|
43
|
-
</Layout>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const QUERY = gql`
|
|
48
|
-
fragment NotFoundProductDetails on Product {
|
|
49
|
-
id
|
|
50
|
-
title
|
|
51
|
-
handle
|
|
52
|
-
priceRange {
|
|
53
|
-
maxVariantPrice {
|
|
54
|
-
amount
|
|
55
|
-
currencyCode
|
|
56
|
-
}
|
|
57
|
-
minVariantPrice {
|
|
58
|
-
amount
|
|
59
|
-
currencyCode
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
variants(first: 1) {
|
|
63
|
-
edges {
|
|
64
|
-
node {
|
|
65
|
-
priceV2 {
|
|
66
|
-
currencyCode
|
|
67
|
-
amount
|
|
68
|
-
}
|
|
69
|
-
compareAtPriceV2 {
|
|
70
|
-
currencyCode
|
|
71
|
-
amount
|
|
72
|
-
}
|
|
73
|
-
image {
|
|
74
|
-
...ImageFragment
|
|
75
|
-
}
|
|
76
|
-
selectedOptions {
|
|
77
|
-
name
|
|
78
|
-
value
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
media(first: 1) {
|
|
84
|
-
edges {
|
|
85
|
-
node {
|
|
86
|
-
...MediaFileFragment
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
query Products {
|
|
93
|
-
products(first: 3) {
|
|
94
|
-
edges {
|
|
95
|
-
node {
|
|
96
|
-
id
|
|
97
|
-
...NotFoundProductDetails
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
${MediaFile.Fragment}
|
|
104
|
-
`;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Link,
|
|
3
|
-
ProductProvider,
|
|
4
|
-
ProductTitle,
|
|
5
|
-
SelectedVariantImage,
|
|
6
|
-
SelectedVariantPrice,
|
|
7
|
-
} from '@shopify/hydrogen/client';
|
|
8
|
-
|
|
9
|
-
export default function ProductCard({product}) {
|
|
10
|
-
const firstVariant = product?.variants?.edges[0]?.node;
|
|
11
|
-
|
|
12
|
-
if (!product) return null;
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<ProductProvider product={product} initialVariantId={firstVariant.id}>
|
|
16
|
-
<Link to={`/products/${product.handle}`}>
|
|
17
|
-
<SelectedVariantImage className="rounded-md bg-gray-100 h-80 w-96 mb-2" />
|
|
18
|
-
<ProductTitle className="text-gray-900 font-medium" />
|
|
19
|
-
</Link>
|
|
20
|
-
<div className="flex items-center">
|
|
21
|
-
<SelectedVariantPrice className="text-gray-900">
|
|
22
|
-
{({currencyCode, amount, currencyNarrowSymbol}) => {
|
|
23
|
-
return (
|
|
24
|
-
<span>{`${currencyCode} ${currencyNarrowSymbol}${amount}`}</span>
|
|
25
|
-
);
|
|
26
|
-
}}
|
|
27
|
-
</SelectedVariantPrice>
|
|
28
|
-
<SelectedVariantPrice
|
|
29
|
-
priceType="compareAt"
|
|
30
|
-
className="text-gray-400 line-through"
|
|
31
|
-
>
|
|
32
|
-
{({amount, currencyNarrowSymbol}) => {
|
|
33
|
-
return <span>{`${currencyNarrowSymbol}${amount}`}</span>;
|
|
34
|
-
}}
|
|
35
|
-
</SelectedVariantPrice>
|
|
36
|
-
</div>
|
|
37
|
-
</ProductProvider>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import {Product} from '@shopify/hydrogen/client';
|
|
2
|
-
|
|
3
|
-
import Layout from './Layout.client';
|
|
4
|
-
import ProductOptions from './ProductOptions.client';
|
|
5
|
-
import Gallery from './Gallery.client';
|
|
6
|
-
import Seo from './Seo.client';
|
|
7
|
-
|
|
8
|
-
export default function ProductDetails({data}) {
|
|
9
|
-
return (
|
|
10
|
-
<Layout>
|
|
11
|
-
<Seo product={data.product} />
|
|
12
|
-
<Product
|
|
13
|
-
product={data.product}
|
|
14
|
-
initialVariantId={data.product.variants.edges[0].node.id}
|
|
15
|
-
>
|
|
16
|
-
<div className="py-4 md:grid md:grid-cols-2 lg:grid-cols-3 gap-12">
|
|
17
|
-
<div className="md:hidden pb-4 flex justify-between items-top">
|
|
18
|
-
<Product.Title as="h1" className="font-bold text-2xl" />
|
|
19
|
-
<div className="flex items-center gap-1">
|
|
20
|
-
<Product.SelectedVariant.Price className="text-xl" />
|
|
21
|
-
<Product.SelectedVariant.Price
|
|
22
|
-
priceType="compareAt"
|
|
23
|
-
className="line-through text-gray-400"
|
|
24
|
-
/>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
<section className="lg:col-span-2 grid gap-10" aria-label="Gallery">
|
|
29
|
-
<Gallery />
|
|
30
|
-
</section>
|
|
31
|
-
|
|
32
|
-
<section
|
|
33
|
-
className="my-4 md:my-0 max-w-md flex flex-col gap-6"
|
|
34
|
-
aria-label="Product details"
|
|
35
|
-
>
|
|
36
|
-
{/* eslint-disable-next-line @shopify/jsx-prefer-fragment-wrappers */}
|
|
37
|
-
<div>
|
|
38
|
-
<Product.Title className="text-gray-900 text-3xl font-medium" />
|
|
39
|
-
|
|
40
|
-
<Product.Metafield
|
|
41
|
-
namespace="reviews"
|
|
42
|
-
keyName="rating"
|
|
43
|
-
className="text-yellow-500 text-lg"
|
|
44
|
-
/>
|
|
45
|
-
|
|
46
|
-
<div className="my-4 gap-1 hidden md:block">
|
|
47
|
-
<Product.SelectedVariant.Price className="font-semibold text-gray-900 text-2xl">
|
|
48
|
-
{({currencyCode, amount, currencyNarrowSymbol}) => {
|
|
49
|
-
return (
|
|
50
|
-
<span>{`${currencyCode} ${currencyNarrowSymbol}${amount}`}</span>
|
|
51
|
-
);
|
|
52
|
-
}}
|
|
53
|
-
</Product.SelectedVariant.Price>
|
|
54
|
-
<Product.SelectedVariant.Price
|
|
55
|
-
priceType="compareAt"
|
|
56
|
-
className="text-gray-400 line-through text-xl"
|
|
57
|
-
>
|
|
58
|
-
{({amount, currencyNarrowSymbol}) => {
|
|
59
|
-
return <span>{`${currencyNarrowSymbol}${amount}`}</span>;
|
|
60
|
-
}}
|
|
61
|
-
</Product.SelectedVariant.Price>
|
|
62
|
-
|
|
63
|
-
<Product.SelectedVariant.UnitPrice className="text-gray-900 text-base">
|
|
64
|
-
{({
|
|
65
|
-
currencyCode,
|
|
66
|
-
amount,
|
|
67
|
-
currencyNarrowSymbol,
|
|
68
|
-
referenceUnit,
|
|
69
|
-
}) => {
|
|
70
|
-
return (
|
|
71
|
-
<span>{`${currencyCode} ${currencyNarrowSymbol}${amount}/${referenceUnit}`}</span>
|
|
72
|
-
);
|
|
73
|
-
}}
|
|
74
|
-
</Product.SelectedVariant.UnitPrice>
|
|
75
|
-
|
|
76
|
-
<Product.SelectedVariant.Metafield
|
|
77
|
-
namespace="my_fields"
|
|
78
|
-
keyName="no_tax"
|
|
79
|
-
>
|
|
80
|
-
{({value}) => {
|
|
81
|
-
return value ? <span>We pay the tax!</span> : null;
|
|
82
|
-
}}
|
|
83
|
-
</Product.SelectedVariant.Metafield>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<ProductOptions />
|
|
87
|
-
|
|
88
|
-
<div className="my-8 space-y-2">
|
|
89
|
-
<Product.SelectedVariant.AddToCartButton className="rounded-md bg-gray-900 text-white text-center p-4 text-sm uppercase w-full">
|
|
90
|
-
Add to bag
|
|
91
|
-
</Product.SelectedVariant.AddToCartButton>
|
|
92
|
-
<Product.SelectedVariant.BuyNowButton className="rounded-md bg-white border border-black text-center p-4 text-sm uppercase w-full">
|
|
93
|
-
Buy it now
|
|
94
|
-
</Product.SelectedVariant.BuyNowButton>
|
|
95
|
-
<Product.SelectedVariant.ShopPayButton className="flex justify-center w-full" />
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<ul className="flex gap-2">
|
|
99
|
-
<Product.Metafield
|
|
100
|
-
namespace="my_fields"
|
|
101
|
-
keyName="made_in_canada"
|
|
102
|
-
>
|
|
103
|
-
{({value}) => {
|
|
104
|
-
return value ? (
|
|
105
|
-
<li className="uppercase text-xs bg-red-500 text-white text-center font-semibold rounded-full h-20 w-20 flex items-center justify-center p-3">
|
|
106
|
-
Made in Canada
|
|
107
|
-
</li>
|
|
108
|
-
) : null;
|
|
109
|
-
}}
|
|
110
|
-
</Product.Metafield>
|
|
111
|
-
<Product.Metafield namespace="my_fields" keyName="flex">
|
|
112
|
-
{({value}) => {
|
|
113
|
-
return (
|
|
114
|
-
<li className="uppercase bg-gray-600 text-white text-center font-semibold rounded-full h-20 w-20 flex flex-col items-center justify-center p-3">
|
|
115
|
-
<span className="text-xs">Flex</span>
|
|
116
|
-
<span className="text-4xl">{value}</span>
|
|
117
|
-
</li>
|
|
118
|
-
);
|
|
119
|
-
}}
|
|
120
|
-
</Product.Metafield>
|
|
121
|
-
</ul>
|
|
122
|
-
|
|
123
|
-
<Product.Description className="prose" />
|
|
124
|
-
|
|
125
|
-
<section className="mt-4">
|
|
126
|
-
<h3 className="text-lg font-semibold">Care Guide</h3>
|
|
127
|
-
<Product.Metafield
|
|
128
|
-
namespace="descriptors"
|
|
129
|
-
keyName="care_guide"
|
|
130
|
-
/>
|
|
131
|
-
</section>
|
|
132
|
-
|
|
133
|
-
<section className="mt-4">
|
|
134
|
-
<h3 className="text-lg font-semibold">Specs</h3>
|
|
135
|
-
<ul>
|
|
136
|
-
<li>
|
|
137
|
-
Weight:{' '}
|
|
138
|
-
<Product.Metafield
|
|
139
|
-
namespace="my_fields"
|
|
140
|
-
keyName="product_weight"
|
|
141
|
-
/>
|
|
142
|
-
</li>
|
|
143
|
-
<li>
|
|
144
|
-
Length:{' '}
|
|
145
|
-
<Product.Metafield namespace="my_fields" keyName="length" />
|
|
146
|
-
</li>
|
|
147
|
-
<li>
|
|
148
|
-
Width:{' '}
|
|
149
|
-
<Product.Metafield namespace="my_fields" keyName="width" />
|
|
150
|
-
</li>
|
|
151
|
-
<li>
|
|
152
|
-
Manufactured on:{' '}
|
|
153
|
-
<Product.Metafield
|
|
154
|
-
namespace="my_fields"
|
|
155
|
-
keyName="manufacture_date"
|
|
156
|
-
/>
|
|
157
|
-
</li>
|
|
158
|
-
<li>
|
|
159
|
-
Manufactured by:{' '}
|
|
160
|
-
<Product.Metafield
|
|
161
|
-
namespace="my_fields"
|
|
162
|
-
keyName="manufacturer_url"
|
|
163
|
-
>
|
|
164
|
-
{({value}) => {
|
|
165
|
-
return (
|
|
166
|
-
<a href={value} className="inline-block">
|
|
167
|
-
<Product.Metafield
|
|
168
|
-
namespace="my_fields"
|
|
169
|
-
keyName="manufacturer_name"
|
|
170
|
-
/>
|
|
171
|
-
</a>
|
|
172
|
-
);
|
|
173
|
-
}}
|
|
174
|
-
</Product.Metafield>
|
|
175
|
-
</li>
|
|
176
|
-
</ul>
|
|
177
|
-
</section>
|
|
178
|
-
</div>
|
|
179
|
-
</section>
|
|
180
|
-
</div>
|
|
181
|
-
</Product>
|
|
182
|
-
</Layout>
|
|
183
|
-
);
|
|
184
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import {useShop, Helmet} from '@shopify/hydrogen/client';
|
|
2
|
-
|
|
3
|
-
export default function Seo({shopName, product}) {
|
|
4
|
-
const {locale} = useShop();
|
|
5
|
-
const lang = locale.split(/[-_]/)[0];
|
|
6
|
-
|
|
7
|
-
if (product) {
|
|
8
|
-
const variant = product.variants.edges[0].node;
|
|
9
|
-
const price = variant.priceV2;
|
|
10
|
-
const image = product.images.edges[0]?.node;
|
|
11
|
-
const title = product.seo?.title ?? product.title;
|
|
12
|
-
const description = product.seo?.description ?? product.description;
|
|
13
|
-
|
|
14
|
-
/* TODO: Find a way to get the full URL */
|
|
15
|
-
const url = typeof window === 'undefined' ? '' : window.location.href;
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<Helmet>
|
|
19
|
-
<title>{title}</title>
|
|
20
|
-
<meta name="description" content={description} />
|
|
21
|
-
{url && <meta property="og:url" content={url} />}
|
|
22
|
-
<meta property="og:title" content={title} />
|
|
23
|
-
<meta property="og:type" content="product" />
|
|
24
|
-
<meta property="og:description" content={description} />
|
|
25
|
-
<meta property="og:price:amount" content={price.amount} />
|
|
26
|
-
<meta property="og:price:currency" content={price.currencyCode} />
|
|
27
|
-
|
|
28
|
-
{image && <meta property="og:image" content={image.originalSrc} />}
|
|
29
|
-
{image && (
|
|
30
|
-
<meta property="og:image:secure_url" content={image.originalSrc} />
|
|
31
|
-
)}
|
|
32
|
-
|
|
33
|
-
<meta name="twitter:card" content="summary_large_image" />
|
|
34
|
-
<meta name="twitter:title" content={title} />
|
|
35
|
-
<meta name="twitter:description" content={description} />
|
|
36
|
-
|
|
37
|
-
<script type="application/ld+json">{`
|
|
38
|
-
{
|
|
39
|
-
"@context": "https://schema.org/",
|
|
40
|
-
"@type": "Product",
|
|
41
|
-
"name": "${product.title}",
|
|
42
|
-
"image": [
|
|
43
|
-
${image ? `"${image.originalSrc}"` : ''}
|
|
44
|
-
],
|
|
45
|
-
"description": "${description}",
|
|
46
|
-
"brand": {
|
|
47
|
-
"@type": "Brand",
|
|
48
|
-
"name": "${product.vendor}"
|
|
49
|
-
},
|
|
50
|
-
"offers": {
|
|
51
|
-
"@type": "Offer",
|
|
52
|
-
"url": "${url}",
|
|
53
|
-
"priceCurrency": "${price.currencyCode}",
|
|
54
|
-
"price": "${price.amount}",
|
|
55
|
-
"availability": "https://schema.org/${
|
|
56
|
-
variant.availableForSale ? 'InStock' : 'OutOfStock'
|
|
57
|
-
}"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
`}</script>
|
|
61
|
-
</Helmet>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Return a global SEO helper if no other props were passed.
|
|
67
|
-
* Useful for placing in the "main" <App> container.
|
|
68
|
-
*/
|
|
69
|
-
return (
|
|
70
|
-
<Helmet defaultTitle={shopName} titleTemplate={`%s - ${shopName}`}>
|
|
71
|
-
<html lang={lang} />
|
|
72
|
-
<meta property="og:site_name" content={shopName} />
|
|
73
|
-
</Helmet>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import renderHydrogen from '@shopify/hydrogen/entry-client';
|
|
2
|
-
import {ShopifyProvider} from '@shopify/hydrogen/client';
|
|
3
|
-
|
|
4
|
-
import shopifyConfig from '../shopify.config';
|
|
5
|
-
|
|
6
|
-
function ClientApp({children}) {
|
|
7
|
-
return (
|
|
8
|
-
<ShopifyProvider shopifyConfig={shopifyConfig}>{children}</ShopifyProvider>
|
|
9
|
-
);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default renderHydrogen(ClientApp);
|