@shopify/create-hydrogen 5.0.23 → 5.0.25
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/assets/hydrogen/bundle/analyzer.html +155 -148
- package/dist/assets/hydrogen/starter/.cursor/rules/hydrogen-react-router.mdc +5 -3
- package/dist/assets/hydrogen/starter/CHANGELOG.md +97 -9
- package/dist/assets/hydrogen/starter/app/components/AddToCartButton.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/components/CartLineItem.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +62 -29
- package/dist/assets/hydrogen/starter/app/components/Header.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/components/PageLayout.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/components/ProductForm.tsx +2 -2
- package/dist/assets/hydrogen/starter/app/components/SearchForm.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/components/SearchFormPredictive.tsx +8 -3
- package/dist/assets/hydrogen/starter/app/components/SearchResults.tsx +3 -11
- package/dist/assets/hydrogen/starter/app/components/SearchResultsPredictive.tsx +2 -6
- package/dist/assets/hydrogen/starter/app/entry.client.tsx +10 -2
- package/dist/assets/hydrogen/starter/app/entry.server.tsx +5 -3
- package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerAddressMutations.ts +7 -4
- package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +1 -1
- package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerOrderQuery.ts +4 -1
- package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerOrdersQuery.ts +10 -5
- package/dist/assets/hydrogen/starter/app/graphql/customer-account/CustomerUpdateMutation.ts +3 -2
- package/dist/assets/hydrogen/starter/app/lib/context.ts +34 -17
- package/dist/assets/hydrogen/starter/app/lib/fragments.ts +1 -0
- package/dist/assets/hydrogen/starter/app/lib/orderFilters.ts +90 -0
- package/dist/assets/hydrogen/starter/app/lib/redirect.ts +1 -1
- package/dist/assets/hydrogen/starter/app/lib/session.ts +1 -1
- package/dist/assets/hydrogen/starter/app/lib/variants.ts +1 -1
- package/dist/assets/hydrogen/starter/app/root.tsx +23 -18
- package/dist/assets/hydrogen/starter/app/routes/$.tsx +2 -2
- package/dist/assets/hydrogen/starter/app/routes/[robots.txt].tsx +2 -2
- package/dist/assets/hydrogen/starter/app/routes/[sitemap.xml].tsx +2 -3
- package/dist/assets/hydrogen/starter/app/routes/_index.tsx +12 -8
- package/dist/assets/hydrogen/starter/app/routes/account.$.tsx +4 -3
- package/dist/assets/hydrogen/starter/app/routes/account._index.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +15 -11
- package/dist/assets/hydrogen/starter/app/routes/account.orders.$id.tsx +47 -22
- package/dist/assets/hydrogen/starter/app/routes/account.orders._index.tsx +152 -23
- package/dist/assets/hydrogen/starter/app/routes/account.profile.tsx +11 -8
- package/dist/assets/hydrogen/starter/app/routes/account.tsx +16 -4
- package/dist/assets/hydrogen/starter/app/routes/account_.authorize.tsx +2 -2
- package/dist/assets/hydrogen/starter/app/routes/account_.login.tsx +5 -3
- package/dist/assets/hydrogen/starter/app/routes/account_.logout.tsx +3 -2
- package/dist/assets/hydrogen/starter/app/routes/api.$version.[graphql.json].tsx +2 -2
- package/dist/assets/hydrogen/starter/app/routes/blogs.$blogHandle.$articleHandle.tsx +6 -10
- package/dist/assets/hydrogen/starter/app/routes/blogs.$blogHandle._index.tsx +10 -7
- package/dist/assets/hydrogen/starter/app/routes/blogs._index.tsx +13 -7
- package/dist/assets/hydrogen/starter/app/routes/cart.$lines.tsx +3 -2
- package/dist/assets/hydrogen/starter/app/routes/cart.tsx +13 -9
- package/dist/assets/hydrogen/starter/app/routes/collections.$handle.tsx +8 -11
- package/dist/assets/hydrogen/starter/app/routes/collections._index.tsx +6 -6
- package/dist/assets/hydrogen/starter/app/routes/collections.all.tsx +10 -7
- package/dist/assets/hydrogen/starter/app/routes/discount.$code.tsx +3 -2
- package/dist/assets/hydrogen/starter/app/routes/pages.$handle.tsx +8 -6
- package/dist/assets/hydrogen/starter/app/routes/policies.$handle.tsx +7 -4
- package/dist/assets/hydrogen/starter/app/routes/policies._index.tsx +19 -13
- package/dist/assets/hydrogen/starter/app/routes/products.$handle.tsx +9 -6
- package/dist/assets/hydrogen/starter/app/routes/search.tsx +14 -14
- package/dist/assets/hydrogen/starter/app/routes/sitemap.$type.$page[.xml].tsx +2 -3
- package/dist/assets/hydrogen/starter/app/routes.ts +1 -1
- package/dist/assets/hydrogen/starter/app/styles/app.css +53 -1
- package/dist/assets/hydrogen/starter/customer-accountapi.generated.d.ts +47 -13
- package/dist/assets/hydrogen/starter/env.d.ts +1 -39
- package/dist/assets/hydrogen/starter/eslint.config.js +35 -52
- package/dist/assets/hydrogen/starter/package.json +14 -15
- package/dist/assets/hydrogen/starter/react-router.config.ts +9 -3
- package/dist/assets/hydrogen/starter/server.ts +7 -7
- package/dist/assets/hydrogen/starter/storefrontapi.generated.d.ts +1 -1
- package/dist/assets/hydrogen/starter/tsconfig.json +17 -13
- package/dist/assets/hydrogen/starter/vite.config.ts +4 -1
- package/dist/assets/hydrogen/virtual-routes/components/RequestDetails.jsx +13 -20
- package/dist/assets/hydrogen/virtual-routes/routes/[.]well-known.appspecific.com[.]chrome[.]devtools[.]json.jsx +37 -0
- package/dist/chunk-2LZQLWDR.js +1189 -0
- package/dist/{chunk-EO6F7WJJ.js → chunk-6YUUFKYO.js} +1 -1
- package/dist/chunk-AUULK6IN.js +5 -0
- package/dist/chunk-CJKPLQJ7.js +51 -0
- package/dist/{chunk-MNT4XW23.js → chunk-LBUW5UHX.js} +1 -1
- package/dist/chunk-RUCJI22O.js +3 -0
- package/dist/{chunk-PMDMUCNY.js → chunk-VXJIQGAB.js} +1 -1
- package/dist/chunk-Y5VZE2FH.js +32 -0
- package/dist/chunk-ZLNTSIDN.js +2 -0
- package/dist/create-app.js +293 -288
- package/dist/{del-72VO4HYK.js → del-VDYQZFAQ.js} +1 -1
- package/dist/devtools-3BYEW2L2.js +8 -0
- package/dist/error-handler-XRI3ZDLO.js +2 -0
- package/dist/is-wsl-52AELLDM.js +2 -0
- package/dist/{morph-3JSBLNUD.js → morph-S2LU6PQ4.js} +7 -7
- package/dist/{multipart-parser-QIHQVIZA.js → multipart-parser-MX4R5XJM.js} +1 -1
- package/dist/open-PMJ32HTM.js +2 -0
- package/dist/out-U7AI7XUQ.js +2 -0
- package/package.json +4 -2
- package/dist/chokidar-FXMI63T6.js +0 -12
- package/dist/chunk-3LZ6M5C2.js +0 -3
- package/dist/chunk-D7CI46F7.js +0 -10
- package/dist/chunk-FB327AH7.js +0 -5
- package/dist/chunk-MZPD7BFF.js +0 -23
- package/dist/chunk-NIHY2BIB.js +0 -1180
- package/dist/chunk-UASQ33JG.js +0 -45
- package/dist/chunk-VMIOG46Y.js +0 -2
- package/dist/devtools-DGRGSZU7.js +0 -8
- package/dist/error-handler-O653XSNU.js +0 -2
- package/dist/is-wsl-LL6KGQIK.js +0 -2
- package/dist/open-OD6DRFEG.js +0 -2
- package/dist/out-DXB3K325.js +0 -2
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Link,
|
|
3
|
+
useLoaderData,
|
|
4
|
+
useNavigation,
|
|
5
|
+
useSearchParams,
|
|
6
|
+
} from 'react-router';
|
|
7
|
+
import type {Route} from './+types/account.orders._index';
|
|
8
|
+
import {useRef} from 'react';
|
|
2
9
|
import {
|
|
3
10
|
Money,
|
|
4
11
|
getPaginationVariables,
|
|
5
12
|
flattenConnection,
|
|
6
13
|
} from '@shopify/hydrogen';
|
|
7
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
buildOrderSearchQuery,
|
|
16
|
+
parseOrderFilters,
|
|
17
|
+
ORDER_FILTER_FIELDS,
|
|
18
|
+
type OrderFilterParams,
|
|
19
|
+
} from '~/lib/orderFilters';
|
|
8
20
|
import {CUSTOMER_ORDERS_QUERY} from '~/graphql/customer-account/CustomerOrdersQuery';
|
|
9
21
|
import type {
|
|
10
22
|
CustomerOrdersFragment,
|
|
@@ -12,67 +24,181 @@ import type {
|
|
|
12
24
|
} from 'customer-accountapi.generated';
|
|
13
25
|
import {PaginatedResourceSection} from '~/components/PaginatedResourceSection';
|
|
14
26
|
|
|
15
|
-
|
|
27
|
+
type OrdersLoaderData = {
|
|
28
|
+
customer: CustomerOrdersFragment;
|
|
29
|
+
filters: OrderFilterParams;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const meta: Route.MetaFunction = () => {
|
|
16
33
|
return [{title: 'Orders'}];
|
|
17
34
|
};
|
|
18
35
|
|
|
19
|
-
export async function loader({request, context}:
|
|
36
|
+
export async function loader({request, context}: Route.LoaderArgs) {
|
|
37
|
+
const {customerAccount} = context;
|
|
20
38
|
const paginationVariables = getPaginationVariables(request, {
|
|
21
39
|
pageBy: 20,
|
|
22
40
|
});
|
|
23
41
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
const url = new URL(request.url);
|
|
43
|
+
const filters = parseOrderFilters(url.searchParams);
|
|
44
|
+
const query = buildOrderSearchQuery(filters);
|
|
45
|
+
|
|
46
|
+
const {data, errors} = await customerAccount.query(CUSTOMER_ORDERS_QUERY, {
|
|
47
|
+
variables: {
|
|
48
|
+
...paginationVariables,
|
|
49
|
+
query,
|
|
50
|
+
language: customerAccount.i18n.language,
|
|
30
51
|
},
|
|
31
|
-
);
|
|
52
|
+
});
|
|
32
53
|
|
|
33
54
|
if (errors?.length || !data?.customer) {
|
|
34
55
|
throw Error('Customer orders not found');
|
|
35
56
|
}
|
|
36
57
|
|
|
37
|
-
return {customer: data.customer};
|
|
58
|
+
return {customer: data.customer, filters};
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
export default function Orders() {
|
|
41
|
-
const {customer} = useLoaderData<
|
|
62
|
+
const {customer, filters} = useLoaderData<OrdersLoaderData>();
|
|
42
63
|
const {orders} = customer;
|
|
64
|
+
|
|
43
65
|
return (
|
|
44
66
|
<div className="orders">
|
|
45
|
-
|
|
67
|
+
<OrderSearchForm currentFilters={filters} />
|
|
68
|
+
<OrdersTable orders={orders} filters={filters} />
|
|
46
69
|
</div>
|
|
47
70
|
);
|
|
48
71
|
}
|
|
49
72
|
|
|
50
|
-
function OrdersTable({
|
|
73
|
+
function OrdersTable({
|
|
74
|
+
orders,
|
|
75
|
+
filters,
|
|
76
|
+
}: {
|
|
77
|
+
orders: CustomerOrdersFragment['orders'];
|
|
78
|
+
filters: OrderFilterParams;
|
|
79
|
+
}) {
|
|
80
|
+
const hasFilters = !!(filters.name || filters.confirmationNumber);
|
|
81
|
+
|
|
51
82
|
return (
|
|
52
|
-
<div className="acccount-orders">
|
|
83
|
+
<div className="acccount-orders" aria-live="polite">
|
|
53
84
|
{orders?.nodes.length ? (
|
|
54
85
|
<PaginatedResourceSection connection={orders}>
|
|
55
86
|
{({node: order}) => <OrderItem key={order.id} order={order} />}
|
|
56
87
|
</PaginatedResourceSection>
|
|
57
88
|
) : (
|
|
58
|
-
<EmptyOrders />
|
|
89
|
+
<EmptyOrders hasFilters={hasFilters} />
|
|
59
90
|
)}
|
|
60
91
|
</div>
|
|
61
92
|
);
|
|
62
93
|
}
|
|
63
94
|
|
|
64
|
-
function EmptyOrders() {
|
|
95
|
+
function EmptyOrders({hasFilters = false}: {hasFilters?: boolean}) {
|
|
65
96
|
return (
|
|
66
97
|
<div>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
98
|
+
{hasFilters ? (
|
|
99
|
+
<>
|
|
100
|
+
<p>No orders found matching your search.</p>
|
|
101
|
+
<br />
|
|
102
|
+
<p>
|
|
103
|
+
<Link to="/account/orders">Clear filters →</Link>
|
|
104
|
+
</p>
|
|
105
|
+
</>
|
|
106
|
+
) : (
|
|
107
|
+
<>
|
|
108
|
+
<p>You haven't placed any orders yet.</p>
|
|
109
|
+
<br />
|
|
110
|
+
<p>
|
|
111
|
+
<Link to="/collections">Start Shopping →</Link>
|
|
112
|
+
</p>
|
|
113
|
+
</>
|
|
114
|
+
)}
|
|
72
115
|
</div>
|
|
73
116
|
);
|
|
74
117
|
}
|
|
75
118
|
|
|
119
|
+
function OrderSearchForm({
|
|
120
|
+
currentFilters,
|
|
121
|
+
}: {
|
|
122
|
+
currentFilters: OrderFilterParams;
|
|
123
|
+
}) {
|
|
124
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
125
|
+
const navigation = useNavigation();
|
|
126
|
+
const isSearching =
|
|
127
|
+
navigation.state !== 'idle' &&
|
|
128
|
+
navigation.location?.pathname?.includes('orders');
|
|
129
|
+
const formRef = useRef<HTMLFormElement>(null);
|
|
130
|
+
|
|
131
|
+
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
const formData = new FormData(event.currentTarget);
|
|
134
|
+
const params = new URLSearchParams();
|
|
135
|
+
|
|
136
|
+
const name = formData.get(ORDER_FILTER_FIELDS.NAME)?.toString().trim();
|
|
137
|
+
const confirmationNumber = formData
|
|
138
|
+
.get(ORDER_FILTER_FIELDS.CONFIRMATION_NUMBER)
|
|
139
|
+
?.toString()
|
|
140
|
+
.trim();
|
|
141
|
+
|
|
142
|
+
if (name) params.set(ORDER_FILTER_FIELDS.NAME, name);
|
|
143
|
+
if (confirmationNumber)
|
|
144
|
+
params.set(ORDER_FILTER_FIELDS.CONFIRMATION_NUMBER, confirmationNumber);
|
|
145
|
+
|
|
146
|
+
setSearchParams(params);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const hasFilters = currentFilters.name || currentFilters.confirmationNumber;
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<form
|
|
153
|
+
ref={formRef}
|
|
154
|
+
onSubmit={handleSubmit}
|
|
155
|
+
className="order-search-form"
|
|
156
|
+
aria-label="Search orders"
|
|
157
|
+
>
|
|
158
|
+
<fieldset className="order-search-fieldset">
|
|
159
|
+
<legend className="order-search-legend">Filter Orders</legend>
|
|
160
|
+
|
|
161
|
+
<div className="order-search-inputs">
|
|
162
|
+
<input
|
|
163
|
+
type="search"
|
|
164
|
+
name={ORDER_FILTER_FIELDS.NAME}
|
|
165
|
+
placeholder="Order #"
|
|
166
|
+
aria-label="Order number"
|
|
167
|
+
defaultValue={currentFilters.name || ''}
|
|
168
|
+
className="order-search-input"
|
|
169
|
+
/>
|
|
170
|
+
<input
|
|
171
|
+
type="search"
|
|
172
|
+
name={ORDER_FILTER_FIELDS.CONFIRMATION_NUMBER}
|
|
173
|
+
placeholder="Confirmation #"
|
|
174
|
+
aria-label="Confirmation number"
|
|
175
|
+
defaultValue={currentFilters.confirmationNumber || ''}
|
|
176
|
+
className="order-search-input"
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<div className="order-search-buttons">
|
|
181
|
+
<button type="submit" disabled={isSearching}>
|
|
182
|
+
{isSearching ? 'Searching' : 'Search'}
|
|
183
|
+
</button>
|
|
184
|
+
{hasFilters && (
|
|
185
|
+
<button
|
|
186
|
+
type="button"
|
|
187
|
+
disabled={isSearching}
|
|
188
|
+
onClick={() => {
|
|
189
|
+
setSearchParams(new URLSearchParams());
|
|
190
|
+
formRef.current?.reset();
|
|
191
|
+
}}
|
|
192
|
+
>
|
|
193
|
+
Clear
|
|
194
|
+
</button>
|
|
195
|
+
)}
|
|
196
|
+
</div>
|
|
197
|
+
</fieldset>
|
|
198
|
+
</form>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
76
202
|
function OrderItem({order}: {order: OrderItemFragment}) {
|
|
77
203
|
const fulfillmentStatus = flattenConnection(order.fulfillments)[0]?.status;
|
|
78
204
|
return (
|
|
@@ -82,6 +208,9 @@ function OrderItem({order}: {order: OrderItemFragment}) {
|
|
|
82
208
|
<strong>#{order.number}</strong>
|
|
83
209
|
</Link>
|
|
84
210
|
<p>{new Date(order.processedAt).toDateString()}</p>
|
|
211
|
+
{order.confirmationNumber && (
|
|
212
|
+
<p>Confirmation: {order.confirmationNumber}</p>
|
|
213
|
+
)}
|
|
85
214
|
<p>{order.financialStatus}</p>
|
|
86
215
|
{fulfillmentStatus && <p>{fulfillmentStatus}</p>}
|
|
87
216
|
<Money data={order.totalPrice} />
|
|
@@ -3,27 +3,29 @@ import type {CustomerUpdateInput} from '@shopify/hydrogen/customer-account-api-t
|
|
|
3
3
|
import {CUSTOMER_UPDATE_MUTATION} from '~/graphql/customer-account/CustomerUpdateMutation';
|
|
4
4
|
import {
|
|
5
5
|
data,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
Form,
|
|
7
|
+
useActionData,
|
|
8
|
+
useNavigation,
|
|
9
|
+
useOutletContext,
|
|
10
|
+
} from 'react-router';
|
|
11
|
+
import type {Route} from './+types/account.profile';
|
|
10
12
|
|
|
11
13
|
export type ActionResponse = {
|
|
12
14
|
error: string | null;
|
|
13
15
|
customer: CustomerFragment | null;
|
|
14
16
|
};
|
|
15
17
|
|
|
16
|
-
export const meta: MetaFunction = () => {
|
|
18
|
+
export const meta: Route.MetaFunction = () => {
|
|
17
19
|
return [{title: 'Profile'}];
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
export async function loader({context}:
|
|
21
|
-
|
|
22
|
+
export async function loader({context}: Route.LoaderArgs) {
|
|
23
|
+
context.customerAccount.handleAuthStatus();
|
|
22
24
|
|
|
23
25
|
return {};
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
export async function action({request, context}:
|
|
28
|
+
export async function action({request, context}: Route.ActionArgs) {
|
|
27
29
|
const {customerAccount} = context;
|
|
28
30
|
|
|
29
31
|
if (request.method !== 'PUT') {
|
|
@@ -50,6 +52,7 @@ export async function action({request, context}: ActionFunctionArgs) {
|
|
|
50
52
|
{
|
|
51
53
|
variables: {
|
|
52
54
|
customer,
|
|
55
|
+
language: customerAccount.i18n.language,
|
|
53
56
|
},
|
|
54
57
|
},
|
|
55
58
|
);
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
data as remixData,
|
|
3
|
+
Form,
|
|
4
|
+
NavLink,
|
|
5
|
+
Outlet,
|
|
6
|
+
useLoaderData,
|
|
7
|
+
} from 'react-router';
|
|
8
|
+
import type {Route} from './+types/account';
|
|
3
9
|
import {CUSTOMER_DETAILS_QUERY} from '~/graphql/customer-account/CustomerDetailsQuery';
|
|
4
10
|
|
|
5
11
|
export function shouldRevalidate() {
|
|
6
12
|
return true;
|
|
7
13
|
}
|
|
8
14
|
|
|
9
|
-
export async function loader({context}:
|
|
10
|
-
const {
|
|
15
|
+
export async function loader({context}: Route.LoaderArgs) {
|
|
16
|
+
const {customerAccount} = context;
|
|
17
|
+
const {data, errors} = await customerAccount.query(
|
|
11
18
|
CUSTOMER_DETAILS_QUERY,
|
|
19
|
+
{
|
|
20
|
+
variables: {
|
|
21
|
+
language: customerAccount.i18n.language,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
12
24
|
);
|
|
13
25
|
|
|
14
26
|
if (errors?.length || !data?.customer) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {Route} from './+types/account_.authorize';
|
|
2
2
|
|
|
3
|
-
export async function loader({context}:
|
|
3
|
+
export async function loader({context}: Route.LoaderArgs) {
|
|
4
4
|
return context.customerAccount.authorize();
|
|
5
5
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {Route} from './+types/account_.login';
|
|
2
2
|
|
|
3
|
-
export async function loader({request, context}:
|
|
4
|
-
return context.customerAccount.login(
|
|
3
|
+
export async function loader({request, context}: Route.LoaderArgs) {
|
|
4
|
+
return context.customerAccount.login({
|
|
5
|
+
countryCode: context.storefront.i18n.country,
|
|
6
|
+
});
|
|
5
7
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {redirect
|
|
1
|
+
import {redirect} from 'react-router';
|
|
2
|
+
import type {Route} from './+types/account_.logout';
|
|
2
3
|
|
|
3
4
|
// if we don't implement this, /account/logout will get caught by account.$.tsx to do login
|
|
4
5
|
export async function loader() {
|
|
5
6
|
return redirect('/');
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
export async function action({context}:
|
|
9
|
+
export async function action({context}: Route.ActionArgs) {
|
|
9
10
|
return context.customerAccount.logout();
|
|
10
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {Route} from './+types/api.$version.[graphql.json]';
|
|
2
2
|
|
|
3
|
-
export async function action({params, context, request}:
|
|
3
|
+
export async function action({params, context, request}: Route.ActionArgs) {
|
|
4
4
|
const response = await fetch(
|
|
5
5
|
`https://${context.env.PUBLIC_CHECKOUT_DOMAIN}/api/${params.version}/graphql.json`,
|
|
6
6
|
{
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import {useLoaderData} from 'react-router';
|
|
2
|
+
import type {Route} from './+types/blogs.$blogHandle.$articleHandle';
|
|
3
3
|
import {Image} from '@shopify/hydrogen';
|
|
4
4
|
import {redirectIfHandleIsLocalized} from '~/lib/redirect';
|
|
5
5
|
|
|
6
|
-
export const meta: MetaFunction
|
|
6
|
+
export const meta: Route.MetaFunction = ({data}) => {
|
|
7
7
|
return [{title: `Hydrogen | ${data?.article.title ?? ''} article`}];
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export async function loader(args:
|
|
10
|
+
export async function loader(args: Route.LoaderArgs) {
|
|
11
11
|
// Start fetching non-critical data without blocking time to first byte
|
|
12
12
|
const deferredData = loadDeferredData(args);
|
|
13
13
|
|
|
@@ -21,11 +21,7 @@ export async function loader(args: LoaderFunctionArgs) {
|
|
|
21
21
|
* Load data necessary for rendering content above the fold. This is the critical data
|
|
22
22
|
* needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
|
|
23
23
|
*/
|
|
24
|
-
async function loadCriticalData({
|
|
25
|
-
context,
|
|
26
|
-
request,
|
|
27
|
-
params,
|
|
28
|
-
}: LoaderFunctionArgs) {
|
|
24
|
+
async function loadCriticalData({context, request, params}: Route.LoaderArgs) {
|
|
29
25
|
const {blogHandle, articleHandle} = params;
|
|
30
26
|
|
|
31
27
|
if (!articleHandle || !blogHandle) {
|
|
@@ -65,7 +61,7 @@ async function loadCriticalData({
|
|
|
65
61
|
* fetched after the initial page load. If it's unavailable, the page should still 200.
|
|
66
62
|
* Make sure to not throw any errors here, as it will cause the page to 500.
|
|
67
63
|
*/
|
|
68
|
-
function loadDeferredData({context}:
|
|
64
|
+
function loadDeferredData({context}: Route.LoaderArgs) {
|
|
69
65
|
return {};
|
|
70
66
|
}
|
|
71
67
|
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Link,
|
|
3
|
+
useLoaderData,
|
|
4
|
+
} from 'react-router';
|
|
5
|
+
import type {Route} from './+types/blogs.$blogHandle._index';
|
|
3
6
|
import {Image, getPaginationVariables} from '@shopify/hydrogen';
|
|
4
7
|
import type {ArticleItemFragment} from 'storefrontapi.generated';
|
|
5
8
|
import {PaginatedResourceSection} from '~/components/PaginatedResourceSection';
|
|
6
9
|
import {redirectIfHandleIsLocalized} from '~/lib/redirect';
|
|
7
10
|
|
|
8
|
-
export const meta: MetaFunction
|
|
11
|
+
export const meta: Route.MetaFunction = ({data}) => {
|
|
9
12
|
return [{title: `Hydrogen | ${data?.blog.title ?? ''} blog`}];
|
|
10
13
|
};
|
|
11
14
|
|
|
12
|
-
export async function loader(args:
|
|
15
|
+
export async function loader(args: Route.LoaderArgs) {
|
|
13
16
|
// Start fetching non-critical data without blocking time to first byte
|
|
14
17
|
const deferredData = loadDeferredData(args);
|
|
15
18
|
|
|
@@ -27,7 +30,7 @@ async function loadCriticalData({
|
|
|
27
30
|
context,
|
|
28
31
|
request,
|
|
29
32
|
params,
|
|
30
|
-
}:
|
|
33
|
+
}: Route.LoaderArgs) {
|
|
31
34
|
const paginationVariables = getPaginationVariables(request, {
|
|
32
35
|
pageBy: 4,
|
|
33
36
|
});
|
|
@@ -60,7 +63,7 @@ async function loadCriticalData({
|
|
|
60
63
|
* fetched after the initial page load. If it's unavailable, the page should still 200.
|
|
61
64
|
* Make sure to not throw any errors here, as it will cause the page to 500.
|
|
62
65
|
*/
|
|
63
|
-
function loadDeferredData({context}:
|
|
66
|
+
function loadDeferredData({context}: Route.LoaderArgs) {
|
|
64
67
|
return {};
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -72,7 +75,7 @@ export default function Blog() {
|
|
|
72
75
|
<div className="blog">
|
|
73
76
|
<h1>{blog.title}</h1>
|
|
74
77
|
<div className="blog-grid">
|
|
75
|
-
<PaginatedResourceSection connection={articles}>
|
|
78
|
+
<PaginatedResourceSection<ArticleItemFragment> connection={articles}>
|
|
76
79
|
{({node: article, index}) => (
|
|
77
80
|
<ArticleItem
|
|
78
81
|
article={article}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Link,
|
|
3
|
+
useLoaderData,
|
|
4
|
+
} from 'react-router';
|
|
5
|
+
import type {Route} from './+types/blogs._index';
|
|
3
6
|
import {getPaginationVariables} from '@shopify/hydrogen';
|
|
4
7
|
import {PaginatedResourceSection} from '~/components/PaginatedResourceSection';
|
|
8
|
+
import type {BlogsQuery} from 'storefrontapi.generated';
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
type BlogNode = BlogsQuery['blogs']['nodes'][0];
|
|
11
|
+
|
|
12
|
+
export const meta: Route.MetaFunction = () => {
|
|
7
13
|
return [{title: `Hydrogen | Blogs`}];
|
|
8
14
|
};
|
|
9
15
|
|
|
10
|
-
export async function loader(args:
|
|
16
|
+
export async function loader(args: Route.LoaderArgs) {
|
|
11
17
|
// Start fetching non-critical data without blocking time to first byte
|
|
12
18
|
const deferredData = loadDeferredData(args);
|
|
13
19
|
|
|
@@ -21,7 +27,7 @@ export async function loader(args: LoaderFunctionArgs) {
|
|
|
21
27
|
* Load data necessary for rendering content above the fold. This is the critical data
|
|
22
28
|
* needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
|
|
23
29
|
*/
|
|
24
|
-
async function loadCriticalData({context, request}:
|
|
30
|
+
async function loadCriticalData({context, request}: Route.LoaderArgs) {
|
|
25
31
|
const paginationVariables = getPaginationVariables(request, {
|
|
26
32
|
pageBy: 10,
|
|
27
33
|
});
|
|
@@ -43,7 +49,7 @@ async function loadCriticalData({context, request}: LoaderFunctionArgs) {
|
|
|
43
49
|
* fetched after the initial page load. If it's unavailable, the page should still 200.
|
|
44
50
|
* Make sure to not throw any errors here, as it will cause the page to 500.
|
|
45
51
|
*/
|
|
46
|
-
function loadDeferredData({context}:
|
|
52
|
+
function loadDeferredData({context}: Route.LoaderArgs) {
|
|
47
53
|
return {};
|
|
48
54
|
}
|
|
49
55
|
|
|
@@ -54,7 +60,7 @@ export default function Blogs() {
|
|
|
54
60
|
<div className="blogs">
|
|
55
61
|
<h1>Blogs</h1>
|
|
56
62
|
<div className="blogs-grid">
|
|
57
|
-
<PaginatedResourceSection connection={blogs}>
|
|
63
|
+
<PaginatedResourceSection<BlogNode> connection={blogs}>
|
|
58
64
|
{({node: blog}) => (
|
|
59
65
|
<Link
|
|
60
66
|
className="blog"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {redirect
|
|
1
|
+
import {redirect} from 'react-router';
|
|
2
|
+
import type {Route} from './+types/cart.$lines';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Automatically creates a new cart based on the URL and redirects straight to checkout.
|
|
@@ -18,7 +19,7 @@ import {redirect, type LoaderFunctionArgs} from '@shopify/remix-oxygen';
|
|
|
18
19
|
*
|
|
19
20
|
* ```
|
|
20
21
|
*/
|
|
21
|
-
export async function loader({request, context, params}:
|
|
22
|
+
export async function loader({request, context, params}: Route.LoaderArgs) {
|
|
22
23
|
const {cart} = context;
|
|
23
24
|
const {lines} = params;
|
|
24
25
|
if (!lines) return redirect('/cart');
|
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import { type MetaFunction, useLoaderData } from 'react-router';
|
|
2
|
-
import type {CartQueryDataReturn} from '@shopify/hydrogen';
|
|
3
|
-
import {CartForm} from '@shopify/hydrogen';
|
|
4
1
|
import {
|
|
2
|
+
useLoaderData,
|
|
5
3
|
data,
|
|
6
|
-
type LoaderFunctionArgs,
|
|
7
|
-
type ActionFunctionArgs,
|
|
8
4
|
type HeadersFunction,
|
|
9
|
-
} from '
|
|
5
|
+
} from 'react-router';
|
|
6
|
+
import type {Route} from './+types/cart';
|
|
7
|
+
import type {CartQueryDataReturn} from '@shopify/hydrogen';
|
|
8
|
+
import {CartForm} from '@shopify/hydrogen';
|
|
10
9
|
import {CartMain} from '~/components/CartMain';
|
|
11
10
|
|
|
12
|
-
export const meta: MetaFunction = () => {
|
|
11
|
+
export const meta: Route.MetaFunction = () => {
|
|
13
12
|
return [{title: `Hydrogen | Cart`}];
|
|
14
13
|
};
|
|
15
14
|
|
|
16
15
|
export const headers: HeadersFunction = ({actionHeaders}) => actionHeaders;
|
|
17
16
|
|
|
18
|
-
export async function action({request, context}:
|
|
17
|
+
export async function action({request, context}: Route.ActionArgs) {
|
|
19
18
|
const {cart} = context;
|
|
20
19
|
|
|
21
20
|
const formData = await request.formData();
|
|
@@ -67,6 +66,11 @@ export async function action({request, context}: ActionFunctionArgs) {
|
|
|
67
66
|
result = await cart.updateGiftCardCodes(giftCardCodes);
|
|
68
67
|
break;
|
|
69
68
|
}
|
|
69
|
+
case CartForm.ACTIONS.GiftCardCodesRemove: {
|
|
70
|
+
const appliedGiftCardIds = inputs.giftCardCodes as string[];
|
|
71
|
+
result = await cart.removeGiftCardCodes(appliedGiftCardIds);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
70
74
|
case CartForm.ACTIONS.BuyerIdentityUpdate: {
|
|
71
75
|
result = await cart.updateBuyerIdentity({
|
|
72
76
|
...inputs.buyerIdentity,
|
|
@@ -100,7 +104,7 @@ export async function action({request, context}: ActionFunctionArgs) {
|
|
|
100
104
|
);
|
|
101
105
|
}
|
|
102
106
|
|
|
103
|
-
export async function loader({context}:
|
|
107
|
+
export async function loader({context}: Route.LoaderArgs) {
|
|
104
108
|
const {cart} = context;
|
|
105
109
|
return await cart.get();
|
|
106
110
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {redirect,
|
|
2
|
-
import
|
|
1
|
+
import {redirect, useLoaderData} from 'react-router';
|
|
2
|
+
import type {Route} from './+types/collections.$handle';
|
|
3
3
|
import {getPaginationVariables, Analytics} from '@shopify/hydrogen';
|
|
4
4
|
import {PaginatedResourceSection} from '~/components/PaginatedResourceSection';
|
|
5
5
|
import {redirectIfHandleIsLocalized} from '~/lib/redirect';
|
|
6
6
|
import {ProductItem} from '~/components/ProductItem';
|
|
7
|
+
import type {ProductItemFragment} from 'storefrontapi.generated';
|
|
7
8
|
|
|
8
|
-
export const meta: MetaFunction
|
|
9
|
+
export const meta: Route.MetaFunction = ({data}) => {
|
|
9
10
|
return [{title: `Hydrogen | ${data?.collection.title ?? ''} Collection`}];
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
export async function loader(args:
|
|
13
|
+
export async function loader(args: Route.LoaderArgs) {
|
|
13
14
|
// Start fetching non-critical data without blocking time to first byte
|
|
14
15
|
const deferredData = loadDeferredData(args);
|
|
15
16
|
|
|
@@ -23,11 +24,7 @@ export async function loader(args: LoaderFunctionArgs) {
|
|
|
23
24
|
* Load data necessary for rendering content above the fold. This is the critical data
|
|
24
25
|
* needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
|
|
25
26
|
*/
|
|
26
|
-
async function loadCriticalData({
|
|
27
|
-
context,
|
|
28
|
-
params,
|
|
29
|
-
request,
|
|
30
|
-
}: LoaderFunctionArgs) {
|
|
27
|
+
async function loadCriticalData({context, params, request}: Route.LoaderArgs) {
|
|
31
28
|
const {handle} = params;
|
|
32
29
|
const {storefront} = context;
|
|
33
30
|
const paginationVariables = getPaginationVariables(request, {
|
|
@@ -64,7 +61,7 @@ async function loadCriticalData({
|
|
|
64
61
|
* fetched after the initial page load. If it's unavailable, the page should still 200.
|
|
65
62
|
* Make sure to not throw any errors here, as it will cause the page to 500.
|
|
66
63
|
*/
|
|
67
|
-
function loadDeferredData({context}:
|
|
64
|
+
function loadDeferredData({context}: Route.LoaderArgs) {
|
|
68
65
|
return {};
|
|
69
66
|
}
|
|
70
67
|
|
|
@@ -75,7 +72,7 @@ export default function Collection() {
|
|
|
75
72
|
<div className="collection">
|
|
76
73
|
<h1>{collection.title}</h1>
|
|
77
74
|
<p className="collection-description">{collection.description}</p>
|
|
78
|
-
<PaginatedResourceSection
|
|
75
|
+
<PaginatedResourceSection<ProductItemFragment>
|
|
79
76
|
connection={collection.products}
|
|
80
77
|
resourcesClassName="products-grid"
|
|
81
78
|
>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import {useLoaderData, Link} from 'react-router';
|
|
2
|
+
import type {Route} from './+types/collections._index';
|
|
3
3
|
import {getPaginationVariables, Image} from '@shopify/hydrogen';
|
|
4
4
|
import type {CollectionFragment} from 'storefrontapi.generated';
|
|
5
5
|
import {PaginatedResourceSection} from '~/components/PaginatedResourceSection';
|
|
6
6
|
|
|
7
|
-
export async function loader(args:
|
|
7
|
+
export async function loader(args: Route.LoaderArgs) {
|
|
8
8
|
// Start fetching non-critical data without blocking time to first byte
|
|
9
9
|
const deferredData = loadDeferredData(args);
|
|
10
10
|
|
|
@@ -18,7 +18,7 @@ export async function loader(args: LoaderFunctionArgs) {
|
|
|
18
18
|
* Load data necessary for rendering content above the fold. This is the critical data
|
|
19
19
|
* needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
|
|
20
20
|
*/
|
|
21
|
-
async function loadCriticalData({context, request}:
|
|
21
|
+
async function loadCriticalData({context, request}: Route.LoaderArgs) {
|
|
22
22
|
const paginationVariables = getPaginationVariables(request, {
|
|
23
23
|
pageBy: 4,
|
|
24
24
|
});
|
|
@@ -38,7 +38,7 @@ async function loadCriticalData({context, request}: LoaderFunctionArgs) {
|
|
|
38
38
|
* fetched after the initial page load. If it's unavailable, the page should still 200.
|
|
39
39
|
* Make sure to not throw any errors here, as it will cause the page to 500.
|
|
40
40
|
*/
|
|
41
|
-
function loadDeferredData({context}:
|
|
41
|
+
function loadDeferredData({context}: Route.LoaderArgs) {
|
|
42
42
|
return {};
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -48,7 +48,7 @@ export default function Collections() {
|
|
|
48
48
|
return (
|
|
49
49
|
<div className="collections">
|
|
50
50
|
<h1>Collections</h1>
|
|
51
|
-
<PaginatedResourceSection
|
|
51
|
+
<PaginatedResourceSection<CollectionFragment>
|
|
52
52
|
connection={collections}
|
|
53
53
|
resourcesClassName="collections-grid"
|
|
54
54
|
>
|