@fayz-ai/plugin-automations 0.9.0 → 0.9.1
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 +4 -4
- package/dist/data/templates.d.ts +9 -0
- package/dist/data/templates.d.ts.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +561 -108
- package/dist/index.js.map +1 -1
- package/dist/lib/runtime.d.ts +4 -0
- package/dist/lib/runtime.d.ts.map +1 -0
- package/dist/views/AutomationDetailPage.d.ts +12 -0
- package/dist/views/AutomationDetailPage.d.ts.map +1 -0
- package/dist/views/AutomationsList.d.ts +6 -0
- package/dist/views/AutomationsList.d.ts.map +1 -0
- package/dist/views/RunLog.d.ts +8 -0
- package/dist/views/RunLog.d.ts.map +1 -0
- package/package.json +5 -6
- package/dist/views/AutomationsHome.d.ts +0 -3
- package/dist/views/AutomationsHome.d.ts.map +0 -1
- package/src/index.ts +0 -52
- package/src/views/AutomationsHome.tsx +0 -112
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/views/AutomationsHome.tsx","../src/index.ts"],"names":["React"],"mappings":";;;;;;AAaA,IAAM,SAAA,GAAwB;AAAA,EAC5B;AAAA,IACE,EAAA,EAAI,GAAA;AAAA,IAAK,IAAA,EAAM,yBAAA;AAAA,IAAsB,OAAA,EAAS,gBAAA;AAAA,IAAkB,QAAA,EAAU,GAAA;AAAA,IAAK,MAAA,EAAQ,IAAA;AAAA,IACvF,KAAA,EAAO;AAAA,MACL,EAAE,IAAA,EAAM,aAAA,EAAe,KAAA,EAAO,UAAA,EAAW;AAAA,MACzC,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,YAAA,EAAa;AAAA,MACnC,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAO,YAAA,EAAa;AAAA,MAClC,EAAE,IAAA,EAAM,GAAA,EAAK,KAAA,EAAO,gBAAA;AAAiB;AACvC,GACF;AAAA,EACA;AAAA,IACE,EAAA,EAAI,GAAA;AAAA,IAAK,IAAA,EAAM,uBAAA;AAAA,IAAyB,OAAA,EAAS,aAAA;AAAA,IAAe,QAAA,EAAU,GAAA;AAAA,IAAK,MAAA,EAAQ,IAAA;AAAA,IACvF,KAAA,EAAO;AAAA,MACL,EAAE,IAAA,EAAM,aAAA,EAAe,KAAA,EAAO,WAAA,EAAY;AAAA,MAC1C,EAAE,IAAA,EAAM,GAAA,EAAK,KAAA,EAAO,aAAA;AAAc;AACpC,GACF;AAAA,EACA;AAAA,IACE,EAAA,EAAI,GAAA;AAAA,IAAK,IAAA,EAAM,sBAAA;AAAA,IAAwB,OAAA,EAAS,oBAAA;AAAA,IAAsB,QAAA,EAAU,EAAA;AAAA,IAAI,MAAA,EAAQ,IAAA;AAAA,IAC5F,KAAA,EAAO;AAAA,MACL,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,uBAAA,EAAwB;AAAA,MAC9C,EAAE,IAAA,EAAM,aAAA,EAAe,KAAA,EAAO,mBAAA;AAAoB;AACpD,GACF;AAAA,EACA;AAAA,IACE,EAAA,EAAI,GAAA;AAAA,IAAK,IAAA,EAAM,gCAAA;AAAA,IAA6B,OAAA,EAAS,iBAAA;AAAA,IAAmB,QAAA,EAAU,EAAA;AAAA,IAAI,MAAA,EAAQ,KAAA;AAAA,IAC9F,KAAA,EAAO;AAAA,MACL,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,aAAA,EAAc;AAAA,MACpC,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAO,gBAAA;AAAiB;AACxC;AAEJ,CAAA;AAEA,SAAS,IAAA,CAAK,EAAE,KAAA,EAAO,KAAA,EAAM,EAAqC;AAChE,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+CAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,2CAAA,EAA6C,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,oBAChE,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,6CAAA,EAA+C,QAAA,EAAA,KAAA,EAAM;AAAA,GAAA,EACpE,CAAA;AAEJ;AAEO,SAAS,eAAA,GAAkB;AAChC,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,iBAAA,EAAA,EACC,+BAAC,MAAA,EAAA,EAAO,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,gBAAA,EAAiB,CAAA;AAAA,MAAE;AAAA,KAAA,EAAa,CAAA,EAC1D,CAAA;AAAA,oBAEA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4CAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAM,kBAAA,EAAmB,KAAA,EAAM,GAAA,EAAI,CAAA;AAAA,sBACzC,GAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAM,mBAAA,EAAoB,OAAM,KAAA,EAAM,CAAA;AAAA,sBAC5C,GAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAM,mBAAA,EAAoB,OAAM,OAAA,EAAQ,CAAA;AAAA,sBAC9C,GAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAM,cAAA,EAAe,OAAM,OAAA,EAAQ;AAAA,KAAA,EAC3C,CAAA;AAAA,oBAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACZ,QAAA,EAAA,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,qBACd,IAAA,CAAC,KAAA,EAAA,EAAe,SAAA,EAAU,+CAAA,EACxB,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,mCAAA,EACb,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,2BAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,SAAI,SAAA,EAAU,iFAAA,EACb,8BAAC,GAAA,EAAA,EAAI,SAAA,EAAU,WAAU,CAAA,EAC3B,CAAA;AAAA,+BACC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uCAAA,EAAyC,QAAA,EAAA,CAAA,CAAE,IAAA,EAAK,CAAA;AAAA,4BAC7D,IAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uDAAA,EACX,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAO,WAAU,SAAA,EAAU,CAAA;AAAA,cAAE,SAAA;AAAA,cAAQ,CAAA,CAAE,OAAA;AAAA,cAAQ,QAAA;AAAA,cAAI,CAAA,CAAE,QAAA;AAAA,cAAS;AAAA,aAAA,EACjE;AAAA,WAAA,EACF;AAAA,SAAA,EACF,CAAA;AAAA,wBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,CAAA,6CAAA,EAAgD,CAAA,CAAE,MAAA,GAAS,iCAAA,GAAoC,gCAAgC,CAAA,CAAA,EAC7I,QAAA,EAAA,CAAA,CAAE,MAAA,GAAS,QAAA,GAAW,QAAA,EACzB,CAAA;AAAA,8BACC,MAAA,EAAA,EAAO,OAAA,EAAQ,SAAA,EAAU,IAAA,EAAK,QAAQ,QAAA,EAAA,CAAA,CAAE,MAAA,mBAAS,GAAA,CAAC,KAAA,EAAA,EAAM,WAAU,SAAA,EAAU,CAAA,uBAAM,IAAA,EAAA,EAAK,SAAA,EAAU,WAAU,CAAA,EAAG;AAAA,SAAA,EACjH;AAAA,OAAA,EACF,CAAA;AAAA,sBAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mEAAA,EACZ,QAAA,EAAA,CAAA,CAAE,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qBACf,IAAA,CAAC,KAAA,CAAM,UAAN,EACC,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,0HAAA,EACd,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,CAAA,CAAE,IAAA,EAAF,EAAO,SAAA,EAAU,mCAAA,EAAoC,CAAA;AAAA,UAAE,GAAA;AAAA,UAAE,CAAA,CAAE;AAAA,SAAA,EAC9D,CAAA;AAAA,QACC,CAAA,GAAI,EAAE,KAAA,CAAM,MAAA,GAAS,qBAAK,GAAA,CAAC,UAAA,EAAA,EAAW,WAAU,mCAAA,EAAoC;AAAA,OAAA,EAAA,EAJlE,CAKrB,CACD,CAAA,EACH;AAAA,KAAA,EAAA,EA9BQ,CAAA,CAAE,EA+BZ,CACD,CAAA,EACH,CAAA;AAAA,oBAEA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gDAAA,EAAiD,QAAA,EAAA,4GAAA,EAE9D;AAAA,GAAA,EACF,CAAA;AAEJ;;;AC7FO,SAAS,wBAAwB,OAAA,EAAoD;AAC1F,EAAA,MAAM,aAAA,GAA8C,MAAMA,KAAAA,CAAM,aAAA,CAAc,eAAe,CAAA;AAC7F,EAAA,aAAA,CAAc,WAAA,GAAc,iBAAA;AAE5B,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,aAAA;AAAA,IACJ,IAAA,EAAM,SAAS,QAAA,IAAY,aAAA;AAAA,IAC3B,IAAA,EAAM,KAAA;AAAA,IACN,OAAA,EAAS,OAAA;AAAA,IACT,KAAA,EAAO,SAAS,KAAA,IAAS,WAAA;AAAA,IACzB,YAAY,OAAA,EAAS,UAAA;AAAA,IACrB,cAAA,EAAgB,IAAA;AAAA,IAChB,cAAc,EAAC;AAAA,IACf,gBAAA,EAAkB,CAAC,EAAE,EAAA,EAAI,eAAe,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO,UAAA,EAAY,CAAA;AAAA,IACjF,UAAA,EAAY;AAAA,MACV;AAAA,QACE,OAAA,EAAS,SAAS,UAAA,IAAc,MAAA;AAAA,QAChC,QAAA,EAAU,SAAS,WAAA,IAAe,CAAA;AAAA,QAClC,KAAA,EAAO,SAAS,QAAA,IAAY,aAAA;AAAA,QAC5B,KAAA,EAAO,cAAA;AAAA,QACP,IAAA,EAAM,KAAA;AAAA,QACN,UAAA,EAAY,EAAE,OAAA,EAAS,aAAA,EAAe,QAAQ,MAAA;AAAgB;AAChE,KACF;AAAA,IACA,MAAA,EAAQ;AAAA,MACN;AAAA,QACE,IAAA,EAAM,cAAA;AAAA,QACN,SAAA,EAAW,aAAA;AAAA,QACX,UAAA,EAAY,EAAE,OAAA,EAAS,aAAA,EAAe,QAAQ,MAAA;AAAgB;AAChE,KACF;AAAA,IACA,SAAS;AAAC,GACZ;AACF","file":"index.js","sourcesContent":["import React from 'react'\nimport { Zap, Plus, Play, Pause, ArrowRight, Filter, Mail, Tag, MessageSquare, Clock } from 'lucide-react'\nimport { Button, PageHeaderActions } from '@fayz-ai/ui'\n\ninterface Workflow {\n id: string\n name: string\n trigger: string\n steps: Array<{ icon: React.ComponentType<{ className?: string }>; label: string }>\n enrolled: number\n active: boolean\n}\n\nconst WORKFLOWS: Workflow[] = [\n {\n id: '1', name: 'New lead → nurture', trigger: 'Form submitted', enrolled: 342, active: true,\n steps: [\n { icon: MessageSquare, label: 'Send SMS' },\n { icon: Clock, label: 'Wait 1 day' },\n { icon: Mail, label: 'Send email' },\n { icon: Tag, label: 'Tag \"nurtured\"' },\n ],\n },\n {\n id: '2', name: 'Missed call text-back', trigger: 'Call missed', enrolled: 128, active: true,\n steps: [\n { icon: MessageSquare, label: 'Text back' },\n { icon: Tag, label: 'Create task' },\n ],\n },\n {\n id: '3', name: 'Appointment reminder', trigger: 'Appointment booked', enrolled: 87, active: true,\n steps: [\n { icon: Clock, label: 'Wait until 24h before' },\n { icon: MessageSquare, label: 'WhatsApp reminder' },\n ],\n },\n {\n id: '4', name: 'Won deal → review request', trigger: 'Deal marked Won', enrolled: 41, active: false,\n steps: [\n { icon: Clock, label: 'Wait 2 days' },\n { icon: Mail, label: 'Ask for review' },\n ],\n },\n]\n\nfunction Stat({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"rounded-card border border-border bg-card p-4\">\n <p className=\"text-xs font-medium text-muted-foreground\">{label}</p>\n <p className=\"mt-2 text-2xl font-semibold text-foreground\">{value}</p>\n </div>\n )\n}\n\nexport function AutomationsHome() {\n return (\n <div className=\"mx-auto max-w-6xl p-6\">\n <PageHeaderActions>\n <Button><Plus className=\"mr-1.5 h-4 w-4\" /> New workflow</Button>\n </PageHeaderActions>\n\n <div className=\"mt-6 grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <Stat label=\"Active workflows\" value=\"3\" />\n <Stat label=\"Contacts enrolled\" value=\"598\" />\n <Stat label=\"Actions run (30d)\" value=\"2,140\" />\n <Stat label=\"Success rate\" value=\"98.6%\" />\n </div>\n\n <div className=\"mt-6 space-y-3\">\n {WORKFLOWS.map((w) => (\n <div key={w.id} className=\"rounded-card border border-border bg-card p-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-amber-100 text-amber-600\">\n <Zap className=\"h-4 w-4\" />\n </div>\n <div>\n <p className=\"text-sm font-semibold text-foreground\">{w.name}</p>\n <p className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n <Filter className=\"h-3 w-3\" /> When: {w.trigger} · {w.enrolled} enrolled\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className={`rounded-full px-2 py-0.5 text-xs font-medium ${w.active ? 'bg-emerald-100 text-emerald-700' : 'bg-muted text-muted-foreground'}`}>\n {w.active ? 'Active' : 'Paused'}\n </span>\n <Button variant=\"outline\" size=\"icon\">{w.active ? <Pause className=\"h-4 w-4\" /> : <Play className=\"h-4 w-4\" />}</Button>\n </div>\n </div>\n\n <div className=\"mt-3 flex flex-wrap items-center gap-2 rounded-md bg-muted/40 p-3\">\n {w.steps.map((s, i) => (\n <React.Fragment key={i}>\n <span className=\"inline-flex items-center gap-1.5 rounded-md border border-border bg-card px-2.5 py-1 text-xs font-medium text-foreground\">\n <s.icon className=\"h-3.5 w-3.5 text-muted-foreground\" /> {s.label}\n </span>\n {i < w.steps.length - 1 && <ArrowRight className=\"h-3.5 w-3.5 text-muted-foreground\" />}\n </React.Fragment>\n ))}\n </div>\n </div>\n ))}\n </div>\n\n <p className=\"mt-4 text-center text-xs text-muted-foreground\">\n Mock preview · the visual builder + execution engine (event bus, scheduler) ships in a later milestone.\n </p>\n </div>\n )\n}\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { AutomationsHome } from './views/AutomationsHome'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-automations — visual workflows (GoHighLevel \"Automation\").\n// Universal plugin. M1 ships a rich mock home; the trigger→action execution\n// engine over the core event bus + scheduler comes in a later milestone.\n// ---------------------------------------------------------------------------\n\nexport interface AutomationsPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n scope?: PluginScope\n verticalId?: VerticalId\n}\n\nexport function createAutomationsPlugin(options?: AutomationsPluginOptions): PluginManifest {\n const PageComponent: React.ComponentType<unknown> = () => React.createElement(AutomationsHome)\n PageComponent.displayName = 'AutomationsHome'\n\n return {\n id: 'automations',\n name: options?.navLabel ?? 'Automations',\n icon: 'Zap',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'automations', label: 'Automations', group: 'Automate' }],\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 6,\n label: options?.navLabel ?? 'Automations',\n route: '/automations',\n icon: 'Zap',\n permission: { feature: 'automations', action: 'read' as const },\n },\n ],\n routes: [\n {\n path: '/automations',\n component: PageComponent,\n permission: { feature: 'automations', action: 'read' as const },\n },\n ],\n widgets: [],\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/runtime.ts","../src/views/AutomationsList.tsx","../src/views/RunLog.tsx","../src/views/AutomationDetailPage.tsx","../src/data/templates.ts","../src/index.ts"],"names":["React","jsxs","jsx","ChevronRight","Card","CHANNEL_LABEL","iconFor","Zap","LucideIcons","usePluginRuntimeOptional","adminNavigateTo","Mail","Button","toast","Badge","Switch","HeaderTabs","Smartphone"],"mappings":"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","file":"index.js","sourcesContent":["import { useOrganizationStore } from '@fayz-ai/admin'\n\n// Re-exports para as views não precisarem saber de onde vem cada peça.\nexport {\n resolveMessages, resolveMessage, renderMessageTemplate,\n getEventsWithoutMessages,\n} from '@fayz-ai/core'\n\n/** Conta ativa — todo modelo é escopado nela. */\nexport function useOrganizationStoreLike(): string | undefined {\n return useOrganizationStore((s) => s.currentOrg?.id)\n}\n","import React from 'react'\nimport * as LucideIcons from 'lucide-react'\nimport { ChevronRight, Mail, MessageCircle, MessageSquare, Smartphone, Zap } from 'lucide-react'\nimport { Card, HeaderTabs, Switch, toast } from '@fayz-ai/ui'\nimport { adminNavigateTo } from '@fayz-ai/admin'\nimport { resolveMessages, useOrganizationStoreLike } from '../lib/runtime'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport type { MessageChannel, MessageKind, ResolvedMessage } from '@fayz-ai/core'\nimport type { MessageTemplateStore } from '../data/templates'\n\n// ---------------------------------------------------------------------------\n// Automações — quando ISTO acontece, mande AQUILO.\n//\n// Cada linha é uma automação inteira: o gatilho à esquerda, o canal na\n// pastilha, o interruptor à direita. Não existe \"modelo\" separado do \"fluxo\" —\n// um texto sem gatilho nunca sai, e um fluxo de um passo é o texto com o\n// gatilho escrito na frente.\n//\n// Agrupado por MÓDULO (Loja, CRM, Agenda) e não por canal, porque é assim que a\n// pergunta chega: \"o que a gente manda quando um pedido é enviado?\" — e a\n// resposta pode ser um e-mail, um WhatsApp, ou os dois. Separar por canal, como\n// fazia a tela de e-mails, obriga a visitar dois menus para responder isso.\n//\n// Cada linha é um par evento×canal. O evento aparece uma vez, com uma pastilha\n// por canal ofertado: é o desenho que o RD Station e o Kommo usam para não\n// esconder que \"confirmação de pedido\" e \"confirmação por WhatsApp\" são o mesmo\n// gatilho com duas saídas.\n// ---------------------------------------------------------------------------\n\nconst CHANNEL_ICON: Record<MessageChannel, React.ComponentType<{ className?: string }>> = {\n email: Mail,\n whatsapp: MessageCircle,\n sms: Smartphone,\n push: MessageSquare,\n webchat: MessageSquare,\n}\n\nconst CHANNEL_LABEL: Record<MessageChannel, string> = {\n email: 'E-mail', whatsapp: 'WhatsApp', sms: 'SMS', push: 'Push', webchat: 'Chat',\n}\n\nconst KIND_TABS: { value: MessageKind | 'all'; label: string }[] = [\n { value: 'all', label: 'Todos' },\n { value: 'transactional', label: 'Transacionais' },\n { value: 'marketing', label: 'Marketing' },\n]\n\nconst KIND_HINT: Record<string, string> = {\n all: 'Tudo que o produto sabe enviar, por qualquer canal.',\n transactional: 'Disparados por uma ação da pessoa. Não precisam de opt-in.',\n marketing: 'Iniciativa da empresa. Só para quem aceitou receber.',\n}\n\nfunction iconFor(name?: string): React.ComponentType<{ className?: string }> {\n if (!name) return Zap\n const icons = LucideIcons as unknown as Record<string, React.ComponentType<{ className?: string }>>\n return icons[name] ?? Zap\n}\n\nexport function AutomationsList({ store }: { store: MessageTemplateStore }) {\n const tenantId = useOrganizationStoreLike()\n // Os eventos vêm do runtime: só os plugins ATIVOS anunciam fatos.\n const runtime = usePluginRuntimeOptional()\n const [messages, setMessages] = React.useState<ResolvedMessage[] | null>(null)\n const [kind, setKind] = React.useState<MessageKind | 'all'>('all')\n\n const reload = React.useCallback(async () => {\n // Uma leitura que falha ainda mostra o catálogo inteiro nos padrões: os\n // eventos são código, então \"sem personalização\" é um estado válido e\n // completo, não uma tela vazia.\n let overrides: Awaited<ReturnType<MessageTemplateStore['list']>> = []\n try {\n overrides = await store.list(tenantId)\n } catch (err) {\n console.warn('[automations] could not load template overrides; showing defaults', err)\n }\n setMessages(resolveMessages(overrides, runtime?.events ?? []))\n }, [store, tenantId, runtime])\n\n React.useEffect(() => { void reload() }, [reload])\n\n const toggle = async (m: ResolvedMessage, enabled: boolean) => {\n setMessages((prev) => prev?.map((x) =>\n x.event.name === m.event.name && x.channel === m.channel ? { ...x, enabled } : x) ?? null)\n try {\n await store.upsert({ eventKey: m.event.name, channel: m.channel, enabled }, tenantId)\n await reload()\n } catch (err) {\n console.warn('[automations] toggle failed', err)\n toast.error('Não foi possível salvar')\n await reload()\n }\n }\n\n const visible = (messages ?? []).filter((m) => kind === 'all' || m.kind === kind)\n const activeCount = (messages ?? []).filter((m) => m.enabled).length\n\n // Agrupa por módulo preservando a ordem de registro dos plugins.\n const groups: { module: string; label: string; items: ResolvedMessage[] }[] = []\n for (const m of visible) {\n let g = groups.find((x) => x.module === m.event.pluginId)\n if (!g) { g = { module: m.event.pluginId, label: m.event.pluginName, items: [] }; groups.push(g) }\n g.items.push(m)\n }\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <HeaderTabs tabs={KIND_TABS} value={kind} onChange={setKind} aria-label=\"Automações\" />\n {messages !== null && (\n <span className=\"text-sm text-muted-foreground\">\n {activeCount} de {messages.length} automações ativas\n </span>\n )}\n </div>\n\n <p className=\"text-sm text-muted-foreground\">{KIND_HINT[kind]}</p>\n\n {messages === null ? (\n <div className=\"space-y-3\">\n {Array.from({ length: 4 }).map((_, i) => (\n <Card key={i} className=\"p-4\">\n <div className=\"h-4 w-40 animate-pulse rounded bg-muted\" />\n <div className=\"mt-2 h-3 w-64 animate-pulse rounded bg-muted\" />\n </Card>\n ))}\n </div>\n ) : groups.length === 0 ? (\n <Card className=\"flex flex-col items-center gap-1 p-12 text-center\">\n <Zap className=\"mb-2 h-9 w-9 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"text-base font-semibold\">Nenhuma automação nesta aba</p>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n Os eventos vêm dos módulos instalados — a loja traz os do pedido, o CRM os do funil.\n </p>\n </Card>\n ) : groups.map((group) => (\n <div key={group.module} className=\"space-y-3\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n {group.label}\n </p>\n {group.items.map((m) => {\n const Icon = iconFor(m.event.icon ?? m.event.pluginIcon)\n const ChannelIcon = CHANNEL_ICON[m.channel]\n const href = `/automations/${encodeURIComponent(m.event.name)}/${m.channel}`\n return (\n <Card\n key={`${m.event.name}:${m.channel}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => adminNavigateTo(href)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); adminNavigateTo(href) }\n }}\n className=\"cursor-pointer overflow-hidden transition-colors hover:border-primary/40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <div className=\"flex items-start gap-4 p-4\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border text-muted-foreground\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"font-medium\">{m.override?.name ?? m.event.title ?? m.event.name}</p>\n <span className=\"inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[11px] text-muted-foreground\">\n <ChannelIcon className=\"h-3 w-3\" />\n {CHANNEL_LABEL[m.channel]}\n </span>\n {m.customized && (\n <span className=\"rounded-full bg-primary/10 px-2 py-0.5 text-[11px] text-primary\">\n personalizado\n </span>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground\">{m.event.description}</p>\n <div className=\"mt-2 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1\">\n <Zap className=\"h-3 w-3\" />\n {m.event.trigger}\n </span>\n {m.subject && <span className=\"truncate\">Assunto: {m.subject}</span>}\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-3\">\n {/* Switch e não checkbox: isto vale na hora, não quando\n algum Salvar for clicado. */}\n <Switch\n checked={m.enabled}\n onCheckedChange={(next) => void toggle(m, next)}\n label={m.enabled ? 'Ativo' : 'Inativo'}\n aria-label={`${m.event.title} — ${CHANNEL_LABEL[m.channel]}`}\n />\n <ChevronRight className=\"h-4 w-4 text-muted-foreground\" />\n </div>\n </div>\n </Card>\n )\n })}\n </div>\n ))}\n </div>\n )\n}\n","import React from 'react'\nimport { AlertTriangle, ChevronRight, CircleCheck, CircleSlash, History, RefreshCw } from 'lucide-react'\nimport { Badge, Button, Card } from '@fayz-ai/ui'\nimport { loadEventRuns, type EventRun, type EventRunStatus } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// As últimas execuções deste gatilho.\n//\n// A tela dizia o que DEVERIA acontecer; faltava o que ACONTECEU. Sem isso, a\n// única forma de testar uma automação era esperar um cliente reclamar — e a\n// reclamação não distingue \"não disparou\" de \"disparou e o envio falhou\", que\n// são defeitos em lugares diferentes.\n//\n// O payload fica visível (recolhido) de propósito: é ele que responde \"por que\n// saiu com o nome errado?\" sem ninguém precisar reproduzir o caso.\n//\n// Vale para QUALQUER gatilho: a lista é lida por chave de evento, e todo evento\n// emitido passa pelo mesmo coletor. Um módulo novo aparece aqui sem tocar nesta\n// tela.\n// ---------------------------------------------------------------------------\n\nconst STATUS: Record<EventRunStatus, {\n label: string; hint: string; variant: 'success' | 'info' | 'warning' | 'destructive'\n Icon: React.ComponentType<{ className?: string }>\n}> = {\n sent: { label: 'Enviado', hint: 'A mensagem saiu.', variant: 'success', Icon: CircleCheck },\n recorded: {\n label: 'Disparou',\n // O estado honesto de hoje: o gatilho funciona, o envio ainda não existe.\n hint: 'O gatilho disparou e ficou registrado. O envio automático ainda não está ligado neste ambiente.',\n variant: 'info', Icon: History,\n },\n skipped: { label: 'Ignorado', hint: 'O gatilho disparou, mas nada foi enviado — automação desligada ou sem canal.', variant: 'warning', Icon: CircleSlash },\n failed: { label: 'Falhou', hint: 'A tentativa de envio quebrou. O erro está na linha.', variant: 'destructive', Icon: AlertTriangle },\n}\n\nfunction when(iso: string): string {\n const then = new Date(iso).getTime()\n const diff = Date.now() - then\n const min = Math.round(diff / 60000)\n if (min < 1) return 'agora'\n if (min < 60) return `há ${min} min`\n const h = Math.round(min / 60)\n if (h < 24) return `há ${h} h`\n return new Date(iso).toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })\n}\n\nfunction RunRow({ run }: { run: EventRun }) {\n const [open, setOpen] = React.useState(false)\n const cfg = STATUS[run.status] ?? STATUS.recorded\n const { Icon } = cfg\n\n return (\n <div className=\"border-b border-border last:border-b-0\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className=\"flex w-full items-center gap-3 px-4 py-2.5 text-left transition-colors hover:bg-muted/40\"\n >\n <ChevronRight className={`h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform ${open ? 'rotate-90' : ''}`} />\n <Icon className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <Badge variant={cfg.variant}>{cfg.label}</Badge>\n <span className=\"min-w-0 flex-1 truncate text-sm text-muted-foreground\">\n {typeof run.payload.record_name === 'string' ? run.payload.record_name\n : typeof run.payload.customer_name === 'string' ? run.payload.customer_name\n : typeof run.payload.contact_name === 'string' ? run.payload.contact_name\n : run.subjectId ?? '—'}\n </span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{when(run.occurredAt)}</span>\n </button>\n\n {open && (\n <div className=\"space-y-3 bg-muted/20 px-4 pb-4 pt-1\">\n <p className=\"text-xs text-muted-foreground\">{cfg.hint}</p>\n <div>\n <p className=\"mb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n Dados do disparo\n </p>\n <pre className=\"overflow-x-auto rounded-md border border-border bg-card p-3 font-mono text-[11px] leading-relaxed\">\n{JSON.stringify(run.payload, null, 2)}\n </pre>\n </div>\n {run.result && (\n <div>\n <p className=\"mb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n Resultado\n </p>\n <pre className=\"overflow-x-auto rounded-md border border-border bg-card p-3 font-mono text-[11px] leading-relaxed\">\n{JSON.stringify(run.result, null, 2)}\n </pre>\n </div>\n )}\n {run.error && (\n <p className=\"rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 font-mono text-[11px] text-destructive\">\n {run.error}\n </p>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport function RunLog({ eventKey, tenantId, enabled }: {\n eventKey: string\n tenantId?: string\n /** Estado atual da automação — muda o que o vazio significa. */\n enabled: boolean\n}) {\n const [runs, setRuns] = React.useState<EventRun[] | null>(null)\n const [loading, setLoading] = React.useState(false)\n\n const load = React.useCallback(async () => {\n setLoading(true)\n setRuns(await loadEventRuns(eventKey, { tenantId, limit: 20 }))\n setLoading(false)\n }, [eventKey, tenantId])\n\n React.useEffect(() => { void load() }, [load])\n\n return (\n <Card className=\"overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <div className=\"min-w-0\">\n <span className=\"text-sm font-medium\">Execuções recentes</span>\n <p className=\"text-xs text-muted-foreground\">Cada vez que este gatilho disparou nesta conta.</p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void load()} disabled={loading}>\n <RefreshCw className={`h-3.5 w-3.5 ${loading ? 'animate-spin' : ''}`} />\n </Button>\n </div>\n\n {runs === null ? (\n <div className=\"space-y-2 p-4\">\n {[1, 2, 3].map((i) => <div key={i} className=\"h-8 animate-pulse rounded bg-muted/40\" />)}\n </div>\n ) : runs.length === 0 ? (\n <div className=\"flex flex-col items-center gap-1 px-4 py-10 text-center\">\n <History className=\"h-7 w-7 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"text-sm font-medium\">Nenhum disparo ainda</p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n {enabled\n ? 'Assim que este evento acontecer, ele aparece aqui — mesmo antes de existir envio.'\n : 'A automação está desligada. O gatilho continua sendo registrado aqui quando o evento acontecer.'}\n </p>\n </div>\n ) : (\n <div>{runs.map((run) => <RunRow key={run.id} run={run} />)}</div>\n )}\n </Card>\n )\n}\n","import React from 'react'\nimport * as LucideIcons from 'lucide-react'\nimport { Clock, Mail, Monitor, RotateCcw, Smartphone, Zap } from 'lucide-react'\nimport { Badge, Button, Card, HeaderTabs, Hint, SubpageHeader, Switch, toast } from '@fayz-ai/ui'\nimport { adminNavigateTo } from '@fayz-ai/admin'\nimport type { MessageChannel, ResolvedMessage } from '@fayz-ai/core'\nimport { usePluginRuntimeOptional } from '@fayz-ai/core'\nimport { resolveMessage, renderMessageTemplate, useOrganizationStoreLike } from '../lib/runtime'\nimport { RunLog } from './RunLog'\nimport type { MessageTemplateStore } from '../data/templates'\n\n// ---------------------------------------------------------------------------\n// Um modelo, em tela cheia. Duas visões do MESMO texto:\n// Prévia o que a pessoa recebe, com os campos já substituídos\n// Código o texto-fonte, onde se edita\n//\n// A substituição da prévia é a de @fayz-ai/core (renderMessageTemplate), não um\n// replace local: prévia e envio precisam concordar, senão aprova-se um texto e\n// entrega-se outro.\n//\n// \"Igual ao padrão\" é gravado como AUSÊNCIA de personalização (null), não como\n// cópia — assim melhorias no texto padrão continuam chegando a quem nunca\n// mexeu. É o mesmo motivo pelo qual \"Restaurar padrão\" APAGA a linha em vez de\n// escrever o texto de fábrica nela.\n// ---------------------------------------------------------------------------\n\ntype ViewTab = 'preview' | 'code' | 'runs'\n\nconst TABS: { value: ViewTab; label: string }[] = [\n { value: 'preview', label: 'Prévia' },\n { value: 'code', label: 'Código' },\n // O que já aconteceu. Fica ao lado do texto, e não numa tela à parte, porque\n // é a mesma pergunta em dois tempos: o que vai sair, e o que saiu.\n { value: 'runs', label: 'Execuções' },\n]\n\nconst CHANNEL_LABEL: Record<MessageChannel, string> = {\n email: 'E-mail', whatsapp: 'WhatsApp', sms: 'SMS', push: 'Push', webchat: 'Chat',\n}\n\n/** Dados de exemplo da prévia. Não são de ninguém — a tela diz isso. */\nconst SAMPLE: Record<string, string> = {\n store_name: 'Sua Loja', company_name: 'Sua Empresa',\n customer_name: 'Maria Silva', contact_name: 'Maria Silva', lead_name: 'Maria Silva',\n order_number: '1042', order_total: 'R$ 189,90',\n order_items: '1 × Camiseta Clássica — R$ 89,90\\n2 × Caneca Esmaltada — R$ 100,00',\n tracking_code: 'BR123456789BR', cart_url: 'https://sualoja.com.br/carrinho',\n deal_name: 'Proposta — Reforma da fachada', deal_value: 'R$ 12.400,00',\n stage_name: 'Negociação', owner_name: 'João Pereira',\n appointment_date: '12/08/2026', appointment_time: '14:30',\n}\n\nfunction iconFor(name?: string): React.ComponentType<{ className?: string }> {\n if (!name) return Zap\n const icons = LucideIcons as unknown as Record<string, React.ComponentType<{ className?: string }>>\n return icons[name] ?? Zap\n}\n\nexport interface AutomationDetailPageProps {\n eventKey?: string\n channel?: string\n store: MessageTemplateStore\n /** Para onde o \"voltar\" leva — a lista pode morar no menu ou nas\n * configurações, e a pessoa tem que voltar por onde entrou. */\n backTo?: string\n}\n\nexport function AutomationDetailPage({ eventKey, channel, store, backTo = '/automations' }: AutomationDetailPageProps) {\n const tenantId = useOrganizationStoreLike()\n const runtime = usePluginRuntimeOptional()\n const [message, setMessage] = React.useState<ResolvedMessage | null | undefined>(undefined)\n const [tab, setTab] = React.useState<ViewTab>('preview')\n const [device, setDevice] = React.useState<'desktop' | 'mobile'>('desktop')\n const [draft, setDraft] = React.useState<{ subject: string; body: string } | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n const back = React.useCallback(() => adminNavigateTo(backTo), [backTo])\n\n const reload = React.useCallback(async () => {\n if (!eventKey || !channel) { setMessage(null); return }\n let overrides: Awaited<ReturnType<MessageTemplateStore['list']>> = []\n try {\n overrides = await store.list(tenantId)\n } catch (err) {\n console.warn('[automations] could not load overrides; showing defaults', err)\n }\n const found = resolveMessage(decodeURIComponent(eventKey), channel as MessageChannel, overrides, runtime?.events ?? [])\n setMessage(found)\n if (found) setDraft({ subject: found.subject, body: found.body })\n }, [eventKey, channel, store, tenantId, runtime])\n\n React.useEffect(() => { void reload() }, [reload])\n\n const header = (\n <SubpageHeader\n title={message === undefined ? '' : (message?.override?.name ?? message?.event.title ?? message?.event.name ?? 'Automação')}\n parentLabel=\"Automações\"\n onBack={back}\n />\n )\n\n if (message === undefined) {\n return (\n <div className=\"space-y-4\">\n {header}\n <div className=\"h-8 w-64 animate-pulse rounded bg-muted\" />\n <Card className=\"h-96 animate-pulse\" />\n </div>\n )\n }\n\n if (!message) {\n return (\n <>\n {header}\n <Card className=\"flex flex-col items-center gap-2 p-12 text-center\">\n <Mail className=\"h-9 w-9 text-muted-foreground/40\" strokeWidth={1.5} />\n <p className=\"font-semibold\">Automação não encontrada</p>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n O evento <code className=\"font-mono\">{eventKey}</code> não está no catálogo — o módulo\n que o registra pode não estar instalado nesta conta.\n </p>\n <Button variant=\"outline\" className=\"mt-2\" onClick={back}>Voltar para Automações</Button>\n </Card>\n </>\n )\n }\n\n const event = message.event\n // O texto de fábrica: o que \"restaurar padrão\" devolve. Vem do registro de\n // padrões, não do evento — o evento é o fato, não a mensagem.\n const fallback = { subject: message.override ? undefined : message.subject, body: message.body }\n const Icon = iconFor(event.icon)\n const current = draft ?? { subject: message.subject, body: message.body }\n const dirty = current.subject !== message.subject || current.body !== message.body\n const hasSubject = message.channel === 'email'\n\n const patch = async (input: Parameters<MessageTemplateStore['upsert']>[0]) => {\n setSaving(true)\n try {\n await store.upsert(input, tenantId)\n await reload()\n } catch (err) {\n console.warn('[automations] save failed', err)\n toast.error('Não foi possível salvar')\n } finally {\n setSaving(false)\n }\n }\n\n const save = () => void patch({\n eventKey: event.name,\n channel: message.channel,\n // Igual ao padrão volta a ser \"sem personalização\", não uma cópia.\n subject: current.subject.trim() === (fallback?.subject ?? '') ? null : current.subject.trim() || null,\n body: current.body.trim() === fallback?.body ? null : current.body.trim() || null,\n })\n\n const reset = async () => {\n setDraft({ subject: fallback?.subject ?? '', body: fallback?.body ?? '' })\n setSaving(true)\n try {\n // Apaga a linha inteira: com ela fora, o padrão volta a valer e melhorias\n // no texto de fábrica voltam a chegar aqui.\n await store.reset(event.name, message.channel, tenantId)\n await reload()\n toast.success('Texto restaurado')\n } catch (err) {\n console.warn('[automations] reset failed', err)\n toast.error('Não foi possível restaurar')\n } finally {\n setSaving(false)\n }\n }\n\n const previewSubject = renderMessageTemplate(current.subject, SAMPLE)\n const previewBody = renderMessageTemplate(current.body, SAMPLE)\n\n return (\n <div className=\"space-y-5\">\n {header}\n\n <div className=\"flex flex-wrap items-start gap-3\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border text-muted-foreground\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{CHANNEL_LABEL[message.channel]}</Badge>\n <Badge variant=\"outline\">{message.kind === 'marketing' ? 'Marketing' : 'Transacional'}</Badge>\n {message.customized && <Badge variant=\"info\">Personalizado</Badge>}\n </div>\n <p className=\"mt-0.5 text-sm text-muted-foreground\">{event.description}</p>\n </div>\n\n <div className=\"flex shrink-0 flex-wrap items-center gap-2\">\n <Hint label=\"Descarta o texto personalizado e volta ao padrão do produto.\">\n <span>\n <Button variant=\"outline\" onClick={() => void reset()} disabled={!message.customized || saving}>\n <RotateCcw className=\"mr-2 h-4 w-4\" />\n Restaurar padrão\n </Button>\n </span>\n </Hint>\n {/* O mesmo interruptor da lista: liga na hora, sem passar pelo Salvar\n — que aqui é só do TEXTO. */}\n <Switch\n size=\"md\"\n checked={message.enabled}\n onCheckedChange={(next) => void patch({ eventKey: event.name, channel: message.channel, enabled: next })}\n disabled={saving}\n label={message.enabled ? 'Ativa' : 'Inativa'}\n />\n <Button onClick={save} disabled={!dirty || saving}>\n {saving ? 'Salvando…' : dirty ? 'Salvar' : 'Salvo'}\n </Button>\n </div>\n </div>\n\n <HeaderTabs tabs={TABS} value={tab} onChange={setTab} aria-label=\"Visualização\" />\n\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-2 border-b border-border pb-4 text-xs text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Zap className=\"h-3.5 w-3.5\" />\n Gatilho:\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-foreground\">{event.name}</code>\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Clock className=\"h-3.5 w-3.5\" />\n {event.trigger}\n </span>\n {hasSubject && current.subject && <span className=\"min-w-0 truncate\">Assunto: {current.subject}</span>}\n </div>\n\n {tab === 'runs' ? (\n <RunLog eventKey={event.name} tenantId={tenantId} enabled={message.enabled} />\n ) : tab === 'preview' ? (\n <Card className=\"overflow-hidden\">\n <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-2.5\">\n <span className=\"text-sm font-medium\">Prévia</span>\n <div className=\"flex items-center gap-1\">\n {(['desktop', 'mobile'] as const).map((d) => (\n <button\n key={d}\n type=\"button\"\n onClick={() => setDevice(d)}\n aria-label={d === 'desktop' ? 'Computador' : 'Celular'}\n className={`flex h-7 w-7 items-center justify-center rounded-md transition-colors ${\n device === d ? 'bg-muted text-foreground' : 'text-muted-foreground hover:bg-muted/60'\n }`}\n >\n {d === 'desktop' ? <Monitor className=\"h-4 w-4\" /> : <Smartphone className=\"h-4 w-4\" />}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"bg-muted/30 p-6\">\n {/* WhatsApp/SMS não têm assunto nem cabeçalho de remetente — mostrar\n a moldura de e-mail neles prometeria uma forma que o canal não\n tem. */}\n <div\n className={`mx-auto rounded-lg border border-border bg-card shadow-sm transition-[max-width] ${\n device === 'mobile' ? 'max-w-[380px]' : hasSubject ? 'max-w-[600px]' : 'max-w-[420px]'\n }`}\n >\n {hasSubject ? (\n <>\n <div className=\"border-b border-border px-6 py-4 text-sm font-semibold\">{SAMPLE.store_name}</div>\n <div className=\"space-y-1 border-b border-border px-6 py-3\">\n <p className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">Assunto</p>\n <p className=\"text-sm font-medium\">{previewSubject}</p>\n </div>\n <div className=\"whitespace-pre-wrap px-6 py-5 text-sm leading-relaxed\">{previewBody}</div>\n </>\n ) : (\n <div className=\"p-4\">\n <div className=\"whitespace-pre-wrap rounded-2xl rounded-tl-sm bg-[#dcf8c6] px-3 py-2 text-sm leading-relaxed text-[#111b21]\">\n {previewBody}\n </div>\n </div>\n )}\n </div>\n <p className=\"mt-4 text-center text-xs text-muted-foreground\">\n Dados de exemplo — nenhum registro real foi usado.\n </p>\n </div>\n </Card>\n ) : (\n <Card className=\"space-y-4 p-4\">\n {hasSubject && (\n <div>\n <label className=\"mb-1 block text-xs font-medium text-muted-foreground\">Assunto</label>\n <input\n value={current.subject}\n onChange={(e) => setDraft({ ...current, subject: e.target.value })}\n className=\"w-full rounded-input border border-input bg-card px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n )}\n <div>\n <label className=\"mb-1 block text-xs font-medium text-muted-foreground\">Mensagem</label>\n <textarea\n rows={14}\n value={current.body}\n onChange={(e) => setDraft({ ...current, body: e.target.value })}\n className=\"w-full rounded-input border border-input bg-card px-3 py-2 font-mono text-xs leading-relaxed focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n <div>\n <p className=\"mb-1.5 text-xs font-medium text-muted-foreground\">\n Campos deste evento — o envio substitui pelo dado real\n </p>\n <div className=\"flex flex-wrap gap-1\">\n {message.placeholders.map((p) => (\n <span key={p} className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground\">\n {p}\n </span>\n ))}\n </div>\n </div>\n </Card>\n )}\n </div>\n )\n}\n","import { getSupabaseClientOptional } from '@fayz-ai/core'\nimport type { MessageTemplate, UpsertMessageTemplateInput } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Acesso aos modelos personalizados. Só as PERSONALIZAÇÕES: o catálogo é\n// código, e uma leitura que falha ainda deve mostrar a lista inteira nos\n// padrões — ver `resolveMessages`.\n// ---------------------------------------------------------------------------\n\nconst TABLE = 'plg_automations_templates'\n\nfunction rowToTemplate(row: any): MessageTemplate {\n return {\n id: row.id,\n tenantId: row.tenant_id,\n eventKey: row.event_key,\n channel: row.channel ?? 'email',\n // NULL fica NULL: quem decide o padrão é o catálogo, não este mapeamento.\n // Colapsar para `false` aqui desligaria em silêncio todo modelo cuja linha\n // só existe porque o texto foi editado.\n enabled: row.enabled ?? null,\n // String vazia e NULL significam a mesma coisa — \"sem personalização\" —,\n // senão um assunto apagado sairia em branco em vez de voltar ao padrão.\n subject: row.subject || null,\n body: row.body || null,\n name: row.name || null,\n updatedAt: row.updated_at ?? row.created_at,\n }\n}\n\nexport interface MessageTemplateStore {\n list(tenantId?: string): Promise<MessageTemplate[]>\n upsert(input: UpsertMessageTemplateInput, tenantId?: string): Promise<MessageTemplate>\n /** Descarta a personalização inteira — a linha some e o padrão volta a valer. */\n reset(eventKey: string, channel: string, tenantId?: string): Promise<void>\n}\n\nexport function createSupabaseTemplateStore(): MessageTemplateStore {\n const db = () => {\n const client = getSupabaseClientOptional()\n if (!client) throw new Error('@fayz-ai/plugin-automations: Supabase client not initialized')\n return client as any\n }\n\n return {\n async list(tenantId) {\n let q = db().from(TABLE).select('*')\n if (tenantId) q = q.eq('tenant_id', tenantId)\n const { data, error } = await q\n if (error) throw error\n return (data ?? []).map(rowToTemplate)\n },\n\n async upsert(input, tenantId) {\n const payload: Record<string, unknown> = {\n tenant_id: tenantId,\n event_key: input.eventKey,\n channel: input.channel,\n }\n // Só o que veio: omitir uma chave tem de significar \"não mexa nisso\",\n // senão salvar o texto apagaria o ligado/desligado junto.\n if (input.enabled !== undefined) payload.enabled = input.enabled\n if (input.subject !== undefined) payload.subject = input.subject\n if (input.body !== undefined) payload.body = input.body\n if (input.name !== undefined) payload.name = input.name\n\n const { data, error } = await db()\n .from(TABLE)\n .upsert(payload, { onConflict: 'tenant_id,event_key,channel' })\n .select().single()\n if (error) throw error\n return rowToTemplate(data)\n },\n\n async reset(eventKey, channel, tenantId) {\n let q = db().from(TABLE).delete().eq('event_key', eventKey).eq('channel', channel)\n if (tenantId) q = q.eq('tenant_id', tenantId)\n const { error } = await q\n if (error) throw error\n },\n }\n}\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { startEventLog } from '@fayz-ai/core'\nimport { AutomationsList } from './views/AutomationsList'\nimport { AutomationDetailPage } from './views/AutomationDetailPage'\nimport { createSupabaseTemplateStore, type MessageTemplateStore } from './data/templates'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-automations — everything the product SENDS, in one place.\n//\n// ONE automation = when THIS happens, send THAT over THIS channel.\n//\n// Events do NOT live here. Each module DECLARES them in its own manifest\n// (`events`) and the runtime aggregates the active plugins' — the store brings\n// the order's, the CRM the pipeline's. If this screen had to import store and\n// CRM, an app installing only the CRM would carry the store catalog too, and\n// every new module would mean another import in here.\n//\n// The same catalog feeds integrations (webhooks) and audit: three readers of the\n// SAME fact, which is why the message text is not part of it.\n// ---------------------------------------------------------------------------\n\nexport interface AutomationsPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n /**\n * Where the list lives.\n *\n * 'nav' its own menu item (default) — for apps where sending is daily\n * routine, like the store.\n * 'settings' a tab inside settings, no menu item. In a salon the calendar is\n * what runs all day; automations are configured once, and a fixed\n * top-level item charges attention daily for a monthly screen.\n */\n placement?: 'nav' | 'settings'\n scope?: PluginScope\n verticalId?: VerticalId\n /** Swaps data access (tests, mock mode). */\n store?: MessageTemplateStore\n}\n\nexport function createAutomationsPlugin(options?: AutomationsPluginOptions): PluginManifest {\n // Built once per manifest: the store holds no state, and rebuilding it every\n // render would remount the effects that depend on it.\n const store = options?.store ?? createSupabaseTemplateStore()\n\n // Turns on the trigger history. Idempotent, and from here on EVERY event the\n // app emits is recorded, not only those with a message — it is the same\n // history webhooks and audit read.\n startEventLog()\n\n const inSettings = options?.placement === 'settings'\n\n const ListPage: React.ComponentType<unknown> = () =>\n React.createElement(AutomationsList, { store })\n ListPage.displayName = 'AutomationsList'\n\n const DetailPage: React.ComponentType<unknown> = (props) =>\n React.createElement(AutomationDetailPage, {\n ...(props as { eventKey?: string; channel?: string }),\n store,\n // \"Back\" must return you through the door you came in: opening the list\n // inside settings must not drop you on a loose page that app's menu does\n // not have.\n backTo: inSettings ? '/settings/automations' : '/automations',\n })\n DetailPage.displayName = 'AutomationDetail'\n\n const READ = { feature: 'automations', action: 'read' as const }\n\n return {\n id: 'automations',\n name: options?.navLabel ?? 'Automações',\n icon: 'Zap',\n version: '2.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'automations', label: 'Automations', group: 'Automate' }],\n navigation: inSettings ? [] : [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 6,\n label: options?.navLabel ?? 'Automações',\n route: '/automations',\n icon: 'Zap',\n permission: READ,\n indexChild: false,\n },\n ],\n // The SAME list, served inside settings — not a second screen.\n settings: inSettings ? [\n { id: 'automations', label: options?.navLabel ?? 'Automações', icon: 'Zap', component: ListPage, permission: READ },\n ] : [],\n routes: [\n { path: '/automations', component: ListPage, permission: READ },\n // One automation's detail. Off-menu: it is a row of the list. Its back\n // link comes from `backTo`.\n { path: '/automations/:eventKey/:channel', component: DetailPage, permission: READ },\n ],\n widgets: [],\n }\n}\n\nexport { createSupabaseTemplateStore }\nexport type { MessageTemplateStore }\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { resolveMessages, resolveMessage, renderMessageTemplate, getEventsWithoutMessages, } from '@fayz-ai/core';
|
|
2
|
+
/** Conta ativa — todo modelo é escopado nela. */
|
|
3
|
+
export declare function useOrganizationStoreLike(): string | undefined;
|
|
4
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/lib/runtime.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,EAAE,cAAc,EAAE,qBAAqB,EACtD,wBAAwB,GACzB,MAAM,eAAe,CAAA;AAEtB,iDAAiD;AACjD,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,SAAS,CAE7D"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { MessageTemplateStore } from '../data/templates';
|
|
3
|
+
export interface AutomationDetailPageProps {
|
|
4
|
+
eventKey?: string;
|
|
5
|
+
channel?: string;
|
|
6
|
+
store: MessageTemplateStore;
|
|
7
|
+
/** Para onde o "voltar" leva — a lista pode morar no menu ou nas
|
|
8
|
+
* configurações, e a pessoa tem que voltar por onde entrou. */
|
|
9
|
+
backTo?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function AutomationDetailPage({ eventKey, channel, store, backTo }: AutomationDetailPageProps): React.JSX.Element;
|
|
12
|
+
//# sourceMappingURL=AutomationDetailPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationDetailPage.d.ts","sourceRoot":"","sources":["../../src/views/AutomationDetailPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAiD7D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,oBAAoB,CAAA;IAC3B;oEACgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAuB,EAAE,EAAE,yBAAyB,qBAkQpH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationsList.d.ts","sourceRoot":"","sources":["../../src/views/AutomationsList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAmD7D,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,oBAAoB,CAAA;CAAE,qBA6IzE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare function RunLog({ eventKey, tenantId, enabled }: {
|
|
3
|
+
eventKey: string;
|
|
4
|
+
tenantId?: string;
|
|
5
|
+
/** Estado atual da automação — muda o que o vazio significa. */
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
}): React.JSX.Element;
|
|
8
|
+
//# sourceMappingURL=RunLog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunLog.d.ts","sourceRoot":"","sources":["../../src/views/RunLog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAuGzB,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IACtD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAA;CACjB,qBA2CA"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "preview"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.9.
|
|
6
|
+
"version": "0.9.1",
|
|
7
7
|
"description": "[experimental] Fayz SDK — workflows & automations plugin",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": false,
|
|
@@ -12,14 +12,12 @@
|
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
|
-
"source": "./src/index.ts",
|
|
16
15
|
"types": "./dist/index.d.ts",
|
|
17
16
|
"import": "./dist/index.js"
|
|
18
17
|
}
|
|
19
18
|
},
|
|
20
19
|
"files": [
|
|
21
|
-
"dist"
|
|
22
|
-
"src"
|
|
20
|
+
"dist"
|
|
23
21
|
],
|
|
24
22
|
"peerDependencies": {
|
|
25
23
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -27,8 +25,9 @@
|
|
|
27
25
|
"lucide-react": ">=0.400.0 <1.0.0"
|
|
28
26
|
},
|
|
29
27
|
"dependencies": {
|
|
30
|
-
"@fayz-ai/core": "^0.
|
|
31
|
-
"@fayz-ai/
|
|
28
|
+
"@fayz-ai/core": "^0.10.0",
|
|
29
|
+
"@fayz-ai/admin": "^0.10.0",
|
|
30
|
+
"@fayz-ai/ui": "^0.10.0"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
34
33
|
"@types/react": "^18.3.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AutomationsHome.d.ts","sourceRoot":"","sources":["../../src/views/AutomationsHome.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAuDzB,wBAAgB,eAAe,sBAwD9B"}
|
package/src/index.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'
|
|
3
|
-
import { AutomationsHome } from './views/AutomationsHome'
|
|
4
|
-
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
// @fayz-ai/plugin-automations — visual workflows (GoHighLevel "Automation").
|
|
7
|
-
// Universal plugin. M1 ships a rich mock home; the trigger→action execution
|
|
8
|
-
// engine over the core event bus + scheduler comes in a later milestone.
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
|
|
11
|
-
export interface AutomationsPluginOptions {
|
|
12
|
-
navPosition?: number
|
|
13
|
-
navSection?: 'main' | 'secondary' | 'settings'
|
|
14
|
-
navLabel?: string
|
|
15
|
-
scope?: PluginScope
|
|
16
|
-
verticalId?: VerticalId
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function createAutomationsPlugin(options?: AutomationsPluginOptions): PluginManifest {
|
|
20
|
-
const PageComponent: React.ComponentType<unknown> = () => React.createElement(AutomationsHome)
|
|
21
|
-
PageComponent.displayName = 'AutomationsHome'
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
id: 'automations',
|
|
25
|
-
name: options?.navLabel ?? 'Automations',
|
|
26
|
-
icon: 'Zap',
|
|
27
|
-
version: '1.0.0',
|
|
28
|
-
scope: options?.scope ?? 'universal',
|
|
29
|
-
verticalId: options?.verticalId,
|
|
30
|
-
defaultEnabled: true,
|
|
31
|
-
dependencies: [],
|
|
32
|
-
declaredFeatures: [{ id: 'automations', label: 'Automations', group: 'Automate' }],
|
|
33
|
-
navigation: [
|
|
34
|
-
{
|
|
35
|
-
section: options?.navSection ?? 'main',
|
|
36
|
-
position: options?.navPosition ?? 6,
|
|
37
|
-
label: options?.navLabel ?? 'Automations',
|
|
38
|
-
route: '/automations',
|
|
39
|
-
icon: 'Zap',
|
|
40
|
-
permission: { feature: 'automations', action: 'read' as const },
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
routes: [
|
|
44
|
-
{
|
|
45
|
-
path: '/automations',
|
|
46
|
-
component: PageComponent,
|
|
47
|
-
permission: { feature: 'automations', action: 'read' as const },
|
|
48
|
-
},
|
|
49
|
-
],
|
|
50
|
-
widgets: [],
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { Zap, Plus, Play, Pause, ArrowRight, Filter, Mail, Tag, MessageSquare, Clock } from 'lucide-react'
|
|
3
|
-
import { Button, PageHeaderActions } from '@fayz-ai/ui'
|
|
4
|
-
|
|
5
|
-
interface Workflow {
|
|
6
|
-
id: string
|
|
7
|
-
name: string
|
|
8
|
-
trigger: string
|
|
9
|
-
steps: Array<{ icon: React.ComponentType<{ className?: string }>; label: string }>
|
|
10
|
-
enrolled: number
|
|
11
|
-
active: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const WORKFLOWS: Workflow[] = [
|
|
15
|
-
{
|
|
16
|
-
id: '1', name: 'New lead → nurture', trigger: 'Form submitted', enrolled: 342, active: true,
|
|
17
|
-
steps: [
|
|
18
|
-
{ icon: MessageSquare, label: 'Send SMS' },
|
|
19
|
-
{ icon: Clock, label: 'Wait 1 day' },
|
|
20
|
-
{ icon: Mail, label: 'Send email' },
|
|
21
|
-
{ icon: Tag, label: 'Tag "nurtured"' },
|
|
22
|
-
],
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: '2', name: 'Missed call text-back', trigger: 'Call missed', enrolled: 128, active: true,
|
|
26
|
-
steps: [
|
|
27
|
-
{ icon: MessageSquare, label: 'Text back' },
|
|
28
|
-
{ icon: Tag, label: 'Create task' },
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
id: '3', name: 'Appointment reminder', trigger: 'Appointment booked', enrolled: 87, active: true,
|
|
33
|
-
steps: [
|
|
34
|
-
{ icon: Clock, label: 'Wait until 24h before' },
|
|
35
|
-
{ icon: MessageSquare, label: 'WhatsApp reminder' },
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: '4', name: 'Won deal → review request', trigger: 'Deal marked Won', enrolled: 41, active: false,
|
|
40
|
-
steps: [
|
|
41
|
-
{ icon: Clock, label: 'Wait 2 days' },
|
|
42
|
-
{ icon: Mail, label: 'Ask for review' },
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
]
|
|
46
|
-
|
|
47
|
-
function Stat({ label, value }: { label: string; value: string }) {
|
|
48
|
-
return (
|
|
49
|
-
<div className="rounded-card border border-border bg-card p-4">
|
|
50
|
-
<p className="text-xs font-medium text-muted-foreground">{label}</p>
|
|
51
|
-
<p className="mt-2 text-2xl font-semibold text-foreground">{value}</p>
|
|
52
|
-
</div>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function AutomationsHome() {
|
|
57
|
-
return (
|
|
58
|
-
<div className="mx-auto max-w-6xl p-6">
|
|
59
|
-
<PageHeaderActions>
|
|
60
|
-
<Button><Plus className="mr-1.5 h-4 w-4" /> New workflow</Button>
|
|
61
|
-
</PageHeaderActions>
|
|
62
|
-
|
|
63
|
-
<div className="mt-6 grid grid-cols-2 gap-4 lg:grid-cols-4">
|
|
64
|
-
<Stat label="Active workflows" value="3" />
|
|
65
|
-
<Stat label="Contacts enrolled" value="598" />
|
|
66
|
-
<Stat label="Actions run (30d)" value="2,140" />
|
|
67
|
-
<Stat label="Success rate" value="98.6%" />
|
|
68
|
-
</div>
|
|
69
|
-
|
|
70
|
-
<div className="mt-6 space-y-3">
|
|
71
|
-
{WORKFLOWS.map((w) => (
|
|
72
|
-
<div key={w.id} className="rounded-card border border-border bg-card p-4">
|
|
73
|
-
<div className="flex items-center justify-between">
|
|
74
|
-
<div className="flex items-center gap-2.5">
|
|
75
|
-
<div className="flex h-9 w-9 items-center justify-center rounded-lg bg-amber-100 text-amber-600">
|
|
76
|
-
<Zap className="h-4 w-4" />
|
|
77
|
-
</div>
|
|
78
|
-
<div>
|
|
79
|
-
<p className="text-sm font-semibold text-foreground">{w.name}</p>
|
|
80
|
-
<p className="flex items-center gap-1 text-xs text-muted-foreground">
|
|
81
|
-
<Filter className="h-3 w-3" /> When: {w.trigger} · {w.enrolled} enrolled
|
|
82
|
-
</p>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
<div className="flex items-center gap-2">
|
|
86
|
-
<span className={`rounded-full px-2 py-0.5 text-xs font-medium ${w.active ? 'bg-emerald-100 text-emerald-700' : 'bg-muted text-muted-foreground'}`}>
|
|
87
|
-
{w.active ? 'Active' : 'Paused'}
|
|
88
|
-
</span>
|
|
89
|
-
<Button variant="outline" size="icon">{w.active ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />}</Button>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
|
|
93
|
-
<div className="mt-3 flex flex-wrap items-center gap-2 rounded-md bg-muted/40 p-3">
|
|
94
|
-
{w.steps.map((s, i) => (
|
|
95
|
-
<React.Fragment key={i}>
|
|
96
|
-
<span className="inline-flex items-center gap-1.5 rounded-md border border-border bg-card px-2.5 py-1 text-xs font-medium text-foreground">
|
|
97
|
-
<s.icon className="h-3.5 w-3.5 text-muted-foreground" /> {s.label}
|
|
98
|
-
</span>
|
|
99
|
-
{i < w.steps.length - 1 && <ArrowRight className="h-3.5 w-3.5 text-muted-foreground" />}
|
|
100
|
-
</React.Fragment>
|
|
101
|
-
))}
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
))}
|
|
105
|
-
</div>
|
|
106
|
-
|
|
107
|
-
<p className="mt-4 text-center text-xs text-muted-foreground">
|
|
108
|
-
Mock preview · the visual builder + execution engine (event bus, scheduler) ships in a later milestone.
|
|
109
|
-
</p>
|
|
110
|
-
</div>
|
|
111
|
-
)
|
|
112
|
-
}
|