@doswiftly/cli 0.1.19 → 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.
Files changed (147) hide show
  1. package/dist/commands/deploy.d.ts +20 -0
  2. package/dist/commands/deploy.d.ts.map +1 -1
  3. package/dist/commands/deploy.js +219 -6
  4. package/dist/commands/deploy.js.map +1 -1
  5. package/package.json +4 -4
  6. package/templates/storefront-minimal/.github/workflows/build-template.yml +10 -0
  7. package/templates/storefront-minimal/wrangler.toml +11 -0
  8. package/templates/storefront-nextjs/.github/workflows/build-template.yml +10 -0
  9. package/templates/storefront-nextjs/wrangler.toml +11 -0
  10. package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +10 -0
  11. package/templates/storefront-nextjs-shadcn/CLAUDE.md +29 -5
  12. package/templates/storefront-nextjs-shadcn/app/{about → [locale]/about}/page.tsx +17 -14
  13. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/addresses/page.tsx +19 -15
  14. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/error.tsx +8 -5
  15. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loyalty/page.tsx +39 -34
  16. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/page.tsx +9 -7
  17. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/tracking/page.tsx +27 -25
  18. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/page.tsx +13 -9
  19. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/page.tsx +1 -2
  20. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/settings/page.tsx +1 -1
  21. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/forgot-password/page.tsx +14 -12
  22. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/login/page.tsx +5 -2
  23. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/register/page.tsx +5 -2
  24. package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/page.tsx +1 -1
  25. package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/page.tsx +14 -10
  26. package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/[slug]/category-products-client.tsx +4 -2
  27. package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/page.tsx +13 -8
  28. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/error.tsx +1 -1
  29. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/page.tsx +228 -184
  30. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/success/[orderId]/page.tsx +36 -34
  31. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/page.tsx +5 -3
  32. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/page.tsx +13 -8
  33. package/templates/storefront-nextjs-shadcn/app/{contact → [locale]/contact}/page.tsx +24 -21
  34. package/templates/storefront-nextjs-shadcn/app/{error.tsx → [locale]/error.tsx} +13 -8
  35. package/templates/storefront-nextjs-shadcn/app/[locale]/layout.tsx +92 -0
  36. package/templates/storefront-nextjs-shadcn/app/{not-found.tsx → [locale]/not-found.tsx} +13 -18
  37. package/templates/storefront-nextjs-shadcn/app/{page.tsx → [locale]/page.tsx} +8 -4
  38. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/error.tsx +1 -1
  39. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/page.tsx +11 -8
  40. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/product-client.tsx +3 -1
  41. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/page.tsx +6 -3
  42. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/products-client.tsx +14 -10
  43. package/templates/storefront-nextjs-shadcn/app/{wishlist → [locale]/wishlist}/page.tsx +21 -25
  44. package/templates/storefront-nextjs-shadcn/app/layout.tsx +6 -68
  45. package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +25 -20
  46. package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +11 -10
  47. package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +14 -12
  48. package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +28 -18
  49. package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +10 -8
  50. package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +27 -22
  51. package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +48 -43
  52. package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +1 -1
  53. package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +1 -1
  54. package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +1 -1
  55. package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +7 -4
  56. package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +1 -1
  57. package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +7 -5
  58. package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +9 -7
  59. package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +8 -5
  60. package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +18 -15
  61. package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +15 -25
  62. package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +10 -8
  63. package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +9 -6
  64. package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +5 -3
  65. package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +8 -5
  66. package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +5 -3
  67. package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +8 -7
  68. package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +1 -1
  69. package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +1 -1
  70. package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +9 -6
  71. package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +21 -11
  72. package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +16 -13
  73. package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +53 -28
  74. package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +7 -5
  75. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +19 -15
  76. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +12 -9
  77. package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +8 -5
  78. package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +1 -1
  79. package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +12 -8
  80. package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +13 -8
  81. package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +10 -8
  82. package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +37 -12
  83. package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +5 -2
  84. package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +24 -23
  85. package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +20 -12
  86. package/templates/storefront-nextjs-shadcn/components/layout/language-switcher.tsx +54 -0
  87. package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +33 -30
  88. package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +27 -24
  89. package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +23 -24
  90. package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +6 -14
  91. package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +1 -1
  92. package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +4 -1
  93. package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +7 -4
  94. package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +5 -3
  95. package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +8 -6
  96. package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +3 -1
  97. package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +3 -7
  98. package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +26 -13
  99. package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +25 -27
  100. package/templates/storefront-nextjs-shadcn/components/providers/language-sync-provider.tsx +27 -0
  101. package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +40 -7
  102. package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +56 -70
  103. package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +7 -4
  104. package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +12 -9
  105. package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +23 -12
  106. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +7 -4
  107. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +1 -1
  108. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +2 -10
  109. package/templates/storefront-nextjs-shadcn/generated/graphql.ts +1159 -551
  110. package/templates/storefront-nextjs-shadcn/hooks/index.ts +1 -0
  111. package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +22 -249
  112. package/templates/storefront-nextjs-shadcn/hooks/use-cart-di.ts +67 -0
  113. package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +3 -3
  114. package/templates/storefront-nextjs-shadcn/i18n/navigation.ts +12 -0
  115. package/templates/storefront-nextjs-shadcn/i18n/request.ts +17 -0
  116. package/templates/storefront-nextjs-shadcn/i18n/routing.ts +17 -0
  117. package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +1 -0
  118. package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +41 -8
  119. package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +20 -18
  120. package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +2 -1
  121. package/templates/storefront-nextjs-shadcn/messages/en.json +869 -0
  122. package/templates/storefront-nextjs-shadcn/messages/pl.json +869 -0
  123. package/templates/storefront-nextjs-shadcn/next.config.ts +6 -5
  124. package/templates/storefront-nextjs-shadcn/package.json +3 -2
  125. package/templates/storefront-nextjs-shadcn/proxy.ts +115 -46
  126. package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +24 -58
  127. package/templates/storefront-nextjs-shadcn/wrangler.toml +11 -0
  128. /package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loading.tsx +0 -0
  129. /package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/loading.tsx +0 -0
  130. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/loading.tsx +0 -0
  131. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/loading.tsx +0 -0
  132. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/page.tsx +0 -0
  133. /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/[slug]/page.tsx +0 -0
  134. /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/page.tsx +0 -0
  135. /package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/loading.tsx +0 -0
  136. /package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/[slug]/loading.tsx +0 -0
  137. /package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/[slug]/page.tsx +0 -0
  138. /package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/loading.tsx +0 -0
  139. /package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/loading.tsx +0 -0
  140. /package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/loading.tsx +0 -0
  141. /package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/loading.tsx +0 -0
  142. /package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/loading.tsx +0 -0
  143. /package/templates/storefront-nextjs-shadcn/app/{returns → [locale]/returns}/page.tsx +0 -0
  144. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/loading.tsx +0 -0
  145. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/page.tsx +0 -0
  146. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/search-client.tsx +0 -0
  147. /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 Link from "next/link";
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: "Order Placed",
45
+ label: t("orderPlaced"),
44
46
  status: "completed" as const,
45
47
  date: "2024-01-15",
46
48
  },
47
49
  {
48
- label: "Processing",
50
+ label: t("processing"),
49
51
  status: "completed" as const,
50
52
  date: "2024-01-16",
51
53
  },
52
54
  {
53
- label: "Shipped",
55
+ label: t("shipped"),
54
56
  status: "completed" as const,
55
57
  date: "2024-01-17",
56
58
  },
57
59
  {
58
- label: "In Transit",
60
+ label: t("inTransit"),
59
61
  status: "current" as const,
60
62
  },
61
63
  {
62
- label: "Delivered",
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: "In Transit",
71
- description: "Package is on the way to the destination",
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: "In Transit",
79
- description: "Package arrived at sorting facility",
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: "Shipped",
87
- description: "Package has been picked up by carrier",
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: "Processing",
95
- description: "Package is being prepared for shipment",
96
- location: "Warehouse",
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: "Order Placed",
103
- description: "Order has been confirmed",
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
- Back to Order Details
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
- Track Order {trackingData.orderNumber}
126
+ {t("trackOrder", { orderNumber: trackingData.orderNumber })}
125
127
  </h1>
126
128
  <p className="mt-2 text-muted-foreground">
127
- Follow your package's journey
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
- Tracking History
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
- Carrier Information
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">Carrier:</span>
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
- Tracking Number:
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
- Track on Carrier Website
199
+ {t("trackOnCarrierWebsite")}
198
200
  </a>
199
201
  </Button>
200
202
  </div>
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
- import Link from "next/link";
3
+ import { Link } from "@/i18n/navigation";
4
+ import { useTranslations } from "next-intl";
4
5
  import { useAuthStore, useAuthHydrated } from "@doswiftly/storefront-sdk/react";
5
6
  import { useCustomer } from "@/lib/graphql/hooks";
6
7
  import { useHydrated } from "@doswiftly/storefront-sdk/react";
@@ -9,6 +10,7 @@ import { OrderHistory } from "@/components/account/order-history";
9
10
  import { Skeleton } from "@/components/ui/skeleton";
10
11
 
11
12
  export default function OrdersPage() {
13
+ const t = useTranslations("account");
12
14
  const hydrated = useHydrated();
13
15
  const authHydrated = useAuthHydrated();
14
16
  const accessToken = useAuthStore((s) => s.accessToken);
@@ -56,11 +58,13 @@ export default function OrdersPage() {
56
58
  <div className="container mx-auto px-4 py-8">
57
59
  <Breadcrumbs className="mb-6" />
58
60
  <div className="rounded-lg border border-destructive bg-destructive/10 p-8 text-center text-sm text-destructive">
59
- You need to{" "}
60
- <Link href="/auth/login?redirect=/account/orders" className="font-medium underline">
61
- sign in
62
- </Link>{" "}
63
- to view your orders.
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
+ })}
64
68
  </div>
65
69
  </div>
66
70
  );
@@ -71,7 +75,7 @@ export default function OrdersPage() {
71
75
  <div className="container mx-auto px-4 py-8">
72
76
  <Breadcrumbs className="mb-6" />
73
77
  <div className="rounded-lg border border-red-200 bg-red-50 p-8 text-center">
74
- <p className="text-red-800">Failed to load orders</p>
78
+ <p className="text-red-800">{t("failedLoadOrders")}</p>
75
79
  </div>
76
80
  </div>
77
81
  );
@@ -85,9 +89,9 @@ export default function OrdersPage() {
85
89
  <Breadcrumbs className="mb-6" />
86
90
 
87
91
  <div className="mb-8">
88
- <h1 className="text-3xl font-bold text-foreground">Order History</h1>
92
+ <h1 className="text-3xl font-bold text-foreground">{t("orders")}</h1>
89
93
  <p className="mt-2 text-muted-foreground">
90
- View and track your orders
94
+ {t("viewTrackOrders")}
91
95
  </p>
92
96
  </div>
93
97
 
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
 
3
- import Link from "next/link";
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";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useState, useEffect } from "react";
4
- import Link from "next/link";
4
+ import { Link } from "@/i18n/navigation";
5
5
  import { useAuthStore, useAuthHydrated } from "@doswiftly/storefront-sdk/react";
6
6
  import { useCustomerProfile, useCustomerUpdate } from "@/lib/graphql/hooks";
7
7
  import { useHydrated } from "@doswiftly/storefront-sdk/react";
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import { useState } from "react";
4
- import Link from "next/link";
4
+ import { useTranslations } from "next-intl";
5
+ import { Link } from "@/i18n/navigation";
5
6
  import { useMutation } from "@tanstack/react-query";
6
7
  import { useExecute } from "@/lib/graphql/client";
7
8
  import {
@@ -13,6 +14,7 @@ import { Input } from "@/components/ui/input";
13
14
  import { ArrowLeft } from "lucide-react";
14
15
 
15
16
  export default function ForgotPasswordPage() {
17
+ const t = useTranslations("auth");
16
18
  const execute = useExecute();
17
19
  const [email, setEmail] = useState("");
18
20
  const [isSubmitted, setIsSubmitted] = useState(false);
@@ -29,7 +31,7 @@ export default function ForgotPasswordPage() {
29
31
  setIsSubmitted(true);
30
32
  },
31
33
  onError: () => {
32
- setError("An error occurred. Please try again.");
34
+ setError(t("unexpectedError"));
33
35
  },
34
36
  });
35
37
 
@@ -59,25 +61,25 @@ export default function ForgotPasswordPage() {
59
61
  />
60
62
  </svg>
61
63
  </div>
62
- <h1 className="text-3xl font-bold text-foreground">Check Your Email</h1>
64
+ <h1 className="text-3xl font-bold text-foreground">{t("checkYourEmail")}</h1>
63
65
  <p className="mt-2 text-muted-foreground">
64
- We've sent password reset instructions to {email}
66
+ {t("resetEmailSent", { email })}
65
67
  </p>
66
68
  </div>
67
69
 
68
70
  <div className="space-y-4">
69
71
  <p className="text-sm text-muted-foreground">
70
- Didn't receive the email? Check your spam folder or try again.
72
+ {t("didntReceiveEmail")}
71
73
  </p>
72
74
  <Button variant="outline" onClick={() => setIsSubmitted(false)}>
73
- Try Another Email
75
+ {t("tryAnotherEmail")}
74
76
  </Button>
75
77
  <div>
76
78
  <Link
77
79
  href="/auth/login"
78
80
  className="text-sm text-primary hover:underline"
79
81
  >
80
- Back to Sign In
82
+ {t("backToSignIn")}
81
83
  </Link>
82
84
  </div>
83
85
  </div>
@@ -94,13 +96,13 @@ export default function ForgotPasswordPage() {
94
96
  className="mb-8 inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground"
95
97
  >
96
98
  <ArrowLeft className="h-4 w-4" />
97
- Back to Sign In
99
+ {t("backToSignIn")}
98
100
  </Link>
99
101
 
100
102
  <div className="mb-8">
101
- <h1 className="text-3xl font-bold text-foreground">Reset Password</h1>
103
+ <h1 className="text-3xl font-bold text-foreground">{t("resetPasswordTitle")}</h1>
102
104
  <p className="mt-2 text-muted-foreground">
103
- Enter your email address and we'll send you instructions to reset your password.
105
+ {t("resetPasswordDescription")}
104
106
  </p>
105
107
  </div>
106
108
 
@@ -113,7 +115,7 @@ export default function ForgotPasswordPage() {
113
115
 
114
116
  <div className="space-y-2">
115
117
  <label htmlFor="email" className="text-sm font-medium text-foreground">
116
- Email
118
+ {t("email")}
117
119
  </label>
118
120
  <Input
119
121
  id="email"
@@ -127,7 +129,7 @@ export default function ForgotPasswordPage() {
127
129
  </div>
128
130
 
129
131
  <Button type="submit" className="w-full" disabled={recoverMutation.isPending}>
130
- {recoverMutation.isPending ? "Sending..." : "Send Reset Instructions"}
132
+ {recoverMutation.isPending ? t("sending") : t("sendResetInstructions")}
131
133
  </Button>
132
134
  </form>
133
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">Sign In</h1>
15
+ <h1 className="text-3xl font-bold text-foreground">{t("signInTitle")}</h1>
13
16
  <p className="mt-2 text-muted-foreground">
14
- Sign in to your account to continue
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">Create Account</h1>
13
+ <h1 className="text-3xl font-bold text-foreground">{t("signUpTitle")}</h1>
11
14
  <p className="mt-2 text-muted-foreground">
12
- Sign up to start shopping
15
+ {t("signUpDescription")}
13
16
  </p>
14
17
  </div>
15
18
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { Metadata } from 'next';
8
8
  import Image from 'next/image';
9
- import Link from 'next/link';
9
+ import { Link } from '@/i18n/navigation';
10
10
  import { notFound } from 'next/navigation';
11
11
  import { Calendar, Clock, Eye, User, ChevronLeft, Share2 } from 'lucide-react';
12
12
  import { Breadcrumbs } from '@/components/layout/breadcrumbs';
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
- import Link from "next/link";
3
+ import { Link, useRouter } from "@/i18n/navigation";
4
+ import { useTranslations } from "next-intl";
4
5
  import { useCartStoreApi } from "@/stores/cart-store";
5
6
  import { useCartSync } from "@/hooks/use-cart-sync";
6
7
  import { useCartActions } from "@/hooks/use-cart-actions";
@@ -14,6 +15,9 @@ import { Button } from "@/components/ui/button";
14
15
  import { ArrowLeft, Loader2 } from "lucide-react";
15
16
 
16
17
  export default function CartPage() {
18
+ const t = useTranslations("cart");
19
+ const router = useRouter();
20
+
17
21
  // Server cart data (source of truth)
18
22
  const {
19
23
  items,
@@ -47,14 +51,14 @@ export default function CartPage() {
47
51
  }
48
52
 
49
53
  const handleCheckout = () => {
50
- window.location.href = "/checkout";
54
+ router.push("/checkout");
51
55
  };
52
56
 
53
57
  const handleApplyPromo = async (code: string) => {
54
58
  try {
55
59
  const cartId = cartStoreApi.getState().cartId;
56
60
  if (!cartId) {
57
- return { success: false, message: "Your cart is empty" };
61
+ return { success: false, message: t("empty") };
58
62
  }
59
63
 
60
64
  const result = await discountMutation.mutateAsync({
@@ -74,15 +78,15 @@ export default function CartPage() {
74
78
  if (!payload?.cart) {
75
79
  return {
76
80
  success: false,
77
- message: "Failed to apply promo code",
81
+ message: t("promoError"),
78
82
  };
79
83
  }
80
84
 
81
- return { success: true, message: "Promo code applied!" };
85
+ return { success: true, message: t("promoApplied") };
82
86
  } catch (error) {
83
87
  return {
84
88
  success: false,
85
- message: "Failed to apply promo code",
89
+ message: t("promoError"),
86
90
  };
87
91
  }
88
92
  };
@@ -104,7 +108,7 @@ export default function CartPage() {
104
108
  if (items.length === 0) {
105
109
  return (
106
110
  <div className="container mx-auto px-4 py-16">
107
- <EmptyCart onContinueShopping={() => (window.location.href = "/products")} />
111
+ <EmptyCart onContinueShopping={() => router.push("/products")} />
108
112
  </div>
109
113
  );
110
114
  }
@@ -116,11 +120,11 @@ export default function CartPage() {
116
120
  <Breadcrumbs className="mb-6" />
117
121
 
118
122
  <div className="mb-8 flex items-center justify-between">
119
- <h1 className="text-3xl font-bold text-foreground">Shopping Cart</h1>
123
+ <h1 className="text-3xl font-bold text-foreground">{t("title")}</h1>
120
124
  <Button variant="ghost" asChild>
121
125
  <Link href="/products">
122
126
  <ArrowLeft className="mr-2 h-4 w-4" />
123
- Continue Shopping
127
+ {t("continueShopping")}
124
128
  </Link>
125
129
  </Button>
126
130
  </div>
@@ -144,7 +148,7 @@ export default function CartPage() {
144
148
  {/* Summary */}
145
149
  <div className="lg:col-span-1">
146
150
  <div className="sticky top-4 space-y-4 rounded-lg border border-border bg-muted/50 p-6">
147
- <h2 className="text-lg font-semibold text-foreground">Order Summary</h2>
151
+ <h2 className="text-lg font-semibold text-foreground">{t("yourOrder")}</h2>
148
152
 
149
153
  <PromoCodeInput
150
154
  onApply={handleApplyPromo}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { useTranslations } from "next-intl";
3
4
  import { ProductGrid } from "@/components/product/product-grid";
4
5
  import { Skeleton } from "@/components/ui/skeleton";
5
6
  import { useProducts } from "@/lib/graphql/hooks";
@@ -17,6 +18,7 @@ interface CategoryProductsClientProps {
17
18
  export function CategoryProductsClient({
18
19
  categoryId,
19
20
  }: CategoryProductsClientProps) {
21
+ const t = useTranslations("product");
20
22
  const { data, isLoading, error } = useProducts({
21
23
  first: 20,
22
24
  filters: { categoryId },
@@ -38,7 +40,7 @@ export function CategoryProductsClient({
38
40
  return (
39
41
  <div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
40
42
  <p className="text-muted-foreground">
41
- Failed to load products. Please try again.
43
+ {t("failedLoadProducts")}
42
44
  </p>
43
45
  </div>
44
46
  );
@@ -50,7 +52,7 @@ export function CategoryProductsClient({
50
52
  columns={4}
51
53
  priorityCount={8}
52
54
  showBadges
53
- emptyMessage="No products in this category"
55
+ emptyMessage={t("noProductsInCategory")}
54
56
  />
55
57
  );
56
58
  }
@@ -1,18 +1,23 @@
1
1
  import { Metadata } from "next";
2
- import Link from "next/link";
2
+ import { getTranslations } from "next-intl/server";
3
+ import { Link } from "@/i18n/navigation";
3
4
  import { Card } from "@/components/ui/card";
4
5
  import { fetchCategories } from "@/lib/graphql/server";
5
6
  import type { CategoryNodeFields } from "@/lib/graphql/fragments";
6
7
 
7
- export const metadata: Metadata = {
8
- title: "Categories",
9
- description: "Browse products by category",
10
- };
8
+ export async function generateMetadata(): Promise<Metadata> {
9
+ const t = await getTranslations("categories");
10
+ return {
11
+ title: t("title"),
12
+ description: t("description"),
13
+ };
14
+ }
11
15
 
12
16
  // Enable ISR with 60 second revalidation
13
17
  export const revalidate = 60;
14
18
 
15
19
  export default async function CategoriesPage() {
20
+ const t = await getTranslations("categories");
16
21
  let categoryList: CategoryNodeFields[] = [];
17
22
 
18
23
  try {
@@ -25,15 +30,15 @@ export default async function CategoriesPage() {
25
30
  return (
26
31
  <div className="container mx-auto px-4 py-8">
27
32
  <div className="mb-8">
28
- <h1 className="text-3xl font-bold text-foreground">Categories</h1>
33
+ <h1 className="text-3xl font-bold text-foreground">{t("title")}</h1>
29
34
  <p className="mt-2 text-muted-foreground">
30
- Browse products by category
35
+ {t("description")}
31
36
  </p>
32
37
  </div>
33
38
 
34
39
  {categoryList.length === 0 ? (
35
40
  <div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
36
- <p className="text-muted-foreground">No categories available yet</p>
41
+ <p className="text-muted-foreground">{t("noCategories")}</p>
37
42
  </div>
38
43
  ) : (
39
44
  <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useEffect } from "react";
4
- import Link from "next/link";
4
+ import { Link } from "@/i18n/navigation";
5
5
  import { AlertCircle } from "lucide-react";
6
6
  import { Button } from "@/components/ui/button";
7
7
  import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";