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 +53 -19
- package/dist/index.js +469 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +469 -40
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/providers/EcommerceProvider.tsx +5 -2
package/README.md
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
# Hey Pharmacist E
|
|
1
|
+
# Hey Pharmacist E‑commerce
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Production‑ready, multi‑tenant e‑commerce 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
|
-
##
|
|
5
|
+
## Highlights
|
|
6
6
|
|
|
7
|
-
- 🛒 **Complete
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
##
|
|
91
|
+
## Theming and customization
|
|
91
92
|
|
|
92
|
-
The package
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
|
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,
|