hey-pharmacist-ecommerce 1.1.35 → 1.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +934 -730
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +587 -383
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/AccountOrdersTab.tsx +3 -1
- package/src/components/CartItem.tsx +6 -2
- package/src/components/NotificationBell.tsx +74 -21
- package/src/components/NotificationModal.tsx +223 -0
- package/src/components/OrderCard.tsx +3 -1
- package/src/components/ProductCard.tsx +6 -1
- package/src/components/QuickViewModal.tsx +1 -1
- package/src/lib/constants/assets.ts +1 -0
- package/src/providers/EcommerceProvider.tsx +0 -2
- package/src/screens/CheckoutScreen.tsx +6 -4
- package/src/screens/OrderDetailScreen.tsx +7 -3
- package/src/screens/ProductDetailScreen.tsx +8 -6
- package/src/screens/ShopScreen.tsx +6 -4
- package/src/screens/WishlistScreen.tsx +4 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var React10 = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var globalAxios21 = require('axios');
|
|
7
7
|
var framerMotion = require('framer-motion');
|
|
@@ -18,7 +18,7 @@ var zod = require('zod');
|
|
|
18
18
|
|
|
19
19
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
20
20
|
|
|
21
|
-
var
|
|
21
|
+
var React10__default = /*#__PURE__*/_interopDefault(React10);
|
|
22
22
|
var globalAxios21__default = /*#__PURE__*/_interopDefault(globalAxios21);
|
|
23
23
|
var Image4__default = /*#__PURE__*/_interopDefault(Image4);
|
|
24
24
|
var Link9__default = /*#__PURE__*/_interopDefault(Link9);
|
|
@@ -228,16 +228,16 @@ function darken(r, g, b, amount) {
|
|
|
228
228
|
const newB = Math.round(b * (1 - amount));
|
|
229
229
|
return formatRgb(newR, newG, newB);
|
|
230
230
|
}
|
|
231
|
-
var ThemeContext =
|
|
231
|
+
var ThemeContext = React10.createContext(void 0);
|
|
232
232
|
function useTheme() {
|
|
233
|
-
const context =
|
|
233
|
+
const context = React10.useContext(ThemeContext);
|
|
234
234
|
if (!context) {
|
|
235
235
|
throw new Error("useTheme must be used within ThemeProvider");
|
|
236
236
|
}
|
|
237
237
|
return context;
|
|
238
238
|
}
|
|
239
239
|
function ThemeProvider({ config, children }) {
|
|
240
|
-
|
|
240
|
+
React10.useEffect(() => {
|
|
241
241
|
const primaryShades = generateColorShades(config.colors.primary);
|
|
242
242
|
const secondaryShades = generateColorShades(config.colors.secondary);
|
|
243
243
|
const accentShades = generateColorShades(config.colors.accent);
|
|
@@ -1994,17 +1994,17 @@ var AuthApi = class extends BaseAPI {
|
|
|
1994
1994
|
return AuthApiFp(this.configuration).verifyUserEmail(body, options).then((request) => request(this.axios, this.basePath));
|
|
1995
1995
|
}
|
|
1996
1996
|
};
|
|
1997
|
-
var AuthContext =
|
|
1997
|
+
var AuthContext = React10.createContext(void 0);
|
|
1998
1998
|
function useAuth() {
|
|
1999
|
-
const context =
|
|
1999
|
+
const context = React10.useContext(AuthContext);
|
|
2000
2000
|
if (!context) {
|
|
2001
2001
|
throw new Error("useAuth must be used within AuthProvider");
|
|
2002
2002
|
}
|
|
2003
2003
|
return context;
|
|
2004
2004
|
}
|
|
2005
2005
|
function AuthProvider({ children }) {
|
|
2006
|
-
const [user, setUser] =
|
|
2007
|
-
const [isLoading, setIsLoading] =
|
|
2006
|
+
const [user, setUser] = React10.useState(null);
|
|
2007
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
2008
2008
|
const getUserKey = () => {
|
|
2009
2009
|
if (typeof window === "undefined") return "ecommerce_user";
|
|
2010
2010
|
const token = getAuthToken();
|
|
@@ -2016,7 +2016,7 @@ function AuthProvider({ children }) {
|
|
|
2016
2016
|
return "ecommerce_user";
|
|
2017
2017
|
}
|
|
2018
2018
|
};
|
|
2019
|
-
const refreshUser =
|
|
2019
|
+
const refreshUser = React10.useCallback(async () => {
|
|
2020
2020
|
try {
|
|
2021
2021
|
const token = getAuthToken();
|
|
2022
2022
|
if (token) {
|
|
@@ -2030,7 +2030,7 @@ function AuthProvider({ children }) {
|
|
|
2030
2030
|
setIsLoading(false);
|
|
2031
2031
|
}
|
|
2032
2032
|
}, []);
|
|
2033
|
-
|
|
2033
|
+
React10.useEffect(() => {
|
|
2034
2034
|
if (typeof window !== "undefined") {
|
|
2035
2035
|
try {
|
|
2036
2036
|
const userKey = getUserKey();
|
|
@@ -11811,11 +11811,11 @@ var notificationConfig = {
|
|
|
11811
11811
|
}
|
|
11812
11812
|
};
|
|
11813
11813
|
function Notification2({ notification, onDismiss }) {
|
|
11814
|
-
const [progress, setProgress] =
|
|
11814
|
+
const [progress, setProgress] = React10.useState(100);
|
|
11815
11815
|
const config = notificationConfig[notification.type];
|
|
11816
11816
|
const Icon = config.icon;
|
|
11817
11817
|
const duration = notification.duration || 4e3;
|
|
11818
|
-
|
|
11818
|
+
React10.useEffect(() => {
|
|
11819
11819
|
const startTime = Date.now();
|
|
11820
11820
|
const timer = setInterval(() => {
|
|
11821
11821
|
const elapsed = Date.now() - startTime;
|
|
@@ -11878,17 +11878,17 @@ function Notification2({ notification, onDismiss }) {
|
|
|
11878
11878
|
function NotificationContainer({ notifications, onDismiss }) {
|
|
11879
11879
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed top-4 right-4 z-50 flex flex-col gap-3 pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "popLayout", children: notifications.map((notification) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsxRuntime.jsx(Notification2, { notification, onDismiss }) }, notification.id)) }) });
|
|
11880
11880
|
}
|
|
11881
|
-
var NotificationContext =
|
|
11881
|
+
var NotificationContext = React10.createContext(void 0);
|
|
11882
11882
|
function useNotification() {
|
|
11883
|
-
const context =
|
|
11883
|
+
const context = React10.useContext(NotificationContext);
|
|
11884
11884
|
if (!context) {
|
|
11885
11885
|
throw new Error("useNotification must be used within NotificationProvider");
|
|
11886
11886
|
}
|
|
11887
11887
|
return context;
|
|
11888
11888
|
}
|
|
11889
11889
|
function NotificationProvider({ children }) {
|
|
11890
|
-
const [notifications, setNotifications] =
|
|
11891
|
-
const addNotification =
|
|
11890
|
+
const [notifications, setNotifications] = React10.useState([]);
|
|
11891
|
+
const addNotification = React10.useCallback(
|
|
11892
11892
|
(type, message, description, duration) => {
|
|
11893
11893
|
const id = Math.random().toString(36).substring(2, 9);
|
|
11894
11894
|
const notification = {
|
|
@@ -11902,23 +11902,23 @@ function NotificationProvider({ children }) {
|
|
|
11902
11902
|
},
|
|
11903
11903
|
[]
|
|
11904
11904
|
);
|
|
11905
|
-
const dismissNotification =
|
|
11905
|
+
const dismissNotification = React10.useCallback((id) => {
|
|
11906
11906
|
setNotifications((prev) => prev.filter((n) => n.id !== id));
|
|
11907
11907
|
}, []);
|
|
11908
11908
|
const value = {
|
|
11909
|
-
success:
|
|
11909
|
+
success: React10.useCallback(
|
|
11910
11910
|
(message, description, duration) => addNotification("success", message, description, duration),
|
|
11911
11911
|
[addNotification]
|
|
11912
11912
|
),
|
|
11913
|
-
error:
|
|
11913
|
+
error: React10.useCallback(
|
|
11914
11914
|
(message, description, duration) => addNotification("error", message, description, duration),
|
|
11915
11915
|
[addNotification]
|
|
11916
11916
|
),
|
|
11917
|
-
warning:
|
|
11917
|
+
warning: React10.useCallback(
|
|
11918
11918
|
(message, description, duration) => addNotification("warning", message, description, duration),
|
|
11919
11919
|
[addNotification]
|
|
11920
11920
|
),
|
|
11921
|
-
info:
|
|
11921
|
+
info: React10.useCallback(
|
|
11922
11922
|
(message, description, duration) => addNotification("info", message, description, duration),
|
|
11923
11923
|
[addNotification]
|
|
11924
11924
|
)
|
|
@@ -11928,24 +11928,24 @@ function NotificationProvider({ children }) {
|
|
|
11928
11928
|
/* @__PURE__ */ jsxRuntime.jsx(NotificationContainer, { notifications, onDismiss: dismissNotification })
|
|
11929
11929
|
] });
|
|
11930
11930
|
}
|
|
11931
|
-
var CartContext =
|
|
11931
|
+
var CartContext = React10.createContext(void 0);
|
|
11932
11932
|
function useCart() {
|
|
11933
|
-
const context =
|
|
11933
|
+
const context = React10.useContext(CartContext);
|
|
11934
11934
|
if (!context) {
|
|
11935
11935
|
throw new Error("useCart must be used within CartProvider");
|
|
11936
11936
|
}
|
|
11937
11937
|
return context;
|
|
11938
11938
|
}
|
|
11939
11939
|
function CartProvider({ children }) {
|
|
11940
|
-
const [cart, setCart] =
|
|
11941
|
-
const [isLoading, setIsLoading] =
|
|
11940
|
+
const [cart, setCart] = React10.useState(null);
|
|
11941
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
11942
11942
|
const { isAuthenticated } = useAuth();
|
|
11943
11943
|
const notification = useNotification();
|
|
11944
|
-
const cartRef =
|
|
11945
|
-
|
|
11944
|
+
const cartRef = React10.useRef(cart);
|
|
11945
|
+
React10.useEffect(() => {
|
|
11946
11946
|
cartRef.current = cart;
|
|
11947
11947
|
}, [cart]);
|
|
11948
|
-
const refreshCart =
|
|
11948
|
+
const refreshCart = React10.useCallback(async () => {
|
|
11949
11949
|
if (!isAuthenticated) {
|
|
11950
11950
|
setCart(null);
|
|
11951
11951
|
return;
|
|
@@ -11959,10 +11959,10 @@ function CartProvider({ children }) {
|
|
|
11959
11959
|
console.error("Failed to fetch cart:", error);
|
|
11960
11960
|
}
|
|
11961
11961
|
}, [isAuthenticated]);
|
|
11962
|
-
|
|
11962
|
+
React10.useEffect(() => {
|
|
11963
11963
|
refreshCart();
|
|
11964
11964
|
}, [refreshCart]);
|
|
11965
|
-
const addToCart =
|
|
11965
|
+
const addToCart = React10.useCallback(async (productId, quantity = 1, variantId) => {
|
|
11966
11966
|
if (!isAuthenticated) return;
|
|
11967
11967
|
setIsLoading(true);
|
|
11968
11968
|
try {
|
|
@@ -12004,7 +12004,7 @@ function CartProvider({ children }) {
|
|
|
12004
12004
|
setIsLoading(false);
|
|
12005
12005
|
}
|
|
12006
12006
|
}, [isAuthenticated, notification]);
|
|
12007
|
-
const updateQuantity =
|
|
12007
|
+
const updateQuantity = React10.useCallback(async (productId, quantity) => {
|
|
12008
12008
|
const currentCart = cartRef.current;
|
|
12009
12009
|
if (!currentCart) return;
|
|
12010
12010
|
setIsLoading(true);
|
|
@@ -12050,7 +12050,7 @@ function CartProvider({ children }) {
|
|
|
12050
12050
|
setIsLoading(false);
|
|
12051
12051
|
}
|
|
12052
12052
|
}, [notification, refreshCart]);
|
|
12053
|
-
const removeFromCart =
|
|
12053
|
+
const removeFromCart = React10.useCallback(async (productId) => {
|
|
12054
12054
|
const currentCart = cartRef.current;
|
|
12055
12055
|
if (!currentCart) return;
|
|
12056
12056
|
setIsLoading(true);
|
|
@@ -12097,7 +12097,7 @@ function CartProvider({ children }) {
|
|
|
12097
12097
|
setIsLoading(false);
|
|
12098
12098
|
}
|
|
12099
12099
|
}, [notification]);
|
|
12100
|
-
const clearCart =
|
|
12100
|
+
const clearCart = React10.useCallback(async () => {
|
|
12101
12101
|
setIsLoading(true);
|
|
12102
12102
|
try {
|
|
12103
12103
|
await new CartApi(getApiConfiguration()).clearCart();
|
|
@@ -12153,9 +12153,9 @@ if (typeof window !== "undefined") {
|
|
|
12153
12153
|
AXIOS_CONFIG.baseOptions.signal = abortController.signal;
|
|
12154
12154
|
}
|
|
12155
12155
|
}
|
|
12156
|
-
var WishlistContext =
|
|
12156
|
+
var WishlistContext = React10.createContext(void 0);
|
|
12157
12157
|
function WishlistProvider({ children }) {
|
|
12158
|
-
const [state, setState] =
|
|
12158
|
+
const [state, setState] = React10.useState({
|
|
12159
12159
|
_id: "",
|
|
12160
12160
|
createdAt: /* @__PURE__ */ new Date(),
|
|
12161
12161
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
@@ -12164,8 +12164,8 @@ function WishlistProvider({ children }) {
|
|
|
12164
12164
|
});
|
|
12165
12165
|
const { isAuthenticated } = useAuth() || {};
|
|
12166
12166
|
const notification = useNotification();
|
|
12167
|
-
const wishlistApi =
|
|
12168
|
-
const fetchWishlist =
|
|
12167
|
+
const wishlistApi = React10.useMemo(() => new WishlistApi(AXIOS_CONFIG), []);
|
|
12168
|
+
const fetchWishlist = React10.useCallback(async () => {
|
|
12169
12169
|
if (!isAuthenticated) {
|
|
12170
12170
|
setState((prev) => ({
|
|
12171
12171
|
...prev,
|
|
@@ -12194,7 +12194,7 @@ function WishlistProvider({ children }) {
|
|
|
12194
12194
|
}));
|
|
12195
12195
|
}
|
|
12196
12196
|
}, [isAuthenticated]);
|
|
12197
|
-
|
|
12197
|
+
React10.useEffect(() => {
|
|
12198
12198
|
fetchWishlist();
|
|
12199
12199
|
}, [fetchWishlist]);
|
|
12200
12200
|
const addToWishlist = async (product) => {
|
|
@@ -12297,13 +12297,13 @@ function WishlistProvider({ children }) {
|
|
|
12297
12297
|
);
|
|
12298
12298
|
}
|
|
12299
12299
|
var useWishlist = () => {
|
|
12300
|
-
const context =
|
|
12300
|
+
const context = React10.useContext(WishlistContext);
|
|
12301
12301
|
if (context === void 0) {
|
|
12302
12302
|
throw new Error("useWishlist must be used within a WishlistProvider");
|
|
12303
12303
|
}
|
|
12304
12304
|
return context;
|
|
12305
12305
|
};
|
|
12306
|
-
var BasePathContext =
|
|
12306
|
+
var BasePathContext = React10.createContext(void 0);
|
|
12307
12307
|
function BasePathProvider({ basePath = "", children }) {
|
|
12308
12308
|
const normalized = basePath ? basePath.startsWith("/") ? basePath : `/${basePath}` : "";
|
|
12309
12309
|
const buildPath = (path) => {
|
|
@@ -12316,7 +12316,7 @@ function BasePathProvider({ basePath = "", children }) {
|
|
|
12316
12316
|
return /* @__PURE__ */ jsxRuntime.jsx(BasePathContext.Provider, { value: { basePath: normalized, buildPath }, children });
|
|
12317
12317
|
}
|
|
12318
12318
|
function useBasePath() {
|
|
12319
|
-
const ctx =
|
|
12319
|
+
const ctx = React10.useContext(BasePathContext);
|
|
12320
12320
|
if (!ctx) throw new Error("useBasePath must be used within BasePathProvider");
|
|
12321
12321
|
return ctx;
|
|
12322
12322
|
}
|
|
@@ -12347,12 +12347,12 @@ function formatDiscountDisplay(discount) {
|
|
|
12347
12347
|
return `$${discount.value.toFixed(2)} OFF`;
|
|
12348
12348
|
}
|
|
12349
12349
|
}
|
|
12350
|
-
var DiscountContext =
|
|
12350
|
+
var DiscountContext = React10.createContext(void 0);
|
|
12351
12351
|
function DiscountProvider({ children }) {
|
|
12352
|
-
const [appliedCoupon, setAppliedCoupon] =
|
|
12353
|
-
const [couponError, setCouponError] =
|
|
12354
|
-
const [isValidatingCoupon, setIsValidatingCoupon] =
|
|
12355
|
-
const validateAndApplyCoupon =
|
|
12352
|
+
const [appliedCoupon, setAppliedCoupon] = React10.useState(null);
|
|
12353
|
+
const [couponError, setCouponError] = React10.useState(null);
|
|
12354
|
+
const [isValidatingCoupon, setIsValidatingCoupon] = React10.useState(false);
|
|
12355
|
+
const validateAndApplyCoupon = React10.useCallback(
|
|
12356
12356
|
async (code, userId) => {
|
|
12357
12357
|
setIsValidatingCoupon(true);
|
|
12358
12358
|
setCouponError(null);
|
|
@@ -12379,11 +12379,11 @@ function DiscountProvider({ children }) {
|
|
|
12379
12379
|
},
|
|
12380
12380
|
[]
|
|
12381
12381
|
);
|
|
12382
|
-
const removeCoupon =
|
|
12382
|
+
const removeCoupon = React10.useCallback(() => {
|
|
12383
12383
|
setAppliedCoupon(null);
|
|
12384
12384
|
setCouponError(null);
|
|
12385
12385
|
}, []);
|
|
12386
|
-
const calculateCouponDiscount =
|
|
12386
|
+
const calculateCouponDiscount = React10.useCallback(
|
|
12387
12387
|
(subtotal) => {
|
|
12388
12388
|
if (!appliedCoupon) {
|
|
12389
12389
|
return 0;
|
|
@@ -12404,16 +12404,16 @@ function DiscountProvider({ children }) {
|
|
|
12404
12404
|
return /* @__PURE__ */ jsxRuntime.jsx(DiscountContext.Provider, { value, children });
|
|
12405
12405
|
}
|
|
12406
12406
|
function useDiscountsContext() {
|
|
12407
|
-
const context =
|
|
12407
|
+
const context = React10.useContext(DiscountContext);
|
|
12408
12408
|
if (!context) {
|
|
12409
12409
|
throw new Error("useDiscountsContext must be used within DiscountProvider");
|
|
12410
12410
|
}
|
|
12411
12411
|
return context;
|
|
12412
12412
|
}
|
|
12413
12413
|
init_config();
|
|
12414
|
-
var NotificationCenterContext =
|
|
12414
|
+
var NotificationCenterContext = React10.createContext(void 0);
|
|
12415
12415
|
function useNotificationCenter() {
|
|
12416
|
-
const context =
|
|
12416
|
+
const context = React10.useContext(NotificationCenterContext);
|
|
12417
12417
|
if (!context) {
|
|
12418
12418
|
throw new Error("useNotificationCenter must be used within NotificationCenterProvider");
|
|
12419
12419
|
}
|
|
@@ -12421,16 +12421,16 @@ function useNotificationCenter() {
|
|
|
12421
12421
|
}
|
|
12422
12422
|
function NotificationCenterProvider({ children }) {
|
|
12423
12423
|
const { isAuthenticated } = useAuth();
|
|
12424
|
-
const [notifications, setNotifications] =
|
|
12425
|
-
const [unreadCount, setUnreadCount] =
|
|
12426
|
-
const [isLoading, setIsLoading] =
|
|
12427
|
-
const [isDrawerOpen, setIsDrawerOpen] =
|
|
12428
|
-
const [settings, setSettings] =
|
|
12429
|
-
const [page, setPage] =
|
|
12430
|
-
const [hasMore, setHasMore] =
|
|
12431
|
-
const eventSourceRef =
|
|
12432
|
-
const notificationsApi =
|
|
12433
|
-
const fetchUnreadCount =
|
|
12424
|
+
const [notifications, setNotifications] = React10.useState([]);
|
|
12425
|
+
const [unreadCount, setUnreadCount] = React10.useState(0);
|
|
12426
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
12427
|
+
const [isDrawerOpen, setIsDrawerOpen] = React10.useState(false);
|
|
12428
|
+
const [settings, setSettings] = React10.useState(null);
|
|
12429
|
+
const [page, setPage] = React10.useState(1);
|
|
12430
|
+
const [hasMore, setHasMore] = React10.useState(true);
|
|
12431
|
+
const eventSourceRef = React10.useRef(null);
|
|
12432
|
+
const notificationsApi = React10.useRef(new NotificationsApi(getApiConfiguration()));
|
|
12433
|
+
const fetchUnreadCount = React10.useCallback(async () => {
|
|
12434
12434
|
if (!isAuthenticated) return;
|
|
12435
12435
|
try {
|
|
12436
12436
|
const response = await notificationsApi.current.getUnreadCount();
|
|
@@ -12439,7 +12439,7 @@ function NotificationCenterProvider({ children }) {
|
|
|
12439
12439
|
console.error("Failed to fetch unread count:", error);
|
|
12440
12440
|
}
|
|
12441
12441
|
}, [isAuthenticated]);
|
|
12442
|
-
const fetchNotifications =
|
|
12442
|
+
const fetchNotifications = React10.useCallback(async (pageNum = 1, append = false) => {
|
|
12443
12443
|
if (!isAuthenticated) return;
|
|
12444
12444
|
setIsLoading(true);
|
|
12445
12445
|
try {
|
|
@@ -12476,7 +12476,7 @@ function NotificationCenterProvider({ children }) {
|
|
|
12476
12476
|
setIsLoading(false);
|
|
12477
12477
|
}
|
|
12478
12478
|
}, [isAuthenticated]);
|
|
12479
|
-
const fetchSettings =
|
|
12479
|
+
const fetchSettings = React10.useCallback(async () => {
|
|
12480
12480
|
if (!isAuthenticated) return;
|
|
12481
12481
|
setIsLoading(true);
|
|
12482
12482
|
try {
|
|
@@ -12532,7 +12532,7 @@ function NotificationCenterProvider({ children }) {
|
|
|
12532
12532
|
setIsLoading(false);
|
|
12533
12533
|
}
|
|
12534
12534
|
}, [isAuthenticated]);
|
|
12535
|
-
|
|
12535
|
+
React10.useEffect(() => {
|
|
12536
12536
|
if (!isAuthenticated) {
|
|
12537
12537
|
if (eventSourceRef.current) {
|
|
12538
12538
|
eventSourceRef.current.close();
|
|
@@ -12589,7 +12589,7 @@ function NotificationCenterProvider({ children }) {
|
|
|
12589
12589
|
console.error("Failed to establish SSE connection:", error);
|
|
12590
12590
|
}
|
|
12591
12591
|
}, [isAuthenticated, isDrawerOpen, fetchUnreadCount]);
|
|
12592
|
-
|
|
12592
|
+
React10.useEffect(() => {
|
|
12593
12593
|
if (isAuthenticated) {
|
|
12594
12594
|
fetchUnreadCount();
|
|
12595
12595
|
fetchNotifications(1);
|
|
@@ -12602,18 +12602,18 @@ function NotificationCenterProvider({ children }) {
|
|
|
12602
12602
|
setHasMore(true);
|
|
12603
12603
|
}
|
|
12604
12604
|
}, [isAuthenticated, fetchUnreadCount, fetchNotifications, fetchSettings]);
|
|
12605
|
-
|
|
12605
|
+
React10.useEffect(() => {
|
|
12606
12606
|
if ("Notification" in window && Notification.permission === "default") {
|
|
12607
12607
|
Notification.requestPermission();
|
|
12608
12608
|
}
|
|
12609
12609
|
}, []);
|
|
12610
|
-
const openDrawer =
|
|
12610
|
+
const openDrawer = React10.useCallback(() => {
|
|
12611
12611
|
setIsDrawerOpen(true);
|
|
12612
12612
|
}, []);
|
|
12613
|
-
const closeDrawer =
|
|
12613
|
+
const closeDrawer = React10.useCallback(() => {
|
|
12614
12614
|
setIsDrawerOpen(false);
|
|
12615
12615
|
}, []);
|
|
12616
|
-
const markAsRead =
|
|
12616
|
+
const markAsRead = React10.useCallback(async (id) => {
|
|
12617
12617
|
try {
|
|
12618
12618
|
await notificationsApi.current.markAsRead(id);
|
|
12619
12619
|
setNotifications(
|
|
@@ -12624,7 +12624,7 @@ function NotificationCenterProvider({ children }) {
|
|
|
12624
12624
|
console.error("Failed to mark notification as read:", error);
|
|
12625
12625
|
}
|
|
12626
12626
|
}, []);
|
|
12627
|
-
const markAllAsRead =
|
|
12627
|
+
const markAllAsRead = React10.useCallback(async () => {
|
|
12628
12628
|
try {
|
|
12629
12629
|
await notificationsApi.current.markAllAsRead();
|
|
12630
12630
|
setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));
|
|
@@ -12633,7 +12633,7 @@ function NotificationCenterProvider({ children }) {
|
|
|
12633
12633
|
console.error("Failed to mark all as read:", error);
|
|
12634
12634
|
}
|
|
12635
12635
|
}, []);
|
|
12636
|
-
const deleteNotification =
|
|
12636
|
+
const deleteNotification = React10.useCallback(async (id) => {
|
|
12637
12637
|
try {
|
|
12638
12638
|
await notificationsApi.current.deleteNotification(id);
|
|
12639
12639
|
const notification = notifications.find((n) => n._id === id);
|
|
@@ -12645,15 +12645,15 @@ function NotificationCenterProvider({ children }) {
|
|
|
12645
12645
|
console.error("Failed to delete notification:", error);
|
|
12646
12646
|
}
|
|
12647
12647
|
}, [notifications]);
|
|
12648
|
-
const loadMore =
|
|
12648
|
+
const loadMore = React10.useCallback(async () => {
|
|
12649
12649
|
if (!hasMore || isLoading) return;
|
|
12650
12650
|
await fetchNotifications(page + 1, true);
|
|
12651
12651
|
}, [hasMore, isLoading, page, fetchNotifications]);
|
|
12652
|
-
const refreshNotifications =
|
|
12652
|
+
const refreshNotifications = React10.useCallback(async () => {
|
|
12653
12653
|
await fetchNotifications(1, false);
|
|
12654
12654
|
await fetchUnreadCount();
|
|
12655
12655
|
}, [fetchNotifications, fetchUnreadCount]);
|
|
12656
|
-
const updateSettings =
|
|
12656
|
+
const updateSettings = React10.useCallback(async (newSettings) => {
|
|
12657
12657
|
try {
|
|
12658
12658
|
const payload = {
|
|
12659
12659
|
_id: newSettings._id,
|
|
@@ -12691,294 +12691,26 @@ function NotificationCenterProvider({ children }) {
|
|
|
12691
12691
|
};
|
|
12692
12692
|
return /* @__PURE__ */ jsxRuntime.jsx(NotificationCenterContext.Provider, { value, children });
|
|
12693
12693
|
}
|
|
12694
|
-
var getNotificationIcon = (type) => {
|
|
12695
|
-
const className = "w-5 h-5";
|
|
12696
|
-
switch (type) {
|
|
12697
|
-
case "ORDER_CONFIRMATION":
|
|
12698
|
-
case "ORDER_SHIPPED":
|
|
12699
|
-
case "ORDER_DELIVERED":
|
|
12700
|
-
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className });
|
|
12701
|
-
case "PAYMENT_FAILED":
|
|
12702
|
-
case "REFUND_PROCESSED":
|
|
12703
|
-
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className });
|
|
12704
|
-
case "PASSWORD_RESET":
|
|
12705
|
-
case "NEW_DEVICE_LOGIN":
|
|
12706
|
-
case "TWO_FA_CODE":
|
|
12707
|
-
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { className });
|
|
12708
|
-
case "ABANDONED_CART_REMINDER":
|
|
12709
|
-
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShoppingCart, { className });
|
|
12710
|
-
case "PRICE_DROP_ALERT":
|
|
12711
|
-
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingDown, { className });
|
|
12712
|
-
case "BACK_IN_STOCK":
|
|
12713
|
-
default:
|
|
12714
|
-
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bell, { className });
|
|
12715
|
-
}
|
|
12716
|
-
};
|
|
12717
|
-
var getNotificationColor = (type) => {
|
|
12718
|
-
switch (type) {
|
|
12719
|
-
case "ORDER_CONFIRMATION":
|
|
12720
|
-
case "ORDER_DELIVERED":
|
|
12721
|
-
case "REFUND_PROCESSED":
|
|
12722
|
-
return "bg-green-100 text-green-600";
|
|
12723
|
-
case "ORDER_SHIPPED":
|
|
12724
|
-
return "bg-blue-100 text-blue-600";
|
|
12725
|
-
case "PAYMENT_FAILED":
|
|
12726
|
-
return "bg-red-100 text-red-600";
|
|
12727
|
-
case "PASSWORD_RESET":
|
|
12728
|
-
case "NEW_DEVICE_LOGIN":
|
|
12729
|
-
case "TWO_FA_CODE":
|
|
12730
|
-
return "bg-purple-100 text-purple-600";
|
|
12731
|
-
case "ABANDONED_CART_REMINDER":
|
|
12732
|
-
case "PRICE_DROP_ALERT":
|
|
12733
|
-
case "BACK_IN_STOCK":
|
|
12734
|
-
return "bg-orange-100 text-orange-600";
|
|
12735
|
-
default:
|
|
12736
|
-
return "bg-gray-100 text-gray-600";
|
|
12737
|
-
}
|
|
12738
|
-
};
|
|
12739
|
-
var formatRelativeTime = (dateString) => {
|
|
12740
|
-
const date = new Date(dateString);
|
|
12741
|
-
const diff = Date.now() - date.getTime();
|
|
12742
|
-
const mins = Math.floor(diff / 6e4);
|
|
12743
|
-
const hours = Math.floor(diff / 36e5);
|
|
12744
|
-
const days = Math.floor(diff / 864e5);
|
|
12745
|
-
if (mins < 1) return "Just now";
|
|
12746
|
-
if (mins < 60) return `${mins} min ago`;
|
|
12747
|
-
if (hours < 24) return `${hours} hour${hours > 1 ? "s" : ""} ago`;
|
|
12748
|
-
if (days < 7) return `${days} day${days > 1 ? "s" : ""} ago`;
|
|
12749
|
-
return date.toLocaleDateString();
|
|
12750
|
-
};
|
|
12751
|
-
function NotificationCard({
|
|
12752
|
-
notification,
|
|
12753
|
-
onMarkAsRead,
|
|
12754
|
-
onDelete
|
|
12755
|
-
}) {
|
|
12756
|
-
const router = navigation.useRouter();
|
|
12757
|
-
const { buildPath } = useBasePath();
|
|
12758
|
-
const hasDragged = React12.useRef(false);
|
|
12759
|
-
const handleClick = () => {
|
|
12760
|
-
if (hasDragged.current) return;
|
|
12761
|
-
if (!notification.isRead) {
|
|
12762
|
-
onMarkAsRead(notification._id);
|
|
12763
|
-
}
|
|
12764
|
-
if (notification.data?.orderId) {
|
|
12765
|
-
router.push(buildPath(`/account/orders/${notification.data.orderId}`));
|
|
12766
|
-
} else if (notification.data?.productId) {
|
|
12767
|
-
router.push(buildPath(`/products/${notification.data.productId}`));
|
|
12768
|
-
}
|
|
12769
|
-
};
|
|
12770
|
-
const handleDelete = (e) => {
|
|
12771
|
-
e.stopPropagation();
|
|
12772
|
-
onDelete(notification._id);
|
|
12773
|
-
};
|
|
12774
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-hidden rounded-lg", children: [
|
|
12775
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-end px-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1 text-white", children: [
|
|
12776
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-5 h-5" }),
|
|
12777
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold uppercase tracking-wider", children: "Remove" })
|
|
12778
|
-
] }) }),
|
|
12779
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12780
|
-
framerMotion.motion.div,
|
|
12781
|
-
{
|
|
12782
|
-
drag: "x",
|
|
12783
|
-
initial: { opacity: 0, x: 0 },
|
|
12784
|
-
animate: { opacity: 1, x: 0 },
|
|
12785
|
-
className: `relative z-10 p-4 border cursor-pointer select-none touch-pan-y transition-colors ${notification.isRead ? "bg-white border-gray-200" : "bg-blue-50 border-blue-200"}`,
|
|
12786
|
-
onClick: handleClick,
|
|
12787
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
12788
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12789
|
-
"div",
|
|
12790
|
-
{
|
|
12791
|
-
className: `flex-shrink-0 w-10 h-10 rounded-full flex items-center justify-center ${getNotificationColor(
|
|
12792
|
-
notification.type
|
|
12793
|
-
)}`,
|
|
12794
|
-
children: getNotificationIcon(notification.type)
|
|
12795
|
-
}
|
|
12796
|
-
),
|
|
12797
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
12798
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
12799
|
-
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-gray-900 text-sm line-clamp-1", children: notification.title }),
|
|
12800
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12801
|
-
"button",
|
|
12802
|
-
{
|
|
12803
|
-
onClick: handleDelete,
|
|
12804
|
-
className: "flex-shrink-0 p-1 bg-gray-100 rounded-full hover:bg-red-50",
|
|
12805
|
-
"aria-label": "Delete notification",
|
|
12806
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4 text-gray-400 hover:text-red-500" })
|
|
12807
|
-
}
|
|
12808
|
-
)
|
|
12809
|
-
] }),
|
|
12810
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600 mt-1 line-clamp-2", children: notification.body }),
|
|
12811
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
12812
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500", children: formatRelativeTime(notification.createdAt) }),
|
|
12813
|
-
!notification.isRead && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12814
|
-
"span",
|
|
12815
|
-
{
|
|
12816
|
-
className: "w-2 h-2 bg-blue-500 rounded-full",
|
|
12817
|
-
"aria-label": "Unread"
|
|
12818
|
-
}
|
|
12819
|
-
)
|
|
12820
|
-
] })
|
|
12821
|
-
] })
|
|
12822
|
-
] })
|
|
12823
|
-
}
|
|
12824
|
-
)
|
|
12825
|
-
] });
|
|
12826
|
-
}
|
|
12827
|
-
function NotificationDrawer() {
|
|
12828
|
-
const {
|
|
12829
|
-
isDrawerOpen,
|
|
12830
|
-
closeDrawer,
|
|
12831
|
-
notifications,
|
|
12832
|
-
unreadCount,
|
|
12833
|
-
isLoading,
|
|
12834
|
-
markAsRead,
|
|
12835
|
-
markAllAsRead,
|
|
12836
|
-
deleteNotification,
|
|
12837
|
-
loadMore,
|
|
12838
|
-
hasMore
|
|
12839
|
-
} = useNotificationCenter();
|
|
12840
|
-
const router = navigation.useRouter();
|
|
12841
|
-
const { buildPath } = useBasePath();
|
|
12842
|
-
const scrollContainerRef = React12.useRef(null);
|
|
12843
|
-
const handleScroll = () => {
|
|
12844
|
-
if (!scrollContainerRef.current || isLoading || !hasMore) return;
|
|
12845
|
-
const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
|
|
12846
|
-
const scrollPercentage = (scrollTop + clientHeight) / scrollHeight;
|
|
12847
|
-
if (scrollPercentage > 0.8) {
|
|
12848
|
-
loadMore();
|
|
12849
|
-
}
|
|
12850
|
-
};
|
|
12851
|
-
React12.useEffect(() => {
|
|
12852
|
-
const handleEscape = (e) => {
|
|
12853
|
-
if (e.key === "Escape" && isDrawerOpen) {
|
|
12854
|
-
closeDrawer();
|
|
12855
|
-
}
|
|
12856
|
-
};
|
|
12857
|
-
document.addEventListener("keydown", handleEscape);
|
|
12858
|
-
return () => document.removeEventListener("keydown", handleEscape);
|
|
12859
|
-
}, [isDrawerOpen, closeDrawer]);
|
|
12860
|
-
React12.useEffect(() => {
|
|
12861
|
-
if (isDrawerOpen) {
|
|
12862
|
-
document.body.style.overflow = "hidden";
|
|
12863
|
-
} else {
|
|
12864
|
-
document.body.style.overflow = "";
|
|
12865
|
-
}
|
|
12866
|
-
return () => {
|
|
12867
|
-
document.body.style.overflow = "";
|
|
12868
|
-
};
|
|
12869
|
-
}, [isDrawerOpen]);
|
|
12870
|
-
const handleSettingsClick = () => {
|
|
12871
|
-
closeDrawer();
|
|
12872
|
-
router.push(buildPath("/account/notifications"));
|
|
12873
|
-
};
|
|
12874
|
-
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isDrawerOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
12875
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12876
|
-
framerMotion.motion.div,
|
|
12877
|
-
{
|
|
12878
|
-
initial: { opacity: 0 },
|
|
12879
|
-
animate: { opacity: 1 },
|
|
12880
|
-
exit: { opacity: 0 },
|
|
12881
|
-
className: "fixed inset-0 bg-black/50 z-40",
|
|
12882
|
-
onClick: closeDrawer
|
|
12883
|
-
}
|
|
12884
|
-
),
|
|
12885
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
12886
|
-
framerMotion.motion.div,
|
|
12887
|
-
{
|
|
12888
|
-
initial: { x: "100%" },
|
|
12889
|
-
animate: { x: 0 },
|
|
12890
|
-
exit: { x: "100%" },
|
|
12891
|
-
transition: { type: "spring", damping: 25, stiffness: 200 },
|
|
12892
|
-
className: "fixed right-0 top-0 bottom-0 w-full sm:w-[480px] bg-white shadow-2xl z-50 flex flex-col max-w-[480px]",
|
|
12893
|
-
children: [
|
|
12894
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b border-gray-200 bg-white", children: [
|
|
12895
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
12896
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold text-gray-900", children: "Notifications" }),
|
|
12897
|
-
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-red-500 text-white text-xs font-bold px-2 py-1 rounded-full", children: unreadCount })
|
|
12898
|
-
] }),
|
|
12899
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
12900
|
-
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12901
|
-
"button",
|
|
12902
|
-
{
|
|
12903
|
-
onClick: markAllAsRead,
|
|
12904
|
-
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
12905
|
-
title: "Mark all as read",
|
|
12906
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { className: "w-5 h-5 text-gray-600" })
|
|
12907
|
-
}
|
|
12908
|
-
),
|
|
12909
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12910
|
-
"button",
|
|
12911
|
-
{
|
|
12912
|
-
onClick: handleSettingsClick,
|
|
12913
|
-
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
12914
|
-
title: "Notification settings",
|
|
12915
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "w-5 h-5 text-gray-600" })
|
|
12916
|
-
}
|
|
12917
|
-
),
|
|
12918
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12919
|
-
"button",
|
|
12920
|
-
{
|
|
12921
|
-
onClick: closeDrawer,
|
|
12922
|
-
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
12923
|
-
"aria-label": "Close",
|
|
12924
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-5 h-5 text-gray-600" })
|
|
12925
|
-
}
|
|
12926
|
-
)
|
|
12927
|
-
] })
|
|
12928
|
-
] }),
|
|
12929
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12930
|
-
"div",
|
|
12931
|
-
{
|
|
12932
|
-
ref: scrollContainerRef,
|
|
12933
|
-
onScroll: handleScroll,
|
|
12934
|
-
className: "flex-1 overflow-y-auto p-4 space-y-3",
|
|
12935
|
-
children: notifications.length === 0 && !isLoading ? (
|
|
12936
|
-
// Empty state
|
|
12937
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center py-12", children: [
|
|
12938
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BellOff, { className: "w-10 h-10 text-gray-400" }) }),
|
|
12939
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: "No notifications yet" }),
|
|
12940
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 max-w-xs", children: "When you receive notifications, they'll appear here" })
|
|
12941
|
-
] })
|
|
12942
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
12943
|
-
notifications.map((notification) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12944
|
-
NotificationCard,
|
|
12945
|
-
{
|
|
12946
|
-
notification,
|
|
12947
|
-
onMarkAsRead: markAsRead,
|
|
12948
|
-
onDelete: deleteNotification
|
|
12949
|
-
},
|
|
12950
|
-
notification._id
|
|
12951
|
-
)),
|
|
12952
|
-
isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 border-2 border-primary-600 border-t-transparent rounded-full animate-spin" }) }),
|
|
12953
|
-
!hasMore && notifications.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-4 text-sm text-gray-500", children: "You're all caught up! \u{1F389}" })
|
|
12954
|
-
] })
|
|
12955
|
-
}
|
|
12956
|
-
)
|
|
12957
|
-
]
|
|
12958
|
-
}
|
|
12959
|
-
)
|
|
12960
|
-
] }) });
|
|
12961
|
-
}
|
|
12962
12694
|
function EcommerceProvider({ config, children, withToaster = true, basePath = "" }) {
|
|
12963
|
-
|
|
12695
|
+
React10__default.default.useMemo(() => {
|
|
12964
12696
|
initializeApiAdapter(config);
|
|
12965
12697
|
}, [config]);
|
|
12966
|
-
const [client] =
|
|
12698
|
+
const [client] = React10__default.default.useState(
|
|
12967
12699
|
new reactQuery.QueryClient({ defaultOptions: { queries: { staleTime: 5e3 } } })
|
|
12968
12700
|
);
|
|
12969
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client, children: /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { config, children: /* @__PURE__ */ jsxRuntime.jsx(BasePathProvider, { basePath, children: /* @__PURE__ */ jsxRuntime.jsx(AuthProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(NotificationProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(NotificationCenterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(CartProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(DiscountProvider, { children: /* @__PURE__ */ jsxRuntime.
|
|
12970
|
-
children,
|
|
12971
|
-
/* @__PURE__ */ jsxRuntime.jsx(NotificationDrawer, {})
|
|
12972
|
-
] }) }) }) }) }) }) }) }) });
|
|
12701
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client, children: /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { config, children: /* @__PURE__ */ jsxRuntime.jsx(BasePathProvider, { basePath, children: /* @__PURE__ */ jsxRuntime.jsx(AuthProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(NotificationProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(NotificationCenterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(CartProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(DiscountProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WishlistProvider, { children }) }) }) }) }) }) }) }) });
|
|
12973
12702
|
}
|
|
12703
|
+
|
|
12704
|
+
// src/lib/constants/assets.ts
|
|
12705
|
+
var PLACEHOLDER_IMAGE_SRC = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjNmNGY2Ii8+CiAgPHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIyNCIgZmlsbD0iIzljYTNhZiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSI+Tm8gSW1hZ2U8L3RleHQ+CiAgPHJlY3QgeD0iMTUwIiB5PSIxMjAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBzdHJva2U9IiM5Y2EzYWYiIHN0cm9rZS13aWR0aD0iNCIgZmlsbD0ibm9uZSIgcng9IjgiLz4KICA8cGF0aCBkPSJNMTUwIDE4MCBMMTcwIDE2MCBMMjAwIDE5MCBMMjIwIDE3MCBMMjUwIDIwMCBMMjUwIDIyMCBMMTUwIDIyMCBaIiBmaWxsPSIjOWNhM2FmIiBvcGFjaXR5PSIwLjUiLz4KPC9zdmc+`;
|
|
12974
12706
|
function QuickViewModal({ product, onClose, onNavigateToProduct }) {
|
|
12975
|
-
const [selectedVariantIndex, setSelectedVariantIndex] =
|
|
12976
|
-
const [selectedSizeIndex, setSelectedSizeIndex] =
|
|
12977
|
-
const [selectedImageIndex, setSelectedImageIndex] =
|
|
12978
|
-
const [addedToCart, setAddedToCart] =
|
|
12979
|
-
const [quantity, setQuantity] =
|
|
12707
|
+
const [selectedVariantIndex, setSelectedVariantIndex] = React10.useState(0);
|
|
12708
|
+
const [selectedSizeIndex, setSelectedSizeIndex] = React10.useState(0);
|
|
12709
|
+
const [selectedImageIndex, setSelectedImageIndex] = React10.useState(0);
|
|
12710
|
+
const [addedToCart, setAddedToCart] = React10.useState(false);
|
|
12711
|
+
const [quantity, setQuantity] = React10.useState(1);
|
|
12980
12712
|
const { addToCart } = useCart();
|
|
12981
|
-
const [isAddingToCart, setIsAddingToCart] =
|
|
12713
|
+
const [isAddingToCart, setIsAddingToCart] = React10.useState(false);
|
|
12982
12714
|
const notification = useNotification();
|
|
12983
12715
|
const handleQuantityChange = (newQuantity) => {
|
|
12984
12716
|
if (newQuantity >= 1 && newQuantity <= (selectedVariant.inventoryCount || 10)) {
|
|
@@ -13129,7 +12861,7 @@ function QuickViewModal({ product, onClose, onNavigateToProduct }) {
|
|
|
13129
12861
|
setSelectedSizeIndex(0);
|
|
13130
12862
|
setSelectedImageIndex(0);
|
|
13131
12863
|
},
|
|
13132
|
-
className: `size-10 rounded-full border-2 transition-all ${selectedVariantIndex === index ? "border-primary scale-110" : "border-gray-200 hover:border-primary
|
|
12864
|
+
className: `size-10 rounded-full border-2 transition-all ${selectedVariantIndex === index ? "border-primary scale-110" : "border-gray-200 hover:border-primary-50"}`,
|
|
13133
12865
|
style: { backgroundColor: variant.colorHex },
|
|
13134
12866
|
title: variant.color,
|
|
13135
12867
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13226,28 +12958,28 @@ function ProductCard({
|
|
|
13226
12958
|
const router = navigation.useRouter();
|
|
13227
12959
|
const { isAuthenticated } = useAuth();
|
|
13228
12960
|
const { buildPath } = useBasePath();
|
|
13229
|
-
const [isFavorite, setIsFavorite] =
|
|
12961
|
+
const [isFavorite, setIsFavorite] = React10.useState(isFavorited);
|
|
13230
12962
|
const { addToWishlist, removeFromWishlist, isInWishlist } = useWishlist();
|
|
13231
12963
|
const { addToCart, isLoading: isAddingToCart } = useCart();
|
|
13232
|
-
const [isHovered, setIsHovered] =
|
|
13233
|
-
const [isImageLoaded, setIsImageLoaded] =
|
|
13234
|
-
const [selectedVariantImage, setSelectedVariantImage] =
|
|
13235
|
-
const [selectedVariantId, setSelectedVariantId] =
|
|
13236
|
-
const [showQuickView, setShowQuickView] =
|
|
12964
|
+
const [isHovered, setIsHovered] = React10.useState(false);
|
|
12965
|
+
const [isImageLoaded, setIsImageLoaded] = React10.useState(false);
|
|
12966
|
+
const [selectedVariantImage, setSelectedVariantImage] = React10.useState(null);
|
|
12967
|
+
const [selectedVariantId, setSelectedVariantId] = React10.useState(null);
|
|
12968
|
+
const [showQuickView, setShowQuickView] = React10.useState(false);
|
|
13237
12969
|
const notification = useNotification();
|
|
13238
|
-
const handleImageLoad =
|
|
12970
|
+
const handleImageLoad = React10.useCallback(() => {
|
|
13239
12971
|
setIsImageLoaded(true);
|
|
13240
12972
|
}, []);
|
|
13241
|
-
const handleCardClick =
|
|
12973
|
+
const handleCardClick = React10.useCallback((e) => {
|
|
13242
12974
|
if (onClickProduct) {
|
|
13243
12975
|
e.preventDefault();
|
|
13244
12976
|
onClickProduct(product);
|
|
13245
12977
|
}
|
|
13246
12978
|
}, [onClickProduct, product]);
|
|
13247
|
-
|
|
12979
|
+
React10.useEffect(() => {
|
|
13248
12980
|
setIsFavorite(isInWishlist(product?._id || "") || isFavorited);
|
|
13249
12981
|
}, [isFavorited, isInWishlist, product?._id]);
|
|
13250
|
-
|
|
12982
|
+
React10.useEffect(() => {
|
|
13251
12983
|
setSelectedVariantImage(null);
|
|
13252
12984
|
setSelectedVariantId(null);
|
|
13253
12985
|
setIsImageLoaded(false);
|
|
@@ -13265,7 +12997,7 @@ function ProductCard({
|
|
|
13265
12997
|
handleCardClick(e);
|
|
13266
12998
|
}
|
|
13267
12999
|
};
|
|
13268
|
-
const variantImages =
|
|
13000
|
+
const variantImages = React10.useMemo(() => {
|
|
13269
13001
|
if (!product.variants || product.variants.length === 0) {
|
|
13270
13002
|
return [];
|
|
13271
13003
|
}
|
|
@@ -13275,35 +13007,35 @@ function ProductCard({
|
|
|
13275
13007
|
image: variant.media[0].file
|
|
13276
13008
|
}));
|
|
13277
13009
|
}, [product.variants]);
|
|
13278
|
-
const selectedVariant =
|
|
13010
|
+
const selectedVariant = React10.useMemo(() => {
|
|
13279
13011
|
if (!selectedVariantId || !product.variants) return null;
|
|
13280
13012
|
return product.variants.find(
|
|
13281
13013
|
(variant) => (variant.id || variant._id) === selectedVariantId
|
|
13282
13014
|
);
|
|
13283
13015
|
}, [selectedVariantId, product.variants]);
|
|
13284
|
-
const displayFinalPrice =
|
|
13016
|
+
const displayFinalPrice = React10.useMemo(() => {
|
|
13285
13017
|
return selectedVariant?.finalPrice ?? product.variants?.[0]?.finalPrice ?? 0;
|
|
13286
13018
|
}, [selectedVariant, product.variants]);
|
|
13287
|
-
const displayPriceBeforeDiscount =
|
|
13019
|
+
const displayPriceBeforeDiscount = React10.useMemo(() => {
|
|
13288
13020
|
return selectedVariant?.retailPrice ?? product.variants?.[0]?.retailPrice ?? 0;
|
|
13289
13021
|
}, [selectedVariant, product.variants]);
|
|
13290
|
-
const displayIsDiscounted =
|
|
13022
|
+
const displayIsDiscounted = React10.useMemo(() => {
|
|
13291
13023
|
return selectedVariant ? selectedVariant.isDiscounted : product.variants?.[0]?.isDiscounted;
|
|
13292
13024
|
}, [selectedVariant, product.variants]);
|
|
13293
|
-
const displayDiscountAmount =
|
|
13025
|
+
const displayDiscountAmount = React10.useMemo(() => {
|
|
13294
13026
|
return selectedVariant ? selectedVariant.discountAmount : product.variants?.[0]?.discountAmount;
|
|
13295
13027
|
}, [selectedVariant, product.variants]);
|
|
13296
|
-
const displayInventoryCount =
|
|
13028
|
+
const displayInventoryCount = React10.useMemo(() => {
|
|
13297
13029
|
return selectedVariant ? selectedVariant.inventoryCount : product.variants?.[0]?.inventoryCount;
|
|
13298
13030
|
}, [selectedVariant, product.variants]);
|
|
13299
|
-
const imageSource =
|
|
13300
|
-
const src = selectedVariantImage || selectedVariant?.media?.[0]?.file || product.media?.[0]?.file ||
|
|
13031
|
+
const imageSource = React10.useMemo(() => {
|
|
13032
|
+
const src = selectedVariantImage || selectedVariant?.media?.[0]?.file || product.media?.[0]?.file || PLACEHOLDER_IMAGE_SRC;
|
|
13301
13033
|
return {
|
|
13302
13034
|
src,
|
|
13303
13035
|
alt: product.name || "Product image"
|
|
13304
13036
|
};
|
|
13305
13037
|
}, [product.media, product.name, selectedVariantImage]);
|
|
13306
|
-
|
|
13038
|
+
React10.useEffect(() => {
|
|
13307
13039
|
setIsImageLoaded(false);
|
|
13308
13040
|
}, [imageSource.src]);
|
|
13309
13041
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -13571,7 +13303,7 @@ function EmptyState({ icon: Icon, title, description, actionLabel, onAction }) {
|
|
|
13571
13303
|
actionLabel && onAction && /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: onAction, children: actionLabel })
|
|
13572
13304
|
] });
|
|
13573
13305
|
}
|
|
13574
|
-
var Input =
|
|
13306
|
+
var Input = React10.forwardRef(
|
|
13575
13307
|
({ label, error, helperText, className = "", ...props }, ref) => {
|
|
13576
13308
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
|
|
13577
13309
|
label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: label }),
|
|
@@ -13662,11 +13394,11 @@ function useProducts(filters, page = 1, limit = 20) {
|
|
|
13662
13394
|
};
|
|
13663
13395
|
}
|
|
13664
13396
|
function useProduct(id) {
|
|
13665
|
-
const [product, setProduct] =
|
|
13666
|
-
const [isLoading, setIsLoading] =
|
|
13667
|
-
const [error, setError] =
|
|
13397
|
+
const [product, setProduct] = React10.useState(null);
|
|
13398
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
13399
|
+
const [error, setError] = React10.useState(null);
|
|
13668
13400
|
console.log("product", product);
|
|
13669
|
-
|
|
13401
|
+
React10.useEffect(() => {
|
|
13670
13402
|
const fetchProduct = async () => {
|
|
13671
13403
|
setIsLoading(true);
|
|
13672
13404
|
setError(null);
|
|
@@ -13683,10 +13415,10 @@ function useProduct(id) {
|
|
|
13683
13415
|
return { product, isLoading, error };
|
|
13684
13416
|
}
|
|
13685
13417
|
function useCategories() {
|
|
13686
|
-
const [categories, setCategories] =
|
|
13687
|
-
const [isLoading, setIsLoading] =
|
|
13688
|
-
const [error, setError] =
|
|
13689
|
-
|
|
13418
|
+
const [categories, setCategories] = React10.useState([]);
|
|
13419
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
13420
|
+
const [error, setError] = React10.useState(null);
|
|
13421
|
+
React10.useEffect(() => {
|
|
13690
13422
|
const fetchCategories = async () => {
|
|
13691
13423
|
try {
|
|
13692
13424
|
setIsLoading(true);
|
|
@@ -13738,20 +13470,20 @@ function getInitials(firstName, lastName) {
|
|
|
13738
13470
|
function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
13739
13471
|
const router = navigation.useRouter();
|
|
13740
13472
|
const { buildPath } = useBasePath();
|
|
13741
|
-
const [filters, setFilters] =
|
|
13742
|
-
const [page, setPage] =
|
|
13743
|
-
const [showFilters, setShowFilters] =
|
|
13744
|
-
const [searchQuery, setSearchQuery] =
|
|
13745
|
-
const [isSearching, setIsSearching] =
|
|
13746
|
-
const [sortOption, setSortOption] =
|
|
13747
|
-
const [viewMode, setViewMode] =
|
|
13748
|
-
const [selectedPriceRange, setSelectedPriceRange] =
|
|
13749
|
-
const [customPrice, setCustomPrice] =
|
|
13473
|
+
const [filters, setFilters] = React10.useState(initialFilters);
|
|
13474
|
+
const [page, setPage] = React10.useState(1);
|
|
13475
|
+
const [showFilters, setShowFilters] = React10.useState(false);
|
|
13476
|
+
const [searchQuery, setSearchQuery] = React10.useState("");
|
|
13477
|
+
const [isSearching, setIsSearching] = React10.useState(false);
|
|
13478
|
+
const [sortOption, setSortOption] = React10.useState("featured");
|
|
13479
|
+
const [viewMode, setViewMode] = React10.useState("grid");
|
|
13480
|
+
const [selectedPriceRange, setSelectedPriceRange] = React10.useState(null);
|
|
13481
|
+
const [customPrice, setCustomPrice] = React10.useState({
|
|
13750
13482
|
min: "",
|
|
13751
13483
|
max: ""
|
|
13752
13484
|
});
|
|
13753
|
-
const [expandedCategories, setExpandedCategories] =
|
|
13754
|
-
const [expandedFilterSections, setExpandedFilterSections] =
|
|
13485
|
+
const [expandedCategories, setExpandedCategories] = React10.useState({});
|
|
13486
|
+
const [expandedFilterSections, setExpandedFilterSections] = React10.useState({
|
|
13755
13487
|
category: true
|
|
13756
13488
|
// Category section starts expanded
|
|
13757
13489
|
});
|
|
@@ -13778,7 +13510,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13778
13510
|
}
|
|
13779
13511
|
}
|
|
13780
13512
|
};
|
|
13781
|
-
const priceRanges =
|
|
13513
|
+
const priceRanges = React10.useMemo(
|
|
13782
13514
|
() => [
|
|
13783
13515
|
{ label: `Under ${formatPrice(25)}`, value: "under-25", min: void 0, max: 25 },
|
|
13784
13516
|
{ label: `${formatPrice(25)} - ${formatPrice(50)}`, value: "25-50", min: 25, max: 50 },
|
|
@@ -13787,13 +13519,13 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13787
13519
|
],
|
|
13788
13520
|
[]
|
|
13789
13521
|
);
|
|
13790
|
-
|
|
13522
|
+
React10.useEffect(() => {
|
|
13791
13523
|
setCustomPrice({
|
|
13792
13524
|
min: filters.minPrice !== void 0 ? String(filters.minPrice) : "",
|
|
13793
13525
|
max: filters.maxPrice !== void 0 ? String(filters.maxPrice) : ""
|
|
13794
13526
|
});
|
|
13795
13527
|
}, [filters.minPrice, filters.maxPrice]);
|
|
13796
|
-
|
|
13528
|
+
React10.useEffect(() => {
|
|
13797
13529
|
const updates = {};
|
|
13798
13530
|
if (filters.category) updates[filters.category] = true;
|
|
13799
13531
|
if (filters.subCategory) {
|
|
@@ -13807,18 +13539,18 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13807
13539
|
setExpandedCategories((prev) => ({ ...prev, ...updates }));
|
|
13808
13540
|
}
|
|
13809
13541
|
}, [filters.category, filters.subCategory, categories]);
|
|
13810
|
-
const toggleCategoryExpand =
|
|
13542
|
+
const toggleCategoryExpand = React10.useCallback((id) => {
|
|
13811
13543
|
setExpandedCategories((prev) => ({ ...prev, [id]: !prev[id] }));
|
|
13812
13544
|
}, []);
|
|
13813
|
-
const sortedCategories =
|
|
13545
|
+
const sortedCategories = React10.useMemo(
|
|
13814
13546
|
() => [...categories].sort((a, b) => a.name?.localeCompare(b.name ?? "") ?? 0),
|
|
13815
13547
|
[categories]
|
|
13816
13548
|
);
|
|
13817
|
-
const topCategories =
|
|
13549
|
+
const topCategories = React10.useMemo(
|
|
13818
13550
|
() => [...categories].sort((a, b) => (b.productCount ?? 0) - (a.productCount ?? 0)).slice(0, 6),
|
|
13819
13551
|
[categories]
|
|
13820
13552
|
);
|
|
13821
|
-
const productInsights =
|
|
13553
|
+
const productInsights = React10.useMemo(() => {
|
|
13822
13554
|
if (!products.length) {
|
|
13823
13555
|
return { newArrivals: 0, inStockCount: 0 };
|
|
13824
13556
|
}
|
|
@@ -13831,7 +13563,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13831
13563
|
});
|
|
13832
13564
|
return { newArrivals: newArrivals2, inStockCount };
|
|
13833
13565
|
}, [products]);
|
|
13834
|
-
|
|
13566
|
+
React10.useMemo(
|
|
13835
13567
|
() => [
|
|
13836
13568
|
{
|
|
13837
13569
|
id: "new",
|
|
@@ -13864,7 +13596,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13864
13596
|
filters.newArrivals
|
|
13865
13597
|
]
|
|
13866
13598
|
);
|
|
13867
|
-
const filteredProducts =
|
|
13599
|
+
const filteredProducts = React10.useMemo(() => {
|
|
13868
13600
|
if (isLoading) return products;
|
|
13869
13601
|
let items = [...products];
|
|
13870
13602
|
if (filters.tags?.length) {
|
|
@@ -13879,7 +13611,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13879
13611
|
}
|
|
13880
13612
|
return items;
|
|
13881
13613
|
}, [isLoading, products, filters.tags, filters.newArrivals, filters.brand]);
|
|
13882
|
-
const sortedProducts =
|
|
13614
|
+
const sortedProducts = React10.useMemo(() => {
|
|
13883
13615
|
if (isLoading) {
|
|
13884
13616
|
return filteredProducts;
|
|
13885
13617
|
}
|
|
@@ -13898,7 +13630,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13898
13630
|
}
|
|
13899
13631
|
}, [isLoading, filteredProducts, sortOption]);
|
|
13900
13632
|
const displayedProducts = sortedProducts;
|
|
13901
|
-
const availableBrands =
|
|
13633
|
+
const availableBrands = React10.useMemo(() => {
|
|
13902
13634
|
const brandSet = /* @__PURE__ */ new Set();
|
|
13903
13635
|
products.forEach((product) => {
|
|
13904
13636
|
if (product.brand && product.brand.trim()) {
|
|
@@ -13907,14 +13639,14 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13907
13639
|
});
|
|
13908
13640
|
return Array.from(brandSet).sort();
|
|
13909
13641
|
}, [products]);
|
|
13910
|
-
|
|
13642
|
+
React10.useMemo(() => {
|
|
13911
13643
|
const counts = /* @__PURE__ */ new Map();
|
|
13912
13644
|
products.forEach((p) => {
|
|
13913
13645
|
(p.tags || []).forEach((t) => counts.set(t, (counts.get(t) || 0) + 1));
|
|
13914
13646
|
});
|
|
13915
13647
|
return Array.from(counts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 4).map(([tag]) => tag);
|
|
13916
13648
|
}, [products]);
|
|
13917
|
-
|
|
13649
|
+
React10.useCallback((term) => {
|
|
13918
13650
|
setSearchQuery("");
|
|
13919
13651
|
setFilters((current) => ({
|
|
13920
13652
|
...current,
|
|
@@ -13923,7 +13655,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13923
13655
|
}));
|
|
13924
13656
|
setPage(1);
|
|
13925
13657
|
}, []);
|
|
13926
|
-
const handleCategoryChange =
|
|
13658
|
+
const handleCategoryChange = React10.useCallback(
|
|
13927
13659
|
(categorySlug) => {
|
|
13928
13660
|
setFilters((current) => {
|
|
13929
13661
|
if (current.category === categorySlug) {
|
|
@@ -13940,7 +13672,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13940
13672
|
},
|
|
13941
13673
|
[]
|
|
13942
13674
|
);
|
|
13943
|
-
|
|
13675
|
+
React10.useCallback((parentCategoryId, subCategoryId) => {
|
|
13944
13676
|
setFilters((current) => {
|
|
13945
13677
|
if (current.subCategory === subCategoryId) {
|
|
13946
13678
|
const { subCategory, ...rest } = current;
|
|
@@ -13950,7 +13682,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13950
13682
|
});
|
|
13951
13683
|
setPage(1);
|
|
13952
13684
|
}, []);
|
|
13953
|
-
const handleToggleStock =
|
|
13685
|
+
const handleToggleStock = React10.useCallback(() => {
|
|
13954
13686
|
setFilters((current) => {
|
|
13955
13687
|
if (current.inStock) {
|
|
13956
13688
|
const { inStock, ...rest } = current;
|
|
@@ -13960,7 +13692,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13960
13692
|
});
|
|
13961
13693
|
setPage(1);
|
|
13962
13694
|
}, []);
|
|
13963
|
-
const handleToggleNewArrivals =
|
|
13695
|
+
const handleToggleNewArrivals = React10.useCallback(() => {
|
|
13964
13696
|
setFilters((current) => {
|
|
13965
13697
|
if (current.newArrivals) {
|
|
13966
13698
|
const { newArrivals: newArrivals2, ...rest } = current;
|
|
@@ -13970,28 +13702,28 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13970
13702
|
});
|
|
13971
13703
|
setPage(1);
|
|
13972
13704
|
}, []);
|
|
13973
|
-
const handleClearCategory =
|
|
13705
|
+
const handleClearCategory = React10.useCallback(() => {
|
|
13974
13706
|
setFilters((current) => {
|
|
13975
13707
|
const { category, subCategory, ...rest } = current;
|
|
13976
13708
|
return rest;
|
|
13977
13709
|
});
|
|
13978
13710
|
setPage(1);
|
|
13979
13711
|
}, []);
|
|
13980
|
-
const handleClearFilters =
|
|
13712
|
+
const handleClearFilters = React10.useCallback(() => {
|
|
13981
13713
|
setFilters({});
|
|
13982
13714
|
setSearchQuery("");
|
|
13983
13715
|
setSelectedPriceRange(null);
|
|
13984
13716
|
setCustomPrice({ min: "", max: "" });
|
|
13985
13717
|
setPage(1);
|
|
13986
13718
|
}, []);
|
|
13987
|
-
const handleRemoveCategory =
|
|
13719
|
+
const handleRemoveCategory = React10.useCallback(() => {
|
|
13988
13720
|
setFilters((current) => {
|
|
13989
13721
|
const { category, subCategory, ...rest } = current;
|
|
13990
13722
|
return rest;
|
|
13991
13723
|
});
|
|
13992
13724
|
setPage(1);
|
|
13993
13725
|
}, []);
|
|
13994
|
-
const handleRemoveSubCategory =
|
|
13726
|
+
const handleRemoveSubCategory = React10.useCallback(() => {
|
|
13995
13727
|
setFilters((current) => {
|
|
13996
13728
|
const next = { ...current };
|
|
13997
13729
|
delete next.subCategory;
|
|
@@ -13999,7 +13731,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
13999
13731
|
});
|
|
14000
13732
|
setPage(1);
|
|
14001
13733
|
}, []);
|
|
14002
|
-
const handleRemoveSearch =
|
|
13734
|
+
const handleRemoveSearch = React10.useCallback(() => {
|
|
14003
13735
|
setFilters((current) => {
|
|
14004
13736
|
const { search, ...rest } = current;
|
|
14005
13737
|
return rest;
|
|
@@ -14007,14 +13739,14 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14007
13739
|
setSearchQuery("");
|
|
14008
13740
|
setPage(1);
|
|
14009
13741
|
}, []);
|
|
14010
|
-
const handleRemoveInStock =
|
|
13742
|
+
const handleRemoveInStock = React10.useCallback(() => {
|
|
14011
13743
|
setFilters((current) => {
|
|
14012
13744
|
const { inStock, ...rest } = current;
|
|
14013
13745
|
return rest;
|
|
14014
13746
|
});
|
|
14015
13747
|
setPage(1);
|
|
14016
13748
|
}, []);
|
|
14017
|
-
const handleRemovePrice =
|
|
13749
|
+
const handleRemovePrice = React10.useCallback(() => {
|
|
14018
13750
|
setFilters((current) => {
|
|
14019
13751
|
const next = { ...current };
|
|
14020
13752
|
delete next.minPrice;
|
|
@@ -14025,7 +13757,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14025
13757
|
setCustomPrice({ min: "", max: "" });
|
|
14026
13758
|
setPage(1);
|
|
14027
13759
|
}, []);
|
|
14028
|
-
const handleRemoveTag =
|
|
13760
|
+
const handleRemoveTag = React10.useCallback((tag) => {
|
|
14029
13761
|
setFilters((current) => {
|
|
14030
13762
|
if (!current.tags) return current;
|
|
14031
13763
|
const updated = current.tags.filter((item) => item !== tag);
|
|
@@ -14039,7 +13771,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14039
13771
|
});
|
|
14040
13772
|
setPage(1);
|
|
14041
13773
|
}, []);
|
|
14042
|
-
const handleBrandChange =
|
|
13774
|
+
const handleBrandChange = React10.useCallback((brand) => {
|
|
14043
13775
|
setFilters((current) => {
|
|
14044
13776
|
if (current.brand === brand) {
|
|
14045
13777
|
const { brand: _, ...rest } = current;
|
|
@@ -14049,14 +13781,14 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14049
13781
|
});
|
|
14050
13782
|
setPage(1);
|
|
14051
13783
|
}, []);
|
|
14052
|
-
const handleRemoveBrand =
|
|
13784
|
+
const handleRemoveBrand = React10.useCallback(() => {
|
|
14053
13785
|
setFilters((current) => {
|
|
14054
13786
|
const { brand, ...rest } = current;
|
|
14055
13787
|
return rest;
|
|
14056
13788
|
});
|
|
14057
13789
|
setPage(1);
|
|
14058
13790
|
}, []);
|
|
14059
|
-
const handlePriceRangeSelect =
|
|
13791
|
+
const handlePriceRangeSelect = React10.useCallback(
|
|
14060
13792
|
(value) => {
|
|
14061
13793
|
const range = priceRanges.find((item) => item.value === value);
|
|
14062
13794
|
if (selectedPriceRange === value) {
|
|
@@ -14095,7 +13827,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14095
13827
|
},
|
|
14096
13828
|
[priceRanges, selectedPriceRange]
|
|
14097
13829
|
);
|
|
14098
|
-
const applyCustomPrice =
|
|
13830
|
+
const applyCustomPrice = React10.useCallback(() => {
|
|
14099
13831
|
const rawMin = customPrice.min.trim();
|
|
14100
13832
|
const rawMax = customPrice.max.trim();
|
|
14101
13833
|
const minValue = rawMin !== "" ? Number(rawMin) : void 0;
|
|
@@ -14133,7 +13865,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14133
13865
|
newArrivals,
|
|
14134
13866
|
brand: brandFilter
|
|
14135
13867
|
} = filters;
|
|
14136
|
-
const activeFilterChips =
|
|
13868
|
+
const activeFilterChips = React10.useMemo(() => {
|
|
14137
13869
|
const chips = [];
|
|
14138
13870
|
if (searchFilter) {
|
|
14139
13871
|
chips.push({
|
|
@@ -14234,7 +13966,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14234
13966
|
]);
|
|
14235
13967
|
const hasActiveFilters = activeFilterChips.length > 0;
|
|
14236
13968
|
const isCustomPriceDirty = customPrice.min.trim() !== "" || customPrice.max.trim() !== "";
|
|
14237
|
-
const toggleFilterSection =
|
|
13969
|
+
const toggleFilterSection = React10.useCallback((section) => {
|
|
14238
13970
|
setExpandedFilterSections((prev) => ({
|
|
14239
13971
|
...prev,
|
|
14240
13972
|
[section]: !prev[section]
|
|
@@ -14402,14 +14134,14 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14402
14134
|
type: "button",
|
|
14403
14135
|
onClick: applyCustomPrice,
|
|
14404
14136
|
disabled: !isCustomPriceDirty,
|
|
14405
|
-
className: "w-full rounded-lg border border-primary bg-primary
|
|
14137
|
+
className: "w-full rounded-lg border border-primary bg-primary-10 px-4 py-2 text-sm font-medium text-primary transition hover:bg-primary-20 disabled:cursor-not-allowed disabled:border-slate-200 disabled:text-slate-400",
|
|
14406
14138
|
children: "Apply"
|
|
14407
14139
|
}
|
|
14408
14140
|
)
|
|
14409
14141
|
] })
|
|
14410
14142
|
] })
|
|
14411
14143
|
] }) }) }) });
|
|
14412
|
-
const displayCategories =
|
|
14144
|
+
const displayCategories = React10.useMemo(() => {
|
|
14413
14145
|
return topCategories.slice(0, 5);
|
|
14414
14146
|
}, [topCategories]);
|
|
14415
14147
|
const getCategoryIcon = (categoryName2) => {
|
|
@@ -14470,7 +14202,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14470
14202
|
animate: { opacity: 1, y: 0 },
|
|
14471
14203
|
className: `group relative overflow-hidden rounded-[24px] p-6 min-h-[180px] min-w-[170px] transition-all duration-300 ${!categoryFilter ? "bg-linear-to-br from-primary to-secondary text-white shadow-xl scale-105" : "bg-linear-to-br from-gray-50 to-white hover:shadow-lg border-2 border-gray-100 hover:border-primary"}`,
|
|
14472
14204
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
14473
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `size-12 rounded-full mb-3 mx-auto flex items-center justify-center transition-all ${!categoryFilter ? "bg-white/20" : "bg-linear-to-br from-primary
|
|
14205
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `size-12 rounded-full mb-3 mx-auto flex items-center justify-center transition-all ${!categoryFilter ? "bg-white/20" : "bg-linear-to-br from-primary-10 to-secondary-10 group-hover:scale-110"}`, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className: `size-6 ${!categoryFilter ? "text-white" : "text-primary"}` }) }),
|
|
14474
14206
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: `font-['Poppins',sans-serif] font-semibold text-[14px] mb-1.5 ${!categoryFilter ? "text-white" : "text-secondary"}`, children: "All Products" }),
|
|
14475
14207
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `font-['Poppins',sans-serif] text-[11px] ${!categoryFilter ? "text-white/80" : "text-muted"}`, children: "Browse Everything" })
|
|
14476
14208
|
] })
|
|
@@ -14489,7 +14221,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14489
14221
|
onClick: () => handleCategoryChange(categoryId),
|
|
14490
14222
|
className: `group relative overflow-hidden rounded-[24px] p-6 min-h-[180px] min-w-[170px] transition-all duration-300 ${isSelected ? "bg-linear-to-br from-primary to-secondary text-white shadow-xl scale-105" : "bg-linear-to-br from-gray-50 to-white hover:shadow-lg border-2 border-gray-100 hover:border-primary"}`,
|
|
14491
14223
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
14492
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `size-12 rounded-full mb-3 mx-auto flex items-center justify-center transition-all ${isSelected ? "bg-white/20" : "bg-linear-to-br from-primary
|
|
14224
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `size-12 rounded-full mb-3 mx-auto flex items-center justify-center transition-all ${isSelected ? "bg-white/20" : "bg-linear-to-br from-primary-10 to-secondary-10 group-hover:scale-110"}`, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: `size-6 ${isSelected ? "text-white" : "text-primary"}` }) }),
|
|
14493
14225
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: `font-['Poppins',sans-serif] font-semibold text-[14px] mb-1.5 ${isSelected ? "text-white" : "text-secondary"}`, children: category.name }),
|
|
14494
14226
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `font-['Poppins',sans-serif] text-[11px] ${isSelected ? "text-white/80" : "text-muted"}`, children: category.description })
|
|
14495
14227
|
] })
|
|
@@ -14600,7 +14332,7 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14600
14332
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-48 w-full overflow-hidden rounded-2xl bg-gray-100 md:h-40 md:w-40", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14601
14333
|
Image4__default.default,
|
|
14602
14334
|
{
|
|
14603
|
-
src: product.media?.[0]?.file ||
|
|
14335
|
+
src: product.media?.[0]?.file || PLACEHOLDER_IMAGE_SRC,
|
|
14604
14336
|
alt: product.name,
|
|
14605
14337
|
fill: true,
|
|
14606
14338
|
className: "object-cover transition duration-500 group-hover:scale-105"
|
|
@@ -14691,10 +14423,10 @@ function ShopScreen({ initialFilters = {}, categoryName }) {
|
|
|
14691
14423
|
] });
|
|
14692
14424
|
}
|
|
14693
14425
|
function useProductReviews(productId) {
|
|
14694
|
-
const [reviews, setReviews] =
|
|
14695
|
-
const [isLoading, setIsLoading] =
|
|
14696
|
-
const [error, setError] =
|
|
14697
|
-
const fetchReviews =
|
|
14426
|
+
const [reviews, setReviews] = React10.useState([]);
|
|
14427
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
14428
|
+
const [error, setError] = React10.useState(null);
|
|
14429
|
+
const fetchReviews = React10.useCallback(async () => {
|
|
14698
14430
|
if (!productId) {
|
|
14699
14431
|
setIsLoading(false);
|
|
14700
14432
|
return;
|
|
@@ -14710,7 +14442,7 @@ function useProductReviews(productId) {
|
|
|
14710
14442
|
setIsLoading(false);
|
|
14711
14443
|
}
|
|
14712
14444
|
}, [productId]);
|
|
14713
|
-
|
|
14445
|
+
React10.useEffect(() => {
|
|
14714
14446
|
fetchReviews();
|
|
14715
14447
|
}, [fetchReviews]);
|
|
14716
14448
|
return {
|
|
@@ -14721,12 +14453,12 @@ function useProductReviews(productId) {
|
|
|
14721
14453
|
};
|
|
14722
14454
|
}
|
|
14723
14455
|
function useUserReviews(userId) {
|
|
14724
|
-
const [reviews, setReviews] =
|
|
14725
|
-
const [isLoading, setIsLoading] =
|
|
14726
|
-
const [error, setError] =
|
|
14456
|
+
const [reviews, setReviews] = React10.useState([]);
|
|
14457
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
14458
|
+
const [error, setError] = React10.useState(null);
|
|
14727
14459
|
const { user } = useAuth();
|
|
14728
14460
|
const resolvedUserId = userId || user?._id || user?.id;
|
|
14729
|
-
const fetchReviews =
|
|
14461
|
+
const fetchReviews = React10.useCallback(async () => {
|
|
14730
14462
|
if (!resolvedUserId) {
|
|
14731
14463
|
setIsLoading(false);
|
|
14732
14464
|
return;
|
|
@@ -14742,7 +14474,7 @@ function useUserReviews(userId) {
|
|
|
14742
14474
|
setIsLoading(false);
|
|
14743
14475
|
}
|
|
14744
14476
|
}, [resolvedUserId]);
|
|
14745
|
-
|
|
14477
|
+
React10.useEffect(() => {
|
|
14746
14478
|
fetchReviews();
|
|
14747
14479
|
}, [fetchReviews]);
|
|
14748
14480
|
return {
|
|
@@ -14753,10 +14485,10 @@ function useUserReviews(userId) {
|
|
|
14753
14485
|
};
|
|
14754
14486
|
}
|
|
14755
14487
|
function useReviewsByRating(rating) {
|
|
14756
|
-
const [reviews, setReviews] =
|
|
14757
|
-
const [isLoading, setIsLoading] =
|
|
14758
|
-
const [error, setError] =
|
|
14759
|
-
const fetchReviews =
|
|
14488
|
+
const [reviews, setReviews] = React10.useState([]);
|
|
14489
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
14490
|
+
const [error, setError] = React10.useState(null);
|
|
14491
|
+
const fetchReviews = React10.useCallback(async () => {
|
|
14760
14492
|
if (!rating || rating < 1 || rating > 5) {
|
|
14761
14493
|
setIsLoading(false);
|
|
14762
14494
|
return;
|
|
@@ -14772,7 +14504,7 @@ function useReviewsByRating(rating) {
|
|
|
14772
14504
|
setIsLoading(false);
|
|
14773
14505
|
}
|
|
14774
14506
|
}, [rating]);
|
|
14775
|
-
|
|
14507
|
+
React10.useEffect(() => {
|
|
14776
14508
|
fetchReviews();
|
|
14777
14509
|
}, [fetchReviews]);
|
|
14778
14510
|
return {
|
|
@@ -14783,10 +14515,10 @@ function useReviewsByRating(rating) {
|
|
|
14783
14515
|
};
|
|
14784
14516
|
}
|
|
14785
14517
|
function useCreateReview() {
|
|
14786
|
-
const [isLoading, setIsLoading] =
|
|
14787
|
-
const [error, setError] =
|
|
14788
|
-
const [success, setSuccess] =
|
|
14789
|
-
const createReview =
|
|
14518
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
14519
|
+
const [error, setError] = React10.useState(null);
|
|
14520
|
+
const [success, setSuccess] = React10.useState(false);
|
|
14521
|
+
const createReview = React10.useCallback(async (orderId, reviewData) => {
|
|
14790
14522
|
setIsLoading(true);
|
|
14791
14523
|
setError(null);
|
|
14792
14524
|
setSuccess(false);
|
|
@@ -14801,7 +14533,7 @@ function useCreateReview() {
|
|
|
14801
14533
|
setIsLoading(false);
|
|
14802
14534
|
}
|
|
14803
14535
|
}, []);
|
|
14804
|
-
const reset =
|
|
14536
|
+
const reset = React10.useCallback(() => {
|
|
14805
14537
|
setError(null);
|
|
14806
14538
|
setSuccess(false);
|
|
14807
14539
|
setIsLoading(false);
|
|
@@ -14815,9 +14547,9 @@ function useCreateReview() {
|
|
|
14815
14547
|
};
|
|
14816
14548
|
}
|
|
14817
14549
|
function useUpdateReview() {
|
|
14818
|
-
const [isLoading, setIsLoading] =
|
|
14819
|
-
const [error, setError] =
|
|
14820
|
-
const updateReview =
|
|
14550
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
14551
|
+
const [error, setError] = React10.useState(null);
|
|
14552
|
+
const updateReview = React10.useCallback(async (reviewId, reviewData) => {
|
|
14821
14553
|
setIsLoading(true);
|
|
14822
14554
|
setError(null);
|
|
14823
14555
|
try {
|
|
@@ -14837,9 +14569,9 @@ function useUpdateReview() {
|
|
|
14837
14569
|
};
|
|
14838
14570
|
}
|
|
14839
14571
|
function useDeleteReview() {
|
|
14840
|
-
const [isLoading, setIsLoading] =
|
|
14841
|
-
const [error, setError] =
|
|
14842
|
-
const deleteReview =
|
|
14572
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
14573
|
+
const [error, setError] = React10.useState(null);
|
|
14574
|
+
const deleteReview = React10.useCallback(async (reviewId) => {
|
|
14843
14575
|
setIsLoading(true);
|
|
14844
14576
|
setError(null);
|
|
14845
14577
|
try {
|
|
@@ -14858,10 +14590,10 @@ function useDeleteReview() {
|
|
|
14858
14590
|
};
|
|
14859
14591
|
}
|
|
14860
14592
|
function useReviewStats() {
|
|
14861
|
-
const [count, setCount] =
|
|
14862
|
-
const [isLoading, setIsLoading] =
|
|
14863
|
-
const [error, setError] =
|
|
14864
|
-
const fetchCount =
|
|
14593
|
+
const [count, setCount] = React10.useState(0);
|
|
14594
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
14595
|
+
const [error, setError] = React10.useState(null);
|
|
14596
|
+
const fetchCount = React10.useCallback(async () => {
|
|
14865
14597
|
setIsLoading(true);
|
|
14866
14598
|
setError(null);
|
|
14867
14599
|
try {
|
|
@@ -14873,7 +14605,7 @@ function useReviewStats() {
|
|
|
14873
14605
|
setIsLoading(false);
|
|
14874
14606
|
}
|
|
14875
14607
|
}, []);
|
|
14876
|
-
|
|
14608
|
+
React10.useEffect(() => {
|
|
14877
14609
|
fetchCount();
|
|
14878
14610
|
}, [fetchCount]);
|
|
14879
14611
|
return {
|
|
@@ -14897,7 +14629,7 @@ function StarRating({
|
|
|
14897
14629
|
onChange,
|
|
14898
14630
|
className
|
|
14899
14631
|
}) {
|
|
14900
|
-
const [hoverRating, setHoverRating] =
|
|
14632
|
+
const [hoverRating, setHoverRating] = React10__default.default.useState(0);
|
|
14901
14633
|
const handleClick = (index) => {
|
|
14902
14634
|
if (interactive && onChange) {
|
|
14903
14635
|
onChange(index + 1);
|
|
@@ -15027,9 +14759,9 @@ function ReviewCard({ review, showProductInfo = false }) {
|
|
|
15027
14759
|
] });
|
|
15028
14760
|
}
|
|
15029
14761
|
function ReviewsList({ reviews, isLoading }) {
|
|
15030
|
-
const [filterRating, setFilterRating] =
|
|
15031
|
-
const [sortBy, setSortBy] =
|
|
15032
|
-
const filteredReviews =
|
|
14762
|
+
const [filterRating, setFilterRating] = React10.useState("all");
|
|
14763
|
+
const [sortBy, setSortBy] = React10.useState("recent");
|
|
14764
|
+
const filteredReviews = React10__default.default.useMemo(() => {
|
|
15033
14765
|
let filtered = [...reviews];
|
|
15034
14766
|
if (filterRating !== "all") {
|
|
15035
14767
|
filtered = filtered.filter((review) => Math.floor(review.rating) === filterRating);
|
|
@@ -15166,18 +14898,18 @@ function ProductDetailScreen({ productId }) {
|
|
|
15166
14898
|
const { isAuthenticated } = useAuth();
|
|
15167
14899
|
const notification = useNotification();
|
|
15168
14900
|
const { reviews, isLoading: reviewsLoading } = useProductReviews(productId);
|
|
15169
|
-
const [selectedVariant, setSelectedVariant] =
|
|
15170
|
-
const [quantity, setQuantity] =
|
|
15171
|
-
const [isAddingToCart, setIsAddingToCart] =
|
|
15172
|
-
const [isFavorited, setIsFavorited] =
|
|
15173
|
-
const [relatedProducts, setRelatedProducts] =
|
|
15174
|
-
const [initialProductData, setInitialProductData] =
|
|
15175
|
-
const [activeImageIndex, setActiveImageIndex] =
|
|
15176
|
-
const [activeTab, setActiveTab] =
|
|
15177
|
-
|
|
14901
|
+
const [selectedVariant, setSelectedVariant] = React10.useState(null);
|
|
14902
|
+
const [quantity, setQuantity] = React10.useState(1);
|
|
14903
|
+
const [isAddingToCart, setIsAddingToCart] = React10.useState(false);
|
|
14904
|
+
const [isFavorited, setIsFavorited] = React10.useState(false);
|
|
14905
|
+
const [relatedProducts, setRelatedProducts] = React10.useState([]);
|
|
14906
|
+
const [initialProductData, setInitialProductData] = React10.useState(null);
|
|
14907
|
+
const [activeImageIndex, setActiveImageIndex] = React10.useState(0);
|
|
14908
|
+
const [activeTab, setActiveTab] = React10.useState("description");
|
|
14909
|
+
React10.useEffect(() => {
|
|
15178
14910
|
setActiveImageIndex(0);
|
|
15179
14911
|
}, [selectedVariant]);
|
|
15180
|
-
const product =
|
|
14912
|
+
const product = React10.useMemo(() => {
|
|
15181
14913
|
if (initialProductData && !productData) {
|
|
15182
14914
|
return initialProductData;
|
|
15183
14915
|
}
|
|
@@ -15194,7 +14926,7 @@ function ProductDetailScreen({ productId }) {
|
|
|
15194
14926
|
}
|
|
15195
14927
|
return productData;
|
|
15196
14928
|
}, [productData, selectedVariant, initialProductData]);
|
|
15197
|
-
const reviewStats =
|
|
14929
|
+
const reviewStats = React10.useMemo(() => {
|
|
15198
14930
|
if (!reviews || reviews.length === 0) {
|
|
15199
14931
|
return {
|
|
15200
14932
|
averageRating: product?.rating || 0,
|
|
@@ -15253,7 +14985,7 @@ function ProductDetailScreen({ productId }) {
|
|
|
15253
14985
|
);
|
|
15254
14986
|
currentVariant?.sku || product?.sku || "N/A";
|
|
15255
14987
|
currentVariant?.inventoryCount > 0;
|
|
15256
|
-
|
|
14988
|
+
React10.useEffect(() => {
|
|
15257
14989
|
if (typeof window === "undefined") return;
|
|
15258
14990
|
const searchParams = new URLSearchParams(window.location.search);
|
|
15259
14991
|
const productParam = searchParams.get("product");
|
|
@@ -15266,13 +14998,13 @@ function ProductDetailScreen({ productId }) {
|
|
|
15266
14998
|
}
|
|
15267
14999
|
}
|
|
15268
15000
|
}, []);
|
|
15269
|
-
|
|
15001
|
+
React10.useEffect(() => {
|
|
15270
15002
|
if (product?.productVariants?.length > 0) {
|
|
15271
15003
|
const newVariant = product?.productVariants?.[0];
|
|
15272
15004
|
setSelectedVariant(newVariant);
|
|
15273
15005
|
}
|
|
15274
15006
|
}, [product?.productVariants]);
|
|
15275
|
-
|
|
15007
|
+
React10.useEffect(() => {
|
|
15276
15008
|
if (!product?._id) return;
|
|
15277
15009
|
const fetchRelated = async () => {
|
|
15278
15010
|
try {
|
|
@@ -15321,7 +15053,7 @@ function ProductDetailScreen({ productId }) {
|
|
|
15321
15053
|
}
|
|
15322
15054
|
};
|
|
15323
15055
|
const { addToWishlist, removeFromWishlist, isInWishlist } = useWishlist();
|
|
15324
|
-
|
|
15056
|
+
React10.useEffect(() => {
|
|
15325
15057
|
if (product) {
|
|
15326
15058
|
setIsFavorited(isInWishlist(product._id));
|
|
15327
15059
|
}
|
|
@@ -15432,7 +15164,7 @@ function ProductDetailScreen({ productId }) {
|
|
|
15432
15164
|
{
|
|
15433
15165
|
type: "button",
|
|
15434
15166
|
onClick: () => setActiveImageIndex(index),
|
|
15435
|
-
className: `relative aspect-square overflow-hidden rounded-lg border-2 transition-all ${activeImageIndex === index ? "border-primary
|
|
15167
|
+
className: `relative aspect-square overflow-hidden rounded-lg border-2 transition-all ${activeImageIndex === index ? "border-primary-50 ring-2 ring-primary-80 ring-offset-2 shadow-md" : "border-slate-200 hover:border-primary-50"}`,
|
|
15436
15168
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15437
15169
|
Image4__default.default,
|
|
15438
15170
|
{
|
|
@@ -15520,13 +15252,13 @@ function ProductDetailScreen({ productId }) {
|
|
|
15520
15252
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-['Poppins',sans-serif] font-semibold text-[14px] text-secondary mb-3", children: "Select Variant" }),
|
|
15521
15253
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3", children: product.variants.map((variant) => {
|
|
15522
15254
|
const isSelected = selectedVariant?._id === variant._id;
|
|
15523
|
-
const variantImage = variant.media?.[0]?.file || product.media?.[0]?.file || product.images?.[0] ||
|
|
15255
|
+
const variantImage = variant.media?.[0]?.file || product.media?.[0]?.file || product.images?.[0] || PLACEHOLDER_IMAGE_SRC;
|
|
15524
15256
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15525
15257
|
"button",
|
|
15526
15258
|
{
|
|
15527
15259
|
type: "button",
|
|
15528
15260
|
onClick: () => handleVariantSelect(variant),
|
|
15529
|
-
className: `flex items-start gap-3 px-4 py-2.5 rounded-xl border-2 transition-all ${isSelected ? "border-primary bg-primary
|
|
15261
|
+
className: `flex items-start gap-3 px-4 py-2.5 rounded-xl border-2 transition-all ${isSelected ? "border-primary bg-primary-5" : "border-gray-200 hover:border-primary-50"}`,
|
|
15530
15262
|
children: [
|
|
15531
15263
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative h-12 w-12 shrink-0 overflow-hidden rounded-full border-2 ${isSelected ? "border-primary" : "border-slate-200"}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15532
15264
|
Image4__default.default,
|
|
@@ -15605,7 +15337,7 @@ function ProductDetailScreen({ productId }) {
|
|
|
15605
15337
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15606
15338
|
"button",
|
|
15607
15339
|
{
|
|
15608
|
-
className: "sm:w-auto px-6 py-4 rounded-full border-2 border-primary hover:bg-primary
|
|
15340
|
+
className: "sm:w-auto px-6 py-4 rounded-full border-2 border-primary hover:bg-primary-5 transition-all flex items-center justify-center",
|
|
15609
15341
|
onClick: handleToggleFavorite,
|
|
15610
15342
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heart, { className: `h-4 w-4 ${isFavorited ? "fill-red-500 text-red-500" : "text-primary"}` })
|
|
15611
15343
|
}
|
|
@@ -15694,8 +15426,8 @@ function ProductDetailScreen({ productId }) {
|
|
|
15694
15426
|
}
|
|
15695
15427
|
function CartItem({ item }) {
|
|
15696
15428
|
const { updateQuantity, removeFromCart } = useCart();
|
|
15697
|
-
const [isUpdating, setIsUpdating] =
|
|
15698
|
-
const [isRemoving, setIsRemoving] =
|
|
15429
|
+
const [isUpdating, setIsUpdating] = React10.useState(false);
|
|
15430
|
+
const [isRemoving, setIsRemoving] = React10.useState(false);
|
|
15699
15431
|
const handleUpdateQuantity = async (newQuantity) => {
|
|
15700
15432
|
if (newQuantity < 1) return;
|
|
15701
15433
|
setIsUpdating(true);
|
|
@@ -15727,7 +15459,7 @@ function CartItem({ item }) {
|
|
|
15727
15459
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-28 h-28 rounded-[16px] overflow-hidden bg-gray-50 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15728
15460
|
Image4__default.default,
|
|
15729
15461
|
{
|
|
15730
|
-
src: item.productVariantData.media[0]?.file ||
|
|
15462
|
+
src: item.productVariantData.media[0]?.file || PLACEHOLDER_IMAGE_SRC,
|
|
15731
15463
|
alt: item.productVariantData.name,
|
|
15732
15464
|
className: "w-full h-full object-cover",
|
|
15733
15465
|
height: 112,
|
|
@@ -15949,20 +15681,20 @@ function CartScreen() {
|
|
|
15949
15681
|
] }) }) });
|
|
15950
15682
|
}
|
|
15951
15683
|
function useAddresses() {
|
|
15952
|
-
const [addresses, setAddresses] =
|
|
15953
|
-
const [isLoading, setIsLoading] =
|
|
15954
|
-
const [error, setError] =
|
|
15955
|
-
const refresh =
|
|
15684
|
+
const [addresses, setAddresses] = React10.useState([]);
|
|
15685
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
15686
|
+
const [error, setError] = React10.useState(null);
|
|
15687
|
+
const refresh = React10.useCallback(async () => {
|
|
15956
15688
|
setIsLoading(true);
|
|
15957
15689
|
setError(null);
|
|
15958
15690
|
const response = await new AddressesApi(AXIOS_CONFIG).getMyAddresses();
|
|
15959
15691
|
setAddresses(response.data || []);
|
|
15960
15692
|
setIsLoading(false);
|
|
15961
15693
|
}, []);
|
|
15962
|
-
|
|
15694
|
+
React10.useEffect(() => {
|
|
15963
15695
|
refresh();
|
|
15964
15696
|
}, [refresh]);
|
|
15965
|
-
const sortedAddresses =
|
|
15697
|
+
const sortedAddresses = React10.useMemo(() => {
|
|
15966
15698
|
return [...addresses].sort((a, b) => {
|
|
15967
15699
|
if (a.isDefault === b.isDefault) {
|
|
15968
15700
|
const dateA = a.updatedAt || "";
|
|
@@ -15972,26 +15704,26 @@ function useAddresses() {
|
|
|
15972
15704
|
return a.isDefault ? -1 : 1;
|
|
15973
15705
|
});
|
|
15974
15706
|
}, [addresses]);
|
|
15975
|
-
const defaultAddress =
|
|
15707
|
+
const defaultAddress = React10.useMemo(
|
|
15976
15708
|
() => sortedAddresses.find((address) => address.isDefault) || null,
|
|
15977
15709
|
[sortedAddresses]
|
|
15978
15710
|
);
|
|
15979
|
-
const addAddress =
|
|
15711
|
+
const addAddress = React10.useCallback(async (payload) => {
|
|
15980
15712
|
const response = await new AddressesApi(AXIOS_CONFIG).createAddressForUser(payload);
|
|
15981
15713
|
setAddresses((prev) => [...prev, response.data]);
|
|
15982
15714
|
return response.data;
|
|
15983
15715
|
}, []);
|
|
15984
|
-
const updateAddress =
|
|
15716
|
+
const updateAddress = React10.useCallback(async (id, payload) => {
|
|
15985
15717
|
const response = await new AddressesApi(AXIOS_CONFIG).updateUserAddress(payload, id);
|
|
15986
15718
|
setAddresses((prev) => prev.map((address) => address.id === id ? response.data : address));
|
|
15987
15719
|
return response.data;
|
|
15988
15720
|
}, []);
|
|
15989
|
-
const removeAddress =
|
|
15721
|
+
const removeAddress = React10.useCallback(async (id) => {
|
|
15990
15722
|
await new AddressesApi(AXIOS_CONFIG).deleteUserAddress(id);
|
|
15991
15723
|
setAddresses((prev) => prev.filter((address) => address.id !== id));
|
|
15992
15724
|
return;
|
|
15993
15725
|
}, []);
|
|
15994
|
-
const markAsDefault =
|
|
15726
|
+
const markAsDefault = React10.useCallback(async (id) => {
|
|
15995
15727
|
const response = await new AddressesApi(AXIOS_CONFIG).updateDefaultAddress(id);
|
|
15996
15728
|
setAddresses((prev) => prev.map((address) => address.id === id ? response.data : address));
|
|
15997
15729
|
return response.data;
|
|
@@ -16012,10 +15744,10 @@ init_config();
|
|
|
16012
15744
|
var cachedCapabilities = null;
|
|
16013
15745
|
var cacheStoreId = null;
|
|
16014
15746
|
function useStoreCapabilities() {
|
|
16015
|
-
const [capabilities, setCapabilities] =
|
|
16016
|
-
const [isLoading, setIsLoading] =
|
|
16017
|
-
const [error, setError] =
|
|
16018
|
-
const fetchCapabilities =
|
|
15747
|
+
const [capabilities, setCapabilities] = React10.useState(cachedCapabilities);
|
|
15748
|
+
const [isLoading, setIsLoading] = React10.useState(!cachedCapabilities);
|
|
15749
|
+
const [error, setError] = React10.useState(null);
|
|
15750
|
+
const fetchCapabilities = React10.useCallback(async (forceRefresh = false) => {
|
|
16019
15751
|
try {
|
|
16020
15752
|
const config = getCurrentConfig();
|
|
16021
15753
|
const storeId = config?.storeId;
|
|
@@ -16043,10 +15775,10 @@ function useStoreCapabilities() {
|
|
|
16043
15775
|
setIsLoading(false);
|
|
16044
15776
|
}
|
|
16045
15777
|
}, []);
|
|
16046
|
-
const refresh =
|
|
15778
|
+
const refresh = React10.useCallback(async () => {
|
|
16047
15779
|
await fetchCapabilities(true);
|
|
16048
15780
|
}, [fetchCapabilities]);
|
|
16049
|
-
|
|
15781
|
+
React10.useEffect(() => {
|
|
16050
15782
|
fetchCapabilities();
|
|
16051
15783
|
}, [fetchCapabilities]);
|
|
16052
15784
|
const showCardPayment = Boolean(capabilities?.hasStripeKey && capabilities?.cardPaymentEnabled);
|
|
@@ -16063,7 +15795,7 @@ function useStoreCapabilities() {
|
|
|
16063
15795
|
};
|
|
16064
15796
|
}
|
|
16065
15797
|
function Modal({ isOpen, onClose, title, children, size = "md" }) {
|
|
16066
|
-
|
|
15798
|
+
React10.useEffect(() => {
|
|
16067
15799
|
if (typeof window === "undefined") return;
|
|
16068
15800
|
if (isOpen) {
|
|
16069
15801
|
document.body.style.overflow = "hidden";
|
|
@@ -16127,7 +15859,7 @@ var addressSchema = zod.z.object({
|
|
|
16127
15859
|
phone: zod.z.string().min(10, "Phone number must be at least 10 characters").optional().or(zod.z.literal(""))
|
|
16128
15860
|
});
|
|
16129
15861
|
function AddressFormModal({ isOpen, onClose, onAddressAdded, onAddressUpdated, initialAddress }) {
|
|
16130
|
-
const [isSubmitting, setIsSubmitting] =
|
|
15862
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
16131
15863
|
const notification = useNotification();
|
|
16132
15864
|
const {
|
|
16133
15865
|
register,
|
|
@@ -16147,7 +15879,7 @@ function AddressFormModal({ isOpen, onClose, onAddressAdded, onAddressUpdated, i
|
|
|
16147
15879
|
country: initialAddress?.country || "United States"
|
|
16148
15880
|
}
|
|
16149
15881
|
});
|
|
16150
|
-
|
|
15882
|
+
React10.useEffect(() => {
|
|
16151
15883
|
reset({
|
|
16152
15884
|
name: initialAddress?.name || "",
|
|
16153
15885
|
phone: initialAddress?.phone || "",
|
|
@@ -16334,9 +16066,9 @@ function CouponCodeInput({
|
|
|
16334
16066
|
validateAndApplyCoupon,
|
|
16335
16067
|
removeCoupon
|
|
16336
16068
|
} = useDiscounts();
|
|
16337
|
-
const [localError, setLocalError] =
|
|
16338
|
-
const [isFocused, setIsFocused] =
|
|
16339
|
-
const inputRef =
|
|
16069
|
+
const [localError, setLocalError] = React10.useState(null);
|
|
16070
|
+
const [isFocused, setIsFocused] = React10.useState(false);
|
|
16071
|
+
const inputRef = React10.useRef(null);
|
|
16340
16072
|
const {
|
|
16341
16073
|
register,
|
|
16342
16074
|
handleSubmit,
|
|
@@ -16355,7 +16087,7 @@ function CouponCodeInput({
|
|
|
16355
16087
|
inputRef.current?.classList.remove("animate-shake");
|
|
16356
16088
|
}, 400);
|
|
16357
16089
|
};
|
|
16358
|
-
const onSubmit =
|
|
16090
|
+
const onSubmit = React10.useCallback(
|
|
16359
16091
|
async (data) => {
|
|
16360
16092
|
setLocalError(null);
|
|
16361
16093
|
const result = await validateAndApplyCoupon(data.code, userId);
|
|
@@ -16503,16 +16235,16 @@ function CheckoutScreen() {
|
|
|
16503
16235
|
const { cart, clearCart } = useCart();
|
|
16504
16236
|
const { isAuthenticated, user } = useAuth();
|
|
16505
16237
|
const { buildPath } = useBasePath();
|
|
16506
|
-
const [isSubmitting, setIsSubmitting] =
|
|
16507
|
-
const [isDelivery, setIsDelivery] =
|
|
16508
|
-
const [hasSetDefaultDelivery, setHasSetDefaultDelivery] =
|
|
16509
|
-
const [paymentMethod, setPaymentMethod] =
|
|
16510
|
-
const [error, setError] =
|
|
16511
|
-
const [selectedAddressId, setSelectedAddressId] =
|
|
16512
|
-
const [storeAddresses, setStoreAddresses] =
|
|
16513
|
-
const [isAddressModalOpen, setIsAddressModalOpen] =
|
|
16514
|
-
const [editingAddress, setEditingAddress] =
|
|
16515
|
-
const [shippingPrice, setShippingPrice] =
|
|
16238
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
16239
|
+
const [isDelivery, setIsDelivery] = React10.useState(null);
|
|
16240
|
+
const [hasSetDefaultDelivery, setHasSetDefaultDelivery] = React10.useState(false);
|
|
16241
|
+
const [paymentMethod, setPaymentMethod] = React10.useState(null);
|
|
16242
|
+
const [error, setError] = React10.useState(null);
|
|
16243
|
+
const [selectedAddressId, setSelectedAddressId] = React10.useState(null);
|
|
16244
|
+
const [storeAddresses, setStoreAddresses] = React10.useState([]);
|
|
16245
|
+
const [isAddressModalOpen, setIsAddressModalOpen] = React10.useState(false);
|
|
16246
|
+
const [editingAddress, setEditingAddress] = React10.useState(null);
|
|
16247
|
+
const [shippingPrice, setShippingPrice] = React10.useState(0);
|
|
16516
16248
|
const notification = useNotification();
|
|
16517
16249
|
const { appliedCoupon, calculateCouponDiscount } = useDiscounts();
|
|
16518
16250
|
const {
|
|
@@ -16532,13 +16264,13 @@ function CheckoutScreen() {
|
|
|
16532
16264
|
}
|
|
16533
16265
|
return true;
|
|
16534
16266
|
});
|
|
16535
|
-
|
|
16267
|
+
React10.useEffect(() => {
|
|
16536
16268
|
if (!capabilitiesLoading && paymentMethod === null && availablePaymentMethods.length > 0) {
|
|
16537
16269
|
const preferCard = availablePaymentMethods.find((pm) => pm.id === "Card");
|
|
16538
16270
|
setPaymentMethod(preferCard ? "Card" : availablePaymentMethods[0].value);
|
|
16539
16271
|
}
|
|
16540
16272
|
}, [capabilitiesLoading, paymentMethod, availablePaymentMethods]);
|
|
16541
|
-
|
|
16273
|
+
React10.useEffect(() => {
|
|
16542
16274
|
if (!capabilitiesLoading && !hasSetDefaultDelivery && capabilities) {
|
|
16543
16275
|
if (!showShippoDelivery && !showCustomDelivery) {
|
|
16544
16276
|
setIsDelivery(false);
|
|
@@ -16571,11 +16303,11 @@ function CheckoutScreen() {
|
|
|
16571
16303
|
desc: "Collect from pharmacy"
|
|
16572
16304
|
}
|
|
16573
16305
|
];
|
|
16574
|
-
const [selectedShippingRateId, setSelectedShippingRateId] =
|
|
16575
|
-
const [shippingRates, setShippingRates] =
|
|
16576
|
-
const [shippingRatesLoading, setShippingRatesLoading] =
|
|
16577
|
-
const [shippingRatesError, setShippingRatesError] =
|
|
16578
|
-
const [storeData, setStoreData] =
|
|
16306
|
+
const [selectedShippingRateId, setSelectedShippingRateId] = React10.useState(null);
|
|
16307
|
+
const [shippingRates, setShippingRates] = React10.useState([]);
|
|
16308
|
+
const [shippingRatesLoading, setShippingRatesLoading] = React10.useState(false);
|
|
16309
|
+
const [shippingRatesError, setShippingRatesError] = React10.useState(null);
|
|
16310
|
+
const [storeData, setStoreData] = React10.useState(null);
|
|
16579
16311
|
const { addresses, isLoading, refresh, removeAddress } = useAddresses();
|
|
16580
16312
|
const {
|
|
16581
16313
|
register,
|
|
@@ -16608,7 +16340,7 @@ function CheckoutScreen() {
|
|
|
16608
16340
|
}
|
|
16609
16341
|
});
|
|
16610
16342
|
const sameAsShipping = watch("sameAsShipping", true);
|
|
16611
|
-
|
|
16343
|
+
React10.useEffect(() => {
|
|
16612
16344
|
if (sameAsShipping) {
|
|
16613
16345
|
setValue("billing.name", watch("shipping.name"));
|
|
16614
16346
|
setValue("billing.phone", watch("shipping.phone"));
|
|
@@ -16620,7 +16352,7 @@ function CheckoutScreen() {
|
|
|
16620
16352
|
setValue("billing.country", watch("shipping.country"));
|
|
16621
16353
|
}
|
|
16622
16354
|
}, [sameAsShipping, watch("shipping.name"), watch("shipping.phone"), watch("shipping.street1"), watch("shipping.street2"), watch("shipping.city"), watch("shipping.state"), watch("shipping.zip"), watch("shipping.country")]);
|
|
16623
|
-
|
|
16355
|
+
React10.useEffect(() => {
|
|
16624
16356
|
if (defaultAddress && !selectedAddressId) {
|
|
16625
16357
|
setSelectedAddressId(defaultAddress.id);
|
|
16626
16358
|
setValue("shipping.name", defaultAddress.name);
|
|
@@ -16658,7 +16390,7 @@ function CheckoutScreen() {
|
|
|
16658
16390
|
setShippingRates([]);
|
|
16659
16391
|
setSelectedShippingRateId(null);
|
|
16660
16392
|
};
|
|
16661
|
-
|
|
16393
|
+
React10.useEffect(() => {
|
|
16662
16394
|
if (isDelivery !== true || !selectedAddressId || !cart || cart?.cartBody?.items?.length === 0 || !cart?.cartBody?.items) {
|
|
16663
16395
|
setShippingRates([]);
|
|
16664
16396
|
setSelectedShippingRateId(null);
|
|
@@ -16687,7 +16419,7 @@ function CheckoutScreen() {
|
|
|
16687
16419
|
}
|
|
16688
16420
|
})();
|
|
16689
16421
|
}, [isDelivery, selectedAddressId, cart]);
|
|
16690
|
-
|
|
16422
|
+
React10.useEffect(() => {
|
|
16691
16423
|
let cancelled = false;
|
|
16692
16424
|
if (isDelivery === false) {
|
|
16693
16425
|
(async () => {
|
|
@@ -16865,7 +16597,7 @@ function CheckoutScreen() {
|
|
|
16865
16597
|
setIsSubmitting(false);
|
|
16866
16598
|
}
|
|
16867
16599
|
};
|
|
16868
|
-
|
|
16600
|
+
React10__default.default.useEffect(() => {
|
|
16869
16601
|
if (!cart || cart?.cartBody?.items?.length === 0 || !cart?.cartBody?.items) {
|
|
16870
16602
|
router.push(buildPath("/cart"));
|
|
16871
16603
|
}
|
|
@@ -17144,7 +16876,7 @@ function CheckoutScreen() {
|
|
|
17144
16876
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17145
16877
|
Image4__default.default,
|
|
17146
16878
|
{
|
|
17147
|
-
src: rate.providerImage75 ||
|
|
16879
|
+
src: rate.providerImage75 || PLACEHOLDER_IMAGE_SRC,
|
|
17148
16880
|
alt: rate.provider,
|
|
17149
16881
|
className: "w-12 h-12 rounded-lg object-contain bg-white border border-gray-200 p-1",
|
|
17150
16882
|
onError: (e) => {
|
|
@@ -17229,7 +16961,7 @@ function CheckoutScreen() {
|
|
|
17229
16961
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-['Poppins',sans-serif] font-semibold text-[#2B4B7C] mb-6 text-2xl", children: "Order Summary" }),
|
|
17230
16962
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "mt-8 pt-6 border-t border-slate-100", children: [
|
|
17231
16963
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 mb-6", children: cart?.cartBody?.items?.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
17232
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 rounded-xl overflow-hidden bg-white shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Image4__default.default, { src: item.productVariantData?.media?.[0]?.file ||
|
|
16964
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 rounded-xl overflow-hidden bg-white shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Image4__default.default, { src: item.productVariantData?.media?.[0]?.file || PLACEHOLDER_IMAGE_SRC, alt: item.productVariantData.name, className: "w-full h-full object-cover", height: 200, width: 200 }) }),
|
|
17233
16965
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
17234
16966
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-['Poppins',sans-serif] font-medium text-[12px] text-[#2B4B7C] mb-1", children: item?.productVariantData?.name }),
|
|
17235
16967
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-['Poppins',sans-serif] text-[11px] text-[#676c80]", children: [
|
|
@@ -17366,9 +17098,9 @@ function LoginScreen() {
|
|
|
17366
17098
|
const searchParams = navigation.useSearchParams();
|
|
17367
17099
|
const redirectUrl = searchParams?.get("redirect") || buildPath("/");
|
|
17368
17100
|
const { login, user, isLoading } = useAuth();
|
|
17369
|
-
const [showPassword, setShowPassword] =
|
|
17370
|
-
const [isSubmitting, setIsSubmitting] =
|
|
17371
|
-
const [status, setStatus] =
|
|
17101
|
+
const [showPassword, setShowPassword] = React10.useState(false);
|
|
17102
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
17103
|
+
const [status, setStatus] = React10.useState(
|
|
17372
17104
|
null
|
|
17373
17105
|
);
|
|
17374
17106
|
const {
|
|
@@ -17525,9 +17257,9 @@ function RegisterScreen() {
|
|
|
17525
17257
|
const router = navigation.useRouter();
|
|
17526
17258
|
const { register: registerUser } = useAuth();
|
|
17527
17259
|
const { buildPath } = useBasePath();
|
|
17528
|
-
const [showPassword, setShowPassword] =
|
|
17529
|
-
const [showConfirmPassword, setShowConfirmPassword] =
|
|
17530
|
-
const [isSubmitting, setIsSubmitting] =
|
|
17260
|
+
const [showPassword, setShowPassword] = React10.useState(false);
|
|
17261
|
+
const [showConfirmPassword, setShowConfirmPassword] = React10.useState(false);
|
|
17262
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
17531
17263
|
const notification = useNotification();
|
|
17532
17264
|
const {
|
|
17533
17265
|
register,
|
|
@@ -17733,8 +17465,8 @@ var forgotPasswordSchema = zod.z.object({
|
|
|
17733
17465
|
});
|
|
17734
17466
|
function ForgotPasswordScreen() {
|
|
17735
17467
|
const { buildPath } = useBasePath();
|
|
17736
|
-
const [isSubmitting, setIsSubmitting] =
|
|
17737
|
-
const [status, setStatus] =
|
|
17468
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
17469
|
+
const [status, setStatus] = React10.useState(
|
|
17738
17470
|
null
|
|
17739
17471
|
);
|
|
17740
17472
|
const {
|
|
@@ -17873,10 +17605,10 @@ function ResetPasswordScreen() {
|
|
|
17873
17605
|
const params = navigation.useParams();
|
|
17874
17606
|
const token = params?.token;
|
|
17875
17607
|
const storeId = params?.storeId;
|
|
17876
|
-
const [showPassword, setShowPassword] =
|
|
17877
|
-
const [showConfirmPassword, setShowConfirmPassword] =
|
|
17878
|
-
const [isSubmitting, setIsSubmitting] =
|
|
17879
|
-
const [status, setStatus] =
|
|
17608
|
+
const [showPassword, setShowPassword] = React10.useState(false);
|
|
17609
|
+
const [showConfirmPassword, setShowConfirmPassword] = React10.useState(false);
|
|
17610
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
17611
|
+
const [status, setStatus] = React10.useState(
|
|
17880
17612
|
null
|
|
17881
17613
|
);
|
|
17882
17614
|
const {
|
|
@@ -17886,7 +17618,7 @@ function ResetPasswordScreen() {
|
|
|
17886
17618
|
} = reactHookForm.useForm({
|
|
17887
17619
|
resolver: zod$1.zodResolver(resetPasswordSchema)
|
|
17888
17620
|
});
|
|
17889
|
-
|
|
17621
|
+
React10.useEffect(() => {
|
|
17890
17622
|
if (!token) {
|
|
17891
17623
|
setStatus({
|
|
17892
17624
|
type: "error",
|
|
@@ -18068,10 +17800,10 @@ function TabNavigation({ tabs: tabs2, activeTab, onTabChange }) {
|
|
|
18068
17800
|
}) }) });
|
|
18069
17801
|
}
|
|
18070
17802
|
function useOrders(page = 1, limit = 10, orderStatus, paymentStatus) {
|
|
18071
|
-
const [orders, setOrders] =
|
|
18072
|
-
const [isLoading, setIsLoading] =
|
|
18073
|
-
const [error, setError] =
|
|
18074
|
-
const [pagination, setPagination] =
|
|
17803
|
+
const [orders, setOrders] = React10.useState([]);
|
|
17804
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
17805
|
+
const [error, setError] = React10.useState(null);
|
|
17806
|
+
const [pagination, setPagination] = React10.useState({
|
|
18075
17807
|
page: 1,
|
|
18076
17808
|
limit: 10,
|
|
18077
17809
|
total: 0,
|
|
@@ -18079,7 +17811,7 @@ function useOrders(page = 1, limit = 10, orderStatus, paymentStatus) {
|
|
|
18079
17811
|
});
|
|
18080
17812
|
const { user } = useAuth();
|
|
18081
17813
|
const resolvedUserId = user?._id || user?.id;
|
|
18082
|
-
const fetchOrders =
|
|
17814
|
+
const fetchOrders = React10.useCallback(async () => {
|
|
18083
17815
|
setIsLoading(true);
|
|
18084
17816
|
setError(null);
|
|
18085
17817
|
try {
|
|
@@ -18106,7 +17838,7 @@ function useOrders(page = 1, limit = 10, orderStatus, paymentStatus) {
|
|
|
18106
17838
|
setIsLoading(false);
|
|
18107
17839
|
}
|
|
18108
17840
|
}, [page, limit, resolvedUserId, orderStatus, paymentStatus]);
|
|
18109
|
-
|
|
17841
|
+
React10.useEffect(() => {
|
|
18110
17842
|
fetchOrders();
|
|
18111
17843
|
}, [fetchOrders]);
|
|
18112
17844
|
const deleteOrder = async (id) => {
|
|
@@ -18129,10 +17861,10 @@ function useOrders(page = 1, limit = 10, orderStatus, paymentStatus) {
|
|
|
18129
17861
|
};
|
|
18130
17862
|
}
|
|
18131
17863
|
function useOrder(id) {
|
|
18132
|
-
const [order, setOrder] =
|
|
18133
|
-
const [isLoading, setIsLoading] =
|
|
18134
|
-
const [error, setError] =
|
|
18135
|
-
const fetchOrder =
|
|
17864
|
+
const [order, setOrder] = React10.useState(null);
|
|
17865
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
17866
|
+
const [error, setError] = React10.useState(null);
|
|
17867
|
+
const fetchOrder = React10.useCallback(async () => {
|
|
18136
17868
|
setIsLoading(true);
|
|
18137
17869
|
setError(null);
|
|
18138
17870
|
try {
|
|
@@ -18144,7 +17876,7 @@ function useOrder(id) {
|
|
|
18144
17876
|
setIsLoading(false);
|
|
18145
17877
|
}
|
|
18146
17878
|
}, [id]);
|
|
18147
|
-
|
|
17879
|
+
React10.useEffect(() => {
|
|
18148
17880
|
if (id) {
|
|
18149
17881
|
fetchOrder();
|
|
18150
17882
|
}
|
|
@@ -18152,10 +17884,10 @@ function useOrder(id) {
|
|
|
18152
17884
|
return { order, isLoading, error, refetch: fetchOrder };
|
|
18153
17885
|
}
|
|
18154
17886
|
function useCurrentOrders() {
|
|
18155
|
-
const [orders, setOrders] =
|
|
18156
|
-
const [isLoading, setIsLoading] =
|
|
18157
|
-
const [error, setError] =
|
|
18158
|
-
const fetchCurrentOrders =
|
|
17887
|
+
const [orders, setOrders] = React10.useState([]);
|
|
17888
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
17889
|
+
const [error, setError] = React10.useState(null);
|
|
17890
|
+
const fetchCurrentOrders = React10.useCallback(async () => {
|
|
18159
17891
|
setIsLoading(true);
|
|
18160
17892
|
setError(null);
|
|
18161
17893
|
try {
|
|
@@ -18167,7 +17899,7 @@ function useCurrentOrders() {
|
|
|
18167
17899
|
setIsLoading(false);
|
|
18168
17900
|
}
|
|
18169
17901
|
}, []);
|
|
18170
|
-
|
|
17902
|
+
React10.useEffect(() => {
|
|
18171
17903
|
fetchCurrentOrders();
|
|
18172
17904
|
}, [fetchCurrentOrders]);
|
|
18173
17905
|
return { orders, isLoading, error, refetch: fetchCurrentOrders };
|
|
@@ -18411,7 +18143,7 @@ function AccountOrdersTab() {
|
|
|
18411
18143
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-12 h-12 rounded-lg bg-slate-100 shrink-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18412
18144
|
Image4__default.default,
|
|
18413
18145
|
{
|
|
18414
|
-
src: item?.productVariantData?.media?.[0]?.file ||
|
|
18146
|
+
src: item?.productVariantData?.media?.[0]?.file || PLACEHOLDER_IMAGE_SRC,
|
|
18415
18147
|
alt: item?.productVariantData?.name || "Product image",
|
|
18416
18148
|
fill: true,
|
|
18417
18149
|
className: "object-cover",
|
|
@@ -18489,11 +18221,11 @@ function ConfirmModal({
|
|
|
18489
18221
|
}
|
|
18490
18222
|
function AccountAddressesTab() {
|
|
18491
18223
|
const { addresses, isLoading, error, removeAddress, markAsDefault, refresh } = useAddresses();
|
|
18492
|
-
const [deletingId, setDeletingId] =
|
|
18493
|
-
const [editingAddress, setEditingAddress] =
|
|
18494
|
-
const [isAddressModalOpen, setIsAddressModalOpen] =
|
|
18495
|
-
const [selectedAddressId, setSelectedAddressId] =
|
|
18496
|
-
const [addressToDelete, setAddressToDelete] =
|
|
18224
|
+
const [deletingId, setDeletingId] = React10.useState(null);
|
|
18225
|
+
const [editingAddress, setEditingAddress] = React10.useState(void 0);
|
|
18226
|
+
const [isAddressModalOpen, setIsAddressModalOpen] = React10.useState(false);
|
|
18227
|
+
const [selectedAddressId, setSelectedAddressId] = React10.useState(null);
|
|
18228
|
+
const [addressToDelete, setAddressToDelete] = React10.useState(null);
|
|
18497
18229
|
const notification = useNotification();
|
|
18498
18230
|
const handleConfirmDelete = async () => {
|
|
18499
18231
|
if (!addressToDelete) return;
|
|
@@ -18645,9 +18377,9 @@ function AccountSettingsTab() {
|
|
|
18645
18377
|
const router = navigation.useRouter();
|
|
18646
18378
|
const { buildPath } = useBasePath();
|
|
18647
18379
|
const { logout } = useAuth();
|
|
18648
|
-
const [showDeleteModal, setShowDeleteModal] =
|
|
18649
|
-
const [isDeleting, setIsDeleting] =
|
|
18650
|
-
const [deleteError, setDeleteError] =
|
|
18380
|
+
const [showDeleteModal, setShowDeleteModal] = React10.useState(false);
|
|
18381
|
+
const [isDeleting, setIsDeleting] = React10.useState(false);
|
|
18382
|
+
const [deleteError, setDeleteError] = React10.useState(null);
|
|
18651
18383
|
const handleDeleteAccount = async () => {
|
|
18652
18384
|
setIsDeleting(true);
|
|
18653
18385
|
setDeleteError(null);
|
|
@@ -18846,10 +18578,10 @@ function AccountPage() {
|
|
|
18846
18578
|
const router = navigation.useRouter();
|
|
18847
18579
|
const { user, logout, isLoading } = useAuth();
|
|
18848
18580
|
const { buildPath } = useBasePath();
|
|
18849
|
-
const [activeTab, setActiveTab] =
|
|
18850
|
-
const [isDropdownOpen, setIsDropdownOpen] =
|
|
18851
|
-
const [isLoggingOut, setIsLoggingOut] =
|
|
18852
|
-
|
|
18581
|
+
const [activeTab, setActiveTab] = React10.useState("overview");
|
|
18582
|
+
const [isDropdownOpen, setIsDropdownOpen] = React10.useState(false);
|
|
18583
|
+
const [isLoggingOut, setIsLoggingOut] = React10.useState(false);
|
|
18584
|
+
React10__default.default.useEffect(() => {
|
|
18853
18585
|
const handleTabSwitch = (event) => {
|
|
18854
18586
|
setActiveTab(event.detail);
|
|
18855
18587
|
};
|
|
@@ -18895,7 +18627,7 @@ function AccountPage() {
|
|
|
18895
18627
|
function OrderCard({ order, onDelete }) {
|
|
18896
18628
|
const router = navigation.useRouter();
|
|
18897
18629
|
const { buildPath } = useBasePath();
|
|
18898
|
-
const [isDragging, setIsDragging] =
|
|
18630
|
+
const [isDragging, setIsDragging] = React10.useState(false);
|
|
18899
18631
|
const dragX = framerMotion.useMotionValue(0);
|
|
18900
18632
|
const deleteOpacity = framerMotion.useTransform(dragX, [-100, -20], [1, 0]);
|
|
18901
18633
|
const config = order.orderStatus;
|
|
@@ -18967,7 +18699,7 @@ function OrderCard({ order, onDelete }) {
|
|
|
18967
18699
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-12 h-12 rounded-sm bg-gray-100 shrink-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18968
18700
|
Image4__default.default,
|
|
18969
18701
|
{
|
|
18970
|
-
src: item?.productVariantData?.media?.[0]?.file ||
|
|
18702
|
+
src: item?.productVariantData?.media?.[0]?.file || PLACEHOLDER_IMAGE_SRC,
|
|
18971
18703
|
alt: item?.productVariantData?.name || "Product image",
|
|
18972
18704
|
fill: true,
|
|
18973
18705
|
className: "object-cover",
|
|
@@ -19051,9 +18783,9 @@ function FilterChips({
|
|
|
19051
18783
|
maxVisible = 4,
|
|
19052
18784
|
variant = "primary"
|
|
19053
18785
|
}) {
|
|
19054
|
-
const [isOverflowOpen, setIsOverflowOpen] =
|
|
19055
|
-
const overflowMenuRef =
|
|
19056
|
-
const { visibleFilters, overflowFilters } =
|
|
18786
|
+
const [isOverflowOpen, setIsOverflowOpen] = React10.useState(false);
|
|
18787
|
+
const overflowMenuRef = React10.useRef(null);
|
|
18788
|
+
const { visibleFilters, overflowFilters } = React10.useMemo(() => {
|
|
19057
18789
|
const basePrimary = filters.slice(0, maxVisible);
|
|
19058
18790
|
if (basePrimary.includes(selected)) {
|
|
19059
18791
|
return {
|
|
@@ -19073,7 +18805,7 @@ function FilterChips({
|
|
|
19073
18805
|
overflowFilters: filters.filter((filter) => !uniquePrimary.includes(filter))
|
|
19074
18806
|
};
|
|
19075
18807
|
}, [filters, maxVisible, selected]);
|
|
19076
|
-
|
|
18808
|
+
React10.useEffect(() => {
|
|
19077
18809
|
function handleClickOutside(event) {
|
|
19078
18810
|
if (overflowMenuRef.current && !overflowMenuRef.current.contains(event.target)) {
|
|
19079
18811
|
setIsOverflowOpen(false);
|
|
@@ -19172,8 +18904,8 @@ function ReviewPromptBanner({
|
|
|
19172
18904
|
}) {
|
|
19173
18905
|
const router = navigation.useRouter();
|
|
19174
18906
|
const { buildPath } = useBasePath();
|
|
19175
|
-
const [isVisible, setIsVisible] =
|
|
19176
|
-
|
|
18907
|
+
const [isVisible, setIsVisible] = React10.useState(false);
|
|
18908
|
+
React10.useEffect(() => {
|
|
19177
18909
|
const dismissedPrompts = JSON.parse(
|
|
19178
18910
|
localStorage.getItem("dismissedReviewPrompts") || "[]"
|
|
19179
18911
|
);
|
|
@@ -19240,23 +18972,23 @@ var PAYMENT_FILTERS = ["All", ...Object.values(PaymentPaymentStatusEnum)];
|
|
|
19240
18972
|
function OrdersScreen() {
|
|
19241
18973
|
const router = navigation.useRouter();
|
|
19242
18974
|
const { buildPath } = useBasePath();
|
|
19243
|
-
const [page, setPage] =
|
|
19244
|
-
const [selectedFilter, setSelectedFilter] =
|
|
19245
|
-
const [selectedPaymentFilter, setSelectedPaymentFilter] =
|
|
18975
|
+
const [page, setPage] = React10.useState(1);
|
|
18976
|
+
const [selectedFilter, setSelectedFilter] = React10.useState("All");
|
|
18977
|
+
const [selectedPaymentFilter, setSelectedPaymentFilter] = React10.useState("All");
|
|
19246
18978
|
const { orders, isLoading, pagination, deleteOrder } = useOrders(
|
|
19247
18979
|
page,
|
|
19248
18980
|
10,
|
|
19249
18981
|
selectedFilter,
|
|
19250
18982
|
selectedPaymentFilter
|
|
19251
18983
|
);
|
|
19252
|
-
const filteredOrders =
|
|
18984
|
+
const filteredOrders = React10.useMemo(() => {
|
|
19253
18985
|
return orders.filter((order) => {
|
|
19254
18986
|
const matchesStatus = selectedFilter === "All" || order?.orderStatus?.toLowerCase() === selectedFilter.toLowerCase();
|
|
19255
18987
|
const matchesPayment = selectedPaymentFilter === "All" || order?.payment?.paymentStatus?.toLowerCase() === selectedPaymentFilter.toLowerCase();
|
|
19256
18988
|
return matchesStatus && matchesPayment;
|
|
19257
18989
|
});
|
|
19258
18990
|
}, [orders, selectedFilter, selectedPaymentFilter]);
|
|
19259
|
-
const completedOrderForPrompt =
|
|
18991
|
+
const completedOrderForPrompt = React10.useMemo(() => {
|
|
19260
18992
|
return filteredOrders.find(
|
|
19261
18993
|
(order) => order.orderStatus && ["Delivered", "Picked Up", "Fulfilled"].includes(order.orderStatus)
|
|
19262
18994
|
);
|
|
@@ -19531,9 +19263,9 @@ function AddressesScreen() {
|
|
|
19531
19263
|
removeAddress,
|
|
19532
19264
|
markAsDefault
|
|
19533
19265
|
} = useAddresses();
|
|
19534
|
-
const [isModalOpen, setIsModalOpen] =
|
|
19535
|
-
const [editingAddress, setEditingAddress] =
|
|
19536
|
-
const [banner, setBanner] =
|
|
19266
|
+
const [isModalOpen, setIsModalOpen] = React10.useState(false);
|
|
19267
|
+
const [editingAddress, setEditingAddress] = React10.useState(null);
|
|
19268
|
+
const [banner, setBanner] = React10.useState(
|
|
19537
19269
|
null
|
|
19538
19270
|
);
|
|
19539
19271
|
const {
|
|
@@ -19545,7 +19277,7 @@ function AddressesScreen() {
|
|
|
19545
19277
|
resolver: zod$1.zodResolver(addressFormSchema),
|
|
19546
19278
|
defaultValues: FORM_DEFAULTS
|
|
19547
19279
|
});
|
|
19548
|
-
|
|
19280
|
+
React10.useEffect(() => {
|
|
19549
19281
|
if (editingAddress) {
|
|
19550
19282
|
reset({
|
|
19551
19283
|
fullName: editingAddress.name,
|
|
@@ -19642,7 +19374,7 @@ You can add it back at any time.`
|
|
|
19642
19374
|
});
|
|
19643
19375
|
}
|
|
19644
19376
|
};
|
|
19645
|
-
const stats =
|
|
19377
|
+
const stats = React10.useMemo(() => {
|
|
19646
19378
|
const shippingCount = addresses.filter((address) => address.addressType !== "Billing").length;
|
|
19647
19379
|
const billingCount = addresses.filter((address) => address.addressType !== "Shipping").length;
|
|
19648
19380
|
return [
|
|
@@ -19936,15 +19668,15 @@ You can add it back at any time.`
|
|
|
19936
19668
|
] });
|
|
19937
19669
|
}
|
|
19938
19670
|
function useWishlistProducts(productIds = []) {
|
|
19939
|
-
const [products, setProducts] =
|
|
19940
|
-
const [isLoading, setIsLoading] =
|
|
19941
|
-
const [error, setError] =
|
|
19942
|
-
const [cache] =
|
|
19943
|
-
const uniqueIds =
|
|
19671
|
+
const [products, setProducts] = React10.useState([]);
|
|
19672
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
19673
|
+
const [error, setError] = React10.useState(null);
|
|
19674
|
+
const [cache] = React10.useState(() => /* @__PURE__ */ new Map());
|
|
19675
|
+
const uniqueIds = React10.useMemo(
|
|
19944
19676
|
() => Array.from(new Set((productIds || []).filter(Boolean))),
|
|
19945
19677
|
[productIds]
|
|
19946
19678
|
);
|
|
19947
|
-
const fetchProducts =
|
|
19679
|
+
const fetchProducts = React10.useCallback(async () => {
|
|
19948
19680
|
if (uniqueIds.length === 0) {
|
|
19949
19681
|
setProducts([]);
|
|
19950
19682
|
setIsLoading(false);
|
|
@@ -19972,7 +19704,7 @@ function useWishlistProducts(productIds = []) {
|
|
|
19972
19704
|
setIsLoading(false);
|
|
19973
19705
|
}
|
|
19974
19706
|
}, [cache, uniqueIds]);
|
|
19975
|
-
|
|
19707
|
+
React10.useEffect(() => {
|
|
19976
19708
|
fetchProducts();
|
|
19977
19709
|
}, [fetchProducts]);
|
|
19978
19710
|
return {
|
|
@@ -20005,10 +19737,10 @@ function WishlistScreen() {
|
|
|
20005
19737
|
const { products: wishlistProducts, isLoading, error } = useWishlistProducts(
|
|
20006
19738
|
wishlistItems
|
|
20007
19739
|
);
|
|
20008
|
-
const [onlyInStock, setOnlyInStock] =
|
|
20009
|
-
const [viewMode, setViewMode] =
|
|
20010
|
-
const [sortOption, setSortOption] =
|
|
20011
|
-
|
|
19740
|
+
const [onlyInStock, setOnlyInStock] = React10.useState(false);
|
|
19741
|
+
const [viewMode, setViewMode] = React10.useState("list");
|
|
19742
|
+
const [sortOption, setSortOption] = React10.useState("featured");
|
|
19743
|
+
React10.useEffect(() => {
|
|
20012
19744
|
if (error) {
|
|
20013
19745
|
notification.error(
|
|
20014
19746
|
"Could not load wishlist",
|
|
@@ -20033,11 +19765,11 @@ function WishlistScreen() {
|
|
|
20033
19765
|
console.error("Error clearing wishlist:", err);
|
|
20034
19766
|
}
|
|
20035
19767
|
};
|
|
20036
|
-
const totalValue =
|
|
19768
|
+
const totalValue = React10.useMemo(
|
|
20037
19769
|
() => wishlistProducts.reduce((sum, product) => sum + (product.summary?.minPrice ?? 0), 0),
|
|
20038
19770
|
[wishlistProducts]
|
|
20039
19771
|
);
|
|
20040
|
-
|
|
19772
|
+
React10.useMemo(
|
|
20041
19773
|
() => wishlistProducts.reduce((sum, product) => {
|
|
20042
19774
|
if (product.summary?.hasDiscount) {
|
|
20043
19775
|
const maxPrice = product.summary?.maxPrice ?? 0;
|
|
@@ -20048,11 +19780,11 @@ function WishlistScreen() {
|
|
|
20048
19780
|
}, 0),
|
|
20049
19781
|
[wishlistProducts]
|
|
20050
19782
|
);
|
|
20051
|
-
|
|
19783
|
+
React10.useMemo(
|
|
20052
19784
|
() => wishlistProducts.filter((product) => (product.summary?.totalInventory ?? 0) > 0).length,
|
|
20053
19785
|
[wishlistProducts]
|
|
20054
19786
|
);
|
|
20055
|
-
const processedProducts =
|
|
19787
|
+
const processedProducts = React10.useMemo(() => {
|
|
20056
19788
|
let list = [...wishlistProducts];
|
|
20057
19789
|
if (onlyInStock) {
|
|
20058
19790
|
list = list.filter((product) => (product.summary?.totalInventory ?? 0) > 0);
|
|
@@ -20236,7 +19968,7 @@ function WishlistScreen() {
|
|
|
20236
19968
|
Image4__default.default,
|
|
20237
19969
|
{
|
|
20238
19970
|
fill: true,
|
|
20239
|
-
src: product.media?.[0]?.file ||
|
|
19971
|
+
src: product.media?.[0]?.file || PLACEHOLDER_IMAGE_SRC,
|
|
20240
19972
|
alt: product.name || "Wishlist item",
|
|
20241
19973
|
className: "h-full w-full object-cover"
|
|
20242
19974
|
}
|
|
@@ -20272,7 +20004,7 @@ function WishlistScreen() {
|
|
|
20272
20004
|
{
|
|
20273
20005
|
size: "sm",
|
|
20274
20006
|
onClick: () => router.push(buildPath(`/products/${product._id}`)),
|
|
20275
|
-
className: "bg-primary
|
|
20007
|
+
className: "bg-primary-90 text-white hover:bg-primary-70",
|
|
20276
20008
|
children: "View details"
|
|
20277
20009
|
}
|
|
20278
20010
|
),
|
|
@@ -20314,15 +20046,15 @@ function SearchPage() {
|
|
|
20314
20046
|
const { buildPath } = useBasePath();
|
|
20315
20047
|
const searchParams = navigation.useSearchParams();
|
|
20316
20048
|
const searchQuery = searchParams.get("q") || "";
|
|
20317
|
-
const [products, setProducts] =
|
|
20318
|
-
const [isLoading, setIsLoading] =
|
|
20319
|
-
const [searchInput, setSearchInput] =
|
|
20320
|
-
const [hasSearched, setHasSearched] =
|
|
20049
|
+
const [products, setProducts] = React10.useState([]);
|
|
20050
|
+
const [isLoading, setIsLoading] = React10.useState(true);
|
|
20051
|
+
const [searchInput, setSearchInput] = React10.useState(searchQuery);
|
|
20052
|
+
const [hasSearched, setHasSearched] = React10.useState(false);
|
|
20321
20053
|
const { isInWishlist } = useWishlist();
|
|
20322
|
-
const [suggestions, setSuggestions] =
|
|
20323
|
-
const [showSuggestions, setShowSuggestions] =
|
|
20324
|
-
const [recentSearches, setRecentSearches] =
|
|
20325
|
-
|
|
20054
|
+
const [suggestions, setSuggestions] = React10.useState([]);
|
|
20055
|
+
const [showSuggestions, setShowSuggestions] = React10.useState(false);
|
|
20056
|
+
const [recentSearches, setRecentSearches] = React10.useState([]);
|
|
20057
|
+
React10.useEffect(() => {
|
|
20326
20058
|
const stored = localStorage.getItem("recent_searches");
|
|
20327
20059
|
if (stored) {
|
|
20328
20060
|
try {
|
|
@@ -20332,7 +20064,7 @@ function SearchPage() {
|
|
|
20332
20064
|
}
|
|
20333
20065
|
}
|
|
20334
20066
|
}, []);
|
|
20335
|
-
const saveRecentSearch =
|
|
20067
|
+
const saveRecentSearch = React10.useCallback((query) => {
|
|
20336
20068
|
if (!query.trim()) return;
|
|
20337
20069
|
setRecentSearches((prev) => {
|
|
20338
20070
|
const updated = [query, ...prev.filter((s) => s !== query)].slice(0, 5);
|
|
@@ -20340,7 +20072,7 @@ function SearchPage() {
|
|
|
20340
20072
|
return updated;
|
|
20341
20073
|
});
|
|
20342
20074
|
}, []);
|
|
20343
|
-
const generateSuggestions =
|
|
20075
|
+
const generateSuggestions = React10.useMemo(() => {
|
|
20344
20076
|
if (!searchInput.trim() || searchInput.length < 2) {
|
|
20345
20077
|
return [];
|
|
20346
20078
|
}
|
|
@@ -20361,15 +20093,15 @@ function SearchPage() {
|
|
|
20361
20093
|
});
|
|
20362
20094
|
return Array.from(suggestionSet).slice(0, 5);
|
|
20363
20095
|
}, [searchInput, products]);
|
|
20364
|
-
|
|
20096
|
+
React10.useEffect(() => {
|
|
20365
20097
|
setSuggestions(generateSuggestions);
|
|
20366
20098
|
}, [generateSuggestions]);
|
|
20367
|
-
const sanitizeSearchInput =
|
|
20099
|
+
const sanitizeSearchInput = React10.useCallback((input) => {
|
|
20368
20100
|
let sanitized = input.trim();
|
|
20369
20101
|
sanitized = sanitized.replace(/\s+/g, " ");
|
|
20370
20102
|
return sanitized;
|
|
20371
20103
|
}, []);
|
|
20372
|
-
|
|
20104
|
+
React10.useEffect(() => {
|
|
20373
20105
|
const fetchSearchResults = async () => {
|
|
20374
20106
|
const sanitizedQuery = sanitizeSearchInput(searchQuery);
|
|
20375
20107
|
if (!sanitizedQuery) {
|
|
@@ -20628,7 +20360,7 @@ function SearchPage() {
|
|
|
20628
20360
|
}
|
|
20629
20361
|
function NewAddressPage() {
|
|
20630
20362
|
const router = navigation.useRouter();
|
|
20631
|
-
const [isSubmitting, setIsSubmitting] =
|
|
20363
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
20632
20364
|
const notification = useNotification();
|
|
20633
20365
|
const {
|
|
20634
20366
|
register,
|
|
@@ -20811,8 +20543,8 @@ function EditProfileScreen() {
|
|
|
20811
20543
|
const router = navigation.useRouter();
|
|
20812
20544
|
const { user, updateUser } = useAuth();
|
|
20813
20545
|
const { buildPath } = useBasePath();
|
|
20814
|
-
const [isSubmitting, setIsSubmitting] =
|
|
20815
|
-
const [status, setStatus] =
|
|
20546
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
20547
|
+
const [status, setStatus] = React10.useState(
|
|
20816
20548
|
null
|
|
20817
20549
|
);
|
|
20818
20550
|
const {
|
|
@@ -20966,7 +20698,7 @@ function ReviewForm({
|
|
|
20966
20698
|
onSuccess,
|
|
20967
20699
|
onCancel
|
|
20968
20700
|
}) {
|
|
20969
|
-
const [rating, setRating] =
|
|
20701
|
+
const [rating, setRating] = React10.useState(0);
|
|
20970
20702
|
const { createReview, isLoading } = useCreateReview();
|
|
20971
20703
|
const notification = useNotification();
|
|
20972
20704
|
const {
|
|
@@ -21130,9 +20862,9 @@ function OrderReviewsScreen() {
|
|
|
21130
20862
|
const router = navigation.useRouter();
|
|
21131
20863
|
const { isAuthenticated } = useAuth();
|
|
21132
20864
|
const { orders, isLoading, error, refetch } = useCurrentOrders();
|
|
21133
|
-
const [selectedOrder, setSelectedOrder] =
|
|
21134
|
-
const [selectedProduct, setSelectedProduct] =
|
|
21135
|
-
|
|
20865
|
+
const [selectedOrder, setSelectedOrder] = React10.useState(null);
|
|
20866
|
+
const [selectedProduct, setSelectedProduct] = React10.useState(null);
|
|
20867
|
+
React10__default.default.useEffect(() => {
|
|
21136
20868
|
if (!isLoading && !isAuthenticated) {
|
|
21137
20869
|
router.push("/login");
|
|
21138
20870
|
}
|
|
@@ -21435,10 +21167,10 @@ var Switch = ({ checked, onChange, disabled }) => /* @__PURE__ */ jsxRuntime.jsx
|
|
|
21435
21167
|
);
|
|
21436
21168
|
function NotificationSettingsScreen() {
|
|
21437
21169
|
const { settings, updateSettings, isLoading } = useNotificationCenter();
|
|
21438
|
-
const [localSettings, setLocalSettings] =
|
|
21439
|
-
const [isSaving, setIsSaving] =
|
|
21440
|
-
const [hasChanges, setHasChanges] =
|
|
21441
|
-
|
|
21170
|
+
const [localSettings, setLocalSettings] = React10.useState(settings);
|
|
21171
|
+
const [isSaving, setIsSaving] = React10.useState(false);
|
|
21172
|
+
const [hasChanges, setHasChanges] = React10.useState(false);
|
|
21173
|
+
React10.useEffect(() => {
|
|
21442
21174
|
if (settings) {
|
|
21443
21175
|
setLocalSettings(settings);
|
|
21444
21176
|
}
|
|
@@ -21584,7 +21316,7 @@ function OrderDetailScreen({ id }) {
|
|
|
21584
21316
|
const { order, isLoading, error } = useOrder(id);
|
|
21585
21317
|
if (isLoading) {
|
|
21586
21318
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen bg-slate-50 flex flex-col items-center justify-center p-4", children: [
|
|
21587
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 border-4 border-primary
|
|
21319
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 border-4 border-primary-20 border-t-primary rounded-full animate-spin mb-4" }),
|
|
21588
21320
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted font-medium animate-pulse", children: "Retrieving order details..." })
|
|
21589
21321
|
] });
|
|
21590
21322
|
}
|
|
@@ -21682,7 +21414,7 @@ function OrderDetailScreen({ id }) {
|
|
|
21682
21414
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-20 h-20 bg-slate-100 rounded-2xl overflow-hidden shrink-0 border border-slate-100 group-hover:scale-105 transition-transform duration-300", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
21683
21415
|
Image4__default.default,
|
|
21684
21416
|
{
|
|
21685
|
-
src: item.productVariantData?.media?.[0]?.file ||
|
|
21417
|
+
src: item.productVariantData?.media?.[0]?.file || PLACEHOLDER_IMAGE_SRC,
|
|
21686
21418
|
alt: item.productVariantData?.name || "Item",
|
|
21687
21419
|
fill: true,
|
|
21688
21420
|
className: "object-cover",
|
|
@@ -21754,7 +21486,7 @@ function OrderDetailScreen({ id }) {
|
|
|
21754
21486
|
{
|
|
21755
21487
|
initial: { opacity: 0, x: 20 },
|
|
21756
21488
|
animate: { opacity: 1, x: 0 },
|
|
21757
|
-
className: "bg-secondary p-8 rounded-[2rem] text-white shadow-xl shadow-secondary
|
|
21489
|
+
className: "bg-secondary p-8 rounded-[2rem] text-white shadow-xl shadow-secondary-20 sticky top-8",
|
|
21758
21490
|
children: [
|
|
21759
21491
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold mb-6 flex items-center gap-2", children: "Summary View" }),
|
|
21760
21492
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 mb-8", children: [
|
|
@@ -21811,8 +21543,8 @@ function ChangePasswordScreen() {
|
|
|
21811
21543
|
const router = navigation.useRouter();
|
|
21812
21544
|
const { user } = useAuth();
|
|
21813
21545
|
const { buildPath } = useBasePath();
|
|
21814
|
-
const [isSubmitting, setIsSubmitting] =
|
|
21815
|
-
const [status, setStatus] =
|
|
21546
|
+
const [isSubmitting, setIsSubmitting] = React10.useState(false);
|
|
21547
|
+
const [status, setStatus] = React10.useState(
|
|
21816
21548
|
null
|
|
21817
21549
|
);
|
|
21818
21550
|
const {
|
|
@@ -21856,103 +21588,440 @@ function ChangePasswordScreen() {
|
|
|
21856
21588
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-semibold text-slate-900", children: "Change password" })
|
|
21857
21589
|
] })
|
|
21858
21590
|
] }),
|
|
21859
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-sm text-slate-600", children: "Use a strong password that you have not used elsewhere. Updating your password will sign you out of other active sessions." }),
|
|
21860
|
-
status && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21591
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-sm text-slate-600", children: "Use a strong password that you have not used elsewhere. Updating your password will sign you out of other active sessions." }),
|
|
21592
|
+
status && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21593
|
+
"div",
|
|
21594
|
+
{
|
|
21595
|
+
className: `mt-4 flex items-start gap-2 rounded-2xl border px-4 py-3 text-sm ${status.type === "success" ? "border-green-200 bg-green-50 text-green-800" : "border-red-200 bg-red-50 text-red-700"}`,
|
|
21596
|
+
children: [
|
|
21597
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-[2px] text-base", children: status.type === "success" ? "\u2714" : "!" }),
|
|
21598
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: status.message })
|
|
21599
|
+
]
|
|
21600
|
+
}
|
|
21601
|
+
),
|
|
21602
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit(onSubmit), className: "mt-8 space-y-5", children: [
|
|
21603
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21604
|
+
Input,
|
|
21605
|
+
{
|
|
21606
|
+
type: "password",
|
|
21607
|
+
label: "Current password",
|
|
21608
|
+
placeholder: "Enter current password",
|
|
21609
|
+
...register("currentPassword"),
|
|
21610
|
+
error: errors.currentPassword?.message
|
|
21611
|
+
}
|
|
21612
|
+
),
|
|
21613
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21614
|
+
Input,
|
|
21615
|
+
{
|
|
21616
|
+
type: "password",
|
|
21617
|
+
label: "New password",
|
|
21618
|
+
placeholder: "Enter new password",
|
|
21619
|
+
...register("newPassword"),
|
|
21620
|
+
error: errors.newPassword?.message
|
|
21621
|
+
}
|
|
21622
|
+
),
|
|
21623
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21624
|
+
Input,
|
|
21625
|
+
{
|
|
21626
|
+
type: "password",
|
|
21627
|
+
label: "Confirm new password",
|
|
21628
|
+
placeholder: "Re-type new password",
|
|
21629
|
+
...register("confirmPassword"),
|
|
21630
|
+
error: errors.confirmPassword?.message
|
|
21631
|
+
}
|
|
21632
|
+
),
|
|
21633
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
21634
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21635
|
+
Button,
|
|
21636
|
+
{
|
|
21637
|
+
variant: "primary",
|
|
21638
|
+
type: "submit",
|
|
21639
|
+
size: "lg",
|
|
21640
|
+
isLoading: isSubmitting,
|
|
21641
|
+
children: "Save password"
|
|
21642
|
+
}
|
|
21643
|
+
),
|
|
21644
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21645
|
+
Button,
|
|
21646
|
+
{
|
|
21647
|
+
type: "button",
|
|
21648
|
+
variant: "outline-solid",
|
|
21649
|
+
size: "lg",
|
|
21650
|
+
className: "border-slate-300 text-slate-800 hover:bg-slate-50",
|
|
21651
|
+
onClick: () => router.push(buildPath("/account")),
|
|
21652
|
+
children: "Cancel"
|
|
21653
|
+
}
|
|
21654
|
+
)
|
|
21655
|
+
] })
|
|
21656
|
+
] }),
|
|
21657
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 flex items-center gap-2 rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600", children: [
|
|
21658
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShieldCheck, { className: "h-4 w-4 text-primary-600" }),
|
|
21659
|
+
"Strong passwords and up-to-date contact details help pharmacists verify changes quickly."
|
|
21660
|
+
] })
|
|
21661
|
+
]
|
|
21662
|
+
}
|
|
21663
|
+
) }) });
|
|
21664
|
+
}
|
|
21665
|
+
var getNotificationIcon = (type) => {
|
|
21666
|
+
const className = "w-5 h-5";
|
|
21667
|
+
switch (type) {
|
|
21668
|
+
case "ORDER_CONFIRMATION":
|
|
21669
|
+
case "ORDER_SHIPPED":
|
|
21670
|
+
case "ORDER_DELIVERED":
|
|
21671
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Package, { className });
|
|
21672
|
+
case "PAYMENT_FAILED":
|
|
21673
|
+
case "REFUND_PROCESSED":
|
|
21674
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className });
|
|
21675
|
+
case "PASSWORD_RESET":
|
|
21676
|
+
case "NEW_DEVICE_LOGIN":
|
|
21677
|
+
case "TWO_FA_CODE":
|
|
21678
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { className });
|
|
21679
|
+
case "ABANDONED_CART_REMINDER":
|
|
21680
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShoppingCart, { className });
|
|
21681
|
+
case "PRICE_DROP_ALERT":
|
|
21682
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingDown, { className });
|
|
21683
|
+
case "BACK_IN_STOCK":
|
|
21684
|
+
default:
|
|
21685
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bell, { className });
|
|
21686
|
+
}
|
|
21687
|
+
};
|
|
21688
|
+
var getNotificationColor = (type) => {
|
|
21689
|
+
switch (type) {
|
|
21690
|
+
case "ORDER_CONFIRMATION":
|
|
21691
|
+
case "ORDER_DELIVERED":
|
|
21692
|
+
case "REFUND_PROCESSED":
|
|
21693
|
+
return "bg-green-100 text-green-600";
|
|
21694
|
+
case "ORDER_SHIPPED":
|
|
21695
|
+
return "bg-blue-100 text-blue-600";
|
|
21696
|
+
case "PAYMENT_FAILED":
|
|
21697
|
+
return "bg-red-100 text-red-600";
|
|
21698
|
+
case "PASSWORD_RESET":
|
|
21699
|
+
case "NEW_DEVICE_LOGIN":
|
|
21700
|
+
case "TWO_FA_CODE":
|
|
21701
|
+
return "bg-purple-100 text-purple-600";
|
|
21702
|
+
case "ABANDONED_CART_REMINDER":
|
|
21703
|
+
case "PRICE_DROP_ALERT":
|
|
21704
|
+
case "BACK_IN_STOCK":
|
|
21705
|
+
return "bg-orange-100 text-orange-600";
|
|
21706
|
+
default:
|
|
21707
|
+
return "bg-gray-100 text-gray-600";
|
|
21708
|
+
}
|
|
21709
|
+
};
|
|
21710
|
+
var formatRelativeTime = (dateString) => {
|
|
21711
|
+
const date = new Date(dateString);
|
|
21712
|
+
const diff = Date.now() - date.getTime();
|
|
21713
|
+
const mins = Math.floor(diff / 6e4);
|
|
21714
|
+
const hours = Math.floor(diff / 36e5);
|
|
21715
|
+
const days = Math.floor(diff / 864e5);
|
|
21716
|
+
if (mins < 1) return "Just now";
|
|
21717
|
+
if (mins < 60) return `${mins} min ago`;
|
|
21718
|
+
if (hours < 24) return `${hours} hour${hours > 1 ? "s" : ""} ago`;
|
|
21719
|
+
if (days < 7) return `${days} day${days > 1 ? "s" : ""} ago`;
|
|
21720
|
+
return date.toLocaleDateString();
|
|
21721
|
+
};
|
|
21722
|
+
function NotificationCard({
|
|
21723
|
+
notification,
|
|
21724
|
+
onMarkAsRead,
|
|
21725
|
+
onDelete
|
|
21726
|
+
}) {
|
|
21727
|
+
const router = navigation.useRouter();
|
|
21728
|
+
const { buildPath } = useBasePath();
|
|
21729
|
+
const hasDragged = React10.useRef(false);
|
|
21730
|
+
const handleClick = () => {
|
|
21731
|
+
if (hasDragged.current) return;
|
|
21732
|
+
if (!notification.isRead) {
|
|
21733
|
+
onMarkAsRead(notification._id);
|
|
21734
|
+
}
|
|
21735
|
+
if (notification.data?.orderId) {
|
|
21736
|
+
router.push(buildPath(`/account/orders/${notification.data.orderId}`));
|
|
21737
|
+
} else if (notification.data?.productId) {
|
|
21738
|
+
router.push(buildPath(`/products/${notification.data.productId}`));
|
|
21739
|
+
}
|
|
21740
|
+
};
|
|
21741
|
+
const handleDelete = (e) => {
|
|
21742
|
+
e.stopPropagation();
|
|
21743
|
+
onDelete(notification._id);
|
|
21744
|
+
};
|
|
21745
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-hidden rounded-lg", children: [
|
|
21746
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-end px-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1 text-white", children: [
|
|
21747
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-5 h-5" }),
|
|
21748
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold uppercase tracking-wider", children: "Remove" })
|
|
21749
|
+
] }) }),
|
|
21750
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21751
|
+
framerMotion.motion.div,
|
|
21752
|
+
{
|
|
21753
|
+
drag: "x",
|
|
21754
|
+
initial: { opacity: 0, x: 0 },
|
|
21755
|
+
animate: { opacity: 1, x: 0 },
|
|
21756
|
+
className: `relative z-10 p-4 border cursor-pointer select-none touch-pan-y transition-colors ${notification.isRead ? "bg-white border-gray-200" : "bg-blue-50 border-blue-200"}`,
|
|
21757
|
+
onClick: handleClick,
|
|
21758
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
21759
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21760
|
+
"div",
|
|
21761
|
+
{
|
|
21762
|
+
className: `flex-shrink-0 w-10 h-10 rounded-full flex items-center justify-center ${getNotificationColor(
|
|
21763
|
+
notification.type
|
|
21764
|
+
)}`,
|
|
21765
|
+
children: getNotificationIcon(notification.type)
|
|
21766
|
+
}
|
|
21767
|
+
),
|
|
21768
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
21769
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
21770
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-gray-900 text-sm line-clamp-1", children: notification.title }),
|
|
21771
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21772
|
+
"button",
|
|
21773
|
+
{
|
|
21774
|
+
onClick: handleDelete,
|
|
21775
|
+
className: "flex-shrink-0 p-1 bg-gray-100 rounded-full hover:bg-red-50",
|
|
21776
|
+
"aria-label": "Delete notification",
|
|
21777
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4 text-gray-400 hover:text-red-500" })
|
|
21778
|
+
}
|
|
21779
|
+
)
|
|
21780
|
+
] }),
|
|
21781
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600 mt-1 line-clamp-2", children: notification.body }),
|
|
21782
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
21783
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500", children: formatRelativeTime(notification.createdAt) }),
|
|
21784
|
+
!notification.isRead && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21785
|
+
"span",
|
|
21786
|
+
{
|
|
21787
|
+
className: "w-2 h-2 bg-blue-500 rounded-full",
|
|
21788
|
+
"aria-label": "Unread"
|
|
21789
|
+
}
|
|
21790
|
+
)
|
|
21791
|
+
] })
|
|
21792
|
+
] })
|
|
21793
|
+
] })
|
|
21794
|
+
}
|
|
21795
|
+
)
|
|
21796
|
+
] });
|
|
21797
|
+
}
|
|
21798
|
+
var modalVariants = {
|
|
21799
|
+
hidden: { opacity: 0, y: -8, scale: 0.96 },
|
|
21800
|
+
visible: { opacity: 1, y: 0, scale: 1 },
|
|
21801
|
+
exit: { opacity: 0, y: -8, scale: 0.96 }
|
|
21802
|
+
};
|
|
21803
|
+
function NotificationModal() {
|
|
21804
|
+
const {
|
|
21805
|
+
isDrawerOpen,
|
|
21806
|
+
closeDrawer,
|
|
21807
|
+
notifications,
|
|
21808
|
+
unreadCount,
|
|
21809
|
+
isLoading,
|
|
21810
|
+
markAsRead,
|
|
21811
|
+
markAllAsRead,
|
|
21812
|
+
deleteNotification,
|
|
21813
|
+
loadMore,
|
|
21814
|
+
hasMore
|
|
21815
|
+
} = useNotificationCenter();
|
|
21816
|
+
const router = navigation.useRouter();
|
|
21817
|
+
const { buildPath } = useBasePath();
|
|
21818
|
+
const scrollRef = React10.useRef(null);
|
|
21819
|
+
const modalRef = React10.useRef(null);
|
|
21820
|
+
const lastScrollTrigger = React10.useRef(0);
|
|
21821
|
+
const handleScroll = React10.useCallback(() => {
|
|
21822
|
+
if (!scrollRef.current || isLoading || !hasMore) return;
|
|
21823
|
+
const now = Date.now();
|
|
21824
|
+
if (now - lastScrollTrigger.current < 300) return;
|
|
21825
|
+
const { scrollTop, scrollHeight, clientHeight } = scrollRef.current;
|
|
21826
|
+
if ((scrollTop + clientHeight) / scrollHeight > 0.8) {
|
|
21827
|
+
lastScrollTrigger.current = now;
|
|
21828
|
+
loadMore();
|
|
21829
|
+
}
|
|
21830
|
+
}, [isLoading, hasMore, loadMore]);
|
|
21831
|
+
const handleSettingsClick = React10.useCallback(() => {
|
|
21832
|
+
closeDrawer();
|
|
21833
|
+
router.push(buildPath("/account/notifications"));
|
|
21834
|
+
}, [closeDrawer, router, buildPath]);
|
|
21835
|
+
React10.useEffect(() => {
|
|
21836
|
+
if (!isDrawerOpen) return;
|
|
21837
|
+
modalRef.current?.focus();
|
|
21838
|
+
const onKeyDown = (e) => {
|
|
21839
|
+
if (e.key === "Escape") closeDrawer();
|
|
21840
|
+
};
|
|
21841
|
+
document.addEventListener("keydown", onKeyDown);
|
|
21842
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
21843
|
+
}, [isDrawerOpen, closeDrawer]);
|
|
21844
|
+
React10.useEffect(() => {
|
|
21845
|
+
if (!isDrawerOpen) return;
|
|
21846
|
+
const handleClickOutside = (e) => {
|
|
21847
|
+
const bellButton = document.getElementById("notification-bell-button");
|
|
21848
|
+
if (modalRef.current && !modalRef.current.contains(e.target) && !bellButton?.contains(e.target)) {
|
|
21849
|
+
closeDrawer();
|
|
21850
|
+
}
|
|
21851
|
+
};
|
|
21852
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
21853
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
21854
|
+
}, [isDrawerOpen, closeDrawer]);
|
|
21855
|
+
const hasNotifications = notifications.length > 0;
|
|
21856
|
+
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isDrawerOpen && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21857
|
+
framerMotion.motion.div,
|
|
21858
|
+
{
|
|
21859
|
+
ref: modalRef,
|
|
21860
|
+
role: "dialog",
|
|
21861
|
+
"aria-modal": "true",
|
|
21862
|
+
"aria-labelledby": "notification-title",
|
|
21863
|
+
tabIndex: -1,
|
|
21864
|
+
variants: modalVariants,
|
|
21865
|
+
initial: "hidden",
|
|
21866
|
+
animate: "visible",
|
|
21867
|
+
exit: "exit",
|
|
21868
|
+
transition: { type: "spring", stiffness: 350, damping: 28 },
|
|
21869
|
+
className: "absolute top-full lg:right-0 mt-1 lg:w-screen lg:max-w-sm bg-white rounded-2xl shadow-[0_20px_50px_-12px_rgba(0,0,0,0.15)] z-[100] flex flex-col overflow-hidden border border-gray-100 origin-top-right rounded-lg border border-slate-200 bg-white shadow-lg",
|
|
21870
|
+
style: { maxHeight: "calc(100vh - 120px)" },
|
|
21871
|
+
children: [
|
|
21872
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-1 right-5 w-3 h-3 bg-white border-l border-t border-gray-100 transform rotate-45 z-10" }),
|
|
21873
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b bg-gradient-to-r from-primary-50 to-white", children: [
|
|
21874
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
21875
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21876
|
+
"h2",
|
|
21877
|
+
{
|
|
21878
|
+
id: "notification-title",
|
|
21879
|
+
className: "text-lg font-bold text-gray-900",
|
|
21880
|
+
children: "Notifications"
|
|
21881
|
+
}
|
|
21882
|
+
),
|
|
21883
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21884
|
+
"span",
|
|
21885
|
+
{
|
|
21886
|
+
"aria-live": "polite",
|
|
21887
|
+
className: "bg-red-500 text-white text-xs font-bold px-2 py-0.5 rounded-full",
|
|
21888
|
+
children: unreadCount
|
|
21889
|
+
}
|
|
21890
|
+
)
|
|
21891
|
+
] }),
|
|
21892
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
21893
|
+
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21894
|
+
"button",
|
|
21895
|
+
{
|
|
21896
|
+
onClick: markAllAsRead,
|
|
21897
|
+
title: "Mark all as read",
|
|
21898
|
+
className: "p-2 rounded-lg hover:bg-white transition",
|
|
21899
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { className: "w-4 h-4 text-gray-600" })
|
|
21900
|
+
}
|
|
21901
|
+
),
|
|
21902
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21903
|
+
"button",
|
|
21904
|
+
{
|
|
21905
|
+
onClick: handleSettingsClick,
|
|
21906
|
+
title: "Notification settings",
|
|
21907
|
+
className: "p-2 rounded-lg hover:bg-white transition",
|
|
21908
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "w-4 h-4 text-gray-600" })
|
|
21909
|
+
}
|
|
21910
|
+
),
|
|
21911
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21912
|
+
"button",
|
|
21913
|
+
{
|
|
21914
|
+
onClick: closeDrawer,
|
|
21915
|
+
"aria-label": "Close notifications",
|
|
21916
|
+
className: "p-2 rounded-lg hover:bg-red-50 transition",
|
|
21917
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4 text-gray-600" })
|
|
21918
|
+
}
|
|
21919
|
+
)
|
|
21920
|
+
] })
|
|
21921
|
+
] }),
|
|
21922
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21861
21923
|
"div",
|
|
21862
21924
|
{
|
|
21863
|
-
|
|
21864
|
-
|
|
21865
|
-
|
|
21866
|
-
|
|
21867
|
-
|
|
21925
|
+
ref: scrollRef,
|
|
21926
|
+
onScroll: handleScroll,
|
|
21927
|
+
className: "flex-1 overflow-y-auto p-3 space-y-2 bg-gray-50 scrollbar-thin scrollbar-thumb-gray-300",
|
|
21928
|
+
children: !hasNotifications && !isLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-14 text-center", children: [
|
|
21929
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BellOff, { className: "w-10 h-10 text-gray-400 mb-3" }),
|
|
21930
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-700", children: "No notifications yet" }),
|
|
21931
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "You\u2019re all caught up \u{1F389}" })
|
|
21932
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21933
|
+
notifications.map((notification) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
21934
|
+
NotificationCard,
|
|
21935
|
+
{
|
|
21936
|
+
notification,
|
|
21937
|
+
onMarkAsRead: markAsRead,
|
|
21938
|
+
onDelete: deleteNotification
|
|
21939
|
+
},
|
|
21940
|
+
notification._id
|
|
21941
|
+
)),
|
|
21942
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2 py-2", children: [...Array(3)].map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
21943
|
+
"div",
|
|
21944
|
+
{
|
|
21945
|
+
className: "h-16 rounded-xl bg-gray-200 animate-pulse"
|
|
21946
|
+
},
|
|
21947
|
+
i
|
|
21948
|
+
)) }),
|
|
21949
|
+
!hasMore && hasNotifications && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-3 text-xs text-gray-500", children: "You\u2019re all caught up \u{1F389}" })
|
|
21950
|
+
] })
|
|
21868
21951
|
}
|
|
21869
|
-
)
|
|
21870
|
-
|
|
21871
|
-
|
|
21872
|
-
|
|
21873
|
-
|
|
21874
|
-
|
|
21875
|
-
|
|
21876
|
-
|
|
21877
|
-
|
|
21878
|
-
|
|
21879
|
-
|
|
21880
|
-
|
|
21881
|
-
|
|
21882
|
-
|
|
21883
|
-
|
|
21884
|
-
|
|
21885
|
-
|
|
21886
|
-
|
|
21887
|
-
|
|
21888
|
-
|
|
21889
|
-
|
|
21890
|
-
|
|
21952
|
+
)
|
|
21953
|
+
]
|
|
21954
|
+
}
|
|
21955
|
+
) }) });
|
|
21956
|
+
}
|
|
21957
|
+
function NotificationBell() {
|
|
21958
|
+
const { unreadCount, isDrawerOpen, openDrawer, closeDrawer } = useNotificationCenter();
|
|
21959
|
+
const handleToggle = (e) => {
|
|
21960
|
+
e.stopPropagation();
|
|
21961
|
+
if (isDrawerOpen) {
|
|
21962
|
+
closeDrawer();
|
|
21963
|
+
} else {
|
|
21964
|
+
openDrawer();
|
|
21965
|
+
}
|
|
21966
|
+
};
|
|
21967
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
21968
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
21969
|
+
framerMotion.motion.button,
|
|
21970
|
+
{
|
|
21971
|
+
id: "notification-bell-button",
|
|
21972
|
+
onClick: handleToggle,
|
|
21973
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
21974
|
+
className: `relative p-2.5 rounded-xl transition-all duration-300 group flex items-center justify-center ${isDrawerOpen ? "bg-primary-50 text-primary-600" : "hover:bg-gradient-to-br hover:from-primary-50 hover:to-primary-100/50 text-gray-700"}`,
|
|
21975
|
+
"aria-label": "Notifications",
|
|
21976
|
+
whileHover: isDrawerOpen ? {} : { scale: 1.05 },
|
|
21977
|
+
whileTap: { scale: 0.95 },
|
|
21978
|
+
children: [
|
|
21891
21979
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21892
|
-
|
|
21980
|
+
lucideReact.Bell,
|
|
21893
21981
|
{
|
|
21894
|
-
|
|
21895
|
-
|
|
21896
|
-
placeholder: "Re-type new password",
|
|
21897
|
-
...register("confirmPassword"),
|
|
21898
|
-
error: errors.confirmPassword?.message
|
|
21982
|
+
className: `w-6 h-6 transition-colors duration-300 ${isDrawerOpen ? "text-primary-600 bg-gray-100 rounded-lg p-2 w-10 h-10 transition-all duration-300" : "group-hover:text-primary-600"}`,
|
|
21983
|
+
strokeWidth: 2
|
|
21899
21984
|
}
|
|
21900
21985
|
),
|
|
21901
|
-
/* @__PURE__ */ jsxRuntime.
|
|
21986
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21902
21987
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21903
|
-
|
|
21988
|
+
framerMotion.motion.span,
|
|
21904
21989
|
{
|
|
21905
|
-
|
|
21906
|
-
|
|
21907
|
-
|
|
21908
|
-
|
|
21909
|
-
|
|
21990
|
+
initial: { scale: 0.8, opacity: 0 },
|
|
21991
|
+
animate: {
|
|
21992
|
+
scale: [1, 1.4, 1.4],
|
|
21993
|
+
opacity: [0.6, 0, 0]
|
|
21994
|
+
},
|
|
21995
|
+
exit: { scale: 0, opacity: 0 },
|
|
21996
|
+
transition: {
|
|
21997
|
+
duration: 2,
|
|
21998
|
+
repeat: Infinity,
|
|
21999
|
+
repeatDelay: 0.5
|
|
22000
|
+
},
|
|
22001
|
+
className: "absolute -top-0.5 -right-0.5 w-6 h-6 bg-red-500 rounded-full"
|
|
21910
22002
|
}
|
|
21911
22003
|
),
|
|
21912
22004
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21913
|
-
|
|
22005
|
+
framerMotion.motion.span,
|
|
21914
22006
|
{
|
|
21915
|
-
|
|
21916
|
-
|
|
21917
|
-
|
|
21918
|
-
|
|
21919
|
-
|
|
21920
|
-
|
|
22007
|
+
initial: { scale: 0, rotate: -180 },
|
|
22008
|
+
animate: { scale: 1, rotate: 0 },
|
|
22009
|
+
exit: { scale: 0, rotate: 180 },
|
|
22010
|
+
transition: {
|
|
22011
|
+
type: "spring",
|
|
22012
|
+
damping: 15,
|
|
22013
|
+
stiffness: 300
|
|
22014
|
+
},
|
|
22015
|
+
className: "absolute -top-1 -right-1 min-w-[20px] h-5 bg-gradient-to-br from-red-500 to-red-600 text-white text-[10px] font-bold rounded-full flex items-center justify-center px-1.5 shadow-lg shadow-red-500/40 border-2 border-white",
|
|
22016
|
+
children: unreadCount > 99 ? "99+" : unreadCount
|
|
21921
22017
|
}
|
|
21922
22018
|
)
|
|
21923
|
-
] })
|
|
21924
|
-
]
|
|
21925
|
-
|
|
21926
|
-
|
|
21927
|
-
|
|
21928
|
-
|
|
21929
|
-
]
|
|
21930
|
-
}
|
|
21931
|
-
) }) });
|
|
21932
|
-
}
|
|
21933
|
-
function NotificationBell() {
|
|
21934
|
-
const { unreadCount, openDrawer } = useNotificationCenter();
|
|
21935
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21936
|
-
"button",
|
|
21937
|
-
{
|
|
21938
|
-
onClick: openDrawer,
|
|
21939
|
-
className: "relative p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
21940
|
-
"aria-label": "Notifications",
|
|
21941
|
-
children: [
|
|
21942
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bell, { className: "w-6 h-6 text-gray-700" }),
|
|
21943
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21944
|
-
framerMotion.motion.span,
|
|
21945
|
-
{
|
|
21946
|
-
initial: { scale: 0 },
|
|
21947
|
-
animate: { scale: 1 },
|
|
21948
|
-
exit: { scale: 0 },
|
|
21949
|
-
className: "absolute -top-1 -right-1 bg-red-500 text-white text-xs font-bold rounded-full w-5 h-5 flex items-center justify-center",
|
|
21950
|
-
children: unreadCount > 99 ? "99+" : unreadCount
|
|
21951
|
-
}
|
|
21952
|
-
) })
|
|
21953
|
-
]
|
|
21954
|
-
}
|
|
21955
|
-
);
|
|
22019
|
+
] }) })
|
|
22020
|
+
]
|
|
22021
|
+
}
|
|
22022
|
+
),
|
|
22023
|
+
/* @__PURE__ */ jsxRuntime.jsx(NotificationModal, {})
|
|
22024
|
+
] });
|
|
21956
22025
|
}
|
|
21957
22026
|
function Header() {
|
|
21958
22027
|
const { config } = useTheme();
|
|
@@ -21960,11 +22029,11 @@ function Header() {
|
|
|
21960
22029
|
const { cart } = useCart() || { cart: { } };
|
|
21961
22030
|
const { getWishlistCount } = useWishlist();
|
|
21962
22031
|
const wishlistCount = getWishlistCount?.() || 0;
|
|
21963
|
-
const [isMobileMenuOpen, setIsMobileMenuOpen] =
|
|
21964
|
-
const [isSearchOpen, setIsSearchOpen] =
|
|
21965
|
-
const [isDropdownOpen, setIsDropdownOpen] =
|
|
21966
|
-
const [isLoggingOut, setIsLoggingOut] =
|
|
21967
|
-
const [searchQuery, setSearchQuery] =
|
|
22032
|
+
const [isMobileMenuOpen, setIsMobileMenuOpen] = React10.useState(false);
|
|
22033
|
+
const [isSearchOpen, setIsSearchOpen] = React10.useState(false);
|
|
22034
|
+
const [isDropdownOpen, setIsDropdownOpen] = React10.useState(false);
|
|
22035
|
+
const [isLoggingOut, setIsLoggingOut] = React10.useState(false);
|
|
22036
|
+
const [searchQuery, setSearchQuery] = React10.useState("");
|
|
21968
22037
|
const { buildPath } = useBasePath();
|
|
21969
22038
|
const router = navigation.useRouter();
|
|
21970
22039
|
const handleLogout = async () => {
|
|
@@ -22297,6 +22366,141 @@ function Footer() {
|
|
|
22297
22366
|
] })
|
|
22298
22367
|
] }) });
|
|
22299
22368
|
}
|
|
22369
|
+
function NotificationDrawer() {
|
|
22370
|
+
const {
|
|
22371
|
+
isDrawerOpen,
|
|
22372
|
+
closeDrawer,
|
|
22373
|
+
notifications,
|
|
22374
|
+
unreadCount,
|
|
22375
|
+
isLoading,
|
|
22376
|
+
markAsRead,
|
|
22377
|
+
markAllAsRead,
|
|
22378
|
+
deleteNotification,
|
|
22379
|
+
loadMore,
|
|
22380
|
+
hasMore
|
|
22381
|
+
} = useNotificationCenter();
|
|
22382
|
+
const router = navigation.useRouter();
|
|
22383
|
+
const { buildPath } = useBasePath();
|
|
22384
|
+
const scrollContainerRef = React10.useRef(null);
|
|
22385
|
+
const handleScroll = () => {
|
|
22386
|
+
if (!scrollContainerRef.current || isLoading || !hasMore) return;
|
|
22387
|
+
const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
|
|
22388
|
+
const scrollPercentage = (scrollTop + clientHeight) / scrollHeight;
|
|
22389
|
+
if (scrollPercentage > 0.8) {
|
|
22390
|
+
loadMore();
|
|
22391
|
+
}
|
|
22392
|
+
};
|
|
22393
|
+
React10.useEffect(() => {
|
|
22394
|
+
const handleEscape = (e) => {
|
|
22395
|
+
if (e.key === "Escape" && isDrawerOpen) {
|
|
22396
|
+
closeDrawer();
|
|
22397
|
+
}
|
|
22398
|
+
};
|
|
22399
|
+
document.addEventListener("keydown", handleEscape);
|
|
22400
|
+
return () => document.removeEventListener("keydown", handleEscape);
|
|
22401
|
+
}, [isDrawerOpen, closeDrawer]);
|
|
22402
|
+
React10.useEffect(() => {
|
|
22403
|
+
if (isDrawerOpen) {
|
|
22404
|
+
document.body.style.overflow = "hidden";
|
|
22405
|
+
} else {
|
|
22406
|
+
document.body.style.overflow = "";
|
|
22407
|
+
}
|
|
22408
|
+
return () => {
|
|
22409
|
+
document.body.style.overflow = "";
|
|
22410
|
+
};
|
|
22411
|
+
}, [isDrawerOpen]);
|
|
22412
|
+
const handleSettingsClick = () => {
|
|
22413
|
+
closeDrawer();
|
|
22414
|
+
router.push(buildPath("/account/notifications"));
|
|
22415
|
+
};
|
|
22416
|
+
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isDrawerOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
22417
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22418
|
+
framerMotion.motion.div,
|
|
22419
|
+
{
|
|
22420
|
+
initial: { opacity: 0 },
|
|
22421
|
+
animate: { opacity: 1 },
|
|
22422
|
+
exit: { opacity: 0 },
|
|
22423
|
+
className: "fixed inset-0 bg-black/50 z-40",
|
|
22424
|
+
onClick: closeDrawer
|
|
22425
|
+
}
|
|
22426
|
+
),
|
|
22427
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22428
|
+
framerMotion.motion.div,
|
|
22429
|
+
{
|
|
22430
|
+
initial: { x: "100%" },
|
|
22431
|
+
animate: { x: 0 },
|
|
22432
|
+
exit: { x: "100%" },
|
|
22433
|
+
transition: { type: "spring", damping: 25, stiffness: 200 },
|
|
22434
|
+
className: "fixed right-0 top-0 bottom-0 w-full sm:w-[480px] bg-white shadow-2xl z-50 flex flex-col max-w-[480px]",
|
|
22435
|
+
children: [
|
|
22436
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b border-gray-200 bg-white", children: [
|
|
22437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
22438
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold text-gray-900", children: "Notifications" }),
|
|
22439
|
+
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-red-500 text-white text-xs font-bold px-2 py-1 rounded-full", children: unreadCount })
|
|
22440
|
+
] }),
|
|
22441
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
22442
|
+
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22443
|
+
"button",
|
|
22444
|
+
{
|
|
22445
|
+
onClick: markAllAsRead,
|
|
22446
|
+
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
22447
|
+
title: "Mark all as read",
|
|
22448
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { className: "w-5 h-5 text-gray-600" })
|
|
22449
|
+
}
|
|
22450
|
+
),
|
|
22451
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22452
|
+
"button",
|
|
22453
|
+
{
|
|
22454
|
+
onClick: handleSettingsClick,
|
|
22455
|
+
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
22456
|
+
title: "Notification settings",
|
|
22457
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "w-5 h-5 text-gray-600" })
|
|
22458
|
+
}
|
|
22459
|
+
),
|
|
22460
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22461
|
+
"button",
|
|
22462
|
+
{
|
|
22463
|
+
onClick: closeDrawer,
|
|
22464
|
+
className: "p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
22465
|
+
"aria-label": "Close",
|
|
22466
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-5 h-5 text-gray-600" })
|
|
22467
|
+
}
|
|
22468
|
+
)
|
|
22469
|
+
] })
|
|
22470
|
+
] }),
|
|
22471
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22472
|
+
"div",
|
|
22473
|
+
{
|
|
22474
|
+
ref: scrollContainerRef,
|
|
22475
|
+
onScroll: handleScroll,
|
|
22476
|
+
className: "flex-1 overflow-y-auto p-4 space-y-3",
|
|
22477
|
+
children: notifications.length === 0 && !isLoading ? (
|
|
22478
|
+
// Empty state
|
|
22479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center py-12", children: [
|
|
22480
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BellOff, { className: "w-10 h-10 text-gray-400" }) }),
|
|
22481
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: "No notifications yet" }),
|
|
22482
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 max-w-xs", children: "When you receive notifications, they'll appear here" })
|
|
22483
|
+
] })
|
|
22484
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
22485
|
+
notifications.map((notification) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
22486
|
+
NotificationCard,
|
|
22487
|
+
{
|
|
22488
|
+
notification,
|
|
22489
|
+
onMarkAsRead: markAsRead,
|
|
22490
|
+
onDelete: deleteNotification
|
|
22491
|
+
},
|
|
22492
|
+
notification._id
|
|
22493
|
+
)),
|
|
22494
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 border-2 border-primary-600 border-t-transparent rounded-full animate-spin" }) }),
|
|
22495
|
+
!hasMore && notifications.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-4 text-sm text-gray-500", children: "You're all caught up! \u{1F389}" })
|
|
22496
|
+
] })
|
|
22497
|
+
}
|
|
22498
|
+
)
|
|
22499
|
+
]
|
|
22500
|
+
}
|
|
22501
|
+
)
|
|
22502
|
+
] }) });
|
|
22503
|
+
}
|
|
22300
22504
|
|
|
22301
22505
|
exports.AccountReviewsTab = AccountReviewsTab;
|
|
22302
22506
|
exports.AddressAddressTypeEnum = AddressAddressTypeEnum;
|