Skip to content

Commit

Permalink
Update Shopify base template
Browse files Browse the repository at this point in the history
Ran `npm create @shopify/hydrogen@latest` with:

```
?  Select a language:
✔  TypeScript

?  Install dependencies with npm?
✔  Yes

?  Create a global `h2` alias to run commands instead of `npx shopify hydrogen` ?
✔  No

?  Do you want to scaffold routes and core functionality?
✔  Yes, set up now

?  Select a URL structure to support multiple markets:
✔  Set up later (run `npx shopify hydrogen setup markets`)
```
  • Loading branch information
Zwyx committed Apr 18, 2024
1 parent 02c1707 commit 7805a1a
Show file tree
Hide file tree
Showing 17 changed files with 2,726 additions and 2,216 deletions.
File renamed without changes.
1 change: 1 addition & 0 deletions app/graphql/customer-account/CustomerDetailsQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// NOTE: https://shopify.dev/docs/api/customer/latest/objects/Customer
export const CUSTOMER_FRAGMENT = `#graphql
fragment Customer on Customer {
id
firstName
lastName
defaultAddress {
Expand Down
2 changes: 2 additions & 0 deletions app/lib/fragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const CART_QUERY_FRAGMENT = `#graphql
handle
title
id
vendor
}
selectedOptions {
name
Expand All @@ -55,6 +56,7 @@ export const CART_QUERY_FRAGMENT = `#graphql
}
}
fragment CartApiQuery on Cart {
updatedAt
id
checkoutUrl
totalQuantity
Expand Down
7 changes: 2 additions & 5 deletions app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {OkendoProvider, getOkendoProviderData} from '@okendo/shopify-hydrogen';
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
Expand All @@ -20,8 +19,8 @@ import {
} from '@shopify/remix-oxygen';
import {Layout} from '~/components/Layout';
import favicon from './assets/favicon.svg';
import appStyles from './styles/app.css';
import resetStyles from './styles/reset.css';
import appStyles from './styles/app.css?url';
import resetStyles from './styles/reset.css?url';

/**
* This is important to avoid re-fetching root queries on sub-navigations
Expand Down Expand Up @@ -134,7 +133,6 @@ export default function App() {
</Layout>
<ScrollRestoration nonce={nonce} />
<Scripts nonce={nonce} />
<LiveReload nonce={nonce} />
</body>
</html>
);
Expand Down Expand Up @@ -176,7 +174,6 @@ export function ErrorBoundary() {
</Layout>
<ScrollRestoration nonce={nonce} />
<Scripts nonce={nonce} />
<LiveReload nonce={nonce} />
</body>
</html>
);
Expand Down
2 changes: 1 addition & 1 deletion app/routes/account.orders._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function OrderItem({order}: {order: OrderItemFragment}) {
return (
<>
<fieldset>
<Link to={`/account/orders/${order.id}`}>
<Link to={`/account/orders/${btoa(order.id)}`}>
<strong>#{order.number}</strong>
</Link>
<p>{new Date(order.processedAt).toDateString()}</p>
Expand Down
2 changes: 1 addition & 1 deletion app/routes/account.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {json, redirect, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
import {Form, NavLink, Outlet, useLoaderData} from '@remix-run/react';
import {CUSTOMER_DETAILS_QUERY} from '~/graphql/customer-account/CustomerDetailsQuery';

Expand Down
160 changes: 160 additions & 0 deletions app/routes/collections.all.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
import {useLoaderData, Link, type MetaFunction} from '@remix-run/react';
import {
Pagination,
getPaginationVariables,
Image,
Money,
} from '@shopify/hydrogen';
import type {ProductItemFragment} from 'storefrontapi.generated';
import {useVariantUrl} from '~/lib/variants';

export const meta: MetaFunction<typeof loader> = () => {
return [{title: `Hydrogen | Procuts`}];
};

export async function loader({request, context}: LoaderFunctionArgs) {
const {storefront} = context;
const paginationVariables = getPaginationVariables(request, {
pageBy: 8,
});

const {products} = await storefront.query(CATALOG_QUERY, {
variables: {...paginationVariables},
});

return json({products});
}

export default function Collection() {
const {products} = useLoaderData<typeof loader>();

return (
<div className="collection">
<h1>Products</h1>
<Pagination connection={products}>
{({nodes, isLoading, PreviousLink, NextLink}) => (
<>
<PreviousLink>
{isLoading ? 'Loading...' : <span>↑ Load previous</span>}
</PreviousLink>
<ProductsGrid products={nodes} />
<br />
<NextLink>
{isLoading ? 'Loading...' : <span>Load more ↓</span>}
</NextLink>
</>
)}
</Pagination>
</div>
);
}

function ProductsGrid({products}: {products: ProductItemFragment[]}) {
return (
<div className="products-grid">
{products.map((product, index) => {
return (
<ProductItem
key={product.id}
product={product}
loading={index < 8 ? 'eager' : undefined}
/>
);
})}
</div>
);
}

function ProductItem({
product,
loading,
}: {
product: ProductItemFragment;
loading?: 'eager' | 'lazy';
}) {
const variant = product.variants.nodes[0];
const variantUrl = useVariantUrl(product.handle, variant.selectedOptions);
return (
<Link
className="product-item"
key={product.id}
prefetch="intent"
to={variantUrl}
>
{product.featuredImage && (
<Image
alt={product.featuredImage.altText || product.title}
aspectRatio="1/1"
data={product.featuredImage}
loading={loading}
sizes="(min-width: 45em) 400px, 100vw"
/>
)}
<h4>{product.title}</h4>
<small>
<Money data={product.priceRange.minVariantPrice} />
</small>
</Link>
);
}

const PRODUCT_ITEM_FRAGMENT = `#graphql
fragment MoneyProductItem on MoneyV2 {
amount
currencyCode
}
fragment ProductItem on Product {
id
handle
title
featuredImage {
id
altText
url
width
height
}
priceRange {
minVariantPrice {
...MoneyProductItem
}
maxVariantPrice {
...MoneyProductItem
}
}
variants(first: 1) {
nodes {
selectedOptions {
name
value
}
}
}
}
` as const;

// NOTE: https://shopify.dev/docs/api/storefront/2024-01/objects/product
const CATALOG_QUERY = `#graphql
query Catalog(
$country: CountryCode
$language: LanguageCode
$first: Int
$last: Int
$startCursor: String
$endCursor: String
) @inContext(country: $country, language: $language) {
products(first: $first, last: $last, before: $startCursor, after: $endCursor) {
nodes {
...ProductItem
}
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
}
}
${PRODUCT_ITEM_FRAGMENT}
` as const;
2 changes: 1 addition & 1 deletion app/routes/products.$handle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import type {
} from 'storefrontapi.generated';
import {getVariantUrl} from '~/lib/variants';

export const meta: MetaFunction<typeof loader> = ({data}) => {
export const meta: MetaFunction<typeof loader> = ({data, location}) => {
return [{title: `Hydrogen | ${data?.product.title ?? ''}`}];
};

Expand Down
9 changes: 6 additions & 3 deletions customer-accountapi.generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export type CustomerAddressCreateMutation = {

export type CustomerFragment = Pick<
CustomerAccountAPI.Customer,
'firstName' | 'lastName'
'id' | 'firstName' | 'lastName'
> & {
defaultAddress?: CustomerAccountAPI.Maybe<
Pick<
Expand Down Expand Up @@ -129,7 +129,10 @@ export type CustomerDetailsQueryVariables = CustomerAccountAPI.Exact<{
}>;

export type CustomerDetailsQuery = {
customer: Pick<CustomerAccountAPI.Customer, 'firstName' | 'lastName'> & {
customer: Pick<
CustomerAccountAPI.Customer,
'id' | 'firstName' | 'lastName'
> & {
defaultAddress?: CustomerAccountAPI.Maybe<
Pick<
CustomerAccountAPI.CustomerAddress,
Expand Down Expand Up @@ -467,7 +470,7 @@ export type CustomerUpdateMutation = {
};

interface GeneratedQueryTypes {
'#graphql\n query CustomerDetails {\n customer {\n ...Customer\n }\n }\n #graphql\n fragment Customer on Customer {\n firstName\n lastName\n defaultAddress {\n ...Address\n }\n addresses(first: 6) {\n nodes {\n ...Address\n }\n }\n }\n fragment Address on CustomerAddress {\n id\n formatted\n firstName\n lastName\n company\n address1\n address2\n territoryCode\n zoneCode\n city\n zip\n phoneNumber\n }\n\n': {
'#graphql\n query CustomerDetails {\n customer {\n ...Customer\n }\n }\n #graphql\n fragment Customer on Customer {\n id\n firstName\n lastName\n defaultAddress {\n ...Address\n }\n addresses(first: 6) {\n nodes {\n ...Address\n }\n }\n }\n fragment Address on CustomerAddress {\n id\n formatted\n firstName\n lastName\n company\n address1\n address2\n territoryCode\n zoneCode\n city\n zip\n phoneNumber\n }\n\n': {
return: CustomerDetailsQuery;
variables: CustomerDetailsQueryVariables;
};
Expand Down
10 changes: 8 additions & 2 deletions remix.env.d.ts → env.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference types="@remix-run/dev" />
/// <reference types="vite/client" />
/// <reference types="@shopify/remix-oxygen" />
/// <reference types="@shopify/oxygen-workers-types" />

Expand All @@ -9,6 +9,7 @@ import type {
Storefront,
CustomerAccount,
HydrogenCart,
HydrogenSessionData,
} from '@shopify/hydrogen';
import type {AppSession} from '~/lib/session';

Expand Down Expand Up @@ -36,12 +37,17 @@ declare module '@shopify/remix-oxygen' {
/**
* Declare local additions to the Remix loader context.
*/
export interface AppLoadContext {
interface AppLoadContext {
env: Env;
cart: HydrogenCart;
storefront: Storefront;
customerAccount: CustomerAccount;
session: AppSession;
waitUntil: ExecutionContext['waitUntil'];
}

/**
* Declare local additions to the Remix session data.
*/
interface SessionData extends HydrogenSessionData {}
}
Binary file removed okendo-shopify-hydrogen-2.0.3.tgz
Binary file not shown.
Loading

0 comments on commit 7805a1a

Please sign in to comment.