@doswiftly/cli 0.1.18 → 0.1.19
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/README.md +23 -323
- package/dist/commands/check.js +1 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +39 -20
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +4 -4
- package/dist/commands/sdk.js +5 -5
- package/dist/commands/sdk.js.map +1 -1
- package/dist/commands/template.js +4 -4
- package/dist/commands/template.js.map +1 -1
- package/dist/commands/types.js +5 -5
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/verify.js +2 -2
- package/dist/commands/verify.js.map +1 -1
- package/dist/lib/package-manager.d.ts +1 -1
- package/dist/lib/package-manager.js +1 -1
- package/package.json +1 -1
- package/templates/storefront-nextjs/README.md +16 -12
- package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
- package/templates/storefront-nextjs/app/account/page.tsx +2 -2
- package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
- package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
- package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
- package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
- package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
- package/templates/storefront-nextjs/app/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/page.tsx +2 -2
- package/templates/storefront-nextjs/app/search/page.tsx +1 -1
- package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
- package/templates/storefront-nextjs/components/providers.tsx +1 -1
- package/templates/storefront-nextjs/lib/currency.tsx +3 -3
- package/templates/storefront-nextjs/lib/format.ts +1 -1
- package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
- package/templates/storefront-nextjs/package.dev.json +1 -1
- package/templates/storefront-nextjs/package.json +1 -1
- package/templates/storefront-nextjs/package.json.template +1 -1
- package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
- package/templates/storefront-nextjs-shadcn/CLAUDE.md +148 -35
- package/templates/storefront-nextjs-shadcn/README.md +29 -162
- package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +98 -91
- package/templates/storefront-nextjs-shadcn/app/account/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/account/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +53 -162
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/loading.tsx +60 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +36 -47
- package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +46 -29
- package/templates/storefront-nextjs-shadcn/app/account/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +108 -71
- package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
- package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
- package/templates/storefront-nextjs-shadcn/app/auth/forgot-password/page.tsx +10 -5
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/loading.tsx +17 -0
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +43 -2
- package/templates/storefront-nextjs-shadcn/app/blog/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/app/cart/loading.tsx +26 -0
- package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +6 -3
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/category-products-client.tsx +56 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +76 -59
- package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +8 -4
- package/templates/storefront-nextjs-shadcn/app/checkout/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/loading.tsx +31 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +116 -79
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/app/collections/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +7 -4
- package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
- package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
- package/templates/storefront-nextjs-shadcn/app/layout.tsx +46 -11
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/loading.tsx +29 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +6 -6
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +15 -61
- package/templates/storefront-nextjs-shadcn/app/products/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +405 -151
- package/templates/storefront-nextjs-shadcn/app/search/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
- package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +26 -24
- package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +9 -9
- package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +11 -37
- package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +37 -23
- package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +4 -3
- package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +22 -7
- package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
- package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +3 -3
- package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +2 -12
- package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
- package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +4 -4
- package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
- package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +33 -23
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
- package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +10 -19
- package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
- package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
- package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +69 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +84 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +138 -0
- package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +3 -31
- package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +176 -123
- package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
- package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +19 -7
- package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
- package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +1 -7
- package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
- package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
- package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +30 -0
- package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
- package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
- package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
- package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
- package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
- package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/generated/graphql.ts +12779 -0
- package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
- package/templates/storefront-nextjs-shadcn/hooks/index.ts +2 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +51 -19
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +13 -9
- package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
- package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
- package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +32 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +687 -632
- package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +86 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +131 -182
- package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
- package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
- package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
- package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
- package/templates/storefront-nextjs-shadcn/package.json +12 -13
- package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
- package/templates/storefront-nextjs-shadcn/proxy.ts +3 -4
- package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +41 -39
- package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
- package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
- package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
- package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
- package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
- package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
- package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
- package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
- package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
- package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
- package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
- package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
- package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
- package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
- package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
- package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
- package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
- package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
- package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
- package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
- package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
- package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
- package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
|
@@ -1,134 +1,191 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useQuery, useMutation, useQueryClient, type UseQueryOptions, type UseMutationOptions } from '@tanstack/react-query';
|
|
4
|
-
import {
|
|
5
|
-
import { useCurrencyStore } from '
|
|
6
|
-
import type
|
|
4
|
+
import { useExecute } from './client';
|
|
5
|
+
import { useCurrencyStore, useAuthStore } from '@doswiftly/storefront-sdk/react';
|
|
6
|
+
import { normalizeConnection, type NormalizedConnection } from '@doswiftly/storefront-sdk';
|
|
7
|
+
import { queryKeys } from './query-keys';
|
|
8
|
+
import type { TypedDocumentString } from '@/generated/graphql';
|
|
9
|
+
import type { NormalizedProductsResult, NormalizedCollectionsResult, NormalizedCategoriesResult } from './types';
|
|
10
|
+
|
|
11
|
+
// Static imports — Documents
|
|
12
|
+
import {
|
|
13
|
+
ProductDocument,
|
|
14
|
+
ProductsDocument,
|
|
15
|
+
CollectionDocument,
|
|
16
|
+
CollectionsDocument,
|
|
17
|
+
CategoriesDocument,
|
|
18
|
+
CategoryDocument,
|
|
19
|
+
AvailableFiltersDocument,
|
|
20
|
+
CartDocument,
|
|
21
|
+
CartCreateDocument,
|
|
22
|
+
CartLinesAddDocument,
|
|
23
|
+
CartLinesUpdateDocument,
|
|
24
|
+
CartLinesRemoveDocument,
|
|
25
|
+
CartDiscountCodesUpdateDocument,
|
|
26
|
+
CheckoutDocument,
|
|
27
|
+
CheckoutCreateDocument,
|
|
28
|
+
CheckoutShippingAddressUpdateDocument,
|
|
29
|
+
CheckoutBillingAddressUpdateDocument,
|
|
30
|
+
CheckoutEmailUpdateDocument,
|
|
31
|
+
CheckoutShippingLineUpdateDocument,
|
|
32
|
+
CheckoutDiscountCodeApplyDocument,
|
|
33
|
+
CheckoutDiscountCodeRemoveDocument,
|
|
34
|
+
CheckoutCompleteDocument,
|
|
35
|
+
CheckoutGiftCardApplyDocument,
|
|
36
|
+
CheckoutGiftCardRemoveDocument,
|
|
37
|
+
CustomerDocument,
|
|
38
|
+
CustomerProfileDocument,
|
|
39
|
+
CustomerOrderDocument,
|
|
40
|
+
CustomerUpdateDocument,
|
|
41
|
+
CustomerAddressCreateDocument,
|
|
42
|
+
CustomerAddressUpdateDocument,
|
|
43
|
+
CustomerAddressDeleteDocument,
|
|
44
|
+
CustomerDefaultAddressUpdateDocument,
|
|
45
|
+
CustomerLoginDocument,
|
|
46
|
+
CustomerLogoutDocument,
|
|
47
|
+
LoyaltyMemberDocument,
|
|
48
|
+
LoyaltyRewardsDocument,
|
|
49
|
+
LoyaltyTransactionsDocument,
|
|
50
|
+
LoyaltySettingsDocument,
|
|
51
|
+
ReferralStatsDocument,
|
|
52
|
+
RedeemLoyaltyRewardDocument,
|
|
53
|
+
} from '@/generated/graphql';
|
|
54
|
+
|
|
55
|
+
// Static imports — Types
|
|
56
|
+
import type {
|
|
57
|
+
ProductQuery,
|
|
58
|
+
ProductQueryVariables,
|
|
59
|
+
ProductsQuery,
|
|
60
|
+
ProductsQueryVariables,
|
|
61
|
+
ProductSortKeys,
|
|
62
|
+
CollectionQuery,
|
|
63
|
+
CollectionQueryVariables,
|
|
64
|
+
CollectionsQuery,
|
|
65
|
+
CollectionsQueryVariables,
|
|
66
|
+
CollectionSortKeys,
|
|
67
|
+
CategoriesQuery,
|
|
68
|
+
CategoryQuery,
|
|
69
|
+
CategoryQueryVariables,
|
|
70
|
+
Category,
|
|
71
|
+
ProductFilterInput,
|
|
72
|
+
AvailableFiltersQuery,
|
|
73
|
+
AvailableFiltersQueryVariables,
|
|
74
|
+
AvailableFiltersInput,
|
|
75
|
+
CartQuery,
|
|
76
|
+
CartQueryVariables,
|
|
77
|
+
CartCreateMutation,
|
|
78
|
+
CartCreateMutationVariables,
|
|
79
|
+
CartLinesAddMutation,
|
|
80
|
+
CartLinesAddMutationVariables,
|
|
81
|
+
CartLinesUpdateMutation,
|
|
82
|
+
CartLinesUpdateMutationVariables,
|
|
83
|
+
CartLinesRemoveMutation,
|
|
84
|
+
CartLinesRemoveMutationVariables,
|
|
85
|
+
CartDiscountCodesUpdateMutation,
|
|
86
|
+
CartDiscountCodesUpdateMutationVariables,
|
|
87
|
+
CheckoutQuery,
|
|
88
|
+
CheckoutQueryVariables,
|
|
89
|
+
CheckoutCreateMutation,
|
|
90
|
+
CheckoutCreateMutationVariables,
|
|
91
|
+
CheckoutShippingAddressUpdateMutation,
|
|
92
|
+
CheckoutShippingAddressUpdateMutationVariables,
|
|
93
|
+
CheckoutBillingAddressUpdateMutation,
|
|
94
|
+
CheckoutBillingAddressUpdateMutationVariables,
|
|
95
|
+
CheckoutEmailUpdateMutation,
|
|
96
|
+
CheckoutEmailUpdateMutationVariables,
|
|
97
|
+
CheckoutShippingLineUpdateMutation,
|
|
98
|
+
CheckoutShippingLineUpdateMutationVariables,
|
|
99
|
+
CheckoutDiscountCodeApplyMutation,
|
|
100
|
+
CheckoutDiscountCodeApplyMutationVariables,
|
|
101
|
+
CheckoutDiscountCodeRemoveMutation,
|
|
102
|
+
CheckoutDiscountCodeRemoveMutationVariables,
|
|
103
|
+
CheckoutCompleteMutation,
|
|
104
|
+
CheckoutCompleteMutationVariables,
|
|
105
|
+
CheckoutGiftCardApplyMutation,
|
|
106
|
+
CheckoutGiftCardApplyMutationVariables,
|
|
107
|
+
CheckoutGiftCardRemoveMutation,
|
|
108
|
+
CheckoutGiftCardRemoveMutationVariables,
|
|
109
|
+
CustomerQuery,
|
|
110
|
+
CustomerQueryVariables,
|
|
111
|
+
CustomerProfileQuery,
|
|
112
|
+
CustomerProfileQueryVariables,
|
|
113
|
+
CustomerOrderQuery,
|
|
114
|
+
CustomerOrderQueryVariables,
|
|
115
|
+
CustomerUpdateMutation,
|
|
116
|
+
CustomerUpdateMutationVariables,
|
|
117
|
+
CustomerUpdateInput,
|
|
118
|
+
CustomerAddressCreateMutation,
|
|
119
|
+
CustomerAddressCreateMutationVariables,
|
|
120
|
+
CustomerAddressUpdateMutation,
|
|
121
|
+
CustomerAddressUpdateMutationVariables,
|
|
122
|
+
CustomerAddressDeleteMutation,
|
|
123
|
+
CustomerAddressDeleteMutationVariables,
|
|
124
|
+
CustomerDefaultAddressUpdateMutation,
|
|
125
|
+
CustomerDefaultAddressUpdateMutationVariables,
|
|
126
|
+
CustomerLoginMutation,
|
|
127
|
+
CustomerLoginMutationVariables,
|
|
128
|
+
CustomerLogoutMutation,
|
|
129
|
+
CustomerLogoutMutationVariables,
|
|
130
|
+
LoyaltyMemberQuery,
|
|
131
|
+
LoyaltyRewardsQuery,
|
|
132
|
+
LoyaltyTransactionsQuery,
|
|
133
|
+
LoyaltyTransactionsQueryVariables,
|
|
134
|
+
LoyaltySettingsQuery,
|
|
135
|
+
ReferralStatsQuery,
|
|
136
|
+
RedeemLoyaltyRewardMutation,
|
|
137
|
+
RedeemLoyaltyRewardMutationVariables,
|
|
138
|
+
} from '@/generated/graphql';
|
|
139
|
+
|
|
140
|
+
// normalizeConnection and NormalizedConnection imported from SDK (see top of file)
|
|
7
141
|
|
|
8
142
|
// ============================================================================
|
|
9
|
-
//
|
|
143
|
+
// GENERIC QUERY HOOK
|
|
10
144
|
// ============================================================================
|
|
11
145
|
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
* Converts GraphQL edges/nodes structure to flat arrays
|
|
15
|
-
*/
|
|
16
|
-
export interface NormalizedConnection<T> {
|
|
17
|
-
items: T[];
|
|
18
|
-
pageInfo: {
|
|
19
|
-
hasNextPage: boolean;
|
|
20
|
-
hasPreviousPage: boolean;
|
|
21
|
-
startCursor?: string | null;
|
|
22
|
-
endCursor?: string | null;
|
|
23
|
-
};
|
|
24
|
-
totalCount?: number;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* GraphQL connection edge structure
|
|
29
|
-
*/
|
|
30
|
-
interface Edge<T> {
|
|
31
|
-
node: T;
|
|
32
|
-
cursor: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* GraphQL connection structure
|
|
37
|
-
*/
|
|
38
|
-
interface Connection<T> {
|
|
39
|
-
edges: Edge<T>[];
|
|
40
|
-
pageInfo: {
|
|
41
|
-
hasNextPage: boolean;
|
|
42
|
-
hasPreviousPage: boolean;
|
|
43
|
-
startCursor?: string | null;
|
|
44
|
-
endCursor?: string | null;
|
|
45
|
-
};
|
|
46
|
-
totalCount?: number;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ============================================================================
|
|
50
|
-
// UTILITY FUNCTIONS
|
|
51
|
-
// ============================================================================
|
|
146
|
+
/** Cache operation names to avoid regex on every render */
|
|
147
|
+
const operationNameCache = new Map<TypedDocumentString<unknown, unknown>, string>();
|
|
52
148
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* @returns Normalized response with flat items array
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```typescript
|
|
64
|
-
* const data = { products: { edges: [...], pageInfo: {...} } };
|
|
65
|
-
* const normalized = normalizeConnection(data.products);
|
|
66
|
-
* // normalized.items is now a flat array
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export function normalizeConnection<T>(
|
|
70
|
-
connection: Connection<T>
|
|
71
|
-
): NormalizedConnection<T> {
|
|
72
|
-
return {
|
|
73
|
-
items: connection.edges.map((edge) => edge.node),
|
|
74
|
-
pageInfo: connection.pageInfo,
|
|
75
|
-
totalCount: connection.totalCount,
|
|
76
|
-
};
|
|
149
|
+
function getOperationName(document: TypedDocumentString<unknown, unknown>): string {
|
|
150
|
+
let name = operationNameCache.get(document);
|
|
151
|
+
if (!name) {
|
|
152
|
+
name = document.toString().match(/^(?:query|mutation|subscription)\s+(\w+)/)?.[1] || 'GraphQLQuery';
|
|
153
|
+
operationNameCache.set(document, name);
|
|
154
|
+
}
|
|
155
|
+
return name;
|
|
77
156
|
}
|
|
78
157
|
|
|
79
|
-
// ============================================================================
|
|
80
|
-
// GENERIC QUERY HOOK
|
|
81
|
-
// ============================================================================
|
|
82
|
-
|
|
83
158
|
/**
|
|
84
159
|
* Generic query hook with currency-aware caching
|
|
85
|
-
*
|
|
160
|
+
*
|
|
86
161
|
* Wraps React Query's useQuery with automatic currency injection
|
|
87
162
|
* into query keys for proper cache invalidation when currency changes.
|
|
88
|
-
*
|
|
89
|
-
* @param document - TypedDocumentNode from codegen
|
|
90
|
-
* @param variables - Query variables
|
|
91
|
-
* @param options - React Query options
|
|
92
|
-
* @returns React Query result
|
|
93
|
-
*
|
|
163
|
+
*
|
|
94
164
|
* @example
|
|
95
165
|
* ```typescript
|
|
96
166
|
* const { data } = useGraphQLQuery(ProductDocument, { handle: 'my-product' });
|
|
97
167
|
* ```
|
|
98
168
|
*/
|
|
99
169
|
export function useGraphQLQuery<TResult, TVariables>(
|
|
100
|
-
document:
|
|
170
|
+
document: TypedDocumentString<TResult, TVariables>,
|
|
101
171
|
variables?: TVariables,
|
|
102
172
|
options?: Omit<UseQueryOptions<TResult>, 'queryKey' | 'queryFn'>
|
|
103
173
|
) {
|
|
104
|
-
const
|
|
105
|
-
const currency = useCurrencyStore((s
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const queryKey = [
|
|
110
|
-
// Extract operation name from document
|
|
111
|
-
(document as any).definitions?.[0]?.name?.value || 'GraphQLQuery',
|
|
112
|
-
variables,
|
|
113
|
-
currency,
|
|
114
|
-
];
|
|
115
|
-
|
|
174
|
+
const execute = useExecute();
|
|
175
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
176
|
+
const operationName = getOperationName(document as TypedDocumentString<unknown, unknown>);
|
|
177
|
+
const queryKey = [operationName, variables, currency];
|
|
178
|
+
|
|
116
179
|
return useQuery({
|
|
117
180
|
queryKey,
|
|
118
|
-
queryFn: () =>
|
|
181
|
+
queryFn: () => execute<TResult>(document.toString(), variables as Record<string, unknown>),
|
|
119
182
|
...options,
|
|
120
183
|
});
|
|
121
184
|
}
|
|
122
185
|
|
|
123
186
|
/**
|
|
124
187
|
* Generic mutation hook
|
|
125
|
-
*
|
|
126
|
-
* Wraps React Query's useMutation for GraphQL mutations.
|
|
127
|
-
*
|
|
128
|
-
* @param document - TypedDocumentNode from codegen
|
|
129
|
-
* @param options - React Query mutation options
|
|
130
|
-
* @returns React Query mutation result
|
|
131
|
-
*
|
|
188
|
+
*
|
|
132
189
|
* @example
|
|
133
190
|
* ```typescript
|
|
134
191
|
* const mutation = useGraphQLMutation(CartCreateDocument);
|
|
@@ -136,13 +193,13 @@ export function useGraphQLQuery<TResult, TVariables>(
|
|
|
136
193
|
* ```
|
|
137
194
|
*/
|
|
138
195
|
export function useGraphQLMutation<TResult, TVariables>(
|
|
139
|
-
document:
|
|
196
|
+
document: TypedDocumentString<TResult, TVariables>,
|
|
140
197
|
options?: UseMutationOptions<TResult, Error, TVariables>
|
|
141
198
|
) {
|
|
142
|
-
const
|
|
143
|
-
|
|
199
|
+
const execute = useExecute();
|
|
200
|
+
|
|
144
201
|
return useMutation({
|
|
145
|
-
mutationFn: (variables: TVariables) =>
|
|
202
|
+
mutationFn: (variables: TVariables) => execute<TResult>(document.toString(), variables as Record<string, unknown>),
|
|
146
203
|
...options,
|
|
147
204
|
});
|
|
148
205
|
}
|
|
@@ -153,106 +210,63 @@ export function useGraphQLMutation<TResult, TVariables>(
|
|
|
153
210
|
|
|
154
211
|
/**
|
|
155
212
|
* Fetch single product by handle or ID
|
|
156
|
-
*
|
|
157
|
-
* Automatically includes current currency in request headers
|
|
158
|
-
* and query key for proper cache invalidation.
|
|
159
|
-
*
|
|
160
|
-
* @param handleOrId - Product handle (string) or ID (gid://)
|
|
161
|
-
* @param options - React Query options
|
|
162
|
-
* @returns Product query result
|
|
163
|
-
*
|
|
213
|
+
*
|
|
164
214
|
* @example
|
|
165
215
|
* ```typescript
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* export function ProductPrice({ handle }) {
|
|
170
|
-
* const { data, isLoading } = useProduct(handle);
|
|
171
|
-
*
|
|
172
|
-
* if (isLoading) return <div>Loading...</div>;
|
|
173
|
-
*
|
|
174
|
-
* return (
|
|
175
|
-
* <div suppressHydrationWarning>
|
|
176
|
-
* {data.product.priceRange.minVariantPrice.amount}{' '}
|
|
177
|
-
* {data.product.priceRange.minVariantPrice.currencyCode}
|
|
178
|
-
* </div>
|
|
179
|
-
* );
|
|
180
|
-
* }
|
|
216
|
+
* const { data, isLoading } = useProduct('my-product-handle');
|
|
217
|
+
* const product = data?.product;
|
|
181
218
|
* ```
|
|
182
219
|
*/
|
|
183
220
|
export function useProduct(
|
|
184
221
|
handleOrId: string,
|
|
185
|
-
options?: Omit<UseQueryOptions<
|
|
222
|
+
options?: Omit<UseQueryOptions<ProductQuery>, 'queryKey' | 'queryFn'>
|
|
186
223
|
) {
|
|
187
|
-
const
|
|
188
|
-
const currency = useCurrencyStore((s
|
|
189
|
-
|
|
190
|
-
// Determine if it's an ID or handle
|
|
224
|
+
const execute = useExecute();
|
|
225
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
226
|
+
|
|
191
227
|
const isId = handleOrId.startsWith('gid://');
|
|
192
|
-
|
|
228
|
+
|
|
193
229
|
return useQuery({
|
|
194
|
-
queryKey:
|
|
195
|
-
queryFn:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return client.request(ProductDocument, variables as any);
|
|
230
|
+
queryKey: queryKeys.products.detail(handleOrId, currency),
|
|
231
|
+
queryFn: () => {
|
|
232
|
+
const variables: ProductQueryVariables = isId
|
|
233
|
+
? { id: handleOrId }
|
|
234
|
+
: { handle: handleOrId };
|
|
235
|
+
return execute<ProductQuery>(ProductDocument.toString(), variables);
|
|
201
236
|
},
|
|
202
237
|
...options,
|
|
203
238
|
});
|
|
204
239
|
}
|
|
205
240
|
|
|
206
|
-
/**
|
|
207
|
-
* Fetch products with pagination and normalization
|
|
208
|
-
*
|
|
209
|
-
* Automatically normalizes GraphQL edges/nodes structure to flat arrays.
|
|
210
|
-
* Includes currency in query key for cache invalidation.
|
|
211
|
-
*
|
|
212
|
-
* @param variables - Query variables (first, after, query, sortKey, reverse)
|
|
213
|
-
* @param options - React Query options
|
|
214
|
-
* @returns Normalized products response
|
|
215
|
-
*
|
|
216
|
-
* @example
|
|
217
|
-
* ```typescript
|
|
218
|
-
* // In a Client Component
|
|
219
|
-
* 'use client';
|
|
220
|
-
*
|
|
221
|
-
* export function ProductList() {
|
|
222
|
-
* const { data, isLoading } = useProducts({ first: 20 });
|
|
223
|
-
*
|
|
224
|
-
* if (isLoading) return <div>Loading...</div>;
|
|
225
|
-
*
|
|
226
|
-
* return (
|
|
227
|
-
* <div>
|
|
228
|
-
* {data.products.map(product => (
|
|
229
|
-
* <ProductCard key={product.id} product={product} />
|
|
230
|
-
* ))}
|
|
231
|
-
* </div>
|
|
232
|
-
* );
|
|
233
|
-
* }
|
|
234
|
-
* ```
|
|
235
|
-
*/
|
|
236
241
|
/**
|
|
237
242
|
* Map frontend sort values to GraphQL enum values
|
|
238
243
|
*/
|
|
239
|
-
function normalizeSortKey(sortKey?: string): { sortKey
|
|
244
|
+
function normalizeSortKey(sortKey?: string): { sortKey: ProductSortKeys; reverse: boolean } {
|
|
240
245
|
if (!sortKey) return { sortKey: 'BEST_SELLING', reverse: false };
|
|
241
|
-
|
|
242
|
-
const sortMap: Record<string, { sortKey:
|
|
246
|
+
|
|
247
|
+
const sortMap: Record<string, { sortKey: ProductSortKeys; reverse: boolean }> = {
|
|
243
248
|
'relevance': { sortKey: 'RELEVANCE', reverse: false },
|
|
244
249
|
'best-selling': { sortKey: 'BEST_SELLING', reverse: false },
|
|
245
250
|
'price-low-to-high': { sortKey: 'PRICE', reverse: false },
|
|
246
251
|
'price-high-to-low': { sortKey: 'PRICE', reverse: true },
|
|
247
252
|
'title-asc': { sortKey: 'TITLE', reverse: false },
|
|
248
253
|
'title-desc': { sortKey: 'TITLE', reverse: true },
|
|
249
|
-
'created-desc': { sortKey: '
|
|
250
|
-
'created-asc': { sortKey: '
|
|
254
|
+
'created-desc': { sortKey: 'CREATED_AT', reverse: true },
|
|
255
|
+
'created-asc': { sortKey: 'CREATED_AT', reverse: false },
|
|
251
256
|
};
|
|
252
|
-
|
|
257
|
+
|
|
253
258
|
return sortMap[sortKey] || { sortKey: 'BEST_SELLING', reverse: false };
|
|
254
259
|
}
|
|
255
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Fetch products with pagination and normalization
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```typescript
|
|
266
|
+
* const { data, isLoading } = useProducts({ first: 20 });
|
|
267
|
+
* data?.products.map(product => ...)
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
256
270
|
export function useProducts(
|
|
257
271
|
variables?: {
|
|
258
272
|
first?: number;
|
|
@@ -260,32 +274,31 @@ export function useProducts(
|
|
|
260
274
|
query?: string;
|
|
261
275
|
sortKey?: string;
|
|
262
276
|
reverse?: boolean;
|
|
277
|
+
filters?: ProductFilterInput;
|
|
263
278
|
},
|
|
264
|
-
options?: Omit<UseQueryOptions<
|
|
279
|
+
options?: Omit<UseQueryOptions<NormalizedProductsResult>, 'queryKey' | 'queryFn'>
|
|
265
280
|
) {
|
|
266
|
-
const
|
|
267
|
-
const currency = useCurrencyStore((s
|
|
268
|
-
|
|
281
|
+
const execute = useExecute();
|
|
282
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
283
|
+
|
|
269
284
|
return useQuery({
|
|
270
|
-
queryKey:
|
|
285
|
+
queryKey: queryKeys.products.list(variables as Record<string, unknown>, currency),
|
|
271
286
|
queryFn: async () => {
|
|
272
|
-
// Dynamic import to avoid circular dependencies
|
|
273
|
-
const { ProductsDocument } = await import('@/generated/graphql');
|
|
274
|
-
|
|
275
|
-
// Normalize sort key to GraphQL enum format
|
|
276
287
|
const { sortKey: normalizedSortKey, reverse: normalizedReverse } = normalizeSortKey(variables?.sortKey);
|
|
277
|
-
|
|
278
|
-
const
|
|
288
|
+
|
|
289
|
+
const graphqlVariables: ProductsQueryVariables = {
|
|
279
290
|
first: variables?.first ?? 20,
|
|
280
291
|
after: variables?.after,
|
|
281
292
|
query: variables?.query,
|
|
282
|
-
sortKey: normalizedSortKey
|
|
293
|
+
sortKey: normalizedSortKey,
|
|
283
294
|
reverse: variables?.reverse !== undefined ? variables.reverse : normalizedReverse,
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
295
|
+
filters: variables?.filters,
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const data = await execute<ProductsQuery>(ProductsDocument.toString(), graphqlVariables);
|
|
299
|
+
|
|
287
300
|
return {
|
|
288
|
-
products: data.products.edges.map((edge
|
|
301
|
+
products: data.products.edges.map((edge) => edge.node),
|
|
289
302
|
pageInfo: data.products.pageInfo,
|
|
290
303
|
totalCount: data.products.totalCount,
|
|
291
304
|
};
|
|
@@ -300,11 +313,7 @@ export function useProducts(
|
|
|
300
313
|
|
|
301
314
|
/**
|
|
302
315
|
* Fetch single collection by handle or ID
|
|
303
|
-
*
|
|
304
|
-
* @param handleOrId - Collection handle or ID
|
|
305
|
-
* @param options - React Query options
|
|
306
|
-
* @returns Collection query result
|
|
307
|
-
*
|
|
316
|
+
*
|
|
308
317
|
* @example
|
|
309
318
|
* ```typescript
|
|
310
319
|
* const { data } = useCollection('featured-products');
|
|
@@ -312,24 +321,20 @@ export function useProducts(
|
|
|
312
321
|
*/
|
|
313
322
|
export function useCollection(
|
|
314
323
|
handleOrId: string,
|
|
315
|
-
options?: Omit<UseQueryOptions<
|
|
324
|
+
options?: Omit<UseQueryOptions<CollectionQuery>, 'queryKey' | 'queryFn'>
|
|
316
325
|
) {
|
|
317
|
-
const
|
|
318
|
-
const currency = useCurrencyStore((s
|
|
319
|
-
|
|
326
|
+
const execute = useExecute();
|
|
327
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
328
|
+
|
|
320
329
|
const isId = handleOrId.startsWith('gid://');
|
|
321
|
-
|
|
330
|
+
|
|
322
331
|
return useQuery({
|
|
323
|
-
queryKey:
|
|
324
|
-
queryFn:
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
? { id: handleOrId } as { id: string }
|
|
330
|
-
: { handle: handleOrId } as { handle: string };
|
|
331
|
-
|
|
332
|
-
return client.request(CollectionDocument, variables as any);
|
|
332
|
+
queryKey: queryKeys.collections.detail(handleOrId, currency),
|
|
333
|
+
queryFn: () => {
|
|
334
|
+
const variables: CollectionQueryVariables = isId
|
|
335
|
+
? { id: handleOrId }
|
|
336
|
+
: { handle: handleOrId };
|
|
337
|
+
return execute<CollectionQuery>(CollectionDocument.toString(), variables);
|
|
333
338
|
},
|
|
334
339
|
...options,
|
|
335
340
|
});
|
|
@@ -337,11 +342,7 @@ export function useCollection(
|
|
|
337
342
|
|
|
338
343
|
/**
|
|
339
344
|
* Fetch collections with pagination and normalization
|
|
340
|
-
*
|
|
341
|
-
* @param variables - Query variables
|
|
342
|
-
* @param options - React Query options
|
|
343
|
-
* @returns Normalized collections response
|
|
344
|
-
*
|
|
345
|
+
*
|
|
345
346
|
* @example
|
|
346
347
|
* ```typescript
|
|
347
348
|
* const { data } = useCollections({ first: 10 });
|
|
@@ -352,30 +353,29 @@ export function useCollections(
|
|
|
352
353
|
first?: number;
|
|
353
354
|
after?: string;
|
|
354
355
|
query?: string;
|
|
355
|
-
sortKey?:
|
|
356
|
+
sortKey?: CollectionSortKeys;
|
|
356
357
|
reverse?: boolean;
|
|
357
358
|
},
|
|
358
|
-
options?: Omit<UseQueryOptions<
|
|
359
|
+
options?: Omit<UseQueryOptions<NormalizedCollectionsResult>, 'queryKey' | 'queryFn'>
|
|
359
360
|
) {
|
|
360
|
-
const
|
|
361
|
-
const currency = useCurrencyStore((s
|
|
362
|
-
|
|
361
|
+
const execute = useExecute();
|
|
362
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
363
|
+
|
|
363
364
|
return useQuery({
|
|
364
|
-
queryKey:
|
|
365
|
+
queryKey: queryKeys.collections.list(variables as Record<string, unknown>, currency),
|
|
365
366
|
queryFn: async () => {
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
const data = await client.request(CollectionsDocument, {
|
|
367
|
+
const graphqlVariables: CollectionsQueryVariables = {
|
|
369
368
|
first: variables?.first ?? 20,
|
|
370
369
|
after: variables?.after,
|
|
371
370
|
query: variables?.query,
|
|
372
|
-
sortKey: variables?.sortKey
|
|
371
|
+
sortKey: variables?.sortKey,
|
|
373
372
|
reverse: variables?.reverse,
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const data = await execute<CollectionsQuery>(CollectionsDocument.toString(), graphqlVariables);
|
|
376
|
+
|
|
377
377
|
return {
|
|
378
|
-
collections: data.collections.edges.map((edge
|
|
378
|
+
collections: data.collections.edges.map((edge) => edge.node),
|
|
379
379
|
pageInfo: data.collections.pageInfo,
|
|
380
380
|
totalCount: data.collections.totalCount,
|
|
381
381
|
};
|
|
@@ -388,17 +388,38 @@ export function useCollections(
|
|
|
388
388
|
// CATEGORY HOOKS
|
|
389
389
|
// ============================================================================
|
|
390
390
|
|
|
391
|
+
/**
|
|
392
|
+
* Fetch single category by slug or ID
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```typescript
|
|
396
|
+
* const { data } = useCategory('gift-cards');
|
|
397
|
+
* const category = data?.category;
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
export function useCategory(
|
|
401
|
+
slugOrId: string,
|
|
402
|
+
options?: Omit<UseQueryOptions<CategoryQuery>, 'queryKey' | 'queryFn'>
|
|
403
|
+
) {
|
|
404
|
+
const execute = useExecute();
|
|
405
|
+
|
|
406
|
+
const isId = slugOrId.startsWith('gid://');
|
|
407
|
+
|
|
408
|
+
return useQuery({
|
|
409
|
+
queryKey: queryKeys.categories.detail(slugOrId),
|
|
410
|
+
queryFn: () => {
|
|
411
|
+
const variables: CategoryQueryVariables = isId
|
|
412
|
+
? { id: slugOrId }
|
|
413
|
+
: { slug: slugOrId };
|
|
414
|
+
return execute<CategoryQuery>(CategoryDocument.toString(), variables);
|
|
415
|
+
},
|
|
416
|
+
...options,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
391
420
|
/**
|
|
392
421
|
* Fetch categories with hierarchical structure
|
|
393
|
-
*
|
|
394
|
-
* Categories are hierarchical (tree structure) and used for catalog organization.
|
|
395
|
-
* Use for filters, navigation, and SEO.
|
|
396
|
-
*
|
|
397
|
-
* Returns flat array of all categories (roots + children) for easy filtering.
|
|
398
|
-
*
|
|
399
|
-
* @param options - React Query options
|
|
400
|
-
* @returns Categories response with flat array
|
|
401
|
-
*
|
|
422
|
+
*
|
|
402
423
|
* @example
|
|
403
424
|
* ```typescript
|
|
404
425
|
* const { data } = useCategories();
|
|
@@ -406,28 +427,25 @@ export function useCollections(
|
|
|
406
427
|
* ```
|
|
407
428
|
*/
|
|
408
429
|
export function useCategories(
|
|
409
|
-
options?: Omit<UseQueryOptions<
|
|
430
|
+
options?: Omit<UseQueryOptions<NormalizedCategoriesResult>, 'queryKey' | 'queryFn'>
|
|
410
431
|
) {
|
|
411
|
-
const
|
|
412
|
-
const currency = useCurrencyStore((s
|
|
413
|
-
|
|
432
|
+
const execute = useExecute();
|
|
433
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
434
|
+
|
|
414
435
|
return useQuery({
|
|
415
|
-
queryKey:
|
|
436
|
+
queryKey: queryKeys.categories.list(currency),
|
|
416
437
|
queryFn: async () => {
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
// Flatten hierarchical structure to array for filters
|
|
422
|
-
const flattenCategories = (cats: any[]): any[] => {
|
|
423
|
-
return cats.flatMap((cat: any) => [
|
|
438
|
+
const data = await execute<CategoriesQuery>(CategoriesDocument.toString());
|
|
439
|
+
|
|
440
|
+
const flattenCategories = (cats: Category[]): Category[] => {
|
|
441
|
+
return cats.flatMap((cat) => [
|
|
424
442
|
cat,
|
|
425
|
-
...(cat.children ? flattenCategories(cat.children) : [])
|
|
443
|
+
...(cat.children ? flattenCategories(cat.children as Category[]) : [])
|
|
426
444
|
]);
|
|
427
445
|
};
|
|
428
|
-
|
|
429
|
-
const allCategories = flattenCategories(data.categories.roots
|
|
430
|
-
|
|
446
|
+
|
|
447
|
+
const allCategories = flattenCategories(data.categories.roots as Category[]);
|
|
448
|
+
|
|
431
449
|
return {
|
|
432
450
|
categories: allCategories,
|
|
433
451
|
roots: data.categories.roots,
|
|
@@ -438,21 +456,47 @@ export function useCategories(
|
|
|
438
456
|
});
|
|
439
457
|
}
|
|
440
458
|
|
|
459
|
+
// ============================================================================
|
|
460
|
+
// AVAILABLE FILTERS HOOK
|
|
461
|
+
// ============================================================================
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Fetch available filters for product listing (dynamic attributes, price range, categories).
|
|
465
|
+
* Context-aware: pass categoryId, collectionId, or searchQuery to scope filters.
|
|
466
|
+
*
|
|
467
|
+
* @example
|
|
468
|
+
* ```typescript
|
|
469
|
+
* const { data } = useAvailableFilters({ categoryId: 'some-id' });
|
|
470
|
+
* data?.availableFilters.attributes // dynamic attribute filters with counts
|
|
471
|
+
* data?.availableFilters.priceRange // { min, max } in context
|
|
472
|
+
* data?.availableFilters.categories // category filters with counts
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
475
|
+
export function useAvailableFilters(
|
|
476
|
+
input?: AvailableFiltersInput,
|
|
477
|
+
options?: Omit<UseQueryOptions<AvailableFiltersQuery>, 'queryKey' | 'queryFn'>
|
|
478
|
+
) {
|
|
479
|
+
const execute = useExecute();
|
|
480
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
481
|
+
|
|
482
|
+
return useQuery({
|
|
483
|
+
queryKey: queryKeys.filters.forContext(input as Record<string, unknown>, currency),
|
|
484
|
+
queryFn: () => {
|
|
485
|
+
const variables: AvailableFiltersQueryVariables = { input: input || null };
|
|
486
|
+
return execute<AvailableFiltersQuery>(AvailableFiltersDocument.toString(), variables);
|
|
487
|
+
},
|
|
488
|
+
staleTime: 60_000, // Filters change infrequently, cache for 1 min
|
|
489
|
+
...options,
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
|
|
441
493
|
// ============================================================================
|
|
442
494
|
// CART HOOKS
|
|
443
495
|
// ============================================================================
|
|
444
496
|
|
|
445
497
|
/**
|
|
446
498
|
* Fetch cart by ID
|
|
447
|
-
*
|
|
448
|
-
* Includes currency in query key to refetch when currency changes.
|
|
449
|
-
* Cart prices are locked for 24 hours, but currency header is still
|
|
450
|
-
* included for consistency.
|
|
451
|
-
*
|
|
452
|
-
* @param cartId - Cart ID
|
|
453
|
-
* @param options - React Query options
|
|
454
|
-
* @returns Cart query result
|
|
455
|
-
*
|
|
499
|
+
*
|
|
456
500
|
* @example
|
|
457
501
|
* ```typescript
|
|
458
502
|
* const { data } = useCart(cartId);
|
|
@@ -460,19 +504,17 @@ export function useCategories(
|
|
|
460
504
|
*/
|
|
461
505
|
export function useCart(
|
|
462
506
|
cartId: string | null,
|
|
463
|
-
options?: Omit<UseQueryOptions<
|
|
507
|
+
options?: Omit<UseQueryOptions<CartQuery | null>, 'queryKey' | 'queryFn'>
|
|
464
508
|
) {
|
|
465
|
-
const
|
|
466
|
-
const currency = useCurrencyStore((s
|
|
467
|
-
|
|
509
|
+
const execute = useExecute();
|
|
510
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
511
|
+
|
|
468
512
|
return useQuery({
|
|
469
|
-
queryKey:
|
|
470
|
-
queryFn:
|
|
513
|
+
queryKey: queryKeys.cart.detail(cartId, currency),
|
|
514
|
+
queryFn: () => {
|
|
471
515
|
if (!cartId) return null;
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
return client.request(CartDocument, { id: cartId });
|
|
516
|
+
const variables: CartQueryVariables = { id: cartId };
|
|
517
|
+
return execute<CartQuery>(CartDocument.toString(), variables);
|
|
476
518
|
},
|
|
477
519
|
enabled: Boolean(cartId),
|
|
478
520
|
...options,
|
|
@@ -481,40 +523,22 @@ export function useCart(
|
|
|
481
523
|
|
|
482
524
|
/**
|
|
483
525
|
* Create a new cart
|
|
484
|
-
*
|
|
485
|
-
* @param options - React Query mutation options
|
|
486
|
-
* @returns Cart create mutation
|
|
487
|
-
*
|
|
488
|
-
* @example
|
|
489
|
-
* ```typescript
|
|
490
|
-
* const createCart = useCartCreate();
|
|
491
|
-
*
|
|
492
|
-
* const handleCreate = async () => {
|
|
493
|
-
* const { cartCreate } = await createCart.mutateAsync({
|
|
494
|
-
* input: { lines: [...] }
|
|
495
|
-
* });
|
|
496
|
-
*
|
|
497
|
-
* if (cartCreate.cart) {
|
|
498
|
-
* // Store cart ID
|
|
499
|
-
* localStorage.setItem('cartId', cartCreate.cart.id);
|
|
500
|
-
* }
|
|
501
|
-
* };
|
|
502
|
-
* ```
|
|
503
526
|
*/
|
|
504
527
|
export function useCartCreate(
|
|
505
|
-
options?: UseMutationOptions<
|
|
528
|
+
options?: UseMutationOptions<CartCreateMutation, Error, CartCreateMutationVariables>
|
|
506
529
|
) {
|
|
507
|
-
const
|
|
530
|
+
const execute = useExecute();
|
|
508
531
|
const queryClient = useQueryClient();
|
|
509
|
-
|
|
532
|
+
|
|
510
533
|
return useMutation({
|
|
511
|
-
mutationFn:
|
|
512
|
-
|
|
513
|
-
|
|
534
|
+
mutationFn: (variables: CartCreateMutationVariables) =>
|
|
535
|
+
execute<CartCreateMutation>(CartCreateDocument.toString(), variables),
|
|
536
|
+
onMutate: async () => {
|
|
537
|
+
// Cancel in-flight cart queries to prevent stale data overwriting mutation result
|
|
538
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.cart.all() });
|
|
514
539
|
},
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
queryClient.invalidateQueries({ queryKey: ['Cart'] });
|
|
540
|
+
onSettled: () => {
|
|
541
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
|
|
518
542
|
},
|
|
519
543
|
...options,
|
|
520
544
|
});
|
|
@@ -522,36 +546,21 @@ export function useCartCreate(
|
|
|
522
546
|
|
|
523
547
|
/**
|
|
524
548
|
* Add lines to cart
|
|
525
|
-
*
|
|
526
|
-
* @param options - React Query mutation options
|
|
527
|
-
* @returns Cart lines add mutation
|
|
528
|
-
*
|
|
529
|
-
* @example
|
|
530
|
-
* ```typescript
|
|
531
|
-
* const addLines = useCartLinesAdd();
|
|
532
|
-
*
|
|
533
|
-
* const handleAddToCart = async () => {
|
|
534
|
-
* await addLines.mutateAsync({
|
|
535
|
-
* cartId: 'cart-123',
|
|
536
|
-
* lines: [{ merchandiseId: 'variant-456', quantity: 1 }]
|
|
537
|
-
* });
|
|
538
|
-
* };
|
|
539
|
-
* ```
|
|
540
549
|
*/
|
|
541
550
|
export function useCartLinesAdd(
|
|
542
|
-
options?: UseMutationOptions<
|
|
551
|
+
options?: UseMutationOptions<CartLinesAddMutation, Error, CartLinesAddMutationVariables>
|
|
543
552
|
) {
|
|
544
|
-
const
|
|
553
|
+
const execute = useExecute();
|
|
545
554
|
const queryClient = useQueryClient();
|
|
546
|
-
|
|
555
|
+
|
|
547
556
|
return useMutation({
|
|
548
|
-
mutationFn:
|
|
549
|
-
|
|
550
|
-
|
|
557
|
+
mutationFn: (variables: CartLinesAddMutationVariables) =>
|
|
558
|
+
execute<CartLinesAddMutation>(CartLinesAddDocument.toString(), variables),
|
|
559
|
+
onMutate: async () => {
|
|
560
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.cart.all() });
|
|
551
561
|
},
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
queryClient.invalidateQueries({ queryKey: ['Cart'] });
|
|
562
|
+
onSettled: () => {
|
|
563
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
|
|
555
564
|
},
|
|
556
565
|
...options,
|
|
557
566
|
});
|
|
@@ -559,36 +568,21 @@ export function useCartLinesAdd(
|
|
|
559
568
|
|
|
560
569
|
/**
|
|
561
570
|
* Update cart lines
|
|
562
|
-
*
|
|
563
|
-
* @param options - React Query mutation options
|
|
564
|
-
* @returns Cart lines update mutation
|
|
565
|
-
*
|
|
566
|
-
* @example
|
|
567
|
-
* ```typescript
|
|
568
|
-
* const updateLines = useCartLinesUpdate();
|
|
569
|
-
*
|
|
570
|
-
* const handleUpdateQuantity = async (lineId: string, quantity: number) => {
|
|
571
|
-
* await updateLines.mutateAsync({
|
|
572
|
-
* cartId: 'cart-123',
|
|
573
|
-
* lines: [{ id: lineId, quantity }]
|
|
574
|
-
* });
|
|
575
|
-
* };
|
|
576
|
-
* ```
|
|
577
571
|
*/
|
|
578
572
|
export function useCartLinesUpdate(
|
|
579
|
-
options?: UseMutationOptions<
|
|
573
|
+
options?: UseMutationOptions<CartLinesUpdateMutation, Error, CartLinesUpdateMutationVariables>
|
|
580
574
|
) {
|
|
581
|
-
const
|
|
575
|
+
const execute = useExecute();
|
|
582
576
|
const queryClient = useQueryClient();
|
|
583
|
-
|
|
577
|
+
|
|
584
578
|
return useMutation({
|
|
585
|
-
mutationFn:
|
|
586
|
-
|
|
587
|
-
|
|
579
|
+
mutationFn: (variables: CartLinesUpdateMutationVariables) =>
|
|
580
|
+
execute<CartLinesUpdateMutation>(CartLinesUpdateDocument.toString(), variables),
|
|
581
|
+
onMutate: async () => {
|
|
582
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.cart.all() });
|
|
588
583
|
},
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
queryClient.invalidateQueries({ queryKey: ['Cart'] });
|
|
584
|
+
onSettled: () => {
|
|
585
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
|
|
592
586
|
},
|
|
593
587
|
...options,
|
|
594
588
|
});
|
|
@@ -596,36 +590,21 @@ export function useCartLinesUpdate(
|
|
|
596
590
|
|
|
597
591
|
/**
|
|
598
592
|
* Remove lines from cart
|
|
599
|
-
*
|
|
600
|
-
* @param options - React Query mutation options
|
|
601
|
-
* @returns Cart lines remove mutation
|
|
602
|
-
*
|
|
603
|
-
* @example
|
|
604
|
-
* ```typescript
|
|
605
|
-
* const removeLines = useCartLinesRemove();
|
|
606
|
-
*
|
|
607
|
-
* const handleRemove = async (lineId: string) => {
|
|
608
|
-
* await removeLines.mutateAsync({
|
|
609
|
-
* cartId: 'cart-123',
|
|
610
|
-
* lineIds: [lineId]
|
|
611
|
-
* });
|
|
612
|
-
* };
|
|
613
|
-
* ```
|
|
614
593
|
*/
|
|
615
594
|
export function useCartLinesRemove(
|
|
616
|
-
options?: UseMutationOptions<
|
|
595
|
+
options?: UseMutationOptions<CartLinesRemoveMutation, Error, CartLinesRemoveMutationVariables>
|
|
617
596
|
) {
|
|
618
|
-
const
|
|
597
|
+
const execute = useExecute();
|
|
619
598
|
const queryClient = useQueryClient();
|
|
620
|
-
|
|
599
|
+
|
|
621
600
|
return useMutation({
|
|
622
|
-
mutationFn:
|
|
623
|
-
|
|
624
|
-
|
|
601
|
+
mutationFn: (variables: CartLinesRemoveMutationVariables) =>
|
|
602
|
+
execute<CartLinesRemoveMutation>(CartLinesRemoveDocument.toString(), variables),
|
|
603
|
+
onMutate: async () => {
|
|
604
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.cart.all() });
|
|
625
605
|
},
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
queryClient.invalidateQueries({ queryKey: ['Cart'] });
|
|
606
|
+
onSettled: () => {
|
|
607
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
|
|
629
608
|
},
|
|
630
609
|
...options,
|
|
631
610
|
});
|
|
@@ -633,26 +612,21 @@ export function useCartLinesRemove(
|
|
|
633
612
|
|
|
634
613
|
/**
|
|
635
614
|
* Update discount codes on cart
|
|
636
|
-
*
|
|
637
|
-
* Invalidates cart query on success so all consumers (useCartSync)
|
|
638
|
-
* automatically receive updated discount data.
|
|
639
|
-
*
|
|
640
|
-
* @param options - React Query mutation options
|
|
641
|
-
* @returns Cart discount codes update mutation
|
|
642
615
|
*/
|
|
643
616
|
export function useCartDiscountCodesUpdate(
|
|
644
|
-
options?: UseMutationOptions<
|
|
617
|
+
options?: UseMutationOptions<CartDiscountCodesUpdateMutation, Error, CartDiscountCodesUpdateMutationVariables>
|
|
645
618
|
) {
|
|
646
|
-
const
|
|
619
|
+
const execute = useExecute();
|
|
647
620
|
const queryClient = useQueryClient();
|
|
648
621
|
|
|
649
622
|
return useMutation({
|
|
650
|
-
mutationFn:
|
|
651
|
-
|
|
652
|
-
|
|
623
|
+
mutationFn: (variables: CartDiscountCodesUpdateMutationVariables) =>
|
|
624
|
+
execute<CartDiscountCodesUpdateMutation>(CartDiscountCodesUpdateDocument.toString(), variables),
|
|
625
|
+
onMutate: async () => {
|
|
626
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.cart.all() });
|
|
653
627
|
},
|
|
654
|
-
|
|
655
|
-
queryClient.invalidateQueries({ queryKey:
|
|
628
|
+
onSettled: () => {
|
|
629
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
|
|
656
630
|
},
|
|
657
631
|
...options,
|
|
658
632
|
});
|
|
@@ -664,25 +638,20 @@ export function useCartDiscountCodesUpdate(
|
|
|
664
638
|
|
|
665
639
|
/**
|
|
666
640
|
* Fetch checkout by ID
|
|
667
|
-
*
|
|
668
|
-
* @param checkoutId - Checkout ID
|
|
669
|
-
* @param options - React Query options
|
|
670
|
-
* @returns Checkout query result
|
|
671
641
|
*/
|
|
672
642
|
export function useCheckout(
|
|
673
643
|
checkoutId: string | null,
|
|
674
|
-
options?: Omit<UseQueryOptions<
|
|
644
|
+
options?: Omit<UseQueryOptions<CheckoutQuery | null>, 'queryKey' | 'queryFn'>
|
|
675
645
|
) {
|
|
676
|
-
const
|
|
677
|
-
const currency = useCurrencyStore((s
|
|
646
|
+
const execute = useExecute();
|
|
647
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
678
648
|
|
|
679
649
|
return useQuery({
|
|
680
|
-
queryKey:
|
|
681
|
-
queryFn:
|
|
650
|
+
queryKey: queryKeys.checkout.detail(checkoutId, currency),
|
|
651
|
+
queryFn: () => {
|
|
682
652
|
if (!checkoutId) return null;
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
return client.request(CheckoutDocument, { id: checkoutId });
|
|
653
|
+
const variables: CheckoutQueryVariables = { id: checkoutId };
|
|
654
|
+
return execute<CheckoutQuery>(CheckoutDocument.toString(), variables);
|
|
686
655
|
},
|
|
687
656
|
enabled: Boolean(checkoutId),
|
|
688
657
|
...options,
|
|
@@ -691,23 +660,21 @@ export function useCheckout(
|
|
|
691
660
|
|
|
692
661
|
/**
|
|
693
662
|
* Create checkout from cart
|
|
694
|
-
*
|
|
695
|
-
* @param options - React Query mutation options
|
|
696
|
-
* @returns Checkout create mutation
|
|
697
663
|
*/
|
|
698
664
|
export function useCheckoutCreate(
|
|
699
|
-
options?: UseMutationOptions<
|
|
665
|
+
options?: UseMutationOptions<CheckoutCreateMutation, Error, CheckoutCreateMutationVariables>
|
|
700
666
|
) {
|
|
701
|
-
const
|
|
667
|
+
const execute = useExecute();
|
|
702
668
|
const queryClient = useQueryClient();
|
|
703
669
|
|
|
704
670
|
return useMutation({
|
|
705
|
-
mutationFn:
|
|
706
|
-
|
|
707
|
-
|
|
671
|
+
mutationFn: (variables: CheckoutCreateMutationVariables) =>
|
|
672
|
+
execute<CheckoutCreateMutation>(CheckoutCreateDocument.toString(), variables),
|
|
673
|
+
onMutate: async () => {
|
|
674
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
708
675
|
},
|
|
709
|
-
|
|
710
|
-
queryClient.invalidateQueries({ queryKey:
|
|
676
|
+
onSettled: () => {
|
|
677
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
711
678
|
},
|
|
712
679
|
...options,
|
|
713
680
|
});
|
|
@@ -715,23 +682,21 @@ export function useCheckoutCreate(
|
|
|
715
682
|
|
|
716
683
|
/**
|
|
717
684
|
* Update checkout shipping address
|
|
718
|
-
*
|
|
719
|
-
* @param options - React Query mutation options
|
|
720
|
-
* @returns Checkout shipping address update mutation
|
|
721
685
|
*/
|
|
722
686
|
export function useCheckoutShippingAddressUpdate(
|
|
723
|
-
options?: UseMutationOptions<
|
|
687
|
+
options?: UseMutationOptions<CheckoutShippingAddressUpdateMutation, Error, CheckoutShippingAddressUpdateMutationVariables>
|
|
724
688
|
) {
|
|
725
|
-
const
|
|
689
|
+
const execute = useExecute();
|
|
726
690
|
const queryClient = useQueryClient();
|
|
727
691
|
|
|
728
692
|
return useMutation({
|
|
729
|
-
mutationFn:
|
|
730
|
-
|
|
731
|
-
|
|
693
|
+
mutationFn: (variables: CheckoutShippingAddressUpdateMutationVariables) =>
|
|
694
|
+
execute<CheckoutShippingAddressUpdateMutation>(CheckoutShippingAddressUpdateDocument.toString(), variables),
|
|
695
|
+
onMutate: async () => {
|
|
696
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
732
697
|
},
|
|
733
|
-
|
|
734
|
-
queryClient.invalidateQueries({ queryKey:
|
|
698
|
+
onSettled: () => {
|
|
699
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
735
700
|
},
|
|
736
701
|
...options,
|
|
737
702
|
});
|
|
@@ -739,23 +704,21 @@ export function useCheckoutShippingAddressUpdate(
|
|
|
739
704
|
|
|
740
705
|
/**
|
|
741
706
|
* Update checkout billing address
|
|
742
|
-
*
|
|
743
|
-
* @param options - React Query mutation options
|
|
744
|
-
* @returns Checkout billing address update mutation
|
|
745
707
|
*/
|
|
746
708
|
export function useCheckoutBillingAddressUpdate(
|
|
747
|
-
options?: UseMutationOptions<
|
|
709
|
+
options?: UseMutationOptions<CheckoutBillingAddressUpdateMutation, Error, CheckoutBillingAddressUpdateMutationVariables>
|
|
748
710
|
) {
|
|
749
|
-
const
|
|
711
|
+
const execute = useExecute();
|
|
750
712
|
const queryClient = useQueryClient();
|
|
751
713
|
|
|
752
714
|
return useMutation({
|
|
753
|
-
mutationFn:
|
|
754
|
-
|
|
755
|
-
|
|
715
|
+
mutationFn: (variables: CheckoutBillingAddressUpdateMutationVariables) =>
|
|
716
|
+
execute<CheckoutBillingAddressUpdateMutation>(CheckoutBillingAddressUpdateDocument.toString(), variables),
|
|
717
|
+
onMutate: async () => {
|
|
718
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
756
719
|
},
|
|
757
|
-
|
|
758
|
-
queryClient.invalidateQueries({ queryKey:
|
|
720
|
+
onSettled: () => {
|
|
721
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
759
722
|
},
|
|
760
723
|
...options,
|
|
761
724
|
});
|
|
@@ -763,23 +726,21 @@ export function useCheckoutBillingAddressUpdate(
|
|
|
763
726
|
|
|
764
727
|
/**
|
|
765
728
|
* Update checkout email
|
|
766
|
-
*
|
|
767
|
-
* @param options - React Query mutation options
|
|
768
|
-
* @returns Checkout email update mutation
|
|
769
729
|
*/
|
|
770
730
|
export function useCheckoutEmailUpdate(
|
|
771
|
-
options?: UseMutationOptions<
|
|
731
|
+
options?: UseMutationOptions<CheckoutEmailUpdateMutation, Error, CheckoutEmailUpdateMutationVariables>
|
|
772
732
|
) {
|
|
773
|
-
const
|
|
733
|
+
const execute = useExecute();
|
|
774
734
|
const queryClient = useQueryClient();
|
|
775
735
|
|
|
776
736
|
return useMutation({
|
|
777
|
-
mutationFn:
|
|
778
|
-
|
|
779
|
-
|
|
737
|
+
mutationFn: (variables: CheckoutEmailUpdateMutationVariables) =>
|
|
738
|
+
execute<CheckoutEmailUpdateMutation>(CheckoutEmailUpdateDocument.toString(), variables),
|
|
739
|
+
onMutate: async () => {
|
|
740
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
780
741
|
},
|
|
781
|
-
|
|
782
|
-
queryClient.invalidateQueries({ queryKey:
|
|
742
|
+
onSettled: () => {
|
|
743
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
783
744
|
},
|
|
784
745
|
...options,
|
|
785
746
|
});
|
|
@@ -787,23 +748,21 @@ export function useCheckoutEmailUpdate(
|
|
|
787
748
|
|
|
788
749
|
/**
|
|
789
750
|
* Update checkout shipping line (select shipping method)
|
|
790
|
-
*
|
|
791
|
-
* @param options - React Query mutation options
|
|
792
|
-
* @returns Checkout shipping line update mutation
|
|
793
751
|
*/
|
|
794
752
|
export function useCheckoutShippingLineUpdate(
|
|
795
|
-
options?: UseMutationOptions<
|
|
753
|
+
options?: UseMutationOptions<CheckoutShippingLineUpdateMutation, Error, CheckoutShippingLineUpdateMutationVariables>
|
|
796
754
|
) {
|
|
797
|
-
const
|
|
755
|
+
const execute = useExecute();
|
|
798
756
|
const queryClient = useQueryClient();
|
|
799
757
|
|
|
800
758
|
return useMutation({
|
|
801
|
-
mutationFn:
|
|
802
|
-
|
|
803
|
-
|
|
759
|
+
mutationFn: (variables: CheckoutShippingLineUpdateMutationVariables) =>
|
|
760
|
+
execute<CheckoutShippingLineUpdateMutation>(CheckoutShippingLineUpdateDocument.toString(), variables),
|
|
761
|
+
onMutate: async () => {
|
|
762
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
804
763
|
},
|
|
805
|
-
|
|
806
|
-
queryClient.invalidateQueries({ queryKey:
|
|
764
|
+
onSettled: () => {
|
|
765
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
807
766
|
},
|
|
808
767
|
...options,
|
|
809
768
|
});
|
|
@@ -811,23 +770,21 @@ export function useCheckoutShippingLineUpdate(
|
|
|
811
770
|
|
|
812
771
|
/**
|
|
813
772
|
* Apply discount code to checkout
|
|
814
|
-
*
|
|
815
|
-
* @param options - React Query mutation options
|
|
816
|
-
* @returns Checkout discount code apply mutation
|
|
817
773
|
*/
|
|
818
774
|
export function useCheckoutDiscountCodeApply(
|
|
819
|
-
options?: UseMutationOptions<
|
|
775
|
+
options?: UseMutationOptions<CheckoutDiscountCodeApplyMutation, Error, CheckoutDiscountCodeApplyMutationVariables>
|
|
820
776
|
) {
|
|
821
|
-
const
|
|
777
|
+
const execute = useExecute();
|
|
822
778
|
const queryClient = useQueryClient();
|
|
823
779
|
|
|
824
780
|
return useMutation({
|
|
825
|
-
mutationFn:
|
|
826
|
-
|
|
827
|
-
|
|
781
|
+
mutationFn: (variables: CheckoutDiscountCodeApplyMutationVariables) =>
|
|
782
|
+
execute<CheckoutDiscountCodeApplyMutation>(CheckoutDiscountCodeApplyDocument.toString(), variables),
|
|
783
|
+
onMutate: async () => {
|
|
784
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
828
785
|
},
|
|
829
|
-
|
|
830
|
-
queryClient.invalidateQueries({ queryKey:
|
|
786
|
+
onSettled: () => {
|
|
787
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
831
788
|
},
|
|
832
789
|
...options,
|
|
833
790
|
});
|
|
@@ -835,23 +792,21 @@ export function useCheckoutDiscountCodeApply(
|
|
|
835
792
|
|
|
836
793
|
/**
|
|
837
794
|
* Remove discount code from checkout
|
|
838
|
-
*
|
|
839
|
-
* @param options - React Query mutation options
|
|
840
|
-
* @returns Checkout discount code remove mutation
|
|
841
795
|
*/
|
|
842
796
|
export function useCheckoutDiscountCodeRemove(
|
|
843
|
-
options?: UseMutationOptions<
|
|
797
|
+
options?: UseMutationOptions<CheckoutDiscountCodeRemoveMutation, Error, CheckoutDiscountCodeRemoveMutationVariables>
|
|
844
798
|
) {
|
|
845
|
-
const
|
|
799
|
+
const execute = useExecute();
|
|
846
800
|
const queryClient = useQueryClient();
|
|
847
801
|
|
|
848
802
|
return useMutation({
|
|
849
|
-
mutationFn:
|
|
850
|
-
|
|
851
|
-
|
|
803
|
+
mutationFn: (variables: CheckoutDiscountCodeRemoveMutationVariables) =>
|
|
804
|
+
execute<CheckoutDiscountCodeRemoveMutation>(CheckoutDiscountCodeRemoveDocument.toString(), variables),
|
|
805
|
+
onMutate: async () => {
|
|
806
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
852
807
|
},
|
|
853
|
-
|
|
854
|
-
queryClient.invalidateQueries({ queryKey:
|
|
808
|
+
onSettled: () => {
|
|
809
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
855
810
|
},
|
|
856
811
|
...options,
|
|
857
812
|
});
|
|
@@ -859,24 +814,22 @@ export function useCheckoutDiscountCodeRemove(
|
|
|
859
814
|
|
|
860
815
|
/**
|
|
861
816
|
* Complete checkout (finalize order)
|
|
862
|
-
*
|
|
863
|
-
* @param options - React Query mutation options
|
|
864
|
-
* @returns Checkout complete mutation
|
|
865
817
|
*/
|
|
866
818
|
export function useCheckoutComplete(
|
|
867
|
-
options?: UseMutationOptions<
|
|
819
|
+
options?: UseMutationOptions<CheckoutCompleteMutation, Error, CheckoutCompleteMutationVariables>
|
|
868
820
|
) {
|
|
869
|
-
const
|
|
821
|
+
const execute = useExecute();
|
|
870
822
|
const queryClient = useQueryClient();
|
|
871
823
|
|
|
872
824
|
return useMutation({
|
|
873
|
-
mutationFn:
|
|
874
|
-
|
|
875
|
-
|
|
825
|
+
mutationFn: (variables: CheckoutCompleteMutationVariables) =>
|
|
826
|
+
execute<CheckoutCompleteMutation>(CheckoutCompleteDocument.toString(), variables),
|
|
827
|
+
onMutate: async () => {
|
|
828
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
876
829
|
},
|
|
877
|
-
|
|
878
|
-
queryClient.invalidateQueries({ queryKey:
|
|
879
|
-
queryClient.invalidateQueries({ queryKey:
|
|
830
|
+
onSettled: () => {
|
|
831
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
832
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.cart.all() });
|
|
880
833
|
},
|
|
881
834
|
...options,
|
|
882
835
|
});
|
|
@@ -884,23 +837,21 @@ export function useCheckoutComplete(
|
|
|
884
837
|
|
|
885
838
|
/**
|
|
886
839
|
* Apply gift card code to checkout
|
|
887
|
-
*
|
|
888
|
-
* @param options - React Query mutation options
|
|
889
|
-
* @returns Checkout gift card apply mutation
|
|
890
840
|
*/
|
|
891
841
|
export function useCheckoutGiftCardApply(
|
|
892
|
-
options?: UseMutationOptions<
|
|
842
|
+
options?: UseMutationOptions<CheckoutGiftCardApplyMutation, Error, CheckoutGiftCardApplyMutationVariables>
|
|
893
843
|
) {
|
|
894
|
-
const
|
|
844
|
+
const execute = useExecute();
|
|
895
845
|
const queryClient = useQueryClient();
|
|
896
846
|
|
|
897
847
|
return useMutation({
|
|
898
|
-
mutationFn:
|
|
899
|
-
|
|
900
|
-
|
|
848
|
+
mutationFn: (variables: CheckoutGiftCardApplyMutationVariables) =>
|
|
849
|
+
execute<CheckoutGiftCardApplyMutation>(CheckoutGiftCardApplyDocument.toString(), variables),
|
|
850
|
+
onMutate: async () => {
|
|
851
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
901
852
|
},
|
|
902
|
-
|
|
903
|
-
queryClient.invalidateQueries({ queryKey:
|
|
853
|
+
onSettled: () => {
|
|
854
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
904
855
|
},
|
|
905
856
|
...options,
|
|
906
857
|
});
|
|
@@ -908,23 +859,21 @@ export function useCheckoutGiftCardApply(
|
|
|
908
859
|
|
|
909
860
|
/**
|
|
910
861
|
* Remove gift card from checkout
|
|
911
|
-
*
|
|
912
|
-
* @param options - React Query mutation options
|
|
913
|
-
* @returns Checkout gift card remove mutation
|
|
914
862
|
*/
|
|
915
863
|
export function useCheckoutGiftCardRemove(
|
|
916
|
-
options?: UseMutationOptions<
|
|
864
|
+
options?: UseMutationOptions<CheckoutGiftCardRemoveMutation, Error, CheckoutGiftCardRemoveMutationVariables>
|
|
917
865
|
) {
|
|
918
|
-
const
|
|
866
|
+
const execute = useExecute();
|
|
919
867
|
const queryClient = useQueryClient();
|
|
920
868
|
|
|
921
869
|
return useMutation({
|
|
922
|
-
mutationFn:
|
|
923
|
-
|
|
924
|
-
|
|
870
|
+
mutationFn: (variables: CheckoutGiftCardRemoveMutationVariables) =>
|
|
871
|
+
execute<CheckoutGiftCardRemoveMutation>(CheckoutGiftCardRemoveDocument.toString(), variables),
|
|
872
|
+
onMutate: async () => {
|
|
873
|
+
await queryClient.cancelQueries({ queryKey: queryKeys.checkout.all() });
|
|
925
874
|
},
|
|
926
|
-
|
|
927
|
-
queryClient.invalidateQueries({ queryKey:
|
|
875
|
+
onSettled: () => {
|
|
876
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.checkout.all() });
|
|
928
877
|
},
|
|
929
878
|
...options,
|
|
930
879
|
});
|
|
@@ -934,78 +883,217 @@ export function useCheckoutGiftCardRemove(
|
|
|
934
883
|
// CUSTOMER HOOKS
|
|
935
884
|
// ============================================================================
|
|
936
885
|
|
|
886
|
+
/**
|
|
887
|
+
* Fetch current customer data (profile, addresses, orders).
|
|
888
|
+
* Automatically reads accessToken from auth store.
|
|
889
|
+
* Query is disabled until accessToken is available (after Zustand persist rehydration).
|
|
890
|
+
*/
|
|
891
|
+
export function useCustomer(
|
|
892
|
+
options?: Omit<UseQueryOptions<CustomerQuery>, 'queryKey' | 'queryFn' | 'enabled'>
|
|
893
|
+
) {
|
|
894
|
+
const execute = useExecute();
|
|
895
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
896
|
+
|
|
897
|
+
return useQuery({
|
|
898
|
+
queryKey: queryKeys.customer.detail(accessToken || ''),
|
|
899
|
+
queryFn: () =>
|
|
900
|
+
execute<CustomerQuery>(CustomerDocument.toString(), {
|
|
901
|
+
customerAccessToken: accessToken!,
|
|
902
|
+
} as CustomerQueryVariables),
|
|
903
|
+
enabled: !!accessToken,
|
|
904
|
+
...options,
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Lightweight customer profile query (no orders, no addresses list).
|
|
910
|
+
* Use for settings/profile pages that only need basic customer info.
|
|
911
|
+
*/
|
|
912
|
+
export function useCustomerProfile(
|
|
913
|
+
options?: Omit<UseQueryOptions<CustomerProfileQuery>, 'queryKey' | 'queryFn' | 'enabled'>
|
|
914
|
+
) {
|
|
915
|
+
const execute = useExecute();
|
|
916
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
917
|
+
|
|
918
|
+
return useQuery({
|
|
919
|
+
queryKey: queryKeys.customer.detail(accessToken || ''),
|
|
920
|
+
queryFn: () =>
|
|
921
|
+
execute<CustomerProfileQuery>(CustomerProfileDocument.toString(), {
|
|
922
|
+
customerAccessToken: accessToken!,
|
|
923
|
+
} as CustomerProfileQueryVariables),
|
|
924
|
+
enabled: !!accessToken,
|
|
925
|
+
...options,
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* Fetch single order by ID for authenticated customer.
|
|
931
|
+
* More efficient than useCustomer() — fetches only the requested order.
|
|
932
|
+
*/
|
|
933
|
+
export function useCustomerOrder(
|
|
934
|
+
orderId: string,
|
|
935
|
+
options?: Omit<UseQueryOptions<CustomerOrderQuery>, 'queryKey' | 'queryFn' | 'enabled'>
|
|
936
|
+
) {
|
|
937
|
+
const execute = useExecute();
|
|
938
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
939
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
940
|
+
|
|
941
|
+
return useQuery({
|
|
942
|
+
queryKey: queryKeys.customer.order(orderId, currency),
|
|
943
|
+
queryFn: () =>
|
|
944
|
+
execute<CustomerOrderQuery>(CustomerOrderDocument.toString(), {
|
|
945
|
+
orderId,
|
|
946
|
+
customerAccessToken: accessToken!,
|
|
947
|
+
} as CustomerOrderQueryVariables),
|
|
948
|
+
enabled: !!accessToken && !!orderId,
|
|
949
|
+
...options,
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Update customer profile (firstName, lastName, phone).
|
|
955
|
+
* Automatically invalidates all customer queries on settle.
|
|
956
|
+
*/
|
|
957
|
+
export function useCustomerUpdate(
|
|
958
|
+
options?: UseMutationOptions<CustomerUpdateMutation, Error, CustomerUpdateInput>
|
|
959
|
+
) {
|
|
960
|
+
const execute = useExecute();
|
|
961
|
+
const { accessToken } = useAuthStore();
|
|
962
|
+
const queryClient = useQueryClient();
|
|
963
|
+
|
|
964
|
+
return useMutation({
|
|
965
|
+
mutationFn: (customer: CustomerUpdateInput) =>
|
|
966
|
+
execute<CustomerUpdateMutation>(CustomerUpdateDocument.toString(), {
|
|
967
|
+
customer,
|
|
968
|
+
customerAccessToken: accessToken!,
|
|
969
|
+
} as CustomerUpdateMutationVariables),
|
|
970
|
+
onSettled: () => {
|
|
971
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.customer.all() });
|
|
972
|
+
},
|
|
973
|
+
...options,
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* Create a new customer address.
|
|
979
|
+
*/
|
|
980
|
+
export function useCustomerAddressCreate(
|
|
981
|
+
options?: UseMutationOptions<CustomerAddressCreateMutation, Error, { address: Record<string, unknown> }>
|
|
982
|
+
) {
|
|
983
|
+
const execute = useExecute();
|
|
984
|
+
const { accessToken } = useAuthStore();
|
|
985
|
+
const queryClient = useQueryClient();
|
|
986
|
+
|
|
987
|
+
return useMutation({
|
|
988
|
+
mutationFn: ({ address }: { address: Record<string, unknown> }) =>
|
|
989
|
+
execute<CustomerAddressCreateMutation>(
|
|
990
|
+
CustomerAddressCreateDocument.toString(),
|
|
991
|
+
{ address, customerAccessToken: accessToken! } as CustomerAddressCreateMutationVariables,
|
|
992
|
+
),
|
|
993
|
+
onSettled: () => {
|
|
994
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.customer.all() });
|
|
995
|
+
},
|
|
996
|
+
...options,
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* Update an existing customer address.
|
|
1002
|
+
*/
|
|
1003
|
+
export function useCustomerAddressUpdate(
|
|
1004
|
+
options?: UseMutationOptions<CustomerAddressUpdateMutation, Error, { id: string; address: Record<string, unknown> }>
|
|
1005
|
+
) {
|
|
1006
|
+
const execute = useExecute();
|
|
1007
|
+
const { accessToken } = useAuthStore();
|
|
1008
|
+
const queryClient = useQueryClient();
|
|
1009
|
+
|
|
1010
|
+
return useMutation({
|
|
1011
|
+
mutationFn: ({ id, address }: { id: string; address: Record<string, unknown> }) =>
|
|
1012
|
+
execute<CustomerAddressUpdateMutation>(
|
|
1013
|
+
CustomerAddressUpdateDocument.toString(),
|
|
1014
|
+
{ id, address, customerAccessToken: accessToken! } as CustomerAddressUpdateMutationVariables,
|
|
1015
|
+
),
|
|
1016
|
+
onSettled: () => {
|
|
1017
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.customer.all() });
|
|
1018
|
+
},
|
|
1019
|
+
...options,
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* Delete a customer address.
|
|
1025
|
+
*/
|
|
1026
|
+
export function useCustomerAddressDelete(
|
|
1027
|
+
options?: UseMutationOptions<CustomerAddressDeleteMutation, Error, string>
|
|
1028
|
+
) {
|
|
1029
|
+
const execute = useExecute();
|
|
1030
|
+
const { accessToken } = useAuthStore();
|
|
1031
|
+
const queryClient = useQueryClient();
|
|
1032
|
+
|
|
1033
|
+
return useMutation({
|
|
1034
|
+
mutationFn: (id: string) =>
|
|
1035
|
+
execute<CustomerAddressDeleteMutation>(
|
|
1036
|
+
CustomerAddressDeleteDocument.toString(),
|
|
1037
|
+
{ id, customerAccessToken: accessToken! } as CustomerAddressDeleteMutationVariables,
|
|
1038
|
+
),
|
|
1039
|
+
onSettled: () => {
|
|
1040
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.customer.all() });
|
|
1041
|
+
},
|
|
1042
|
+
...options,
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Set default customer address.
|
|
1048
|
+
*/
|
|
1049
|
+
export function useCustomerDefaultAddressUpdate(
|
|
1050
|
+
options?: UseMutationOptions<CustomerDefaultAddressUpdateMutation, Error, string>
|
|
1051
|
+
) {
|
|
1052
|
+
const execute = useExecute();
|
|
1053
|
+
const { accessToken } = useAuthStore();
|
|
1054
|
+
const queryClient = useQueryClient();
|
|
1055
|
+
|
|
1056
|
+
return useMutation({
|
|
1057
|
+
mutationFn: (addressId: string) =>
|
|
1058
|
+
execute<CustomerDefaultAddressUpdateMutation>(
|
|
1059
|
+
CustomerDefaultAddressUpdateDocument.toString(),
|
|
1060
|
+
{ addressId, customerAccessToken: accessToken! } as CustomerDefaultAddressUpdateMutationVariables,
|
|
1061
|
+
),
|
|
1062
|
+
onSettled: () => {
|
|
1063
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.customer.all() });
|
|
1064
|
+
},
|
|
1065
|
+
...options,
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
|
|
937
1069
|
/**
|
|
938
1070
|
* Customer login mutation
|
|
939
|
-
*
|
|
940
|
-
* @param options - React Query mutation options
|
|
941
|
-
* @returns Customer login mutation
|
|
942
|
-
*
|
|
943
|
-
* @example
|
|
944
|
-
* ```typescript
|
|
945
|
-
* const login = useCustomerLogin();
|
|
946
|
-
*
|
|
947
|
-
* const handleLogin = async (email: string, password: string) => {
|
|
948
|
-
* const { customerAccessTokenCreate } = await login.mutateAsync({
|
|
949
|
-
* input: { email, password }
|
|
950
|
-
* });
|
|
951
|
-
*
|
|
952
|
-
* if (customerAccessTokenCreate.customerAccessToken) {
|
|
953
|
-
* // Store token in httpOnly cookie via API route
|
|
954
|
-
* await fetch('/api/auth/set-token', {
|
|
955
|
-
* method: 'POST',
|
|
956
|
-
* body: JSON.stringify({
|
|
957
|
-
* token: customerAccessTokenCreate.customerAccessToken.accessToken
|
|
958
|
-
* })
|
|
959
|
-
* });
|
|
960
|
-
* }
|
|
961
|
-
* };
|
|
962
|
-
* ```
|
|
963
1071
|
*/
|
|
964
1072
|
export function useCustomerLogin(
|
|
965
|
-
options?: UseMutationOptions<
|
|
1073
|
+
options?: UseMutationOptions<CustomerLoginMutation, Error, CustomerLoginMutationVariables>
|
|
966
1074
|
) {
|
|
967
|
-
const
|
|
968
|
-
|
|
1075
|
+
const execute = useExecute();
|
|
1076
|
+
|
|
969
1077
|
return useMutation({
|
|
970
|
-
mutationFn:
|
|
971
|
-
|
|
972
|
-
return client.request(CustomerLoginDocument, variables);
|
|
973
|
-
},
|
|
1078
|
+
mutationFn: (variables: CustomerLoginMutationVariables) =>
|
|
1079
|
+
execute<CustomerLoginMutation>(CustomerLoginDocument.toString(), variables),
|
|
974
1080
|
...options,
|
|
975
1081
|
});
|
|
976
1082
|
}
|
|
977
1083
|
|
|
978
1084
|
/**
|
|
979
1085
|
* Customer logout mutation
|
|
980
|
-
*
|
|
981
|
-
* @param options - React Query mutation options
|
|
982
|
-
* @returns Customer logout mutation
|
|
983
|
-
*
|
|
984
|
-
* @example
|
|
985
|
-
* ```typescript
|
|
986
|
-
* const logout = useCustomerLogout();
|
|
987
|
-
*
|
|
988
|
-
* const handleLogout = async () => {
|
|
989
|
-
* await logout.mutateAsync({ customerAccessToken: token });
|
|
990
|
-
*
|
|
991
|
-
* // Clear cookie via API route
|
|
992
|
-
* await fetch('/api/auth/clear-token', { method: 'POST' });
|
|
993
|
-
* };
|
|
994
|
-
* ```
|
|
995
1086
|
*/
|
|
996
1087
|
export function useCustomerLogout(
|
|
997
|
-
options?: UseMutationOptions<
|
|
1088
|
+
options?: UseMutationOptions<CustomerLogoutMutation, Error, CustomerLogoutMutationVariables>
|
|
998
1089
|
) {
|
|
999
|
-
const
|
|
1090
|
+
const execute = useExecute();
|
|
1000
1091
|
const queryClient = useQueryClient();
|
|
1001
|
-
|
|
1092
|
+
|
|
1002
1093
|
return useMutation({
|
|
1003
|
-
mutationFn:
|
|
1004
|
-
|
|
1005
|
-
return client.request(CustomerLogoutDocument, variables);
|
|
1006
|
-
},
|
|
1094
|
+
mutationFn: (variables: CustomerLogoutMutationVariables) =>
|
|
1095
|
+
execute<CustomerLogoutMutation>(CustomerLogoutDocument.toString(), variables),
|
|
1007
1096
|
onSuccess: () => {
|
|
1008
|
-
// Clear all queries on logout
|
|
1009
1097
|
queryClient.clear();
|
|
1010
1098
|
},
|
|
1011
1099
|
...options,
|
|
@@ -1018,139 +1106,114 @@ export function useCustomerLogout(
|
|
|
1018
1106
|
|
|
1019
1107
|
/**
|
|
1020
1108
|
* Fetch loyalty member data
|
|
1021
|
-
*
|
|
1022
|
-
* @param options - React Query options
|
|
1023
|
-
* @returns Loyalty member query result
|
|
1024
1109
|
*/
|
|
1025
1110
|
export function useLoyaltyMember(
|
|
1026
|
-
options?: Omit<UseQueryOptions<
|
|
1111
|
+
options?: Omit<UseQueryOptions<LoyaltyMemberQuery>, 'queryKey' | 'queryFn' | 'enabled'>
|
|
1027
1112
|
) {
|
|
1028
|
-
const
|
|
1029
|
-
const
|
|
1113
|
+
const execute = useExecute();
|
|
1114
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
1115
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
1030
1116
|
|
|
1031
1117
|
return useQuery({
|
|
1032
|
-
queryKey:
|
|
1033
|
-
queryFn:
|
|
1034
|
-
|
|
1035
|
-
return client.request(LoyaltyMemberDocument);
|
|
1036
|
-
},
|
|
1118
|
+
queryKey: queryKeys.loyalty.member(currency),
|
|
1119
|
+
queryFn: () => execute<LoyaltyMemberQuery>(LoyaltyMemberDocument.toString()),
|
|
1120
|
+
enabled: !!accessToken,
|
|
1037
1121
|
...options,
|
|
1038
1122
|
});
|
|
1039
1123
|
}
|
|
1040
1124
|
|
|
1041
1125
|
/**
|
|
1042
1126
|
* Fetch loyalty rewards
|
|
1043
|
-
*
|
|
1044
|
-
* @param options - React Query options
|
|
1045
|
-
* @returns Loyalty rewards query result
|
|
1046
1127
|
*/
|
|
1047
1128
|
export function useLoyaltyRewards(
|
|
1048
|
-
options?: Omit<UseQueryOptions<
|
|
1129
|
+
options?: Omit<UseQueryOptions<LoyaltyRewardsQuery>, 'queryKey' | 'queryFn' | 'enabled'>
|
|
1049
1130
|
) {
|
|
1050
|
-
const
|
|
1051
|
-
const
|
|
1131
|
+
const execute = useExecute();
|
|
1132
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
1133
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
1052
1134
|
|
|
1053
1135
|
return useQuery({
|
|
1054
|
-
queryKey:
|
|
1055
|
-
queryFn:
|
|
1056
|
-
|
|
1057
|
-
return client.request(LoyaltyRewardsDocument);
|
|
1058
|
-
},
|
|
1136
|
+
queryKey: queryKeys.loyalty.rewards(currency),
|
|
1137
|
+
queryFn: () => execute<LoyaltyRewardsQuery>(LoyaltyRewardsDocument.toString()),
|
|
1138
|
+
enabled: !!accessToken,
|
|
1059
1139
|
...options,
|
|
1060
1140
|
});
|
|
1061
1141
|
}
|
|
1062
1142
|
|
|
1063
1143
|
/**
|
|
1064
1144
|
* Fetch loyalty transactions with pagination
|
|
1065
|
-
*
|
|
1066
|
-
* @param variables - Query variables (first, after)
|
|
1067
|
-
* @param options - React Query options
|
|
1068
|
-
* @returns Loyalty transactions query result
|
|
1069
1145
|
*/
|
|
1070
1146
|
export function useLoyaltyTransactions(
|
|
1071
1147
|
variables?: { first?: number; after?: string },
|
|
1072
|
-
options?: Omit<UseQueryOptions<
|
|
1148
|
+
options?: Omit<UseQueryOptions<LoyaltyTransactionsQuery>, 'queryKey' | 'queryFn' | 'enabled'>
|
|
1073
1149
|
) {
|
|
1074
|
-
const
|
|
1075
|
-
const
|
|
1150
|
+
const execute = useExecute();
|
|
1151
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
1152
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
1076
1153
|
|
|
1077
1154
|
return useQuery({
|
|
1078
|
-
queryKey:
|
|
1079
|
-
queryFn:
|
|
1080
|
-
const
|
|
1081
|
-
return client.request(LoyaltyTransactionsDocument, {
|
|
1155
|
+
queryKey: queryKeys.loyalty.transactions(variables as Record<string, unknown>, currency),
|
|
1156
|
+
queryFn: () => {
|
|
1157
|
+
const graphqlVariables: LoyaltyTransactionsQueryVariables = {
|
|
1082
1158
|
first: variables?.first ?? 20,
|
|
1083
1159
|
after: variables?.after,
|
|
1084
|
-
}
|
|
1160
|
+
};
|
|
1161
|
+
return execute<LoyaltyTransactionsQuery>(LoyaltyTransactionsDocument.toString(), graphqlVariables);
|
|
1085
1162
|
},
|
|
1163
|
+
enabled: !!accessToken,
|
|
1086
1164
|
...options,
|
|
1087
1165
|
});
|
|
1088
1166
|
}
|
|
1089
1167
|
|
|
1090
1168
|
/**
|
|
1091
1169
|
* Fetch loyalty settings
|
|
1092
|
-
*
|
|
1093
|
-
* @param options - React Query options
|
|
1094
|
-
* @returns Loyalty settings query result
|
|
1095
1170
|
*/
|
|
1096
1171
|
export function useLoyaltySettings(
|
|
1097
|
-
options?: Omit<UseQueryOptions<
|
|
1172
|
+
options?: Omit<UseQueryOptions<LoyaltySettingsQuery>, 'queryKey' | 'queryFn'>
|
|
1098
1173
|
) {
|
|
1099
|
-
const
|
|
1174
|
+
const execute = useExecute();
|
|
1100
1175
|
|
|
1101
1176
|
return useQuery({
|
|
1102
|
-
queryKey:
|
|
1103
|
-
queryFn:
|
|
1104
|
-
const { LoyaltySettingsDocument } = await import('@/generated/graphql');
|
|
1105
|
-
return client.request(LoyaltySettingsDocument);
|
|
1106
|
-
},
|
|
1177
|
+
queryKey: queryKeys.loyalty.settings(),
|
|
1178
|
+
queryFn: () => execute<LoyaltySettingsQuery>(LoyaltySettingsDocument.toString()),
|
|
1107
1179
|
...options,
|
|
1108
1180
|
});
|
|
1109
1181
|
}
|
|
1110
1182
|
|
|
1111
1183
|
/**
|
|
1112
1184
|
* Fetch referral stats
|
|
1113
|
-
*
|
|
1114
|
-
* @param options - React Query options
|
|
1115
|
-
* @returns Referral stats query result
|
|
1116
1185
|
*/
|
|
1117
1186
|
export function useReferralStats(
|
|
1118
|
-
options?: Omit<UseQueryOptions<
|
|
1187
|
+
options?: Omit<UseQueryOptions<ReferralStatsQuery>, 'queryKey' | 'queryFn' | 'enabled'>
|
|
1119
1188
|
) {
|
|
1120
|
-
const
|
|
1189
|
+
const execute = useExecute();
|
|
1190
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
1121
1191
|
|
|
1122
1192
|
return useQuery({
|
|
1123
|
-
queryKey:
|
|
1124
|
-
queryFn:
|
|
1125
|
-
|
|
1126
|
-
return client.request(ReferralStatsDocument);
|
|
1127
|
-
},
|
|
1193
|
+
queryKey: queryKeys.loyalty.referralStats(),
|
|
1194
|
+
queryFn: () => execute<ReferralStatsQuery>(ReferralStatsDocument.toString()),
|
|
1195
|
+
enabled: !!accessToken,
|
|
1128
1196
|
...options,
|
|
1129
1197
|
});
|
|
1130
1198
|
}
|
|
1131
1199
|
|
|
1132
1200
|
/**
|
|
1133
1201
|
* Redeem loyalty reward mutation
|
|
1134
|
-
*
|
|
1135
|
-
* @param options - React Query mutation options
|
|
1136
|
-
* @returns Redeem reward mutation
|
|
1137
1202
|
*/
|
|
1138
1203
|
export function useRedeemLoyaltyReward(
|
|
1139
|
-
options?: UseMutationOptions<
|
|
1204
|
+
options?: UseMutationOptions<RedeemLoyaltyRewardMutation, Error, RedeemLoyaltyRewardMutationVariables>
|
|
1140
1205
|
) {
|
|
1141
|
-
const
|
|
1206
|
+
const execute = useExecute();
|
|
1142
1207
|
const queryClient = useQueryClient();
|
|
1208
|
+
const currency = useCurrencyStore((s) => s.currency);
|
|
1143
1209
|
|
|
1144
1210
|
return useMutation({
|
|
1145
|
-
mutationFn:
|
|
1146
|
-
|
|
1147
|
-
return client.request(RedeemLoyaltyRewardDocument, variables);
|
|
1148
|
-
},
|
|
1211
|
+
mutationFn: (variables: RedeemLoyaltyRewardMutationVariables) =>
|
|
1212
|
+
execute<RedeemLoyaltyRewardMutation>(RedeemLoyaltyRewardDocument.toString(), variables),
|
|
1149
1213
|
onSuccess: () => {
|
|
1150
|
-
|
|
1151
|
-
queryClient.invalidateQueries({ queryKey:
|
|
1152
|
-
queryClient.invalidateQueries({ queryKey:
|
|
1153
|
-
queryClient.invalidateQueries({ queryKey: ['LoyaltyTransactions'] });
|
|
1214
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.loyalty.member(currency) });
|
|
1215
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.loyalty.rewards(currency) });
|
|
1216
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.loyalty.transactions() });
|
|
1154
1217
|
},
|
|
1155
1218
|
...options,
|
|
1156
1219
|
});
|
|
@@ -1162,21 +1225,13 @@ export function useRedeemLoyaltyReward(
|
|
|
1162
1225
|
|
|
1163
1226
|
/**
|
|
1164
1227
|
* Hook to invalidate all queries when currency changes
|
|
1165
|
-
*
|
|
1228
|
+
*
|
|
1166
1229
|
* This is automatically handled by including currency in query keys,
|
|
1167
1230
|
* but this utility can be used for manual invalidation if needed.
|
|
1168
|
-
*
|
|
1169
|
-
* @example
|
|
1170
|
-
* ```typescript
|
|
1171
|
-
* const invalidateOnCurrencyChange = useInvalidateOnCurrencyChange();
|
|
1172
|
-
*
|
|
1173
|
-
* // Manually trigger invalidation
|
|
1174
|
-
* invalidateOnCurrencyChange();
|
|
1175
|
-
* ```
|
|
1176
1231
|
*/
|
|
1177
1232
|
export function useInvalidateOnCurrencyChange() {
|
|
1178
1233
|
const queryClient = useQueryClient();
|
|
1179
|
-
|
|
1234
|
+
|
|
1180
1235
|
return () => {
|
|
1181
1236
|
queryClient.invalidateQueries();
|
|
1182
1237
|
};
|