hey-pharmacist-ecommerce 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,17 @@
1
- # Hey Pharmacist E-commerce Package
1
+ # Hey Pharmacist Ecommerce
2
2
 
3
- A multi-tenant e-commerce package for Next.js applications with stunning design and full functionality.
3
+ Production‑ready, multitenant ecommerce UI + API adapter for Next.js. It ships with end‑to‑end flows (browse, cart, checkout, orders), robust authentication, typed SDKs, and a polished pharmacist‑grade UX. Drop it into a Next.js app, point it at your API, and ship a beautiful store in hours—not weeks.
4
4
 
5
- ## Features
5
+ ## Highlights
6
6
 
7
- - 🛒 **Complete E-commerce Flow**: Shop, cart, checkout, orders
8
- - 🎨 **Stunning Design**: Modern UI with smooth animations
9
- - 🔐 **Authentication**: Login, register, profile management
10
- - 💳 **Stripe Integration**: Secure payment processing
11
- - 🏪 **Multi-tenant**: Single package, multiple stores
12
- - 📱 **Responsive**: Works on all devices
13
- - **Fast**: Optimized for performance
7
+ - 🛒 **Complete flows**: Shop, product details, wishlist, cart, checkout, orders (history + current)
8
+ - 🔐 **Auth built‑in**: Sign up/in, profile, token persistence, background rehydration
9
+ - 💳 **Payments**: Card/Cash/Credit modes; Stripe‑ready checkout handoff
10
+ - 🧩 **Typed API adapters**: Generated axios SDK under `src/lib/Apis` with bearer + store key headers
11
+ - 🎨 **Themeable**: Brand colors + configurable header gradient via `EcommerceConfig`
12
+ - 🧠 **Smart UX**: Skeletons, optimistic UI, searchable overflow filters, and mobile‑first layouts
13
+ - 🧱 **Composable**: Use our screens, or import atomic components and hooks
14
+ - ⚡ **Production‑grade**: Tree‑shakable build, types, sourcemaps, React 18, Next 14
14
15
 
15
16
  ## Installation
16
17
 
@@ -20,7 +21,7 @@ npm install hey-pharmacist-ecommerce react-hook-form @hookform/resolvers
20
21
 
21
22
  ## Quick Start
22
23
 
23
- ### 1. Configure Your Store
24
+ ### 1) Configure your store
24
25
 
25
26
  Create a config file for your store:
26
27
 
@@ -40,7 +41,7 @@ export const ecommerceConfig = {
40
41
  };
41
42
  ```
42
43
 
43
- ### 2. Wrap Your App
44
+ ### 2) Wrap your app
44
45
 
45
46
  ```tsx
46
47
  // app/layout.tsx
@@ -64,7 +65,7 @@ export default function RootLayout({
64
65
  }
65
66
  ```
66
67
 
67
- ### 3. Use the Screens
68
+ ### 3) Use the screens
68
69
 
69
70
  ```tsx
70
71
  // app/shop/page.tsx
@@ -75,7 +76,7 @@ export default function ShopPage() {
75
76
  }
76
77
  ```
77
78
 
78
- ## Available Screens
79
+ ## Available screens
79
80
 
80
81
  - `<ShopScreen />` - Product listing with filters
81
82
  - `<ProductDetailScreen />` - Individual product page
@@ -87,9 +88,26 @@ export default function ShopPage() {
87
88
  - `<OrdersScreen />` - Order history
88
89
  - `<CurrentOrdersScreen />` - Active orders
89
90
 
90
- ## Customization
91
+ ## Theming and customization
91
92
 
92
- The package uses CSS variables for theming. Your colors are automatically applied throughout the interface.
93
+ The package exposes CSS variables for theme colors and a dynamic header gradient. Update via `EcommerceConfig`:
94
+
95
+ ```ts
96
+ headerGradient?: { from: string; via: string; to: string } // hex colors
97
+ ```
98
+
99
+ Under the hood, `ThemeProvider` sets `--color-<brand>-<shade>` and:
100
+
101
+ ```css
102
+ from: rgb(var(--header-from));
103
+ via: rgb(var(--header-via));
104
+ to: rgb(var(--header-to));
105
+ ```
106
+
107
+ Update colors/gradient at runtime and the UI updates automatically.
108
+
109
+ ### Using individual components
110
+ You can import components like `Header`, `Footer`, `ProductCard`, `OrderCard`, and UI primitives (`Button`, `Input`, `Modal`, etc.) for bespoke pages.
93
111
 
94
112
  ## Requirements
95
113
 
@@ -97,9 +115,19 @@ The package uses CSS variables for theming. Your colors are automatically applie
97
115
  - Next.js 14+
98
116
  - react-hook-form 7+
99
117
 
100
- ## Local Development & Testing
118
+ ## Architecture
119
+
120
+ - Screens (page‑level flows) under `src/screens`
121
+ - Providers for Auth, Cart, Wishlist, Theme under `src/providers`
122
+ - Hooks for products, orders, wishlist, addresses under `src/hooks`
123
+ - Generated API SDK under `src/lib/Apis` (axios + typed models)
124
+ - API adapter bridge under `src/lib/api-adapter`
125
+
126
+ Auth persists access token using `localStorage` and rehydrates on load. Requests attach `x-store-key` and `Authorization: Bearer` automatically.
101
127
 
102
- ### Testing Locally Before Publishing
128
+ ## Local development & testing
129
+
130
+ ### Testing locally before publishing
103
131
 
104
132
  You can test the package locally in your frontend project using npm link:
105
133
 
@@ -203,6 +231,12 @@ npm version patch # or minor, or major
203
231
  npm publish
204
232
  ```
205
233
 
234
+ ## Troubleshooting
235
+
236
+ - Types not emitted: ensure `tsup` dts is enabled and `tsconfig` does not use incremental for dts build.
237
+ - 401 after refresh: confirm `AuthProvider` calls `setAuthToken` on login/register and that `initializeApiAdapter` runs at app boot.
238
+ - Filters not working server‑side: pass `orderStatus` and `paymentStatus` to `useOrders` to forward to `getAllOrders`.
239
+
206
240
  ## License
207
241
 
208
- MIT# hey-pharmacist-customer
242
+ MIT
package/dist/index.js CHANGED
@@ -6357,6 +6357,318 @@ var ShippingApi = class extends BaseAPI {
6357
6357
  return ShippingApiFp(this.configuration).updateZone(body, zoneId, options).then((request) => request(this.axios, this.basePath));
6358
6358
  }
6359
6359
  };
6360
+ var WishlistApiAxiosParamCreator = function(configuration) {
6361
+ return {
6362
+ /**
6363
+ *
6364
+ * @summary Add product to wishlist
6365
+ * @param {string} productId
6366
+ * @param {*} [options] Override http request option.
6367
+ * @throws {RequiredError}
6368
+ */
6369
+ addToWishlist: async (productId, options = {}) => {
6370
+ if (productId === null || productId === void 0) {
6371
+ throw new RequiredError("productId", "Required parameter productId was null or undefined when calling addToWishlist.");
6372
+ }
6373
+ const localVarPath = `/wishlist/add/{productId}`.replace(`{${"productId"}}`, encodeURIComponent(String(productId)));
6374
+ const localVarUrlObj = new URL(localVarPath, "https://example.com");
6375
+ let baseOptions;
6376
+ if (configuration) {
6377
+ baseOptions = configuration.baseOptions;
6378
+ }
6379
+ const localVarRequestOptions = { method: "POST", ...baseOptions, ...options };
6380
+ const localVarHeaderParameter = {};
6381
+ const localVarQueryParameter = {};
6382
+ if (configuration && configuration.accessToken) {
6383
+ const accessToken = typeof configuration.accessToken === "function" ? await configuration.accessToken() : await configuration.accessToken;
6384
+ localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
6385
+ }
6386
+ const query = new URLSearchParams(localVarUrlObj.search);
6387
+ for (const key in localVarQueryParameter) {
6388
+ query.set(key, localVarQueryParameter[key]);
6389
+ }
6390
+ for (const key in options.params) {
6391
+ query.set(key, options.params[key]);
6392
+ }
6393
+ localVarUrlObj.search = new URLSearchParams(query).toString();
6394
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6395
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6396
+ return {
6397
+ url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
6398
+ options: localVarRequestOptions
6399
+ };
6400
+ },
6401
+ /**
6402
+ *
6403
+ * @summary Clear wishlist
6404
+ * @param {*} [options] Override http request option.
6405
+ * @throws {RequiredError}
6406
+ */
6407
+ clearWishlist: async (options = {}) => {
6408
+ const localVarPath = `/wishlist/clear`;
6409
+ const localVarUrlObj = new URL(localVarPath, "https://example.com");
6410
+ let baseOptions;
6411
+ if (configuration) {
6412
+ baseOptions = configuration.baseOptions;
6413
+ }
6414
+ const localVarRequestOptions = { method: "DELETE", ...baseOptions, ...options };
6415
+ const localVarHeaderParameter = {};
6416
+ const localVarQueryParameter = {};
6417
+ if (configuration && configuration.accessToken) {
6418
+ const accessToken = typeof configuration.accessToken === "function" ? await configuration.accessToken() : await configuration.accessToken;
6419
+ localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
6420
+ }
6421
+ const query = new URLSearchParams(localVarUrlObj.search);
6422
+ for (const key in localVarQueryParameter) {
6423
+ query.set(key, localVarQueryParameter[key]);
6424
+ }
6425
+ for (const key in options.params) {
6426
+ query.set(key, options.params[key]);
6427
+ }
6428
+ localVarUrlObj.search = new URLSearchParams(query).toString();
6429
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6430
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6431
+ return {
6432
+ url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
6433
+ options: localVarRequestOptions
6434
+ };
6435
+ },
6436
+ /**
6437
+ *
6438
+ * @summary Get user wishlist
6439
+ * @param {*} [options] Override http request option.
6440
+ * @throws {RequiredError}
6441
+ */
6442
+ getWishlist: async (options = {}) => {
6443
+ const localVarPath = `/wishlist`;
6444
+ const localVarUrlObj = new URL(localVarPath, "https://example.com");
6445
+ let baseOptions;
6446
+ if (configuration) {
6447
+ baseOptions = configuration.baseOptions;
6448
+ }
6449
+ const localVarRequestOptions = { method: "GET", ...baseOptions, ...options };
6450
+ const localVarHeaderParameter = {};
6451
+ const localVarQueryParameter = {};
6452
+ if (configuration && configuration.accessToken) {
6453
+ const accessToken = typeof configuration.accessToken === "function" ? await configuration.accessToken() : await configuration.accessToken;
6454
+ localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
6455
+ }
6456
+ const query = new URLSearchParams(localVarUrlObj.search);
6457
+ for (const key in localVarQueryParameter) {
6458
+ query.set(key, localVarQueryParameter[key]);
6459
+ }
6460
+ for (const key in options.params) {
6461
+ query.set(key, options.params[key]);
6462
+ }
6463
+ localVarUrlObj.search = new URLSearchParams(query).toString();
6464
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6465
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6466
+ return {
6467
+ url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
6468
+ options: localVarRequestOptions
6469
+ };
6470
+ },
6471
+ /**
6472
+ *
6473
+ * @summary Get wishlist item count
6474
+ * @param {*} [options] Override http request option.
6475
+ * @throws {RequiredError}
6476
+ */
6477
+ getWishlistItemCount: async (options = {}) => {
6478
+ const localVarPath = `/wishlist/count`;
6479
+ const localVarUrlObj = new URL(localVarPath, "https://example.com");
6480
+ let baseOptions;
6481
+ if (configuration) {
6482
+ baseOptions = configuration.baseOptions;
6483
+ }
6484
+ const localVarRequestOptions = { method: "GET", ...baseOptions, ...options };
6485
+ const localVarHeaderParameter = {};
6486
+ const localVarQueryParameter = {};
6487
+ if (configuration && configuration.accessToken) {
6488
+ const accessToken = typeof configuration.accessToken === "function" ? await configuration.accessToken() : await configuration.accessToken;
6489
+ localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
6490
+ }
6491
+ const query = new URLSearchParams(localVarUrlObj.search);
6492
+ for (const key in localVarQueryParameter) {
6493
+ query.set(key, localVarQueryParameter[key]);
6494
+ }
6495
+ for (const key in options.params) {
6496
+ query.set(key, options.params[key]);
6497
+ }
6498
+ localVarUrlObj.search = new URLSearchParams(query).toString();
6499
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6500
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6501
+ return {
6502
+ url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
6503
+ options: localVarRequestOptions
6504
+ };
6505
+ },
6506
+ /**
6507
+ *
6508
+ * @summary Remove product from wishlist
6509
+ * @param {string} productId
6510
+ * @param {*} [options] Override http request option.
6511
+ * @throws {RequiredError}
6512
+ */
6513
+ removeFromWishlist: async (productId, options = {}) => {
6514
+ if (productId === null || productId === void 0) {
6515
+ throw new RequiredError("productId", "Required parameter productId was null or undefined when calling removeFromWishlist.");
6516
+ }
6517
+ const localVarPath = `/wishlist/remove/{productId}`.replace(`{${"productId"}}`, encodeURIComponent(String(productId)));
6518
+ const localVarUrlObj = new URL(localVarPath, "https://example.com");
6519
+ let baseOptions;
6520
+ if (configuration) {
6521
+ baseOptions = configuration.baseOptions;
6522
+ }
6523
+ const localVarRequestOptions = { method: "DELETE", ...baseOptions, ...options };
6524
+ const localVarHeaderParameter = {};
6525
+ const localVarQueryParameter = {};
6526
+ if (configuration && configuration.accessToken) {
6527
+ const accessToken = typeof configuration.accessToken === "function" ? await configuration.accessToken() : await configuration.accessToken;
6528
+ localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
6529
+ }
6530
+ const query = new URLSearchParams(localVarUrlObj.search);
6531
+ for (const key in localVarQueryParameter) {
6532
+ query.set(key, localVarQueryParameter[key]);
6533
+ }
6534
+ for (const key in options.params) {
6535
+ query.set(key, options.params[key]);
6536
+ }
6537
+ localVarUrlObj.search = new URLSearchParams(query).toString();
6538
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6539
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6540
+ return {
6541
+ url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
6542
+ options: localVarRequestOptions
6543
+ };
6544
+ }
6545
+ };
6546
+ };
6547
+ var WishlistApiFp = function(configuration) {
6548
+ return {
6549
+ /**
6550
+ *
6551
+ * @summary Add product to wishlist
6552
+ * @param {string} productId
6553
+ * @param {*} [options] Override http request option.
6554
+ * @throws {RequiredError}
6555
+ */
6556
+ async addToWishlist(productId, options) {
6557
+ const localVarAxiosArgs = await WishlistApiAxiosParamCreator(configuration).addToWishlist(productId, options);
6558
+ return (axios = globalAxios4__default.default, basePath = BASE_PATH) => {
6559
+ const axiosRequestArgs = { ...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url };
6560
+ return axios.request(axiosRequestArgs);
6561
+ };
6562
+ },
6563
+ /**
6564
+ *
6565
+ * @summary Clear wishlist
6566
+ * @param {*} [options] Override http request option.
6567
+ * @throws {RequiredError}
6568
+ */
6569
+ async clearWishlist(options) {
6570
+ const localVarAxiosArgs = await WishlistApiAxiosParamCreator(configuration).clearWishlist(options);
6571
+ return (axios = globalAxios4__default.default, basePath = BASE_PATH) => {
6572
+ const axiosRequestArgs = { ...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url };
6573
+ return axios.request(axiosRequestArgs);
6574
+ };
6575
+ },
6576
+ /**
6577
+ *
6578
+ * @summary Get user wishlist
6579
+ * @param {*} [options] Override http request option.
6580
+ * @throws {RequiredError}
6581
+ */
6582
+ async getWishlist(options) {
6583
+ const localVarAxiosArgs = await WishlistApiAxiosParamCreator(configuration).getWishlist(options);
6584
+ return (axios = globalAxios4__default.default, basePath = BASE_PATH) => {
6585
+ const axiosRequestArgs = { ...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url };
6586
+ return axios.request(axiosRequestArgs);
6587
+ };
6588
+ },
6589
+ /**
6590
+ *
6591
+ * @summary Get wishlist item count
6592
+ * @param {*} [options] Override http request option.
6593
+ * @throws {RequiredError}
6594
+ */
6595
+ async getWishlistItemCount(options) {
6596
+ const localVarAxiosArgs = await WishlistApiAxiosParamCreator(configuration).getWishlistItemCount(options);
6597
+ return (axios = globalAxios4__default.default, basePath = BASE_PATH) => {
6598
+ const axiosRequestArgs = { ...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url };
6599
+ return axios.request(axiosRequestArgs);
6600
+ };
6601
+ },
6602
+ /**
6603
+ *
6604
+ * @summary Remove product from wishlist
6605
+ * @param {string} productId
6606
+ * @param {*} [options] Override http request option.
6607
+ * @throws {RequiredError}
6608
+ */
6609
+ async removeFromWishlist(productId, options) {
6610
+ const localVarAxiosArgs = await WishlistApiAxiosParamCreator(configuration).removeFromWishlist(productId, options);
6611
+ return (axios = globalAxios4__default.default, basePath = BASE_PATH) => {
6612
+ const axiosRequestArgs = { ...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url };
6613
+ return axios.request(axiosRequestArgs);
6614
+ };
6615
+ }
6616
+ };
6617
+ };
6618
+ var WishlistApi = class extends BaseAPI {
6619
+ /**
6620
+ *
6621
+ * @summary Add product to wishlist
6622
+ * @param {string} productId
6623
+ * @param {*} [options] Override http request option.
6624
+ * @throws {RequiredError}
6625
+ * @memberof WishlistApi
6626
+ */
6627
+ async addToWishlist(productId, options) {
6628
+ return WishlistApiFp(this.configuration).addToWishlist(productId, options).then((request) => request(this.axios, this.basePath));
6629
+ }
6630
+ /**
6631
+ *
6632
+ * @summary Clear wishlist
6633
+ * @param {*} [options] Override http request option.
6634
+ * @throws {RequiredError}
6635
+ * @memberof WishlistApi
6636
+ */
6637
+ async clearWishlist(options) {
6638
+ return WishlistApiFp(this.configuration).clearWishlist(options).then((request) => request(this.axios, this.basePath));
6639
+ }
6640
+ /**
6641
+ *
6642
+ * @summary Get user wishlist
6643
+ * @param {*} [options] Override http request option.
6644
+ * @throws {RequiredError}
6645
+ * @memberof WishlistApi
6646
+ */
6647
+ async getWishlist(options) {
6648
+ return WishlistApiFp(this.configuration).getWishlist(options).then((request) => request(this.axios, this.basePath));
6649
+ }
6650
+ /**
6651
+ *
6652
+ * @summary Get wishlist item count
6653
+ * @param {*} [options] Override http request option.
6654
+ * @throws {RequiredError}
6655
+ * @memberof WishlistApi
6656
+ */
6657
+ async getWishlistItemCount(options) {
6658
+ return WishlistApiFp(this.configuration).getWishlistItemCount(options).then((request) => request(this.axios, this.basePath));
6659
+ }
6660
+ /**
6661
+ *
6662
+ * @summary Remove product from wishlist
6663
+ * @param {string} productId
6664
+ * @param {*} [options] Override http request option.
6665
+ * @throws {RequiredError}
6666
+ * @memberof WishlistApi
6667
+ */
6668
+ async removeFromWishlist(productId, options) {
6669
+ return WishlistApiFp(this.configuration).removeFromWishlist(productId, options).then((request) => request(this.axios, this.basePath));
6670
+ }
6671
+ };
6360
6672
 
6361
6673
  // src/lib/Apis/models/manual-order-dto.ts
6362
6674
  var ManualOrderDTOOrderStatusEnum = /* @__PURE__ */ ((ManualOrderDTOOrderStatusEnum2) => {
@@ -6482,6 +6794,162 @@ function CartProvider({ children }) {
6482
6794
  };
6483
6795
  return /* @__PURE__ */ React19__default.default.createElement(CartContext.Provider, { value }, children);
6484
6796
  }
6797
+ var BaseUrl = "https://api.heypharmacist.com";
6798
+ globalAxios4__default.default.interceptors.request.use(async (config) => {
6799
+ if (!config?.headers) {
6800
+ throw new Error(
6801
+ `Expected 'config' and 'config.headers' not to be undefined`
6802
+ );
6803
+ }
6804
+ if (typeof window !== "undefined") {
6805
+ try {
6806
+ const ecommerceConfig = getCurrentConfig();
6807
+ const token = getAuthToken();
6808
+ if (token) {
6809
+ config.headers.Authorization = `Bearer ${token}`;
6810
+ }
6811
+ if (ecommerceConfig?.storeId) {
6812
+ config.headers["X-Store-Key"] = ecommerceConfig.storeId;
6813
+ }
6814
+ } catch (error) {
6815
+ console.warn("API configuration not initialized yet:", error);
6816
+ }
6817
+ }
6818
+ return config;
6819
+ });
6820
+ var ABORT_CONTROLLER = new AbortController();
6821
+ var AXIOS_CONFIG = new Configuration({
6822
+ basePath: BaseUrl,
6823
+ baseOptions: {
6824
+ signal: ABORT_CONTROLLER.signal,
6825
+ timeout: 2e4
6826
+ }
6827
+ });
6828
+ var WishlistContext = React19.createContext(void 0);
6829
+ function WishlistProvider({ children }) {
6830
+ const [state, setState] = React19.useState({
6831
+ _id: "",
6832
+ createdAt: /* @__PURE__ */ new Date(),
6833
+ updatedAt: /* @__PURE__ */ new Date(),
6834
+ userId: "",
6835
+ products: []
6836
+ });
6837
+ const { isAuthenticated } = useAuth() || {};
6838
+ const wishlistApi = React19.useMemo(() => new WishlistApi(AXIOS_CONFIG), []);
6839
+ const fetchWishlist = React19.useCallback(async () => {
6840
+ if (!isAuthenticated) {
6841
+ setState((prev) => ({
6842
+ ...prev,
6843
+ isLoading: false,
6844
+ products: []
6845
+ }));
6846
+ return;
6847
+ }
6848
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
6849
+ try {
6850
+ const response = await wishlistApi.getWishlist();
6851
+ const responseData = response?.data;
6852
+ setState({
6853
+ _id: responseData._id,
6854
+ createdAt: responseData.createdAt,
6855
+ updatedAt: responseData.updatedAt,
6856
+ userId: responseData.userId,
6857
+ products: responseData.products
6858
+ });
6859
+ } catch (error) {
6860
+ console.error("Error fetching wishlist:", error);
6861
+ setState((prev) => ({
6862
+ ...prev,
6863
+ isLoading: false,
6864
+ error: error instanceof Error ? error.message : "Failed to load wishlist"
6865
+ }));
6866
+ }
6867
+ }, [isAuthenticated]);
6868
+ React19.useEffect(() => {
6869
+ fetchWishlist();
6870
+ }, [fetchWishlist]);
6871
+ const addToWishlist = async (product) => {
6872
+ if (!isAuthenticated) {
6873
+ sonner.toast.error("Please sign in to add items to your wishlist");
6874
+ return;
6875
+ }
6876
+ try {
6877
+ if (isInWishlist(product?._id || "")) {
6878
+ sonner.toast.info("This item is already in your wishlist");
6879
+ return;
6880
+ }
6881
+ await wishlistApi.addToWishlist(product?._id || "");
6882
+ await fetchWishlist();
6883
+ sonner.toast.success("Added to wishlist");
6884
+ } catch (error) {
6885
+ console.error("Error adding to wishlist:", error);
6886
+ sonner.toast.error("Failed to add to wishlist");
6887
+ throw error;
6888
+ }
6889
+ };
6890
+ const removeFromWishlist = async (productId) => {
6891
+ try {
6892
+ await wishlistApi.removeFromWishlist(productId);
6893
+ setState((prev) => {
6894
+ const newProducts = prev.products.filter((product) => product?._id !== productId);
6895
+ return {
6896
+ ...prev,
6897
+ products: newProducts
6898
+ };
6899
+ });
6900
+ sonner.toast.success("Removed from wishlist");
6901
+ } catch (error) {
6902
+ console.error("Error removing from wishlist:", error);
6903
+ sonner.toast.error("Failed to remove from wishlist");
6904
+ throw error;
6905
+ }
6906
+ };
6907
+ const clearWishlist = async () => {
6908
+ try {
6909
+ await wishlistApi.clearWishlist();
6910
+ setState((prev) => ({
6911
+ ...prev,
6912
+ products: []
6913
+ }));
6914
+ sonner.toast.success("Wishlist cleared");
6915
+ } catch (error) {
6916
+ console.error("Error clearing wishlist:", error);
6917
+ sonner.toast.error("Failed to clear wishlist");
6918
+ throw error;
6919
+ }
6920
+ };
6921
+ const isInWishlist = (productId) => {
6922
+ return state.products.some((product) => product?._id === productId);
6923
+ };
6924
+ const getWishlistCount = () => {
6925
+ return state.products.length;
6926
+ };
6927
+ const refreshWishlist = async () => {
6928
+ await fetchWishlist();
6929
+ };
6930
+ return /* @__PURE__ */ React19__default.default.createElement(
6931
+ WishlistContext.Provider,
6932
+ {
6933
+ value: {
6934
+ ...state,
6935
+ addToWishlist,
6936
+ removeFromWishlist,
6937
+ isInWishlist,
6938
+ getWishlistCount,
6939
+ refreshWishlist,
6940
+ clearWishlist
6941
+ }
6942
+ },
6943
+ children
6944
+ );
6945
+ }
6946
+ var useWishlist = () => {
6947
+ const context = React19.useContext(WishlistContext);
6948
+ if (context === void 0) {
6949
+ throw new Error("useWishlist must be used within a WishlistProvider");
6950
+ }
6951
+ return context;
6952
+ };
6485
6953
  function EcommerceProvider({ config, children }) {
6486
6954
  React19.useEffect(() => {
6487
6955
  initializeApiAdapter(config);
@@ -6489,7 +6957,7 @@ function EcommerceProvider({ config, children }) {
6489
6957
  const [client] = React19__default.default.useState(
6490
6958
  new reactQuery.QueryClient({ defaultOptions: { queries: { staleTime: 5e3 } } })
6491
6959
  );
6492
- return /* @__PURE__ */ React19__default.default.createElement(reactQuery.QueryClientProvider, { client }, /* @__PURE__ */ React19__default.default.createElement(ThemeProvider, { config }, /* @__PURE__ */ React19__default.default.createElement(AuthProvider, null, /* @__PURE__ */ React19__default.default.createElement(CartProvider, null, children, /* @__PURE__ */ React19__default.default.createElement(sonner.Toaster, { position: "top-right", richColors: true })))));
6960
+ return /* @__PURE__ */ React19__default.default.createElement(reactQuery.QueryClientProvider, { client }, /* @__PURE__ */ React19__default.default.createElement(ThemeProvider, { config }, /* @__PURE__ */ React19__default.default.createElement(AuthProvider, null, /* @__PURE__ */ React19__default.default.createElement(CartProvider, null, /* @__PURE__ */ React19__default.default.createElement(WishlistProvider, null, children, /* @__PURE__ */ React19__default.default.createElement(sonner.Toaster, { position: "top-right", richColors: true }))))));
6493
6961
  }
6494
6962
 
6495
6963
  // src/lib/utils/format.ts
@@ -6523,45 +6991,6 @@ function truncate(text, maxLength) {
6523
6991
  function getInitials(firstName, lastName) {
6524
6992
  return `${firstName?.charAt(0)}${lastName?.charAt(0)}`.toUpperCase();
6525
6993
  }
6526
- var BaseUrl = "https://api.heypharmacist.com";
6527
- globalAxios4__default.default.interceptors.request.use(async (config) => {
6528
- if (!config?.headers) {
6529
- throw new Error(
6530
- `Expected 'config' and 'config.headers' not to be undefined`
6531
- );
6532
- }
6533
- if (typeof window !== "undefined") {
6534
- try {
6535
- const ecommerceConfig = getCurrentConfig();
6536
- const token = getAuthToken();
6537
- if (token) {
6538
- config.headers.Authorization = `Bearer ${token}`;
6539
- }
6540
- if (ecommerceConfig?.storeId) {
6541
- config.headers["X-Store-Key"] = ecommerceConfig.storeId;
6542
- }
6543
- } catch (error) {
6544
- console.warn("API configuration not initialized yet:", error);
6545
- }
6546
- }
6547
- return config;
6548
- });
6549
- var ABORT_CONTROLLER = new AbortController();
6550
- var AXIOS_CONFIG = new Configuration({
6551
- basePath: BaseUrl,
6552
- baseOptions: {
6553
- signal: ABORT_CONTROLLER.signal,
6554
- timeout: 2e4
6555
- }
6556
- });
6557
- var WishlistContext = React19.createContext(void 0);
6558
- var useWishlist = () => {
6559
- const context = React19.useContext(WishlistContext);
6560
- if (context === void 0) {
6561
- throw new Error("useWishlist must be used within a WishlistProvider");
6562
- }
6563
- return context;
6564
- };
6565
6994
  function ProductCard({
6566
6995
  product,
6567
6996
  onClickProduct,