@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,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect } from "react";
|
|
4
|
-
import
|
|
5
|
-
import { usePathname } from "
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { Link, usePathname } from "@/i18n/navigation";
|
|
6
6
|
import { Menu, X, ChevronDown, ChevronRight } from "lucide-react";
|
|
7
7
|
import { cn } from "@/lib/utils";
|
|
8
8
|
|
|
@@ -17,26 +17,29 @@ export interface MobileMenuProps {
|
|
|
17
17
|
className?: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
20
|
+
export function MobileMenu({ items, className }: MobileMenuProps) {
|
|
21
|
+
const t = useTranslations("nav");
|
|
22
|
+
|
|
23
|
+
const defaultItems: MobileMenuItem[] = [
|
|
24
|
+
{
|
|
25
|
+
label: t("products"),
|
|
26
|
+
href: "/products",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: t("collections"),
|
|
30
|
+
href: "/collections",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
label: t("categories"),
|
|
34
|
+
href: "/categories",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: t("about"),
|
|
38
|
+
href: "/about",
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const resolvedItems = items ?? defaultItems;
|
|
40
43
|
const [isOpen, setIsOpen] = useState(false);
|
|
41
44
|
const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
|
|
42
45
|
const pathname = usePathname();
|
|
@@ -108,7 +111,7 @@ export function MobileMenu({ items = defaultItems, className }: MobileMenuProps)
|
|
|
108
111
|
toggleExpanded(item.href);
|
|
109
112
|
}}
|
|
110
113
|
className="p-3 text-muted-foreground hover:text-foreground"
|
|
111
|
-
aria-label={
|
|
114
|
+
aria-label={t("toggleSubmenu", { label: item.label })}
|
|
112
115
|
aria-expanded={isExpanded}
|
|
113
116
|
>
|
|
114
117
|
{isExpanded ? (
|
|
@@ -140,7 +143,7 @@ export function MobileMenu({ items = defaultItems, className }: MobileMenuProps)
|
|
|
140
143
|
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
141
144
|
className
|
|
142
145
|
)}
|
|
143
|
-
aria-label="
|
|
146
|
+
aria-label={t("toggleMobileMenu")}
|
|
144
147
|
aria-expanded={isOpen}
|
|
145
148
|
aria-controls="mobile-menu"
|
|
146
149
|
>
|
|
@@ -163,16 +166,16 @@ export function MobileMenu({ items = defaultItems, className }: MobileMenuProps)
|
|
|
163
166
|
className="fixed inset-y-0 left-0 z-50 w-full max-w-sm bg-background shadow-xl"
|
|
164
167
|
role="dialog"
|
|
165
168
|
aria-modal="true"
|
|
166
|
-
aria-label="
|
|
169
|
+
aria-label={t("mobileNavigation")}
|
|
167
170
|
>
|
|
168
171
|
<div className="flex h-full flex-col">
|
|
169
172
|
{/* Header */}
|
|
170
173
|
<div className="flex items-center justify-between border-b border-border p-4">
|
|
171
|
-
<h2 className="text-lg font-semibold">
|
|
174
|
+
<h2 className="text-lg font-semibold">{t("menu")}</h2>
|
|
172
175
|
<button
|
|
173
176
|
onClick={() => setIsOpen(false)}
|
|
174
177
|
className="rounded-md p-2 text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
|
175
|
-
aria-label="
|
|
178
|
+
aria-label={t("closeMobileMenu")}
|
|
176
179
|
>
|
|
177
180
|
<X className="h-5 w-5" />
|
|
178
181
|
</button>
|
|
@@ -181,7 +184,7 @@ export function MobileMenu({ items = defaultItems, className }: MobileMenuProps)
|
|
|
181
184
|
{/* Menu Items */}
|
|
182
185
|
<nav className="flex-1 overflow-y-auto p-4">
|
|
183
186
|
<div className="space-y-1">
|
|
184
|
-
{
|
|
187
|
+
{resolvedItems.map((item) => renderMenuItem(item))}
|
|
185
188
|
</div>
|
|
186
189
|
</nav>
|
|
187
190
|
|
|
@@ -192,13 +195,13 @@ export function MobileMenu({ items = defaultItems, className }: MobileMenuProps)
|
|
|
192
195
|
href="/account"
|
|
193
196
|
className="rounded-md bg-primary px-4 py-2 text-center text-sm font-medium text-primary-foreground hover:bg-primary/90"
|
|
194
197
|
>
|
|
195
|
-
|
|
198
|
+
{t("account")}
|
|
196
199
|
</Link>
|
|
197
200
|
<Link
|
|
198
201
|
href="/cart"
|
|
199
202
|
className="rounded-md border border-border px-4 py-2 text-center text-sm font-medium hover:bg-accent"
|
|
200
203
|
>
|
|
201
|
-
|
|
204
|
+
{t("viewCart")}
|
|
202
205
|
</Link>
|
|
203
206
|
</div>
|
|
204
207
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { usePathname } from "
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
import { Link, usePathname } from "@/i18n/navigation";
|
|
5
5
|
import { cn } from "@/lib/utils";
|
|
6
6
|
|
|
7
7
|
export interface NavigationItem {
|
|
@@ -15,28 +15,31 @@ export interface NavigationProps {
|
|
|
15
15
|
className?: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
label: "Products",
|
|
21
|
-
href: "/products",
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
label: "Collections",
|
|
25
|
-
href: "/collections",
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
label: "Categories",
|
|
29
|
-
href: "/categories",
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
label: "About",
|
|
33
|
-
href: "/about",
|
|
34
|
-
},
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
export function Navigation({ items = defaultItems, className }: NavigationProps) {
|
|
18
|
+
export function Navigation({ items, className }: NavigationProps) {
|
|
19
|
+
const t = useTranslations("nav");
|
|
38
20
|
const pathname = usePathname();
|
|
39
21
|
|
|
22
|
+
const defaultItems: NavigationItem[] = [
|
|
23
|
+
{
|
|
24
|
+
label: t("products"),
|
|
25
|
+
href: "/products",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: t("collections"),
|
|
29
|
+
href: "/collections",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: t("categories"),
|
|
33
|
+
href: "/categories",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: t("about"),
|
|
37
|
+
href: "/about",
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const resolvedItems = items ?? defaultItems;
|
|
42
|
+
|
|
40
43
|
const isActive = (href: string) => {
|
|
41
44
|
if (href === "/") {
|
|
42
45
|
return pathname === "/";
|
|
@@ -48,9 +51,9 @@ export function Navigation({ items = defaultItems, className }: NavigationProps)
|
|
|
48
51
|
<nav
|
|
49
52
|
className={cn("flex items-center gap-6", className)}
|
|
50
53
|
role="navigation"
|
|
51
|
-
aria-label="
|
|
54
|
+
aria-label={t("mainNavigation")}
|
|
52
55
|
>
|
|
53
|
-
{
|
|
56
|
+
{resolvedItems.map((item) => (
|
|
54
57
|
<div key={item.href} className="relative group">
|
|
55
58
|
<Link
|
|
56
59
|
href={item.href}
|
|
@@ -10,19 +10,10 @@ import { Coins, AlertTriangle } from 'lucide-react';
|
|
|
10
10
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
11
11
|
import { Badge } from '@/components/ui/badge';
|
|
12
12
|
import { cn } from '@/lib/utils';
|
|
13
|
-
|
|
14
|
-
interface PointsSummary {
|
|
15
|
-
totalPoints: number;
|
|
16
|
-
currentPoints: number;
|
|
17
|
-
pendingPoints: number;
|
|
18
|
-
redeemedPoints: number;
|
|
19
|
-
expiredPoints: number;
|
|
20
|
-
expiringPoints?: number;
|
|
21
|
-
nextExpiryDate?: string;
|
|
22
|
-
}
|
|
13
|
+
import type { LoyaltyPointsSummary } from '@/lib/graphql/fragments';
|
|
23
14
|
|
|
24
15
|
interface PointsBalanceProps {
|
|
25
|
-
points:
|
|
16
|
+
points: LoyaltyPointsSummary;
|
|
26
17
|
variant?: 'default' | 'compact';
|
|
27
18
|
className?: string;
|
|
28
19
|
}
|
|
@@ -10,35 +10,14 @@ import { ArrowUpCircle, ArrowDownCircle, Clock, Gift, ShoppingCart, UserPlus, St
|
|
|
10
10
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
11
11
|
import { Badge } from '@/components/ui/badge';
|
|
12
12
|
import { cn } from '@/lib/utils';
|
|
13
|
-
|
|
14
|
-
type TransactionType =
|
|
15
|
-
| 'EARN_PURCHASE'
|
|
16
|
-
| 'EARN_SIGNUP'
|
|
17
|
-
| 'EARN_REFERRAL'
|
|
18
|
-
| 'EARN_REVIEW'
|
|
19
|
-
| 'EARN_BIRTHDAY'
|
|
20
|
-
| 'EARN_BONUS'
|
|
21
|
-
| 'REDEEM'
|
|
22
|
-
| 'EXPIRE'
|
|
23
|
-
| 'ADJUST';
|
|
24
|
-
|
|
25
|
-
interface Transaction {
|
|
26
|
-
id: string;
|
|
27
|
-
type: TransactionType;
|
|
28
|
-
points: number;
|
|
29
|
-
balanceAfter: number;
|
|
30
|
-
orderId?: string;
|
|
31
|
-
description?: string;
|
|
32
|
-
expiresAt?: string;
|
|
33
|
-
createdAt: string;
|
|
34
|
-
}
|
|
13
|
+
import type { LoyaltyTransaction } from '@/lib/graphql/fragments';
|
|
35
14
|
|
|
36
15
|
interface PointsHistoryProps {
|
|
37
|
-
transactions:
|
|
16
|
+
transactions: LoyaltyTransaction[];
|
|
38
17
|
className?: string;
|
|
39
18
|
}
|
|
40
19
|
|
|
41
|
-
const transactionConfig: Record<
|
|
20
|
+
const transactionConfig: Record<string, {
|
|
42
21
|
label: string;
|
|
43
22
|
icon: typeof ArrowUpCircle;
|
|
44
23
|
color: string;
|
|
@@ -127,7 +106,11 @@ export function PointsHistory({ transactions, className }: PointsHistoryProps) {
|
|
|
127
106
|
<CardContent>
|
|
128
107
|
<div className="space-y-4">
|
|
129
108
|
{transactions.map((transaction) => {
|
|
130
|
-
const config = transactionConfig[transaction.type]
|
|
109
|
+
const config = transactionConfig[transaction.type] ?? {
|
|
110
|
+
label: transaction.type,
|
|
111
|
+
icon: AlertCircle,
|
|
112
|
+
color: 'text-muted-foreground',
|
|
113
|
+
};
|
|
131
114
|
const Icon = config.icon;
|
|
132
115
|
const isEarning = transaction.points > 0;
|
|
133
116
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { useState } from 'react';
|
|
15
|
+
import { useTranslations } from 'next-intl';
|
|
15
16
|
import { Users, Copy, Check, Share2, Gift, UserPlus, Clock, Award } from 'lucide-react';
|
|
16
17
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
|
17
18
|
import { Button } from '@/components/ui/button';
|
|
@@ -19,18 +20,10 @@ import { Input } from '@/components/ui/input';
|
|
|
19
20
|
import { Badge } from '@/components/ui/badge';
|
|
20
21
|
import { cn } from '@/lib/utils';
|
|
21
22
|
import { toast } from 'sonner';
|
|
22
|
-
|
|
23
|
-
interface ReferralStats {
|
|
24
|
-
totalReferred: number;
|
|
25
|
-
completedReferrals: number;
|
|
26
|
-
pendingReferrals: number;
|
|
27
|
-
totalPointsEarned: number;
|
|
28
|
-
}
|
|
23
|
+
import type { ReferralStats } from '@/lib/graphql/fragments';
|
|
29
24
|
|
|
30
25
|
interface ReferralSectionProps {
|
|
31
|
-
|
|
32
|
-
shareUrl: string;
|
|
33
|
-
stats: ReferralStats;
|
|
26
|
+
referralStats: ReferralStats;
|
|
34
27
|
pointsName?: string;
|
|
35
28
|
referralPoints?: number;
|
|
36
29
|
bonusPoints?: number;
|
|
@@ -38,14 +31,14 @@ interface ReferralSectionProps {
|
|
|
38
31
|
}
|
|
39
32
|
|
|
40
33
|
export function ReferralSection({
|
|
41
|
-
|
|
42
|
-
shareUrl,
|
|
43
|
-
stats,
|
|
34
|
+
referralStats,
|
|
44
35
|
pointsName = 'punktów',
|
|
45
36
|
referralPoints = 0,
|
|
46
37
|
bonusPoints = 0,
|
|
47
38
|
className,
|
|
48
39
|
}: ReferralSectionProps) {
|
|
40
|
+
const t = useTranslations("loyalty.referral");
|
|
41
|
+
const { referralCode, shareUrl } = referralStats;
|
|
49
42
|
const [copied, setCopied] = useState<'code' | 'url' | null>(null);
|
|
50
43
|
|
|
51
44
|
const formatNumber = (num: number) => {
|
|
@@ -56,10 +49,10 @@ export function ReferralSection({
|
|
|
56
49
|
try {
|
|
57
50
|
await navigator.clipboard.writeText(text);
|
|
58
51
|
setCopied(type);
|
|
59
|
-
toast.success(type === 'code' ? '
|
|
52
|
+
toast.success(type === 'code' ? t('codeCopied') : t('linkCopied'));
|
|
60
53
|
setTimeout(() => setCopied(null), 2000);
|
|
61
54
|
} catch {
|
|
62
|
-
toast.error('
|
|
55
|
+
toast.error(t('copyFailed'));
|
|
63
56
|
}
|
|
64
57
|
};
|
|
65
58
|
|
|
@@ -67,14 +60,14 @@ export function ReferralSection({
|
|
|
67
60
|
if (navigator.share) {
|
|
68
61
|
try {
|
|
69
62
|
await navigator.share({
|
|
70
|
-
title: '
|
|
71
|
-
text:
|
|
63
|
+
title: t('shareFriends'),
|
|
64
|
+
text: t('shareText', { code: referralCode }),
|
|
72
65
|
url: shareUrl,
|
|
73
66
|
});
|
|
74
67
|
} catch (err) {
|
|
75
68
|
// User cancelled or error
|
|
76
69
|
if ((err as Error).name !== 'AbortError') {
|
|
77
|
-
toast.error('
|
|
70
|
+
toast.error(t('shareFailed'));
|
|
78
71
|
}
|
|
79
72
|
}
|
|
80
73
|
} else {
|
|
@@ -90,11 +83,10 @@ export function ReferralSection({
|
|
|
90
83
|
<CardHeader>
|
|
91
84
|
<CardTitle className="flex items-center gap-2">
|
|
92
85
|
<Users className="h-5 w-5" />
|
|
93
|
-
|
|
86
|
+
{t('yourCode')}
|
|
94
87
|
</CardTitle>
|
|
95
88
|
<CardDescription>
|
|
96
|
-
|
|
97
|
-
otrzymacie punkty!
|
|
89
|
+
{t('shareDescription')}
|
|
98
90
|
</CardDescription>
|
|
99
91
|
</CardHeader>
|
|
100
92
|
<CardContent className="space-y-4">
|
|
@@ -141,7 +133,7 @@ export function ReferralSection({
|
|
|
141
133
|
{/* Share Button */}
|
|
142
134
|
<Button onClick={handleShare} className="w-full">
|
|
143
135
|
<Share2 className="h-4 w-4 mr-2" />
|
|
144
|
-
|
|
136
|
+
{t('shareFriends')}
|
|
145
137
|
</Button>
|
|
146
138
|
</CardContent>
|
|
147
139
|
</Card>
|
|
@@ -149,7 +141,7 @@ export function ReferralSection({
|
|
|
149
141
|
{/* How it Works */}
|
|
150
142
|
<Card>
|
|
151
143
|
<CardHeader>
|
|
152
|
-
<CardTitle className="text-lg">
|
|
144
|
+
<CardTitle className="text-lg">{t('howItWorks')}</CardTitle>
|
|
153
145
|
</CardHeader>
|
|
154
146
|
<CardContent>
|
|
155
147
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
@@ -157,9 +149,9 @@ export function ReferralSection({
|
|
|
157
149
|
<div className="p-3 bg-primary/10 rounded-full mb-3">
|
|
158
150
|
<Share2 className="h-6 w-6 text-primary" />
|
|
159
151
|
</div>
|
|
160
|
-
<h4 className="font-medium mb-1">
|
|
152
|
+
<h4 className="font-medium mb-1">{t('step1Title')}</h4>
|
|
161
153
|
<p className="text-sm text-muted-foreground">
|
|
162
|
-
|
|
154
|
+
{t('step1Desc')}
|
|
163
155
|
</p>
|
|
164
156
|
</div>
|
|
165
157
|
|
|
@@ -167,9 +159,9 @@ export function ReferralSection({
|
|
|
167
159
|
<div className="p-3 bg-primary/10 rounded-full mb-3">
|
|
168
160
|
<UserPlus className="h-6 w-6 text-primary" />
|
|
169
161
|
</div>
|
|
170
|
-
<h4 className="font-medium mb-1">
|
|
162
|
+
<h4 className="font-medium mb-1">{t('step2Title')}</h4>
|
|
171
163
|
<p className="text-sm text-muted-foreground">
|
|
172
|
-
|
|
164
|
+
{t('step2Desc')}
|
|
173
165
|
</p>
|
|
174
166
|
</div>
|
|
175
167
|
|
|
@@ -177,10 +169,9 @@ export function ReferralSection({
|
|
|
177
169
|
<div className="p-3 bg-primary/10 rounded-full mb-3">
|
|
178
170
|
<Gift className="h-6 w-6 text-primary" />
|
|
179
171
|
</div>
|
|
180
|
-
<h4 className="font-medium mb-1">
|
|
172
|
+
<h4 className="font-medium mb-1">{t('step3Title')}</h4>
|
|
181
173
|
<p className="text-sm text-muted-foreground">
|
|
182
|
-
|
|
183
|
-
{formatNumber(bonusPoints)} {pointsName}
|
|
174
|
+
{t('step3Desc', { points: formatNumber(referralPoints), name: pointsName })}
|
|
184
175
|
</p>
|
|
185
176
|
</div>
|
|
186
177
|
</div>
|
|
@@ -192,54 +183,53 @@ export function ReferralSection({
|
|
|
192
183
|
<CardHeader>
|
|
193
184
|
<CardTitle className="text-lg flex items-center gap-2">
|
|
194
185
|
<Award className="h-5 w-5" />
|
|
195
|
-
|
|
186
|
+
{t('yourStats')}
|
|
196
187
|
</CardTitle>
|
|
197
188
|
</CardHeader>
|
|
198
189
|
<CardContent>
|
|
199
190
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
200
191
|
<div className="p-4 bg-muted/50 rounded-lg text-center">
|
|
201
192
|
<div className="text-2xl font-bold text-primary">
|
|
202
|
-
{formatNumber(
|
|
193
|
+
{formatNumber(referralStats.totalReferred)}
|
|
203
194
|
</div>
|
|
204
|
-
<div className="text-sm text-muted-foreground">
|
|
195
|
+
<div className="text-sm text-muted-foreground">{t('invited')}</div>
|
|
205
196
|
</div>
|
|
206
197
|
|
|
207
198
|
<div className="p-4 bg-muted/50 rounded-lg text-center">
|
|
208
199
|
<div className="flex items-center justify-center gap-1">
|
|
209
200
|
<div className="text-2xl font-bold text-green-600">
|
|
210
|
-
{formatNumber(
|
|
201
|
+
{formatNumber(referralStats.completedReferrals)}
|
|
211
202
|
</div>
|
|
212
203
|
<Check className="h-5 w-5 text-green-600" />
|
|
213
204
|
</div>
|
|
214
|
-
<div className="text-sm text-muted-foreground">
|
|
205
|
+
<div className="text-sm text-muted-foreground">{t('completed')}</div>
|
|
215
206
|
</div>
|
|
216
207
|
|
|
217
208
|
<div className="p-4 bg-muted/50 rounded-lg text-center">
|
|
218
209
|
<div className="flex items-center justify-center gap-1">
|
|
219
210
|
<div className="text-2xl font-bold text-amber-600">
|
|
220
|
-
{formatNumber(
|
|
211
|
+
{formatNumber(referralStats.pendingReferrals)}
|
|
221
212
|
</div>
|
|
222
213
|
<Clock className="h-5 w-5 text-amber-600" />
|
|
223
214
|
</div>
|
|
224
|
-
<div className="text-sm text-muted-foreground">
|
|
215
|
+
<div className="text-sm text-muted-foreground">{t('pending')}</div>
|
|
225
216
|
</div>
|
|
226
217
|
|
|
227
218
|
<div className="p-4 bg-muted/50 rounded-lg text-center">
|
|
228
219
|
<div className="text-2xl font-bold text-primary">
|
|
229
|
-
{formatNumber(
|
|
220
|
+
{formatNumber(referralStats.totalPointsEarned)}
|
|
230
221
|
</div>
|
|
231
222
|
<div className="text-sm text-muted-foreground">
|
|
232
|
-
|
|
223
|
+
{t('earned', { name: pointsName })}
|
|
233
224
|
</div>
|
|
234
225
|
</div>
|
|
235
226
|
</div>
|
|
236
227
|
|
|
237
|
-
{
|
|
228
|
+
{referralStats.pendingReferrals > 0 && (
|
|
238
229
|
<div className="mt-4 p-3 bg-amber-50 dark:bg-amber-950/30 rounded-lg border border-amber-200 dark:border-amber-800">
|
|
239
230
|
<p className="text-sm text-amber-800 dark:text-amber-200">
|
|
240
231
|
<Clock className="h-4 w-4 inline mr-1" />
|
|
241
|
-
|
|
242
|
-
przyznane po dokonaniu pierwszego zakupu przez poleconą osobę.
|
|
232
|
+
{t('pendingReferrals', { count: referralStats.pendingReferrals })}
|
|
243
233
|
</p>
|
|
244
234
|
</div>
|
|
245
235
|
)}
|
|
@@ -15,41 +15,17 @@ import { Badge } from '@/components/ui/badge';
|
|
|
15
15
|
import { cn } from '@/lib/utils';
|
|
16
16
|
import { TierBadge } from './tier-badge';
|
|
17
17
|
import { toast } from 'sonner';
|
|
18
|
-
|
|
19
|
-
type TierType = 'BRONZE' | 'SILVER' | 'GOLD' | 'PLATINUM' | 'DIAMOND';
|
|
20
|
-
|
|
21
|
-
interface Reward {
|
|
22
|
-
id: string;
|
|
23
|
-
name: string;
|
|
24
|
-
slug: string;
|
|
25
|
-
type: string;
|
|
26
|
-
pointsCost: number;
|
|
27
|
-
discountPercent?: number;
|
|
28
|
-
discountAmount?: {
|
|
29
|
-
amount: string;
|
|
30
|
-
currencyCode: string;
|
|
31
|
-
};
|
|
32
|
-
description?: string;
|
|
33
|
-
image?: {
|
|
34
|
-
url: string;
|
|
35
|
-
altText?: string | null;
|
|
36
|
-
} | null;
|
|
37
|
-
available: boolean;
|
|
38
|
-
tierRequired?: TierType | null;
|
|
39
|
-
remainingRedemptions?: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
interface RedeemResult {
|
|
43
|
-
discountCode?: string | null;
|
|
44
|
-
productDiscountCode?: string | null;
|
|
45
|
-
giftCardCode?: string | null;
|
|
46
|
-
}
|
|
18
|
+
import type { LoyaltyReward, LoyaltyTier } from '@/lib/graphql/fragments';
|
|
47
19
|
|
|
48
20
|
interface RewardsCatalogProps {
|
|
49
|
-
rewards:
|
|
21
|
+
rewards: LoyaltyReward[];
|
|
50
22
|
currentPoints: number;
|
|
51
|
-
currentTier?:
|
|
52
|
-
onRedeem?: (rewardId: string) => Promise<
|
|
23
|
+
currentTier?: LoyaltyTier['type'] | null;
|
|
24
|
+
onRedeem?: (rewardId: string) => Promise<{
|
|
25
|
+
discountCode?: string | null;
|
|
26
|
+
productDiscountCode?: string | null;
|
|
27
|
+
giftCardCode?: string | null;
|
|
28
|
+
}>;
|
|
53
29
|
className?: string;
|
|
54
30
|
}
|
|
55
31
|
|
|
@@ -73,13 +49,13 @@ export function RewardsCatalog({
|
|
|
73
49
|
}).format(parseFloat(amount));
|
|
74
50
|
};
|
|
75
51
|
|
|
76
|
-
const tierOrder:
|
|
77
|
-
const canAccessTier = (
|
|
78
|
-
if (!
|
|
79
|
-
return tierOrder.indexOf(currentTier) >= tierOrder.indexOf(
|
|
52
|
+
const tierOrder: string[] = ['BRONZE', 'SILVER', 'GOLD', 'PLATINUM', 'DIAMOND'];
|
|
53
|
+
const canAccessTier = (requiredTierType?: string | null) => {
|
|
54
|
+
if (!requiredTierType || !currentTier) return true;
|
|
55
|
+
return tierOrder.indexOf(currentTier) >= tierOrder.indexOf(requiredTierType);
|
|
80
56
|
};
|
|
81
57
|
|
|
82
|
-
const handleRedeem = async (reward:
|
|
58
|
+
const handleRedeem = async (reward: LoyaltyReward) => {
|
|
83
59
|
if (!onRedeem) return;
|
|
84
60
|
|
|
85
61
|
setRedeemingId(reward.id);
|
|
@@ -125,7 +101,7 @@ export function RewardsCatalog({
|
|
|
125
101
|
<div className={cn('grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4', className)}>
|
|
126
102
|
{rewards.map((reward) => {
|
|
127
103
|
const canAfford = currentPoints >= reward.pointsCost;
|
|
128
|
-
const hasTierAccess = canAccessTier(reward.tierRequired);
|
|
104
|
+
const hasTierAccess = canAccessTier(reward.tierRequired?.type);
|
|
129
105
|
const canRedeem = reward.available && canAfford && hasTierAccess;
|
|
130
106
|
|
|
131
107
|
return (
|
|
@@ -144,8 +120,8 @@ export function RewardsCatalog({
|
|
|
144
120
|
<CardContent className="p-4">
|
|
145
121
|
<div className="flex items-start justify-between gap-2 mb-2">
|
|
146
122
|
<h3 className="font-semibold">{reward.name}</h3>
|
|
147
|
-
{reward.tierRequired && (
|
|
148
|
-
<TierBadge tier={reward.tierRequired} size="sm" />
|
|
123
|
+
{reward.tierRequired?.type && (
|
|
124
|
+
<TierBadge tier={reward.tierRequired.type} size="sm" />
|
|
149
125
|
)}
|
|
150
126
|
</div>
|
|
151
127
|
|
|
@@ -183,7 +159,7 @@ export function RewardsCatalog({
|
|
|
183
159
|
{!hasTierAccess ? (
|
|
184
160
|
<Button variant="outline" className="w-full" disabled>
|
|
185
161
|
<Lock className="h-4 w-4 mr-2" />
|
|
186
|
-
Wymaga {reward.tierRequired}
|
|
162
|
+
Wymaga {reward.tierRequired?.name ?? reward.tierRequired?.type}
|
|
187
163
|
</Button>
|
|
188
164
|
) : !canAfford ? (
|
|
189
165
|
<Button variant="outline" className="w-full" disabled>
|
|
@@ -11,37 +11,10 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
|
11
11
|
import { Progress } from '@/components/ui/progress';
|
|
12
12
|
import { TierBadge } from './tier-badge';
|
|
13
13
|
import { cn } from '@/lib/utils';
|
|
14
|
-
|
|
15
|
-
type TierType = 'BRONZE' | 'SILVER' | 'GOLD' | 'PLATINUM' | 'DIAMOND';
|
|
16
|
-
|
|
17
|
-
interface CustomBenefit {
|
|
18
|
-
name: string;
|
|
19
|
-
description?: string | null;
|
|
20
|
-
icon?: string | null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface Tier {
|
|
24
|
-
id: string;
|
|
25
|
-
name: string;
|
|
26
|
-
type?: TierType | null;
|
|
27
|
-
minPoints: number;
|
|
28
|
-
pointsMultiplier: number;
|
|
29
|
-
customBenefits?: CustomBenefit[];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface TierProgressData {
|
|
33
|
-
currentTier: Tier;
|
|
34
|
-
nextTier?: Tier;
|
|
35
|
-
pointsToNextTier: number;
|
|
36
|
-
progressPercent: number;
|
|
37
|
-
spendToNextTier?: {
|
|
38
|
-
amount: string;
|
|
39
|
-
currencyCode: string;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
14
|
+
import type { TierProgress as TierProgressType } from '@/lib/graphql/fragments';
|
|
42
15
|
|
|
43
16
|
interface TierProgressProps {
|
|
44
|
-
progress:
|
|
17
|
+
progress: TierProgressType;
|
|
45
18
|
className?: string;
|
|
46
19
|
}
|
|
47
20
|
|
|
@@ -7,5 +7,10 @@
|
|
|
7
7
|
export * from "./order-tracking";
|
|
8
8
|
export * from "./shipment-card";
|
|
9
9
|
export * from "./tracking-timeline";
|
|
10
|
-
export
|
|
10
|
+
export {
|
|
11
|
+
TrackingStatus,
|
|
12
|
+
CompactTrackingStatus,
|
|
13
|
+
type TrackingStatusProps,
|
|
14
|
+
type CompactTrackingStatusProps,
|
|
15
|
+
} from "./tracking-status";
|
|
11
16
|
export * from "./delivery-estimate";
|