@cobrastyle/adapter-dummy-data 1.0.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/LICENSE +21 -0
- package/dist/adapter.d.ts +3 -0
- package/dist/adapter.js +669 -0
- package/dist/fixtures/categories.d.ts +3 -0
- package/dist/fixtures/categories.js +134 -0
- package/dist/fixtures/cms.d.ts +2 -0
- package/dist/fixtures/cms.js +79 -0
- package/dist/fixtures/index.d.ts +3 -0
- package/dist/fixtures/index.js +3 -0
- package/dist/fixtures/products.d.ts +3 -0
- package/dist/fixtures/products.js +119 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +35 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cobrastyle
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
import { products, productListItems } from './fixtures/products';
|
|
2
|
+
import { categories, navigation } from './fixtures/categories';
|
|
3
|
+
import { cmsPages } from './fixtures/cms';
|
|
4
|
+
// Simulated latency for realistic behavior
|
|
5
|
+
const LATENCY_MS = 100;
|
|
6
|
+
const delay = (ms = LATENCY_MS) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7
|
+
// In-memory cart storage
|
|
8
|
+
const carts = new Map();
|
|
9
|
+
// Mock shipping methods
|
|
10
|
+
const shippingMethods = [
|
|
11
|
+
{ carrierCode: 'flatrate', carrierTitle: 'Flat Rate', methodCode: 'flatrate', methodTitle: 'Fixed', amount: 10, currency: 'USD' },
|
|
12
|
+
{ carrierCode: 'freeshipping', carrierTitle: 'Free Shipping', methodCode: 'freeshipping', methodTitle: 'Free', amount: 0, currency: 'USD' },
|
|
13
|
+
{ carrierCode: 'tablerate', carrierTitle: 'Express', methodCode: 'express', methodTitle: '2-3 Business Days', amount: 15, currency: 'USD' },
|
|
14
|
+
];
|
|
15
|
+
// Mock payment methods
|
|
16
|
+
const paymentMethods = [
|
|
17
|
+
{ code: 'checkmo', title: 'Check / Money Order' },
|
|
18
|
+
{ code: 'stripe', title: 'Credit Card (Stripe)' },
|
|
19
|
+
{ code: 'paypal', title: 'PayPal' },
|
|
20
|
+
];
|
|
21
|
+
// Helper to generate cart ID
|
|
22
|
+
const generateCartId = () => `cart_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
23
|
+
// Helper to calculate cart totals
|
|
24
|
+
const calculateTotals = (items, shipping) => {
|
|
25
|
+
const subtotal = items.reduce((sum, item) => sum + item.prices.rowTotal, 0);
|
|
26
|
+
const shippingAmount = shipping ?? 0;
|
|
27
|
+
return {
|
|
28
|
+
subtotal,
|
|
29
|
+
subtotalIncludingTax: subtotal * 1.08, // 8% tax
|
|
30
|
+
grandTotal: subtotal * 1.08 + shippingAmount,
|
|
31
|
+
discounts: [],
|
|
32
|
+
taxes: [{ amount: subtotal * 0.08, label: 'Tax', rate: 8 }],
|
|
33
|
+
shipping: shippingAmount,
|
|
34
|
+
currency: 'USD',
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
// Create empty cart
|
|
38
|
+
const createEmptyCart = (id) => ({
|
|
39
|
+
id,
|
|
40
|
+
items: [],
|
|
41
|
+
totals: calculateTotals([]),
|
|
42
|
+
appliedCoupons: [],
|
|
43
|
+
shippingAddresses: [],
|
|
44
|
+
availableShippingMethods: shippingMethods,
|
|
45
|
+
availablePaymentMethods: paymentMethods,
|
|
46
|
+
});
|
|
47
|
+
export const dummyDataAdapter = {
|
|
48
|
+
product: {
|
|
49
|
+
get: async (id) => {
|
|
50
|
+
await delay();
|
|
51
|
+
return products.find((p) => p.id === id) ?? null;
|
|
52
|
+
},
|
|
53
|
+
getByUrlKey: async (urlKey) => {
|
|
54
|
+
await delay();
|
|
55
|
+
return products.find((p) => p.urlKey === urlKey) ?? null;
|
|
56
|
+
},
|
|
57
|
+
getRelated: async () => {
|
|
58
|
+
await delay();
|
|
59
|
+
return productListItems.slice(0, 4);
|
|
60
|
+
},
|
|
61
|
+
getUpsells: async () => {
|
|
62
|
+
await delay();
|
|
63
|
+
return productListItems.slice(4, 8);
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
category: {
|
|
67
|
+
get: async (id) => {
|
|
68
|
+
await delay();
|
|
69
|
+
const findCategory = (cats) => {
|
|
70
|
+
for (const cat of cats) {
|
|
71
|
+
if (cat.id === id)
|
|
72
|
+
return cat;
|
|
73
|
+
if (cat.children.length) {
|
|
74
|
+
const found = findCategory(cat.children);
|
|
75
|
+
if (found)
|
|
76
|
+
return found;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
};
|
|
81
|
+
return findCategory(categories);
|
|
82
|
+
},
|
|
83
|
+
getByUrlKey: async (urlKey) => {
|
|
84
|
+
await delay();
|
|
85
|
+
const findCategory = (cats) => {
|
|
86
|
+
for (const cat of cats) {
|
|
87
|
+
if (cat.urlKey === urlKey)
|
|
88
|
+
return cat;
|
|
89
|
+
if (cat.children.length) {
|
|
90
|
+
const found = findCategory(cat.children);
|
|
91
|
+
if (found)
|
|
92
|
+
return found;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
};
|
|
97
|
+
return findCategory(categories);
|
|
98
|
+
},
|
|
99
|
+
getProducts: async (input) => {
|
|
100
|
+
await delay();
|
|
101
|
+
let filteredProducts = [...productListItems];
|
|
102
|
+
// Apply filters (basic simulation)
|
|
103
|
+
if (input.filters) {
|
|
104
|
+
for (const [code, values] of Object.entries(input.filters)) {
|
|
105
|
+
const filterValues = Array.isArray(values) ? values : [values];
|
|
106
|
+
// For dummy data, we just simulate filtering by reducing the result count
|
|
107
|
+
// In a real implementation, you'd filter based on product attributes
|
|
108
|
+
if (filterValues.length > 0) {
|
|
109
|
+
// Simulate filtering by taking a subset
|
|
110
|
+
filteredProducts = filteredProducts.slice(0, Math.max(1, filteredProducts.length - filterValues.length));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Apply sorting
|
|
115
|
+
if (input.sort) {
|
|
116
|
+
filteredProducts.sort((a, b) => {
|
|
117
|
+
let comparison = 0;
|
|
118
|
+
if (input.sort.field === 'price') {
|
|
119
|
+
comparison = a.price.final - b.price.final;
|
|
120
|
+
}
|
|
121
|
+
else if (input.sort.field === 'name') {
|
|
122
|
+
comparison = a.name.localeCompare(b.name);
|
|
123
|
+
}
|
|
124
|
+
return input.sort.direction === 'DESC' ? -comparison : comparison;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const page = input.page ?? 1;
|
|
128
|
+
const pageSize = input.pageSize ?? 12;
|
|
129
|
+
const start = (page - 1) * pageSize;
|
|
130
|
+
const items = filteredProducts.slice(start, start + pageSize);
|
|
131
|
+
return {
|
|
132
|
+
items,
|
|
133
|
+
totalCount: filteredProducts.length,
|
|
134
|
+
pageInfo: {
|
|
135
|
+
currentPage: page,
|
|
136
|
+
pageSize,
|
|
137
|
+
totalPages: Math.ceil(filteredProducts.length / pageSize),
|
|
138
|
+
},
|
|
139
|
+
filters: [
|
|
140
|
+
{
|
|
141
|
+
code: 'price',
|
|
142
|
+
label: 'Price',
|
|
143
|
+
type: 'range',
|
|
144
|
+
values: [
|
|
145
|
+
{ value: '0-50', label: 'Under $50', count: 5 },
|
|
146
|
+
{ value: '50-100', label: '$50 - $100', count: 7 },
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
code: 'size',
|
|
151
|
+
label: 'Size',
|
|
152
|
+
type: 'multiselect',
|
|
153
|
+
values: [
|
|
154
|
+
{ value: 's', label: 'S', count: 10 },
|
|
155
|
+
{ value: 'm', label: 'M', count: 12 },
|
|
156
|
+
{ value: 'l', label: 'L', count: 10 },
|
|
157
|
+
{ value: 'xl', label: 'XL', count: 8 },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
sortOptions: [
|
|
162
|
+
{ value: 'position', label: 'Position' },
|
|
163
|
+
{ value: 'name', label: 'Name' },
|
|
164
|
+
{ value: 'price_asc', label: 'Price: Low to High' },
|
|
165
|
+
{ value: 'price_desc', label: 'Price: High to Low' },
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
getRootCategories: async () => {
|
|
170
|
+
await delay();
|
|
171
|
+
return categories;
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
navigation: {
|
|
175
|
+
get: async () => {
|
|
176
|
+
await delay();
|
|
177
|
+
return navigation;
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
cart: {
|
|
181
|
+
create: async () => {
|
|
182
|
+
await delay();
|
|
183
|
+
const id = generateCartId();
|
|
184
|
+
const cart = createEmptyCart(id);
|
|
185
|
+
carts.set(id, cart);
|
|
186
|
+
return cart;
|
|
187
|
+
},
|
|
188
|
+
get: async (cartId) => {
|
|
189
|
+
await delay();
|
|
190
|
+
return carts.get(cartId) ?? null;
|
|
191
|
+
},
|
|
192
|
+
addItem: async (cartId, input) => {
|
|
193
|
+
await delay();
|
|
194
|
+
let cart = carts.get(cartId);
|
|
195
|
+
if (!cart) {
|
|
196
|
+
cart = createEmptyCart(cartId);
|
|
197
|
+
}
|
|
198
|
+
const product = products.find((p) => p.sku === input.sku);
|
|
199
|
+
if (!product)
|
|
200
|
+
throw new Error(`Product not found: ${input.sku}`);
|
|
201
|
+
const itemUid = `item_${Date.now()}`;
|
|
202
|
+
const newItem = {
|
|
203
|
+
id: itemUid,
|
|
204
|
+
uid: itemUid,
|
|
205
|
+
product: {
|
|
206
|
+
id: product.id,
|
|
207
|
+
sku: product.sku,
|
|
208
|
+
name: product.name,
|
|
209
|
+
urlKey: product.urlKey,
|
|
210
|
+
thumbnail: { url: product.images[0].url, label: product.images[0].label },
|
|
211
|
+
},
|
|
212
|
+
quantity: input.quantity,
|
|
213
|
+
prices: {
|
|
214
|
+
price: product.price.final,
|
|
215
|
+
rowTotal: product.price.final * input.quantity,
|
|
216
|
+
rowTotalIncludingTax: product.price.final * input.quantity * 1.08,
|
|
217
|
+
currency: 'USD',
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
cart = {
|
|
221
|
+
...cart,
|
|
222
|
+
items: [...cart.items, newItem],
|
|
223
|
+
};
|
|
224
|
+
cart.totals = calculateTotals(cart.items, cart.totals.shipping);
|
|
225
|
+
carts.set(cartId, cart);
|
|
226
|
+
return cart;
|
|
227
|
+
},
|
|
228
|
+
updateItem: async (cartId, input) => {
|
|
229
|
+
await delay();
|
|
230
|
+
const cart = carts.get(cartId);
|
|
231
|
+
if (!cart)
|
|
232
|
+
throw new Error('Cart not found');
|
|
233
|
+
const updatedItems = cart.items.map((item) => {
|
|
234
|
+
if (item.uid === input.itemUid) {
|
|
235
|
+
return {
|
|
236
|
+
...item,
|
|
237
|
+
quantity: input.quantity,
|
|
238
|
+
prices: {
|
|
239
|
+
...item.prices,
|
|
240
|
+
rowTotal: item.prices.price * input.quantity,
|
|
241
|
+
rowTotalIncludingTax: item.prices.price * input.quantity * 1.08,
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return item;
|
|
246
|
+
});
|
|
247
|
+
const updatedCart = {
|
|
248
|
+
...cart,
|
|
249
|
+
items: updatedItems,
|
|
250
|
+
totals: calculateTotals(updatedItems, cart.totals.shipping),
|
|
251
|
+
};
|
|
252
|
+
carts.set(cartId, updatedCart);
|
|
253
|
+
return updatedCart;
|
|
254
|
+
},
|
|
255
|
+
removeItem: async (cartId, itemUid) => {
|
|
256
|
+
await delay();
|
|
257
|
+
const cart = carts.get(cartId);
|
|
258
|
+
if (!cart)
|
|
259
|
+
throw new Error('Cart not found');
|
|
260
|
+
const filteredItems = cart.items.filter((item) => item.uid !== itemUid);
|
|
261
|
+
const updatedCart = {
|
|
262
|
+
...cart,
|
|
263
|
+
items: filteredItems,
|
|
264
|
+
totals: calculateTotals(filteredItems, cart.totals.shipping),
|
|
265
|
+
};
|
|
266
|
+
carts.set(cartId, updatedCart);
|
|
267
|
+
return updatedCart;
|
|
268
|
+
},
|
|
269
|
+
applyCoupon: async (cartId, input) => {
|
|
270
|
+
await delay();
|
|
271
|
+
const cart = carts.get(cartId);
|
|
272
|
+
if (!cart)
|
|
273
|
+
throw new Error('Cart not found');
|
|
274
|
+
if (input.couponCode.toUpperCase() === 'SAVE10') {
|
|
275
|
+
const updatedCart = {
|
|
276
|
+
...cart,
|
|
277
|
+
appliedCoupons: [{ code: input.couponCode }],
|
|
278
|
+
totals: {
|
|
279
|
+
...cart.totals,
|
|
280
|
+
discounts: [{ amount: cart.totals.subtotal * 0.1, label: '10% OFF' }],
|
|
281
|
+
grandTotal: cart.totals.grandTotal * 0.9,
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
carts.set(cartId, updatedCart);
|
|
285
|
+
return updatedCart;
|
|
286
|
+
}
|
|
287
|
+
throw new Error('Invalid coupon code');
|
|
288
|
+
},
|
|
289
|
+
removeCoupon: async (cartId) => {
|
|
290
|
+
await delay();
|
|
291
|
+
const cart = carts.get(cartId);
|
|
292
|
+
if (!cart)
|
|
293
|
+
throw new Error('Cart not found');
|
|
294
|
+
const updatedCart = {
|
|
295
|
+
...cart,
|
|
296
|
+
appliedCoupons: [],
|
|
297
|
+
totals: calculateTotals(cart.items, cart.totals.shipping),
|
|
298
|
+
};
|
|
299
|
+
carts.set(cartId, updatedCart);
|
|
300
|
+
return updatedCart;
|
|
301
|
+
},
|
|
302
|
+
setEmail: async (cartId, email) => {
|
|
303
|
+
await delay();
|
|
304
|
+
let cart = carts.get(cartId);
|
|
305
|
+
if (!cart) {
|
|
306
|
+
// Create cart if it doesn't exist (handles server restart case)
|
|
307
|
+
cart = createEmptyCart(cartId);
|
|
308
|
+
}
|
|
309
|
+
const updatedCart = { ...cart, email };
|
|
310
|
+
carts.set(cartId, updatedCart);
|
|
311
|
+
return updatedCart;
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
checkout: {
|
|
315
|
+
setShippingAddress: async (cartId, input) => {
|
|
316
|
+
await delay();
|
|
317
|
+
let cart = carts.get(cartId);
|
|
318
|
+
if (!cart) {
|
|
319
|
+
cart = createEmptyCart(cartId);
|
|
320
|
+
}
|
|
321
|
+
const updatedCart = {
|
|
322
|
+
...cart,
|
|
323
|
+
shippingAddresses: [{
|
|
324
|
+
...input.address,
|
|
325
|
+
country: 'United States',
|
|
326
|
+
}],
|
|
327
|
+
};
|
|
328
|
+
carts.set(cartId, updatedCart);
|
|
329
|
+
return updatedCart;
|
|
330
|
+
},
|
|
331
|
+
setBillingAddress: async (cartId, input) => {
|
|
332
|
+
await delay();
|
|
333
|
+
let cart = carts.get(cartId);
|
|
334
|
+
if (!cart) {
|
|
335
|
+
cart = createEmptyCart(cartId);
|
|
336
|
+
}
|
|
337
|
+
if (input.sameAsShipping && cart.shippingAddresses[0]) {
|
|
338
|
+
const updatedCart = {
|
|
339
|
+
...cart,
|
|
340
|
+
billingAddress: cart.shippingAddresses[0],
|
|
341
|
+
};
|
|
342
|
+
carts.set(cartId, updatedCart);
|
|
343
|
+
return updatedCart;
|
|
344
|
+
}
|
|
345
|
+
const updatedCart = {
|
|
346
|
+
...cart,
|
|
347
|
+
billingAddress: {
|
|
348
|
+
...input.address,
|
|
349
|
+
country: 'United States',
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
carts.set(cartId, updatedCart);
|
|
353
|
+
return updatedCart;
|
|
354
|
+
},
|
|
355
|
+
setShippingMethod: async (cartId, input) => {
|
|
356
|
+
await delay();
|
|
357
|
+
let cart = carts.get(cartId);
|
|
358
|
+
if (!cart) {
|
|
359
|
+
cart = createEmptyCart(cartId);
|
|
360
|
+
}
|
|
361
|
+
const method = shippingMethods.find((m) => m.carrierCode === input.carrierCode && m.methodCode === input.methodCode);
|
|
362
|
+
if (!method)
|
|
363
|
+
throw new Error('Shipping method not found');
|
|
364
|
+
const updatedCart = {
|
|
365
|
+
...cart,
|
|
366
|
+
selectedShippingMethod: method,
|
|
367
|
+
totals: calculateTotals(cart.items, method.amount),
|
|
368
|
+
};
|
|
369
|
+
carts.set(cartId, updatedCart);
|
|
370
|
+
return updatedCart;
|
|
371
|
+
},
|
|
372
|
+
setPaymentMethod: async (cartId, input) => {
|
|
373
|
+
await delay();
|
|
374
|
+
let cart = carts.get(cartId);
|
|
375
|
+
if (!cart) {
|
|
376
|
+
cart = createEmptyCart(cartId);
|
|
377
|
+
}
|
|
378
|
+
const method = paymentMethods.find((m) => m.code === input.code);
|
|
379
|
+
if (!method)
|
|
380
|
+
throw new Error('Payment method not found');
|
|
381
|
+
const updatedCart = {
|
|
382
|
+
...cart,
|
|
383
|
+
selectedPaymentMethod: method,
|
|
384
|
+
};
|
|
385
|
+
carts.set(cartId, updatedCart);
|
|
386
|
+
return updatedCart;
|
|
387
|
+
},
|
|
388
|
+
placeOrder: async (cartId) => {
|
|
389
|
+
await delay(500); // Simulate longer processing
|
|
390
|
+
const cart = carts.get(cartId);
|
|
391
|
+
if (!cart || cart.items.length === 0) {
|
|
392
|
+
throw new Error('Cart is empty. Items may have been lost due to server restart.');
|
|
393
|
+
}
|
|
394
|
+
const orderNumber = `ORD-${Date.now()}`;
|
|
395
|
+
carts.delete(cartId); // Clear the cart
|
|
396
|
+
return {
|
|
397
|
+
success: true,
|
|
398
|
+
orderId: `order_${Date.now()}`,
|
|
399
|
+
orderNumber,
|
|
400
|
+
};
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
cms: {
|
|
404
|
+
getPage: async (identifier) => {
|
|
405
|
+
await delay();
|
|
406
|
+
return cmsPages.find((p) => p.identifier === identifier) ?? null;
|
|
407
|
+
},
|
|
408
|
+
getPageByUrlKey: async (urlKey) => {
|
|
409
|
+
await delay();
|
|
410
|
+
return cmsPages.find((p) => p.urlKey === urlKey) ?? null;
|
|
411
|
+
},
|
|
412
|
+
resolveUrl: async (urlKey) => {
|
|
413
|
+
await delay();
|
|
414
|
+
// Check products
|
|
415
|
+
const product = products.find((p) => p.urlKey === urlKey);
|
|
416
|
+
if (product) {
|
|
417
|
+
return { type: 'PRODUCT', id: product.id, urlKey };
|
|
418
|
+
}
|
|
419
|
+
// Check categories (including nested)
|
|
420
|
+
const findCategory = (cats) => {
|
|
421
|
+
for (const cat of cats) {
|
|
422
|
+
if (cat.urlKey === urlKey)
|
|
423
|
+
return cat;
|
|
424
|
+
if (cat.children.length) {
|
|
425
|
+
const found = findCategory(cat.children);
|
|
426
|
+
if (found)
|
|
427
|
+
return found;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return null;
|
|
431
|
+
};
|
|
432
|
+
const category = findCategory(categories);
|
|
433
|
+
if (category) {
|
|
434
|
+
return { type: 'CATEGORY', id: category.id, urlKey };
|
|
435
|
+
}
|
|
436
|
+
// Check CMS pages
|
|
437
|
+
const cmsPage = cmsPages.find((p) => p.urlKey === urlKey);
|
|
438
|
+
if (cmsPage) {
|
|
439
|
+
return { type: 'CMS_PAGE', id: cmsPage.id, urlKey };
|
|
440
|
+
}
|
|
441
|
+
return { type: 'NOT_FOUND', id: '', urlKey };
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
search: {
|
|
445
|
+
search: async (query, options) => {
|
|
446
|
+
await delay();
|
|
447
|
+
const lowerQuery = query.toLowerCase();
|
|
448
|
+
const filtered = productListItems.filter((p) => p.name.toLowerCase().includes(lowerQuery) ||
|
|
449
|
+
p.sku.toLowerCase().includes(lowerQuery));
|
|
450
|
+
const page = options?.page ?? 1;
|
|
451
|
+
const pageSize = options?.pageSize ?? 12;
|
|
452
|
+
const start = (page - 1) * pageSize;
|
|
453
|
+
return {
|
|
454
|
+
items: filtered.slice(start, start + pageSize),
|
|
455
|
+
totalCount: filtered.length,
|
|
456
|
+
pageInfo: {
|
|
457
|
+
currentPage: page,
|
|
458
|
+
pageSize,
|
|
459
|
+
totalPages: Math.ceil(filtered.length / pageSize),
|
|
460
|
+
},
|
|
461
|
+
suggestions: [],
|
|
462
|
+
};
|
|
463
|
+
},
|
|
464
|
+
getSuggestions: async (query) => {
|
|
465
|
+
await delay(50);
|
|
466
|
+
const lowerQuery = query.toLowerCase();
|
|
467
|
+
return productListItems
|
|
468
|
+
.filter((p) => p.name.toLowerCase().includes(lowerQuery))
|
|
469
|
+
.slice(0, 5)
|
|
470
|
+
.map((p) => p.name);
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
customer: {
|
|
474
|
+
login: async (credentials) => {
|
|
475
|
+
await delay();
|
|
476
|
+
// Mock login - accept any email/password combination
|
|
477
|
+
if (credentials.email && credentials.password) {
|
|
478
|
+
const customer = {
|
|
479
|
+
id: 'cust_1',
|
|
480
|
+
email: credentials.email,
|
|
481
|
+
firstname: 'John',
|
|
482
|
+
lastname: 'Doe',
|
|
483
|
+
createdAt: new Date().toISOString(),
|
|
484
|
+
addresses: [],
|
|
485
|
+
};
|
|
486
|
+
return {
|
|
487
|
+
customer,
|
|
488
|
+
token: `token_${Date.now()}`,
|
|
489
|
+
expiresAt: new Date(Date.now() + 86400000).toISOString(), // 24 hours
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
throw new Error('Invalid credentials');
|
|
493
|
+
},
|
|
494
|
+
register: async (input) => {
|
|
495
|
+
await delay();
|
|
496
|
+
const customer = {
|
|
497
|
+
id: `cust_${Date.now()}`,
|
|
498
|
+
email: input.email,
|
|
499
|
+
firstname: input.firstname,
|
|
500
|
+
lastname: input.lastname,
|
|
501
|
+
dateOfBirth: input.dateOfBirth,
|
|
502
|
+
gender: input.gender,
|
|
503
|
+
createdAt: new Date().toISOString(),
|
|
504
|
+
addresses: [],
|
|
505
|
+
};
|
|
506
|
+
return {
|
|
507
|
+
customer,
|
|
508
|
+
token: `token_${Date.now()}`,
|
|
509
|
+
expiresAt: new Date(Date.now() + 86400000).toISOString(),
|
|
510
|
+
};
|
|
511
|
+
},
|
|
512
|
+
logout: async () => {
|
|
513
|
+
await delay();
|
|
514
|
+
// No-op for mock
|
|
515
|
+
},
|
|
516
|
+
get: async (token) => {
|
|
517
|
+
await delay();
|
|
518
|
+
if (token) {
|
|
519
|
+
return {
|
|
520
|
+
id: 'cust_1',
|
|
521
|
+
email: 'john@example.com',
|
|
522
|
+
firstname: 'John',
|
|
523
|
+
lastname: 'Doe',
|
|
524
|
+
createdAt: new Date().toISOString(),
|
|
525
|
+
addresses: [],
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
return null;
|
|
529
|
+
},
|
|
530
|
+
update: async (token, input) => {
|
|
531
|
+
await delay();
|
|
532
|
+
return {
|
|
533
|
+
id: 'cust_1',
|
|
534
|
+
email: input.email ?? 'john@example.com',
|
|
535
|
+
firstname: input.firstname ?? 'John',
|
|
536
|
+
lastname: input.lastname ?? 'Doe',
|
|
537
|
+
dateOfBirth: input.dateOfBirth,
|
|
538
|
+
gender: input.gender,
|
|
539
|
+
createdAt: new Date().toISOString(),
|
|
540
|
+
addresses: [],
|
|
541
|
+
};
|
|
542
|
+
},
|
|
543
|
+
changePassword: async (_token, _input) => {
|
|
544
|
+
await delay();
|
|
545
|
+
return true;
|
|
546
|
+
},
|
|
547
|
+
requestPasswordReset: async (_email) => {
|
|
548
|
+
await delay();
|
|
549
|
+
return true;
|
|
550
|
+
},
|
|
551
|
+
resetPassword: async (_token, _newPassword) => {
|
|
552
|
+
await delay();
|
|
553
|
+
return true;
|
|
554
|
+
},
|
|
555
|
+
getOrders: async (_token, page = 1, pageSize = 10) => {
|
|
556
|
+
await delay();
|
|
557
|
+
// Generate mock orders
|
|
558
|
+
const mockOrders = [
|
|
559
|
+
{
|
|
560
|
+
id: 'order_1',
|
|
561
|
+
orderNumber: '100000001',
|
|
562
|
+
createdAt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
563
|
+
status: 'Complete',
|
|
564
|
+
total: 149.99,
|
|
565
|
+
currency: 'USD',
|
|
566
|
+
items: [
|
|
567
|
+
{
|
|
568
|
+
id: 'item_1',
|
|
569
|
+
productName: 'Performance Running Shoes',
|
|
570
|
+
sku: 'RUN-001',
|
|
571
|
+
quantity: 1,
|
|
572
|
+
price: 149.99,
|
|
573
|
+
thumbnail: 'https://picsum.photos/seed/item1/100/100',
|
|
574
|
+
},
|
|
575
|
+
],
|
|
576
|
+
shippingAddress: {
|
|
577
|
+
firstname: 'John',
|
|
578
|
+
lastname: 'Doe',
|
|
579
|
+
street: ['123 Main St'],
|
|
580
|
+
city: 'New York',
|
|
581
|
+
region: 'NY',
|
|
582
|
+
postcode: '10001',
|
|
583
|
+
country: 'United States',
|
|
584
|
+
countryCode: 'US',
|
|
585
|
+
telephone: '555-1234',
|
|
586
|
+
},
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
id: 'order_2',
|
|
590
|
+
orderNumber: '100000002',
|
|
591
|
+
createdAt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(),
|
|
592
|
+
status: 'Complete',
|
|
593
|
+
total: 89.95,
|
|
594
|
+
currency: 'USD',
|
|
595
|
+
items: [
|
|
596
|
+
{
|
|
597
|
+
id: 'item_2',
|
|
598
|
+
productName: 'Athletic T-Shirt',
|
|
599
|
+
sku: 'TSH-002',
|
|
600
|
+
quantity: 2,
|
|
601
|
+
price: 29.99,
|
|
602
|
+
thumbnail: 'https://picsum.photos/seed/item2/100/100',
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
id: 'item_3',
|
|
606
|
+
productName: 'Sports Shorts',
|
|
607
|
+
sku: 'SHR-003',
|
|
608
|
+
quantity: 1,
|
|
609
|
+
price: 29.97,
|
|
610
|
+
thumbnail: 'https://picsum.photos/seed/item3/100/100',
|
|
611
|
+
},
|
|
612
|
+
],
|
|
613
|
+
shippingAddress: {
|
|
614
|
+
firstname: 'John',
|
|
615
|
+
lastname: 'Doe',
|
|
616
|
+
street: ['123 Main St'],
|
|
617
|
+
city: 'New York',
|
|
618
|
+
region: 'NY',
|
|
619
|
+
postcode: '10001',
|
|
620
|
+
country: 'United States',
|
|
621
|
+
countryCode: 'US',
|
|
622
|
+
telephone: '555-1234',
|
|
623
|
+
},
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
id: 'order_3',
|
|
627
|
+
orderNumber: '100000003',
|
|
628
|
+
createdAt: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(),
|
|
629
|
+
status: 'Shipped',
|
|
630
|
+
total: 249.00,
|
|
631
|
+
currency: 'USD',
|
|
632
|
+
items: [
|
|
633
|
+
{
|
|
634
|
+
id: 'item_4',
|
|
635
|
+
productName: 'Premium Gym Bag',
|
|
636
|
+
sku: 'BAG-004',
|
|
637
|
+
quantity: 1,
|
|
638
|
+
price: 249.00,
|
|
639
|
+
thumbnail: 'https://picsum.photos/seed/item4/100/100',
|
|
640
|
+
},
|
|
641
|
+
],
|
|
642
|
+
shippingAddress: {
|
|
643
|
+
firstname: 'John',
|
|
644
|
+
lastname: 'Doe',
|
|
645
|
+
street: ['123 Main St'],
|
|
646
|
+
city: 'New York',
|
|
647
|
+
region: 'NY',
|
|
648
|
+
postcode: '10001',
|
|
649
|
+
country: 'United States',
|
|
650
|
+
countryCode: 'US',
|
|
651
|
+
telephone: '555-1234',
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
];
|
|
655
|
+
const start = (page - 1) * pageSize;
|
|
656
|
+
const paginatedOrders = mockOrders.slice(start, start + pageSize);
|
|
657
|
+
return {
|
|
658
|
+
items: paginatedOrders,
|
|
659
|
+
totalCount: mockOrders.length,
|
|
660
|
+
pageInfo: {
|
|
661
|
+
currentPage: page,
|
|
662
|
+
pageSize,
|
|
663
|
+
totalPages: Math.ceil(mockOrders.length / pageSize),
|
|
664
|
+
},
|
|
665
|
+
};
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
};
|
|
669
|
+
export default dummyDataAdapter;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export const categories = [
|
|
2
|
+
{
|
|
3
|
+
id: '1',
|
|
4
|
+
name: 'Shop All',
|
|
5
|
+
urlKey: 'shop',
|
|
6
|
+
description: 'Browse our complete collection of athletic wear and equipment.',
|
|
7
|
+
productCount: 12,
|
|
8
|
+
children: [],
|
|
9
|
+
breadcrumbs: [],
|
|
10
|
+
metaTitle: 'Shop All - Cobrastyle Express',
|
|
11
|
+
metaDescription: 'Browse our complete collection of athletic wear and equipment.',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: '2',
|
|
15
|
+
name: 'Apparel',
|
|
16
|
+
urlKey: 'apparel',
|
|
17
|
+
description: 'High-performance athletic apparel designed for comfort and durability.',
|
|
18
|
+
productCount: 7,
|
|
19
|
+
children: [
|
|
20
|
+
{
|
|
21
|
+
id: '2-1',
|
|
22
|
+
name: 'Tops',
|
|
23
|
+
urlKey: 'apparel/tops',
|
|
24
|
+
description: 'Athletic tops for every workout.',
|
|
25
|
+
productCount: 3,
|
|
26
|
+
children: [],
|
|
27
|
+
breadcrumbs: [{ id: '2', name: 'Apparel', urlKey: 'apparel' }],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: '2-2',
|
|
31
|
+
name: 'Bottoms',
|
|
32
|
+
urlKey: 'apparel/bottoms',
|
|
33
|
+
description: 'Shorts, pants, and leggings.',
|
|
34
|
+
productCount: 3,
|
|
35
|
+
children: [],
|
|
36
|
+
breadcrumbs: [{ id: '2', name: 'Apparel', urlKey: 'apparel' }],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: '2-3',
|
|
40
|
+
name: 'Outerwear',
|
|
41
|
+
urlKey: 'apparel/outerwear',
|
|
42
|
+
description: 'Jackets and hoodies for any weather.',
|
|
43
|
+
productCount: 2,
|
|
44
|
+
children: [],
|
|
45
|
+
breadcrumbs: [{ id: '2', name: 'Apparel', urlKey: 'apparel' }],
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
breadcrumbs: [],
|
|
49
|
+
metaTitle: 'Apparel - Cobrastyle Express',
|
|
50
|
+
metaDescription: 'High-performance athletic apparel designed for comfort and durability.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: '3',
|
|
54
|
+
name: 'Equipment',
|
|
55
|
+
urlKey: 'equipment',
|
|
56
|
+
description: 'Professional-grade fitness equipment for home and gym.',
|
|
57
|
+
productCount: 5,
|
|
58
|
+
children: [
|
|
59
|
+
{
|
|
60
|
+
id: '3-1',
|
|
61
|
+
name: 'Weights',
|
|
62
|
+
urlKey: 'equipment/weights',
|
|
63
|
+
description: 'Dumbbells, kettlebells, and more.',
|
|
64
|
+
productCount: 1,
|
|
65
|
+
children: [],
|
|
66
|
+
breadcrumbs: [{ id: '3', name: 'Equipment', urlKey: 'equipment' }],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: '3-2',
|
|
70
|
+
name: 'Accessories',
|
|
71
|
+
urlKey: 'equipment/accessories',
|
|
72
|
+
description: 'Bands, mats, rollers, and more.',
|
|
73
|
+
productCount: 4,
|
|
74
|
+
children: [],
|
|
75
|
+
breadcrumbs: [{ id: '3', name: 'Equipment', urlKey: 'equipment' }],
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
breadcrumbs: [],
|
|
79
|
+
metaTitle: 'Equipment - Cobrastyle Express',
|
|
80
|
+
metaDescription: 'Professional-grade fitness equipment for home and gym.',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: '4',
|
|
84
|
+
name: 'Sale',
|
|
85
|
+
urlKey: 'sale',
|
|
86
|
+
description: 'Limited time offers on select items.',
|
|
87
|
+
productCount: 0,
|
|
88
|
+
children: [],
|
|
89
|
+
breadcrumbs: [],
|
|
90
|
+
metaTitle: 'Sale - Cobrastyle Express',
|
|
91
|
+
metaDescription: 'Limited time offers on select items.',
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
export const navigation = [
|
|
95
|
+
{
|
|
96
|
+
id: '1',
|
|
97
|
+
name: 'Shop All',
|
|
98
|
+
urlKey: 'shop',
|
|
99
|
+
level: 1,
|
|
100
|
+
position: 1,
|
|
101
|
+
children: [],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: '2',
|
|
105
|
+
name: 'Apparel',
|
|
106
|
+
urlKey: 'apparel',
|
|
107
|
+
level: 1,
|
|
108
|
+
position: 2,
|
|
109
|
+
children: [
|
|
110
|
+
{ id: '2-1', name: 'Tops', urlKey: 'apparel/tops', level: 2, position: 1, children: [] },
|
|
111
|
+
{ id: '2-2', name: 'Bottoms', urlKey: 'apparel/bottoms', level: 2, position: 2, children: [] },
|
|
112
|
+
{ id: '2-3', name: 'Outerwear', urlKey: 'apparel/outerwear', level: 2, position: 3, children: [] },
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: '3',
|
|
117
|
+
name: 'Equipment',
|
|
118
|
+
urlKey: 'equipment',
|
|
119
|
+
level: 1,
|
|
120
|
+
position: 3,
|
|
121
|
+
children: [
|
|
122
|
+
{ id: '3-1', name: 'Weights', urlKey: 'equipment/weights', level: 2, position: 1, children: [] },
|
|
123
|
+
{ id: '3-2', name: 'Accessories', urlKey: 'equipment/accessories', level: 2, position: 2, children: [] },
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: '4',
|
|
128
|
+
name: 'Sale',
|
|
129
|
+
urlKey: 'sale',
|
|
130
|
+
level: 1,
|
|
131
|
+
position: 4,
|
|
132
|
+
children: [],
|
|
133
|
+
},
|
|
134
|
+
];
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export const cmsPages = [
|
|
2
|
+
{
|
|
3
|
+
id: 'home',
|
|
4
|
+
identifier: 'home',
|
|
5
|
+
title: 'Welcome to Cobrastyle Express',
|
|
6
|
+
urlKey: '',
|
|
7
|
+
content: `
|
|
8
|
+
<div class="hero">
|
|
9
|
+
<h1>Unleash Your Potential</h1>
|
|
10
|
+
<p>Premium athletic wear and equipment for every workout.</p>
|
|
11
|
+
</div>
|
|
12
|
+
`,
|
|
13
|
+
metaTitle: 'Cobrastyle Express - Premium Athletic Gear',
|
|
14
|
+
metaDescription: 'Shop premium athletic wear and equipment at Cobrastyle Express.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'about',
|
|
18
|
+
identifier: 'about-us',
|
|
19
|
+
title: 'About Us',
|
|
20
|
+
urlKey: 'about-us',
|
|
21
|
+
content: `
|
|
22
|
+
<h1>About Cobrastyle Express</h1>
|
|
23
|
+
<p>Founded with a passion for fitness and performance, Cobrastyle Express delivers premium athletic gear to help you achieve your goals.</p>
|
|
24
|
+
<h2>Our Mission</h2>
|
|
25
|
+
<p>To provide high-quality, stylish, and functional athletic wear that empowers athletes at every level.</p>
|
|
26
|
+
`,
|
|
27
|
+
metaTitle: 'About Us - Cobrastyle Express',
|
|
28
|
+
metaDescription: 'Learn about Cobrastyle Express and our mission.',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'contact',
|
|
32
|
+
identifier: 'contact',
|
|
33
|
+
title: 'Contact Us',
|
|
34
|
+
urlKey: 'contact',
|
|
35
|
+
content: `
|
|
36
|
+
<h1>Contact Us</h1>
|
|
37
|
+
<p>Have questions? We're here to help.</p>
|
|
38
|
+
<p>Email: support@cobrastyle-express.com</p>
|
|
39
|
+
<p>Phone: 1-800-COBRA-FIT</p>
|
|
40
|
+
`,
|
|
41
|
+
metaTitle: 'Contact Us - Cobrastyle Express',
|
|
42
|
+
metaDescription: 'Get in touch with Cobrastyle Express.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'shipping',
|
|
46
|
+
identifier: 'shipping-policy',
|
|
47
|
+
title: 'Shipping Policy',
|
|
48
|
+
urlKey: 'shipping-policy',
|
|
49
|
+
content: `
|
|
50
|
+
<h1>Shipping Policy</h1>
|
|
51
|
+
<h2>Free Shipping</h2>
|
|
52
|
+
<p>Enjoy free standard shipping on all orders over $75.</p>
|
|
53
|
+
<h2>Delivery Times</h2>
|
|
54
|
+
<ul>
|
|
55
|
+
<li>Standard Shipping: 5-7 business days</li>
|
|
56
|
+
<li>Express Shipping: 2-3 business days</li>
|
|
57
|
+
<li>Next Day: Available for select areas</li>
|
|
58
|
+
</ul>
|
|
59
|
+
`,
|
|
60
|
+
metaTitle: 'Shipping Policy - Cobrastyle Express',
|
|
61
|
+
metaDescription: 'Learn about our shipping options and delivery times.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'returns',
|
|
65
|
+
identifier: 'returns-policy',
|
|
66
|
+
title: 'Returns & Exchanges',
|
|
67
|
+
urlKey: 'returns-policy',
|
|
68
|
+
content: `
|
|
69
|
+
<h1>Returns & Exchanges</h1>
|
|
70
|
+
<p>We want you to be completely satisfied with your purchase.</p>
|
|
71
|
+
<h2>30-Day Returns</h2>
|
|
72
|
+
<p>Return any unworn item within 30 days for a full refund.</p>
|
|
73
|
+
<h2>Easy Exchanges</h2>
|
|
74
|
+
<p>Need a different size? Exchange for free.</p>
|
|
75
|
+
`,
|
|
76
|
+
metaTitle: 'Returns & Exchanges - Cobrastyle Express',
|
|
77
|
+
metaDescription: 'Our hassle-free return and exchange policy.',
|
|
78
|
+
},
|
|
79
|
+
];
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const createSimpleProduct = (id, name, urlKey, price, categoryId) => ({
|
|
2
|
+
id,
|
|
3
|
+
sku: `SKU-${id}`,
|
|
4
|
+
name,
|
|
5
|
+
type: 'simple',
|
|
6
|
+
description: `<p>High-quality ${name.toLowerCase()} designed for performance and style. Made with premium materials.</p>`,
|
|
7
|
+
shortDescription: `Premium ${name.toLowerCase()} for the modern athlete.`,
|
|
8
|
+
urlKey,
|
|
9
|
+
price: {
|
|
10
|
+
regular: price,
|
|
11
|
+
final: price,
|
|
12
|
+
currency: 'USD',
|
|
13
|
+
},
|
|
14
|
+
images: [
|
|
15
|
+
{
|
|
16
|
+
url: `https://picsum.photos/seed/${urlKey}/800/800`,
|
|
17
|
+
label: name,
|
|
18
|
+
position: 0,
|
|
19
|
+
isMain: true,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
url: `https://picsum.photos/seed/${urlKey}-2/800/800`,
|
|
23
|
+
label: `${name} - View 2`,
|
|
24
|
+
position: 1,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
categories: [{ id: categoryId, name: 'Category', urlKey: 'category' }],
|
|
28
|
+
stock: { inStock: true, qty: 100 },
|
|
29
|
+
attributes: [],
|
|
30
|
+
metaTitle: name,
|
|
31
|
+
metaDescription: `Shop ${name} at Cobrastyle Express`,
|
|
32
|
+
});
|
|
33
|
+
const createConfigurableProduct = (id, name, urlKey, basePrice, categoryId) => ({
|
|
34
|
+
...createSimpleProduct(id, name, urlKey, basePrice, categoryId),
|
|
35
|
+
type: 'configurable',
|
|
36
|
+
configurableOptions: [
|
|
37
|
+
{
|
|
38
|
+
id: 'size',
|
|
39
|
+
attributeCode: 'size',
|
|
40
|
+
label: 'Size',
|
|
41
|
+
values: [
|
|
42
|
+
{ id: 's', label: 'S', value: 's' },
|
|
43
|
+
{ id: 'm', label: 'M', value: 'm' },
|
|
44
|
+
{ id: 'l', label: 'L', value: 'l' },
|
|
45
|
+
{ id: 'xl', label: 'XL', value: 'xl' },
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'color',
|
|
50
|
+
attributeCode: 'color',
|
|
51
|
+
label: 'Color',
|
|
52
|
+
values: [
|
|
53
|
+
{ id: 'black', label: 'Black', value: 'black', swatch: { type: 'color', value: '#000000' } },
|
|
54
|
+
{ id: 'white', label: 'White', value: 'white', swatch: { type: 'color', value: '#FFFFFF' } },
|
|
55
|
+
{ id: 'navy', label: 'Navy', value: 'navy', swatch: { type: 'color', value: '#001F3F' } },
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
variants: [
|
|
60
|
+
{
|
|
61
|
+
id: `${id}-s-black`,
|
|
62
|
+
sku: `SKU-${id}-S-BLK`,
|
|
63
|
+
name: `${name} - S / Black`,
|
|
64
|
+
price: { regular: basePrice, final: basePrice, currency: 'USD' },
|
|
65
|
+
stock: { inStock: true, qty: 25 },
|
|
66
|
+
attributes: [
|
|
67
|
+
{ code: 'size', label: 'Size', value: 's' },
|
|
68
|
+
{ code: 'color', label: 'Color', value: 'black' },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: `${id}-m-black`,
|
|
73
|
+
sku: `SKU-${id}-M-BLK`,
|
|
74
|
+
name: `${name} - M / Black`,
|
|
75
|
+
price: { regular: basePrice, final: basePrice, currency: 'USD' },
|
|
76
|
+
stock: { inStock: true, qty: 30 },
|
|
77
|
+
attributes: [
|
|
78
|
+
{ code: 'size', label: 'Size', value: 'm' },
|
|
79
|
+
{ code: 'color', label: 'Color', value: 'black' },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: `${id}-l-white`,
|
|
84
|
+
sku: `SKU-${id}-L-WHT`,
|
|
85
|
+
name: `${name} - L / White`,
|
|
86
|
+
price: { regular: basePrice, final: basePrice, currency: 'USD' },
|
|
87
|
+
stock: { inStock: true, qty: 20 },
|
|
88
|
+
attributes: [
|
|
89
|
+
{ code: 'size', label: 'Size', value: 'l' },
|
|
90
|
+
{ code: 'color', label: 'Color', value: 'white' },
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
export const products = [
|
|
96
|
+
createConfigurableProduct('1', 'Performance Running Tee', 'performance-running-tee', 49.99, '2'),
|
|
97
|
+
createConfigurableProduct('2', 'Training Shorts Pro', 'training-shorts-pro', 59.99, '2'),
|
|
98
|
+
createSimpleProduct('3', 'Resistance Band Set', 'resistance-band-set', 29.99, '3'),
|
|
99
|
+
createConfigurableProduct('4', 'Compression Leggings', 'compression-leggings', 79.99, '2'),
|
|
100
|
+
createSimpleProduct('5', 'Yoga Mat Premium', 'yoga-mat-premium', 45.00, '3'),
|
|
101
|
+
createConfigurableProduct('6', 'Windbreaker Jacket', 'windbreaker-jacket', 89.99, '2'),
|
|
102
|
+
createSimpleProduct('7', 'Foam Roller Recovery', 'foam-roller-recovery', 34.99, '3'),
|
|
103
|
+
createConfigurableProduct('8', 'Athletic Hoodie', 'athletic-hoodie', 69.99, '2'),
|
|
104
|
+
createSimpleProduct('9', 'Jump Rope Speed', 'jump-rope-speed', 19.99, '3'),
|
|
105
|
+
createConfigurableProduct('10', 'Track Pants Slim', 'track-pants-slim', 64.99, '2'),
|
|
106
|
+
createSimpleProduct('11', 'Kettlebell 20lb', 'kettlebell-20lb', 49.99, '3'),
|
|
107
|
+
createConfigurableProduct('12', 'Sports Bra High Support', 'sports-bra-high-support', 54.99, '2'),
|
|
108
|
+
];
|
|
109
|
+
export const productListItems = products.map((p) => ({
|
|
110
|
+
id: p.id,
|
|
111
|
+
sku: p.sku,
|
|
112
|
+
name: p.name,
|
|
113
|
+
urlKey: p.urlKey,
|
|
114
|
+
price: p.price,
|
|
115
|
+
thumbnail: p.images[0],
|
|
116
|
+
hoverImage: p.images[1],
|
|
117
|
+
stock: p.stock,
|
|
118
|
+
type: p.type,
|
|
119
|
+
}));
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cobrastyle/adapter-dummy-data",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"types": "./dist/index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"default": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@cobrastyle/shared-types": "1.0.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"typescript": "^5.3.0",
|
|
20
|
+
"@cobrastyle/adapter-conformance": "1.0.1"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/eComero/cobrastyle-express-next.git",
|
|
26
|
+
"directory": "packages/adapters/dummy-data"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc --project tsconfig.build.json",
|
|
33
|
+
"type-check": "tsc --noEmit"
|
|
34
|
+
}
|
|
35
|
+
}
|