@fayz-ai/plugin-menu 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/{MenuPage-WOI5IELV.js → MenuPage-ZNKKQJKD.js} +4 -4
- package/dist/{MenuPage-WOI5IELV.js.map → MenuPage-ZNKKQJKD.js.map} +1 -1
- package/dist/{MenuContext.d.ts → context.d.ts} +2 -2
- package/dist/context.d.ts.map +1 -0
- package/dist/data/registries.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/{MenuPage.d.ts → views/MenuPage.d.ts} +3 -3
- package/dist/views/MenuPage.d.ts.map +1 -0
- package/package.json +6 -8
- package/dist/MenuContext.d.ts.map +0 -1
- package/dist/MenuPage.d.ts.map +0 -1
- package/dist/registries.d.ts.map +0 -1
- package/src/MenuContext.tsx +0 -40
- package/src/MenuPage.tsx +0 -21
- package/src/data/mock.ts +0 -289
- package/src/data/platform.ts +0 -429
- package/src/data/types.ts +0 -33
- package/src/index.ts +0 -191
- package/src/locales/en.ts +0 -64
- package/src/locales/index.ts +0 -4
- package/src/locales/pt-BR.ts +0 -64
- package/src/registries.ts +0 -84
- package/src/store.ts +0 -161
- package/src/types.ts +0 -145
- package/src/views/MenuManagerView.tsx +0 -694
- /package/dist/{registries.d.ts → data/registries.d.ts} +0 -0
package/src/data/mock.ts
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import type { MenuDataProvider } from './types'
|
|
2
|
-
import type {
|
|
3
|
-
MenuCategory, MenuItem, ModifierGroup,
|
|
4
|
-
CreateMenuItemInput, UpdateMenuItemInput, CreateMenuCategoryInput,
|
|
5
|
-
MenuItemQuery, PaginatedResult, MenuSummary,
|
|
6
|
-
} from '../types'
|
|
7
|
-
|
|
8
|
-
let uid = 0
|
|
9
|
-
function nextId(prefix: string) { return prefix + '-' + (++uid) }
|
|
10
|
-
function now(): string { return new Date().toISOString() }
|
|
11
|
-
|
|
12
|
-
function paginate<T>(items: T[], page?: number, pageSize?: number): PaginatedResult<T> {
|
|
13
|
-
const p = page ?? 1
|
|
14
|
-
const ps = pageSize ?? 50
|
|
15
|
-
const start = (p - 1) * ps
|
|
16
|
-
return { data: items.slice(start, start + ps), total: items.length }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function seedCategories(): MenuCategory[] {
|
|
20
|
-
const t = 'mock-tenant'
|
|
21
|
-
const ts = now()
|
|
22
|
-
return [
|
|
23
|
-
{ id: nextId('cat'), name: 'Burgers', icon: '🍔', color: '#f59e0b', sortOrder: 0, isActive: true, itemCount: 3, tenantId: t, createdAt: ts, updatedAt: ts },
|
|
24
|
-
{ id: nextId('cat'), name: 'Sides', icon: '🍟', color: '#22c55e', sortOrder: 1, isActive: true, itemCount: 3, tenantId: t, createdAt: ts, updatedAt: ts },
|
|
25
|
-
{ id: nextId('cat'), name: 'Drinks', icon: '🥤', color: '#3b82f6', sortOrder: 2, isActive: true, itemCount: 4, tenantId: t, createdAt: ts, updatedAt: ts },
|
|
26
|
-
{ id: nextId('cat'), name: 'Desserts', icon: '🍰', color: '#ec4899', sortOrder: 3, isActive: true, itemCount: 2, tenantId: t, createdAt: ts, updatedAt: ts },
|
|
27
|
-
{ id: nextId('cat'), name: 'Combos', icon: '⭐', color: '#8b5cf6', sortOrder: 4, isActive: true, itemCount: 0, tenantId: t, createdAt: ts, updatedAt: ts },
|
|
28
|
-
]
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function seedItems(categories: MenuCategory[]): MenuItem[] {
|
|
32
|
-
const t = 'mock-tenant'
|
|
33
|
-
const ts = now()
|
|
34
|
-
const [burgers, sides, drinks, desserts] = categories.map((c) => c.id)
|
|
35
|
-
|
|
36
|
-
const item = (
|
|
37
|
-
name: string, price: number, categoryId: string, categoryName: string,
|
|
38
|
-
opts: Partial<MenuItem> = {},
|
|
39
|
-
): MenuItem => ({
|
|
40
|
-
id: nextId('mi'),
|
|
41
|
-
name,
|
|
42
|
-
price,
|
|
43
|
-
currency: 'BRL',
|
|
44
|
-
categoryId,
|
|
45
|
-
categoryName,
|
|
46
|
-
status: 'available',
|
|
47
|
-
isActive: true,
|
|
48
|
-
availableForPos: true,
|
|
49
|
-
availableForDelivery: true,
|
|
50
|
-
sortOrder: 0,
|
|
51
|
-
isFeatured: false,
|
|
52
|
-
tenantId: t,
|
|
53
|
-
createdAt: ts,
|
|
54
|
-
updatedAt: ts,
|
|
55
|
-
...opts,
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
let order = 0
|
|
59
|
-
return [
|
|
60
|
-
item('Classic Burger', 32, burgers, 'Burgers', { prepTimeMinutes: 12, sortOrder: order++, isFeatured: true }),
|
|
61
|
-
item('Cheese Burger', 36, burgers, 'Burgers', { prepTimeMinutes: 12, sortOrder: order++ }),
|
|
62
|
-
item('BBQ Bacon', 42, burgers, 'Burgers', { prepTimeMinutes: 15, sortOrder: order++, isFeatured: true }),
|
|
63
|
-
item('Fries', 15, sides, 'Sides', { prepTimeMinutes: 8, sortOrder: order++ }),
|
|
64
|
-
item('Onion Rings', 18, sides, 'Sides', { prepTimeMinutes: 8, sortOrder: order++ }),
|
|
65
|
-
item('Coleslaw', 12, sides, 'Sides', { prepTimeMinutes: 2, sortOrder: order++, availableForDelivery: false }),
|
|
66
|
-
item('Soda', 8, drinks, 'Drinks', { prepTimeMinutes: 1, sortOrder: order++ }),
|
|
67
|
-
item('Juice', 12, drinks, 'Drinks', { prepTimeMinutes: 3, sortOrder: order++ }),
|
|
68
|
-
item('Water', 5, drinks, 'Drinks', { prepTimeMinutes: 0, sortOrder: order++ }),
|
|
69
|
-
item('Milkshake', 16, drinks, 'Drinks', { prepTimeMinutes: 5, sortOrder: order++, isFeatured: true }),
|
|
70
|
-
item('Brownie', 14, desserts, 'Desserts', { prepTimeMinutes: 1, sortOrder: order++ }),
|
|
71
|
-
item('Ice Cream', 12, desserts, 'Desserts', { prepTimeMinutes: 2, sortOrder: order++, availableForDelivery: false }),
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function seedModifierGroups(): ModifierGroup[] {
|
|
76
|
-
const t = 'mock-tenant'
|
|
77
|
-
const ts = now()
|
|
78
|
-
|
|
79
|
-
const g1Id = nextId('mg')
|
|
80
|
-
const g2Id = nextId('mg')
|
|
81
|
-
|
|
82
|
-
return [
|
|
83
|
-
{
|
|
84
|
-
id: g1Id, name: 'Extra Toppings', minSelections: 0, maxSelections: 3, isRequired: false, sortOrder: 0, tenantId: t, createdAt: ts,
|
|
85
|
-
items: [
|
|
86
|
-
{ id: nextId('mod'), groupId: g1Id, name: 'Extra Cheese', priceAdjustment: 5, isActive: true, sortOrder: 0 },
|
|
87
|
-
{ id: nextId('mod'), groupId: g1Id, name: 'Bacon', priceAdjustment: 7, isActive: true, sortOrder: 1 },
|
|
88
|
-
{ id: nextId('mod'), groupId: g1Id, name: 'Jalapeños', priceAdjustment: 4, isActive: true, sortOrder: 2 },
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
id: g2Id, name: 'Drink Size', minSelections: 1, maxSelections: 1, isRequired: true, sortOrder: 1, tenantId: t, createdAt: ts,
|
|
93
|
-
items: [
|
|
94
|
-
{ id: nextId('mod'), groupId: g2Id, name: 'Small', priceAdjustment: 0, isActive: true, sortOrder: 0 },
|
|
95
|
-
{ id: nextId('mod'), groupId: g2Id, name: 'Medium', priceAdjustment: 3, isActive: true, sortOrder: 1 },
|
|
96
|
-
{ id: nextId('mod'), groupId: g2Id, name: 'Large', priceAdjustment: 5, isActive: true, sortOrder: 2 },
|
|
97
|
-
],
|
|
98
|
-
},
|
|
99
|
-
]
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function createMockMenuProvider(): MenuDataProvider {
|
|
103
|
-
const tenantId = 'mock-tenant'
|
|
104
|
-
const categories = seedCategories()
|
|
105
|
-
const items = seedItems(categories)
|
|
106
|
-
const modifierGroups = seedModifierGroups()
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
async getCategories(): Promise<MenuCategory[]> {
|
|
110
|
-
return [...categories].sort((a, b) => a.sortOrder - b.sortOrder)
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
async getCategoryById(id: string): Promise<MenuCategory | null> {
|
|
114
|
-
return categories.find((c) => c.id === id) ?? null
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
async createCategory(input: CreateMenuCategoryInput): Promise<MenuCategory> {
|
|
118
|
-
const cat: MenuCategory = {
|
|
119
|
-
id: nextId('cat'),
|
|
120
|
-
name: input.name,
|
|
121
|
-
parentId: input.parentId,
|
|
122
|
-
icon: input.icon,
|
|
123
|
-
color: input.color,
|
|
124
|
-
sortOrder: input.sortOrder ?? categories.length,
|
|
125
|
-
isActive: true,
|
|
126
|
-
itemCount: 0,
|
|
127
|
-
tenantId,
|
|
128
|
-
createdAt: now(),
|
|
129
|
-
updatedAt: now(),
|
|
130
|
-
}
|
|
131
|
-
categories.push(cat)
|
|
132
|
-
return cat
|
|
133
|
-
},
|
|
134
|
-
|
|
135
|
-
async updateCategory(id: string, data: Partial<MenuCategory>): Promise<MenuCategory> {
|
|
136
|
-
const cat = categories.find((c) => c.id === id)
|
|
137
|
-
if (!cat) throw new Error(`Category ${id} not found`)
|
|
138
|
-
Object.assign(cat, data, { updatedAt: now() })
|
|
139
|
-
return cat
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
async deleteCategory(id: string): Promise<void> {
|
|
143
|
-
const idx = categories.findIndex((c) => c.id === id)
|
|
144
|
-
if (idx >= 0) categories.splice(idx, 1)
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
async reorderCategories(ids: string[]): Promise<void> {
|
|
148
|
-
ids.forEach((id, i) => {
|
|
149
|
-
const cat = categories.find((c) => c.id === id)
|
|
150
|
-
if (cat) cat.sortOrder = i
|
|
151
|
-
})
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
async getMenuItems(query: MenuItemQuery): Promise<PaginatedResult<MenuItem>> {
|
|
155
|
-
let results = [...items]
|
|
156
|
-
if (query.categoryId) results = results.filter((i) => i.categoryId === query.categoryId)
|
|
157
|
-
if (query.status) {
|
|
158
|
-
const statuses = Array.isArray(query.status) ? query.status : [query.status]
|
|
159
|
-
results = results.filter((i) => statuses.includes(i.status))
|
|
160
|
-
}
|
|
161
|
-
if (query.availableForPos !== undefined) results = results.filter((i) => i.availableForPos === query.availableForPos)
|
|
162
|
-
if (query.availableForDelivery !== undefined) results = results.filter((i) => i.availableForDelivery === query.availableForDelivery)
|
|
163
|
-
if (query.isFeatured !== undefined) results = results.filter((i) => i.isFeatured === query.isFeatured)
|
|
164
|
-
if (query.search) {
|
|
165
|
-
const s = query.search.toLowerCase()
|
|
166
|
-
results = results.filter((i) => i.name.toLowerCase().includes(s) || i.description?.toLowerCase().includes(s))
|
|
167
|
-
}
|
|
168
|
-
results.sort((a, b) => a.sortOrder - b.sortOrder)
|
|
169
|
-
return paginate(results, query.page, query.pageSize)
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
async getMenuItemById(id: string): Promise<MenuItem | null> {
|
|
173
|
-
return items.find((i) => i.id === id) ?? null
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
async createMenuItem(input: CreateMenuItemInput): Promise<MenuItem> {
|
|
177
|
-
const cat = input.categoryId ? categories.find((c) => c.id === input.categoryId) : undefined
|
|
178
|
-
const item: MenuItem = {
|
|
179
|
-
id: nextId('mi'),
|
|
180
|
-
name: input.name,
|
|
181
|
-
description: input.description,
|
|
182
|
-
price: input.price,
|
|
183
|
-
cost: input.cost,
|
|
184
|
-
currency: 'BRL',
|
|
185
|
-
imageUrl: input.imageUrl,
|
|
186
|
-
categoryId: input.categoryId,
|
|
187
|
-
categoryName: cat?.name,
|
|
188
|
-
status: input.status ?? 'available',
|
|
189
|
-
isActive: true,
|
|
190
|
-
prepTimeMinutes: input.prepTimeMinutes,
|
|
191
|
-
allergens: input.allergens,
|
|
192
|
-
dietaryTags: input.dietaryTags,
|
|
193
|
-
availableForPos: input.availableForPos ?? true,
|
|
194
|
-
availableForDelivery: input.availableForDelivery ?? true,
|
|
195
|
-
deliveryPrice: input.deliveryPrice,
|
|
196
|
-
sortOrder: items.length,
|
|
197
|
-
isFeatured: input.isFeatured ?? false,
|
|
198
|
-
modifierGroupIds: input.modifierGroupIds,
|
|
199
|
-
tenantId,
|
|
200
|
-
createdAt: now(),
|
|
201
|
-
updatedAt: now(),
|
|
202
|
-
}
|
|
203
|
-
items.push(item)
|
|
204
|
-
if (cat) cat.itemCount = (cat.itemCount ?? 0) + 1
|
|
205
|
-
return item
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
async updateMenuItem(id: string, data: UpdateMenuItemInput): Promise<MenuItem> {
|
|
209
|
-
const item = items.find((i) => i.id === id)
|
|
210
|
-
if (!item) throw new Error(`MenuItem ${id} not found`)
|
|
211
|
-
Object.assign(item, data, { updatedAt: now() })
|
|
212
|
-
return item
|
|
213
|
-
},
|
|
214
|
-
|
|
215
|
-
async deleteMenuItem(id: string): Promise<void> {
|
|
216
|
-
const idx = items.findIndex((i) => i.id === id)
|
|
217
|
-
if (idx >= 0) {
|
|
218
|
-
const [removed] = items.splice(idx, 1)
|
|
219
|
-
if (removed.categoryId) {
|
|
220
|
-
const cat = categories.find((c) => c.id === removed.categoryId)
|
|
221
|
-
if (cat && cat.itemCount) cat.itemCount--
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
|
|
226
|
-
async toggleAvailability(id: string, field: 'status' | 'availableForPos' | 'availableForDelivery', value: any): Promise<MenuItem> {
|
|
227
|
-
const item = items.find((i) => i.id === id)
|
|
228
|
-
if (!item) throw new Error(`MenuItem ${id} not found`)
|
|
229
|
-
;(item as any)[field] = value
|
|
230
|
-
item.updatedAt = now()
|
|
231
|
-
return item
|
|
232
|
-
},
|
|
233
|
-
|
|
234
|
-
async reorderItems(categoryId: string, ids: string[]): Promise<void> {
|
|
235
|
-
ids.forEach((id, i) => {
|
|
236
|
-
const item = items.find((it) => it.id === id && it.categoryId === categoryId)
|
|
237
|
-
if (item) item.sortOrder = i
|
|
238
|
-
})
|
|
239
|
-
},
|
|
240
|
-
|
|
241
|
-
async getModifierGroups(): Promise<ModifierGroup[]> {
|
|
242
|
-
return [...modifierGroups].sort((a, b) => a.sortOrder - b.sortOrder)
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
async createModifierGroup(input: Partial<ModifierGroup>): Promise<ModifierGroup> {
|
|
246
|
-
const group: ModifierGroup = {
|
|
247
|
-
id: nextId('mg'),
|
|
248
|
-
name: input.name ?? '',
|
|
249
|
-
minSelections: input.minSelections ?? 0,
|
|
250
|
-
maxSelections: input.maxSelections ?? 1,
|
|
251
|
-
isRequired: input.isRequired ?? false,
|
|
252
|
-
sortOrder: input.sortOrder ?? modifierGroups.length,
|
|
253
|
-
items: input.items ?? [],
|
|
254
|
-
tenantId,
|
|
255
|
-
createdAt: now(),
|
|
256
|
-
}
|
|
257
|
-
modifierGroups.push(group)
|
|
258
|
-
return group
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
async updateModifierGroup(id: string, data: Partial<ModifierGroup>): Promise<ModifierGroup> {
|
|
262
|
-
const group = modifierGroups.find((g) => g.id === id)
|
|
263
|
-
if (!group) throw new Error(`ModifierGroup ${id} not found`)
|
|
264
|
-
Object.assign(group, data)
|
|
265
|
-
return group
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
async deleteModifierGroup(id: string): Promise<void> {
|
|
269
|
-
const idx = modifierGroups.findIndex((g) => g.id === id)
|
|
270
|
-
if (idx >= 0) modifierGroups.splice(idx, 1)
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
async getSummary(): Promise<MenuSummary> {
|
|
274
|
-
const available = items.filter((i) => i.status === 'available')
|
|
275
|
-
const soldOut = items.filter((i) => i.status === 'sold_out')
|
|
276
|
-
const hidden = items.filter((i) => i.status === 'hidden')
|
|
277
|
-
const prices = items.filter((i) => i.price > 0).map((i) => i.price)
|
|
278
|
-
return {
|
|
279
|
-
totalItems: items.length,
|
|
280
|
-
availableItems: available.length,
|
|
281
|
-
soldOutItems: soldOut.length,
|
|
282
|
-
hiddenItems: hidden.length,
|
|
283
|
-
categoryCount: categories.length,
|
|
284
|
-
averagePrice: prices.length ? prices.reduce((a, b) => a + b, 0) / prices.length : 0,
|
|
285
|
-
featuredCount: items.filter((i) => i.isFeatured).length,
|
|
286
|
-
}
|
|
287
|
-
},
|
|
288
|
-
}
|
|
289
|
-
}
|