@doswiftly/cli 0.1.18 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -323
- package/dist/commands/check.js +1 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +39 -20
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.js +4 -4
- package/dist/commands/sdk.js +5 -5
- package/dist/commands/sdk.js.map +1 -1
- package/dist/commands/template.js +4 -4
- package/dist/commands/template.js.map +1 -1
- package/dist/commands/types.js +5 -5
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/verify.js +2 -2
- package/dist/commands/verify.js.map +1 -1
- package/dist/lib/package-manager.d.ts +1 -1
- package/dist/lib/package-manager.js +1 -1
- package/package.json +1 -1
- package/templates/storefront-nextjs/README.md +16 -12
- package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
- package/templates/storefront-nextjs/app/account/page.tsx +2 -2
- package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
- package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
- package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
- package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
- package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
- package/templates/storefront-nextjs/app/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
- package/templates/storefront-nextjs/app/products/page.tsx +2 -2
- package/templates/storefront-nextjs/app/search/page.tsx +1 -1
- package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
- package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
- package/templates/storefront-nextjs/components/providers.tsx +1 -1
- package/templates/storefront-nextjs/lib/currency.tsx +3 -3
- package/templates/storefront-nextjs/lib/format.ts +1 -1
- package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
- package/templates/storefront-nextjs/package.dev.json +1 -1
- package/templates/storefront-nextjs/package.json +1 -1
- package/templates/storefront-nextjs/package.json.template +1 -1
- package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
- package/templates/storefront-nextjs-shadcn/CLAUDE.md +148 -35
- package/templates/storefront-nextjs-shadcn/README.md +29 -162
- package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +98 -91
- package/templates/storefront-nextjs-shadcn/app/account/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/account/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +53 -162
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/loading.tsx +60 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +36 -47
- package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +46 -29
- package/templates/storefront-nextjs-shadcn/app/account/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +108 -71
- package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
- package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
- package/templates/storefront-nextjs-shadcn/app/auth/forgot-password/page.tsx +10 -5
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/loading.tsx +17 -0
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +43 -2
- package/templates/storefront-nextjs-shadcn/app/blog/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/app/cart/loading.tsx +26 -0
- package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +6 -3
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/category-products-client.tsx +56 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +76 -59
- package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +8 -4
- package/templates/storefront-nextjs-shadcn/app/checkout/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/loading.tsx +31 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +116 -79
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/loading.tsx +19 -0
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/app/collections/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +7 -4
- package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
- package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
- package/templates/storefront-nextjs-shadcn/app/layout.tsx +46 -11
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/error.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/loading.tsx +29 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +6 -6
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +15 -61
- package/templates/storefront-nextjs-shadcn/app/products/loading.tsx +32 -0
- package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +405 -151
- package/templates/storefront-nextjs-shadcn/app/search/loading.tsx +18 -0
- package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
- package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +26 -24
- package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
- package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +9 -9
- package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +11 -37
- package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +37 -23
- package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +4 -3
- package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +8 -5
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +22 -7
- package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
- package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +3 -3
- package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +2 -1
- package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +2 -12
- package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
- package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +4 -4
- package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
- package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +33 -23
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
- package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +10 -19
- package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
- package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
- package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +69 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +84 -0
- package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +138 -0
- package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +3 -31
- package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +176 -123
- package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
- package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
- package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +19 -7
- package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
- package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +1 -7
- package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
- package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
- package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +30 -0
- package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
- package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
- package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
- package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
- package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
- package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
- package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
- package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +3 -1
- package/templates/storefront-nextjs-shadcn/generated/graphql.ts +12779 -0
- package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
- package/templates/storefront-nextjs-shadcn/hooks/index.ts +2 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +51 -19
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +13 -9
- package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
- package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
- package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +32 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +687 -632
- package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +86 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +131 -182
- package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
- package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
- package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
- package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
- package/templates/storefront-nextjs-shadcn/package.json +12 -13
- package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
- package/templates/storefront-nextjs-shadcn/proxy.ts +3 -4
- package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +41 -39
- package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
- package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
- package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
- package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
- package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
- package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
- package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
- package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
- package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
- package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
- package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
- package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
- package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
- package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
- package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
- package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
- package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
- package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
- package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
- package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
- package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
- package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
- package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
# Product Detail Page Implementation
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
This document describes the implementation of the product detail page (Task 21) following the Next.js 15+ App Router architecture with Server Components and Client Components.
|
|
6
|
-
|
|
7
|
-
## Implementation Summary
|
|
8
|
-
|
|
9
|
-
### Files Created/Modified
|
|
10
|
-
|
|
11
|
-
1. **`app/products/[slug]/page.tsx`** - Server Component (MODIFIED)
|
|
12
|
-
- Converted from Client Component to Server Component
|
|
13
|
-
- Added metadata generation for SEO
|
|
14
|
-
- Added structured data (JSON-LD) for search engines
|
|
15
|
-
- Added static params generation for top 100 products
|
|
16
|
-
- Implemented ISR with 60-second revalidation
|
|
17
|
-
|
|
18
|
-
2. **`app/products/[slug]/product-client.tsx`** - Client Component (MODIFIED)
|
|
19
|
-
- Enhanced to handle SSR hydration with currency switching
|
|
20
|
-
- Added logic to refetch product data when user's preferred currency differs from SSR currency
|
|
21
|
-
- Added `suppressHydrationWarning` to prevent hydration mismatches
|
|
22
|
-
- Maintains selected variant across currency changes
|
|
23
|
-
|
|
24
|
-
3. **`app/not-found.tsx`** - 404 Page (CREATED)
|
|
25
|
-
- Created custom 404 page for better error handling
|
|
26
|
-
- Provides helpful navigation back to the site
|
|
27
|
-
|
|
28
|
-
## Architecture
|
|
29
|
-
|
|
30
|
-
### Server Component Flow
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
1. Build Time (SSG)
|
|
34
|
-
├─ generateStaticParams() fetches top 100 products
|
|
35
|
-
├─ Pre-renders pages for each product handle
|
|
36
|
-
└─ Uses base currency (no X-Preferred-Currency header)
|
|
37
|
-
|
|
38
|
-
2. Request Time
|
|
39
|
-
├─ Server Component fetches product data (base currency)
|
|
40
|
-
├─ Generates metadata (title, description, Open Graph)
|
|
41
|
-
├─ Generates JSON-LD structured data
|
|
42
|
-
└─ Passes initial data to Client Component
|
|
43
|
-
|
|
44
|
-
3. ISR Revalidation
|
|
45
|
-
└─ Pages revalidate every 60 seconds
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Client Component Flow
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
1. Initial Render
|
|
52
|
-
├─ Receives product data from Server Component (base currency)
|
|
53
|
-
├─ Displays product with SSR data
|
|
54
|
-
└─ suppressHydrationWarning prevents mismatch
|
|
55
|
-
|
|
56
|
-
2. Currency Store Initialization
|
|
57
|
-
├─ CurrencyProvider initializes from Shop data
|
|
58
|
-
├─ Checks localStorage for saved currency
|
|
59
|
-
├─ Detects browser locale
|
|
60
|
-
└─ Sets preferred currency
|
|
61
|
-
|
|
62
|
-
3. Currency-Aware Refetch
|
|
63
|
-
├─ Compares preferred currency vs SSR currency
|
|
64
|
-
├─ If different, refetches product with new currency
|
|
65
|
-
├─ Updates prices dynamically
|
|
66
|
-
└─ Maintains selected variant
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Key Features
|
|
70
|
-
|
|
71
|
-
### 1. Metadata Generation (Requirement 13.1, 13.3)
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
export async function generateMetadata({ params }): Promise<Metadata> {
|
|
75
|
-
const data = await fetchProduct(params.slug);
|
|
76
|
-
const product = data?.product;
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
title: product.title,
|
|
80
|
-
description: product.description,
|
|
81
|
-
openGraph: {
|
|
82
|
-
title: product.title,
|
|
83
|
-
description: product.description,
|
|
84
|
-
images: [product.images[0]],
|
|
85
|
-
},
|
|
86
|
-
twitter: {
|
|
87
|
-
card: "summary_large_image",
|
|
88
|
-
// ...
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**Benefits:**
|
|
95
|
-
- Improved SEO with proper meta tags
|
|
96
|
-
- Better social media sharing with Open Graph
|
|
97
|
-
- Twitter Card support for rich previews
|
|
98
|
-
|
|
99
|
-
### 2. Structured Data (JSON-LD) (Requirement 13.3)
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
const jsonLd = {
|
|
103
|
-
"@context": "https://schema.org",
|
|
104
|
-
"@type": "Product",
|
|
105
|
-
name: product.title,
|
|
106
|
-
description: product.description,
|
|
107
|
-
image: product.images[0].url,
|
|
108
|
-
brand: { "@type": "Brand", name: product.vendor },
|
|
109
|
-
offers: {
|
|
110
|
-
"@type": "Offer",
|
|
111
|
-
price: product.priceRange.minVariantPrice.amount,
|
|
112
|
-
priceCurrency: product.priceRange.minVariantPrice.currencyCode,
|
|
113
|
-
availability: "https://schema.org/InStock",
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Benefits:**
|
|
119
|
-
- Rich snippets in search results
|
|
120
|
-
- Better product visibility in Google Shopping
|
|
121
|
-
- Improved search engine understanding
|
|
122
|
-
|
|
123
|
-
### 3. Static Params Generation (Requirement 2.2, 6.4)
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
export async function generateStaticParams() {
|
|
127
|
-
const { products } = await fetchProducts({
|
|
128
|
-
first: 100,
|
|
129
|
-
sortKey: "BEST_SELLING",
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
return products.map((product) => ({
|
|
133
|
-
slug: product.handle,
|
|
134
|
-
}));
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
**Benefits:**
|
|
139
|
-
- Pre-renders top 100 products at build time
|
|
140
|
-
- Instant page loads for popular products
|
|
141
|
-
- Reduced server load
|
|
142
|
-
- Better Core Web Vitals scores
|
|
143
|
-
|
|
144
|
-
### 4. SSR with Client Hydration (Requirement 2.2, 3.2, 6.4)
|
|
145
|
-
|
|
146
|
-
**Server Component:**
|
|
147
|
-
```typescript
|
|
148
|
-
export default async function ProductPage({ params }) {
|
|
149
|
-
const data = await fetchProduct(params.slug);
|
|
150
|
-
return <ProductClient product={data.product} />;
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
**Client Component:**
|
|
155
|
-
```typescript
|
|
156
|
-
export function ProductClient({ product: initialProduct }) {
|
|
157
|
-
const currency = useCurrencyStore((s) => s.currency);
|
|
158
|
-
const needsRefetch = currency !== initialProduct.priceRange.minVariantPrice.currencyCode;
|
|
159
|
-
|
|
160
|
-
const { data } = useProduct(initialProduct.handle, {
|
|
161
|
-
initialData: { product: initialProduct },
|
|
162
|
-
enabled: needsRefetch,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
const product = data?.product || initialProduct;
|
|
166
|
-
|
|
167
|
-
return (
|
|
168
|
-
<div suppressHydrationWarning>
|
|
169
|
-
<ProductPrice price={product.priceRange.minVariantPrice} />
|
|
170
|
-
</div>
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
**Benefits:**
|
|
176
|
-
- Fast initial render with SSR
|
|
177
|
-
- Dynamic currency switching without page reload
|
|
178
|
-
- No hydration mismatches
|
|
179
|
-
- Optimal user experience
|
|
180
|
-
|
|
181
|
-
### 5. ISR Configuration
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
export const revalidate = 60;
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
**Benefits:**
|
|
188
|
-
- Pages stay fresh with 60-second revalidation
|
|
189
|
-
- Maintains static generation benefits
|
|
190
|
-
- Automatic updates when products change
|
|
191
|
-
- No manual cache invalidation needed
|
|
192
|
-
|
|
193
|
-
## Requirements Validation
|
|
194
|
-
|
|
195
|
-
✅ **Requirement 2.2**: Server Component renders prices in base currency for SSG
|
|
196
|
-
✅ **Requirement 3.2**: Client Component renders prices in preferred currency
|
|
197
|
-
✅ **Requirement 6.4**: Clear separation between server and client data fetching
|
|
198
|
-
✅ **Requirement 13.1**: Metadata generation with title, description, Open Graph
|
|
199
|
-
✅ **Requirement 13.3**: Structured data (JSON-LD) with Product schema
|
|
200
|
-
|
|
201
|
-
## Testing Recommendations
|
|
202
|
-
|
|
203
|
-
### Manual Testing
|
|
204
|
-
|
|
205
|
-
1. **SSG Verification**
|
|
206
|
-
- Build the project: `npm run build`
|
|
207
|
-
- Check `.next/server/app/products/[slug]` for pre-rendered pages
|
|
208
|
-
- Verify top 100 products are statically generated
|
|
209
|
-
|
|
210
|
-
2. **Metadata Verification**
|
|
211
|
-
- View page source in browser
|
|
212
|
-
- Check `<head>` for meta tags
|
|
213
|
-
- Verify Open Graph tags
|
|
214
|
-
- Test social media sharing
|
|
215
|
-
|
|
216
|
-
3. **Structured Data Verification**
|
|
217
|
-
- View page source
|
|
218
|
-
- Find `<script type="application/ld+json">`
|
|
219
|
-
- Validate with Google's Rich Results Test
|
|
220
|
-
- Check schema.org compliance
|
|
221
|
-
|
|
222
|
-
4. **Currency Switching**
|
|
223
|
-
- Load product page (should show base currency)
|
|
224
|
-
- Change currency in selector
|
|
225
|
-
- Verify prices update without page reload
|
|
226
|
-
- Check no hydration warnings in console
|
|
227
|
-
|
|
228
|
-
5. **ISR Verification**
|
|
229
|
-
- Update product in backend
|
|
230
|
-
- Wait 60 seconds
|
|
231
|
-
- Refresh page
|
|
232
|
-
- Verify changes appear
|
|
233
|
-
|
|
234
|
-
### Automated Testing
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
// Example test for metadata generation
|
|
238
|
-
describe('Product Page Metadata', () => {
|
|
239
|
-
it('should generate correct metadata', async () => {
|
|
240
|
-
const metadata = await generateMetadata({ params: { slug: 'test-product' } });
|
|
241
|
-
expect(metadata.title).toBeDefined();
|
|
242
|
-
expect(metadata.description).toBeDefined();
|
|
243
|
-
expect(metadata.openGraph).toBeDefined();
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// Example test for static params
|
|
248
|
-
describe('Static Params Generation', () => {
|
|
249
|
-
it('should generate params for top products', async () => {
|
|
250
|
-
const params = await generateStaticParams();
|
|
251
|
-
expect(params.length).toBeGreaterThan(0);
|
|
252
|
-
expect(params[0]).toHaveProperty('slug');
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## Performance Considerations
|
|
258
|
-
|
|
259
|
-
1. **Static Generation**: Top 100 products are pre-rendered at build time
|
|
260
|
-
2. **ISR**: Pages revalidate every 60 seconds for fresh data
|
|
261
|
-
3. **React Cache**: Server-side requests are deduplicated within a render
|
|
262
|
-
4. **Client-side Caching**: React Query caches product data with currency in key
|
|
263
|
-
5. **Image Optimization**: Next.js Image component handles optimization
|
|
264
|
-
|
|
265
|
-
## Future Enhancements
|
|
266
|
-
|
|
267
|
-
1. **Related Products**: Add similar products section based on tags/category
|
|
268
|
-
2. **Product Reviews**: Integrate review system with structured data
|
|
269
|
-
3. **Variant Images**: Show variant-specific images when variant changes
|
|
270
|
-
4. **Breadcrumbs**: Add dynamic breadcrumbs based on product category
|
|
271
|
-
5. **Share Buttons**: Add social media share buttons
|
|
272
|
-
6. **Recently Viewed**: Track and display recently viewed products
|
|
273
|
-
|
|
274
|
-
## Troubleshooting
|
|
275
|
-
|
|
276
|
-
### Hydration Mismatch Errors
|
|
277
|
-
|
|
278
|
-
**Problem**: Console shows hydration mismatch warnings
|
|
279
|
-
**Solution**: Ensure `suppressHydrationWarning` is on price elements
|
|
280
|
-
|
|
281
|
-
### Currency Not Switching
|
|
282
|
-
|
|
283
|
-
**Problem**: Prices don't update when currency changes
|
|
284
|
-
**Solution**: Check currency store initialization and query key includes currency
|
|
285
|
-
|
|
286
|
-
### 404 Errors
|
|
287
|
-
|
|
288
|
-
**Problem**: Product pages return 404
|
|
289
|
-
**Solution**: Verify product handle matches exactly, check generateStaticParams
|
|
290
|
-
|
|
291
|
-
### Metadata Not Showing
|
|
292
|
-
|
|
293
|
-
**Problem**: Meta tags not appearing in page source
|
|
294
|
-
**Solution**: Ensure generateMetadata is async and returns Metadata object
|
|
295
|
-
|
|
296
|
-
## Conclusion
|
|
297
|
-
|
|
298
|
-
The product detail page implementation follows Next.js 15+ best practices with:
|
|
299
|
-
- Server Components for optimal performance
|
|
300
|
-
- Client Components for interactivity
|
|
301
|
-
- Proper metadata for SEO
|
|
302
|
-
- Structured data for search engines
|
|
303
|
-
- Static generation for popular products
|
|
304
|
-
- ISR for fresh data
|
|
305
|
-
- Currency-aware price display
|
|
306
|
-
|
|
307
|
-
This implementation satisfies all requirements (2.2, 3.2, 6.4, 13.1, 13.3) and provides a solid foundation for a production-ready e-commerce storefront.
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
# Theme Customization Guide
|
|
2
|
-
|
|
3
|
-
This guide explains how to customize the theme colors and appearance of your storefront.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The storefront uses a theme system based on CSS variables and Tailwind CSS v4. The theme supports:
|
|
8
|
-
- Light mode
|
|
9
|
-
- Dark mode
|
|
10
|
-
- System preference detection
|
|
11
|
-
- Smooth transitions between themes
|
|
12
|
-
- Persistent theme selection (localStorage)
|
|
13
|
-
|
|
14
|
-
## Theme Configuration
|
|
15
|
-
|
|
16
|
-
The main theme configuration is located in `lib/theme/theme-config.ts`:
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
export const themeConfig = {
|
|
20
|
-
defaultTheme: "system",
|
|
21
|
-
themes: ["light", "dark", "system"],
|
|
22
|
-
enableSystem: true,
|
|
23
|
-
disableTransitionOnChange: false,
|
|
24
|
-
storageKey: "doswiftly-theme",
|
|
25
|
-
attribute: "class",
|
|
26
|
-
colors: {
|
|
27
|
-
light: { /* ... */ },
|
|
28
|
-
dark: { /* ... */ }
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Customizing Colors
|
|
34
|
-
|
|
35
|
-
### Method 1: Update CSS Variables (Recommended)
|
|
36
|
-
|
|
37
|
-
Edit `app/globals.css` to change theme colors:
|
|
38
|
-
|
|
39
|
-
```css
|
|
40
|
-
@theme {
|
|
41
|
-
/* Light mode colors */
|
|
42
|
-
--color-primary: rgb(59 130 246); /* Change this */
|
|
43
|
-
--color-primary-foreground: rgb(255 255 255);
|
|
44
|
-
/* ... other colors */
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.dark {
|
|
48
|
-
/* Dark mode colors */
|
|
49
|
-
--color-primary: rgb(96 165 250); /* Change this */
|
|
50
|
-
--color-primary-foreground: rgb(15 23 42);
|
|
51
|
-
/* ... other colors */
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Method 2: Update Theme Config
|
|
56
|
-
|
|
57
|
-
Edit `lib/theme/theme-config.ts`:
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
export const themeConfig = {
|
|
61
|
-
// ...
|
|
62
|
-
colors: {
|
|
63
|
-
light: {
|
|
64
|
-
primary: "220 90% 56%", // HSL format
|
|
65
|
-
// ...
|
|
66
|
-
},
|
|
67
|
-
dark: {
|
|
68
|
-
primary: "220 90% 70%",
|
|
69
|
-
// ...
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Available Color Variables
|
|
76
|
-
|
|
77
|
-
The following CSS variables are available for customization:
|
|
78
|
-
|
|
79
|
-
### Core Colors
|
|
80
|
-
- `--color-background` - Main background color
|
|
81
|
-
- `--color-foreground` - Main text color
|
|
82
|
-
- `--color-primary` - Primary brand color
|
|
83
|
-
- `--color-primary-foreground` - Text on primary color
|
|
84
|
-
- `--color-secondary` - Secondary brand color
|
|
85
|
-
- `--color-secondary-foreground` - Text on secondary color
|
|
86
|
-
|
|
87
|
-
### UI Colors
|
|
88
|
-
- `--color-muted` - Muted background (for disabled states, etc.)
|
|
89
|
-
- `--color-muted-foreground` - Muted text color
|
|
90
|
-
- `--color-accent` - Accent color (for highlights)
|
|
91
|
-
- `--color-accent-foreground` - Text on accent color
|
|
92
|
-
- `--color-border` - Border color
|
|
93
|
-
- `--color-ring` - Focus ring color
|
|
94
|
-
|
|
95
|
-
### Component Colors
|
|
96
|
-
- `--color-card` - Card background
|
|
97
|
-
- `--color-card-foreground` - Card text
|
|
98
|
-
- `--color-destructive` - Error/danger color
|
|
99
|
-
- `--color-destructive-foreground` - Text on destructive color
|
|
100
|
-
|
|
101
|
-
## Brand Color Examples
|
|
102
|
-
|
|
103
|
-
### Blue Theme (Default)
|
|
104
|
-
```css
|
|
105
|
-
--color-primary: rgb(59 130 246); /* blue-500 */
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### Green Theme
|
|
109
|
-
```css
|
|
110
|
-
--color-primary: rgb(34 197 94); /* green-500 */
|
|
111
|
-
--color-accent: rgb(74 222 128); /* green-400 */
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Purple Theme
|
|
115
|
-
```css
|
|
116
|
-
--color-primary: rgb(168 85 247); /* purple-500 */
|
|
117
|
-
--color-accent: rgb(192 132 252); /* purple-400 */
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Orange Theme
|
|
121
|
-
```css
|
|
122
|
-
--color-primary: rgb(249 115 22); /* orange-500 */
|
|
123
|
-
--color-accent: rgb(251 146 60); /* orange-400 */
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Theme Switcher Components
|
|
127
|
-
|
|
128
|
-
Three theme switcher variants are available:
|
|
129
|
-
|
|
130
|
-
### 1. Simple Toggle (Default)
|
|
131
|
-
```tsx
|
|
132
|
-
import { ThemeSwitcher } from "@/components/layout/theme-switcher";
|
|
133
|
-
|
|
134
|
-
<ThemeSwitcher />
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### 2. Dropdown Menu
|
|
138
|
-
```tsx
|
|
139
|
-
import { ThemeSwitcherDropdown } from "@/components/layout/theme-switcher";
|
|
140
|
-
|
|
141
|
-
<ThemeSwitcherDropdown />
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### 3. Compact Buttons
|
|
145
|
-
```tsx
|
|
146
|
-
import { ThemeSwitcherCompact } from "@/components/layout/theme-switcher";
|
|
147
|
-
|
|
148
|
-
<ThemeSwitcherCompact showLabel />
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Programmatic Theme Control
|
|
152
|
-
|
|
153
|
-
Use the `useTheme` hook from `next-themes`:
|
|
154
|
-
|
|
155
|
-
```tsx
|
|
156
|
-
"use client";
|
|
157
|
-
|
|
158
|
-
import { useTheme } from "next-themes";
|
|
159
|
-
|
|
160
|
-
export function MyComponent() {
|
|
161
|
-
const { theme, setTheme, systemTheme } = useTheme();
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
<button onClick={() => setTheme("dark")}>
|
|
165
|
-
Switch to Dark Mode
|
|
166
|
-
</button>
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
## Disable Theme Transitions
|
|
172
|
-
|
|
173
|
-
To disable transitions when theme changes (prevents flash):
|
|
174
|
-
|
|
175
|
-
```typescript
|
|
176
|
-
// lib/theme/theme-config.ts
|
|
177
|
-
export const themeConfig = {
|
|
178
|
-
// ...
|
|
179
|
-
disableTransitionOnChange: true, // Set to true
|
|
180
|
-
}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## Custom Theme Storage
|
|
184
|
-
|
|
185
|
-
To use a different storage key:
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
// lib/theme/theme-config.ts
|
|
189
|
-
export const themeConfig = {
|
|
190
|
-
// ...
|
|
191
|
-
storageKey: "my-custom-theme-key",
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
## Force a Specific Theme
|
|
196
|
-
|
|
197
|
-
To force light or dark mode without system detection:
|
|
198
|
-
|
|
199
|
-
```typescript
|
|
200
|
-
// lib/theme/theme-config.ts
|
|
201
|
-
export const themeConfig = {
|
|
202
|
-
defaultTheme: "light", // or "dark"
|
|
203
|
-
enableSystem: false, // Disable system detection
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Testing Themes
|
|
208
|
-
|
|
209
|
-
1. **Manual Testing**: Use the theme switcher in the header
|
|
210
|
-
2. **Browser DevTools**: Toggle dark mode in DevTools
|
|
211
|
-
3. **System Preference**: Change your OS theme settings
|
|
212
|
-
|
|
213
|
-
## Troubleshooting
|
|
214
|
-
|
|
215
|
-
### Theme Flashing on Page Load
|
|
216
|
-
|
|
217
|
-
Add `suppressHydrationWarning` to the `<html>` tag (already done in `app/layout.tsx`):
|
|
218
|
-
|
|
219
|
-
```tsx
|
|
220
|
-
<html lang="en" suppressHydrationWarning>
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### Theme Not Persisting
|
|
224
|
-
|
|
225
|
-
Check that localStorage is enabled and the storage key is correct in `theme-config.ts`.
|
|
226
|
-
|
|
227
|
-
### Colors Not Updating
|
|
228
|
-
|
|
229
|
-
1. Clear browser cache
|
|
230
|
-
2. Restart dev server
|
|
231
|
-
3. Check CSS variable names match in both `globals.css` and components
|
|
232
|
-
|
|
233
|
-
## Best Practices
|
|
234
|
-
|
|
235
|
-
1. **Use CSS Variables**: Always use CSS variables instead of hardcoded colors
|
|
236
|
-
2. **Test Both Themes**: Ensure your custom colors work in both light and dark mode
|
|
237
|
-
3. **Maintain Contrast**: Ensure sufficient contrast for accessibility (WCAG AA)
|
|
238
|
-
4. **Consistent Naming**: Keep color variable names consistent across themes
|
|
239
|
-
5. **Document Changes**: Document any custom color choices for your team
|
|
240
|
-
|
|
241
|
-
## Resources
|
|
242
|
-
|
|
243
|
-
- [next-themes Documentation](https://github.com/pacocoursey/next-themes)
|
|
244
|
-
- [Tailwind CSS v4 Documentation](https://tailwindcss.com/docs)
|
|
245
|
-
- [WCAG Contrast Checker](https://webaim.org/resources/contrastchecker/)
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* CurrencyProvider - Initializes currency store with Shop data
|
|
5
|
-
*
|
|
6
|
-
* This provider:
|
|
7
|
-
* 1. Receives Shop data from server (via root layout)
|
|
8
|
-
* 2. Initializes currency store on mount
|
|
9
|
-
* 3. Handles currency detection from:
|
|
10
|
-
* - localStorage (saved preference)
|
|
11
|
-
* - Browser locale (auto-detection)
|
|
12
|
-
* - Shop base currency (fallback)
|
|
13
|
-
*
|
|
14
|
-
* The currency store manages:
|
|
15
|
-
* - User's preferred currency
|
|
16
|
-
* - Supported currencies list
|
|
17
|
-
* - Base currency for the shop
|
|
18
|
-
* - Persistence to localStorage
|
|
19
|
-
*
|
|
20
|
-
* @module storefront-nextjs/components/providers/currency-provider
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { useEffect, type ReactNode } from 'react';
|
|
24
|
-
import { useCurrencyStore, type ShopCurrencyData } from '@/stores/currency-store';
|
|
25
|
-
|
|
26
|
-
// ============================================================================
|
|
27
|
-
// TYPES
|
|
28
|
-
// ============================================================================
|
|
29
|
-
|
|
30
|
-
interface CurrencyProviderProps {
|
|
31
|
-
/**
|
|
32
|
-
* Shop data containing currency configuration
|
|
33
|
-
* Fetched from GraphQL Shop query in root layout
|
|
34
|
-
*/
|
|
35
|
-
shopData: ShopCurrencyData;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Child components
|
|
39
|
-
*/
|
|
40
|
-
children: ReactNode;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// ============================================================================
|
|
44
|
-
// COMPONENT
|
|
45
|
-
// ============================================================================
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* CurrencyProvider - Initializes currency store with Shop data
|
|
49
|
-
*
|
|
50
|
-
* This component should be placed in the root layout after fetching Shop data.
|
|
51
|
-
* It initializes the currency store once on mount, which triggers:
|
|
52
|
-
* 1. Loading saved currency from localStorage (if valid)
|
|
53
|
-
* 2. Auto-detecting currency from browser locale (if no saved preference)
|
|
54
|
-
* 3. Falling back to shop's base currency
|
|
55
|
-
*
|
|
56
|
-
* The initialization only happens once per session. Subsequent currency changes
|
|
57
|
-
* are handled by the currency store's setCurrency action.
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* ```tsx
|
|
61
|
-
* // app/layout.tsx
|
|
62
|
-
* import { fetchShop } from '@/lib/graphql/server';
|
|
63
|
-
* import { CurrencyProvider } from '@/components/providers/currency-provider';
|
|
64
|
-
*
|
|
65
|
-
* export default async function RootLayout({ children }) {
|
|
66
|
-
* const { shop } = await fetchShop();
|
|
67
|
-
*
|
|
68
|
-
* return (
|
|
69
|
-
* <html lang="en">
|
|
70
|
-
* <body>
|
|
71
|
-
* <QueryProvider>
|
|
72
|
-
* <CurrencyProvider shopData={shop}>
|
|
73
|
-
* <Header />
|
|
74
|
-
* <main>{children}</main>
|
|
75
|
-
* <Footer />
|
|
76
|
-
* </CurrencyProvider>
|
|
77
|
-
* </QueryProvider>
|
|
78
|
-
* </body>
|
|
79
|
-
* </html>
|
|
80
|
-
* );
|
|
81
|
-
* }
|
|
82
|
-
* ```
|
|
83
|
-
*
|
|
84
|
-
* @param props - Component props
|
|
85
|
-
* @param props.shopData - Shop currency configuration
|
|
86
|
-
* @param props.children - Child components to render
|
|
87
|
-
*/
|
|
88
|
-
export function CurrencyProvider({ shopData, children }: CurrencyProviderProps) {
|
|
89
|
-
const initialize = useCurrencyStore((state: any) => state.initialize);
|
|
90
|
-
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
// Initialize currency store with Shop data
|
|
93
|
-
// This will:
|
|
94
|
-
// 1. Set base currency and supported currencies
|
|
95
|
-
// 2. Restore saved currency from localStorage (if valid)
|
|
96
|
-
// 3. Auto-detect from browser locale (if no saved preference)
|
|
97
|
-
// 4. Fall back to base currency
|
|
98
|
-
initialize(shopData);
|
|
99
|
-
}, [shopData, initialize]);
|
|
100
|
-
|
|
101
|
-
// Simply render children - the store initialization happens in the background
|
|
102
|
-
return <>{children}</>;
|
|
103
|
-
}
|