@eetech-commerce/cart-react 0.4.1

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 ADDED
@@ -0,0 +1,356 @@
1
+ # @eetech-commerce/cart-react
2
+
3
+ React hooks and provider for interacting with the EETech Commerce Cart API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @eetech-commerce/cart-react
9
+ # or
10
+ yarn add @eetech-commerce/cart-react
11
+ # or
12
+ pnpm add @eetech-commerce/cart-react
13
+ # or
14
+ bun add @eetech-commerce/cart-react
15
+ ```
16
+
17
+ For payment features (optional):
18
+
19
+ ```bash
20
+ npm install @stripe/stripe-js
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```tsx
26
+ import {
27
+ CartProvider,
28
+ useCart,
29
+ useAddToCart,
30
+ } from '@eetech-commerce/cart-react';
31
+
32
+ function App() {
33
+ return (
34
+ <CartProvider
35
+ tenantSlug="my-store"
36
+ cartApiUrl="https://cart.api.com"
37
+ >
38
+ <Shop />
39
+ </CartProvider>
40
+ );
41
+ }
42
+
43
+ function Shop() {
44
+ const { data: cart, isLoading } = useCart();
45
+ const { addToCart, isPending } = useAddToCart();
46
+
47
+ if (isLoading) return <div>Loading cart...</div>;
48
+
49
+ return (
50
+ <div>
51
+ <h2>Cart ({cart?.items.length ?? 0} items)</h2>
52
+ <button
53
+ onClick={() => addToCart({ offerId: 'offer-123', quantity: 1 })}
54
+ disabled={isPending}
55
+ >
56
+ Add Item
57
+ </button>
58
+ </div>
59
+ );
60
+ }
61
+ ```
62
+
63
+ ## CartProvider Configuration
64
+
65
+ | Prop | Type | Required | Default | Description |
66
+ |------|------|----------|---------|-------------|
67
+ | `tenantSlug` | `string` | Yes | - | Your tenant identifier |
68
+ | `cartApiUrl` | `string` | Yes | - | Base URL of the cart API |
69
+ | `storageAdapter` | `StorageAdapter` | No | `localStorage` | Custom storage implementation |
70
+ | `autoInitialize` | `boolean` | No | `true` | Auto-create cart on mount |
71
+ | `queryClient` | `QueryClient` | No | - | Custom TanStack Query client instance |
72
+
73
+ ## Hooks Reference
74
+
75
+ ### Cart Hooks
76
+
77
+ | Hook | Description |
78
+ |------|-------------|
79
+ | `useCart()` | Fetch the current cart |
80
+ | `useCreateCart()` | Create a new cart |
81
+ | `useAddToCart()` | Add an item to the cart |
82
+ | `useUpdateItemQty()` | Update item quantity |
83
+ | `useRemoveItem()` | Remove an item from cart |
84
+ | `useClearCart()` | Clear all items from cart |
85
+ | `useInitializeCart()` | Manually initialize cart (for `autoInitialize={false}`) |
86
+
87
+ ### Checkout Hooks
88
+
89
+ | Hook | Description |
90
+ |------|-------------|
91
+ | `useVerifyCart()` | Verify cart items before checkout |
92
+ | `useCreateCheckoutSession()` | Create a checkout session |
93
+ | `useShippingOptions(cartSessionId)` | Fetch available shipping options |
94
+ | `useUpdateShippingSelections()` | Update selected shipping options |
95
+
96
+ ### Payment Hooks
97
+
98
+ | Hook | Description |
99
+ |------|-------------|
100
+ | `useStripePromise()` | Get the Stripe.js instance |
101
+ | `useCreateEmbeddedCheckoutSession()` | Create an embedded payment session |
102
+ | `usePaymentSession(sessionId)` | Fetch payment session details |
103
+
104
+ ### Context Hook
105
+
106
+ | Hook | Description |
107
+ |------|-------------|
108
+ | `useCartContext()` | Access cart context (tenantSlug, cartSessionId, etc.) |
109
+
110
+ ## Mutation Callbacks
111
+
112
+ All mutation hooks support optional callbacks for success and error handling:
113
+
114
+ ```tsx
115
+ const { addToCart } = useAddToCart();
116
+
117
+ addToCart(
118
+ { offerId: 'offer-123', quantity: 1 },
119
+ {
120
+ onSuccess: (cart) => {
121
+ toast('Added to cart!');
122
+ },
123
+ onError: (error) => {
124
+ toast.error(error.message);
125
+ },
126
+ }
127
+ );
128
+ ```
129
+
130
+ ## Custom Storage Adapter
131
+
132
+ By default, the cart session ID is stored in `localStorage`. You can provide a custom storage adapter for different storage mechanisms:
133
+
134
+ ### Interface
135
+
136
+ ```typescript
137
+ interface StorageAdapter {
138
+ get(key: string): string | null;
139
+ set(key: string, value: string): void;
140
+ remove(key: string): void;
141
+ }
142
+ ```
143
+
144
+ ### Example: Cookie Adapter
145
+
146
+ ```tsx
147
+ import { CartProvider, type StorageAdapter } from '@eetech-commerce/cart-react';
148
+ import Cookies from 'js-cookie';
149
+
150
+ const cookieAdapter: StorageAdapter = {
151
+ get: (key) => Cookies.get(key) ?? null,
152
+ set: (key, value) => Cookies.set(key, value, { expires: 7 }),
153
+ remove: (key) => Cookies.remove(key),
154
+ };
155
+
156
+ function App() {
157
+ return (
158
+ <CartProvider
159
+ tenantSlug="my-store"
160
+ cartApiUrl="https://cart.api.com"
161
+ storageAdapter={cookieAdapter}
162
+ >
163
+ <Shop />
164
+ </CartProvider>
165
+ );
166
+ }
167
+ ```
168
+
169
+ ## Manual Cart Initialization
170
+
171
+ By default, `CartProvider` automatically creates a cart on mount. If you need more control over when the cart is created, set `autoInitialize={false}`:
172
+
173
+ ```tsx
174
+ import {
175
+ CartProvider,
176
+ useInitializeCart,
177
+ useCartContext,
178
+ } from '@eetech-commerce/cart-react';
179
+
180
+ function App() {
181
+ return (
182
+ <CartProvider
183
+ tenantSlug="my-store"
184
+ cartApiUrl="https://cart.api.com"
185
+ autoInitialize={false}
186
+ >
187
+ <CartInitializer />
188
+ <Shop />
189
+ </CartProvider>
190
+ );
191
+ }
192
+
193
+ function CartInitializer() {
194
+ const { isInitializing } = useInitializeCart();
195
+ const { cartSessionId } = useCartContext();
196
+
197
+ if (isInitializing) {
198
+ return <div>Initializing cart...</div>;
199
+ }
200
+
201
+ return null;
202
+ }
203
+ ```
204
+
205
+ This is useful when you want to:
206
+ - Delay cart creation until user interaction
207
+ - Initialize the cart conditionally based on route or user state
208
+ - Handle initialization loading states explicitly
209
+
210
+ ## Using with Existing QueryClient
211
+
212
+ If your application already uses TanStack Query, you can pass your existing `QueryClient` to share the cache:
213
+
214
+ ```tsx
215
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
216
+ import { CartProvider } from '@eetech-commerce/cart-react';
217
+
218
+ const queryClient = new QueryClient();
219
+
220
+ function App() {
221
+ return (
222
+ <QueryClientProvider client={queryClient}>
223
+ <CartProvider
224
+ tenantSlug="my-store"
225
+ cartApiUrl="https://cart.api.com"
226
+ queryClient={queryClient}
227
+ >
228
+ <Shop />
229
+ </CartProvider>
230
+ </QueryClientProvider>
231
+ );
232
+ }
233
+ ```
234
+
235
+ Benefits of sharing the QueryClient:
236
+ - Unified cache management across your application
237
+ - Shared devtools integration
238
+ - Consistent query/mutation defaults
239
+
240
+ ## Payment Hooks (Stripe)
241
+
242
+ To use payment features, install `@stripe/stripe-js`:
243
+
244
+ ```bash
245
+ npm install @stripe/stripe-js
246
+ ```
247
+
248
+ ### Using useStripePromise
249
+
250
+ The `useStripePromise` hook automatically fetches your tenant's Stripe publishable key and initializes Stripe.js:
251
+
252
+ ```tsx
253
+ import { useStripePromise } from '@eetech-commerce/cart-react';
254
+ import { Elements } from '@stripe/react-stripe-js';
255
+
256
+ function CheckoutPage() {
257
+ const stripePromise = useStripePromise();
258
+
259
+ if (!stripePromise) {
260
+ return <div>Loading payment provider...</div>;
261
+ }
262
+
263
+ return (
264
+ <Elements stripe={stripePromise}>
265
+ <PaymentForm />
266
+ </Elements>
267
+ );
268
+ }
269
+ ```
270
+
271
+ ### Creating an Embedded Checkout Session
272
+
273
+ ```tsx
274
+ import {
275
+ useCreateEmbeddedCheckoutSession,
276
+ useCartContext,
277
+ } from '@eetech-commerce/cart-react';
278
+
279
+ function CheckoutButton() {
280
+ const { cartSessionId } = useCartContext();
281
+ const { createEmbeddedCheckoutSession, isPending, data } =
282
+ useCreateEmbeddedCheckoutSession();
283
+
284
+ const handleCheckout = () => {
285
+ createEmbeddedCheckoutSession(
286
+ {
287
+ cartSessionId: cartSessionId!,
288
+ returnUrl: 'https://my-store.com/checkout/complete',
289
+ },
290
+ {
291
+ onSuccess: (session) => {
292
+ // Use session.clientSecret with Stripe Embedded Checkout
293
+ console.log('Session created:', session.id);
294
+ },
295
+ onError: (error) => {
296
+ console.error('Failed to create session:', error);
297
+ },
298
+ }
299
+ );
300
+ };
301
+
302
+ return (
303
+ <button onClick={handleCheckout} disabled={isPending}>
304
+ {isPending ? 'Creating session...' : 'Checkout'}
305
+ </button>
306
+ );
307
+ }
308
+ ```
309
+
310
+ ## TypeScript
311
+
312
+ This package is fully typed. All hooks, providers, and utilities include TypeScript definitions.
313
+
314
+ ### Exported Types
315
+
316
+ ```typescript
317
+ import type {
318
+ // Provider
319
+ CartProviderProps,
320
+ CartContextValue,
321
+
322
+ // Storage
323
+ StorageAdapter,
324
+
325
+ // Mutation callbacks
326
+ MutationCallbacks,
327
+
328
+ // API types
329
+ CartResponseDto,
330
+ LineItemResponseDto,
331
+ CreateCheckoutDto,
332
+ VerificationResultDto,
333
+ ShippingOptionDto,
334
+ ShippingSelectionDto,
335
+ CreateEmbeddedPaymentSessionDto,
336
+ EmbeddedPaymentSessionResponseDto,
337
+ } from '@eetech-commerce/cart-react';
338
+ ```
339
+
340
+ ## Advanced: Query Keys
341
+
342
+ For advanced cache control, query key factories are exported:
343
+
344
+ ```typescript
345
+ import { cartKeys, shippingKeys, paymentKeys } from '@eetech-commerce/cart-react';
346
+
347
+ // Invalidate all cart queries
348
+ queryClient.invalidateQueries({ queryKey: cartKeys.all() });
349
+
350
+ // Invalidate shipping options
351
+ queryClient.invalidateQueries({ queryKey: shippingKeys.all() });
352
+ ```
353
+
354
+ ## License
355
+
356
+ MIT