@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,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useParams } from "next/navigation";
|
|
4
|
-
import
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { Link } from "@/i18n/navigation";
|
|
5
6
|
import { ChevronLeft } from "lucide-react";
|
|
6
7
|
import { Button } from "@/components/ui/button";
|
|
7
8
|
import { Breadcrumbs } from "@/components/layout/breadcrumbs";
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
export default function OrderTrackingPage() {
|
|
20
21
|
const params = useParams();
|
|
21
22
|
const orderId = params.id as string;
|
|
23
|
+
const t = useTranslations("tracking");
|
|
22
24
|
|
|
23
25
|
// TODO: Fetch tracking data from backend using GraphQL
|
|
24
26
|
const trackingData = {
|
|
@@ -40,26 +42,26 @@ export default function OrderTrackingPage() {
|
|
|
40
42
|
|
|
41
43
|
const milestones = [
|
|
42
44
|
{
|
|
43
|
-
label: "
|
|
45
|
+
label: t("orderPlaced"),
|
|
44
46
|
status: "completed" as const,
|
|
45
47
|
date: "2024-01-15",
|
|
46
48
|
},
|
|
47
49
|
{
|
|
48
|
-
label: "
|
|
50
|
+
label: t("processing"),
|
|
49
51
|
status: "completed" as const,
|
|
50
52
|
date: "2024-01-16",
|
|
51
53
|
},
|
|
52
54
|
{
|
|
53
|
-
label: "
|
|
55
|
+
label: t("shipped"),
|
|
54
56
|
status: "completed" as const,
|
|
55
57
|
date: "2024-01-17",
|
|
56
58
|
},
|
|
57
59
|
{
|
|
58
|
-
label: "
|
|
60
|
+
label: t("inTransit"),
|
|
59
61
|
status: "current" as const,
|
|
60
62
|
},
|
|
61
63
|
{
|
|
62
|
-
label: "
|
|
64
|
+
label: t("delivered"),
|
|
63
65
|
status: "pending" as const,
|
|
64
66
|
},
|
|
65
67
|
];
|
|
@@ -67,40 +69,40 @@ export default function OrderTrackingPage() {
|
|
|
67
69
|
const events: TrackingEvent[] = [
|
|
68
70
|
{
|
|
69
71
|
id: "1",
|
|
70
|
-
status: "
|
|
71
|
-
description: "
|
|
72
|
+
status: t("inTransit"),
|
|
73
|
+
description: t("onTheWay"),
|
|
72
74
|
location: "Warsaw Distribution Center",
|
|
73
75
|
timestamp: "2024-01-18T14:30:00Z",
|
|
74
76
|
isCompleted: true,
|
|
75
77
|
},
|
|
76
78
|
{
|
|
77
79
|
id: "2",
|
|
78
|
-
status: "
|
|
79
|
-
description: "
|
|
80
|
+
status: t("inTransit"),
|
|
81
|
+
description: t("arrivedAtFacility"),
|
|
80
82
|
location: "Krakow Sorting Facility",
|
|
81
83
|
timestamp: "2024-01-18T08:15:00Z",
|
|
82
84
|
isCompleted: true,
|
|
83
85
|
},
|
|
84
86
|
{
|
|
85
87
|
id: "3",
|
|
86
|
-
status: "
|
|
87
|
-
description: "
|
|
88
|
+
status: t("shipped"),
|
|
89
|
+
description: t("pickedUpByCarrier"),
|
|
88
90
|
location: "Origin Facility",
|
|
89
91
|
timestamp: "2024-01-17T16:45:00Z",
|
|
90
92
|
isCompleted: true,
|
|
91
93
|
},
|
|
92
94
|
{
|
|
93
95
|
id: "4",
|
|
94
|
-
status: "
|
|
95
|
-
description: "
|
|
96
|
-
location: "
|
|
96
|
+
status: t("processing"),
|
|
97
|
+
description: t("preparingShipment"),
|
|
98
|
+
location: t("warehouse"),
|
|
97
99
|
timestamp: "2024-01-16T10:00:00Z",
|
|
98
100
|
isCompleted: true,
|
|
99
101
|
},
|
|
100
102
|
{
|
|
101
103
|
id: "5",
|
|
102
|
-
status: "
|
|
103
|
-
description: "
|
|
104
|
+
status: t("orderPlaced"),
|
|
105
|
+
description: t("orderConfirmed"),
|
|
104
106
|
timestamp: "2024-01-15T12:30:00Z",
|
|
105
107
|
isCompleted: true,
|
|
106
108
|
},
|
|
@@ -114,17 +116,17 @@ export default function OrderTrackingPage() {
|
|
|
114
116
|
<Button variant="ghost" asChild>
|
|
115
117
|
<Link href={`/account/orders/${orderId}`}>
|
|
116
118
|
<ChevronLeft className="mr-2 h-4 w-4" />
|
|
117
|
-
|
|
119
|
+
{t("backToOrderDetails")}
|
|
118
120
|
</Link>
|
|
119
121
|
</Button>
|
|
120
122
|
</div>
|
|
121
123
|
|
|
122
124
|
<div className="mb-8">
|
|
123
125
|
<h1 className="text-3xl font-bold text-foreground">
|
|
124
|
-
|
|
126
|
+
{t("trackOrder", { orderNumber: trackingData.orderNumber })}
|
|
125
127
|
</h1>
|
|
126
128
|
<p className="mt-2 text-muted-foreground">
|
|
127
|
-
|
|
129
|
+
{t("followJourney")}
|
|
128
130
|
</p>
|
|
129
131
|
</div>
|
|
130
132
|
|
|
@@ -154,7 +156,7 @@ export default function OrderTrackingPage() {
|
|
|
154
156
|
{/* Tracking Timeline */}
|
|
155
157
|
<div>
|
|
156
158
|
<h2 className="text-xl font-semibold text-foreground mb-4">
|
|
157
|
-
|
|
159
|
+
{t("trackingHistory")}
|
|
158
160
|
</h2>
|
|
159
161
|
<TrackingTimeline events={events} />
|
|
160
162
|
</div>
|
|
@@ -173,16 +175,16 @@ export default function OrderTrackingPage() {
|
|
|
173
175
|
{/* Carrier Information */}
|
|
174
176
|
<div className="rounded-lg border border-border bg-background p-6">
|
|
175
177
|
<h3 className="text-lg font-semibold text-foreground mb-4">
|
|
176
|
-
|
|
178
|
+
{t("carrierInfo")}
|
|
177
179
|
</h3>
|
|
178
180
|
<div className="space-y-3 text-sm">
|
|
179
181
|
<div>
|
|
180
|
-
<span className="font-medium text-foreground">
|
|
182
|
+
<span className="font-medium text-foreground">{t("carrier")}</span>
|
|
181
183
|
<p className="text-muted-foreground">{trackingData.carrier}</p>
|
|
182
184
|
</div>
|
|
183
185
|
<div>
|
|
184
186
|
<span className="font-medium text-foreground">
|
|
185
|
-
|
|
187
|
+
{t("trackingNumberLabel")}
|
|
186
188
|
</span>
|
|
187
189
|
<p className="font-mono text-muted-foreground">
|
|
188
190
|
{trackingData.trackingNumber}
|
|
@@ -194,7 +196,7 @@ export default function OrderTrackingPage() {
|
|
|
194
196
|
target="_blank"
|
|
195
197
|
rel="noopener noreferrer"
|
|
196
198
|
>
|
|
197
|
-
|
|
199
|
+
{t("trackOnCarrierWebsite")}
|
|
198
200
|
</a>
|
|
199
201
|
</Button>
|
|
200
202
|
</div>
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Link } from "@/i18n/navigation";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { useAuthStore, useAuthHydrated } from "@doswiftly/storefront-sdk/react";
|
|
6
|
+
import { useCustomer } from "@/lib/graphql/hooks";
|
|
7
|
+
import { useHydrated } from "@doswiftly/storefront-sdk/react";
|
|
8
|
+
import { Breadcrumbs } from "@/components/layout/breadcrumbs";
|
|
9
|
+
import { OrderHistory } from "@/components/account/order-history";
|
|
10
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
11
|
+
|
|
12
|
+
export default function OrdersPage() {
|
|
13
|
+
const t = useTranslations("account");
|
|
14
|
+
const hydrated = useHydrated();
|
|
15
|
+
const authHydrated = useAuthHydrated();
|
|
16
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
17
|
+
|
|
18
|
+
const { data, isPending, error } = useCustomer();
|
|
19
|
+
|
|
20
|
+
// Wait for DOM + auth persist hydration before checking accessToken
|
|
21
|
+
if (!hydrated || !authHydrated) {
|
|
22
|
+
return (
|
|
23
|
+
<div className="container mx-auto px-4 py-8">
|
|
24
|
+
<Breadcrumbs className="mb-6" />
|
|
25
|
+
<div className="mb-8">
|
|
26
|
+
<Skeleton className="h-10 w-64 mb-2" />
|
|
27
|
+
<Skeleton className="h-6 w-96" />
|
|
28
|
+
</div>
|
|
29
|
+
<div className="space-y-4">
|
|
30
|
+
{[...Array(3)].map((_, i) => (
|
|
31
|
+
<Skeleton key={i} className="h-32 w-full" />
|
|
32
|
+
))}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Data loading (customer query fetching after accessToken is available)
|
|
39
|
+
if (isPending) {
|
|
40
|
+
return (
|
|
41
|
+
<div className="container mx-auto px-4 py-8">
|
|
42
|
+
<Breadcrumbs className="mb-6" />
|
|
43
|
+
<div className="mb-8">
|
|
44
|
+
<Skeleton className="h-10 w-64 mb-2" />
|
|
45
|
+
<Skeleton className="h-6 w-96" />
|
|
46
|
+
</div>
|
|
47
|
+
<div className="space-y-4">
|
|
48
|
+
{[...Array(3)].map((_, i) => (
|
|
49
|
+
<Skeleton key={i} className="h-32 w-full" />
|
|
50
|
+
))}
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!accessToken) {
|
|
57
|
+
return (
|
|
58
|
+
<div className="container mx-auto px-4 py-8">
|
|
59
|
+
<Breadcrumbs className="mb-6" />
|
|
60
|
+
<div className="rounded-lg border border-destructive bg-destructive/10 p-8 text-center text-sm text-destructive">
|
|
61
|
+
{t.rich("signInToView", {
|
|
62
|
+
link: (chunks) => (
|
|
63
|
+
<Link href="/auth/login?redirect=/account/orders" className="font-medium underline">
|
|
64
|
+
{chunks}
|
|
65
|
+
</Link>
|
|
66
|
+
),
|
|
67
|
+
})}
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (error) {
|
|
74
|
+
return (
|
|
75
|
+
<div className="container mx-auto px-4 py-8">
|
|
76
|
+
<Breadcrumbs className="mb-6" />
|
|
77
|
+
<div className="rounded-lg border border-red-200 bg-red-50 p-8 text-center">
|
|
78
|
+
<p className="text-red-800">{t("failedLoadOrders")}</p>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const customer = data?.customer;
|
|
85
|
+
const orders = customer?.orders?.edges.map((edge) => edge.node) ?? [];
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className="container mx-auto px-4 py-8">
|
|
89
|
+
<Breadcrumbs className="mb-6" />
|
|
90
|
+
|
|
91
|
+
<div className="mb-8">
|
|
92
|
+
<h1 className="text-3xl font-bold text-foreground">{t("orders")}</h1>
|
|
93
|
+
<p className="mt-2 text-muted-foreground">
|
|
94
|
+
{t("viewTrackOrders")}
|
|
95
|
+
</p>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<OrderHistory orders={orders} />
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import Link from "
|
|
4
|
-
import { useRouter } from "next/navigation";
|
|
3
|
+
import { Link, useRouter } from "@/i18n/navigation";
|
|
5
4
|
import { User, Package, MapPin, Settings } from "lucide-react";
|
|
6
5
|
import { Button } from "@/components/ui/button";
|
|
7
6
|
import { Card } from "@/components/ui/card";
|
|
7
|
+
import { useAuth } from "@/hooks/use-auth";
|
|
8
8
|
|
|
9
9
|
export default function AccountPage() {
|
|
10
10
|
const router = useRouter();
|
|
11
|
+
const { logout, isLoggingOut } = useAuth();
|
|
11
12
|
|
|
12
13
|
const handleLogout = async () => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const result = await logout();
|
|
15
|
+
if (result.success) {
|
|
16
|
+
router.push("/");
|
|
17
|
+
}
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
return (
|
|
@@ -97,8 +99,8 @@ export default function AccountPage() {
|
|
|
97
99
|
|
|
98
100
|
{/* Logout Button */}
|
|
99
101
|
<div className="mt-8">
|
|
100
|
-
<Button variant="destructive" onClick={handleLogout}>
|
|
101
|
-
Sign Out
|
|
102
|
+
<Button variant="destructive" onClick={handleLogout} disabled={isLoggingOut}>
|
|
103
|
+
{isLoggingOut ? "Signing out..." : "Sign Out"}
|
|
102
104
|
</Button>
|
|
103
105
|
</div>
|
|
104
106
|
</div>
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from "react";
|
|
4
|
+
import { Link } from "@/i18n/navigation";
|
|
5
|
+
import { useAuthStore, useAuthHydrated } from "@doswiftly/storefront-sdk/react";
|
|
6
|
+
import { useCustomerProfile, useCustomerUpdate } from "@/lib/graphql/hooks";
|
|
7
|
+
import { useHydrated } from "@doswiftly/storefront-sdk/react";
|
|
8
|
+
import type { CustomerInfoFields } from "@/lib/graphql/fragments";
|
|
9
|
+
import { Breadcrumbs } from "@/components/layout/breadcrumbs";
|
|
10
|
+
import { Button } from "@/components/ui/button";
|
|
11
|
+
import { Input } from "@/components/ui/input";
|
|
12
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
13
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
14
|
+
|
|
15
|
+
export default function SettingsPage() {
|
|
16
|
+
const hydrated = useHydrated();
|
|
17
|
+
const authHydrated = useAuthHydrated();
|
|
18
|
+
const accessToken = useAuthStore((s) => s.accessToken);
|
|
19
|
+
const updateAuthStore = useAuthStore((s) => s.updateCustomer);
|
|
20
|
+
|
|
21
|
+
const [firstName, setFirstName] = useState("");
|
|
22
|
+
const [lastName, setLastName] = useState("");
|
|
23
|
+
const [phone, setPhone] = useState("");
|
|
24
|
+
|
|
25
|
+
const { data: customerData, isPending } = useCustomerProfile();
|
|
26
|
+
const customer: CustomerInfoFields | undefined = customerData?.customer ?? undefined;
|
|
27
|
+
|
|
28
|
+
// Populate form when customer data loads
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (customer) {
|
|
31
|
+
setFirstName(customer.firstName || "");
|
|
32
|
+
setLastName(customer.lastName || "");
|
|
33
|
+
setPhone(customer.phone || "");
|
|
34
|
+
}
|
|
35
|
+
}, [customer]);
|
|
36
|
+
|
|
37
|
+
const updateMutation = useCustomerUpdate({
|
|
38
|
+
onSuccess: (data) => {
|
|
39
|
+
const errors = data?.customerUpdate?.userErrors;
|
|
40
|
+
if (errors && errors.length > 0) {
|
|
41
|
+
alert(errors.map((e) => e.message).join(", "));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const updated = data?.customerUpdate?.customer;
|
|
45
|
+
if (updated) {
|
|
46
|
+
updateAuthStore({
|
|
47
|
+
firstName: updated.firstName || undefined,
|
|
48
|
+
lastName: updated.lastName || undefined,
|
|
49
|
+
phone: updated.phone || undefined,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
alert("Settings saved successfully!");
|
|
53
|
+
},
|
|
54
|
+
onError: (error: Error) => {
|
|
55
|
+
alert(`Failed to save settings: ${error.message}`);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const handleSave = (e: React.FormEvent) => {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
if (!accessToken) return;
|
|
62
|
+
updateMutation.mutate({
|
|
63
|
+
firstName: firstName || undefined,
|
|
64
|
+
lastName: lastName || undefined,
|
|
65
|
+
phone: phone || undefined,
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Wait for DOM hydration AND auth persist rehydration before checking accessToken
|
|
70
|
+
if (!hydrated || !authHydrated) {
|
|
71
|
+
return (
|
|
72
|
+
<div className="container mx-auto px-4 py-8">
|
|
73
|
+
<Breadcrumbs className="mb-6" />
|
|
74
|
+
<div className="mx-auto max-w-2xl">
|
|
75
|
+
<Skeleton className="mb-8 h-10 w-64" />
|
|
76
|
+
<Skeleton className="h-96 w-full" />
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Data loading (customer query enabled only when accessToken is available)
|
|
83
|
+
if (isPending) {
|
|
84
|
+
return (
|
|
85
|
+
<div className="container mx-auto px-4 py-8">
|
|
86
|
+
<Breadcrumbs className="mb-6" />
|
|
87
|
+
<div className="mx-auto max-w-2xl">
|
|
88
|
+
<Skeleton className="mb-8 h-10 w-64" />
|
|
89
|
+
<Skeleton className="h-96 w-full" />
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!accessToken) {
|
|
96
|
+
return (
|
|
97
|
+
<div className="container mx-auto px-4 py-8">
|
|
98
|
+
<Breadcrumbs className="mb-6" />
|
|
99
|
+
<div className="mx-auto max-w-2xl">
|
|
100
|
+
<div className="rounded-lg border border-destructive bg-destructive/10 p-8 text-center text-sm text-destructive">
|
|
101
|
+
You need to{" "}
|
|
102
|
+
<Link href="/auth/login?redirect=/account/settings" className="font-medium underline">
|
|
103
|
+
sign in
|
|
104
|
+
</Link>{" "}
|
|
105
|
+
to manage your account settings.
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const email = customer?.email || "";
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<div className="container mx-auto px-4 py-8">
|
|
116
|
+
<Breadcrumbs className="mb-6" />
|
|
117
|
+
|
|
118
|
+
<div className="mx-auto max-w-2xl">
|
|
119
|
+
<h1 className="mb-8 text-3xl font-bold text-foreground">Account Settings</h1>
|
|
120
|
+
|
|
121
|
+
<div className="space-y-6">
|
|
122
|
+
<Card>
|
|
123
|
+
<CardHeader>
|
|
124
|
+
<CardTitle>Personal Information</CardTitle>
|
|
125
|
+
</CardHeader>
|
|
126
|
+
<CardContent>
|
|
127
|
+
<form onSubmit={handleSave} className="space-y-4">
|
|
128
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
129
|
+
<div className="space-y-2">
|
|
130
|
+
<label htmlFor="firstName" className="text-sm font-medium">
|
|
131
|
+
First Name
|
|
132
|
+
</label>
|
|
133
|
+
<Input
|
|
134
|
+
id="firstName"
|
|
135
|
+
value={firstName}
|
|
136
|
+
onChange={(e) => setFirstName(e.target.value)}
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
<div className="space-y-2">
|
|
140
|
+
<label htmlFor="lastName" className="text-sm font-medium">
|
|
141
|
+
Last Name
|
|
142
|
+
</label>
|
|
143
|
+
<Input
|
|
144
|
+
id="lastName"
|
|
145
|
+
value={lastName}
|
|
146
|
+
onChange={(e) => setLastName(e.target.value)}
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
<div className="space-y-2">
|
|
151
|
+
<label htmlFor="email" className="text-sm font-medium">
|
|
152
|
+
Email
|
|
153
|
+
</label>
|
|
154
|
+
<Input
|
|
155
|
+
id="email"
|
|
156
|
+
type="email"
|
|
157
|
+
value={email}
|
|
158
|
+
disabled
|
|
159
|
+
className="bg-muted"
|
|
160
|
+
/>
|
|
161
|
+
<p className="text-xs text-muted-foreground">
|
|
162
|
+
Email cannot be changed. Contact support if you need to update it.
|
|
163
|
+
</p>
|
|
164
|
+
</div>
|
|
165
|
+
<div className="space-y-2">
|
|
166
|
+
<label htmlFor="phone" className="text-sm font-medium">
|
|
167
|
+
Phone
|
|
168
|
+
</label>
|
|
169
|
+
<Input
|
|
170
|
+
id="phone"
|
|
171
|
+
type="tel"
|
|
172
|
+
value={phone}
|
|
173
|
+
onChange={(e) => setPhone(e.target.value)}
|
|
174
|
+
/>
|
|
175
|
+
</div>
|
|
176
|
+
<Button type="submit" disabled={updateMutation.isPending}>
|
|
177
|
+
{updateMutation.isPending ? "Saving..." : "Save Changes"}
|
|
178
|
+
</Button>
|
|
179
|
+
</form>
|
|
180
|
+
</CardContent>
|
|
181
|
+
</Card>
|
|
182
|
+
|
|
183
|
+
<Card>
|
|
184
|
+
<CardHeader>
|
|
185
|
+
<CardTitle>Change Password</CardTitle>
|
|
186
|
+
</CardHeader>
|
|
187
|
+
<CardContent>
|
|
188
|
+
<p className="mb-4 text-sm text-muted-foreground">
|
|
189
|
+
To change your password, we'll send a password reset link to your email.
|
|
190
|
+
</p>
|
|
191
|
+
<Button
|
|
192
|
+
variant="outline"
|
|
193
|
+
onClick={() => {
|
|
194
|
+
if (email) {
|
|
195
|
+
alert(`Password reset email sent to ${email}. Check your inbox.`);
|
|
196
|
+
}
|
|
197
|
+
}}
|
|
198
|
+
disabled={!email}
|
|
199
|
+
>
|
|
200
|
+
Send Password Reset Email
|
|
201
|
+
</Button>
|
|
202
|
+
</CardContent>
|
|
203
|
+
</Card>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
);
|
|
208
|
+
}
|
package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/forgot-password/page.tsx
RENAMED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState } from "react";
|
|
4
|
-
import
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { Link } from "@/i18n/navigation";
|
|
5
6
|
import { useMutation } from "@tanstack/react-query";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import { useExecute } from "@/lib/graphql/client";
|
|
8
|
+
import {
|
|
9
|
+
CustomerPasswordRecoverDocument,
|
|
10
|
+
type CustomerPasswordRecoverMutation,
|
|
11
|
+
} from "@/generated/graphql";
|
|
8
12
|
import { Button } from "@/components/ui/button";
|
|
9
13
|
import { Input } from "@/components/ui/input";
|
|
10
14
|
import { ArrowLeft } from "lucide-react";
|
|
11
15
|
|
|
12
16
|
export default function ForgotPasswordPage() {
|
|
17
|
+
const t = useTranslations("auth");
|
|
18
|
+
const execute = useExecute();
|
|
13
19
|
const [email, setEmail] = useState("");
|
|
14
20
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
|
15
21
|
const [error, setError] = useState("");
|
|
16
22
|
|
|
17
|
-
const client = getGraphQLClient();
|
|
18
|
-
|
|
19
23
|
const recoverMutation = useMutation({
|
|
20
24
|
mutationFn: async (email: string) => {
|
|
21
|
-
return
|
|
25
|
+
return execute<CustomerPasswordRecoverMutation>(
|
|
26
|
+
CustomerPasswordRecoverDocument.toString(),
|
|
27
|
+
{ email },
|
|
28
|
+
);
|
|
22
29
|
},
|
|
23
30
|
onSuccess: () => {
|
|
24
31
|
setIsSubmitted(true);
|
|
25
32
|
},
|
|
26
33
|
onError: () => {
|
|
27
|
-
setError("
|
|
34
|
+
setError(t("unexpectedError"));
|
|
28
35
|
},
|
|
29
36
|
});
|
|
30
37
|
|
|
@@ -54,25 +61,25 @@ export default function ForgotPasswordPage() {
|
|
|
54
61
|
/>
|
|
55
62
|
</svg>
|
|
56
63
|
</div>
|
|
57
|
-
<h1 className="text-3xl font-bold text-foreground">
|
|
64
|
+
<h1 className="text-3xl font-bold text-foreground">{t("checkYourEmail")}</h1>
|
|
58
65
|
<p className="mt-2 text-muted-foreground">
|
|
59
|
-
|
|
66
|
+
{t("resetEmailSent", { email })}
|
|
60
67
|
</p>
|
|
61
68
|
</div>
|
|
62
69
|
|
|
63
70
|
<div className="space-y-4">
|
|
64
71
|
<p className="text-sm text-muted-foreground">
|
|
65
|
-
|
|
72
|
+
{t("didntReceiveEmail")}
|
|
66
73
|
</p>
|
|
67
74
|
<Button variant="outline" onClick={() => setIsSubmitted(false)}>
|
|
68
|
-
|
|
75
|
+
{t("tryAnotherEmail")}
|
|
69
76
|
</Button>
|
|
70
77
|
<div>
|
|
71
78
|
<Link
|
|
72
79
|
href="/auth/login"
|
|
73
80
|
className="text-sm text-primary hover:underline"
|
|
74
81
|
>
|
|
75
|
-
|
|
82
|
+
{t("backToSignIn")}
|
|
76
83
|
</Link>
|
|
77
84
|
</div>
|
|
78
85
|
</div>
|
|
@@ -89,13 +96,13 @@ export default function ForgotPasswordPage() {
|
|
|
89
96
|
className="mb-8 inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground"
|
|
90
97
|
>
|
|
91
98
|
<ArrowLeft className="h-4 w-4" />
|
|
92
|
-
|
|
99
|
+
{t("backToSignIn")}
|
|
93
100
|
</Link>
|
|
94
101
|
|
|
95
102
|
<div className="mb-8">
|
|
96
|
-
<h1 className="text-3xl font-bold text-foreground">
|
|
103
|
+
<h1 className="text-3xl font-bold text-foreground">{t("resetPasswordTitle")}</h1>
|
|
97
104
|
<p className="mt-2 text-muted-foreground">
|
|
98
|
-
|
|
105
|
+
{t("resetPasswordDescription")}
|
|
99
106
|
</p>
|
|
100
107
|
</div>
|
|
101
108
|
|
|
@@ -108,7 +115,7 @@ export default function ForgotPasswordPage() {
|
|
|
108
115
|
|
|
109
116
|
<div className="space-y-2">
|
|
110
117
|
<label htmlFor="email" className="text-sm font-medium text-foreground">
|
|
111
|
-
|
|
118
|
+
{t("email")}
|
|
112
119
|
</label>
|
|
113
120
|
<Input
|
|
114
121
|
id="email"
|
|
@@ -122,7 +129,7 @@ export default function ForgotPasswordPage() {
|
|
|
122
129
|
</div>
|
|
123
130
|
|
|
124
131
|
<Button type="submit" className="w-full" disabled={recoverMutation.isPending}>
|
|
125
|
-
{recoverMutation.isPending ? "
|
|
132
|
+
{recoverMutation.isPending ? t("sending") : t("sendResetInstructions")}
|
|
126
133
|
</Button>
|
|
127
134
|
</form>
|
|
128
135
|
</div>
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { Suspense } from "react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
4
5
|
import { LoginForm } from "@/components/auth/login-form";
|
|
5
6
|
import { Spinner } from "@/components/ui/spinner";
|
|
6
7
|
|
|
7
8
|
export default function LoginPage() {
|
|
9
|
+
const t = useTranslations("auth");
|
|
10
|
+
|
|
8
11
|
return (
|
|
9
12
|
<div className="container mx-auto px-4 py-16">
|
|
10
13
|
<div className="mx-auto max-w-md">
|
|
11
14
|
<div className="mb-8 text-center">
|
|
12
|
-
<h1 className="text-3xl font-bold text-foreground">
|
|
15
|
+
<h1 className="text-3xl font-bold text-foreground">{t("signInTitle")}</h1>
|
|
13
16
|
<p className="mt-2 text-muted-foreground">
|
|
14
|
-
|
|
17
|
+
{t("signInDescription")}
|
|
15
18
|
</p>
|
|
16
19
|
</div>
|
|
17
20
|
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
3
4
|
import { RegisterForm } from "@/components/auth/register-form";
|
|
4
5
|
|
|
5
6
|
export default function RegisterPage() {
|
|
7
|
+
const t = useTranslations("auth");
|
|
8
|
+
|
|
6
9
|
return (
|
|
7
10
|
<div className="container mx-auto px-4 py-16">
|
|
8
11
|
<div className="mx-auto max-w-md">
|
|
9
12
|
<div className="mb-8 text-center">
|
|
10
|
-
<h1 className="text-3xl font-bold text-foreground">
|
|
13
|
+
<h1 className="text-3xl font-bold text-foreground">{t("signUpTitle")}</h1>
|
|
11
14
|
<p className="mt-2 text-muted-foreground">
|
|
12
|
-
|
|
15
|
+
{t("signUpDescription")}
|
|
13
16
|
</p>
|
|
14
17
|
</div>
|
|
15
18
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
2
|
+
|
|
3
|
+
export default function BlogPostLoading() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="container mx-auto max-w-3xl px-4 py-8">
|
|
6
|
+
<Skeleton className="mb-4 h-5 w-64" />
|
|
7
|
+
<Skeleton className="mb-2 h-10 w-full" />
|
|
8
|
+
<Skeleton className="mb-8 h-5 w-48" />
|
|
9
|
+
<Skeleton className="mb-8 aspect-video w-full rounded-lg" />
|
|
10
|
+
<div className="space-y-4">
|
|
11
|
+
{[...Array(8)].map((_, i) => (
|
|
12
|
+
<Skeleton key={i} className="h-4 w-full" />
|
|
13
|
+
))}
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|