@storepecker/storefront-core 1.1.1 → 2.0.0

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 (72) hide show
  1. package/dist/api/index.cjs +76 -75
  2. package/dist/api/index.d.cts +4 -3
  3. package/dist/api/index.d.ts +4 -3
  4. package/dist/api/index.js +9 -8
  5. package/dist/{booking-B21s0inO.d.cts → booking-B39Ilxhg.d.ts} +1 -1
  6. package/dist/{booking-CegE1cje.d.ts → booking-Dk-BoHUB.d.cts} +1 -1
  7. package/dist/cart-BY8D8w-s.d.cts +90 -0
  8. package/dist/cart-GuhgeBBt.d.ts +90 -0
  9. package/dist/checkout/index.cjs +38 -37
  10. package/dist/checkout/index.d.cts +2 -1
  11. package/dist/checkout/index.d.ts +2 -1
  12. package/dist/checkout/index.js +6 -5
  13. package/dist/{chunk-34KV265H.cjs → chunk-26A3EBZI.cjs} +20 -20
  14. package/dist/chunk-2AHH3XBW.cjs +47 -0
  15. package/dist/{chunk-K5B62JZO.cjs → chunk-47XTPPII.cjs} +4 -4
  16. package/dist/chunk-4C4NTH6O.js +41 -0
  17. package/dist/{chunk-UM24VDYB.js → chunk-7R2V4C7Q.js} +2 -2
  18. package/dist/{chunk-CSISWBZZ.js → chunk-B7FOXIZN.js} +1 -1
  19. package/dist/chunk-BBRB475I.cjs +43 -0
  20. package/dist/chunk-BBRXE57K.cjs +50 -0
  21. package/dist/{chunk-QCQCFYYR.js → chunk-BHOXJGIE.js} +1 -1
  22. package/dist/chunk-BQ256JKN.js +39 -0
  23. package/dist/{chunk-7UH6REGV.js → chunk-C7ZJZEEN.js} +1 -1
  24. package/dist/{chunk-A6IO3HIN.cjs → chunk-FMHR5ABF.cjs} +28 -28
  25. package/dist/{chunk-JHGXIIBZ.cjs → chunk-G3R7ZVAG.cjs} +7 -7
  26. package/dist/{chunk-4MJMNIAB.js → chunk-GHABOHLA.js} +1 -1
  27. package/dist/chunk-GTV42PDK.cjs +46 -0
  28. package/dist/chunk-HEFA67WK.js +42 -0
  29. package/dist/chunk-HSF2D56O.js +40 -0
  30. package/dist/{chunk-GB3HW6DM.js → chunk-JWKDXFS4.js} +1 -1
  31. package/dist/{chunk-KWKHHRRJ.cjs → chunk-KKQKHG26.cjs} +3 -3
  32. package/dist/{chunk-QM73PI5L.cjs → chunk-N3ZCCKXV.cjs} +10 -10
  33. package/dist/{chunk-GQTO5ZE2.cjs → chunk-NE3ZHELZ.cjs} +0 -46
  34. package/dist/chunk-PWYWNRVO.cjs +150 -0
  35. package/dist/{chunk-E7WPE3PV.js → chunk-QAC72HKO.js} +1 -1
  36. package/dist/{chunk-CFF632IQ.cjs → chunk-SMHJRNCR.cjs} +4 -4
  37. package/dist/chunk-UOFTDL4D.js +146 -0
  38. package/dist/chunk-WEMNXIRS.js +47 -0
  39. package/dist/{chunk-LC5ZAUKL.cjs → chunk-XLQAALMU.cjs} +10 -10
  40. package/dist/{chunk-Z7LHRD3V.js → chunk-Y6NFUWTH.js} +3 -3
  41. package/dist/{chunk-LBGIUNM6.js → chunk-YY77CUWX.js} +1 -1
  42. package/dist/{chunk-UXLUE3HW.cjs → chunk-ZO2HREQL.cjs} +2 -2
  43. package/dist/components/index.cjs +126 -7
  44. package/dist/components/index.d.cts +35 -8
  45. package/dist/components/index.d.ts +35 -8
  46. package/dist/components/index.js +122 -7
  47. package/dist/hooks/index.cjs +368 -27
  48. package/dist/hooks/index.d.cts +83 -3
  49. package/dist/hooks/index.d.ts +83 -3
  50. package/dist/hooks/index.js +352 -14
  51. package/dist/middleware/index.cjs +47 -0
  52. package/dist/middleware/index.d.cts +8 -0
  53. package/dist/middleware/index.d.ts +8 -0
  54. package/dist/middleware/index.js +44 -0
  55. package/dist/models/index.d.cts +4 -3
  56. package/dist/models/index.d.ts +4 -3
  57. package/dist/{cart-VaCKkJ1C.d.cts → product-Dfi0ke-4.d.cts} +1 -88
  58. package/dist/{cart-VaCKkJ1C.d.ts → product-Dfi0ke-4.d.ts} +1 -88
  59. package/dist/store/index.cjs +17 -85
  60. package/dist/store/index.d.cts +22 -2
  61. package/dist/store/index.d.ts +22 -2
  62. package/dist/store/index.js +7 -82
  63. package/dist/utils/index.cjs +80 -65
  64. package/dist/utils/index.d.cts +54 -3
  65. package/dist/utils/index.d.ts +54 -3
  66. package/dist/utils/index.js +20 -43
  67. package/dist/{wishlist-FG8tgn76.d.ts → wishlist-DHOvXmJj.d.cts} +1 -1
  68. package/dist/{wishlist-CkAhLpbI.d.cts → wishlist-LfdFxddw.d.ts} +1 -1
  69. package/package.json +24 -5
  70. package/dist/chunk-7DQIKSGY.js +0 -40
  71. package/dist/chunk-FLBJKM6G.js +0 -83
  72. package/dist/chunk-S3WIGYDS.cjs +0 -42
@@ -1,7 +1,8 @@
1
1
  import { A as Address } from '../address-DQEZzyUG.cjs';
2
- import { C as Cart, j as Product, d as Category, e as Coupon } from '../cart-VaCKkJ1C.cjs';
2
+ import { C as Cart, b as Category, c as Coupon } from '../cart-BY8D8w-s.cjs';
3
3
  import { O as Order } from '../orders-DHJhJ3xz.cjs';
4
- import { U as User, W as Wishlist } from '../wishlist-CkAhLpbI.cjs';
4
+ import { b as Product, c as ProductDetail, A as Attributes } from '../product-Dfi0ke-4.cjs';
5
+ import { U as User, W as Wishlist } from '../wishlist-DHOvXmJj.cjs';
5
6
  export { U as UseAddressFormOptions, a as UseAddressFormReturn, u as useAddressForm } from '../useAddressForm-DgkCP1nG.cjs';
6
7
  import 'react-toastify';
7
8
  import 'react';
@@ -134,4 +135,83 @@ interface UseCheckoutCouponReturn {
134
135
  */
135
136
  declare function useCheckoutCoupon(options: UseCheckoutCouponOptions): UseCheckoutCouponReturn;
136
137
 
137
- export { type PaginationMode, type UseCheckoutCouponOptions, type UseCheckoutCouponReturn, type UseCheckoutPaymentOptions, type UseCheckoutPaymentReturn, type UseGetProductsOptions, type UseGetProductsReturn, useAddress, useCart, useCheckoutCoupon, useCheckoutPayment, useGetProductCategories, useGetProductDetails, useGetProducts, useOrders, useProductDetailModal, useServiceFormModal, useUserDetails, useWishlist };
138
+ interface UseVariantSelectorOptions {
139
+ /** The current product detail. */
140
+ product: ProductDetail.Root;
141
+ /** Product attributes map (variant type → choices). */
142
+ productAttributes: Record<string, ProductDetail.ProductAttribute[]>;
143
+ /** Called when a new variant is resolved. Theme handles navigation/callback. */
144
+ onVariantChange?: (slug: string) => void;
145
+ }
146
+ interface UseVariantSelectorReturn {
147
+ /** The currently selected variant attributes (includes slug). */
148
+ selectedVariant: Attributes;
149
+ /** Call this when the user clicks a variant option. */
150
+ handleVariantSelected: (variantType: string, variant: {
151
+ name: string;
152
+ value: string;
153
+ }) => void;
154
+ /** Check if a specific variant choice is available given the current selection. */
155
+ checkIfVariantAvailable: (variantType: string, variant: {
156
+ name: string;
157
+ value: string;
158
+ }) => boolean;
159
+ /** Check if a variant type is a color type ("color" or "colors"). */
160
+ isColorType: (variantType: string) => boolean;
161
+ /** Size chart modal open state. */
162
+ isSizeChartModalOpen: boolean;
163
+ /** Toggle the size chart modal. */
164
+ toggleSizeChartModal: () => void;
165
+ }
166
+ declare function useVariantSelector(options: UseVariantSelectorOptions): UseVariantSelectorReturn;
167
+
168
+ interface UseShopCheckoutOptions {
169
+ product: ProductDetail.Root;
170
+ /** Called after successfully adding to cart or when navigating to cart. */
171
+ onNavigateToCart?: () => void;
172
+ /** Called when a toast/notification should be shown. */
173
+ onToast?: (message: string, type?: "success" | "error") => void;
174
+ }
175
+ interface UseShopCheckoutReturn {
176
+ isWishlisted: boolean;
177
+ isAddedToCart: boolean;
178
+ loading: boolean;
179
+ quantity: number;
180
+ showLoginModal: boolean;
181
+ showNotifyMeModal: boolean;
182
+ categories: Category.Root[];
183
+ isUserAuthenticated: boolean;
184
+ productCustomizations: ProductDetail.Customization[];
185
+ handleAddToCart: () => Promise<void>;
186
+ handleCustomizationSubmit: (data: any) => Promise<void>;
187
+ handleQuantityChange: (value: number) => void;
188
+ handleShare: () => void;
189
+ handleLogin: () => void;
190
+ closeLoginModal: () => void;
191
+ handleNotifyMe: () => void;
192
+ handleNotifyMeFormSubmit: (values: any) => Promise<void>;
193
+ handleNotifyMeModalClose: () => void;
194
+ handleWishlistUpdated: (status: "add" | "remove") => void;
195
+ isOutOfStock: boolean;
196
+ isLowStock: boolean;
197
+ }
198
+ declare function useShopCheckout(options: UseShopCheckoutOptions): UseShopCheckoutReturn;
199
+
200
+ interface UseCouponOptions {
201
+ /** Called when coupon status changes (applied or removed). */
202
+ onCouponStatusChange?: (coupon: Coupon | null) => void;
203
+ }
204
+ interface UseCouponReturn {
205
+ isCouponModalOpen: boolean;
206
+ availableCoupons: Coupon[];
207
+ appliedCoupon: Coupon | null;
208
+ couponApplyingLoading: boolean;
209
+ couponApplyingError: string | null;
210
+ handleViewCoupons: () => void;
211
+ handleCloseCouponModal: () => void;
212
+ handleApplyCoupon: (code: string) => Promise<void>;
213
+ handleRemoveCoupon: () => Promise<void>;
214
+ }
215
+ declare function useCoupon(options?: UseCouponOptions): UseCouponReturn;
216
+
217
+ export { type PaginationMode, type UseCheckoutCouponOptions, type UseCheckoutCouponReturn, type UseCheckoutPaymentOptions, type UseCheckoutPaymentReturn, type UseCouponOptions, type UseCouponReturn, type UseGetProductsOptions, type UseGetProductsReturn, type UseShopCheckoutOptions, type UseShopCheckoutReturn, type UseVariantSelectorOptions, type UseVariantSelectorReturn, useAddress, useCart, useCheckoutCoupon, useCheckoutPayment, useCoupon, useGetProductCategories, useGetProductDetails, useGetProducts, useOrders, useProductDetailModal, useServiceFormModal, useShopCheckout, useUserDetails, useVariantSelector, useWishlist };
@@ -1,7 +1,8 @@
1
1
  import { A as Address } from '../address-DQEZzyUG.js';
2
- import { C as Cart, j as Product, d as Category, e as Coupon } from '../cart-VaCKkJ1C.js';
2
+ import { C as Cart, b as Category, c as Coupon } from '../cart-GuhgeBBt.js';
3
3
  import { O as Order } from '../orders-DHJhJ3xz.js';
4
- import { U as User, W as Wishlist } from '../wishlist-FG8tgn76.js';
4
+ import { b as Product, c as ProductDetail, A as Attributes } from '../product-Dfi0ke-4.js';
5
+ import { U as User, W as Wishlist } from '../wishlist-LfdFxddw.js';
5
6
  export { U as UseAddressFormOptions, a as UseAddressFormReturn, u as useAddressForm } from '../useAddressForm-C-Uzug4d.js';
6
7
  import 'react-toastify';
7
8
  import 'react';
@@ -134,4 +135,83 @@ interface UseCheckoutCouponReturn {
134
135
  */
135
136
  declare function useCheckoutCoupon(options: UseCheckoutCouponOptions): UseCheckoutCouponReturn;
136
137
 
137
- export { type PaginationMode, type UseCheckoutCouponOptions, type UseCheckoutCouponReturn, type UseCheckoutPaymentOptions, type UseCheckoutPaymentReturn, type UseGetProductsOptions, type UseGetProductsReturn, useAddress, useCart, useCheckoutCoupon, useCheckoutPayment, useGetProductCategories, useGetProductDetails, useGetProducts, useOrders, useProductDetailModal, useServiceFormModal, useUserDetails, useWishlist };
138
+ interface UseVariantSelectorOptions {
139
+ /** The current product detail. */
140
+ product: ProductDetail.Root;
141
+ /** Product attributes map (variant type → choices). */
142
+ productAttributes: Record<string, ProductDetail.ProductAttribute[]>;
143
+ /** Called when a new variant is resolved. Theme handles navigation/callback. */
144
+ onVariantChange?: (slug: string) => void;
145
+ }
146
+ interface UseVariantSelectorReturn {
147
+ /** The currently selected variant attributes (includes slug). */
148
+ selectedVariant: Attributes;
149
+ /** Call this when the user clicks a variant option. */
150
+ handleVariantSelected: (variantType: string, variant: {
151
+ name: string;
152
+ value: string;
153
+ }) => void;
154
+ /** Check if a specific variant choice is available given the current selection. */
155
+ checkIfVariantAvailable: (variantType: string, variant: {
156
+ name: string;
157
+ value: string;
158
+ }) => boolean;
159
+ /** Check if a variant type is a color type ("color" or "colors"). */
160
+ isColorType: (variantType: string) => boolean;
161
+ /** Size chart modal open state. */
162
+ isSizeChartModalOpen: boolean;
163
+ /** Toggle the size chart modal. */
164
+ toggleSizeChartModal: () => void;
165
+ }
166
+ declare function useVariantSelector(options: UseVariantSelectorOptions): UseVariantSelectorReturn;
167
+
168
+ interface UseShopCheckoutOptions {
169
+ product: ProductDetail.Root;
170
+ /** Called after successfully adding to cart or when navigating to cart. */
171
+ onNavigateToCart?: () => void;
172
+ /** Called when a toast/notification should be shown. */
173
+ onToast?: (message: string, type?: "success" | "error") => void;
174
+ }
175
+ interface UseShopCheckoutReturn {
176
+ isWishlisted: boolean;
177
+ isAddedToCart: boolean;
178
+ loading: boolean;
179
+ quantity: number;
180
+ showLoginModal: boolean;
181
+ showNotifyMeModal: boolean;
182
+ categories: Category.Root[];
183
+ isUserAuthenticated: boolean;
184
+ productCustomizations: ProductDetail.Customization[];
185
+ handleAddToCart: () => Promise<void>;
186
+ handleCustomizationSubmit: (data: any) => Promise<void>;
187
+ handleQuantityChange: (value: number) => void;
188
+ handleShare: () => void;
189
+ handleLogin: () => void;
190
+ closeLoginModal: () => void;
191
+ handleNotifyMe: () => void;
192
+ handleNotifyMeFormSubmit: (values: any) => Promise<void>;
193
+ handleNotifyMeModalClose: () => void;
194
+ handleWishlistUpdated: (status: "add" | "remove") => void;
195
+ isOutOfStock: boolean;
196
+ isLowStock: boolean;
197
+ }
198
+ declare function useShopCheckout(options: UseShopCheckoutOptions): UseShopCheckoutReturn;
199
+
200
+ interface UseCouponOptions {
201
+ /** Called when coupon status changes (applied or removed). */
202
+ onCouponStatusChange?: (coupon: Coupon | null) => void;
203
+ }
204
+ interface UseCouponReturn {
205
+ isCouponModalOpen: boolean;
206
+ availableCoupons: Coupon[];
207
+ appliedCoupon: Coupon | null;
208
+ couponApplyingLoading: boolean;
209
+ couponApplyingError: string | null;
210
+ handleViewCoupons: () => void;
211
+ handleCloseCouponModal: () => void;
212
+ handleApplyCoupon: (code: string) => Promise<void>;
213
+ handleRemoveCoupon: () => Promise<void>;
214
+ }
215
+ declare function useCoupon(options?: UseCouponOptions): UseCouponReturn;
216
+
217
+ export { type PaginationMode, type UseCheckoutCouponOptions, type UseCheckoutCouponReturn, type UseCheckoutPaymentOptions, type UseCheckoutPaymentReturn, type UseCouponOptions, type UseCouponReturn, type UseGetProductsOptions, type UseGetProductsReturn, type UseShopCheckoutOptions, type UseShopCheckoutReturn, type UseVariantSelectorOptions, type UseVariantSelectorReturn, useAddress, useCart, useCheckoutCoupon, useCheckoutPayment, useCoupon, useGetProductCategories, useGetProductDetails, useGetProducts, useOrders, useProductDetailModal, useServiceFormModal, useShopCheckout, useUserDetails, useVariantSelector, useWishlist };
@@ -1,18 +1,21 @@
1
- import { getUserDetails } from '../chunk-7UH6REGV.js';
2
- import { useCartStore } from '../chunk-7DQIKSGY.js';
3
- import { getCart, getProductList, getProductDetail, getWishlist, getProductCategories } from '../chunk-Z7LHRD3V.js';
4
- import '../chunk-E7WPE3PV.js';
5
- import { processPayment, fetchAvailableCoupons, applyCheckoutCoupon, removeCheckoutCoupon } from '../chunk-QCQCFYYR.js';
6
- import { getOrders, placeOrder } from '../chunk-4MJMNIAB.js';
1
+ import { getUserDetails } from '../chunk-C7ZJZEEN.js';
2
+ import { findMatchingVariant, findSimilarVariant, isVariantCombinationAvailable, isColorVariantType } from '../chunk-HEFA67WK.js';
3
+ import { useCartStore, useAuthStore } from '../chunk-UOFTDL4D.js';
4
+ import { getCart, getProductList, getProductDetail, getWishlist, notifyProductStock, getProductCategories, getCategories } from '../chunk-Y6NFUWTH.js';
5
+ import { cart_default } from '../chunk-QAC72HKO.js';
6
+ import { processPayment, fetchAvailableCoupons, applyCheckoutCoupon, removeCheckoutCoupon } from '../chunk-BHOXJGIE.js';
7
+ import { getOrders, placeOrder, applyCoupon, removeCoupon, getCoupons, getAppliedCoupon } from '../chunk-GHABOHLA.js';
7
8
  import '../chunk-WFDKKOO7.js';
8
- export { useAddressForm } from '../chunk-UM24VDYB.js';
9
- import { getAddresses } from '../chunk-LBGIUNM6.js';
10
- import '../chunk-YUPBTD4M.js';
11
- import '../chunk-CSISWBZZ.js';
12
- import '../chunk-GB3HW6DM.js';
13
- import '../chunk-FLBJKM6G.js';
9
+ export { useAddressForm } from '../chunk-7R2V4C7Q.js';
10
+ import { getAddresses } from '../chunk-YY77CUWX.js';
11
+ import { shareLink, convertToCurrency } from '../chunk-YUPBTD4M.js';
12
+ import '../chunk-B7FOXIZN.js';
13
+ import '../chunk-JWKDXFS4.js';
14
+ import '../chunk-WEMNXIRS.js';
15
+ import '../chunk-BQ256JKN.js';
14
16
  import '../chunk-JQMLHRWL.js';
15
- import { useState, useRef, useCallback, useEffect } from 'react';
17
+ import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
18
+ import { AxiosError } from 'axios';
16
19
 
17
20
  var useAddress = () => {
18
21
  const [data, setData] = useState([]);
@@ -418,5 +421,340 @@ function useCheckoutCoupon(options) {
418
421
  refreshCoupons
419
422
  };
420
423
  }
424
+ function useVariantSelector(options) {
425
+ const { product, productAttributes, onVariantChange } = options;
426
+ const [selectedVariant, setSelectedVariant] = useState(
427
+ product.attributes ?? {}
428
+ );
429
+ const [isSizeChartModalOpen, setIsSizeChartModalOpen] = useState(false);
430
+ useEffect(() => {
431
+ setSelectedVariant(product.attributes);
432
+ }, [product]);
433
+ const attributeKeys = useMemo(
434
+ () => Object.keys(productAttributes ?? {}),
435
+ [productAttributes]
436
+ );
437
+ const handleVariantSelected = useCallback(
438
+ (variantType, variant) => {
439
+ const newSelectedVariants = {
440
+ ...selectedVariant,
441
+ [variantType]: variant
442
+ };
443
+ const matchedVariant = findMatchingVariant(
444
+ product.variantAttributes,
445
+ attributeKeys,
446
+ newSelectedVariants
447
+ );
448
+ if (matchedVariant) {
449
+ if (matchedVariant.slug === selectedVariant.slug)
450
+ return;
451
+ setSelectedVariant(matchedVariant);
452
+ onVariantChange?.(matchedVariant.slug);
453
+ } else {
454
+ const similarVariant = findSimilarVariant(
455
+ product.variantAttributes,
456
+ variantType,
457
+ variant
458
+ );
459
+ if (similarVariant) {
460
+ setSelectedVariant(similarVariant);
461
+ onVariantChange?.(similarVariant.slug);
462
+ }
463
+ }
464
+ },
465
+ [selectedVariant, product.variantAttributes, attributeKeys, onVariantChange]
466
+ );
467
+ const checkIfVariantAvailable = useCallback(
468
+ (variantType, variant) => {
469
+ if (!product.variants || product.variants.length === 0 || !productAttributes)
470
+ return false;
471
+ return isVariantCombinationAvailable(
472
+ product.variantAttributes,
473
+ attributeKeys,
474
+ selectedVariant,
475
+ variantType,
476
+ variant
477
+ );
478
+ },
479
+ [
480
+ product.variants,
481
+ product.variantAttributes,
482
+ productAttributes,
483
+ attributeKeys,
484
+ selectedVariant
485
+ ]
486
+ );
487
+ const toggleSizeChartModal = useCallback(() => {
488
+ setIsSizeChartModalOpen((prev) => !prev);
489
+ }, []);
490
+ return {
491
+ selectedVariant,
492
+ handleVariantSelected,
493
+ checkIfVariantAvailable,
494
+ isColorType: isColorVariantType,
495
+ isSizeChartModalOpen,
496
+ toggleSizeChartModal
497
+ };
498
+ }
499
+ function useShopCheckout(options) {
500
+ const { product, onNavigateToCart, onToast } = options;
501
+ const { addToCart, setCart } = useCartStore();
502
+ const isUserAuthenticated = useAuthStore((s) => s.isAuthenticated);
503
+ const [isWishlisted, setIsWishlisted] = useState(product.is_wishlisted);
504
+ const [isAddedToCart, setIsAddedToCart] = useState(false);
505
+ const [loading, setLoading] = useState(false);
506
+ const [quantity, setQuantity] = useState(1);
507
+ const [showLoginModal, setShowLoginModal] = useState(false);
508
+ const [showNotifyMeModal, setShowNotifyMeModal] = useState(false);
509
+ const [categories, setCategories] = useState([]);
510
+ useEffect(() => {
511
+ const fetchCategories = async () => {
512
+ try {
513
+ const response = await getCategories();
514
+ setCategories(response.data);
515
+ } catch (error) {
516
+ console.log(error);
517
+ }
518
+ };
519
+ fetchCategories();
520
+ }, []);
521
+ const productCustomizations = useMemo(() => {
522
+ return product.product.customizations ?? [];
523
+ }, [product]);
524
+ const handleAddToCart = useCallback(async () => {
525
+ if (isAddedToCart) {
526
+ onNavigateToCart?.();
527
+ return;
528
+ }
529
+ if (isUserAuthenticated) {
530
+ setLoading(true);
531
+ try {
532
+ await addToCart([{ variant_id: product.id, quantity }]);
533
+ setIsAddedToCart(true);
534
+ } catch (error) {
535
+ console.log(error);
536
+ } finally {
537
+ setLoading(false);
538
+ }
539
+ } else {
540
+ cart_default.add(product);
541
+ const localCartItems = cart_default.get();
542
+ if (localCartItems) {
543
+ setCart(localCartItems);
544
+ }
545
+ setIsAddedToCart(true);
546
+ }
547
+ }, [
548
+ isAddedToCart,
549
+ isUserAuthenticated,
550
+ product,
551
+ quantity,
552
+ addToCart,
553
+ setCart,
554
+ onNavigateToCart
555
+ ]);
556
+ const handleCustomizationSubmit = useCallback(
557
+ async (data) => {
558
+ if (isAddedToCart) {
559
+ onNavigateToCart?.();
560
+ return;
561
+ }
562
+ const customizePayload = [];
563
+ Object.keys(data).forEach((key) => {
564
+ if (data[key]) {
565
+ customizePayload.push({
566
+ customization_option: Number(key),
567
+ customer_input: data[key],
568
+ product_variant: product.id
569
+ });
570
+ }
571
+ });
572
+ if (isUserAuthenticated) {
573
+ setLoading(true);
574
+ try {
575
+ await addToCart(
576
+ [{ variant_id: product.id, quantity }],
577
+ customizePayload
578
+ );
579
+ setIsAddedToCart(true);
580
+ } catch (error) {
581
+ console.log(error);
582
+ } finally {
583
+ setLoading(false);
584
+ }
585
+ } else {
586
+ cart_default.add(product);
587
+ const localCartItems = cart_default.get();
588
+ if (localCartItems) {
589
+ setCart(localCartItems);
590
+ }
591
+ setIsAddedToCart(true);
592
+ }
593
+ },
594
+ [
595
+ isAddedToCart,
596
+ isUserAuthenticated,
597
+ product,
598
+ quantity,
599
+ addToCart,
600
+ setCart,
601
+ onNavigateToCart
602
+ ]
603
+ );
604
+ const handleQuantityChange = useCallback((value) => {
605
+ setQuantity(value);
606
+ }, []);
607
+ const handleShare = useCallback(() => {
608
+ shareLink(
609
+ `Buy ${product.name} at ${convertToCurrency(
610
+ Number(product.selling_price)
611
+ )}`,
612
+ product.name
613
+ );
614
+ }, [product]);
615
+ const handleLogin = useCallback(() => {
616
+ setShowLoginModal(true);
617
+ }, []);
618
+ const closeLoginModal = useCallback(() => {
619
+ setShowLoginModal(false);
620
+ }, []);
621
+ const handleNotifyMe = useCallback(() => {
622
+ setShowNotifyMeModal(true);
623
+ }, []);
624
+ const handleNotifyMeFormSubmit = useCallback(
625
+ async (values) => {
626
+ try {
627
+ const response = await notifyProductStock({
628
+ ...values,
629
+ variant_slug: product.slug
630
+ });
631
+ if (response.data) {
632
+ setShowNotifyMeModal(false);
633
+ onToast?.("Thank you for subscribing to our newsletter", "success");
634
+ }
635
+ } catch (error) {
636
+ console.log(error);
637
+ }
638
+ },
639
+ [product.slug, onToast]
640
+ );
641
+ const handleNotifyMeModalClose = useCallback(() => {
642
+ setShowNotifyMeModal(false);
643
+ }, []);
644
+ const handleWishlistUpdated = useCallback(
645
+ (status) => {
646
+ setIsWishlisted(status === "add");
647
+ onToast?.(
648
+ status === "add" ? "Added to wishlist" : "Removed from wishlist",
649
+ "success"
650
+ );
651
+ },
652
+ [onToast]
653
+ );
654
+ return {
655
+ isWishlisted,
656
+ isAddedToCart,
657
+ loading,
658
+ quantity,
659
+ showLoginModal,
660
+ showNotifyMeModal,
661
+ categories,
662
+ isUserAuthenticated,
663
+ productCustomizations,
664
+ handleAddToCart,
665
+ handleCustomizationSubmit,
666
+ handleQuantityChange,
667
+ handleShare,
668
+ handleLogin,
669
+ closeLoginModal,
670
+ handleNotifyMe,
671
+ handleNotifyMeFormSubmit,
672
+ handleNotifyMeModalClose,
673
+ handleWishlistUpdated,
674
+ isOutOfStock: product.stock_quantity === 0 && !product.booking_service,
675
+ isLowStock: product.stock_quantity > 0 && product.stock_quantity < 5
676
+ };
677
+ }
678
+ function useCoupon(options = {}) {
679
+ const { onCouponStatusChange } = options;
680
+ const [isCouponModalOpen, setIsCouponModalOpen] = useState(false);
681
+ const [availableCoupons, setAvailableCoupons] = useState([]);
682
+ const [appliedCoupon, setAppliedCoupon] = useState(null);
683
+ const [couponApplyingLoading, setCouponApplyingLoading] = useState(false);
684
+ const [couponApplyingError, setCouponApplyingError] = useState(
685
+ null
686
+ );
687
+ useEffect(() => {
688
+ const fetchCoupons = async () => {
689
+ try {
690
+ const response = await getCoupons();
691
+ if (response.data) {
692
+ setAvailableCoupons(response.data);
693
+ }
694
+ } catch (error) {
695
+ }
696
+ };
697
+ const fetchAppliedCoupon2 = async () => {
698
+ try {
699
+ const response = await getAppliedCoupon();
700
+ if (response.data) {
701
+ setAppliedCoupon(response.data);
702
+ }
703
+ } catch (error) {
704
+ }
705
+ };
706
+ fetchCoupons();
707
+ fetchAppliedCoupon2();
708
+ }, []);
709
+ const handleViewCoupons = useCallback(() => {
710
+ setIsCouponModalOpen(true);
711
+ }, []);
712
+ const handleCloseCouponModal = useCallback(() => {
713
+ setIsCouponModalOpen(false);
714
+ }, []);
715
+ const handleApplyCoupon = useCallback(
716
+ async (code) => {
717
+ try {
718
+ setCouponApplyingLoading(true);
719
+ setCouponApplyingError(null);
720
+ const response = await applyCoupon(code);
721
+ if (response.data) {
722
+ onCouponStatusChange?.(response.data.coupon);
723
+ setAppliedCoupon(response.data.coupon);
724
+ }
725
+ } catch (error) {
726
+ if (error instanceof AxiosError) {
727
+ setCouponApplyingError(error.response?.data?.detail ?? null);
728
+ }
729
+ } finally {
730
+ setCouponApplyingLoading(false);
731
+ }
732
+ },
733
+ [onCouponStatusChange]
734
+ );
735
+ const handleRemoveCoupon = useCallback(async () => {
736
+ if (!appliedCoupon) return;
737
+ try {
738
+ const response = await removeCoupon(appliedCoupon.coupon_code);
739
+ if (response.data) {
740
+ setAppliedCoupon(null);
741
+ onCouponStatusChange?.(null);
742
+ }
743
+ } catch (error) {
744
+ console.log(error);
745
+ }
746
+ }, [appliedCoupon, onCouponStatusChange]);
747
+ return {
748
+ isCouponModalOpen,
749
+ availableCoupons,
750
+ appliedCoupon,
751
+ couponApplyingLoading,
752
+ couponApplyingError,
753
+ handleViewCoupons,
754
+ handleCloseCouponModal,
755
+ handleApplyCoupon,
756
+ handleRemoveCoupon
757
+ };
758
+ }
421
759
 
422
- export { useAddress, useCart, useCheckoutCoupon, useCheckoutPayment, useGetProductCategories, useGetProductDetails, useGetProducts, useOrders, useProductDetailModal, useServiceFormModal, useUserDetails, useWishlist };
760
+ export { useAddress, useCart, useCheckoutCoupon, useCheckoutPayment, useCoupon, useGetProductCategories, useGetProductDetails, useGetProducts, useOrders, useProductDetailModal, useServiceFormModal, useShopCheckout, useUserDetails, useVariantSelector, useWishlist };
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ var chunkGTV42PDK_cjs = require('../chunk-GTV42PDK.cjs');
4
+ var chunkNE3ZHELZ_cjs = require('../chunk-NE3ZHELZ.cjs');
5
+ var server = require('next/server');
6
+ var jwtDecode = require('jwt-decode');
7
+
8
+ function middleware(request) {
9
+ const token = request.cookies.get(chunkNE3ZHELZ_cjs.USER_CRED_TOKEN)?.value;
10
+ const pathname = request.nextUrl.pathname;
11
+ if (token) {
12
+ const decodedJWT = jwtDecode.jwtDecode(token);
13
+ if (decodedJWT && decodedJWT.exp) {
14
+ const expiryDate = new Date(decodedJWT.exp * 1e3);
15
+ if (/* @__PURE__ */ new Date() > expiryDate && pathname !== "/re-auth")
16
+ return server.NextResponse.redirect(
17
+ new URL(`/re-auth?referer=${request.nextUrl.pathname}`, request.url)
18
+ );
19
+ }
20
+ }
21
+ if (chunkGTV42PDK_cjs.protectedRoutes.includes(request.nextUrl.pathname) && !token) {
22
+ const response = server.NextResponse.redirect(
23
+ new URL(`/login?referer=${request.nextUrl.pathname}`, request.url)
24
+ );
25
+ return response;
26
+ }
27
+ if (chunkGTV42PDK_cjs.authRoutes.includes(request.nextUrl.pathname) && token) {
28
+ return server.NextResponse.redirect(
29
+ new URL(`/?referer=${request.nextUrl.pathname}`, request.url)
30
+ );
31
+ }
32
+ }
33
+ var config = {
34
+ matcher: [
35
+ /*
36
+ * Match all request paths except for the ones starting with:
37
+ * - api (API routes)
38
+ * - _next/static (static files)
39
+ * - _next/image (image optimization files)
40
+ * - favicon.ico (favicon file)
41
+ */
42
+ "/((?!api|_next/static|_next/image|favicon.ico).*)"
43
+ ]
44
+ };
45
+
46
+ exports.config = config;
47
+ exports.middleware = middleware;
@@ -0,0 +1,8 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ declare function middleware(request: NextRequest): NextResponse<unknown> | undefined;
4
+ declare const config: {
5
+ matcher: string[];
6
+ };
7
+
8
+ export { config, middleware };
@@ -0,0 +1,8 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ declare function middleware(request: NextRequest): NextResponse<unknown> | undefined;
4
+ declare const config: {
5
+ matcher: string[];
6
+ };
7
+
8
+ export { config, middleware };
@@ -0,0 +1,44 @@
1
+ import { protectedRoutes, authRoutes } from '../chunk-4C4NTH6O.js';
2
+ import { USER_CRED_TOKEN } from '../chunk-BQ256JKN.js';
3
+ import { NextResponse } from 'next/server';
4
+ import { jwtDecode } from 'jwt-decode';
5
+
6
+ function middleware(request) {
7
+ const token = request.cookies.get(USER_CRED_TOKEN)?.value;
8
+ const pathname = request.nextUrl.pathname;
9
+ if (token) {
10
+ const decodedJWT = jwtDecode(token);
11
+ if (decodedJWT && decodedJWT.exp) {
12
+ const expiryDate = new Date(decodedJWT.exp * 1e3);
13
+ if (/* @__PURE__ */ new Date() > expiryDate && pathname !== "/re-auth")
14
+ return NextResponse.redirect(
15
+ new URL(`/re-auth?referer=${request.nextUrl.pathname}`, request.url)
16
+ );
17
+ }
18
+ }
19
+ if (protectedRoutes.includes(request.nextUrl.pathname) && !token) {
20
+ const response = NextResponse.redirect(
21
+ new URL(`/login?referer=${request.nextUrl.pathname}`, request.url)
22
+ );
23
+ return response;
24
+ }
25
+ if (authRoutes.includes(request.nextUrl.pathname) && token) {
26
+ return NextResponse.redirect(
27
+ new URL(`/?referer=${request.nextUrl.pathname}`, request.url)
28
+ );
29
+ }
30
+ }
31
+ var config = {
32
+ matcher: [
33
+ /*
34
+ * Match all request paths except for the ones starting with:
35
+ * - api (API routes)
36
+ * - _next/static (static files)
37
+ * - _next/image (image optimization files)
38
+ * - favicon.ico (favicon file)
39
+ */
40
+ "/((?!api|_next/static|_next/image|favicon.ico).*)"
41
+ ]
42
+ };
43
+
44
+ export { config, middleware };