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