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