@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.
Files changed (210) hide show
  1. package/README.md +23 -323
  2. package/dist/commands/check.js +1 -1
  3. package/dist/commands/check.js.map +1 -1
  4. package/dist/commands/deploy.d.ts.map +1 -1
  5. package/dist/commands/deploy.js +39 -20
  6. package/dist/commands/deploy.js.map +1 -1
  7. package/dist/commands/doctor.js +3 -3
  8. package/dist/commands/doctor.js.map +1 -1
  9. package/dist/commands/init.js +4 -4
  10. package/dist/commands/sdk.js +5 -5
  11. package/dist/commands/sdk.js.map +1 -1
  12. package/dist/commands/template.js +4 -4
  13. package/dist/commands/template.js.map +1 -1
  14. package/dist/commands/types.js +5 -5
  15. package/dist/commands/types.js.map +1 -1
  16. package/dist/commands/verify.js +2 -2
  17. package/dist/commands/verify.js.map +1 -1
  18. package/dist/lib/package-manager.d.ts +1 -1
  19. package/dist/lib/package-manager.js +1 -1
  20. package/package.json +1 -1
  21. package/templates/storefront-nextjs/README.md +16 -12
  22. package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
  23. package/templates/storefront-nextjs/app/account/page.tsx +2 -2
  24. package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
  25. package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
  26. package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
  27. package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
  28. package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
  29. package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
  30. package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
  31. package/templates/storefront-nextjs/app/page.tsx +1 -1
  32. package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
  33. package/templates/storefront-nextjs/app/products/page.tsx +2 -2
  34. package/templates/storefront-nextjs/app/search/page.tsx +1 -1
  35. package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
  36. package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
  37. package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
  38. package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
  39. package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
  40. package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
  41. package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
  42. package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
  43. package/templates/storefront-nextjs/components/providers.tsx +1 -1
  44. package/templates/storefront-nextjs/lib/currency.tsx +3 -3
  45. package/templates/storefront-nextjs/lib/format.ts +1 -1
  46. package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
  47. package/templates/storefront-nextjs/package.dev.json +1 -1
  48. package/templates/storefront-nextjs/package.json +1 -1
  49. package/templates/storefront-nextjs/package.json.template +1 -1
  50. package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
  51. package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
  52. package/templates/storefront-nextjs-shadcn/CLAUDE.md +148 -35
  53. package/templates/storefront-nextjs-shadcn/README.md +29 -162
  54. package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +98 -91
  55. package/templates/storefront-nextjs-shadcn/app/account/error.tsx +43 -0
  56. package/templates/storefront-nextjs-shadcn/app/account/loading.tsx +19 -0
  57. package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +53 -162
  58. package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/loading.tsx +60 -0
  59. package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +36 -47
  60. package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +46 -29
  61. package/templates/storefront-nextjs-shadcn/app/account/page.tsx +8 -5
  62. package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +108 -71
  63. package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
  64. package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
  65. package/templates/storefront-nextjs-shadcn/app/auth/forgot-password/page.tsx +10 -5
  66. package/templates/storefront-nextjs-shadcn/app/blog/[slug]/loading.tsx +17 -0
  67. package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +43 -2
  68. package/templates/storefront-nextjs-shadcn/app/blog/loading.tsx +19 -0
  69. package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +2 -1
  70. package/templates/storefront-nextjs-shadcn/app/cart/loading.tsx +26 -0
  71. package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +6 -3
  72. package/templates/storefront-nextjs-shadcn/app/categories/[slug]/category-products-client.tsx +56 -0
  73. package/templates/storefront-nextjs-shadcn/app/categories/[slug]/loading.tsx +32 -0
  74. package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +76 -59
  75. package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +8 -4
  76. package/templates/storefront-nextjs-shadcn/app/checkout/error.tsx +43 -0
  77. package/templates/storefront-nextjs-shadcn/app/checkout/loading.tsx +31 -0
  78. package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +116 -79
  79. package/templates/storefront-nextjs-shadcn/app/collections/[handle]/loading.tsx +19 -0
  80. package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +1 -1
  81. package/templates/storefront-nextjs-shadcn/app/collections/loading.tsx +18 -0
  82. package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +7 -4
  83. package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
  84. package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
  85. package/templates/storefront-nextjs-shadcn/app/layout.tsx +46 -11
  86. package/templates/storefront-nextjs-shadcn/app/products/[slug]/error.tsx +43 -0
  87. package/templates/storefront-nextjs-shadcn/app/products/[slug]/loading.tsx +29 -0
  88. package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +6 -6
  89. package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +15 -61
  90. package/templates/storefront-nextjs-shadcn/app/products/loading.tsx +32 -0
  91. package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +405 -151
  92. package/templates/storefront-nextjs-shadcn/app/search/loading.tsx +18 -0
  93. package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +8 -5
  94. package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
  95. package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
  96. package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +3 -1
  97. package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +26 -24
  98. package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
  99. package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +9 -9
  100. package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +11 -37
  101. package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +37 -23
  102. package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +4 -3
  103. package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +8 -5
  104. package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +1 -1
  105. package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
  106. package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +1 -1
  107. package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +22 -7
  108. package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +2 -2
  109. package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +1 -1
  110. package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +2 -2
  111. package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
  112. package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +1 -1
  113. package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +3 -3
  114. package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
  115. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +2 -2
  116. package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +2 -1
  117. package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
  118. package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +2 -12
  119. package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
  120. package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
  121. package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +4 -4
  122. package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
  123. package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +2 -2
  124. package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +33 -23
  125. package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
  126. package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
  127. package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +10 -19
  128. package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
  129. package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
  130. package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
  131. package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +3 -1
  132. package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +69 -0
  133. package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +84 -0
  134. package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +138 -0
  135. package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
  136. package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
  137. package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +3 -31
  138. package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
  139. package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +176 -123
  140. package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
  141. package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +2 -2
  142. package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
  143. package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
  144. package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +19 -7
  145. package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
  146. package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
  147. package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
  148. package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +1 -7
  149. package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
  150. package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
  151. package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
  152. package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +30 -0
  153. package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
  154. package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
  155. package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +3 -2
  156. package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
  157. package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
  158. package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
  159. package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
  160. package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
  161. package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
  162. package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
  163. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +3 -1
  164. package/templates/storefront-nextjs-shadcn/generated/graphql.ts +12779 -0
  165. package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
  166. package/templates/storefront-nextjs-shadcn/hooks/index.ts +2 -0
  167. package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
  168. package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
  169. package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +51 -19
  170. package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +13 -9
  171. package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
  172. package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
  173. package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +32 -0
  174. package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
  175. package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +687 -632
  176. package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +86 -0
  177. package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +131 -182
  178. package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
  179. package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
  180. package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
  181. package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
  182. package/templates/storefront-nextjs-shadcn/package.json +12 -13
  183. package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
  184. package/templates/storefront-nextjs-shadcn/proxy.ts +3 -4
  185. package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +41 -39
  186. package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
  187. package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
  188. package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
  189. package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
  190. package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
  191. package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
  192. package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
  193. package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
  194. package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
  195. package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
  196. package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
  197. package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
  198. package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
  199. package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
  200. package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
  201. package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
  202. package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
  203. package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
  204. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
  205. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
  206. package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
  207. package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
  208. package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
  209. package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
  210. package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
@@ -0,0 +1,31 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function CheckoutLoading() {
4
+ return (
5
+ <div className="container mx-auto px-4 py-8">
6
+ <Skeleton className="mb-8 h-10 w-40" />
7
+ <div className="grid gap-8 lg:grid-cols-5">
8
+ {/* Checkout form */}
9
+ <div className="space-y-6 lg:col-span-3">
10
+ <Skeleton className="h-6 w-48" />
11
+ <div className="space-y-4">
12
+ <div className="grid grid-cols-2 gap-4">
13
+ <Skeleton className="h-10 w-full" />
14
+ <Skeleton className="h-10 w-full" />
15
+ </div>
16
+ <Skeleton className="h-10 w-full" />
17
+ <Skeleton className="h-10 w-full" />
18
+ <div className="grid grid-cols-2 gap-4">
19
+ <Skeleton className="h-10 w-full" />
20
+ <Skeleton className="h-10 w-full" />
21
+ </div>
22
+ </div>
23
+ </div>
24
+ {/* Order summary */}
25
+ <div className="lg:col-span-2">
26
+ <Skeleton className="h-80 w-full rounded-lg" />
27
+ </div>
28
+ </div>
29
+ </div>
30
+ );
31
+ }
@@ -3,6 +3,7 @@
3
3
  import { useState, useEffect } from "react";
4
4
  import { useRouter } from "next/navigation";
5
5
  import Link from "next/link";
6
+ import { StorefrontError } from "@doswiftly/storefront-sdk";
6
7
  import { useCartStore } from "@/stores/cart-store";
7
8
  import { useCartSync } from "@/hooks/use-cart-sync";
8
9
  import {
@@ -18,7 +19,7 @@ import {
18
19
  useCheckoutComplete,
19
20
  useCheckout,
20
21
  } from "@/lib/graphql/hooks";
21
- import { formatAmount } from "@/lib/format";
22
+ import { formatAmount } from "@doswiftly/storefront-sdk";
22
23
  import { Button } from "@/components/ui/button";
23
24
  import { Input } from "@/components/ui/input";
24
25
  import { Label } from "@/components/ui/label";
@@ -345,8 +346,8 @@ export default function CheckoutPage() {
345
346
 
346
347
  // Sync discount codes from checkout (transferred from cart) to form state
347
348
  useEffect(() => {
348
- if (checkout?.discountCodes?.length > 0 && !formState.appliedDiscountCode) {
349
- const applicableCode = checkout.discountCodes.find((dc: any) => dc.applicable);
349
+ if ((checkout?.discountCodes?.length ?? 0) > 0 && !formState.appliedDiscountCode) {
350
+ const applicableCode = checkout?.discountCodes?.find((dc) => dc.applicable);
350
351
  if (applicableCode) {
351
352
  setFormState((prev) => ({
352
353
  ...prev,
@@ -429,8 +430,9 @@ export default function CheckoutPage() {
429
430
  }
430
431
 
431
432
  setCurrentStep(allGiftCards ? "payment" : "shipping");
432
- } catch (error: any) {
433
- toast.error(error.message || "Nie udało się przetworzyć danych kontaktowych");
433
+ } catch (error: unknown) {
434
+ const message = error instanceof Error ? error.message : "Nie udało się przetworzyć danych kontaktowych";
435
+ toast.error(message);
434
436
  }
435
437
  };
436
438
 
@@ -510,8 +512,9 @@ export default function CheckoutPage() {
510
512
  // Refetch checkout to get shipping rates
511
513
  await refetchCheckout();
512
514
  setCurrentStep("delivery");
513
- } catch (error: any) {
514
- toast.error(error.message || "Nie udało się zaktualizować adresu");
515
+ } catch (error: unknown) {
516
+ const message = error instanceof Error ? error.message : "Nie udało się zaktualizować adresu";
517
+ toast.error(message);
515
518
  }
516
519
  };
517
520
 
@@ -544,8 +547,9 @@ export default function CheckoutPage() {
544
547
 
545
548
  await refetchCheckout();
546
549
  setCurrentStep("payment");
547
- } catch (error: any) {
548
- toast.error(error.message || "Nie udało się wybrać metody dostawy");
550
+ } catch (error: unknown) {
551
+ const message = error instanceof Error ? error.message : "Nie udało się wybrać metody dostawy";
552
+ toast.error(message);
549
553
  }
550
554
  };
551
555
 
@@ -556,10 +560,10 @@ export default function CheckoutPage() {
556
560
  const handlePaymentMethodSelect = (paymentMethodId: string) => {
557
561
  // Validate payment method supports current currency
558
562
  const selectedMethod = checkout?.availablePaymentMethods?.find(
559
- (pm: any) => pm.id === paymentMethodId
563
+ (pm) => pm.id === paymentMethodId
560
564
  );
561
565
 
562
- if (selectedMethod?.supportedCurrencies?.length > 0) {
566
+ if (selectedMethod?.supportedCurrencies && selectedMethod.supportedCurrencies.length > 0) {
563
567
  const supportsCurrency = selectedMethod.supportedCurrencies.includes(currencyCode);
564
568
  if (!supportsCurrency) {
565
569
  setErrors({
@@ -581,7 +585,7 @@ export default function CheckoutPage() {
581
585
 
582
586
  // Validate selected payment method still exists and is valid
583
587
  const selectedMethod = checkout?.availablePaymentMethods?.find(
584
- (pm: any) => pm.id === formState.selectedPaymentMethodId
588
+ (pm) => pm.id === formState.selectedPaymentMethodId
585
589
  );
586
590
 
587
591
  if (!selectedMethod) {
@@ -591,7 +595,7 @@ export default function CheckoutPage() {
591
595
  }
592
596
 
593
597
  // Validate currency support
594
- if (selectedMethod.supportedCurrencies?.length > 0) {
598
+ if (selectedMethod.supportedCurrencies && selectedMethod.supportedCurrencies.length > 0) {
595
599
  const supportsCurrency = selectedMethod.supportedCurrencies.includes(currencyCode);
596
600
  if (!supportsCurrency) {
597
601
  setErrors({
@@ -644,8 +648,9 @@ export default function CheckoutPage() {
644
648
  }));
645
649
  await refetchCheckout();
646
650
  toast.success("Kod rabatowy został zastosowany");
647
- } catch (error: any) {
648
- toast.error(error.message || "Nie udało się zastosować kodu rabatowego");
651
+ } catch (error: unknown) {
652
+ const message = error instanceof Error ? error.message : "Nie udało się zastosować kodu rabatowego";
653
+ toast.error(message);
649
654
  }
650
655
  };
651
656
 
@@ -671,8 +676,9 @@ export default function CheckoutPage() {
671
676
  }));
672
677
  await refetchCheckout();
673
678
  toast.success("Kod rabatowy został usunięty");
674
- } catch (error: any) {
675
- toast.error(error.message || "Nie udało się usunąć kodu rabatowego");
679
+ } catch (error: unknown) {
680
+ const message = error instanceof Error ? error.message : "Nie udało się usunąć kodu rabatowego";
681
+ toast.error(message);
676
682
  }
677
683
  };
678
684
 
@@ -703,10 +709,10 @@ export default function CheckoutPage() {
703
709
  GIFT_CARD_NOT_FOUND: "Nie znaleziono karty podarunkowej o podanym kodzie",
704
710
  GIFT_CARD_EXPIRED: "Ta karta podarunkowa wygasła",
705
711
  GIFT_CARD_DISABLED: "Ta karta podarunkowa jest wyłączona",
706
- GIFT_CARD_NO_BALANCE: "Ta karta podarunkowa nie ma dostępnego salda",
707
- GIFT_CARD_ALREADY_APPLIED: "Ta karta jest już zastosowana",
712
+ GIFT_CARD_DEPLETED: "Ta karta podarunkowa nie ma dostępnego salda",
713
+ GIFT_CARD_UNUSABLE: "Ta karta jest już zastosowana",
708
714
  };
709
- toast.error(errorMessages[error.code] || error.message);
715
+ toast.error((error.code && errorMessages[error.code]) || error.message);
710
716
  return;
711
717
  }
712
718
 
@@ -716,8 +722,9 @@ export default function CheckoutPage() {
716
722
  }));
717
723
  await refetchCheckout();
718
724
  toast.success("Karta podarunkowa została zastosowana");
719
- } catch (error: any) {
720
- toast.error(error.message || "Nie udało się zastosować karty podarunkowej");
725
+ } catch (error: unknown) {
726
+ const message = error instanceof Error ? error.message : "Nie udało się zastosować karty podarunkowej";
727
+ toast.error(message);
721
728
  }
722
729
  };
723
730
 
@@ -739,8 +746,9 @@ export default function CheckoutPage() {
739
746
 
740
747
  await refetchCheckout();
741
748
  toast.success("Karta podarunkowa została usunięta");
742
- } catch (error: any) {
743
- toast.error(error.message || "Nie udało się usunąć karty podarunkowej");
749
+ } catch (error: unknown) {
750
+ const message = error instanceof Error ? error.message : "Nie udało się usunąć karty podarunkowej";
751
+ toast.error(message);
744
752
  }
745
753
  };
746
754
 
@@ -781,27 +789,20 @@ export default function CheckoutPage() {
781
789
  const errorMessage = error.message;
782
790
 
783
791
  // Handle specific payment-related error codes
784
- switch (errorCode) {
792
+ // Cast to string since backend may return codes not in the generated enum
793
+ const codeStr = errorCode as string | null | undefined;
794
+ switch (codeStr) {
785
795
  case "INVALID_PAYMENT_METHOD":
786
- case "PAYMENT_METHOD_NOT_FOUND":
796
+ case "NO_PAYMENT_METHODS":
787
797
  setErrors({ payment: "Wybrana metoda płatności jest niedostępna. Wybierz inną metodę." });
788
798
  setFormState((prev) => ({ ...prev, selectedPaymentMethodId: null }));
789
799
  setCurrentStep("payment");
790
800
  toast.error("Metoda płatności jest niedostępna");
791
801
  break;
792
- case "PAYMENT_METHOD_CURRENCY_NOT_SUPPORTED":
793
- setErrors({ payment: `Metoda płatności nie obsługuje wybranej waluty (${currencyCode}).` });
794
- setCurrentStep("payment");
795
- toast.error("Waluta nie jest obsługiwana przez tę metodę płatności");
796
- break;
797
- case "PAYMENT_DECLINED":
798
- toast.error("Płatność została odrzucona. Spróbuj ponownie lub wybierz inną metodę.");
799
- setCurrentStep("payment");
800
- break;
801
- case "CHECKOUT_EXPIRED":
802
+ case "ALREADY_COMPLETED":
802
803
  toast.error("Sesja checkout wygasła. Proszę odświeżyć stronę i spróbować ponownie.");
803
804
  break;
804
- case "INVENTORY_NOT_AVAILABLE":
805
+ case "NOT_ENOUGH_IN_STOCK":
805
806
  toast.error("Niektóre produkty są niedostępne. Sprawdź swój koszyk.");
806
807
  break;
807
808
  default:
@@ -821,7 +822,7 @@ export default function CheckoutPage() {
821
822
  const orderId = completeResult.checkoutComplete.order.id;
822
823
  const paymentType = formState.selectedPaymentMethodId
823
824
  ? checkout?.availablePaymentMethods?.find(
824
- (pm: any) => pm.id === formState.selectedPaymentMethodId
825
+ (pm) => pm.id === formState.selectedPaymentMethodId
825
826
  )?.type
826
827
  : null;
827
828
 
@@ -832,8 +833,9 @@ export default function CheckoutPage() {
832
833
  // Fallback: no payment URL and no order - show error
833
834
  toast.error("Wystąpił nieoczekiwany błąd. Skontaktuj się z obsługą.");
834
835
  }
835
- } catch (error: any) {
836
- toast.error(error.message || "Nie udało się sfinalizować zamówienia");
836
+ } catch (error: unknown) {
837
+ const message = error instanceof Error ? error.message : "Nie udało się sfinalizować zamówienia";
838
+ toast.error(message);
837
839
  }
838
840
  };
839
841
 
@@ -1283,7 +1285,7 @@ export default function CheckoutPage() {
1283
1285
  {/* PaymentStep component handles payment method selection */}
1284
1286
  <PaymentStep
1285
1287
  availablePaymentMethods={(checkout.availablePaymentMethods || []).map(
1286
- (pm: any): PaymentMethod => ({
1288
+ (pm): PaymentMethod => ({
1287
1289
  id: pm.id,
1288
1290
  name: pm.name,
1289
1291
  provider: pm.provider,
@@ -1417,7 +1419,7 @@ export default function CheckoutPage() {
1417
1419
  {formState.selectedPaymentMethodId && (
1418
1420
  <p className="text-sm text-muted-foreground">
1419
1421
  {checkout.availablePaymentMethods?.find(
1420
- (pm: any) => pm.id === formState.selectedPaymentMethodId
1422
+ (pm) => pm.id === formState.selectedPaymentMethodId
1421
1423
  )?.name || "Wybrana metoda płatności"}
1422
1424
  </p>
1423
1425
  )}
@@ -1497,43 +1499,78 @@ export default function CheckoutPage() {
1497
1499
  <CardContent className="space-y-4">
1498
1500
  {/* Line Items */}
1499
1501
  <div className="space-y-3">
1500
- {(checkout?.lineItems || items).map((item: any) => (
1501
- <div
1502
- key={item.id || item.lineId || item.variantId}
1503
- className="flex gap-3 text-sm"
1504
- >
1505
- <div className="relative h-16 w-16 flex-shrink-0 overflow-hidden rounded-md border bg-muted">
1506
- {item.image?.url ? (
1507
- <img
1508
- src={item.image.url}
1509
- alt={item.title || item.productTitle}
1510
- className="h-full w-full object-cover"
1511
- />
1512
- ) : (
1513
- <div className="flex h-full w-full items-center justify-center">
1514
- <Package className="h-6 w-6 text-muted-foreground" />
1502
+ {(checkout?.lineItems ?? []).length > 0
1503
+ ? checkout!.lineItems.map((item) => (
1504
+ <div
1505
+ key={item.id}
1506
+ className="flex gap-3 text-sm"
1507
+ >
1508
+ <div className="relative h-16 w-16 flex-shrink-0 overflow-hidden rounded-md border bg-muted">
1509
+ {item.image?.url ? (
1510
+ <img
1511
+ src={item.image.url}
1512
+ alt={item.title}
1513
+ className="h-full w-full object-cover"
1514
+ />
1515
+ ) : (
1516
+ <div className="flex h-full w-full items-center justify-center">
1517
+ <Package className="h-6 w-6 text-muted-foreground" />
1518
+ </div>
1519
+ )}
1520
+ <span className="absolute -right-2 -top-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground">
1521
+ {item.quantity}
1522
+ </span>
1515
1523
  </div>
1516
- )}
1517
- <span className="absolute -right-2 -top-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground">
1518
- {item.quantity}
1519
- </span>
1520
- </div>
1521
- <div className="flex-1">
1522
- <p className="font-medium line-clamp-2">
1523
- {item.title || item.productTitle}
1524
- </p>
1525
- {item.variantTitle && item.variantTitle !== "Default" && (
1526
- <p className="text-xs text-muted-foreground">{item.variantTitle}</p>
1527
- )}
1528
- </div>
1529
- <p className="font-medium">
1530
- {formatPrice(
1531
- item.totalPrice?.amount ||
1532
- parseFloat(item.price.amount) * item.quantity
1533
- )}
1534
- </p>
1535
- </div>
1536
- ))}
1524
+ <div className="flex-1">
1525
+ <p className="font-medium line-clamp-2">
1526
+ {item.title}
1527
+ </p>
1528
+ {item.variantTitle && item.variantTitle !== "Default" && (
1529
+ <p className="text-xs text-muted-foreground">{item.variantTitle}</p>
1530
+ )}
1531
+ </div>
1532
+ <p className="font-medium">
1533
+ {formatPrice(item.totalPrice.amount)}
1534
+ </p>
1535
+ </div>
1536
+ ))
1537
+ : items.map((item) => (
1538
+ <div
1539
+ key={item.lineId}
1540
+ className="flex gap-3 text-sm"
1541
+ >
1542
+ <div className="relative h-16 w-16 flex-shrink-0 overflow-hidden rounded-md border bg-muted">
1543
+ {item.image?.url ? (
1544
+ <img
1545
+ src={item.image.url}
1546
+ alt={item.productTitle}
1547
+ className="h-full w-full object-cover"
1548
+ />
1549
+ ) : (
1550
+ <div className="flex h-full w-full items-center justify-center">
1551
+ <Package className="h-6 w-6 text-muted-foreground" />
1552
+ </div>
1553
+ )}
1554
+ <span className="absolute -right-2 -top-2 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground">
1555
+ {item.quantity}
1556
+ </span>
1557
+ </div>
1558
+ <div className="flex-1">
1559
+ <p className="font-medium line-clamp-2">
1560
+ {item.productTitle}
1561
+ </p>
1562
+ {item.variantTitle && item.variantTitle !== "Default" && (
1563
+ <p className="text-xs text-muted-foreground">{item.variantTitle}</p>
1564
+ )}
1565
+ </div>
1566
+ <p className="font-medium">
1567
+ {formatPrice(
1568
+ parseFloat(item.price.amount) * item.quantity
1569
+ )}
1570
+ </p>
1571
+ </div>
1572
+ ))
1573
+ }
1537
1574
  </div>
1538
1575
 
1539
1576
  {/* Discount Code */}
@@ -1591,7 +1628,7 @@ export default function CheckoutPage() {
1591
1628
  {/* Applied Gift Cards */}
1592
1629
  {checkout?.appliedGiftCards && checkout.appliedGiftCards.length > 0 && (
1593
1630
  <div className="space-y-2">
1594
- {checkout.appliedGiftCards.map((giftCard: any) => (
1631
+ {checkout.appliedGiftCards.map((giftCard) => (
1595
1632
  <div
1596
1633
  key={giftCard.lastCharacters}
1597
1634
  className="flex items-center justify-between rounded-lg bg-purple-50 p-3 dark:bg-purple-950"
@@ -0,0 +1,19 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function CollectionLoading() {
4
+ return (
5
+ <div className="container mx-auto px-4 py-8">
6
+ <Skeleton className="mb-2 h-10 w-64" />
7
+ <Skeleton className="mb-8 h-5 w-96" />
8
+ <div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
9
+ {[...Array(8)].map((_, i) => (
10
+ <div key={i} className="space-y-3">
11
+ <Skeleton className="aspect-square w-full rounded-lg" />
12
+ <Skeleton className="h-4 w-3/4" />
13
+ <Skeleton className="h-4 w-1/2" />
14
+ </div>
15
+ ))}
16
+ </div>
17
+ </div>
18
+ );
19
+ }
@@ -14,7 +14,7 @@ export default function CollectionPage() {
14
14
  const { data, isLoading, error } = useCollection(handle);
15
15
 
16
16
  const collection = data?.collection;
17
- const products = collection?.products?.edges?.map((edge: any) => edge.node) ?? [];
17
+ const products = collection?.products?.edges?.map((edge) => edge.node) ?? [];
18
18
 
19
19
  if (isLoading) {
20
20
  return (
@@ -0,0 +1,18 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function CollectionsLoading() {
4
+ return (
5
+ <div className="container mx-auto px-4 py-8">
6
+ <Skeleton className="mb-8 h-10 w-48" />
7
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
8
+ {[...Array(6)].map((_, i) => (
9
+ <div key={i} className="space-y-3">
10
+ <Skeleton className="aspect-[3/2] w-full rounded-lg" />
11
+ <Skeleton className="h-5 w-3/4" />
12
+ <Skeleton className="h-4 w-1/2" />
13
+ </div>
14
+ ))}
15
+ </div>
16
+ </div>
17
+ );
18
+ }
@@ -12,11 +12,14 @@ export const metadata: Metadata = {
12
12
  export const revalidate = 60;
13
13
 
14
14
  export default async function CollectionsPage() {
15
- // Fetch collections from GraphQL API (already normalized to flat array)
16
- const { collections } = await fetchCollections({ first: 20 });
15
+ let collectionList: Awaited<ReturnType<typeof fetchCollections>>['collections'] = [];
17
16
 
18
- // Defensive check for empty/undefined response
19
- const collectionList = collections || [];
17
+ try {
18
+ const { collections } = await fetchCollections({ first: 20 });
19
+ collectionList = collections || [];
20
+ } catch (error) {
21
+ console.error('[CollectionsPage] Failed to fetch collections:', error instanceof Error ? error.message : error);
22
+ }
20
23
 
21
24
  return (
22
25
  <div className="container mx-auto px-4 py-8">
@@ -0,0 +1,117 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * GlobalError — catches errors from root layout (where error.tsx cannot reach).
5
+ *
6
+ * This replaces the entire <html> document, so it must include its own
7
+ * <html> and <body> tags. No providers, no Header/Footer — just a
8
+ * self-contained error page.
9
+ *
10
+ * Next.js docs: https://nextjs.org/docs/app/api-reference/file-conventions/error#global-errorjs
11
+ */
12
+
13
+ import { useEffect } from 'react';
14
+
15
+ interface GlobalErrorProps {
16
+ error: Error & { digest?: string };
17
+ reset: () => void;
18
+ }
19
+
20
+ export default function GlobalError({ error, reset }: GlobalErrorProps) {
21
+ useEffect(() => {
22
+ console.error('[GlobalError]', error);
23
+ }, [error]);
24
+
25
+ return (
26
+ <html lang="pl">
27
+ <body
28
+ style={{
29
+ margin: 0,
30
+ fontFamily:
31
+ '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
32
+ backgroundColor: '#fafafa',
33
+ color: '#1e293b',
34
+ display: 'flex',
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ minHeight: '100vh',
38
+ }}
39
+ >
40
+ <div
41
+ style={{
42
+ maxWidth: '28rem',
43
+ width: '100%',
44
+ padding: '2rem',
45
+ textAlign: 'center',
46
+ }}
47
+ >
48
+ <div
49
+ style={{
50
+ width: '4rem',
51
+ height: '4rem',
52
+ margin: '0 auto 1.5rem',
53
+ borderRadius: '50%',
54
+ backgroundColor: '#fef2f2',
55
+ display: 'flex',
56
+ alignItems: 'center',
57
+ justifyContent: 'center',
58
+ fontSize: '1.5rem',
59
+ }}
60
+ >
61
+ !
62
+ </div>
63
+
64
+ <h1 style={{ fontSize: '1.5rem', fontWeight: 600, margin: '0 0 0.5rem' }}>
65
+ Serwer tymczasowo niedostępny
66
+ </h1>
67
+
68
+ <p style={{ color: '#64748b', margin: '0 0 2rem', lineHeight: 1.6 }}>
69
+ Nie udało się załadować strony. Serwer może być tymczasowo niedostępny.
70
+ Spróbuj odświeżyć stronę za chwilę.
71
+ </p>
72
+
73
+ {process.env.NODE_ENV === 'development' && (
74
+ <div
75
+ style={{
76
+ backgroundColor: '#f1f5f9',
77
+ borderRadius: '0.5rem',
78
+ padding: '0.75rem 1rem',
79
+ marginBottom: '1.5rem',
80
+ textAlign: 'left',
81
+ fontSize: '0.75rem',
82
+ wordBreak: 'break-word',
83
+ }}
84
+ >
85
+ <strong style={{ color: '#ef4444' }}>{error.message}</strong>
86
+ {error.digest && (
87
+ <p style={{ color: '#64748b', margin: '0.25rem 0 0' }}>
88
+ Digest: {error.digest}
89
+ </p>
90
+ )}
91
+ </div>
92
+ )}
93
+
94
+ <button
95
+ onClick={reset}
96
+ style={{
97
+ display: 'inline-flex',
98
+ alignItems: 'center',
99
+ justifyContent: 'center',
100
+ width: '100%',
101
+ padding: '0.625rem 1.25rem',
102
+ fontSize: '0.875rem',
103
+ fontWeight: 500,
104
+ color: '#fff',
105
+ backgroundColor: '#3b82f6',
106
+ border: 'none',
107
+ borderRadius: '0.5rem',
108
+ cursor: 'pointer',
109
+ }}
110
+ >
111
+ Spróbuj ponownie
112
+ </button>
113
+ </div>
114
+ </body>
115
+ </html>
116
+ );
117
+ }
@@ -122,4 +122,12 @@
122
122
  .text-balance {
123
123
  text-wrap: balance;
124
124
  }
125
+
126
+ .scrollbar-hide {
127
+ -ms-overflow-style: none;
128
+ scrollbar-width: none;
129
+ }
130
+ .scrollbar-hide::-webkit-scrollbar {
131
+ display: none;
132
+ }
125
133
  }