@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,13 +1,13 @@
|
|
|
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 { ChevronRight, Home } from "lucide-react";
|
|
6
6
|
import { cn } from "@/lib/utils";
|
|
7
7
|
|
|
8
8
|
export interface BreadcrumbItem {
|
|
9
9
|
label: string;
|
|
10
|
-
href
|
|
10
|
+
href?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface BreadcrumbsProps {
|
|
@@ -31,15 +31,33 @@ export interface BreadcrumbsProps {
|
|
|
31
31
|
* { label: "Laptops", href: "/products/electronics/laptops" }
|
|
32
32
|
* ]} />
|
|
33
33
|
*/
|
|
34
|
+
// Known segment keys that exist in nav translations
|
|
35
|
+
const SEGMENT_TRANSLATION_KEYS: Record<string, string> = {
|
|
36
|
+
products: "products",
|
|
37
|
+
collections: "collections",
|
|
38
|
+
categories: "categories",
|
|
39
|
+
about: "about",
|
|
40
|
+
brands: "brands",
|
|
41
|
+
blog: "blog",
|
|
42
|
+
cart: "cart",
|
|
43
|
+
account: "account",
|
|
44
|
+
contact: "contact",
|
|
45
|
+
shipping: "shipping",
|
|
46
|
+
returns: "returns",
|
|
47
|
+
search: "searchBreadcrumb",
|
|
48
|
+
wishlist: "wishlist",
|
|
49
|
+
};
|
|
50
|
+
|
|
34
51
|
export function Breadcrumbs({
|
|
35
52
|
items,
|
|
36
53
|
className,
|
|
37
54
|
showHome = true,
|
|
38
55
|
}: BreadcrumbsProps) {
|
|
56
|
+
const t = useTranslations("nav");
|
|
39
57
|
const pathname = usePathname();
|
|
40
58
|
|
|
41
59
|
// Auto-generate breadcrumbs from pathname if items not provided
|
|
42
|
-
const breadcrumbItems = items || generateBreadcrumbs(pathname);
|
|
60
|
+
const breadcrumbItems = items || generateBreadcrumbs(pathname, t);
|
|
43
61
|
|
|
44
62
|
// Don't show breadcrumbs on homepage
|
|
45
63
|
if (pathname === "/" || breadcrumbItems.length === 0) {
|
|
@@ -48,7 +66,7 @@ export function Breadcrumbs({
|
|
|
48
66
|
|
|
49
67
|
return (
|
|
50
68
|
<nav
|
|
51
|
-
aria-label="
|
|
69
|
+
aria-label={t("breadcrumb")}
|
|
52
70
|
className={cn("flex items-center gap-2 text-sm", className)}
|
|
53
71
|
>
|
|
54
72
|
<ol className="flex items-center gap-2">
|
|
@@ -57,7 +75,7 @@ export function Breadcrumbs({
|
|
|
57
75
|
<Link
|
|
58
76
|
href="/"
|
|
59
77
|
className="flex items-center text-muted-foreground hover:text-foreground transition-colors"
|
|
60
|
-
aria-label="
|
|
78
|
+
aria-label={t("home")}
|
|
61
79
|
>
|
|
62
80
|
<Home className="h-4 w-4" />
|
|
63
81
|
</Link>
|
|
@@ -68,7 +86,7 @@ export function Breadcrumbs({
|
|
|
68
86
|
const isLast = index === breadcrumbItems.length - 1;
|
|
69
87
|
|
|
70
88
|
return (
|
|
71
|
-
<li key={item.href} className="flex items-center gap-2">
|
|
89
|
+
<li key={item.href || `breadcrumb-${index}`} className="flex items-center gap-2">
|
|
72
90
|
{(showHome || index > 0) && (
|
|
73
91
|
<ChevronRight
|
|
74
92
|
className="h-4 w-4 text-muted-foreground"
|
|
@@ -76,10 +94,10 @@ export function Breadcrumbs({
|
|
|
76
94
|
/>
|
|
77
95
|
)}
|
|
78
96
|
|
|
79
|
-
{isLast ? (
|
|
97
|
+
{isLast || !item.href ? (
|
|
80
98
|
<span
|
|
81
99
|
className="font-medium text-foreground"
|
|
82
|
-
aria-current="page"
|
|
100
|
+
aria-current={isLast ? "page" : undefined}
|
|
83
101
|
>
|
|
84
102
|
{item.label}
|
|
85
103
|
</span>
|
|
@@ -101,20 +119,27 @@ export function Breadcrumbs({
|
|
|
101
119
|
|
|
102
120
|
/**
|
|
103
121
|
* Generate breadcrumb items from pathname
|
|
122
|
+
* Uses translations for known segments, falls back to capitalized segment name
|
|
104
123
|
*/
|
|
105
|
-
function generateBreadcrumbs(
|
|
124
|
+
function generateBreadcrumbs(
|
|
125
|
+
pathname: string,
|
|
126
|
+
t: (key: string) => string,
|
|
127
|
+
): BreadcrumbItem[] {
|
|
106
128
|
const segments = pathname.split("/").filter(Boolean);
|
|
107
129
|
const breadcrumbs: BreadcrumbItem[] = [];
|
|
108
130
|
|
|
109
131
|
let currentPath = "";
|
|
110
132
|
for (const segment of segments) {
|
|
111
133
|
currentPath += `/${segment}`;
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
|
|
135
|
+
// Use translation for known segments, fallback to capitalized segment
|
|
136
|
+
const translationKey = SEGMENT_TRANSLATION_KEYS[segment];
|
|
137
|
+
const label = translationKey
|
|
138
|
+
? t(translationKey)
|
|
139
|
+
: segment
|
|
140
|
+
.split("-")
|
|
141
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
142
|
+
.join(" ");
|
|
118
143
|
|
|
119
144
|
breadcrumbs.push({
|
|
120
145
|
label,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Fragment for CategoryCard / CategoryNav components.
|
|
2
|
+
#
|
|
3
|
+
# Category data for navigation, sidebar filters, breadcrumbs.
|
|
4
|
+
#
|
|
5
|
+
# Usage in components:
|
|
6
|
+
# import type { CategoryNodeFieldsFragment } from '@/generated/graphql';
|
|
7
|
+
# interface Props { category: CategoryNodeFieldsFragment }
|
|
8
|
+
|
|
9
|
+
fragment CategoryNodeFields on Category {
|
|
10
|
+
id
|
|
11
|
+
name
|
|
12
|
+
slug
|
|
13
|
+
description
|
|
14
|
+
productCount
|
|
15
|
+
level
|
|
16
|
+
path
|
|
17
|
+
sortOrder
|
|
18
|
+
image {
|
|
19
|
+
url
|
|
20
|
+
altText
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { useState, useRef, useEffect } from 'react';
|
|
21
|
-
import { useCurrencyStore } from '
|
|
21
|
+
import { useCurrencyStore } from '@doswiftly/storefront-sdk/react';
|
|
22
22
|
import { useQueryClient } from '@tanstack/react-query';
|
|
23
23
|
import { ChevronDown, Check, Globe } from 'lucide-react';
|
|
24
|
+
import { useTranslations } from 'next-intl';
|
|
24
25
|
|
|
25
26
|
// ============================================================================
|
|
26
27
|
// CURRENCY DATA
|
|
@@ -149,12 +150,14 @@ export function CurrencySelector({
|
|
|
149
150
|
showIcon = true,
|
|
150
151
|
variant = 'default',
|
|
151
152
|
}: CurrencySelectorProps) {
|
|
153
|
+
const t = useTranslations("currency");
|
|
154
|
+
|
|
152
155
|
// Currency store state
|
|
153
156
|
const currency = useCurrencyStore((state) => state.currency);
|
|
154
157
|
const supportedCurrencies = useCurrencyStore((state) => state.supportedCurrencies);
|
|
155
158
|
const setCurrency = useCurrencyStore((state) => state.setCurrency);
|
|
156
159
|
const isLoaded = useCurrencyStore((state) => state.isLoaded);
|
|
157
|
-
|
|
160
|
+
|
|
158
161
|
// React Query client for cache invalidation
|
|
159
162
|
const queryClient = useQueryClient();
|
|
160
163
|
|
|
@@ -261,7 +264,7 @@ export function CurrencySelector({
|
|
|
261
264
|
`}
|
|
262
265
|
aria-expanded={isOpen}
|
|
263
266
|
aria-haspopup="listbox"
|
|
264
|
-
aria-label="
|
|
267
|
+
aria-label={t("selectCurrency")}
|
|
265
268
|
>
|
|
266
269
|
{showIcon && variant !== 'minimal' && (
|
|
267
270
|
<Globe className="w-4 h-4 text-gray-400" aria-hidden="true" />
|
|
@@ -287,7 +290,7 @@ export function CurrencySelector({
|
|
|
287
290
|
${dropdownStyles[variant]}
|
|
288
291
|
`}
|
|
289
292
|
role="listbox"
|
|
290
|
-
aria-label="
|
|
293
|
+
aria-label={t("currencyOptions")}
|
|
291
294
|
>
|
|
292
295
|
<div className="py-1 max-h-64 overflow-y-auto">
|
|
293
296
|
{supportedCurrencies.map((code) => {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import Link from "
|
|
1
|
+
import { Link } from "@/i18n/navigation";
|
|
2
|
+
import { getTranslations } from "next-intl/server";
|
|
2
3
|
|
|
3
|
-
export function Footer() {
|
|
4
|
+
export async function Footer() {
|
|
4
5
|
const currentYear = new Date().getFullYear();
|
|
5
6
|
const siteName = process.env.NEXT_PUBLIC_SITE_NAME || "My Store";
|
|
7
|
+
const t = await getTranslations("footer");
|
|
8
|
+
const tc = await getTranslations("common");
|
|
6
9
|
|
|
7
10
|
return (
|
|
8
11
|
<footer className="border-t border-border bg-muted/50">
|
|
@@ -14,33 +17,32 @@ export function Footer() {
|
|
|
14
17
|
{siteName}
|
|
15
18
|
</Link>
|
|
16
19
|
<p className="mt-4 text-sm text-muted-foreground">
|
|
17
|
-
|
|
18
|
-
Commerce.
|
|
20
|
+
{t("description")}
|
|
19
21
|
</p>
|
|
20
22
|
</div>
|
|
21
23
|
|
|
22
24
|
{/* Shop */}
|
|
23
25
|
<div>
|
|
24
|
-
<h3 className="mb-4 font-semibold text-foreground">
|
|
26
|
+
<h3 className="mb-4 font-semibold text-foreground">{t("shop")}</h3>
|
|
25
27
|
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
26
28
|
<li>
|
|
27
29
|
<Link href="/products" className="hover:text-primary transition-colors">
|
|
28
|
-
|
|
30
|
+
{t("allProducts")}
|
|
29
31
|
</Link>
|
|
30
32
|
</li>
|
|
31
33
|
<li>
|
|
32
34
|
<Link href="/collections" className="hover:text-primary transition-colors">
|
|
33
|
-
|
|
35
|
+
{t("collections")}
|
|
34
36
|
</Link>
|
|
35
37
|
</li>
|
|
36
38
|
<li>
|
|
37
39
|
<Link href="/categories" className="hover:text-primary transition-colors">
|
|
38
|
-
|
|
40
|
+
{t("categories")}
|
|
39
41
|
</Link>
|
|
40
42
|
</li>
|
|
41
43
|
<li>
|
|
42
44
|
<Link href="/search" className="hover:text-primary transition-colors">
|
|
43
|
-
|
|
45
|
+
{tc("search")}
|
|
44
46
|
</Link>
|
|
45
47
|
</li>
|
|
46
48
|
</ul>
|
|
@@ -48,31 +50,31 @@ export function Footer() {
|
|
|
48
50
|
|
|
49
51
|
{/* Account */}
|
|
50
52
|
<div>
|
|
51
|
-
<h3 className="mb-4 font-semibold text-foreground">
|
|
53
|
+
<h3 className="mb-4 font-semibold text-foreground">{t("myAccount")}</h3>
|
|
52
54
|
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
53
55
|
<li>
|
|
54
56
|
<Link href="/auth/login" className="hover:text-primary transition-colors">
|
|
55
|
-
|
|
57
|
+
{t("signIn")}
|
|
56
58
|
</Link>
|
|
57
59
|
</li>
|
|
58
60
|
<li>
|
|
59
61
|
<Link href="/auth/register" className="hover:text-primary transition-colors">
|
|
60
|
-
|
|
62
|
+
{t("createAccount")}
|
|
61
63
|
</Link>
|
|
62
64
|
</li>
|
|
63
65
|
<li>
|
|
64
66
|
<Link href="/account" className="hover:text-primary transition-colors">
|
|
65
|
-
|
|
67
|
+
{t("myAccount")}
|
|
66
68
|
</Link>
|
|
67
69
|
</li>
|
|
68
70
|
<li>
|
|
69
71
|
<Link href="/account/orders" className="hover:text-primary transition-colors">
|
|
70
|
-
|
|
72
|
+
{t("orderHistory")}
|
|
71
73
|
</Link>
|
|
72
74
|
</li>
|
|
73
75
|
<li>
|
|
74
76
|
<Link href="/cart" className="hover:text-primary transition-colors">
|
|
75
|
-
|
|
77
|
+
{t("shoppingCart")}
|
|
76
78
|
</Link>
|
|
77
79
|
</li>
|
|
78
80
|
</ul>
|
|
@@ -80,26 +82,26 @@ export function Footer() {
|
|
|
80
82
|
|
|
81
83
|
{/* Support */}
|
|
82
84
|
<div>
|
|
83
|
-
<h3 className="mb-4 font-semibold text-foreground">
|
|
85
|
+
<h3 className="mb-4 font-semibold text-foreground">{t("support")}</h3>
|
|
84
86
|
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
85
87
|
<li>
|
|
86
88
|
<Link href="/contact" className="hover:text-primary transition-colors">
|
|
87
|
-
|
|
89
|
+
{t("contactUs")}
|
|
88
90
|
</Link>
|
|
89
91
|
</li>
|
|
90
92
|
<li>
|
|
91
93
|
<Link href="/about" className="hover:text-primary transition-colors">
|
|
92
|
-
|
|
94
|
+
{t("aboutUs")}
|
|
93
95
|
</Link>
|
|
94
96
|
</li>
|
|
95
97
|
<li>
|
|
96
98
|
<Link href="/shipping" className="hover:text-primary transition-colors">
|
|
97
|
-
|
|
99
|
+
{t("shippingInfo")}
|
|
98
100
|
</Link>
|
|
99
101
|
</li>
|
|
100
102
|
<li>
|
|
101
103
|
<Link href="/returns" className="hover:text-primary transition-colors">
|
|
102
|
-
|
|
104
|
+
{t("returnsRefunds")}
|
|
103
105
|
</Link>
|
|
104
106
|
</li>
|
|
105
107
|
</ul>
|
|
@@ -108,17 +110,16 @@ export function Footer() {
|
|
|
108
110
|
|
|
109
111
|
<div className="mt-12 border-t border-border pt-8 text-center text-sm text-muted-foreground">
|
|
110
112
|
<p>
|
|
111
|
-
© {currentYear} {siteName}.
|
|
113
|
+
© {currentYear} {siteName}. {t("allRightsReserved")}.
|
|
112
114
|
</p>
|
|
113
115
|
<p className="mt-2">
|
|
114
|
-
Powered by{" "}
|
|
115
116
|
<a
|
|
116
117
|
href="https://doswiftly.pl"
|
|
117
118
|
target="_blank"
|
|
118
119
|
rel="noopener noreferrer"
|
|
119
120
|
className="text-primary hover:underline transition-colors"
|
|
120
121
|
>
|
|
121
|
-
|
|
122
|
+
{t("poweredBy")}
|
|
122
123
|
</a>
|
|
123
124
|
</p>
|
|
124
125
|
</div>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import Link from "next/link";
|
|
4
3
|
import { useState } from "react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { Link } from "@/i18n/navigation";
|
|
5
6
|
import { Menu, X } from "lucide-react";
|
|
6
7
|
import { CurrencySelector } from "@/components/commerce/currency-selector";
|
|
7
8
|
import { CartIcon } from "@/components/cart/cart-icon";
|
|
@@ -9,32 +10,42 @@ import { SearchInput } from "@/components/commerce/search-input";
|
|
|
9
10
|
import { Navigation } from "@/components/layout/navigation";
|
|
10
11
|
import { AccountMenu } from "@/components/auth/account-menu";
|
|
11
12
|
import { ThemeSwitcher } from "@/components/layout/theme-switcher";
|
|
12
|
-
import {
|
|
13
|
+
import { LanguageSwitcher } from "@/components/layout/language-switcher";
|
|
14
|
+
import { useAuthStore, useAuthHydrated } from "@doswiftly/storefront-sdk/react";
|
|
15
|
+
import { useHydrated } from "@doswiftly/storefront-sdk/react";
|
|
16
|
+
import { useAuthSync } from "@/hooks/use-auth-sync";
|
|
13
17
|
|
|
14
18
|
export function Header() {
|
|
19
|
+
const t = useTranslations("nav");
|
|
15
20
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
16
|
-
|
|
17
|
-
//
|
|
21
|
+
|
|
22
|
+
// Auto-fix cookie/store desync (e.g., localStorage cleared but cookie persists)
|
|
23
|
+
useAuthSync();
|
|
24
|
+
|
|
25
|
+
// Double-guard: DOM must be mounted (useHydrated) AND store must be rehydrated (useAuthHydrated from Zustand persist)
|
|
26
|
+
const hydrated = useHydrated();
|
|
18
27
|
const { isAuthenticated, customer } = useAuthStore();
|
|
28
|
+
const authHydrated = useAuthHydrated();
|
|
29
|
+
const showAuth = hydrated && authHydrated;
|
|
19
30
|
const customerName = customer
|
|
20
31
|
? `${customer.firstName || ""} ${customer.lastName || ""}`.trim() || customer.email
|
|
21
32
|
: undefined;
|
|
22
33
|
|
|
23
34
|
const navigationItems = [
|
|
24
35
|
{
|
|
25
|
-
label: "
|
|
36
|
+
label: t("products"),
|
|
26
37
|
href: "/products",
|
|
27
38
|
},
|
|
28
39
|
{
|
|
29
|
-
label: "
|
|
40
|
+
label: t("collections"),
|
|
30
41
|
href: "/collections",
|
|
31
42
|
},
|
|
32
43
|
{
|
|
33
|
-
label: "
|
|
44
|
+
label: t("categories"),
|
|
34
45
|
href: "/categories",
|
|
35
46
|
},
|
|
36
47
|
{
|
|
37
|
-
label: "
|
|
48
|
+
label: t("about"),
|
|
38
49
|
href: "/about",
|
|
39
50
|
},
|
|
40
51
|
];
|
|
@@ -57,39 +68,46 @@ export function Header() {
|
|
|
57
68
|
<div className="flex items-center gap-3">
|
|
58
69
|
{/* Search */}
|
|
59
70
|
<div className="hidden w-64 lg:block">
|
|
60
|
-
<SearchInput placeholder="
|
|
71
|
+
<SearchInput placeholder={t("search")} />
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
{/* Language Switcher */}
|
|
75
|
+
<div className="hidden md:block">
|
|
76
|
+
<LanguageSwitcher />
|
|
61
77
|
</div>
|
|
62
|
-
|
|
78
|
+
|
|
63
79
|
{/* Currency Selector */}
|
|
64
80
|
<div className="hidden md:block">
|
|
65
81
|
<CurrencySelector variant="compact" />
|
|
66
82
|
</div>
|
|
67
|
-
|
|
83
|
+
|
|
68
84
|
{/* Theme Switcher */}
|
|
69
85
|
<div className="hidden md:block">
|
|
70
86
|
<ThemeSwitcher />
|
|
71
87
|
</div>
|
|
72
|
-
|
|
73
|
-
{/* Account Menu or Login Link */}
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
|
|
89
|
+
{/* Account Menu or Login Link — hidden until DOM + auth store hydrate */}
|
|
90
|
+
{showAuth && (
|
|
91
|
+
isAuthenticated ? (
|
|
92
|
+
<AccountMenu customerName={customerName} />
|
|
93
|
+
) : (
|
|
94
|
+
<Link
|
|
95
|
+
href="/auth/login"
|
|
96
|
+
className="hidden md:inline-flex items-center rounded-md px-3 py-2 text-sm font-medium text-foreground hover:bg-accent hover:text-accent-foreground transition-colors"
|
|
97
|
+
>
|
|
98
|
+
{t("signIn")}
|
|
99
|
+
</Link>
|
|
100
|
+
)
|
|
83
101
|
)}
|
|
84
|
-
|
|
102
|
+
|
|
85
103
|
{/* Cart Icon */}
|
|
86
104
|
<CartIcon />
|
|
87
|
-
|
|
105
|
+
|
|
88
106
|
{/* Mobile Menu Toggle */}
|
|
89
107
|
<button
|
|
90
108
|
className="p-2 text-foreground hover:text-primary md:hidden"
|
|
91
109
|
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
|
92
|
-
aria-label="
|
|
110
|
+
aria-label={t("menu")}
|
|
93
111
|
aria-expanded={isMenuOpen}
|
|
94
112
|
>
|
|
95
113
|
{isMenuOpen ? (
|
|
@@ -107,15 +125,15 @@ export function Header() {
|
|
|
107
125
|
<div className="flex flex-col gap-4">
|
|
108
126
|
{/* Mobile Search */}
|
|
109
127
|
<div className="lg:hidden">
|
|
110
|
-
<SearchInput placeholder="
|
|
128
|
+
<SearchInput placeholder={t("search")} />
|
|
111
129
|
</div>
|
|
112
|
-
|
|
113
|
-
{/* Mobile Currency
|
|
130
|
+
|
|
131
|
+
{/* Mobile Language & Currency */}
|
|
114
132
|
<div className="flex items-center justify-between">
|
|
115
|
-
<
|
|
133
|
+
<LanguageSwitcher />
|
|
116
134
|
<CurrencySelector variant="compact" />
|
|
117
135
|
</div>
|
|
118
|
-
|
|
136
|
+
|
|
119
137
|
{/* Mobile Navigation Links */}
|
|
120
138
|
{navigationItems.map((item) => (
|
|
121
139
|
<Link
|
|
@@ -127,15 +145,15 @@ export function Header() {
|
|
|
127
145
|
{item.label}
|
|
128
146
|
</Link>
|
|
129
147
|
))}
|
|
130
|
-
|
|
131
|
-
{/* Mobile Account Link */}
|
|
132
|
-
{!isAuthenticated && (
|
|
148
|
+
|
|
149
|
+
{/* Mobile Account Link — guarded by showAuth */}
|
|
150
|
+
{showAuth && !isAuthenticated && (
|
|
133
151
|
<Link
|
|
134
152
|
href="/auth/login"
|
|
135
153
|
className="text-foreground hover:text-primary transition-colors font-medium"
|
|
136
154
|
onClick={() => setIsMenuOpen(false)}
|
|
137
155
|
>
|
|
138
|
-
|
|
156
|
+
{t("signIn")}
|
|
139
157
|
</Link>
|
|
140
158
|
)}
|
|
141
159
|
</div>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useLanguageStore } from "@doswiftly/storefront-sdk/react";
|
|
4
|
+
import { useRouter, usePathname } from "@/i18n/navigation";
|
|
5
|
+
import { useLocale, useTranslations } from "next-intl";
|
|
6
|
+
import {
|
|
7
|
+
Select,
|
|
8
|
+
SelectContent,
|
|
9
|
+
SelectItem,
|
|
10
|
+
SelectTrigger,
|
|
11
|
+
SelectValue,
|
|
12
|
+
} from "@/components/ui/select";
|
|
13
|
+
|
|
14
|
+
const LANGUAGE_NAMES: Record<string, string> = {
|
|
15
|
+
pl: "Polski",
|
|
16
|
+
en: "English",
|
|
17
|
+
de: "Deutsch",
|
|
18
|
+
fr: "Français",
|
|
19
|
+
es: "Español",
|
|
20
|
+
cs: "Čeština",
|
|
21
|
+
it: "Italiano",
|
|
22
|
+
nl: "Nederlands",
|
|
23
|
+
pt: "Português",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export function LanguageSwitcher() {
|
|
27
|
+
const t = useTranslations("language");
|
|
28
|
+
const locale = useLocale();
|
|
29
|
+
const router = useRouter();
|
|
30
|
+
const pathname = usePathname();
|
|
31
|
+
const supportedLanguages = useLanguageStore((s) => s.supportedLanguages);
|
|
32
|
+
|
|
33
|
+
if (supportedLanguages.length < 2) return null;
|
|
34
|
+
|
|
35
|
+
const handleLocaleChange = (newLocale: string) => {
|
|
36
|
+
if (newLocale === locale) return;
|
|
37
|
+
router.replace(pathname, { locale: newLocale });
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Select value={locale} onValueChange={handleLocaleChange}>
|
|
42
|
+
<SelectTrigger className="h-8 w-auto gap-1 border-0 bg-transparent px-2 text-xs font-medium shadow-none" aria-label={t("switchLanguage")}>
|
|
43
|
+
<SelectValue>{locale.toUpperCase()}</SelectValue>
|
|
44
|
+
</SelectTrigger>
|
|
45
|
+
<SelectContent align="end">
|
|
46
|
+
{supportedLanguages.map((lang) => (
|
|
47
|
+
<SelectItem key={lang} value={lang}>
|
|
48
|
+
{lang.toUpperCase()} — {LANGUAGE_NAMES[lang] || lang}
|
|
49
|
+
</SelectItem>
|
|
50
|
+
))}
|
|
51
|
+
</SelectContent>
|
|
52
|
+
</Select>
|
|
53
|
+
);
|
|
54
|
+
}
|