@fayz-ai/plugin-orders 0.2.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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/dist/OrdersContext.d.ts +40 -0
  4. package/dist/OrdersContext.d.ts.map +1 -0
  5. package/dist/OrdersPage-2IXARHDR.cjs +157 -0
  6. package/dist/OrdersPage-2IXARHDR.cjs.map +1 -0
  7. package/dist/OrdersPage-LJIEIZYE.js +155 -0
  8. package/dist/OrdersPage-LJIEIZYE.js.map +1 -0
  9. package/dist/OrdersPage.d.ts +13 -0
  10. package/dist/OrdersPage.d.ts.map +1 -0
  11. package/dist/chunk-7LFVFZKZ.js +23 -0
  12. package/dist/chunk-7LFVFZKZ.js.map +1 -0
  13. package/dist/chunk-WBGECNYU.cjs +28 -0
  14. package/dist/chunk-WBGECNYU.cjs.map +1 -0
  15. package/dist/data/fayz.d.ts +18 -0
  16. package/dist/data/fayz.d.ts.map +1 -0
  17. package/dist/data/mock.d.ts +3 -0
  18. package/dist/data/mock.d.ts.map +1 -0
  19. package/dist/data/types.d.ts +17 -0
  20. package/dist/data/types.d.ts.map +1 -0
  21. package/dist/index.cjs +1185 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.ts +42 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +1178 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/locales/en.d.ts +2 -0
  28. package/dist/locales/en.d.ts.map +1 -0
  29. package/dist/locales/index.d.ts +2 -0
  30. package/dist/locales/index.d.ts.map +1 -0
  31. package/dist/locales/pt-BR.d.ts +2 -0
  32. package/dist/locales/pt-BR.d.ts.map +1 -0
  33. package/dist/registries.d.ts +3 -0
  34. package/dist/registries.d.ts.map +1 -0
  35. package/dist/store.d.ts +29 -0
  36. package/dist/store.d.ts.map +1 -0
  37. package/dist/types.d.ts +119 -0
  38. package/dist/types.d.ts.map +1 -0
  39. package/dist/views/OrderKanbanView.d.ts +3 -0
  40. package/dist/views/OrderKanbanView.d.ts.map +1 -0
  41. package/package.json +54 -0
  42. package/src/OrdersContext.tsx +47 -0
  43. package/src/OrdersPage.tsx +20 -0
  44. package/src/data/fayz.ts +456 -0
  45. package/src/data/mock.ts +512 -0
  46. package/src/data/types.ts +23 -0
  47. package/src/index.ts +217 -0
  48. package/src/locales/en.ts +53 -0
  49. package/src/locales/index.ts +4 -0
  50. package/src/locales/pt-BR.ts +53 -0
  51. package/src/registries.ts +32 -0
  52. package/src/store.ts +191 -0
  53. package/src/types.ts +190 -0
  54. package/src/views/OrderKanbanView.tsx +240 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,1185 @@
1
+ 'use strict';
2
+
3
+ var chunkWBGECNYU_cjs = require('./chunk-WBGECNYU.cjs');
4
+ var React = require('react');
5
+ var vanilla = require('zustand/vanilla');
6
+ var saas = require('@fayz-ai/saas');
7
+ var sonner = require('sonner');
8
+ var sdk = require('@fayz-ai/sdk');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ var React__default = /*#__PURE__*/_interopDefault(React);
13
+
14
+ // src/data/mock.ts
15
+ var uid = 100;
16
+ function nextId(prefix) {
17
+ return prefix + "-" + ++uid;
18
+ }
19
+ var now = (/* @__PURE__ */ new Date()).toISOString();
20
+ function makeItem(orderId, name, quantity, unitPrice, sortOrder, productId) {
21
+ const id = nextId("item");
22
+ return {
23
+ id,
24
+ orderId,
25
+ productId,
26
+ name,
27
+ quantity,
28
+ unitPrice,
29
+ discount: 0,
30
+ total: quantity * unitPrice,
31
+ sortOrder,
32
+ createdAt: now
33
+ };
34
+ }
35
+ function createSeedOrders() {
36
+ const order1Id = nextId("order");
37
+ const order1Items = [
38
+ makeItem(order1Id, "Classic Burger", 1, 32, 0, "prod-burger-classic"),
39
+ makeItem(order1Id, "Fries", 1, 15, 1, "prod-fries")
40
+ ];
41
+ const order1 = {
42
+ id: order1Id,
43
+ referenceNumber: "ORD-0001",
44
+ kind: "dine_in",
45
+ status: "preparing",
46
+ source: "pos",
47
+ tableId: "table-3",
48
+ tableName: "Table 3",
49
+ subtotal: 47,
50
+ discount: 0,
51
+ tax: 0,
52
+ total: 47,
53
+ currency: "BRL",
54
+ tags: [],
55
+ items: order1Items,
56
+ tenantId: "tenant-mock",
57
+ createdAt: now,
58
+ updatedAt: now
59
+ };
60
+ const order2Id = nextId("order");
61
+ const order2Items = [
62
+ makeItem(order2Id, "Cheese Burger", 1, 36, 0, "prod-burger-cheese")
63
+ ];
64
+ const order2 = {
65
+ id: order2Id,
66
+ referenceNumber: "ORD-0002",
67
+ kind: "takeout",
68
+ status: "ready",
69
+ source: "pos",
70
+ subtotal: 36,
71
+ discount: 0,
72
+ tax: 0,
73
+ total: 36,
74
+ currency: "BRL",
75
+ tags: [],
76
+ items: order2Items,
77
+ tenantId: "tenant-mock",
78
+ createdAt: now,
79
+ updatedAt: now
80
+ };
81
+ const order3Id = nextId("order");
82
+ const order3Items = [
83
+ makeItem(order3Id, "Margherita Pizza", 1, 38, 0, "prod-pizza-margherita"),
84
+ makeItem(order3Id, "Caesar Salad", 1, 22, 1, "prod-salad-caesar"),
85
+ makeItem(order3Id, "Soda 350ml", 1, 12, 2, "prod-soda")
86
+ ];
87
+ const order3 = {
88
+ id: order3Id,
89
+ referenceNumber: "ORD-0003",
90
+ kind: "delivery",
91
+ status: "confirmed",
92
+ source: "ifood",
93
+ subtotal: 72,
94
+ discount: 0,
95
+ tax: 0,
96
+ total: 72,
97
+ currency: "BRL",
98
+ tags: [],
99
+ items: order3Items,
100
+ tenantId: "tenant-mock",
101
+ createdAt: now,
102
+ updatedAt: now
103
+ };
104
+ const order4Id = nextId("order");
105
+ const order4Items = [
106
+ makeItem(order4Id, "BBQ Bacon Burger", 1, 42, 0, "prod-burger-bbq")
107
+ ];
108
+ const order4 = {
109
+ id: order4Id,
110
+ referenceNumber: "ORD-0004",
111
+ kind: "dine_in",
112
+ status: "new",
113
+ source: "pos",
114
+ tableId: "table-7",
115
+ tableName: "Table 7",
116
+ subtotal: 42,
117
+ discount: 0,
118
+ tax: 0,
119
+ total: 42,
120
+ currency: "BRL",
121
+ tags: [],
122
+ items: order4Items,
123
+ tenantId: "tenant-mock",
124
+ createdAt: now,
125
+ updatedAt: now
126
+ };
127
+ const order5Id = nextId("order");
128
+ const order5Items = [
129
+ makeItem(order5Id, "Classic Burger", 2, 32, 0, "prod-burger-classic"),
130
+ makeItem(order5Id, "Fries", 1, 15, 1, "prod-fries"),
131
+ makeItem(order5Id, "Onion Rings", 1, 18, 2, "prod-onion-rings"),
132
+ makeItem(order5Id, "Milkshake", 1, 23, 3, "prod-milkshake")
133
+ ];
134
+ const order5 = {
135
+ id: order5Id,
136
+ referenceNumber: "ORD-0005",
137
+ kind: "dine_in",
138
+ status: "completed",
139
+ source: "pos",
140
+ tableId: "table-1",
141
+ tableName: "Table 1",
142
+ subtotal: 120,
143
+ discount: 0,
144
+ tax: 0,
145
+ total: 120,
146
+ currency: "BRL",
147
+ tags: [],
148
+ items: order5Items,
149
+ tenantId: "tenant-mock",
150
+ createdAt: now,
151
+ updatedAt: now,
152
+ completedAt: now
153
+ };
154
+ return [order1, order2, order3, order4, order5];
155
+ }
156
+ function recomputeTotals(order) {
157
+ order.subtotal = order.items.reduce((sum, i) => sum + i.total, 0);
158
+ order.total = order.subtotal - order.discount + order.tax;
159
+ }
160
+ var refCounter = 5;
161
+ function generateReferenceNumber() {
162
+ refCounter++;
163
+ return "ORD-" + String(refCounter).padStart(4, "0");
164
+ }
165
+ function toDateStr(d) {
166
+ return d.toISOString().slice(0, 10);
167
+ }
168
+ function createMockOrdersProvider() {
169
+ const orders = createSeedOrders();
170
+ function findOrder(id) {
171
+ return orders.find((o) => o.id === id);
172
+ }
173
+ function findItem(itemId) {
174
+ for (const order of orders) {
175
+ const index = order.items.findIndex((i) => i.id === itemId);
176
+ if (index !== -1) return { order, item: order.items[index], index };
177
+ }
178
+ return void 0;
179
+ }
180
+ const provider = {
181
+ // ------------------------------------------------------------------
182
+ // getOrders
183
+ // ------------------------------------------------------------------
184
+ async getOrders(query) {
185
+ let result = [...orders];
186
+ if (query.kind) {
187
+ const kinds = Array.isArray(query.kind) ? query.kind : [query.kind];
188
+ result = result.filter((o) => kinds.includes(o.kind));
189
+ }
190
+ if (query.status) {
191
+ const statuses = Array.isArray(query.status) ? query.status : [query.status];
192
+ result = result.filter((o) => statuses.includes(o.status));
193
+ }
194
+ if (query.source) {
195
+ result = result.filter((o) => o.source === query.source);
196
+ }
197
+ if (query.tableId) {
198
+ result = result.filter((o) => o.tableId === query.tableId);
199
+ }
200
+ if (query.assigneeId) {
201
+ result = result.filter((o) => o.assigneeId === query.assigneeId);
202
+ }
203
+ if (query.search) {
204
+ const q = query.search.toLowerCase();
205
+ result = result.filter(
206
+ (o) => o.referenceNumber.toLowerCase().includes(q) || o.partyName?.toLowerCase().includes(q) || o.tableName?.toLowerCase().includes(q) || o.items.some((i) => i.name.toLowerCase().includes(q))
207
+ );
208
+ }
209
+ if (query.dateRange) {
210
+ const from = query.dateRange.from;
211
+ const to = query.dateRange.to;
212
+ result = result.filter((o) => {
213
+ const d = o.createdAt.slice(0, 10);
214
+ return d >= from && d <= to;
215
+ });
216
+ }
217
+ result.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
218
+ const total = result.length;
219
+ const page = query.page ?? 1;
220
+ const pageSize = query.pageSize ?? 20;
221
+ const start = (page - 1) * pageSize;
222
+ const data = result.slice(start, start + pageSize);
223
+ return { data, total };
224
+ },
225
+ // ------------------------------------------------------------------
226
+ // getOrderById
227
+ // ------------------------------------------------------------------
228
+ async getOrderById(id) {
229
+ return findOrder(id) ?? null;
230
+ },
231
+ // ------------------------------------------------------------------
232
+ // createOrder
233
+ // ------------------------------------------------------------------
234
+ async createOrder(input) {
235
+ const orderId = nextId("order");
236
+ const items = input.items.map((item, idx) => ({
237
+ id: nextId("item"),
238
+ orderId,
239
+ productId: item.productId,
240
+ name: item.name,
241
+ quantity: item.quantity,
242
+ unitPrice: item.unitPrice,
243
+ discount: item.discount ?? 0,
244
+ total: item.quantity * item.unitPrice - (item.discount ?? 0),
245
+ sortOrder: idx,
246
+ modifiers: item.modifiers,
247
+ kitchenNotes: item.kitchenNotes,
248
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
249
+ }));
250
+ const subtotal = items.reduce((sum, i) => sum + i.total, 0);
251
+ const order = {
252
+ id: orderId,
253
+ referenceNumber: generateReferenceNumber(),
254
+ kind: input.kind,
255
+ status: "new",
256
+ source: input.source ?? "pos",
257
+ tableId: input.tableId,
258
+ partyId: input.partyId,
259
+ assigneeId: input.assigneeId,
260
+ notes: input.notes,
261
+ estimatedMinutes: input.estimatedMinutes,
262
+ subtotal,
263
+ discount: 0,
264
+ tax: 0,
265
+ total: subtotal,
266
+ currency: "BRL",
267
+ tags: [],
268
+ items,
269
+ tenantId: "tenant-mock",
270
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
271
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
272
+ };
273
+ orders.push(order);
274
+ return order;
275
+ },
276
+ // ------------------------------------------------------------------
277
+ // updateOrderStatus
278
+ // ------------------------------------------------------------------
279
+ async updateOrderStatus(input) {
280
+ const order = findOrder(input.orderId);
281
+ if (!order) throw new Error(`Order not found: ${input.orderId}`);
282
+ if (input.status !== "cancelled") {
283
+ const flow = chunkWBGECNYU_cjs.STATUS_FLOW[order.kind];
284
+ const currentIdx = flow.indexOf(order.status);
285
+ const targetIdx = flow.indexOf(input.status);
286
+ if (targetIdx < 0 || targetIdx !== currentIdx + 1) {
287
+ const next = chunkWBGECNYU_cjs.getNextStatus(order.kind, order.status);
288
+ throw new Error(
289
+ `Invalid status transition: ${order.status} \u2192 ${input.status}. ` + (next ? `Expected next status: ${next}` : "Order is already in a terminal state.")
290
+ );
291
+ }
292
+ }
293
+ order.status = input.status;
294
+ order.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
295
+ if (input.status === "completed") {
296
+ order.completedAt = order.updatedAt;
297
+ }
298
+ return order;
299
+ },
300
+ // ------------------------------------------------------------------
301
+ // updateOrder
302
+ // ------------------------------------------------------------------
303
+ async updateOrder(id, data) {
304
+ const order = findOrder(id);
305
+ if (!order) throw new Error(`Order not found: ${id}`);
306
+ const { id: _id, items: _items, tenantId: _t, createdAt: _c, ...safe } = data;
307
+ Object.assign(order, safe);
308
+ order.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
309
+ return order;
310
+ },
311
+ // ------------------------------------------------------------------
312
+ // cancelOrder
313
+ // ------------------------------------------------------------------
314
+ async cancelOrder(id, reason) {
315
+ const order = findOrder(id);
316
+ if (!order) throw new Error(`Order not found: ${id}`);
317
+ order.status = "cancelled";
318
+ order.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
319
+ if (reason) {
320
+ order.notes = order.notes ? `${order.notes}
321
+ Cancelled: ${reason}` : `Cancelled: ${reason}`;
322
+ }
323
+ },
324
+ // ------------------------------------------------------------------
325
+ // addOrderItem
326
+ // ------------------------------------------------------------------
327
+ async addOrderItem(orderId, item) {
328
+ const order = findOrder(orderId);
329
+ if (!order) throw new Error(`Order not found: ${orderId}`);
330
+ const newItem = {
331
+ id: nextId("item"),
332
+ orderId,
333
+ productId: item.productId,
334
+ name: item.name,
335
+ quantity: item.quantity,
336
+ unitPrice: item.unitPrice,
337
+ discount: item.discount ?? 0,
338
+ total: item.quantity * item.unitPrice - (item.discount ?? 0),
339
+ sortOrder: order.items.length,
340
+ modifiers: item.modifiers,
341
+ kitchenNotes: item.kitchenNotes,
342
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
343
+ };
344
+ order.items.push(newItem);
345
+ recomputeTotals(order);
346
+ order.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
347
+ return newItem;
348
+ },
349
+ // ------------------------------------------------------------------
350
+ // removeOrderItem
351
+ // ------------------------------------------------------------------
352
+ async removeOrderItem(itemId) {
353
+ const found = findItem(itemId);
354
+ if (!found) throw new Error(`Order item not found: ${itemId}`);
355
+ found.order.items.splice(found.index, 1);
356
+ recomputeTotals(found.order);
357
+ found.order.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
358
+ },
359
+ // ------------------------------------------------------------------
360
+ // updateOrderItem
361
+ // ------------------------------------------------------------------
362
+ async updateOrderItem(itemId, data) {
363
+ const found = findItem(itemId);
364
+ if (!found) throw new Error(`Order item not found: ${itemId}`);
365
+ const { id: _id, orderId: _oid, createdAt: _c, ...safe } = data;
366
+ Object.assign(found.item, safe);
367
+ found.item.total = found.item.quantity * found.item.unitPrice - found.item.discount;
368
+ recomputeTotals(found.order);
369
+ found.order.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
370
+ return found.item;
371
+ },
372
+ // ------------------------------------------------------------------
373
+ // getSummary
374
+ // ------------------------------------------------------------------
375
+ async getSummary(dateRange) {
376
+ const today = toDateStr(/* @__PURE__ */ new Date());
377
+ const from = dateRange?.from ?? today;
378
+ const to = dateRange?.to ?? today;
379
+ const inRange = orders.filter((o) => {
380
+ const d = o.createdAt.slice(0, 10);
381
+ return d >= from && d <= to;
382
+ });
383
+ const completed = inRange.filter((o) => o.status !== "cancelled");
384
+ const revenue = completed.reduce((sum, o) => sum + o.total, 0);
385
+ const activeStatuses = /* @__PURE__ */ new Set(["new", "confirmed", "preparing", "ready", "served", "dispatched"]);
386
+ const active = orders.filter((o) => activeStatuses.has(o.status));
387
+ const ordersByKind = { dine_in: 0, takeout: 0, delivery: 0 };
388
+ const ordersByStatus = {};
389
+ for (const o of inRange) {
390
+ ordersByKind[o.kind] = (ordersByKind[o.kind] || 0) + 1;
391
+ ordersByStatus[o.status] = (ordersByStatus[o.status] || 0) + 1;
392
+ }
393
+ const itemMap = /* @__PURE__ */ new Map();
394
+ for (const o of completed) {
395
+ for (const item of o.items) {
396
+ const existing = itemMap.get(item.name);
397
+ if (existing) {
398
+ existing.quantity += item.quantity;
399
+ existing.revenue += item.total;
400
+ } else {
401
+ itemMap.set(item.name, { name: item.name, quantity: item.quantity, revenue: item.total });
402
+ }
403
+ }
404
+ }
405
+ const topItems = Array.from(itemMap.values()).sort((a, b) => b.quantity - a.quantity).slice(0, 5);
406
+ return {
407
+ todayOrderCount: inRange.length,
408
+ todayRevenue: revenue,
409
+ averageTicket: completed.length > 0 ? revenue / completed.length : 0,
410
+ activeOrderCount: active.length,
411
+ ordersByKind,
412
+ ordersByStatus,
413
+ topItems
414
+ };
415
+ }
416
+ };
417
+ return provider;
418
+ }
419
+ function createOrdersStore(provider) {
420
+ return vanilla.createStore((set, get) => ({
421
+ orders: [],
422
+ ordersTotal: 0,
423
+ ordersLoading: false,
424
+ orderQuery: {},
425
+ activeOrders: [],
426
+ activeOrdersLoading: false,
427
+ summary: null,
428
+ summaryLoading: false,
429
+ selectedOrderId: null,
430
+ async fetchOrders(query) {
431
+ return saas.dedup("orders:list:" + JSON.stringify(query), async () => {
432
+ set({ ordersLoading: true, orderQuery: query });
433
+ const result = await provider.getOrders(query);
434
+ set({ orders: result.data, ordersTotal: result.total, ordersLoading: false });
435
+ });
436
+ },
437
+ async fetchActiveOrders() {
438
+ return saas.dedup("orders:active", async () => {
439
+ set({ activeOrdersLoading: true });
440
+ const result = await provider.getOrders({
441
+ status: ["new", "confirmed", "preparing", "ready"]
442
+ });
443
+ set({ activeOrders: result.data, activeOrdersLoading: false });
444
+ });
445
+ },
446
+ async fetchSummary(dateRange) {
447
+ return saas.dedup("orders:summary", async () => {
448
+ set({ summaryLoading: true });
449
+ const summary = await provider.getSummary(dateRange);
450
+ set({ summary, summaryLoading: false });
451
+ });
452
+ },
453
+ selectOrder(id) {
454
+ set({ selectedOrderId: id });
455
+ },
456
+ async createOrder(input) {
457
+ try {
458
+ const order = await provider.createOrder(input);
459
+ const query = get().orderQuery;
460
+ const [result, summary] = await Promise.all([
461
+ provider.getOrders(query),
462
+ provider.getSummary()
463
+ ]);
464
+ set({ orders: result.data, ordersTotal: result.total, summary });
465
+ sonner.toast.success("Order created");
466
+ return order;
467
+ } catch (err) {
468
+ sonner.toast.error("Failed to create order", { description: err?.message });
469
+ throw err;
470
+ }
471
+ },
472
+ async advanceOrderStatus(orderId) {
473
+ try {
474
+ const { orders, activeOrders } = get();
475
+ const order = orders.find((o) => o.id === orderId) ?? activeOrders.find((o) => o.id === orderId);
476
+ if (!order) throw new Error("Order not found");
477
+ const nextStatus = chunkWBGECNYU_cjs.getNextStatus(order.kind, order.status);
478
+ if (!nextStatus) throw new Error("No next status available");
479
+ await provider.updateOrderStatus({ orderId, status: nextStatus });
480
+ const activeResult = await provider.getOrders({
481
+ status: ["new", "confirmed", "preparing", "ready"]
482
+ });
483
+ set({ activeOrders: activeResult.data });
484
+ sonner.toast.success(`Order advanced to ${nextStatus.replace("_", " ")}`);
485
+ } catch (err) {
486
+ sonner.toast.error("Failed to advance order", { description: err?.message });
487
+ throw err;
488
+ }
489
+ },
490
+ async updateOrderStatus(input) {
491
+ try {
492
+ await provider.updateOrderStatus(input);
493
+ const query = get().orderQuery;
494
+ const [result, summary] = await Promise.all([
495
+ provider.getOrders(query),
496
+ provider.getSummary()
497
+ ]);
498
+ set({ orders: result.data, ordersTotal: result.total, summary });
499
+ sonner.toast.success("Order status updated");
500
+ } catch (err) {
501
+ sonner.toast.error("Failed to update status", { description: err?.message });
502
+ throw err;
503
+ }
504
+ },
505
+ async cancelOrder(id, reason) {
506
+ try {
507
+ await provider.cancelOrder(id, reason);
508
+ const query = get().orderQuery;
509
+ const [result, summary] = await Promise.all([
510
+ provider.getOrders(query),
511
+ provider.getSummary()
512
+ ]);
513
+ set({ orders: result.data, ordersTotal: result.total, summary });
514
+ sonner.toast.success("Order cancelled");
515
+ } catch (err) {
516
+ sonner.toast.error("Failed to cancel order", { description: err?.message });
517
+ throw err;
518
+ }
519
+ },
520
+ async addOrderItem(orderId, item) {
521
+ try {
522
+ await provider.addOrderItem(orderId, item);
523
+ const query = get().orderQuery;
524
+ const result = await provider.getOrders(query);
525
+ set({ orders: result.data, ordersTotal: result.total });
526
+ sonner.toast.success("Item added");
527
+ } catch (err) {
528
+ sonner.toast.error("Failed to add item", { description: err?.message });
529
+ throw err;
530
+ }
531
+ },
532
+ async removeOrderItem(itemId) {
533
+ try {
534
+ await provider.removeOrderItem(itemId);
535
+ const query = get().orderQuery;
536
+ const result = await provider.getOrders(query);
537
+ set({ orders: result.data, ordersTotal: result.total });
538
+ sonner.toast.success("Item removed");
539
+ } catch (err) {
540
+ sonner.toast.error("Failed to remove item", { description: err?.message });
541
+ throw err;
542
+ }
543
+ }
544
+ }));
545
+ }
546
+
547
+ // src/registries.ts
548
+ var orderSourceEntity = {
549
+ name: "Order Source",
550
+ namePlural: "Order Sources",
551
+ icon: "Globe",
552
+ displayField: "name",
553
+ defaultSort: "name",
554
+ fields: [
555
+ { key: "name", label: "Name", type: "text", required: true, showInTable: true },
556
+ { key: "icon", label: "Icon", type: "text", showInTable: true },
557
+ { key: "isActive", label: "Active", type: "boolean", showInTable: true, defaultValue: true }
558
+ ],
559
+ data: { table: "order_sources", tenantScoped: true }
560
+ };
561
+ var ordersRegistries = [
562
+ {
563
+ id: "order-sources",
564
+ entity: orderSourceEntity,
565
+ icon: "Globe",
566
+ description: "Order sources and delivery platforms",
567
+ display: "table",
568
+ seedData: [
569
+ { id: "os-dine", name: "Dine-in", icon: "\u{1F37D}\uFE0F", isActive: true },
570
+ { id: "os-takeout", name: "Takeout", icon: "\u{1F961}", isActive: true },
571
+ { id: "os-ifood", name: "iFood", icon: "\u{1F534}", isActive: true },
572
+ { id: "os-99food", name: "99Food", icon: "\u{1F7E1}", isActive: true }
573
+ ]
574
+ }
575
+ ];
576
+
577
+ // src/locales/en.ts
578
+ var en = {
579
+ "orders.title": "Orders",
580
+ "orders.nav.kanban": "Orders",
581
+ "orders.nav.list": "History",
582
+ "orders.nav.new": "New Order",
583
+ "orders.nav.dashboard": "Dashboard",
584
+ "orders.kanban.title": "Orders",
585
+ "orders.kanban.subtitle": "Active orders",
586
+ "orders.kanban.noOrders": "No active orders",
587
+ "orders.kanban.noOrdersDesc": "Orders will appear here as they come in",
588
+ "orders.kanban.newOrder": "New Order",
589
+ "orders.kanban.advance": "Advance",
590
+ "orders.kanban.cancel": "Cancel Order",
591
+ "orders.kanban.column.new": "New",
592
+ "orders.kanban.column.confirmed": "Confirmed",
593
+ "orders.kanban.column.preparing": "Preparing",
594
+ "orders.kanban.column.ready": "Ready",
595
+ "orders.kanban.column.out": "Out",
596
+ "orders.kanban.column.completed": "Completed",
597
+ "orders.kanban.column.cancelled": "Cancelled",
598
+ "orders.detail.title": "Order Details",
599
+ "orders.detail.items": "Items",
600
+ "orders.detail.table": "Table",
601
+ "orders.detail.customer": "Customer",
602
+ "orders.detail.waiter": "Waiter",
603
+ "orders.detail.source": "Source",
604
+ "orders.detail.subtotal": "Subtotal",
605
+ "orders.detail.discount": "Discount",
606
+ "orders.detail.tax": "Tax",
607
+ "orders.detail.total": "Total",
608
+ "orders.detail.notes": "Notes",
609
+ "orders.newOrder.title": "New Order",
610
+ "orders.newOrder.selectKind": "Order type",
611
+ "orders.newOrder.dineIn": "Dine-in",
612
+ "orders.newOrder.takeout": "Takeout",
613
+ "orders.newOrder.delivery": "Delivery",
614
+ "orders.newOrder.selectTable": "Select table",
615
+ "orders.newOrder.addItems": "Add items",
616
+ "orders.newOrder.searchItems": "Search menu...",
617
+ "orders.newOrder.noItems": "No items added yet",
618
+ "orders.newOrder.confirm": "Place Order",
619
+ "orders.newOrder.cancel": "Cancel",
620
+ "orders.list.title": "Order History",
621
+ "orders.list.subtitle": "All orders",
622
+ "orders.list.search": "Search orders...",
623
+ "orders.list.noOrders": "No orders found",
624
+ "orders.source.dine_in": "Dine-in",
625
+ "orders.source.takeout": "Takeout",
626
+ "orders.source.ifood": "iFood",
627
+ "orders.source.99food": "99Food",
628
+ "orders.source.delivery": "Delivery",
629
+ "orders.settings.title": "Orders Settings"
630
+ };
631
+
632
+ // src/locales/pt-BR.ts
633
+ var ptBR = {
634
+ "orders.title": "Pedidos",
635
+ "orders.nav.kanban": "Pedidos",
636
+ "orders.nav.list": "Hist\xF3rico",
637
+ "orders.nav.new": "Novo Pedido",
638
+ "orders.nav.dashboard": "Painel",
639
+ "orders.kanban.title": "Pedidos",
640
+ "orders.kanban.subtitle": "Pedidos ativos",
641
+ "orders.kanban.noOrders": "Nenhum pedido ativo",
642
+ "orders.kanban.noOrdersDesc": "Os pedidos aparecer\xE3o aqui conforme chegarem",
643
+ "orders.kanban.newOrder": "Novo Pedido",
644
+ "orders.kanban.advance": "Avan\xE7ar",
645
+ "orders.kanban.cancel": "Cancelar Pedido",
646
+ "orders.kanban.column.new": "Novo",
647
+ "orders.kanban.column.confirmed": "Confirmado",
648
+ "orders.kanban.column.preparing": "Preparando",
649
+ "orders.kanban.column.ready": "Pronto",
650
+ "orders.kanban.column.out": "Saiu",
651
+ "orders.kanban.column.completed": "Conclu\xEDdo",
652
+ "orders.kanban.column.cancelled": "Cancelado",
653
+ "orders.detail.title": "Detalhes do Pedido",
654
+ "orders.detail.items": "Itens",
655
+ "orders.detail.table": "Mesa",
656
+ "orders.detail.customer": "Cliente",
657
+ "orders.detail.waiter": "Gar\xE7om",
658
+ "orders.detail.source": "Origem",
659
+ "orders.detail.subtotal": "Subtotal",
660
+ "orders.detail.discount": "Desconto",
661
+ "orders.detail.tax": "Imposto",
662
+ "orders.detail.total": "Total",
663
+ "orders.detail.notes": "Observa\xE7\xF5es",
664
+ "orders.newOrder.title": "Novo Pedido",
665
+ "orders.newOrder.selectKind": "Tipo de pedido",
666
+ "orders.newOrder.dineIn": "Mesa",
667
+ "orders.newOrder.takeout": "Para Viagem",
668
+ "orders.newOrder.delivery": "Delivery",
669
+ "orders.newOrder.selectTable": "Selecionar mesa",
670
+ "orders.newOrder.addItems": "Adicionar itens",
671
+ "orders.newOrder.searchItems": "Buscar no card\xE1pio...",
672
+ "orders.newOrder.noItems": "Nenhum item adicionado",
673
+ "orders.newOrder.confirm": "Fazer Pedido",
674
+ "orders.newOrder.cancel": "Cancelar",
675
+ "orders.list.title": "Hist\xF3rico de Pedidos",
676
+ "orders.list.subtitle": "Todos os pedidos",
677
+ "orders.list.search": "Buscar pedidos...",
678
+ "orders.list.noOrders": "Nenhum pedido encontrado",
679
+ "orders.source.dine_in": "Mesa",
680
+ "orders.source.takeout": "Para Viagem",
681
+ "orders.source.ifood": "iFood",
682
+ "orders.source.99food": "99Food",
683
+ "orders.source.delivery": "Delivery",
684
+ "orders.settings.title": "Configura\xE7\xF5es de Pedidos"
685
+ };
686
+
687
+ // src/locales/index.ts
688
+ var ordersLocales = { en, "pt-BR": ptBR };
689
+ var DEFAULT_ORDERS_TABLE = "orders";
690
+ var DEFAULT_ORDER_ITEMS_TABLE = "order_items";
691
+ var ACTIVE_STATUSES = /* @__PURE__ */ new Set(["new", "confirmed", "preparing", "ready", "served", "dispatched"]);
692
+ function nowIso() {
693
+ return (/* @__PURE__ */ new Date()).toISOString();
694
+ }
695
+ function numberValue(value) {
696
+ if (typeof value === "number") return value;
697
+ if (typeof value === "string") return Number(value) || 0;
698
+ return 0;
699
+ }
700
+ function dateKey(value) {
701
+ return value.slice(0, 10);
702
+ }
703
+ function referenceNumber() {
704
+ return `ORD-${Date.now().toString().slice(-6)}`;
705
+ }
706
+ function itemToRow(item, orderId, sortOrder) {
707
+ const discount = item.discount ?? 0;
708
+ return {
709
+ order_id: orderId,
710
+ product_id: item.productId ?? null,
711
+ name: item.name,
712
+ quantity: item.quantity,
713
+ unit_price: item.unitPrice,
714
+ discount,
715
+ total: item.quantity * item.unitPrice - discount,
716
+ sort_order: sortOrder,
717
+ modifiers: item.modifiers ?? null,
718
+ kitchen_notes: item.kitchenNotes ?? null
719
+ };
720
+ }
721
+ function rowToItem(row) {
722
+ const quantity = numberValue(row.quantity);
723
+ const unitPrice = numberValue(row.unit_price);
724
+ const discount = numberValue(row.discount);
725
+ return {
726
+ id: row.id,
727
+ orderId: row.order_id ?? "",
728
+ productId: row.product_id ?? void 0,
729
+ name: row.name ?? "Item",
730
+ description: row.description ?? void 0,
731
+ quantity,
732
+ unitPrice,
733
+ discount,
734
+ total: numberValue(row.total) || quantity * unitPrice - discount,
735
+ sortOrder: row.sort_order ?? 0,
736
+ modifiers: row.modifiers ?? void 0,
737
+ kitchenNotes: row.kitchen_notes ?? void 0,
738
+ metadata: row.metadata ?? {},
739
+ createdAt: row.created_at ?? nowIso()
740
+ };
741
+ }
742
+ function rowToOrder(row, items = []) {
743
+ const subtotal = numberValue(row.subtotal) || items.reduce((sum, item) => sum + item.total, 0);
744
+ const discount = numberValue(row.discount);
745
+ const tax = numberValue(row.tax);
746
+ return {
747
+ id: row.id,
748
+ referenceNumber: row.reference_number ?? row.id,
749
+ kind: row.kind ?? "dine_in",
750
+ status: row.status ?? "new",
751
+ partyId: row.party_id ?? void 0,
752
+ partyName: row.party_name ?? void 0,
753
+ assigneeId: row.assignee_id ?? void 0,
754
+ assigneeName: row.assignee_name ?? void 0,
755
+ locationId: row.location_id ?? void 0,
756
+ subtotal,
757
+ discount,
758
+ tax,
759
+ total: numberValue(row.total) || subtotal - discount + tax,
760
+ currency: row.currency ?? "BRL",
761
+ notes: row.notes ?? void 0,
762
+ tags: row.tags ?? [],
763
+ source: row.source ?? "pos",
764
+ tableId: row.table_id ?? void 0,
765
+ tableName: row.table_name ?? void 0,
766
+ estimatedMinutes: row.estimated_minutes ?? void 0,
767
+ items,
768
+ metadata: row.metadata ?? {},
769
+ tenantId: row.tenant_id ?? "runtime-tenant",
770
+ createdAt: row.created_at ?? nowIso(),
771
+ updatedAt: row.updated_at ?? row.created_at ?? nowIso(),
772
+ completedAt: row.completed_at ?? void 0
773
+ };
774
+ }
775
+ function orderPayload(input) {
776
+ const subtotal = input.items.reduce((sum, item) => sum + item.quantity * item.unitPrice - (item.discount ?? 0), 0);
777
+ return {
778
+ reference_number: referenceNumber(),
779
+ kind: input.kind,
780
+ status: "new",
781
+ source: input.source ?? "pos",
782
+ table_id: input.tableId ?? null,
783
+ party_id: input.partyId ?? null,
784
+ assignee_id: input.assigneeId ?? null,
785
+ notes: input.notes ?? null,
786
+ estimated_minutes: input.estimatedMinutes ?? null,
787
+ subtotal,
788
+ discount: 0,
789
+ tax: 0,
790
+ total: subtotal,
791
+ currency: "BRL",
792
+ tags: []
793
+ };
794
+ }
795
+ function updatePayload(data) {
796
+ const payload = {};
797
+ if (data.referenceNumber !== void 0) payload.reference_number = data.referenceNumber;
798
+ if (data.kind !== void 0) payload.kind = data.kind;
799
+ if (data.status !== void 0) payload.status = data.status;
800
+ if (data.partyId !== void 0) payload.party_id = data.partyId;
801
+ if (data.partyName !== void 0) payload.party_name = data.partyName;
802
+ if (data.assigneeId !== void 0) payload.assignee_id = data.assigneeId;
803
+ if (data.assigneeName !== void 0) payload.assignee_name = data.assigneeName;
804
+ if (data.locationId !== void 0) payload.location_id = data.locationId;
805
+ if (data.subtotal !== void 0) payload.subtotal = data.subtotal;
806
+ if (data.discount !== void 0) payload.discount = data.discount;
807
+ if (data.tax !== void 0) payload.tax = data.tax;
808
+ if (data.total !== void 0) payload.total = data.total;
809
+ if (data.currency !== void 0) payload.currency = data.currency;
810
+ if (data.notes !== void 0) payload.notes = data.notes;
811
+ if (data.tags !== void 0) payload.tags = data.tags;
812
+ if (data.source !== void 0) payload.source = data.source;
813
+ if (data.tableId !== void 0) payload.table_id = data.tableId;
814
+ if (data.tableName !== void 0) payload.table_name = data.tableName;
815
+ if (data.estimatedMinutes !== void 0) payload.estimated_minutes = data.estimatedMinutes;
816
+ if (data.metadata !== void 0) payload.metadata = data.metadata;
817
+ if (data.completedAt !== void 0) payload.completed_at = data.completedAt;
818
+ return payload;
819
+ }
820
+ function filtersFromQuery(query) {
821
+ const filters = [];
822
+ if (query.kind && !Array.isArray(query.kind)) filters.push({ column: "kind", operator: "eq", value: query.kind });
823
+ if (query.status && !Array.isArray(query.status)) filters.push({ column: "status", operator: "eq", value: query.status });
824
+ if (query.source) filters.push({ column: "source", operator: "eq", value: query.source });
825
+ if (query.tableId) filters.push({ column: "table_id", operator: "eq", value: query.tableId });
826
+ if (query.assigneeId) filters.push({ column: "assignee_id", operator: "eq", value: query.assigneeId });
827
+ return filters;
828
+ }
829
+ function matchesClientQuery(order, query) {
830
+ if (Array.isArray(query.kind) && !query.kind.includes(order.kind)) return false;
831
+ if (Array.isArray(query.status) && !query.status.includes(order.status)) return false;
832
+ if (query.dateRange) {
833
+ const created = dateKey(order.createdAt);
834
+ if (created < query.dateRange.from || created > query.dateRange.to) return false;
835
+ }
836
+ if (query.search) {
837
+ const search = query.search.toLowerCase();
838
+ return order.referenceNumber.toLowerCase().includes(search) || (order.partyName?.toLowerCase().includes(search) ?? false) || (order.tableName?.toLowerCase().includes(search) ?? false) || order.items.some((item) => item.name.toLowerCase().includes(search));
839
+ }
840
+ return true;
841
+ }
842
+ function paginate(items, page, pageSize) {
843
+ const currentPage = page ?? 1;
844
+ const limit = pageSize ?? 20;
845
+ const start = (currentPage - 1) * limit;
846
+ return { data: items.slice(start, start + limit), total: items.length };
847
+ }
848
+ function summarize(orders, dateRange) {
849
+ const today = dateKey(nowIso());
850
+ const from = dateRange?.from ?? today;
851
+ const to = dateRange?.to ?? today;
852
+ const inRange = orders.filter((order) => {
853
+ const created = dateKey(order.createdAt);
854
+ return created >= from && created <= to;
855
+ });
856
+ const billable = inRange.filter((order) => order.status !== "cancelled");
857
+ const revenue = billable.reduce((sum, order) => sum + order.total, 0);
858
+ const ordersByKind = { dine_in: 0, takeout: 0, delivery: 0 };
859
+ const ordersByStatus = {};
860
+ const top = /* @__PURE__ */ new Map();
861
+ for (const order of inRange) {
862
+ ordersByKind[order.kind] = (ordersByKind[order.kind] ?? 0) + 1;
863
+ ordersByStatus[order.status] = (ordersByStatus[order.status] ?? 0) + 1;
864
+ if (order.status === "cancelled") continue;
865
+ for (const item of order.items) {
866
+ const current = top.get(item.name) ?? { name: item.name, quantity: 0, revenue: 0 };
867
+ current.quantity += item.quantity;
868
+ current.revenue += item.total;
869
+ top.set(item.name, current);
870
+ }
871
+ }
872
+ return {
873
+ todayOrderCount: inRange.length,
874
+ todayRevenue: revenue,
875
+ averageTicket: billable.length > 0 ? revenue / billable.length : 0,
876
+ activeOrderCount: orders.filter((order) => ACTIVE_STATUSES.has(order.status)).length,
877
+ ordersByKind,
878
+ ordersByStatus,
879
+ topItems: [...top.values()].sort((a, b) => b.quantity - a.quantity).slice(0, 5)
880
+ };
881
+ }
882
+ function createFayzOrdersProvider(options = {}) {
883
+ const client = sdk.createFayzClient(options);
884
+ const ordersTable = options.ordersTable ?? DEFAULT_ORDERS_TABLE;
885
+ const orderItemsTable = options.orderItemsTable ?? DEFAULT_ORDER_ITEMS_TABLE;
886
+ const tableOptions = { projectId: options.projectId, schema: options.schema, runtime: options.runtime };
887
+ function resolveTenant() {
888
+ const value = typeof options.tenantId === "function" ? options.tenantId() : options.tenantId;
889
+ return value ?? void 0;
890
+ }
891
+ function withTenant(filters) {
892
+ const tenantId = resolveTenant();
893
+ return tenantId ? [{ column: "tenant_id", operator: "eq", value: tenantId }, ...filters] : filters;
894
+ }
895
+ async function listItemRows(orderIds) {
896
+ if (orderIds.length === 0) return [];
897
+ const rows = [];
898
+ await Promise.all(orderIds.map(async (orderId) => {
899
+ const response = await client.data.listRows({
900
+ ...tableOptions,
901
+ table: orderItemsTable,
902
+ filters: [{ column: "order_id", operator: "eq", value: orderId }],
903
+ sortColumn: "sort_order",
904
+ sortDirection: "asc",
905
+ limit: 200
906
+ });
907
+ rows.push(...response.rows);
908
+ }));
909
+ return rows;
910
+ }
911
+ async function hydrate(rows) {
912
+ const itemRows = await listItemRows(rows.map((row) => row.id));
913
+ const byOrder = /* @__PURE__ */ new Map();
914
+ for (const itemRow of itemRows) {
915
+ const item = rowToItem(itemRow);
916
+ const list = byOrder.get(item.orderId) ?? [];
917
+ list.push(item);
918
+ byOrder.set(item.orderId, list);
919
+ }
920
+ return rows.map((row) => rowToOrder(row, byOrder.get(row.id) ?? []));
921
+ }
922
+ async function listOrders(query = {}) {
923
+ const response = await client.data.listRows({
924
+ ...tableOptions,
925
+ table: ordersTable,
926
+ filters: withTenant(filtersFromQuery(query)),
927
+ sortColumn: "created_at",
928
+ sortDirection: "desc",
929
+ limit: 500
930
+ });
931
+ return (await hydrate(response.rows)).filter((order) => matchesClientQuery(order, query));
932
+ }
933
+ async function getById(id) {
934
+ const response = await client.data.listRows({
935
+ ...tableOptions,
936
+ table: ordersTable,
937
+ filters: withTenant([{ column: "id", operator: "eq", value: id }]),
938
+ limit: 1
939
+ });
940
+ return (await hydrate(response.rows))[0] ?? null;
941
+ }
942
+ return {
943
+ async getOrders(query) {
944
+ const orders = await listOrders(query);
945
+ return paginate(orders, query.page, query.pageSize);
946
+ },
947
+ async getOrderById(id) {
948
+ return getById(id);
949
+ },
950
+ async createOrder(input) {
951
+ const tenantId = resolveTenant();
952
+ const orderRow = await client.data.createRow({
953
+ ...tableOptions,
954
+ table: ordersTable,
955
+ row: tenantId ? { ...orderPayload(input), tenant_id: tenantId } : orderPayload(input)
956
+ });
957
+ await Promise.all(input.items.map((item, index) => client.data.createRow({
958
+ ...tableOptions,
959
+ table: orderItemsTable,
960
+ row: itemToRow(item, orderRow.id, index)
961
+ })));
962
+ return await getById(orderRow.id) ?? rowToOrder(orderRow);
963
+ },
964
+ async updateOrderStatus(input) {
965
+ const completedAt = input.status === "completed" ? nowIso() : void 0;
966
+ return this.updateOrder(input.orderId, { status: input.status, completedAt });
967
+ },
968
+ async updateOrder(id, data) {
969
+ const row = await client.data.updateRow({
970
+ ...tableOptions,
971
+ table: ordersTable,
972
+ primaryKeys: { id },
973
+ row: updatePayload(data)
974
+ });
975
+ return await getById(row.id) ?? rowToOrder(row);
976
+ },
977
+ async cancelOrder(id, reason) {
978
+ const order = await getById(id);
979
+ await this.updateOrder(id, {
980
+ status: "cancelled",
981
+ notes: reason ? `${order?.notes ? `${order.notes}
982
+ ` : ""}Cancelled: ${reason}` : order?.notes
983
+ });
984
+ },
985
+ async addOrderItem(orderId, item) {
986
+ const order = await getById(orderId);
987
+ const row = await client.data.createRow({
988
+ ...tableOptions,
989
+ table: orderItemsTable,
990
+ row: itemToRow(item, orderId, order?.items.length ?? 0)
991
+ });
992
+ const created = rowToItem(row);
993
+ const items = [...order?.items ?? [], created];
994
+ await this.updateOrder(orderId, {
995
+ subtotal: items.reduce((sum, orderItem) => sum + orderItem.total, 0),
996
+ total: items.reduce((sum, orderItem) => sum + orderItem.total, 0) - (order?.discount ?? 0) + (order?.tax ?? 0)
997
+ });
998
+ return created;
999
+ },
1000
+ async removeOrderItem(itemId) {
1001
+ const orders = await listOrders();
1002
+ const order = orders.find((item) => item.items.some((orderItem) => orderItem.id === itemId));
1003
+ await client.data.deleteRows({ ...tableOptions, table: orderItemsTable, rows: [{ id: itemId }] });
1004
+ if (order) {
1005
+ const items = order.items.filter((item) => item.id !== itemId);
1006
+ const subtotal = items.reduce((sum, item) => sum + item.total, 0);
1007
+ await this.updateOrder(order.id, { subtotal, total: subtotal - order.discount + order.tax });
1008
+ }
1009
+ },
1010
+ async updateOrderItem(itemId, data) {
1011
+ const row = await client.data.updateRow({
1012
+ ...tableOptions,
1013
+ table: orderItemsTable,
1014
+ primaryKeys: { id: itemId },
1015
+ row: {
1016
+ product_id: data.productId,
1017
+ name: data.name,
1018
+ description: data.description,
1019
+ quantity: data.quantity,
1020
+ unit_price: data.unitPrice,
1021
+ discount: data.discount,
1022
+ total: data.total,
1023
+ sort_order: data.sortOrder,
1024
+ modifiers: data.modifiers,
1025
+ kitchen_notes: data.kitchenNotes,
1026
+ metadata: data.metadata
1027
+ }
1028
+ });
1029
+ return rowToItem(row);
1030
+ },
1031
+ async getSummary(dateRange) {
1032
+ return summarize(await listOrders({ dateRange }), dateRange);
1033
+ }
1034
+ };
1035
+ }
1036
+
1037
+ // src/index.ts
1038
+ var OrdersPage = React__default.default.lazy(() => import('./OrdersPage-2IXARHDR.cjs').then((m) => ({ default: m.OrdersPage })));
1039
+ var DEFAULT_LABELS = {
1040
+ pageTitle: "Orders",
1041
+ kanban: "Orders",
1042
+ newOrder: "New Order",
1043
+ orderList: "History"
1044
+ };
1045
+ var DEFAULT_CURRENCY = { code: "BRL", locale: "pt-BR", symbol: "R$" };
1046
+ var DEFAULT_ORDER_SOURCES = [
1047
+ { value: "dine_in", label: "Dine-in", icon: "\u{1F37D}\uFE0F" },
1048
+ { value: "takeout", label: "Takeout", icon: "\u{1F961}" }
1049
+ ];
1050
+ function resolveConfig(options) {
1051
+ return {
1052
+ modules: {
1053
+ delivery: options?.modules?.delivery !== false,
1054
+ takeout: options?.modules?.takeout !== false
1055
+ },
1056
+ labels: { ...DEFAULT_LABELS, ...options?.labels },
1057
+ currency: { ...DEFAULT_CURRENCY, ...options?.currency },
1058
+ orderSources: options?.orderSources ?? DEFAULT_ORDER_SOURCES,
1059
+ menuItemLookup: options?.menuItemLookup,
1060
+ staffLookup: options?.staffLookup,
1061
+ onOrderCompleted: options?.onOrderCompleted
1062
+ };
1063
+ }
1064
+ function createOrdersPlugin(options) {
1065
+ const config = resolveConfig(options);
1066
+ const provider = options?.dataProvider ?? createMockOrdersProvider();
1067
+ const store = createOrdersStore(provider);
1068
+ const PageComponent = () => React__default.default.createElement(
1069
+ React__default.default.Suspense,
1070
+ { fallback: null },
1071
+ React__default.default.createElement(OrdersPage, { config, provider, store, registries: ordersRegistries })
1072
+ );
1073
+ return {
1074
+ id: "orders",
1075
+ name: config.labels.pageTitle,
1076
+ icon: "ClipboardList",
1077
+ version: "1.0.0",
1078
+ scope: options?.scope ?? "vertical",
1079
+ verticalId: options?.verticalId,
1080
+ defaultEnabled: true,
1081
+ dependencies: ["menu"],
1082
+ navigation: [
1083
+ {
1084
+ section: options?.navSection ?? "main",
1085
+ position: options?.navPosition ?? 2,
1086
+ label: config.labels.pageTitle,
1087
+ route: "/orders",
1088
+ icon: "ClipboardList",
1089
+ permission: { feature: "orders", action: "read" }
1090
+ }
1091
+ ],
1092
+ routes: [
1093
+ {
1094
+ path: "/orders",
1095
+ component: PageComponent,
1096
+ permission: { feature: "orders", action: "read" }
1097
+ }
1098
+ ],
1099
+ widgets: [],
1100
+ aiTools: [
1101
+ {
1102
+ id: "orders.today-summary",
1103
+ name: "getOrdersSummary",
1104
+ description: "Returns order count, revenue, and average ticket for today or a given period.",
1105
+ icon: "ClipboardList",
1106
+ mode: "read",
1107
+ category: "Orders",
1108
+ parameters: {
1109
+ type: "object",
1110
+ properties: {
1111
+ period: { type: "string", description: "today, week, month" }
1112
+ }
1113
+ },
1114
+ suggestions: [
1115
+ { label: "How many orders today?" },
1116
+ { label: "What's the average ticket today?" },
1117
+ { label: "What's the most ordered item?" }
1118
+ ]
1119
+ },
1120
+ {
1121
+ id: "orders.active-orders",
1122
+ name: "getActiveOrders",
1123
+ description: "Lists currently active (non-completed) orders.",
1124
+ icon: "Clock",
1125
+ mode: "read",
1126
+ category: "Orders",
1127
+ parameters: {
1128
+ type: "object",
1129
+ properties: {
1130
+ kind: { type: "string", enum: ["dine_in", "takeout", "delivery"] },
1131
+ status: { type: "string", description: "Filter by status" }
1132
+ }
1133
+ },
1134
+ suggestions: [
1135
+ { label: "What orders are being prepared right now?" },
1136
+ { label: "Any delivery orders waiting?" }
1137
+ ]
1138
+ },
1139
+ {
1140
+ id: "orders.create-order",
1141
+ name: "createOrder",
1142
+ description: "Creates a new restaurant order with items.",
1143
+ icon: "PlusCircle",
1144
+ mode: "persist",
1145
+ category: "Orders",
1146
+ parameters: {
1147
+ type: "object",
1148
+ properties: {
1149
+ kind: { type: "string", enum: ["dine_in", "takeout", "delivery"] },
1150
+ tableNumber: { type: "number", description: "Table number (for dine-in)" },
1151
+ items: { type: "array", description: "Item names and quantities" }
1152
+ },
1153
+ required: ["kind", "items"]
1154
+ },
1155
+ permission: { feature: "orders", action: "create" }
1156
+ }
1157
+ ],
1158
+ registries: ordersRegistries,
1159
+ settings: [
1160
+ {
1161
+ id: "orders",
1162
+ label: config.labels.pageTitle,
1163
+ icon: "ClipboardList",
1164
+ component: (() => {
1165
+ const OrdersSettingsTab = () => React__default.default.createElement(saas.PluginSettingsPanel, {
1166
+ title: "Orders Settings",
1167
+ subtitle: "Order sources and preferences",
1168
+ registries: ordersRegistries,
1169
+ routeBase: "/settings/orders"
1170
+ });
1171
+ OrdersSettingsTab.displayName = "OrdersSettingsTab";
1172
+ return OrdersSettingsTab;
1173
+ })(),
1174
+ order: 22,
1175
+ permission: { feature: "orders", action: "read" }
1176
+ }
1177
+ ],
1178
+ locales: ordersLocales
1179
+ };
1180
+ }
1181
+
1182
+ exports.createFayzOrdersProvider = createFayzOrdersProvider;
1183
+ exports.createOrdersPlugin = createOrdersPlugin;
1184
+ //# sourceMappingURL=index.cjs.map
1185
+ //# sourceMappingURL=index.cjs.map