@fayz-ai/shop 0.8.3 → 0.9.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog.js +2 -168
- package/dist/catalog.js.map +1 -1
- package/dist/{catalog.cjs → chunk-CTKZ6O2J.js} +11 -9
- package/dist/chunk-CTKZ6O2J.js.map +1 -0
- package/dist/chunk-IYQHKMLB.js +21 -0
- package/dist/chunk-IYQHKMLB.js.map +1 -0
- package/dist/chunk-JR25TISO.js +3 -0
- package/dist/chunk-JR25TISO.js.map +1 -0
- package/dist/{mock.cjs → chunk-SVTCJ6HP.js} +62 -103
- package/dist/chunk-SVTCJ6HP.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -579
- package/dist/index.js.map +1 -1
- package/dist/mock-catalog.d.ts.map +1 -1
- package/dist/mock-provider.d.ts +8 -1
- package/dist/mock-provider.d.ts.map +1 -1
- package/dist/mock.js +2 -476
- package/dist/mock.js.map +1 -1
- package/dist/provider.d.ts +5 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/runtime.js +3 -492
- package/dist/runtime.js.map +1 -1
- package/dist/supabase-provider.d.ts +5 -1
- package/dist/supabase-provider.d.ts.map +1 -1
- package/dist/tables.d.ts +1 -0
- package/dist/tables.d.ts.map +1 -1
- package/dist/types.d.ts +48 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +22 -26
- package/src/index.ts +1 -0
- package/src/mock-catalog.ts +8 -0
- package/src/mock-provider.ts +63 -5
- package/src/provider.ts +8 -0
- package/src/supabase-provider.ts +64 -1
- package/src/tables.ts +1 -0
- package/src/types.ts +67 -0
- package/dist/catalog.cjs.map +0 -1
- package/dist/index.cjs +0 -1250
- package/dist/index.cjs.map +0 -1
- package/dist/mock.cjs.map +0 -1
- package/dist/provider.cjs +0 -4
- package/dist/provider.cjs.map +0 -1
- package/dist/runtime.cjs +0 -498
- package/dist/runtime.cjs.map +0 -1
- package/dist/types.cjs +0 -4
- package/dist/types.cjs.map +0 -1
package/dist/catalog.js
CHANGED
|
@@ -1,170 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
function svgPlaceholder(label, hueA, hueB) {
|
|
4
|
-
const initials = label.split(/\s+/).map((w) => w[0]).slice(0, 2).join("").toUpperCase();
|
|
5
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="hsl(${hueA},45%,82%)"/><stop offset="1" stop-color="hsl(${hueB},50%,62%)"/></linearGradient></defs><rect width="600" height="600" fill="url(#g)"/><text x="300" y="330" font-family="sans-serif" font-size="120" font-weight="700" fill="rgba(255,255,255,0.85)" text-anchor="middle">${initials}</text></svg>`;
|
|
6
|
-
return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
|
|
7
|
-
}
|
|
8
|
-
function image(productId, name, hueA, hueB, idx = 0) {
|
|
9
|
-
return {
|
|
10
|
-
id: `img-${productId}-${idx}`,
|
|
11
|
-
productId,
|
|
12
|
-
url: svgPlaceholder(name, hueA, hueB),
|
|
13
|
-
altText: name,
|
|
14
|
-
sortOrder: idx,
|
|
15
|
-
isPrimary: idx === 0,
|
|
16
|
-
createdAt: T0
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
var MOCK_CATEGORIES = [
|
|
20
|
-
{ id: "cat-apparel", tenantId: "mock", name: "Apparel", slug: "apparel", description: "Clothing and wearables", parentId: null, sortOrder: 0, createdAt: T0 },
|
|
21
|
-
{ id: "cat-bags", tenantId: "mock", name: "Bags & Accessories", slug: "bags-accessories", description: "Bags, wallets and carry gear", parentId: null, sortOrder: 1, createdAt: T0 },
|
|
22
|
-
{ id: "cat-home", tenantId: "mock", name: "Home & Kitchen", slug: "home-kitchen", description: "Everyday home goods", parentId: null, sortOrder: 2, createdAt: T0 },
|
|
23
|
-
{ id: "cat-tech", tenantId: "mock", name: "Stationery & Tech", slug: "stationery-tech", description: "Desk, audio and paper goods", parentId: null, sortOrder: 3, createdAt: T0 }
|
|
24
|
-
];
|
|
25
|
-
var SEEDS = [
|
|
26
|
-
// --- Apparel ---
|
|
27
|
-
{ id: "p-01", name: "Classic T-Shirt", slug: "classic-t-shirt", description: "A timeless crew-neck tee in heavyweight combed cotton. Pre-shrunk, breathable, and built to outlast trends.", price: 59.9, compareAtPrice: 79.9, inventoryCount: 50, sku: "TSH-001", categoryId: "cat-apparel", hues: [210, 240], weight: 0.2 },
|
|
28
|
-
{ id: "p-02", name: "Linen Shirt", slug: "linen-shirt", description: "A relaxed-fit shirt in 100% European linen. Naturally breathable and softer with every wash.", price: 189.9, inventoryCount: 24, sku: "LNS-002", categoryId: "cat-apparel", hues: [35, 20], weight: 0.3 },
|
|
29
|
-
{ id: "p-03", name: "Denim Jacket", slug: "denim-jacket", description: "A structured trucker jacket in 12oz raw denim. Ages beautifully with hidden interior pockets.", price: 299.9, inventoryCount: 12, sku: "DNJ-003", categoryId: "cat-apparel", hues: [215, 200], weight: 0.8 },
|
|
30
|
-
{ id: "p-04", name: "Wool Beanie", slug: "wool-beanie", description: "A double-layer merino wool beanie. Warm without itch, with a low-profile cuffed fit.", price: 79.9, inventoryCount: 0, sku: "WBN-004", categoryId: "cat-apparel", hues: [0, 350], weight: 0.1 },
|
|
31
|
-
// --- Bags & Accessories ---
|
|
32
|
-
{ id: "p-05", name: "Canvas Tote Bag", slug: "canvas-tote-bag", description: "An everyday carryall in 16oz waxed canvas with reinforced straps and an interior zip pocket.", price: 39.9, inventoryCount: 30, sku: "BAG-001", categoryId: "cat-bags", hues: [80, 110], weight: 0.3 },
|
|
33
|
-
{ id: "p-06", name: "Leather Backpack", slug: "leather-backpack", description: 'Full-grain leather backpack with a padded 15" laptop sleeve, magnetic closures and brass hardware.', price: 549.9, inventoryCount: 8, sku: "LBP-006", categoryId: "cat-bags", hues: [25, 15], weight: 1.4 },
|
|
34
|
-
{ id: "p-07", name: "Leather Card Wallet", slug: "leather-card-wallet", description: "A slim six-card wallet in vegetable-tanned leather. RFID-shielded with a center cash slot.", price: 89.9, compareAtPrice: 119.9, inventoryCount: 45, sku: "LCW-007", categoryId: "cat-bags", hues: [30, 45], weight: 0.08 },
|
|
35
|
-
{ id: "p-08", name: "Travel Duffel", slug: "travel-duffel", description: "A 40L weekender in ballistic nylon with a trolley sleeve, shoe compartment and detachable strap.", price: 329.9, inventoryCount: 15, sku: "TDF-008", categoryId: "cat-bags", hues: [150, 170], weight: 1.1 },
|
|
36
|
-
// --- Home & Kitchen ---
|
|
37
|
-
{ id: "p-09", name: "Ceramic Coffee Mug", slug: "ceramic-coffee-mug", description: "A 350ml stoneware mug with a matte glaze and comfortable wide handle. Dishwasher and microwave safe.", price: 34.9, inventoryCount: 0, sku: "MUG-001", categoryId: "cat-home", hues: [190, 210], weight: 0.4 },
|
|
38
|
-
{ id: "p-10", name: "Scented Soy Candle", slug: "scented-soy-candle", description: "Hand-poured soy wax candle with cedar and bergamot notes. 45-hour burn time in a reusable glass jar.", price: 69.9, inventoryCount: 60, sku: "SSC-010", categoryId: "cat-home", hues: [45, 30], weight: 0.5 },
|
|
39
|
-
{ id: "p-11", name: "Bamboo Cutting Board", slug: "bamboo-cutting-board", description: "An end-grain bamboo board that is gentle on knives, with a juice groove and inset handles.", price: 119.9, inventoryCount: 22, sku: "BCB-011", categoryId: "cat-home", hues: [90, 70], weight: 1.2 },
|
|
40
|
-
{ id: "p-12", name: "Stoneware Plate Set", slug: "stoneware-plate-set", description: "A set of four reactive-glaze dinner plates. Each piece is unique, oven-safe to 220\xB0C.", price: 249.9, inventoryCount: 10, sku: "SPS-012", categoryId: "cat-home", hues: [200, 180], weight: 2.4 },
|
|
41
|
-
// --- Stationery & Tech ---
|
|
42
|
-
{ id: "p-13", name: "Wireless Headphones", slug: "wireless-headphones", description: "Over-ear headphones with active noise cancelling, 40-hour battery and multipoint Bluetooth 5.3.", price: 899.9, inventoryCount: 18, sku: "WHP-013", categoryId: "cat-tech", hues: [260, 280], weight: 0.35 },
|
|
43
|
-
{ id: "p-14", name: "Notebook Set", slug: "notebook-set", description: "Three A5 dot-grid notebooks with 120gsm paper, lay-flat binding and numbered pages.", price: 29.9, inventoryCount: 80, sku: "NBS-014", categoryId: "cat-tech", hues: [330, 310], weight: 0.45 },
|
|
44
|
-
{ id: "p-15", name: "Bluetooth Speaker", slug: "bluetooth-speaker", description: "A pocket-size speaker with surprising low end, IPX7 waterproofing and 14-hour playtime.", price: 199.9, compareAtPrice: 259.9, inventoryCount: 26, sku: "BTS-015", categoryId: "cat-tech", hues: [170, 190], weight: 0.3 },
|
|
45
|
-
{ id: "p-16", name: "Felt Desk Mat", slug: "felt-desk-mat", description: "A 80x30cm merino felt desk mat with a cork base. Protects the desk and quiets the keyboard.", price: 99.9, inventoryCount: 34, sku: "FDM-016", categoryId: "cat-tech", hues: [220, 230], weight: 0.6 }
|
|
46
|
-
];
|
|
47
|
-
var CATEGORY_NAME = Object.fromEntries(
|
|
48
|
-
MOCK_CATEGORIES.map((c) => [c.id, c.name])
|
|
49
|
-
);
|
|
50
|
-
var MOCK_PRODUCTS = SEEDS.map((s, i) => ({
|
|
51
|
-
id: s.id,
|
|
52
|
-
tenantId: "mock",
|
|
53
|
-
name: s.name,
|
|
54
|
-
slug: s.slug,
|
|
55
|
-
description: s.description,
|
|
56
|
-
price: s.price,
|
|
57
|
-
compareAtPrice: s.compareAtPrice ?? null,
|
|
58
|
-
currency: "BRL",
|
|
59
|
-
status: "active",
|
|
60
|
-
inventoryCount: s.inventoryCount,
|
|
61
|
-
sku: s.sku,
|
|
62
|
-
sortOrder: i,
|
|
63
|
-
metadata: {},
|
|
64
|
-
images: [image(s.id, s.name, s.hues[0], s.hues[1])],
|
|
65
|
-
categoryId: s.categoryId,
|
|
66
|
-
categoryName: CATEGORY_NAME[s.categoryId] ?? null,
|
|
67
|
-
isPhysical: true,
|
|
68
|
-
weight: s.weight,
|
|
69
|
-
weightUnit: "kg",
|
|
70
|
-
// staggered timestamps → deterministic 'newest' sort (p-16 newest)
|
|
71
|
-
createdAt: `2026-01-${String(i + 1).padStart(2, "0")}T12:00:00.000Z`,
|
|
72
|
-
updatedAt: `2026-01-${String(i + 1).padStart(2, "0")}T12:00:00.000Z`
|
|
73
|
-
}));
|
|
74
|
-
var MOCK_DISCOUNTS = [
|
|
75
|
-
{
|
|
76
|
-
id: "disc-welcome",
|
|
77
|
-
tenantId: "mock",
|
|
78
|
-
title: "Welcome 10%",
|
|
79
|
-
code: "BEMVINDO10",
|
|
80
|
-
type: "percentage",
|
|
81
|
-
method: "code",
|
|
82
|
-
value: 10,
|
|
83
|
-
usageLimit: null,
|
|
84
|
-
oncePerCustomer: false,
|
|
85
|
-
startsAt: T0,
|
|
86
|
-
endsAt: null,
|
|
87
|
-
status: "active",
|
|
88
|
-
timesUsed: 0,
|
|
89
|
-
createdAt: T0,
|
|
90
|
-
updatedAt: T0
|
|
91
|
-
}
|
|
92
|
-
];
|
|
93
|
-
function slugifyName(name) {
|
|
94
|
-
return name.toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
95
|
-
}
|
|
96
|
-
function buildMockCatalog(input) {
|
|
97
|
-
const categories = input.categories.map((c, i) => ({
|
|
98
|
-
id: `cat-${slugifyName(c.name)}`,
|
|
99
|
-
tenantId: "mock",
|
|
100
|
-
name: c.name,
|
|
101
|
-
slug: slugifyName(c.name),
|
|
102
|
-
description: c.description ?? null,
|
|
103
|
-
parentId: null,
|
|
104
|
-
sortOrder: i,
|
|
105
|
-
imageUrl: c.image ?? null,
|
|
106
|
-
createdAt: T0
|
|
107
|
-
}));
|
|
108
|
-
const byName = Object.fromEntries(categories.map((c) => [c.name, c]));
|
|
109
|
-
const products = input.products.map((p, i) => {
|
|
110
|
-
const cat = byName[p.category];
|
|
111
|
-
const id = `p-${String(i + 1).padStart(2, "0")}`;
|
|
112
|
-
const hues = p.hues ?? [i * 47 % 360, (i * 47 + 50) % 360];
|
|
113
|
-
const stamp = `2026-01-${String(i % 27 + 1).padStart(2, "0")}T12:00:00.000Z`;
|
|
114
|
-
return {
|
|
115
|
-
id,
|
|
116
|
-
tenantId: "mock",
|
|
117
|
-
name: p.name,
|
|
118
|
-
slug: slugifyName(p.name),
|
|
119
|
-
description: p.description,
|
|
120
|
-
price: p.price,
|
|
121
|
-
compareAtPrice: p.compareAtPrice ?? null,
|
|
122
|
-
currency: input.currency ?? "BRL",
|
|
123
|
-
status: "active",
|
|
124
|
-
inventoryCount: p.inventory,
|
|
125
|
-
sku: p.sku,
|
|
126
|
-
sortOrder: i,
|
|
127
|
-
metadata: p.metadata ?? {},
|
|
128
|
-
images: [
|
|
129
|
-
{
|
|
130
|
-
id: `img-${id}-0`,
|
|
131
|
-
productId: id,
|
|
132
|
-
url: p.image ?? svgPlaceholder(p.name, hues[0], hues[1]),
|
|
133
|
-
altText: p.name,
|
|
134
|
-
sortOrder: 0,
|
|
135
|
-
isPrimary: true,
|
|
136
|
-
createdAt: T0
|
|
137
|
-
}
|
|
138
|
-
],
|
|
139
|
-
categoryId: cat?.id ?? null,
|
|
140
|
-
categoryName: cat?.name ?? null,
|
|
141
|
-
isPhysical: true,
|
|
142
|
-
weight: p.weight ?? 0.5,
|
|
143
|
-
weightUnit: "kg",
|
|
144
|
-
createdAt: stamp,
|
|
145
|
-
updatedAt: stamp
|
|
146
|
-
};
|
|
147
|
-
});
|
|
148
|
-
const discounts = (input.discounts ?? []).map((d, i) => ({
|
|
149
|
-
id: `disc-${slugifyName(d.code)}`,
|
|
150
|
-
tenantId: "mock",
|
|
151
|
-
title: d.title ?? `${d.percent}% off`,
|
|
152
|
-
code: d.code,
|
|
153
|
-
type: "percentage",
|
|
154
|
-
method: "code",
|
|
155
|
-
value: d.percent,
|
|
156
|
-
usageLimit: null,
|
|
157
|
-
oncePerCustomer: false,
|
|
158
|
-
startsAt: T0,
|
|
159
|
-
endsAt: null,
|
|
160
|
-
status: "active",
|
|
161
|
-
timesUsed: 0,
|
|
162
|
-
createdAt: T0,
|
|
163
|
-
updatedAt: T0
|
|
164
|
-
}));
|
|
165
|
-
return { products, categories, discounts };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export { MOCK_CATEGORIES, MOCK_DISCOUNTS, MOCK_PRODUCTS, buildMockCatalog, svgPlaceholder };
|
|
1
|
+
import './chunk-JR25TISO.js';
|
|
2
|
+
export { MOCK_CATEGORIES, MOCK_DISCOUNTS, MOCK_PRODUCTS, buildMockCatalog, svgPlaceholder } from './chunk-CTKZ6O2J.js';
|
|
169
3
|
//# sourceMappingURL=catalog.js.map
|
|
170
4
|
//# sourceMappingURL=catalog.js.map
|
package/dist/catalog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mock-catalog.ts"],"names":[],"mappings":";AASA,IAAM,EAAA,GAAK,0BAAA;AAGJ,SAAS,cAAA,CAAe,KAAA,EAAe,IAAA,EAAc,IAAA,EAAsB;AAChF,EAAA,MAAM,WAAW,KAAA,CACd,KAAA,CAAM,KAAK,CAAA,CACX,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAC,CAAA,CACf,MAAM,CAAA,EAAG,CAAC,EACV,IAAA,CAAK,EAAE,EACP,WAAA,EAAY;AACf,EAAA,MAAM,MACJ,CAAA,2JAAA,EAEoC,IAAI,CAAA,6CAAA,EACJ,IAAI,0NAIc,QAAQ,CAAA,aAAA,CAAA;AAEhE,EAAA,OAAO,CAAA,wBAAA,EAA2B,kBAAA,CAAmB,GAAG,CAAC,CAAA,CAAA;AAC3D;AAEA,SAAS,MAAM,SAAA,EAAmB,IAAA,EAAc,IAAA,EAAc,IAAA,EAAc,MAAM,CAAA,EAAiB;AACjG,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,CAAA,IAAA,EAAO,SAAS,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAAA,IAC3B,SAAA;AAAA,IACA,GAAA,EAAK,cAAA,CAAe,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA;AAAA,IACpC,OAAA,EAAS,IAAA;AAAA,IACT,SAAA,EAAW,GAAA;AAAA,IACX,WAAW,GAAA,KAAQ,CAAA;AAAA,IACnB,SAAA,EAAW;AAAA,GACb;AACF;AAEO,IAAM,eAAA,GAA8B;AAAA,EACzC,EAAE,EAAA,EAAI,aAAA,EAAe,QAAA,EAAU,MAAA,EAAQ,MAAM,SAAA,EAAW,IAAA,EAAM,SAAA,EAAW,WAAA,EAAa,0BAA0B,QAAA,EAAU,IAAA,EAAM,SAAA,EAAW,CAAA,EAAG,WAAW,EAAA,EAAG;AAAA,EAC5J,EAAE,EAAA,EAAI,UAAA,EAAY,QAAA,EAAU,MAAA,EAAQ,MAAM,oBAAA,EAAsB,IAAA,EAAM,kBAAA,EAAoB,WAAA,EAAa,gCAAgC,QAAA,EAAU,IAAA,EAAM,SAAA,EAAW,CAAA,EAAG,WAAW,EAAA,EAAG;AAAA,EACnL,EAAE,EAAA,EAAI,UAAA,EAAY,QAAA,EAAU,MAAA,EAAQ,MAAM,gBAAA,EAAkB,IAAA,EAAM,cAAA,EAAgB,WAAA,EAAa,uBAAuB,QAAA,EAAU,IAAA,EAAM,SAAA,EAAW,CAAA,EAAG,WAAW,EAAA,EAAG;AAAA,EAClK,EAAE,EAAA,EAAI,UAAA,EAAY,QAAA,EAAU,MAAA,EAAQ,MAAM,mBAAA,EAAqB,IAAA,EAAM,iBAAA,EAAmB,WAAA,EAAa,+BAA+B,QAAA,EAAU,IAAA,EAAM,SAAA,EAAW,CAAA,EAAG,WAAW,EAAA;AAC/K;AAgBA,IAAM,KAAA,GAAuB;AAAA;AAAA,EAE3B,EAAE,EAAA,EAAI,MAAA,EAAQ,IAAA,EAAM,iBAAA,EAAmB,MAAM,iBAAA,EAAmB,WAAA,EAAa,6GAAA,EAA+G,KAAA,EAAO,IAAA,EAAM,cAAA,EAAgB,MAAM,cAAA,EAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,aAAA,EAAe,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EAC5T,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,eAAe,IAAA,EAAM,aAAA,EAAe,WAAA,EAAa,8FAAA,EAAgG,KAAA,EAAO,KAAA,EAAO,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,aAAA,EAAe,IAAA,EAAM,CAAC,EAAA,EAAI,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EAC9Q,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,gBAAgB,IAAA,EAAM,cAAA,EAAgB,WAAA,EAAa,+FAAA,EAAiG,KAAA,EAAO,KAAA,EAAO,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,aAAA,EAAe,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EACnR,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,eAAe,IAAA,EAAM,aAAA,EAAe,WAAA,EAAa,sFAAA,EAAwF,KAAA,EAAO,IAAA,EAAM,gBAAgB,CAAA,EAAG,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,aAAA,EAAe,IAAA,EAAM,CAAC,CAAA,EAAG,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA;AAAA,EAGpQ,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,mBAAmB,IAAA,EAAM,iBAAA,EAAmB,WAAA,EAAa,8FAAA,EAAgG,KAAA,EAAO,IAAA,EAAM,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,EAAA,EAAI,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EACnR,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,oBAAoB,IAAA,EAAM,kBAAA,EAAoB,WAAA,EAAa,oGAAA,EAAsG,KAAA,EAAO,KAAA,EAAO,gBAAgB,CAAA,EAAG,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,EAAA,EAAI,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EAC1R,EAAE,EAAA,EAAI,MAAA,EAAQ,IAAA,EAAM,qBAAA,EAAuB,MAAM,qBAAA,EAAuB,WAAA,EAAa,4FAAA,EAA8F,KAAA,EAAO,IAAA,EAAM,cAAA,EAAgB,OAAO,cAAA,EAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,EAAA,EAAI,EAAE,CAAA,EAAG,MAAA,EAAQ,IAAA,EAAK;AAAA,EAChT,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,iBAAiB,IAAA,EAAM,eAAA,EAAiB,WAAA,EAAa,kGAAA,EAAoG,KAAA,EAAO,KAAA,EAAO,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA;AAAA,EAGrR,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,sBAAsB,IAAA,EAAM,oBAAA,EAAsB,WAAA,EAAa,sGAAA,EAAwG,KAAA,EAAO,IAAA,EAAM,gBAAgB,CAAA,EAAG,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EACjS,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,sBAAsB,IAAA,EAAM,oBAAA,EAAsB,WAAA,EAAa,sGAAA,EAAwG,KAAA,EAAO,IAAA,EAAM,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,EAAA,EAAI,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EAChS,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,wBAAwB,IAAA,EAAM,sBAAA,EAAwB,WAAA,EAAa,4FAAA,EAA8F,KAAA,EAAO,KAAA,EAAO,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,EAAA,EAAI,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EAC3R,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,uBAAuB,IAAA,EAAM,qBAAA,EAAuB,WAAA,EAAa,0FAAA,EAAyF,KAAA,EAAO,KAAA,EAAO,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA;AAAA,EAGtR,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,uBAAuB,IAAA,EAAM,qBAAA,EAAuB,WAAA,EAAa,iGAAA,EAAmG,KAAA,EAAO,KAAA,EAAO,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,IAAA,EAAK;AAAA,EACjS,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,gBAAgB,IAAA,EAAM,cAAA,EAAgB,WAAA,EAAa,qFAAA,EAAuF,KAAA,EAAO,IAAA,EAAM,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,IAAA,EAAK;AAAA,EACtQ,EAAE,EAAA,EAAI,MAAA,EAAQ,IAAA,EAAM,mBAAA,EAAqB,MAAM,mBAAA,EAAqB,WAAA,EAAa,yFAAA,EAA2F,KAAA,EAAO,KAAA,EAAO,cAAA,EAAgB,OAAO,cAAA,EAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAI;AAAA,EAC3S,EAAE,IAAI,MAAA,EAAQ,IAAA,EAAM,iBAAiB,IAAA,EAAM,eAAA,EAAiB,WAAA,EAAa,6FAAA,EAA+F,KAAA,EAAO,IAAA,EAAM,gBAAgB,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,CAAC,GAAA,EAAK,GAAG,CAAA,EAAG,MAAA,EAAQ,GAAA;AAC7Q,CAAA;AAEA,IAAM,gBAAwC,MAAA,CAAO,WAAA;AAAA,EACnD,eAAA,CAAgB,IAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,IAAI,CAAC;AAC3C,CAAA;AAEO,IAAM,aAAA,GAA2B,KAAA,CAAM,GAAA,CAAI,CAAC,GAAG,CAAA,MAAO;AAAA,EAC3D,IAAI,CAAA,CAAE,EAAA;AAAA,EACN,QAAA,EAAU,MAAA;AAAA,EACV,MAAM,CAAA,CAAE,IAAA;AAAA,EACR,MAAM,CAAA,CAAE,IAAA;AAAA,EACR,aAAa,CAAA,CAAE,WAAA;AAAA,EACf,OAAO,CAAA,CAAE,KAAA;AAAA,EACT,cAAA,EAAgB,EAAE,cAAA,IAAkB,IAAA;AAAA,EACpC,QAAA,EAAU,KAAA;AAAA,EACV,MAAA,EAAQ,QAAA;AAAA,EACR,gBAAgB,CAAA,CAAE,cAAA;AAAA,EAClB,KAAK,CAAA,CAAE,GAAA;AAAA,EACP,SAAA,EAAW,CAAA;AAAA,EACX,UAAU,EAAC;AAAA,EACX,MAAA,EAAQ,CAAC,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA;AAAA,EAClD,YAAY,CAAA,CAAE,UAAA;AAAA,EACd,YAAA,EAAc,aAAA,CAAc,CAAA,CAAE,UAAU,CAAA,IAAK,IAAA;AAAA,EAC7C,UAAA,EAAY,IAAA;AAAA,EACZ,QAAQ,CAAA,CAAE,MAAA;AAAA,EACV,UAAA,EAAY,IAAA;AAAA;AAAA,EAEZ,SAAA,EAAW,WAAW,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,cAAA,CAAA;AAAA,EACpD,SAAA,EAAW,WAAW,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,cAAA;AACtD,CAAA,CAAE;AAEK,IAAM,cAAA,GAA6B;AAAA,EACxC;AAAA,IACE,EAAA,EAAI,cAAA;AAAA,IACJ,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,aAAA;AAAA,IACP,IAAA,EAAM,YAAA;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,MAAA,EAAQ,MAAA;AAAA,IACR,KAAA,EAAO,EAAA;AAAA,IACP,UAAA,EAAY,IAAA;AAAA,IACZ,eAAA,EAAiB,KAAA;AAAA,IACjB,QAAA,EAAU,EAAA;AAAA,IACV,MAAA,EAAQ,IAAA;AAAA,IACR,MAAA,EAAQ,QAAA;AAAA,IACR,SAAA,EAAW,CAAA;AAAA,IACX,SAAA,EAAW,EAAA;AAAA,IACX,SAAA,EAAW;AAAA;AAEf;AAqCA,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,OAAO,KACJ,WAAA,EAAY,CACZ,SAAA,CAAU,KAAK,EACf,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA,CACpB,QAAQ,aAAA,EAAe,GAAG,CAAA,CAC1B,OAAA,CAAQ,UAAU,EAAE,CAAA;AACzB;AAEO,SAAS,iBAAiB,KAAA,EAA6F;AAC5H,EAAA,MAAM,aAAyB,KAAA,CAAM,UAAA,CAAW,GAAA,CAAI,CAAC,GAAG,CAAA,MAAO;AAAA,IAC7D,EAAA,EAAI,CAAA,IAAA,EAAO,WAAA,CAAY,CAAA,CAAE,IAAI,CAAC,CAAA,CAAA;AAAA,IAC9B,QAAA,EAAU,MAAA;AAAA,IACV,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,IAAA,EAAM,WAAA,CAAY,CAAA,CAAE,IAAI,CAAA;AAAA,IACxB,WAAA,EAAa,EAAE,WAAA,IAAe,IAAA;AAAA,IAC9B,QAAA,EAAU,IAAA;AAAA,IACV,SAAA,EAAW,CAAA;AAAA,IACX,QAAA,EAAU,EAAE,KAAA,IAAS,IAAA;AAAA,IACrB,SAAA,EAAW;AAAA,GACb,CAAE,CAAA;AACF,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAY,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,IAAA,EAAM,CAAC,CAAC,CAAC,CAAA;AAEpE,EAAA,MAAM,WAAsB,KAAA,CAAM,QAAA,CAAS,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AACvD,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAA;AAC7B,IAAA,MAAM,EAAA,GAAK,KAAK,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAC9C,IAAA,MAAM,IAAA,GAAO,CAAA,CAAE,IAAA,IAAQ,CAAE,CAAA,GAAI,KAAM,GAAA,EAAA,CAAM,CAAA,GAAI,EAAA,GAAK,EAAA,IAAM,GAAG,CAAA;AAC3D,IAAA,MAAM,KAAA,GAAQ,CAAA,QAAA,EAAW,MAAA,CAAQ,CAAA,GAAI,EAAA,GAAM,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,cAAA,CAAA;AAC9D,IAAA,OAAO;AAAA,MACL,EAAA;AAAA,MACA,QAAA,EAAU,MAAA;AAAA,MACV,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,IAAA,EAAM,WAAA,CAAY,CAAA,CAAE,IAAI,CAAA;AAAA,MACxB,aAAa,CAAA,CAAE,WAAA;AAAA,MACf,OAAO,CAAA,CAAE,KAAA;AAAA,MACT,cAAA,EAAgB,EAAE,cAAA,IAAkB,IAAA;AAAA,MACpC,QAAA,EAAU,MAAM,QAAA,IAAY,KAAA;AAAA,MAC5B,MAAA,EAAQ,QAAA;AAAA,MACR,gBAAgB,CAAA,CAAE,SAAA;AAAA,MAClB,KAAK,CAAA,CAAE,GAAA;AAAA,MACP,SAAA,EAAW,CAAA;AAAA,MACX,QAAA,EAAU,CAAA,CAAE,QAAA,IAAY,EAAC;AAAA,MACzB,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,EAAA,EAAI,OAAO,EAAE,CAAA,EAAA,CAAA;AAAA,UACb,SAAA,EAAW,EAAA;AAAA,UACX,GAAA,EAAK,CAAA,CAAE,KAAA,IAAS,cAAA,CAAe,CAAA,CAAE,IAAA,EAAM,IAAA,CAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AAAA,UACvD,SAAS,CAAA,CAAE,IAAA;AAAA,UACX,SAAA,EAAW,CAAA;AAAA,UACX,SAAA,EAAW,IAAA;AAAA,UACX,SAAA,EAAW;AAAA;AACb,OACF;AAAA,MACA,UAAA,EAAY,KAAK,EAAA,IAAM,IAAA;AAAA,MACvB,YAAA,EAAc,KAAK,IAAA,IAAQ,IAAA;AAAA,MAC3B,UAAA,EAAY,IAAA;AAAA,MACZ,MAAA,EAAQ,EAAE,MAAA,IAAU,GAAA;AAAA,MACpB,UAAA,EAAY,IAAA;AAAA,MACZ,SAAA,EAAW,KAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACb;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,SAAA,GAAA,CAAyB,MAAM,SAAA,IAAa,IAAI,GAAA,CAAI,CAAC,GAAG,CAAA,MAAO;AAAA,IACnE,EAAA,EAAI,CAAA,KAAA,EAAQ,WAAA,CAAY,CAAA,CAAE,IAAI,CAAC,CAAA,CAAA;AAAA,IAC/B,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,CAAA,CAAE,KAAA,IAAS,CAAA,EAAG,EAAE,OAAO,CAAA,KAAA,CAAA;AAAA,IAC9B,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,IAAA,EAAM,YAAA;AAAA,IACN,MAAA,EAAQ,MAAA;AAAA,IACR,OAAO,CAAA,CAAE,OAAA;AAAA,IACT,UAAA,EAAY,IAAA;AAAA,IACZ,eAAA,EAAiB,KAAA;AAAA,IACjB,QAAA,EAAU,EAAA;AAAA,IACV,MAAA,EAAQ,IAAA;AAAA,IACR,MAAA,EAAQ,QAAA;AAAA,IACR,SAAA,EAAW,CAAA;AAAA,IACX,SAAA,EAAW,EAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACb,CAAE,CAAA;AAEF,EAAA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,SAAA,EAAU;AAC3C","file":"catalog.js","sourcesContent":["import type { Product, ProductImage, Category, Discount } from './types'\n\n// ---------------------------------------------------------------------------\n// Deterministic, offline product catalog for the mock provider.\n// Product names sourced from the Fayz client repo references\n// (apps/web ShopSection mockups + original shop seeds), expanded to a\n// 16-product / 4-category Shopify-style catalog.\n// ---------------------------------------------------------------------------\n\nconst T0 = '2026-01-01T12:00:00.000Z'\n\n/** 600x600 gradient SVG with product initials — no network, e2e-stable. */\nexport function svgPlaceholder(label: string, hueA: number, hueB: number): string {\n const initials = label\n .split(/\\s+/)\n .map((w) => w[0])\n .slice(0, 2)\n .join('')\n .toUpperCase()\n const svg =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"600\" height=\"600\">` +\n `<defs><linearGradient id=\"g\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">` +\n `<stop offset=\"0\" stop-color=\"hsl(${hueA},45%,82%)\"/>` +\n `<stop offset=\"1\" stop-color=\"hsl(${hueB},50%,62%)\"/>` +\n `</linearGradient></defs>` +\n `<rect width=\"600\" height=\"600\" fill=\"url(#g)\"/>` +\n `<text x=\"300\" y=\"330\" font-family=\"sans-serif\" font-size=\"120\" font-weight=\"700\" ` +\n `fill=\"rgba(255,255,255,0.85)\" text-anchor=\"middle\">${initials}</text>` +\n `</svg>`\n return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`\n}\n\nfunction image(productId: string, name: string, hueA: number, hueB: number, idx = 0): ProductImage {\n return {\n id: `img-${productId}-${idx}`,\n productId,\n url: svgPlaceholder(name, hueA, hueB),\n altText: name,\n sortOrder: idx,\n isPrimary: idx === 0,\n createdAt: T0,\n }\n}\n\nexport const MOCK_CATEGORIES: Category[] = [\n { id: 'cat-apparel', tenantId: 'mock', name: 'Apparel', slug: 'apparel', description: 'Clothing and wearables', parentId: null, sortOrder: 0, createdAt: T0 },\n { id: 'cat-bags', tenantId: 'mock', name: 'Bags & Accessories', slug: 'bags-accessories', description: 'Bags, wallets and carry gear', parentId: null, sortOrder: 1, createdAt: T0 },\n { id: 'cat-home', tenantId: 'mock', name: 'Home & Kitchen', slug: 'home-kitchen', description: 'Everyday home goods', parentId: null, sortOrder: 2, createdAt: T0 },\n { id: 'cat-tech', tenantId: 'mock', name: 'Stationery & Tech', slug: 'stationery-tech', description: 'Desk, audio and paper goods', parentId: null, sortOrder: 3, createdAt: T0 },\n]\n\ninterface SeedProduct {\n id: string\n name: string\n slug: string\n description: string\n price: number\n compareAtPrice?: number\n inventoryCount: number\n sku: string\n categoryId: string\n hues: [number, number]\n weight: number\n}\n\nconst SEEDS: SeedProduct[] = [\n // --- Apparel ---\n { id: 'p-01', name: 'Classic T-Shirt', slug: 'classic-t-shirt', description: 'A timeless crew-neck tee in heavyweight combed cotton. Pre-shrunk, breathable, and built to outlast trends.', price: 59.9, compareAtPrice: 79.9, inventoryCount: 50, sku: 'TSH-001', categoryId: 'cat-apparel', hues: [210, 240], weight: 0.2 },\n { id: 'p-02', name: 'Linen Shirt', slug: 'linen-shirt', description: 'A relaxed-fit shirt in 100% European linen. Naturally breathable and softer with every wash.', price: 189.9, inventoryCount: 24, sku: 'LNS-002', categoryId: 'cat-apparel', hues: [35, 20], weight: 0.3 },\n { id: 'p-03', name: 'Denim Jacket', slug: 'denim-jacket', description: 'A structured trucker jacket in 12oz raw denim. Ages beautifully with hidden interior pockets.', price: 299.9, inventoryCount: 12, sku: 'DNJ-003', categoryId: 'cat-apparel', hues: [215, 200], weight: 0.8 },\n { id: 'p-04', name: 'Wool Beanie', slug: 'wool-beanie', description: 'A double-layer merino wool beanie. Warm without itch, with a low-profile cuffed fit.', price: 79.9, inventoryCount: 0, sku: 'WBN-004', categoryId: 'cat-apparel', hues: [0, 350], weight: 0.1 },\n\n // --- Bags & Accessories ---\n { id: 'p-05', name: 'Canvas Tote Bag', slug: 'canvas-tote-bag', description: 'An everyday carryall in 16oz waxed canvas with reinforced straps and an interior zip pocket.', price: 39.9, inventoryCount: 30, sku: 'BAG-001', categoryId: 'cat-bags', hues: [80, 110], weight: 0.3 },\n { id: 'p-06', name: 'Leather Backpack', slug: 'leather-backpack', description: 'Full-grain leather backpack with a padded 15\" laptop sleeve, magnetic closures and brass hardware.', price: 549.9, inventoryCount: 8, sku: 'LBP-006', categoryId: 'cat-bags', hues: [25, 15], weight: 1.4 },\n { id: 'p-07', name: 'Leather Card Wallet', slug: 'leather-card-wallet', description: 'A slim six-card wallet in vegetable-tanned leather. RFID-shielded with a center cash slot.', price: 89.9, compareAtPrice: 119.9, inventoryCount: 45, sku: 'LCW-007', categoryId: 'cat-bags', hues: [30, 45], weight: 0.08 },\n { id: 'p-08', name: 'Travel Duffel', slug: 'travel-duffel', description: 'A 40L weekender in ballistic nylon with a trolley sleeve, shoe compartment and detachable strap.', price: 329.9, inventoryCount: 15, sku: 'TDF-008', categoryId: 'cat-bags', hues: [150, 170], weight: 1.1 },\n\n // --- Home & Kitchen ---\n { id: 'p-09', name: 'Ceramic Coffee Mug', slug: 'ceramic-coffee-mug', description: 'A 350ml stoneware mug with a matte glaze and comfortable wide handle. Dishwasher and microwave safe.', price: 34.9, inventoryCount: 0, sku: 'MUG-001', categoryId: 'cat-home', hues: [190, 210], weight: 0.4 },\n { id: 'p-10', name: 'Scented Soy Candle', slug: 'scented-soy-candle', description: 'Hand-poured soy wax candle with cedar and bergamot notes. 45-hour burn time in a reusable glass jar.', price: 69.9, inventoryCount: 60, sku: 'SSC-010', categoryId: 'cat-home', hues: [45, 30], weight: 0.5 },\n { id: 'p-11', name: 'Bamboo Cutting Board', slug: 'bamboo-cutting-board', description: 'An end-grain bamboo board that is gentle on knives, with a juice groove and inset handles.', price: 119.9, inventoryCount: 22, sku: 'BCB-011', categoryId: 'cat-home', hues: [90, 70], weight: 1.2 },\n { id: 'p-12', name: 'Stoneware Plate Set', slug: 'stoneware-plate-set', description: 'A set of four reactive-glaze dinner plates. Each piece is unique, oven-safe to 220°C.', price: 249.9, inventoryCount: 10, sku: 'SPS-012', categoryId: 'cat-home', hues: [200, 180], weight: 2.4 },\n\n // --- Stationery & Tech ---\n { id: 'p-13', name: 'Wireless Headphones', slug: 'wireless-headphones', description: 'Over-ear headphones with active noise cancelling, 40-hour battery and multipoint Bluetooth 5.3.', price: 899.9, inventoryCount: 18, sku: 'WHP-013', categoryId: 'cat-tech', hues: [260, 280], weight: 0.35 },\n { id: 'p-14', name: 'Notebook Set', slug: 'notebook-set', description: 'Three A5 dot-grid notebooks with 120gsm paper, lay-flat binding and numbered pages.', price: 29.9, inventoryCount: 80, sku: 'NBS-014', categoryId: 'cat-tech', hues: [330, 310], weight: 0.45 },\n { id: 'p-15', name: 'Bluetooth Speaker', slug: 'bluetooth-speaker', description: 'A pocket-size speaker with surprising low end, IPX7 waterproofing and 14-hour playtime.', price: 199.9, compareAtPrice: 259.9, inventoryCount: 26, sku: 'BTS-015', categoryId: 'cat-tech', hues: [170, 190], weight: 0.3 },\n { id: 'p-16', name: 'Felt Desk Mat', slug: 'felt-desk-mat', description: 'A 80x30cm merino felt desk mat with a cork base. Protects the desk and quiets the keyboard.', price: 99.9, inventoryCount: 34, sku: 'FDM-016', categoryId: 'cat-tech', hues: [220, 230], weight: 0.6 },\n]\n\nconst CATEGORY_NAME: Record<string, string> = Object.fromEntries(\n MOCK_CATEGORIES.map((c) => [c.id, c.name]),\n)\n\nexport const MOCK_PRODUCTS: Product[] = SEEDS.map((s, i) => ({\n id: s.id,\n tenantId: 'mock',\n name: s.name,\n slug: s.slug,\n description: s.description,\n price: s.price,\n compareAtPrice: s.compareAtPrice ?? null,\n currency: 'BRL',\n status: 'active',\n inventoryCount: s.inventoryCount,\n sku: s.sku,\n sortOrder: i,\n metadata: {},\n images: [image(s.id, s.name, s.hues[0], s.hues[1])],\n categoryId: s.categoryId,\n categoryName: CATEGORY_NAME[s.categoryId] ?? null,\n isPhysical: true,\n weight: s.weight,\n weightUnit: 'kg',\n // staggered timestamps → deterministic 'newest' sort (p-16 newest)\n createdAt: `2026-01-${String(i + 1).padStart(2, '0')}T12:00:00.000Z`,\n updatedAt: `2026-01-${String(i + 1).padStart(2, '0')}T12:00:00.000Z`,\n}))\n\nexport const MOCK_DISCOUNTS: Discount[] = [\n {\n id: 'disc-welcome',\n tenantId: 'mock',\n title: 'Welcome 10%',\n code: 'BEMVINDO10',\n type: 'percentage',\n method: 'code',\n value: 10,\n usageLimit: null,\n oncePerCustomer: false,\n startsAt: T0,\n endsAt: null,\n status: 'active',\n timesUsed: 0,\n createdAt: T0,\n updatedAt: T0,\n },\n]\n\n// ---------------------------------------------------------------------------\n// buildMockCatalog — terse per-store catalog definition. Generates ids,\n// slugs, SVG imagery and staggered timestamps so every store gets a\n// deterministic, e2e-stable catalog from a few lines of data.\n// ---------------------------------------------------------------------------\n\nexport interface CatalogCategoryInput {\n name: string\n description?: string\n image?: string\n}\n\nexport interface CatalogProductInput {\n name: string\n description: string\n price: number\n compareAtPrice?: number\n inventory: number\n sku: string\n /** Category name — must match one of the categories */\n category: string\n hues?: [number, number]\n weight?: number\n image?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface CatalogInput {\n categories: CatalogCategoryInput[]\n products: CatalogProductInput[]\n /** Percentage discount codes, e.g. [{ code: 'BEMVINDO10', percent: 10 }] */\n discounts?: Array<{ code: string; percent: number; title?: string }>\n currency?: string\n}\n\nfunction slugifyName(name: string): string {\n return name\n .toLowerCase()\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n}\n\nexport function buildMockCatalog(input: CatalogInput): { products: Product[]; categories: Category[]; discounts: Discount[] } {\n const categories: Category[] = input.categories.map((c, i) => ({\n id: `cat-${slugifyName(c.name)}`,\n tenantId: 'mock',\n name: c.name,\n slug: slugifyName(c.name),\n description: c.description ?? null,\n parentId: null,\n sortOrder: i,\n imageUrl: c.image ?? null,\n createdAt: T0,\n }))\n const byName = Object.fromEntries(categories.map((c) => [c.name, c]))\n\n const products: Product[] = input.products.map((p, i) => {\n const cat = byName[p.category]\n const id = `p-${String(i + 1).padStart(2, '0')}`\n const hues = p.hues ?? [(i * 47) % 360, (i * 47 + 50) % 360]\n const stamp = `2026-01-${String((i % 27) + 1).padStart(2, '0')}T12:00:00.000Z`\n return {\n id,\n tenantId: 'mock',\n name: p.name,\n slug: slugifyName(p.name),\n description: p.description,\n price: p.price,\n compareAtPrice: p.compareAtPrice ?? null,\n currency: input.currency ?? 'BRL',\n status: 'active',\n inventoryCount: p.inventory,\n sku: p.sku,\n sortOrder: i,\n metadata: p.metadata ?? {},\n images: [\n {\n id: `img-${id}-0`,\n productId: id,\n url: p.image ?? svgPlaceholder(p.name, hues[0], hues[1]),\n altText: p.name,\n sortOrder: 0,\n isPrimary: true,\n createdAt: T0,\n },\n ],\n categoryId: cat?.id ?? null,\n categoryName: cat?.name ?? null,\n isPhysical: true,\n weight: p.weight ?? 0.5,\n weightUnit: 'kg',\n createdAt: stamp,\n updatedAt: stamp,\n }\n })\n\n const discounts: Discount[] = (input.discounts ?? []).map((d, i) => ({\n id: `disc-${slugifyName(d.code)}`,\n tenantId: 'mock',\n title: d.title ?? `${d.percent}% off`,\n code: d.code,\n type: 'percentage',\n method: 'code',\n value: d.percent,\n usageLimit: null,\n oncePerCustomer: false,\n startsAt: T0,\n endsAt: null,\n status: 'active',\n timesUsed: 0,\n createdAt: T0,\n updatedAt: T0,\n }))\n\n return { products, categories, discounts }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"catalog.js"}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
// src/mock-catalog.ts
|
|
4
2
|
var T0 = "2026-01-01T12:00:00.000Z";
|
|
5
3
|
function svgPlaceholder(label, hueA, hueB) {
|
|
@@ -84,6 +82,10 @@ var MOCK_DISCOUNTS = [
|
|
|
84
82
|
value: 10,
|
|
85
83
|
usageLimit: null,
|
|
86
84
|
oncePerCustomer: false,
|
|
85
|
+
minSubtotal: null,
|
|
86
|
+
appliesTo: "all",
|
|
87
|
+
productIds: [],
|
|
88
|
+
categoryIds: [],
|
|
87
89
|
startsAt: T0,
|
|
88
90
|
endsAt: null,
|
|
89
91
|
status: "active",
|
|
@@ -157,6 +159,10 @@ function buildMockCatalog(input) {
|
|
|
157
159
|
value: d.percent,
|
|
158
160
|
usageLimit: null,
|
|
159
161
|
oncePerCustomer: false,
|
|
162
|
+
minSubtotal: null,
|
|
163
|
+
appliesTo: "all",
|
|
164
|
+
productIds: [],
|
|
165
|
+
categoryIds: [],
|
|
160
166
|
startsAt: T0,
|
|
161
167
|
endsAt: null,
|
|
162
168
|
status: "active",
|
|
@@ -167,10 +173,6 @@ function buildMockCatalog(input) {
|
|
|
167
173
|
return { products, categories, discounts };
|
|
168
174
|
}
|
|
169
175
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
exports.buildMockCatalog = buildMockCatalog;
|
|
174
|
-
exports.svgPlaceholder = svgPlaceholder;
|
|
175
|
-
//# sourceMappingURL=catalog.cjs.map
|
|
176
|
-
//# sourceMappingURL=catalog.cjs.map
|
|
176
|
+
export { MOCK_CATEGORIES, MOCK_DISCOUNTS, MOCK_PRODUCTS, buildMockCatalog, svgPlaceholder };
|
|
177
|
+
//# sourceMappingURL=chunk-CTKZ6O2J.js.map
|
|
178
|
+
//# sourceMappingURL=chunk-CTKZ6O2J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mock-catalog.ts"],"names":[],"mappings":"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","file":"chunk-CTKZ6O2J.js","sourcesContent":["import type { Product, ProductImage, Category, Discount } from './types'\n\n// ---------------------------------------------------------------------------\n// Deterministic, offline product catalog for the mock provider.\n// Product names sourced from the Fayz client repo references\n// (apps/web ShopSection mockups + original shop seeds), expanded to a\n// 16-product / 4-category Shopify-style catalog.\n// ---------------------------------------------------------------------------\n\nconst T0 = '2026-01-01T12:00:00.000Z'\n\n/** 600x600 gradient SVG with product initials — no network, e2e-stable. */\nexport function svgPlaceholder(label: string, hueA: number, hueB: number): string {\n const initials = label\n .split(/\\s+/)\n .map((w) => w[0])\n .slice(0, 2)\n .join('')\n .toUpperCase()\n const svg =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"600\" height=\"600\">` +\n `<defs><linearGradient id=\"g\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">` +\n `<stop offset=\"0\" stop-color=\"hsl(${hueA},45%,82%)\"/>` +\n `<stop offset=\"1\" stop-color=\"hsl(${hueB},50%,62%)\"/>` +\n `</linearGradient></defs>` +\n `<rect width=\"600\" height=\"600\" fill=\"url(#g)\"/>` +\n `<text x=\"300\" y=\"330\" font-family=\"sans-serif\" font-size=\"120\" font-weight=\"700\" ` +\n `fill=\"rgba(255,255,255,0.85)\" text-anchor=\"middle\">${initials}</text>` +\n `</svg>`\n return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`\n}\n\nfunction image(productId: string, name: string, hueA: number, hueB: number, idx = 0): ProductImage {\n return {\n id: `img-${productId}-${idx}`,\n productId,\n url: svgPlaceholder(name, hueA, hueB),\n altText: name,\n sortOrder: idx,\n isPrimary: idx === 0,\n createdAt: T0,\n }\n}\n\nexport const MOCK_CATEGORIES: Category[] = [\n { id: 'cat-apparel', tenantId: 'mock', name: 'Apparel', slug: 'apparel', description: 'Clothing and wearables', parentId: null, sortOrder: 0, createdAt: T0 },\n { id: 'cat-bags', tenantId: 'mock', name: 'Bags & Accessories', slug: 'bags-accessories', description: 'Bags, wallets and carry gear', parentId: null, sortOrder: 1, createdAt: T0 },\n { id: 'cat-home', tenantId: 'mock', name: 'Home & Kitchen', slug: 'home-kitchen', description: 'Everyday home goods', parentId: null, sortOrder: 2, createdAt: T0 },\n { id: 'cat-tech', tenantId: 'mock', name: 'Stationery & Tech', slug: 'stationery-tech', description: 'Desk, audio and paper goods', parentId: null, sortOrder: 3, createdAt: T0 },\n]\n\ninterface SeedProduct {\n id: string\n name: string\n slug: string\n description: string\n price: number\n compareAtPrice?: number\n inventoryCount: number\n sku: string\n categoryId: string\n hues: [number, number]\n weight: number\n}\n\nconst SEEDS: SeedProduct[] = [\n // --- Apparel ---\n { id: 'p-01', name: 'Classic T-Shirt', slug: 'classic-t-shirt', description: 'A timeless crew-neck tee in heavyweight combed cotton. Pre-shrunk, breathable, and built to outlast trends.', price: 59.9, compareAtPrice: 79.9, inventoryCount: 50, sku: 'TSH-001', categoryId: 'cat-apparel', hues: [210, 240], weight: 0.2 },\n { id: 'p-02', name: 'Linen Shirt', slug: 'linen-shirt', description: 'A relaxed-fit shirt in 100% European linen. Naturally breathable and softer with every wash.', price: 189.9, inventoryCount: 24, sku: 'LNS-002', categoryId: 'cat-apparel', hues: [35, 20], weight: 0.3 },\n { id: 'p-03', name: 'Denim Jacket', slug: 'denim-jacket', description: 'A structured trucker jacket in 12oz raw denim. Ages beautifully with hidden interior pockets.', price: 299.9, inventoryCount: 12, sku: 'DNJ-003', categoryId: 'cat-apparel', hues: [215, 200], weight: 0.8 },\n { id: 'p-04', name: 'Wool Beanie', slug: 'wool-beanie', description: 'A double-layer merino wool beanie. Warm without itch, with a low-profile cuffed fit.', price: 79.9, inventoryCount: 0, sku: 'WBN-004', categoryId: 'cat-apparel', hues: [0, 350], weight: 0.1 },\n\n // --- Bags & Accessories ---\n { id: 'p-05', name: 'Canvas Tote Bag', slug: 'canvas-tote-bag', description: 'An everyday carryall in 16oz waxed canvas with reinforced straps and an interior zip pocket.', price: 39.9, inventoryCount: 30, sku: 'BAG-001', categoryId: 'cat-bags', hues: [80, 110], weight: 0.3 },\n { id: 'p-06', name: 'Leather Backpack', slug: 'leather-backpack', description: 'Full-grain leather backpack with a padded 15\" laptop sleeve, magnetic closures and brass hardware.', price: 549.9, inventoryCount: 8, sku: 'LBP-006', categoryId: 'cat-bags', hues: [25, 15], weight: 1.4 },\n { id: 'p-07', name: 'Leather Card Wallet', slug: 'leather-card-wallet', description: 'A slim six-card wallet in vegetable-tanned leather. RFID-shielded with a center cash slot.', price: 89.9, compareAtPrice: 119.9, inventoryCount: 45, sku: 'LCW-007', categoryId: 'cat-bags', hues: [30, 45], weight: 0.08 },\n { id: 'p-08', name: 'Travel Duffel', slug: 'travel-duffel', description: 'A 40L weekender in ballistic nylon with a trolley sleeve, shoe compartment and detachable strap.', price: 329.9, inventoryCount: 15, sku: 'TDF-008', categoryId: 'cat-bags', hues: [150, 170], weight: 1.1 },\n\n // --- Home & Kitchen ---\n { id: 'p-09', name: 'Ceramic Coffee Mug', slug: 'ceramic-coffee-mug', description: 'A 350ml stoneware mug with a matte glaze and comfortable wide handle. Dishwasher and microwave safe.', price: 34.9, inventoryCount: 0, sku: 'MUG-001', categoryId: 'cat-home', hues: [190, 210], weight: 0.4 },\n { id: 'p-10', name: 'Scented Soy Candle', slug: 'scented-soy-candle', description: 'Hand-poured soy wax candle with cedar and bergamot notes. 45-hour burn time in a reusable glass jar.', price: 69.9, inventoryCount: 60, sku: 'SSC-010', categoryId: 'cat-home', hues: [45, 30], weight: 0.5 },\n { id: 'p-11', name: 'Bamboo Cutting Board', slug: 'bamboo-cutting-board', description: 'An end-grain bamboo board that is gentle on knives, with a juice groove and inset handles.', price: 119.9, inventoryCount: 22, sku: 'BCB-011', categoryId: 'cat-home', hues: [90, 70], weight: 1.2 },\n { id: 'p-12', name: 'Stoneware Plate Set', slug: 'stoneware-plate-set', description: 'A set of four reactive-glaze dinner plates. Each piece is unique, oven-safe to 220°C.', price: 249.9, inventoryCount: 10, sku: 'SPS-012', categoryId: 'cat-home', hues: [200, 180], weight: 2.4 },\n\n // --- Stationery & Tech ---\n { id: 'p-13', name: 'Wireless Headphones', slug: 'wireless-headphones', description: 'Over-ear headphones with active noise cancelling, 40-hour battery and multipoint Bluetooth 5.3.', price: 899.9, inventoryCount: 18, sku: 'WHP-013', categoryId: 'cat-tech', hues: [260, 280], weight: 0.35 },\n { id: 'p-14', name: 'Notebook Set', slug: 'notebook-set', description: 'Three A5 dot-grid notebooks with 120gsm paper, lay-flat binding and numbered pages.', price: 29.9, inventoryCount: 80, sku: 'NBS-014', categoryId: 'cat-tech', hues: [330, 310], weight: 0.45 },\n { id: 'p-15', name: 'Bluetooth Speaker', slug: 'bluetooth-speaker', description: 'A pocket-size speaker with surprising low end, IPX7 waterproofing and 14-hour playtime.', price: 199.9, compareAtPrice: 259.9, inventoryCount: 26, sku: 'BTS-015', categoryId: 'cat-tech', hues: [170, 190], weight: 0.3 },\n { id: 'p-16', name: 'Felt Desk Mat', slug: 'felt-desk-mat', description: 'A 80x30cm merino felt desk mat with a cork base. Protects the desk and quiets the keyboard.', price: 99.9, inventoryCount: 34, sku: 'FDM-016', categoryId: 'cat-tech', hues: [220, 230], weight: 0.6 },\n]\n\nconst CATEGORY_NAME: Record<string, string> = Object.fromEntries(\n MOCK_CATEGORIES.map((c) => [c.id, c.name]),\n)\n\nexport const MOCK_PRODUCTS: Product[] = SEEDS.map((s, i) => ({\n id: s.id,\n tenantId: 'mock',\n name: s.name,\n slug: s.slug,\n description: s.description,\n price: s.price,\n compareAtPrice: s.compareAtPrice ?? null,\n currency: 'BRL',\n status: 'active',\n inventoryCount: s.inventoryCount,\n sku: s.sku,\n sortOrder: i,\n metadata: {},\n images: [image(s.id, s.name, s.hues[0], s.hues[1])],\n categoryId: s.categoryId,\n categoryName: CATEGORY_NAME[s.categoryId] ?? null,\n isPhysical: true,\n weight: s.weight,\n weightUnit: 'kg',\n // staggered timestamps → deterministic 'newest' sort (p-16 newest)\n createdAt: `2026-01-${String(i + 1).padStart(2, '0')}T12:00:00.000Z`,\n updatedAt: `2026-01-${String(i + 1).padStart(2, '0')}T12:00:00.000Z`,\n}))\n\nexport const MOCK_DISCOUNTS: Discount[] = [\n {\n id: 'disc-welcome',\n tenantId: 'mock',\n title: 'Welcome 10%',\n code: 'BEMVINDO10',\n type: 'percentage',\n method: 'code',\n value: 10,\n usageLimit: null,\n oncePerCustomer: false,\n minSubtotal: null,\n appliesTo: 'all',\n productIds: [],\n categoryIds: [],\n startsAt: T0,\n endsAt: null,\n status: 'active',\n timesUsed: 0,\n createdAt: T0,\n updatedAt: T0,\n },\n]\n\n// ---------------------------------------------------------------------------\n// buildMockCatalog — terse per-store catalog definition. Generates ids,\n// slugs, SVG imagery and staggered timestamps so every store gets a\n// deterministic, e2e-stable catalog from a few lines of data.\n// ---------------------------------------------------------------------------\n\nexport interface CatalogCategoryInput {\n name: string\n description?: string\n image?: string\n}\n\nexport interface CatalogProductInput {\n name: string\n description: string\n price: number\n compareAtPrice?: number\n inventory: number\n sku: string\n /** Category name — must match one of the categories */\n category: string\n hues?: [number, number]\n weight?: number\n image?: string\n metadata?: Record<string, unknown>\n}\n\nexport interface CatalogInput {\n categories: CatalogCategoryInput[]\n products: CatalogProductInput[]\n /** Percentage discount codes, e.g. [{ code: 'BEMVINDO10', percent: 10 }] */\n discounts?: Array<{ code: string; percent: number; title?: string }>\n currency?: string\n}\n\nfunction slugifyName(name: string): string {\n return name\n .toLowerCase()\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n}\n\nexport function buildMockCatalog(input: CatalogInput): { products: Product[]; categories: Category[]; discounts: Discount[] } {\n const categories: Category[] = input.categories.map((c, i) => ({\n id: `cat-${slugifyName(c.name)}`,\n tenantId: 'mock',\n name: c.name,\n slug: slugifyName(c.name),\n description: c.description ?? null,\n parentId: null,\n sortOrder: i,\n imageUrl: c.image ?? null,\n createdAt: T0,\n }))\n const byName = Object.fromEntries(categories.map((c) => [c.name, c]))\n\n const products: Product[] = input.products.map((p, i) => {\n const cat = byName[p.category]\n const id = `p-${String(i + 1).padStart(2, '0')}`\n const hues = p.hues ?? [(i * 47) % 360, (i * 47 + 50) % 360]\n const stamp = `2026-01-${String((i % 27) + 1).padStart(2, '0')}T12:00:00.000Z`\n return {\n id,\n tenantId: 'mock',\n name: p.name,\n slug: slugifyName(p.name),\n description: p.description,\n price: p.price,\n compareAtPrice: p.compareAtPrice ?? null,\n currency: input.currency ?? 'BRL',\n status: 'active',\n inventoryCount: p.inventory,\n sku: p.sku,\n sortOrder: i,\n metadata: p.metadata ?? {},\n images: [\n {\n id: `img-${id}-0`,\n productId: id,\n url: p.image ?? svgPlaceholder(p.name, hues[0], hues[1]),\n altText: p.name,\n sortOrder: 0,\n isPrimary: true,\n createdAt: T0,\n },\n ],\n categoryId: cat?.id ?? null,\n categoryName: cat?.name ?? null,\n isPhysical: true,\n weight: p.weight ?? 0.5,\n weightUnit: 'kg',\n createdAt: stamp,\n updatedAt: stamp,\n }\n })\n\n const discounts: Discount[] = (input.discounts ?? []).map((d, i) => ({\n id: `disc-${slugifyName(d.code)}`,\n tenantId: 'mock',\n title: d.title ?? `${d.percent}% off`,\n code: d.code,\n type: 'percentage',\n method: 'code',\n value: d.percent,\n usageLimit: null,\n oncePerCustomer: false,\n minSubtotal: null,\n appliesTo: 'all',\n productIds: [],\n categoryIds: [],\n startsAt: T0,\n endsAt: null,\n status: 'active',\n timesUsed: 0,\n createdAt: T0,\n updatedAt: T0,\n }))\n\n return { products, categories, discounts }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createMockShopProvider } from './chunk-SVTCJ6HP.js';
|
|
2
|
+
|
|
3
|
+
// src/runtime.ts
|
|
4
|
+
var provider = null;
|
|
5
|
+
var mockFallback = null;
|
|
6
|
+
function getShopProvider() {
|
|
7
|
+
if (provider) return provider;
|
|
8
|
+
if (!mockFallback) mockFallback = createMockShopProvider();
|
|
9
|
+
return mockFallback;
|
|
10
|
+
}
|
|
11
|
+
function setShopProvider(nextProvider) {
|
|
12
|
+
provider = nextProvider;
|
|
13
|
+
}
|
|
14
|
+
function resetShopProvider() {
|
|
15
|
+
provider = null;
|
|
16
|
+
mockFallback = null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { getShopProvider, resetShopProvider, setShopProvider };
|
|
20
|
+
//# sourceMappingURL=chunk-IYQHKMLB.js.map
|
|
21
|
+
//# sourceMappingURL=chunk-IYQHKMLB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts"],"names":[],"mappings":";;;AAGA,IAAI,QAAA,GAAgC,IAAA;AACpC,IAAI,YAAA,GAAoC,IAAA;AAEjC,SAAS,eAAA,GAAgC;AAC9C,EAAA,IAAI,UAAU,OAAO,QAAA;AACrB,EAAA,IAAI,CAAC,YAAA,EAAc,YAAA,GAAe,sBAAA,EAAuB;AACzD,EAAA,OAAO,YAAA;AACT;AAEO,SAAS,gBAAgB,YAAA,EAAkC;AAChE,EAAA,QAAA,GAAW,YAAA;AACb;AAEO,SAAS,iBAAA,GAA0B;AACxC,EAAA,QAAA,GAAW,IAAA;AACX,EAAA,YAAA,GAAe,IAAA;AACjB","file":"chunk-IYQHKMLB.js","sourcesContent":["import type { ShopProvider } from './provider'\nimport { createMockShopProvider } from './mock-provider'\n\nlet provider: ShopProvider | null = null\nlet mockFallback: ShopProvider | null = null\n\nexport function getShopProvider(): ShopProvider {\n if (provider) return provider\n if (!mockFallback) mockFallback = createMockShopProvider()\n return mockFallback\n}\n\nexport function setShopProvider(nextProvider: ShopProvider): void {\n provider = nextProvider\n}\n\nexport function resetShopProvider(): void {\n provider = null\n mockFallback = null\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-JR25TISO.js"}
|
|
@@ -1,97 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// src/mock-catalog.ts
|
|
4
|
-
var T0 = "2026-01-01T12:00:00.000Z";
|
|
5
|
-
function svgPlaceholder(label, hueA, hueB) {
|
|
6
|
-
const initials = label.split(/\s+/).map((w) => w[0]).slice(0, 2).join("").toUpperCase();
|
|
7
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="hsl(${hueA},45%,82%)"/><stop offset="1" stop-color="hsl(${hueB},50%,62%)"/></linearGradient></defs><rect width="600" height="600" fill="url(#g)"/><text x="300" y="330" font-family="sans-serif" font-size="120" font-weight="700" fill="rgba(255,255,255,0.85)" text-anchor="middle">${initials}</text></svg>`;
|
|
8
|
-
return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
|
|
9
|
-
}
|
|
10
|
-
function image(productId, name, hueA, hueB, idx = 0) {
|
|
11
|
-
return {
|
|
12
|
-
id: `img-${productId}-${idx}`,
|
|
13
|
-
productId,
|
|
14
|
-
url: svgPlaceholder(name, hueA, hueB),
|
|
15
|
-
altText: name,
|
|
16
|
-
sortOrder: idx,
|
|
17
|
-
isPrimary: idx === 0,
|
|
18
|
-
createdAt: T0
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
var MOCK_CATEGORIES = [
|
|
22
|
-
{ id: "cat-apparel", tenantId: "mock", name: "Apparel", slug: "apparel", description: "Clothing and wearables", parentId: null, sortOrder: 0, createdAt: T0 },
|
|
23
|
-
{ id: "cat-bags", tenantId: "mock", name: "Bags & Accessories", slug: "bags-accessories", description: "Bags, wallets and carry gear", parentId: null, sortOrder: 1, createdAt: T0 },
|
|
24
|
-
{ id: "cat-home", tenantId: "mock", name: "Home & Kitchen", slug: "home-kitchen", description: "Everyday home goods", parentId: null, sortOrder: 2, createdAt: T0 },
|
|
25
|
-
{ id: "cat-tech", tenantId: "mock", name: "Stationery & Tech", slug: "stationery-tech", description: "Desk, audio and paper goods", parentId: null, sortOrder: 3, createdAt: T0 }
|
|
26
|
-
];
|
|
27
|
-
var SEEDS = [
|
|
28
|
-
// --- Apparel ---
|
|
29
|
-
{ id: "p-01", name: "Classic T-Shirt", slug: "classic-t-shirt", description: "A timeless crew-neck tee in heavyweight combed cotton. Pre-shrunk, breathable, and built to outlast trends.", price: 59.9, compareAtPrice: 79.9, inventoryCount: 50, sku: "TSH-001", categoryId: "cat-apparel", hues: [210, 240], weight: 0.2 },
|
|
30
|
-
{ id: "p-02", name: "Linen Shirt", slug: "linen-shirt", description: "A relaxed-fit shirt in 100% European linen. Naturally breathable and softer with every wash.", price: 189.9, inventoryCount: 24, sku: "LNS-002", categoryId: "cat-apparel", hues: [35, 20], weight: 0.3 },
|
|
31
|
-
{ id: "p-03", name: "Denim Jacket", slug: "denim-jacket", description: "A structured trucker jacket in 12oz raw denim. Ages beautifully with hidden interior pockets.", price: 299.9, inventoryCount: 12, sku: "DNJ-003", categoryId: "cat-apparel", hues: [215, 200], weight: 0.8 },
|
|
32
|
-
{ id: "p-04", name: "Wool Beanie", slug: "wool-beanie", description: "A double-layer merino wool beanie. Warm without itch, with a low-profile cuffed fit.", price: 79.9, inventoryCount: 0, sku: "WBN-004", categoryId: "cat-apparel", hues: [0, 350], weight: 0.1 },
|
|
33
|
-
// --- Bags & Accessories ---
|
|
34
|
-
{ id: "p-05", name: "Canvas Tote Bag", slug: "canvas-tote-bag", description: "An everyday carryall in 16oz waxed canvas with reinforced straps and an interior zip pocket.", price: 39.9, inventoryCount: 30, sku: "BAG-001", categoryId: "cat-bags", hues: [80, 110], weight: 0.3 },
|
|
35
|
-
{ id: "p-06", name: "Leather Backpack", slug: "leather-backpack", description: 'Full-grain leather backpack with a padded 15" laptop sleeve, magnetic closures and brass hardware.', price: 549.9, inventoryCount: 8, sku: "LBP-006", categoryId: "cat-bags", hues: [25, 15], weight: 1.4 },
|
|
36
|
-
{ id: "p-07", name: "Leather Card Wallet", slug: "leather-card-wallet", description: "A slim six-card wallet in vegetable-tanned leather. RFID-shielded with a center cash slot.", price: 89.9, compareAtPrice: 119.9, inventoryCount: 45, sku: "LCW-007", categoryId: "cat-bags", hues: [30, 45], weight: 0.08 },
|
|
37
|
-
{ id: "p-08", name: "Travel Duffel", slug: "travel-duffel", description: "A 40L weekender in ballistic nylon with a trolley sleeve, shoe compartment and detachable strap.", price: 329.9, inventoryCount: 15, sku: "TDF-008", categoryId: "cat-bags", hues: [150, 170], weight: 1.1 },
|
|
38
|
-
// --- Home & Kitchen ---
|
|
39
|
-
{ id: "p-09", name: "Ceramic Coffee Mug", slug: "ceramic-coffee-mug", description: "A 350ml stoneware mug with a matte glaze and comfortable wide handle. Dishwasher and microwave safe.", price: 34.9, inventoryCount: 0, sku: "MUG-001", categoryId: "cat-home", hues: [190, 210], weight: 0.4 },
|
|
40
|
-
{ id: "p-10", name: "Scented Soy Candle", slug: "scented-soy-candle", description: "Hand-poured soy wax candle with cedar and bergamot notes. 45-hour burn time in a reusable glass jar.", price: 69.9, inventoryCount: 60, sku: "SSC-010", categoryId: "cat-home", hues: [45, 30], weight: 0.5 },
|
|
41
|
-
{ id: "p-11", name: "Bamboo Cutting Board", slug: "bamboo-cutting-board", description: "An end-grain bamboo board that is gentle on knives, with a juice groove and inset handles.", price: 119.9, inventoryCount: 22, sku: "BCB-011", categoryId: "cat-home", hues: [90, 70], weight: 1.2 },
|
|
42
|
-
{ id: "p-12", name: "Stoneware Plate Set", slug: "stoneware-plate-set", description: "A set of four reactive-glaze dinner plates. Each piece is unique, oven-safe to 220\xB0C.", price: 249.9, inventoryCount: 10, sku: "SPS-012", categoryId: "cat-home", hues: [200, 180], weight: 2.4 },
|
|
43
|
-
// --- Stationery & Tech ---
|
|
44
|
-
{ id: "p-13", name: "Wireless Headphones", slug: "wireless-headphones", description: "Over-ear headphones with active noise cancelling, 40-hour battery and multipoint Bluetooth 5.3.", price: 899.9, inventoryCount: 18, sku: "WHP-013", categoryId: "cat-tech", hues: [260, 280], weight: 0.35 },
|
|
45
|
-
{ id: "p-14", name: "Notebook Set", slug: "notebook-set", description: "Three A5 dot-grid notebooks with 120gsm paper, lay-flat binding and numbered pages.", price: 29.9, inventoryCount: 80, sku: "NBS-014", categoryId: "cat-tech", hues: [330, 310], weight: 0.45 },
|
|
46
|
-
{ id: "p-15", name: "Bluetooth Speaker", slug: "bluetooth-speaker", description: "A pocket-size speaker with surprising low end, IPX7 waterproofing and 14-hour playtime.", price: 199.9, compareAtPrice: 259.9, inventoryCount: 26, sku: "BTS-015", categoryId: "cat-tech", hues: [170, 190], weight: 0.3 },
|
|
47
|
-
{ id: "p-16", name: "Felt Desk Mat", slug: "felt-desk-mat", description: "A 80x30cm merino felt desk mat with a cork base. Protects the desk and quiets the keyboard.", price: 99.9, inventoryCount: 34, sku: "FDM-016", categoryId: "cat-tech", hues: [220, 230], weight: 0.6 }
|
|
48
|
-
];
|
|
49
|
-
var CATEGORY_NAME = Object.fromEntries(
|
|
50
|
-
MOCK_CATEGORIES.map((c) => [c.id, c.name])
|
|
51
|
-
);
|
|
52
|
-
var MOCK_PRODUCTS = SEEDS.map((s, i) => ({
|
|
53
|
-
id: s.id,
|
|
54
|
-
tenantId: "mock",
|
|
55
|
-
name: s.name,
|
|
56
|
-
slug: s.slug,
|
|
57
|
-
description: s.description,
|
|
58
|
-
price: s.price,
|
|
59
|
-
compareAtPrice: s.compareAtPrice ?? null,
|
|
60
|
-
currency: "BRL",
|
|
61
|
-
status: "active",
|
|
62
|
-
inventoryCount: s.inventoryCount,
|
|
63
|
-
sku: s.sku,
|
|
64
|
-
sortOrder: i,
|
|
65
|
-
metadata: {},
|
|
66
|
-
images: [image(s.id, s.name, s.hues[0], s.hues[1])],
|
|
67
|
-
categoryId: s.categoryId,
|
|
68
|
-
categoryName: CATEGORY_NAME[s.categoryId] ?? null,
|
|
69
|
-
isPhysical: true,
|
|
70
|
-
weight: s.weight,
|
|
71
|
-
weightUnit: "kg",
|
|
72
|
-
// staggered timestamps → deterministic 'newest' sort (p-16 newest)
|
|
73
|
-
createdAt: `2026-01-${String(i + 1).padStart(2, "0")}T12:00:00.000Z`,
|
|
74
|
-
updatedAt: `2026-01-${String(i + 1).padStart(2, "0")}T12:00:00.000Z`
|
|
75
|
-
}));
|
|
76
|
-
var MOCK_DISCOUNTS = [
|
|
77
|
-
{
|
|
78
|
-
id: "disc-welcome",
|
|
79
|
-
tenantId: "mock",
|
|
80
|
-
title: "Welcome 10%",
|
|
81
|
-
code: "BEMVINDO10",
|
|
82
|
-
type: "percentage",
|
|
83
|
-
method: "code",
|
|
84
|
-
value: 10,
|
|
85
|
-
usageLimit: null,
|
|
86
|
-
oncePerCustomer: false,
|
|
87
|
-
startsAt: T0,
|
|
88
|
-
endsAt: null,
|
|
89
|
-
status: "active",
|
|
90
|
-
timesUsed: 0,
|
|
91
|
-
createdAt: T0,
|
|
92
|
-
updatedAt: T0
|
|
93
|
-
}
|
|
94
|
-
];
|
|
1
|
+
import { MOCK_PRODUCTS, MOCK_CATEGORIES, MOCK_DISCOUNTS } from './chunk-CTKZ6O2J.js';
|
|
95
2
|
|
|
96
3
|
// src/mock-provider.ts
|
|
97
4
|
function uid() {
|
|
@@ -103,6 +10,10 @@ function now() {
|
|
|
103
10
|
var ORDERS_KEY = "fayz.shop.mock.orders.v1";
|
|
104
11
|
var CUSTOMERS_KEY = "fayz.shop.mock.customers.v1";
|
|
105
12
|
var ENQUIRIES_KEY = "fayz.shop.mock.enquiries.v1";
|
|
13
|
+
var CHANNELS_KEY = "fayz.shop.mock.channels.v1";
|
|
14
|
+
var DEFAULT_CHANNELS = [
|
|
15
|
+
{ id: "online-store", tenantId: "mock", kind: "online_store", label: "Loja Online", url: null, enabled: true, position: 0, createdAt: now(), updatedAt: now() }
|
|
16
|
+
];
|
|
106
17
|
function loadStored(key) {
|
|
107
18
|
try {
|
|
108
19
|
if (typeof localStorage === "undefined") return [];
|
|
@@ -124,6 +35,10 @@ var MockShopProvider = class {
|
|
|
124
35
|
this.orders = loadStored(ORDERS_KEY);
|
|
125
36
|
this.customers = loadStored(CUSTOMERS_KEY);
|
|
126
37
|
this.enquiries = loadStored(ENQUIRIES_KEY);
|
|
38
|
+
this.channels = (() => {
|
|
39
|
+
const stored = loadStored(CHANNELS_KEY);
|
|
40
|
+
return stored.length ? stored : DEFAULT_CHANNELS.map((c) => ({ ...c }));
|
|
41
|
+
})();
|
|
127
42
|
this.products = (seed?.products ?? MOCK_PRODUCTS).map((p) => ({ ...p }));
|
|
128
43
|
this.categories = (seed?.categories ?? MOCK_CATEGORIES).map((c) => ({ ...c }));
|
|
129
44
|
this.discounts = (seed?.discounts ?? MOCK_DISCOUNTS).map((d) => ({ ...d }));
|
|
@@ -139,6 +54,10 @@ var MockShopProvider = class {
|
|
|
139
54
|
syncEnquiries() {
|
|
140
55
|
this.enquiries = loadStored(ENQUIRIES_KEY);
|
|
141
56
|
}
|
|
57
|
+
syncChannels() {
|
|
58
|
+
const stored = loadStored(CHANNELS_KEY);
|
|
59
|
+
if (stored.length) this.channels = stored;
|
|
60
|
+
}
|
|
142
61
|
persistOrders() {
|
|
143
62
|
store(ORDERS_KEY, this.orders);
|
|
144
63
|
}
|
|
@@ -148,6 +67,9 @@ var MockShopProvider = class {
|
|
|
148
67
|
persistEnquiries() {
|
|
149
68
|
store(ENQUIRIES_KEY, this.enquiries);
|
|
150
69
|
}
|
|
70
|
+
persistChannels() {
|
|
71
|
+
store(CHANNELS_KEY, this.channels);
|
|
72
|
+
}
|
|
151
73
|
// ---------------------------------------------------------------------------
|
|
152
74
|
// Products
|
|
153
75
|
// ---------------------------------------------------------------------------
|
|
@@ -356,13 +278,16 @@ var MockShopProvider = class {
|
|
|
356
278
|
}
|
|
357
279
|
}
|
|
358
280
|
const items = [];
|
|
281
|
+
const lineDetails = [];
|
|
359
282
|
let subtotal = 0;
|
|
360
283
|
for (const line of input.items) {
|
|
361
284
|
const product = this.products.find((p) => p.id === line.productId);
|
|
362
285
|
if (!product || product.status !== "active") throw new Error(`Product unavailable: ${line.productId}`);
|
|
363
286
|
if (product.inventoryCount < line.quantity) throw new Error(`Insufficient stock for ${product.name}`);
|
|
364
287
|
const name = line.optionsLabel ? `${product.name} (${line.optionsLabel})` : product.name;
|
|
365
|
-
|
|
288
|
+
const lineTotal = product.price * line.quantity;
|
|
289
|
+
subtotal += lineTotal;
|
|
290
|
+
lineDetails.push({ productId: product.id, categoryId: product.categoryId, lineTotal });
|
|
366
291
|
items.push({ productId: product.id, name, sku: product.sku ?? void 0, quantity: line.quantity, unitPrice: product.price, imageUrl: product.images[0]?.url });
|
|
367
292
|
}
|
|
368
293
|
subtotal = Math.round(subtotal * 100) / 100;
|
|
@@ -373,11 +298,19 @@ var MockShopProvider = class {
|
|
|
373
298
|
const code = input.discountCode.trim().toLowerCase();
|
|
374
299
|
const d = this.discounts.find((x) => (x.code ?? "").toLowerCase() === code);
|
|
375
300
|
const ts = now();
|
|
376
|
-
const
|
|
301
|
+
const meetsMin = !d?.minSubtotal || subtotal >= d.minSubtotal;
|
|
302
|
+
const valid = !!d && d.status === "active" && d.startsAt <= ts && (!d.endsAt || d.endsAt >= ts) && (d.usageLimit == null || d.timesUsed < d.usageLimit) && meetsMin;
|
|
377
303
|
if (valid && d) {
|
|
378
304
|
appliedCode = d.code;
|
|
379
|
-
|
|
380
|
-
|
|
305
|
+
let eligible = subtotal;
|
|
306
|
+
if (d.appliesTo === "products") {
|
|
307
|
+
eligible = lineDetails.filter((l) => d.productIds.includes(l.productId)).reduce((s, l) => s + l.lineTotal, 0);
|
|
308
|
+
} else if (d.appliesTo === "categories") {
|
|
309
|
+
eligible = lineDetails.filter((l) => l.categoryId && d.categoryIds.includes(l.categoryId)).reduce((s, l) => s + l.lineTotal, 0);
|
|
310
|
+
}
|
|
311
|
+
eligible = Math.round(eligible * 100) / 100;
|
|
312
|
+
if (d.type === "percentage") discountTotal = Math.round(eligible * d.value) / 100;
|
|
313
|
+
else if (d.type === "fixed_amount") discountTotal = Math.min(d.value, eligible);
|
|
381
314
|
else if (d.type === "free_shipping") shippingTotal = 0;
|
|
382
315
|
d.timesUsed += 1;
|
|
383
316
|
}
|
|
@@ -457,7 +390,7 @@ var MockShopProvider = class {
|
|
|
457
390
|
return this.discounts.find((d) => d.id === id) ?? null;
|
|
458
391
|
}
|
|
459
392
|
async createDiscount(input) {
|
|
460
|
-
const d = { id: uid(), tenantId: "mock", title: input.title, code: input.code ?? null, type: input.type, method: input.method ?? "code", value: input.value, usageLimit: input.usageLimit ?? null, oncePerCustomer: input.oncePerCustomer ?? false, startsAt: input.startsAt ?? now(), endsAt: input.endsAt ?? null, status: input.status ?? "active", timesUsed: 0, createdAt: now(), updatedAt: now() };
|
|
393
|
+
const d = { id: uid(), tenantId: "mock", title: input.title, code: input.code ?? null, type: input.type, method: input.method ?? "code", value: input.value, usageLimit: input.usageLimit ?? null, oncePerCustomer: input.oncePerCustomer ?? false, minSubtotal: input.minSubtotal ?? null, appliesTo: input.appliesTo ?? "all", productIds: input.productIds ?? [], categoryIds: input.categoryIds ?? [], startsAt: input.startsAt ?? now(), endsAt: input.endsAt ?? null, status: input.status ?? "active", timesUsed: 0, createdAt: now(), updatedAt: now() };
|
|
461
394
|
this.discounts.push(d);
|
|
462
395
|
return d;
|
|
463
396
|
}
|
|
@@ -470,12 +403,38 @@ var MockShopProvider = class {
|
|
|
470
403
|
async deleteDiscount(id) {
|
|
471
404
|
this.discounts = this.discounts.filter((d) => d.id !== id);
|
|
472
405
|
}
|
|
406
|
+
// ---------------------------------------------------------------------------
|
|
407
|
+
// Sales channels
|
|
408
|
+
// ---------------------------------------------------------------------------
|
|
409
|
+
async listSalesChannels() {
|
|
410
|
+
this.syncChannels();
|
|
411
|
+
return [...this.channels].sort((a, b) => a.position - b.position);
|
|
412
|
+
}
|
|
413
|
+
async createSalesChannel(input) {
|
|
414
|
+
this.syncChannels();
|
|
415
|
+
const c = { id: uid(), tenantId: "mock", kind: input.kind, label: input.label, url: input.url ?? null, enabled: input.enabled ?? true, position: input.position ?? this.channels.length, createdAt: now(), updatedAt: now() };
|
|
416
|
+
this.channels.push(c);
|
|
417
|
+
this.persistChannels();
|
|
418
|
+
return c;
|
|
419
|
+
}
|
|
420
|
+
async updateSalesChannel(id, input) {
|
|
421
|
+
this.syncChannels();
|
|
422
|
+
const i = this.channels.findIndex((c) => c.id === id);
|
|
423
|
+
if (i < 0) throw new Error("Sales channel not found");
|
|
424
|
+
this.channels[i] = { ...this.channels[i], ...input, updatedAt: now() };
|
|
425
|
+
this.persistChannels();
|
|
426
|
+
return this.channels[i];
|
|
427
|
+
}
|
|
428
|
+
async deleteSalesChannel(id) {
|
|
429
|
+
this.syncChannels();
|
|
430
|
+
this.channels = this.channels.filter((c) => c.id !== id);
|
|
431
|
+
this.persistChannels();
|
|
432
|
+
}
|
|
473
433
|
};
|
|
474
434
|
function createMockShopProvider(seed) {
|
|
475
435
|
return new MockShopProvider(seed);
|
|
476
436
|
}
|
|
477
437
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
//# sourceMappingURL=
|
|
481
|
-
//# sourceMappingURL=mock.cjs.map
|
|
438
|
+
export { MockShopProvider, createMockShopProvider };
|
|
439
|
+
//# sourceMappingURL=chunk-SVTCJ6HP.js.map
|
|
440
|
+
//# sourceMappingURL=chunk-SVTCJ6HP.js.map
|