@fayz-ai/plugin-menu 0.3.0 → 0.9.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/{MenuPage-OABV6JYB.js → MenuPage-WOI5IELV.js} +6 -3
- package/dist/MenuPage-WOI5IELV.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/views/MenuManagerView.d.ts.map +1 -1
- package/package.json +19 -13
- package/src/index.ts +7 -0
- package/src/types.ts +2 -2
- package/src/views/MenuManagerView.tsx +6 -0
- package/dist/MenuPage-OABV6JYB.js.map +0 -1
- package/dist/MenuPage-VMI2YAPY.cjs +0 -522
- package/dist/MenuPage-VMI2YAPY.cjs.map +0 -1
- package/dist/index.cjs +0 -1053
- package/dist/index.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@fayz-ai/plugin-menu)
|
|
6
6
|
[](https://github.com/FayaLabs/fayz-sdk/blob/main/LICENSE)
|
|
7
7
|
|
|
8
|
+
**Status:** beta — pre-1.0. Core surface is stable; some backend facets (see `PLUGIN_PATTERNS.md`) are still landing. APIs may change before 1.0.
|
|
9
|
+
|
|
8
10
|
A menu is the product catalog of a food business — and it changes by the hour. `plugin-menu` is the management surface for that: items, categories, allergens, and modifiers, with sold-out toggles that take effect instantly. It's the foundation the orders flow reads from, so the two compose into a working restaurant.
|
|
9
11
|
|
|
10
12
|
It's provider-first by design. Ship a demo on the bundled mock provider, then drop in `createFayzMenuProvider` (or your own `MenuDataProvider`) for real data. Modifiers and delivery pricing are opt-in modules, labels and currency are configurable, and the host AI can list items and flip availability by name. The intent: menu management shouldn't be a bespoke build — it's a plugin you snap into a `defineSaas` app to compose a real food SaaS.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createPluginContext, formatCurrency } from '@fayz-ai/saas';
|
|
1
|
+
import { createPluginContext, formatCurrency, useLimitGuard, invalidateLimit } from '@fayz-ai/saas';
|
|
2
2
|
import { useState, useEffect, useMemo } from 'react';
|
|
3
3
|
import { Loader2, Plus, Search, UtensilsCrossed, GripVertical, ChevronDown, ChevronRight, MoreHorizontal, Star } from 'lucide-react';
|
|
4
4
|
import { Modal, ModalContent, ModalHeader, ModalTitle, ModalBody, Input, ModalFooter, Button, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '@fayz-ai/ui';
|
|
@@ -66,6 +66,7 @@ function ItemModal({
|
|
|
66
66
|
const t = useTranslation();
|
|
67
67
|
const config = useMenuConfig();
|
|
68
68
|
const createMenuItem = useMenuStore((s) => s.createMenuItem);
|
|
69
|
+
const guardMenuItems = useLimitGuard("menu_items");
|
|
69
70
|
const [name, setName] = useState("");
|
|
70
71
|
const [price, setPrice] = useState("");
|
|
71
72
|
const [categoryId, setCategoryId] = useState(defaultCategoryId ?? UNCATEGORIZED);
|
|
@@ -73,6 +74,7 @@ function ItemModal({
|
|
|
73
74
|
const [saving, setSaving] = useState(false);
|
|
74
75
|
const submit = async () => {
|
|
75
76
|
if (!name.trim()) return;
|
|
77
|
+
if (await guardMenuItems() === "blocked") return;
|
|
76
78
|
setSaving(true);
|
|
77
79
|
try {
|
|
78
80
|
await createMenuItem({
|
|
@@ -81,6 +83,7 @@ function ItemModal({
|
|
|
81
83
|
categoryId: categoryId === UNCATEGORIZED ? void 0 : categoryId,
|
|
82
84
|
description: description.trim() || void 0
|
|
83
85
|
});
|
|
86
|
+
invalidateLimit("menu_items");
|
|
84
87
|
onClose();
|
|
85
88
|
} catch {
|
|
86
89
|
} finally {
|
|
@@ -516,5 +519,5 @@ function MenuPage({ config, provider, store, registries }) {
|
|
|
516
519
|
}
|
|
517
520
|
|
|
518
521
|
export { MenuPage };
|
|
519
|
-
//# sourceMappingURL=MenuPage-
|
|
520
|
-
//# sourceMappingURL=MenuPage-
|
|
522
|
+
//# sourceMappingURL=MenuPage-WOI5IELV.js.map
|
|
523
|
+
//# sourceMappingURL=MenuPage-WOI5IELV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/MenuContext.tsx","../src/views/MenuManagerView.tsx","../src/MenuPage.tsx"],"names":["jsx"],"mappings":"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","file":"MenuPage-WOI5IELV.js","sourcesContent":["import { createPluginContext, formatCurrency, type CurrencyConfig } from '@fayz-ai/saas'\nimport type { MenuDataProvider } from './data/types'\nimport type { MenuUIState } from './store'\n\n// ---------------------------------------------------------------------------\n// Labels\n// ---------------------------------------------------------------------------\n\nexport interface MenuPluginLabels {\n pageTitle: string\n menuManager: string\n categories: string\n newItem: string\n}\n\n// ---------------------------------------------------------------------------\n// Resolved config — fully merged, no optionals\n// ---------------------------------------------------------------------------\n\nexport interface MenuModules {\n modifiers: boolean\n deliveryPricing: boolean\n}\n\nexport type MenuCurrency = CurrencyConfig\n\nexport interface ResolvedMenuConfig {\n modules: MenuModules\n labels: MenuPluginLabels\n currency: MenuCurrency\n}\n\nconst ctx = createPluginContext<ResolvedMenuConfig, MenuDataProvider, MenuUIState>('MenuPage')\n\nexport const MenuContextProvider = ctx.ContextProvider\nexport const useMenuConfig = ctx.useConfig\nexport const useMenuProvider = ctx.useProvider\nexport const useMenuStore = ctx.useStore\n\nexport { formatCurrency }\n","import React, { useEffect, useMemo, useState } from 'react'\nimport {\n Plus,\n Search,\n GripVertical,\n ChevronDown,\n ChevronRight,\n MoreHorizontal,\n Star,\n Loader2,\n UtensilsCrossed,\n} from 'lucide-react'\nimport {\n Modal, ModalContent, ModalHeader, ModalTitle, ModalBody, ModalFooter,\n Button, Input,\n Select, SelectTrigger, SelectValue, SelectContent, SelectItem,\n} from '@fayz-ai/ui'\nimport { useMenuConfig, useMenuStore, formatCurrency } from '../MenuContext'\nimport { useTranslation } from '@fayz-ai/core'\nimport { useLimitGuard, invalidateLimit } from '@fayz-ai/saas'\nimport type { MenuCategory, MenuItem } from '../types'\n\n// ---------------------------------------------------------------------------\n// Create forms (category / item) — design-system Modal\n// ---------------------------------------------------------------------------\n\nconst UNCATEGORIZED = '__none'\nconst fieldLabel = 'text-sm font-medium text-foreground'\n\nfunction CategoryModal({ open, onClose }: { open: boolean; onClose: () => void }) {\n const t = useTranslation()\n const createCategory = useMenuStore((s) => s.createCategory)\n const [name, setName] = useState('')\n const [saving, setSaving] = useState(false)\n\n const submit = async () => {\n if (!name.trim()) return\n setSaving(true)\n try {\n await createCategory({ name: name.trim() })\n setName('')\n onClose()\n } catch {\n // store surfaces a toast on failure\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Modal open={open} onOpenChange={(o) => { if (!o) onClose() }}>\n <ModalContent size=\"sm\">\n <ModalHeader>\n <ModalTitle>{t('menu.manager.addCategory')}</ModalTitle>\n </ModalHeader>\n <ModalBody className=\"space-y-4\">\n <label className=\"block space-y-1.5\">\n <span className={fieldLabel}>{t('menu.form.categoryName')}</span>\n <Input\n autoFocus\n value={name}\n onChange={(e) => setName(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Enter') submit() }}\n />\n </label>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"outline\" onClick={onClose}>{t('menu.form.cancel')}</Button>\n <Button onClick={submit} disabled={saving || !name.trim()}>\n {saving && <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />}\n {t('menu.form.save')}\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n )\n}\n\nfunction ItemModal({\n open,\n categories,\n defaultCategoryId,\n onClose,\n}: {\n open: boolean\n categories: MenuCategory[]\n defaultCategoryId?: string\n onClose: () => void\n}) {\n const t = useTranslation()\n const config = useMenuConfig()\n const createMenuItem = useMenuStore((s) => s.createMenuItem)\n const guardMenuItems = useLimitGuard('menu_items')\n const [name, setName] = useState('')\n const [price, setPrice] = useState('')\n const [categoryId, setCategoryId] = useState(defaultCategoryId ?? UNCATEGORIZED)\n const [description, setDescription] = useState('')\n const [saving, setSaving] = useState(false)\n\n const submit = async () => {\n if (!name.trim()) return\n // Client-side plan guard before the store create. (Note: this dialog also\n // has the known board bug B29 — out of scope here, guard only.)\n if ((await guardMenuItems()) === 'blocked') return\n setSaving(true)\n try {\n await createMenuItem({\n name: name.trim(),\n price: Number(price) || 0,\n categoryId: categoryId === UNCATEGORIZED ? undefined : categoryId,\n description: description.trim() || undefined,\n })\n invalidateLimit('menu_items')\n onClose()\n } catch {\n // store surfaces a toast on failure\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Modal open={open} onOpenChange={(o) => { if (!o) onClose() }}>\n <ModalContent size=\"md\">\n <ModalHeader>\n <ModalTitle>{t('menu.manager.addProduct')}</ModalTitle>\n </ModalHeader>\n <ModalBody className=\"space-y-4\">\n <label className=\"block space-y-1.5\">\n <span className={fieldLabel}>{t('menu.form.itemName')}</span>\n <Input autoFocus value={name} onChange={(e) => setName(e.target.value)} />\n </label>\n <div className=\"grid grid-cols-2 gap-3\">\n <label className=\"block space-y-1.5\">\n <span className={fieldLabel}>{t('menu.manager.price')} ({config.currency.symbol})</span>\n <Input\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={price}\n onChange={(e) => setPrice(e.target.value)}\n placeholder=\"0\"\n />\n </label>\n <label className=\"block space-y-1.5\">\n <span className={fieldLabel}>{t('menu.form.category')}</span>\n <Select value={categoryId} onValueChange={setCategoryId}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value={UNCATEGORIZED}>{t('menu.form.uncategorized')}</SelectItem>\n {categories.map((cat) => (\n <SelectItem key={cat.id} value={cat.id}>{cat.name}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </label>\n </div>\n <label className=\"block space-y-1.5\">\n <span className={fieldLabel}>\n {t('menu.form.description')}{' '}\n <span className=\"text-muted-foreground font-normal\">({t('menu.form.optional')})</span>\n </span>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n className=\"w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n </label>\n </ModalBody>\n <ModalFooter>\n <Button variant=\"outline\" onClick={onClose}>{t('menu.form.cancel')}</Button>\n <Button onClick={submit} disabled={saving || !name.trim()}>\n {saving && <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />}\n {t('menu.form.save')}\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Toggle — inline switch component\n// ---------------------------------------------------------------------------\n\nfunction Toggle({\n checked,\n onChange,\n size = 'sm',\n}: {\n checked: boolean\n onChange: (v: boolean) => void\n size?: 'sm' | 'xs'\n}) {\n const h = size === 'xs' ? 'h-4 w-7' : 'h-5 w-9'\n const dot = size === 'xs' ? 'h-3 w-3' : 'h-4 w-4'\n const translate = size === 'xs' ? 'translate-x-[13px]' : 'translate-x-[18px]'\n return (\n <button\n type=\"button\"\n onClick={() => onChange(!checked)}\n className={`relative inline-flex ${h} items-center rounded-full transition-colors ${\n checked ? 'bg-primary' : 'bg-muted-foreground/30'\n }`}\n >\n <span\n className={`pointer-events-none block ${dot} rounded-full bg-white shadow-sm transition-transform ${\n checked ? translate : 'translate-x-[2px]'\n }`}\n />\n </button>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton loader\n// ---------------------------------------------------------------------------\n\nfunction CategorySkeleton() {\n return (\n <div className=\"rounded-lg border bg-card animate-pulse\">\n <div className=\"flex items-center gap-3 px-4 py-3\">\n <div className=\"h-4 w-4 rounded bg-muted\" />\n <div className=\"h-4 w-4 rounded bg-muted\" />\n <div className=\"h-4 w-32 rounded bg-muted flex-1\" />\n <div className=\"h-4 w-16 rounded bg-muted\" />\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Category section\n// ---------------------------------------------------------------------------\n\nfunction CategorySection({\n category,\n items,\n expanded,\n onToggle,\n onAddProduct,\n}: {\n category: MenuCategory\n items: MenuItem[]\n expanded: boolean\n onToggle: () => void\n onAddProduct: () => void\n}) {\n const t = useTranslation()\n const config = useMenuConfig()\n const toggleAvailability = useMenuStore((s) => s.toggleAvailability)\n\n const handleToggle = async (\n id: string,\n field: 'availableForPos' | 'availableForDelivery',\n current: boolean,\n ) => {\n await toggleAvailability(id, field, !current)\n }\n\n const handleFeatureToggle = async (id: string, current: boolean) => {\n await toggleAvailability(id, 'isFeatured' as any, !current)\n }\n\n return (\n <div className=\"rounded-lg border bg-card\">\n {/* Category header */}\n <div className=\"flex items-center gap-3 px-4 py-3\">\n <GripVertical className=\"h-4 w-4 text-muted-foreground/40 cursor-grab\" />\n <button type=\"button\" onClick={onToggle} className=\"p-0.5\">\n {expanded ? (\n <ChevronDown className=\"h-4 w-4\" />\n ) : (\n <ChevronRight className=\"h-4 w-4\" />\n )}\n </button>\n <h3 className=\"text-sm font-semibold flex-1\">{category.name}</h3>\n <div className=\"flex items-center gap-4 text-xs text-muted-foreground\">\n <span>{t('menu.manager.itemsCount', { count: items.length })}</span>\n </div>\n <button className=\"p-1 text-muted-foreground hover:text-foreground rounded\">\n <MoreHorizontal className=\"h-4 w-4\" />\n </button>\n </div>\n\n {expanded && (\n <>\n {/* Add product button */}\n <div className=\"px-4 pb-2\">\n <button\n type=\"button\"\n onClick={onAddProduct}\n className=\"flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground border border-dashed rounded-md px-3 py-1.5 hover:bg-muted/30 transition-colors\"\n >\n <Plus className=\"h-3 w-3\" />\n {t('menu.manager.addProduct')}\n </button>\n </div>\n\n {/* Items table */}\n {/* drift-allow: raw-table — interactive cells (drag handles, availability toggles, inline price/feature controls) don't fit DataTable */}\n {items.length > 0 ? (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-t bg-muted/30 text-[10px] uppercase tracking-wider text-muted-foreground\">\n <th className=\"text-left py-2 pl-4 pr-2 font-medium\">\n {t('menu.manager.item')}\n </th>\n <th className=\"py-2 px-2 font-medium text-center w-16\">\n {t('menu.manager.pos')}\n </th>\n <th className=\"py-2 px-2 font-medium text-center w-16\">\n {t('menu.manager.delivery')}\n </th>\n <th className=\"py-2 px-2 font-medium text-center w-28\">\n {t('menu.manager.price')}\n </th>\n {config.modules.deliveryPricing && (\n <th className=\"py-2 px-2 font-medium text-center w-28\">\n {t('menu.manager.deliveryPrice')}\n </th>\n )}\n <th className=\"py-2 px-2 font-medium text-center w-16\">\n {t('menu.manager.featured')}\n </th>\n <th className=\"py-2 pr-4 w-8\" />\n </tr>\n </thead>\n <tbody className=\"divide-y\">\n {items.map((item) => (\n <tr\n key={item.id}\n className=\"hover:bg-muted/20 transition-colors\"\n >\n <td className=\"py-2.5 pl-4 pr-2\">\n <div className=\"flex items-center gap-3\">\n <GripVertical className=\"h-3.5 w-3.5 text-muted-foreground/30 cursor-grab shrink-0\" />\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted/50 overflow-hidden\">\n {item.imageUrl ? (\n <img\n src={item.imageUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <UtensilsCrossed className=\"h-4 w-4 text-muted-foreground/40\" />\n )}\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {item.name}\n </p>\n {item.description && (\n <p className=\"text-xs text-muted-foreground truncate max-w-[280px]\">\n {item.description}\n </p>\n )}\n </div>\n </div>\n </td>\n <td className=\"py-2.5 px-2 text-center\">\n <Toggle\n checked={item.availableForPos}\n onChange={() =>\n handleToggle(\n item.id,\n 'availableForPos',\n item.availableForPos,\n )\n }\n size=\"xs\"\n />\n </td>\n <td className=\"py-2.5 px-2 text-center\">\n <Toggle\n checked={item.availableForDelivery}\n onChange={() =>\n handleToggle(\n item.id,\n 'availableForDelivery',\n item.availableForDelivery,\n )\n }\n size=\"xs\"\n />\n </td>\n <td className=\"py-2.5 px-2 text-center\">\n <span className=\"text-sm font-medium\">\n {formatCurrency(item.price, config.currency)}\n </span>\n </td>\n {config.modules.deliveryPricing && (\n <td className=\"py-2.5 px-2 text-center\">\n <span className=\"text-sm text-muted-foreground\">\n {item.deliveryPrice != null\n ? formatCurrency(\n item.deliveryPrice,\n config.currency,\n )\n : '\\u2014'}\n </span>\n </td>\n )}\n <td className=\"py-2.5 px-2 text-center\">\n <button\n onClick={() =>\n handleFeatureToggle(item.id, item.isFeatured)\n }\n className={`p-1 rounded ${\n item.isFeatured\n ? 'text-amber-500'\n : 'text-muted-foreground/30 hover:text-muted-foreground'\n }`}\n >\n <Star\n className={`h-4 w-4 ${\n item.isFeatured ? 'fill-current' : ''\n }`}\n />\n </button>\n </td>\n <td className=\"py-2.5 pr-4\">\n <button className=\"p-1 text-muted-foreground hover:text-foreground rounded\">\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <div className=\"border-t px-4 py-6 text-center text-xs text-muted-foreground\">\n {t('menu.manager.noItems')}\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Main view\n// ---------------------------------------------------------------------------\n\nexport function MenuManagerView() {\n const t = useTranslation()\n const config = useMenuConfig()\n\n const categories = useMenuStore((s) => s.categories)\n const categoriesLoading = useMenuStore((s) => s.categoriesLoading)\n const menuItems = useMenuStore((s) => s.menuItems)\n const menuItemsLoading = useMenuStore((s) => s.menuItemsLoading)\n const fetchCategories = useMenuStore((s) => s.fetchCategories)\n const fetchMenuItems = useMenuStore((s) => s.fetchMenuItems)\n\n const [expandedCategories, setExpandedCategories] = useState<Set<string>>(\n new Set(),\n )\n const [search, setSearch] = useState('')\n const [categoryFilter, setCategoryFilter] = useState('all')\n const [showCategoryModal, setShowCategoryModal] = useState(false)\n const [showItemModal, setShowItemModal] = useState(false)\n const [itemModalCategory, setItemModalCategory] = useState<string | undefined>(undefined)\n\n const openItemModal = (categoryId?: string) => {\n setItemModalCategory(categoryId)\n setShowItemModal(true)\n }\n\n // ---- Load data on mount ----\n useEffect(() => {\n fetchCategories()\n fetchMenuItems({})\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // ---- Expand all once categories load ----\n useEffect(() => {\n if (categories.length > 0 && expandedCategories.size === 0) {\n setExpandedCategories(new Set(categories.map((c) => c.id)))\n }\n }, [categories]) // eslint-disable-line react-hooks/exhaustive-deps\n\n // ---- Group items by categoryId ----\n const grouped = useMemo(() => {\n const map = new Map<string, MenuItem[]>()\n for (const item of menuItems) {\n const key = item.categoryId ?? '__uncategorized'\n const list = map.get(key) ?? []\n list.push(item)\n map.set(key, list)\n }\n return map\n }, [menuItems])\n\n // ---- Client-side filtering ----\n const filteredCategories = useMemo(() => {\n const lowerSearch = search.toLowerCase()\n\n return categories.filter((cat) => {\n // Category dropdown filter\n if (categoryFilter !== 'all' && cat.id !== categoryFilter) return false\n\n // Search filter — match category items by name or description\n if (lowerSearch) {\n const items = grouped.get(cat.id) ?? []\n return items.some(\n (item) =>\n item.name.toLowerCase().includes(lowerSearch) ||\n (item.description?.toLowerCase().includes(lowerSearch) ?? false),\n )\n }\n return true\n })\n }, [categories, categoryFilter, search, grouped])\n\n // Get filtered items for a category (applying search within it)\n const getFilteredItems = (categoryId: string): MenuItem[] => {\n const items = grouped.get(categoryId) ?? []\n if (!search) return items\n const lowerSearch = search.toLowerCase()\n return items.filter(\n (item) =>\n item.name.toLowerCase().includes(lowerSearch) ||\n (item.description?.toLowerCase().includes(lowerSearch) ?? false),\n )\n }\n\n const toggleCategory = (id: string) => {\n setExpandedCategories((prev) => {\n const next = new Set(prev)\n next.has(id) ? next.delete(id) : next.add(id)\n return next\n })\n }\n\n const isLoading = categoriesLoading || menuItemsLoading\n\n // ---- Loading skeleton ----\n if (isLoading && categories.length === 0) {\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"h-7 w-40 rounded bg-muted animate-pulse\" />\n <div className=\"h-4 w-64 rounded bg-muted animate-pulse mt-2\" />\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"h-9 w-40 rounded bg-muted animate-pulse\" />\n <div className=\"h-9 flex-1 max-w-sm rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"space-y-3\">\n <CategorySkeleton />\n <CategorySkeleton />\n <CategorySkeleton />\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold\">{t('menu.manager.title')}</h1>\n <p className=\"text-sm text-muted-foreground\">\n {t('menu.manager.subtitle')}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n {isLoading && (\n <Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\" />\n )}\n <button\n type=\"button\"\n onClick={() => setShowCategoryModal(true)}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-muted/50 transition-colors\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('menu.manager.addCategory')}\n </button>\n <button\n type=\"button\"\n onClick={() => openItemModal(undefined)}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('menu.manager.addProduct')}\n </button>\n </div>\n </div>\n\n {/* Filters */}\n <div className=\"flex items-center gap-3\">\n <select\n value={categoryFilter}\n onChange={(e) => setCategoryFilter(e.target.value)}\n className=\"h-9 rounded-md border border-input bg-background px-3 text-sm\"\n >\n <option value=\"all\">{t('menu.manager.allCategories')}</option>\n {categories.map((cat) => (\n <option key={cat.id} value={cat.id}>\n {cat.name}\n </option>\n ))}\n </select>\n <div className=\"relative flex-1 max-w-sm\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={t('menu.manager.search')}\n className=\"h-9 w-full rounded-md border border-input bg-background pl-9 pr-3 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n </div>\n </div>\n\n {/* Categories */}\n <div className=\"space-y-3\">\n {filteredCategories.map((category) => (\n <CategorySection\n key={category.id}\n category={category}\n items={getFilteredItems(category.id)}\n expanded={expandedCategories.has(category.id)}\n onToggle={() => toggleCategory(category.id)}\n onAddProduct={() => openItemModal(category.id)}\n />\n ))}\n </div>\n\n {/* Empty state — no results after filtering */}\n {filteredCategories.length === 0 && !isLoading && (\n <div className=\"text-center py-12\">\n {categories.length === 0 ? (\n <>\n <UtensilsCrossed className=\"mx-auto h-10 w-10 text-muted-foreground/40 mb-3\" />\n <p className=\"text-sm font-medium\">{t('menu.manager.noItems')}</p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t('menu.manager.noItemsDesc')}\n </p>\n <div className=\"mt-4 flex items-center justify-center gap-2\">\n <button\n type=\"button\"\n onClick={() => setShowCategoryModal(true)}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm hover:bg-muted/50\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('menu.manager.addCategory')}\n </button>\n <button\n type=\"button\"\n onClick={() => openItemModal(undefined)}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('menu.manager.addProduct')}\n </button>\n </div>\n </>\n ) : (\n <>\n <Search className=\"mx-auto h-10 w-10 text-muted-foreground/40 mb-3\" />\n <p className=\"text-sm font-medium\">\n {t('menu.manager.noResults')}\n </p>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t('menu.manager.noResultsDesc')}\n </p>\n </>\n )}\n </div>\n )}\n\n {showCategoryModal && (\n <CategoryModal open onClose={() => setShowCategoryModal(false)} />\n )}\n {showItemModal && (\n <ItemModal\n open\n categories={categories}\n defaultCategoryId={itemModalCategory}\n onClose={() => setShowItemModal(false)}\n />\n )}\n </div>\n )\n}\n","import React from 'react'\nimport type { StoreApi } from 'zustand/vanilla'\nimport { MenuContextProvider, type ResolvedMenuConfig } from './MenuContext'\nimport type { MenuDataProvider } from './data/types'\nimport type { MenuUIState } from './store'\nimport type { PluginRegistryDef } from '@fayz-ai/core'\n\nimport { MenuManagerView } from './views/MenuManagerView'\n\nexport function MenuPage({ config, provider, store, registries }: {\n config: ResolvedMenuConfig\n provider: MenuDataProvider\n store: StoreApi<MenuUIState>\n registries?: PluginRegistryDef[]\n}) {\n return (\n <MenuContextProvider config={config} provider={provider} store={store}>\n <MenuManagerView />\n </MenuContextProvider>\n )\n}\n"]}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAcpD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;CAChB;AAmBD,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,eAAe,CAAC,EAAE,OAAO,CAAA;KAC1B,CAAA;IACD,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAClC,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,YAAY,CAAC,EAAE,gBAAgB,CAAA;IAC/B,cAAc,CAAC,EAAE,YAAY,CAAA;CAC9B;AAqBD,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAcpD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;CAChB;AAmBD,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,eAAe,CAAC,EAAE,OAAO,CAAA;KAC1B,CAAA;IACD,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAClC,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,YAAY,CAAC,EAAE,gBAAgB,CAAA;IAC/B,cAAc,CAAC,EAAE,YAAY,CAAA;CAC9B;AAqBD,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,cAAc,CA0G5E;AAED,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAGvD,mBAAmB,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -924,7 +924,7 @@ function createFayzMenuProvider(options = {}) {
|
|
|
924
924
|
}
|
|
925
925
|
|
|
926
926
|
// src/index.ts
|
|
927
|
-
var MenuPage = React.lazy(() => import('./MenuPage-
|
|
927
|
+
var MenuPage = React.lazy(() => import('./MenuPage-WOI5IELV.js').then((m) => ({ default: m.MenuPage })));
|
|
928
928
|
var DEFAULT_LABELS = {
|
|
929
929
|
pageTitle: "Menu",
|
|
930
930
|
menuManager: "Menu Manager",
|
|
@@ -959,8 +959,15 @@ function createMenuPlugin(options) {
|
|
|
959
959
|
version: "1.0.0",
|
|
960
960
|
scope: options?.scope ?? "vertical",
|
|
961
961
|
verticalId: options?.verticalId,
|
|
962
|
+
// Digital menu serves both internal ops (saas) and online ordering
|
|
963
|
+
// (ecommerce) — genuinely dual-surface, low confidence, revisit if a
|
|
964
|
+
// real host disagrees.
|
|
965
|
+
scaffolds: ["saas", "ecommerce"],
|
|
962
966
|
defaultEnabled: true,
|
|
963
967
|
dependencies: [],
|
|
968
|
+
declaredLimits: [
|
|
969
|
+
{ key: "menu_items", label: "Menu items", table: "menu_items" }
|
|
970
|
+
],
|
|
964
971
|
navigation: [
|
|
965
972
|
{
|
|
966
973
|
section: options?.navSection ?? "main",
|