@fayz-ai/plugin-marketing 0.10.1 → 0.11.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/dist/components/MarketingBits.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +228 -157
- package/dist/index.js.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/views/CampaignsView.d.ts.map +1 -1
- package/dist/views/ChannelsView.d.ts.map +1 -1
- package/dist/views/FunnelView.d.ts.map +1 -1
- package/dist/views/LandingPageComposer.d.ts.map +1 -1
- package/dist/views/LandingPagesView.d.ts.map +1 -1
- package/dist/views/blog/BlogAdminView.d.ts.map +1 -1
- package/dist/views/content/PlanBriefView.d.ts +2 -2
- package/dist/views/content/PlanBriefView.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/data/capability.test.d.ts +0 -2
- package/dist/data/capability.test.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarketingBits.d.ts","sourceRoot":"","sources":["../../src/components/MarketingBits.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,UAAU,CAAA;AAU5D,wBAAgB,OAAO,CAAC,EACtB,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,GAC9D,EAAE;IACD,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,qBA0BA;
|
|
1
|
+
{"version":3,"file":"MarketingBits.d.ts","sourceRoot":"","sources":["../../src/components/MarketingBits.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,UAAU,CAAA;AAU5D,wBAAgB,OAAO,CAAC,EACtB,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,GAC9D,EAAE;IACD,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,qBA0BA;AAaD,wBAAgB,SAAS,sBAUxB;AAaD,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,cAAc,CAAA;CAAE,qBAOjE;AAMD,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,qBAS/D;AAMD,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACxB,qBAaA"}
|
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,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAQ/F,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,cAAc,CAAA;AAIrB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAOjE,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACvE,OAAO,EAAqB,KAAK,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAA;AACpG,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAclE,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACvC,yEAAyE;IACzE,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,6EAA6E;IAC7E,cAAc,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,sBAAsB,CAAA;KAAE,CAAA;IAC1D,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAA;IACxC,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,oEAAoE;IACpE,WAAW,CAAC,EAAE,sBAAsB,CAAA;IACpC;6DACyD;IACzD,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACxE;AA+CD,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,cAAc,CAoUtF;AAED,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,kBAAkB,EAClB,eAAe,GAChB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAA;AACjE,YAAY,EACV,sBAAsB,EACtB,WAAW,EACX,WAAW,EACX,aAAa,EACb,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,EAAE,oCAAoC,EAAE,MAAM,wBAAwB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React9, { useState, useEffect, useMemo, useCallback } from 'react';
|
|
2
2
|
import { connectionSettings, connectionStatus, settingsStatus, createConnectionStore, getActiveTenantId, registerTranslations, createSafeDataProvider, getSupabaseClientOptional, useTranslation, useDataChanged, resolveDataProvider } from '@fayz-ai/core';
|
|
3
|
-
import { createPluginContext, fayzConnectorOAuth, PluginSettingsPanel, useModuleNavigation, createViewRouter, ModuleActionBar, SettingsGroup, SelectRow, ToggleRow, PermissionGate, useLimitGuard, useOrganizationStore, CrudFormPage, invalidateLimit, CrudListView } from '@fayz-ai/admin';
|
|
4
|
-
import { defineKpiWidget, defineCustomWidget, defineTableWidget, ModulePage, DataTable, SubpageHeader, Button, Skeleton, ConfirmDialog, ContentSplit, ContentSplitTrigger, Input, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MarkdownEditor, DashboardCanvas,
|
|
3
|
+
import { createPluginContext, fayzConnectorOAuth, PluginSettingsPanel, useModuleNavigation, createViewRouter, ModuleActionBar, SettingsGroup, SelectRow, ToggleRow, askAI, PermissionGate, QuickActionsButton, useLimitGuard, useOrganizationStore, CrudFormPage, RightRailPage, invalidateLimit, CrudListView } from '@fayz-ai/admin';
|
|
4
|
+
import { defineKpiWidget, defineCustomWidget, defineTableWidget, ModulePage, PageToolbar, DataTable, SubpageHeader, PageHeaderActions, Button, Skeleton, ConfirmDialog, ContentSplit, ContentSplitTrigger, Input, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MarkdownEditor, DashboardCanvas, RangeControl, cn, Modal, ModalContent, ModalHeader, ModalTitle, ModalBody, ModalFooter, SheetBody, SegmentedControl, Badge, SheetFooter, SelectSeparator, Checkbox, toast, KpiCard as KpiCard$1, Card, CardHeader, CardTitle, CardContent, TableWidget } from '@fayz-ai/ui';
|
|
5
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
import { History, CheckCircle2, AlertCircle, ChevronRight, Users, Target, Percent, DollarSign, Trash2,
|
|
6
|
+
import { History, CheckCircle2, AlertCircle, ChevronRight, Users, Target, Percent, DollarSign, Trash2, ExternalLink, Sparkles, Pencil, Plus, Layers, MousePointerClick, NotebookPen, ArrowUpRight, ArrowDownRight, Settings2, Columns3, CalendarDays, List, ChevronLeft, Loader2, ImagePlus, X, Bike, Utensils, DoorOpen, MessageCircle, Instagram, Mail, Globe, Megaphone, Search, Link2, AtSign, Pin, Twitter, Linkedin, Facebook, Youtube, Music2, Repeat2, Heart, BarChart2, Share2, ThumbsUp, Send, MoreHorizontal, Bookmark, GripVertical, Image, Trophy } from 'lucide-react';
|
|
7
7
|
import { createStore } from 'zustand/vanilla';
|
|
8
8
|
|
|
9
9
|
// src/index.ts
|
|
@@ -128,12 +128,11 @@ function RangeTabs() {
|
|
|
128
128
|
const range = useMarketingStore((s) => s.range);
|
|
129
129
|
const setRange = useMarketingStore((s) => s.setRange);
|
|
130
130
|
return /* @__PURE__ */ jsx(
|
|
131
|
-
|
|
131
|
+
RangeControl,
|
|
132
132
|
{
|
|
133
|
-
options: RANGES,
|
|
133
|
+
options: RANGES.map((r) => ({ value: r, label: r })),
|
|
134
134
|
value: range,
|
|
135
|
-
onChange: (r) => void setRange(r)
|
|
136
|
-
"aria-label": "Time range"
|
|
135
|
+
onChange: (r) => void setRange(r)
|
|
137
136
|
}
|
|
138
137
|
);
|
|
139
138
|
}
|
|
@@ -192,10 +191,7 @@ function ChannelsView({ onOpen }) {
|
|
|
192
191
|
{ id: "open", header: "", enableSorting: false, cell: () => /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" }) }
|
|
193
192
|
], [t, conversion.labelPlural, conversion.valueLabel, currency]);
|
|
194
193
|
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-6xl space-y-4", children: [
|
|
195
|
-
/* @__PURE__ */
|
|
196
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("marketing.channels.subtitle") }),
|
|
197
|
-
/* @__PURE__ */ jsx(RangeTabs, {})
|
|
198
|
-
] }),
|
|
194
|
+
/* @__PURE__ */ jsx(PageToolbar, { range: /* @__PURE__ */ jsx(RangeTabs, {}) }),
|
|
199
195
|
/* @__PURE__ */ jsx(
|
|
200
196
|
DataTable,
|
|
201
197
|
{
|
|
@@ -354,18 +350,42 @@ function CampaignsView() {
|
|
|
354
350
|
)
|
|
355
351
|
}
|
|
356
352
|
], [t, conversion.labelPlural, currency, deleteCampaign]);
|
|
353
|
+
const createActions = React9.useMemo(() => [
|
|
354
|
+
{
|
|
355
|
+
id: "with-ai",
|
|
356
|
+
label: t("assistant.askAI"),
|
|
357
|
+
description: t("marketing.campaigns.aiHint"),
|
|
358
|
+
icon: "WandSparkles",
|
|
359
|
+
highlight: true,
|
|
360
|
+
action: () => askAI({
|
|
361
|
+
hint: t("marketing.campaigns.askPlaceholder"),
|
|
362
|
+
intro: {
|
|
363
|
+
role: "growth",
|
|
364
|
+
persona: t("marketing.campaigns.askPersona"),
|
|
365
|
+
pitch: t("marketing.campaigns.askPitch"),
|
|
366
|
+
description: t("marketing.campaigns.askDescription"),
|
|
367
|
+
suggestions: [0, 1, 2].map((i) => ({ label: t(`marketing.campaigns.askSuggestion.${i}`) }))
|
|
368
|
+
}
|
|
369
|
+
})
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
id: "by-hand",
|
|
373
|
+
label: t("marketing.campaigns.newByHand"),
|
|
374
|
+
description: t("marketing.campaigns.newByHandHint"),
|
|
375
|
+
icon: "SlidersHorizontal",
|
|
376
|
+
action: () => setComposerOpen(true)
|
|
377
|
+
}
|
|
378
|
+
], [t]);
|
|
357
379
|
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-6xl space-y-4", children: [
|
|
358
|
-
/* @__PURE__ */
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
] })
|
|
368
|
-
] }),
|
|
380
|
+
/* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsx(PermissionGate, { feature: "marketing", action: "create", children: /* @__PURE__ */ jsx(
|
|
381
|
+
QuickActionsButton,
|
|
382
|
+
{
|
|
383
|
+
label: t("marketing.campaigns.new"),
|
|
384
|
+
variant: "default",
|
|
385
|
+
actions: createActions
|
|
386
|
+
}
|
|
387
|
+
) }) }),
|
|
388
|
+
/* @__PURE__ */ jsx(PageToolbar, { range: /* @__PURE__ */ jsx(RangeTabs, {}) }),
|
|
369
389
|
/* @__PURE__ */ jsx(DataTable, { columns, data: campaigns, emptyMessage: t("marketing.campaigns.empty") }),
|
|
370
390
|
/* @__PURE__ */ jsx(CampaignComposer, { open: composerOpen, onClose: () => setComposerOpen(false) })
|
|
371
391
|
] });
|
|
@@ -376,14 +396,7 @@ function FunnelView() {
|
|
|
376
396
|
const funnel = useMarketingStore((s) => s.funnel);
|
|
377
397
|
const max = Math.max(...funnel.map((s) => s.count), 1);
|
|
378
398
|
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl space-y-4", children: [
|
|
379
|
-
/* @__PURE__ */
|
|
380
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
381
|
-
t("marketing.funnel.subtitlePrefix"),
|
|
382
|
-
" ",
|
|
383
|
-
conversion.label.toLowerCase()
|
|
384
|
-
] }),
|
|
385
|
-
/* @__PURE__ */ jsx(RangeTabs, {})
|
|
386
|
-
] }),
|
|
399
|
+
/* @__PURE__ */ jsx(PageToolbar, { range: /* @__PURE__ */ jsx(RangeTabs, {}) }),
|
|
387
400
|
/* @__PURE__ */ jsxs("div", { className: "rounded-card border border-border bg-card p-5", children: [
|
|
388
401
|
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: funnel.map((stage, i) => {
|
|
389
402
|
const pct = max > 0 ? Math.max(stage.count / max * 100, 4) : 0;
|
|
@@ -480,113 +493,128 @@ function LandingPageComposer({
|
|
|
480
493
|
setSaving(false);
|
|
481
494
|
}
|
|
482
495
|
}
|
|
483
|
-
return
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
/* @__PURE__ */
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
{
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
className: "
|
|
530
|
-
|
|
531
|
-
/* @__PURE__ */
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
const active = tags.includes(opt.slug);
|
|
554
|
-
return /* @__PURE__ */ jsx(
|
|
555
|
-
Badge,
|
|
556
|
-
{
|
|
557
|
-
variant: active ? "default" : "outline",
|
|
558
|
-
className: "cursor-pointer text-xs",
|
|
559
|
-
onClick: () => toggleTag(opt.slug),
|
|
560
|
-
children: opt.label
|
|
561
|
-
},
|
|
562
|
-
opt.slug
|
|
563
|
-
);
|
|
564
|
-
}),
|
|
565
|
-
/* @__PURE__ */ jsx(
|
|
566
|
-
"input",
|
|
567
|
-
{
|
|
568
|
-
value: newTag,
|
|
569
|
-
onChange: (e) => setNewTag(e.target.value),
|
|
570
|
-
onKeyDown: (e) => {
|
|
571
|
-
if (e.key === "Enter") {
|
|
572
|
-
e.preventDefault();
|
|
573
|
-
addTag();
|
|
496
|
+
return (
|
|
497
|
+
// Beside the list, not over it: the routes already taken are what you check
|
|
498
|
+
// a new one against, and the dialog covered them.
|
|
499
|
+
/* @__PURE__ */ jsxs(
|
|
500
|
+
RightRailPage,
|
|
501
|
+
{
|
|
502
|
+
title: page ? page.name || t("marketing.landing.edit") : t("marketing.landing.new"),
|
|
503
|
+
open,
|
|
504
|
+
onClose,
|
|
505
|
+
width: "max-w-md",
|
|
506
|
+
children: [
|
|
507
|
+
/* @__PURE__ */ jsxs(SheetBody, { className: "space-y-4", children: [
|
|
508
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5", children: [
|
|
509
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: t("marketing.landing.site") }),
|
|
510
|
+
/* @__PURE__ */ jsxs(Select, { value: siteId, onValueChange: setSiteId, children: [
|
|
511
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("marketing.landing.sitePlaceholder") }) }),
|
|
512
|
+
/* @__PURE__ */ jsx(SelectContent, { children: sites.map((s) => /* @__PURE__ */ jsx(SelectItem, { value: s.id, children: s.url ? `${s.name} \xB7 ${s.url.replace(/^https?:\/\//, "")}` : s.name }, s.id)) })
|
|
513
|
+
] })
|
|
514
|
+
] }),
|
|
515
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5", children: [
|
|
516
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: t("marketing.landing.name") }),
|
|
517
|
+
/* @__PURE__ */ jsx(Input, { value: name, onChange: (e) => setName(e.target.value), placeholder: t("marketing.landing.namePlaceholder") })
|
|
518
|
+
] }),
|
|
519
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5", children: [
|
|
520
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: t("marketing.landing.route") }),
|
|
521
|
+
/* @__PURE__ */ jsx(Input, { value: route, onChange: (e) => setRoute(e.target.value), placeholder: "/lp-capilar" }),
|
|
522
|
+
site?.url && previewPath ? /* @__PURE__ */ jsxs("span", { className: "block text-xs text-muted-foreground", children: [
|
|
523
|
+
site.url.replace(/\/+$/, ""),
|
|
524
|
+
previewPath
|
|
525
|
+
] }) : null
|
|
526
|
+
] }),
|
|
527
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
528
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: t("marketing.landing.status") }),
|
|
529
|
+
/* @__PURE__ */ jsx(
|
|
530
|
+
SegmentedControl,
|
|
531
|
+
{
|
|
532
|
+
value: status,
|
|
533
|
+
onChange: (v) => setStatus(v),
|
|
534
|
+
options: [
|
|
535
|
+
{ value: "live", label: t("marketing.landing.statusLive") },
|
|
536
|
+
{ value: "planned", label: t("marketing.landing.statusPlanned") }
|
|
537
|
+
]
|
|
538
|
+
}
|
|
539
|
+
)
|
|
540
|
+
] }),
|
|
541
|
+
status === "planned" ? /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
542
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
543
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: t("marketing.landing.prompt") }),
|
|
544
|
+
site?.editorUrl ? /* @__PURE__ */ jsxs(
|
|
545
|
+
"button",
|
|
546
|
+
{
|
|
547
|
+
type: "button",
|
|
548
|
+
onClick: () => window.open(site.editorUrl, "_blank", "noopener,noreferrer"),
|
|
549
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-primary hover:underline",
|
|
550
|
+
children: [
|
|
551
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5" }),
|
|
552
|
+
" ",
|
|
553
|
+
t("marketing.landing.buildWithFayz")
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
) : null
|
|
557
|
+
] }),
|
|
558
|
+
/* @__PURE__ */ jsx(
|
|
559
|
+
"textarea",
|
|
560
|
+
{
|
|
561
|
+
value: prompt,
|
|
562
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
563
|
+
rows: 3,
|
|
564
|
+
placeholder: t("marketing.landing.promptPlaceholder"),
|
|
565
|
+
className: "w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:ring-2 focus:ring-ring"
|
|
574
566
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
567
|
+
)
|
|
568
|
+
] }) : null,
|
|
569
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
570
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: t("marketing.landing.leadTag") }),
|
|
571
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 rounded-md border border-border bg-background px-2 py-2 focus-within:ring-2 focus-within:ring-ring", children: [
|
|
572
|
+
options.map((opt) => {
|
|
573
|
+
const active = tags.includes(opt.slug);
|
|
574
|
+
return /* @__PURE__ */ jsx(
|
|
575
|
+
Badge,
|
|
576
|
+
{
|
|
577
|
+
variant: active ? "default" : "outline",
|
|
578
|
+
className: "cursor-pointer text-xs",
|
|
579
|
+
onClick: () => toggleTag(opt.slug),
|
|
580
|
+
children: opt.label
|
|
581
|
+
},
|
|
582
|
+
opt.slug
|
|
583
|
+
);
|
|
584
|
+
}),
|
|
585
|
+
/* @__PURE__ */ jsx(
|
|
586
|
+
"input",
|
|
587
|
+
{
|
|
588
|
+
value: newTag,
|
|
589
|
+
onChange: (e) => setNewTag(e.target.value),
|
|
590
|
+
onKeyDown: (e) => {
|
|
591
|
+
if (e.key === "Enter") {
|
|
592
|
+
e.preventDefault();
|
|
593
|
+
addTag();
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
onBlur: addTag,
|
|
597
|
+
placeholder: t("marketing.landing.leadTagPlaceholder"),
|
|
598
|
+
className: "min-w-[8rem] flex-1 border-0 bg-transparent px-1 text-xs text-foreground outline-none placeholder:text-muted-foreground"
|
|
599
|
+
}
|
|
600
|
+
)
|
|
601
|
+
] }),
|
|
602
|
+
/* @__PURE__ */ jsx("span", { className: "block text-xs text-muted-foreground", children: t("marketing.landing.leadTagHint") })
|
|
603
|
+
] })
|
|
604
|
+
] }),
|
|
605
|
+
/* @__PURE__ */ jsx(SheetFooter, { children: /* @__PURE__ */ jsx(
|
|
606
|
+
Button,
|
|
607
|
+
{
|
|
608
|
+
className: "flex-1",
|
|
609
|
+
onClick: handleSave,
|
|
610
|
+
disabled: saving || !siteId || !name.trim() || !route.trim(),
|
|
611
|
+
children: page ? t("marketing.landing.save") : t("marketing.landing.create")
|
|
579
612
|
}
|
|
580
|
-
)
|
|
581
|
-
]
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
/* @__PURE__ */ jsxs(ModalFooter, { children: [
|
|
586
|
-
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, children: t("marketing.composer.cancel") }),
|
|
587
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: saving || !siteId || !name.trim() || !route.trim(), children: page ? t("marketing.landing.save") : t("marketing.landing.create") })
|
|
588
|
-
] })
|
|
589
|
-
] }) });
|
|
613
|
+
) })
|
|
614
|
+
]
|
|
615
|
+
}
|
|
616
|
+
)
|
|
617
|
+
);
|
|
590
618
|
}
|
|
591
619
|
function LandingPagesView() {
|
|
592
620
|
const t = useTranslation();
|
|
@@ -710,14 +738,12 @@ function LandingPagesView() {
|
|
|
710
738
|
}
|
|
711
739
|
], [t, deleteLandingPage]);
|
|
712
740
|
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-6xl space-y-4", children: [
|
|
713
|
-
/* @__PURE__ */
|
|
714
|
-
/* @__PURE__ */ jsx(
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
] }) })
|
|
720
|
-
] }),
|
|
741
|
+
/* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsx(PermissionGate, { feature: "marketing", action: "create", children: /* @__PURE__ */ jsxs(Button, { onClick: openNew, children: [
|
|
742
|
+
/* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-4 w-4" }),
|
|
743
|
+
" ",
|
|
744
|
+
t("marketing.landing.new")
|
|
745
|
+
] }) }) }),
|
|
746
|
+
/* @__PURE__ */ jsx(PageToolbar, { range: /* @__PURE__ */ jsx(RangeTabs, {}) }),
|
|
721
747
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-4", children: [
|
|
722
748
|
/* @__PURE__ */ jsx(KpiCard, { icon: Layers, label: t("marketing.metric.pages"), value: String(pages.length) }),
|
|
723
749
|
/* @__PURE__ */ jsx(
|
|
@@ -1013,19 +1039,19 @@ function PlanBriefView({ onBack }) {
|
|
|
1013
1039
|
function PlanBriefSheet({ open, onClose }) {
|
|
1014
1040
|
const t = useTranslation();
|
|
1015
1041
|
const { plan, draft, patch, dirty, saving, save } = useBriefDraft();
|
|
1016
|
-
return /* @__PURE__ */
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1042
|
+
return /* @__PURE__ */ jsxs(
|
|
1043
|
+
RightRailPage,
|
|
1044
|
+
{
|
|
1045
|
+
title: plan?.name ?? t("marketing.content.brief"),
|
|
1046
|
+
open,
|
|
1047
|
+
onClose,
|
|
1048
|
+
width: "max-w-2xl",
|
|
1049
|
+
children: [
|
|
1050
|
+
/* @__PURE__ */ jsx(SheetBody, { children: draft ? /* @__PURE__ */ jsx(BriefFields, { draft, patch }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "\u2026" }) }),
|
|
1051
|
+
/* @__PURE__ */ jsx(SheetFooter, { children: /* @__PURE__ */ jsx(Button, { className: "flex-1", onClick: () => void save(), disabled: !dirty || saving, children: t("marketing.content.save") }) })
|
|
1052
|
+
]
|
|
1053
|
+
}
|
|
1054
|
+
);
|
|
1029
1055
|
}
|
|
1030
1056
|
var DEFAULT_WEEKS = 8;
|
|
1031
1057
|
var ADD_ACCOUNT_VALUE = "__add-account__";
|
|
@@ -2580,6 +2606,21 @@ function PostsList({ navigate, navTabs }) {
|
|
|
2580
2606
|
navTabs,
|
|
2581
2607
|
activeNavTab: "posts",
|
|
2582
2608
|
onNew: () => navigate("blog-new"),
|
|
2609
|
+
aiCreate: {
|
|
2610
|
+
hint: "Descreva o post\u2026",
|
|
2611
|
+
description: "Descreva o assunto e eu escrevo o rascunho.",
|
|
2612
|
+
intro: {
|
|
2613
|
+
role: "growth",
|
|
2614
|
+
persona: "Redator do blog",
|
|
2615
|
+
pitch: "Diga sobre o que \xE9 o post.",
|
|
2616
|
+
description: "Escrevo t\xEDtulo, resumo e corpo em markdown, com slug e tempo de leitura. Nasce como rascunho \u2014 voc\xEA l\xEA, ajusta e publica quando quiser.",
|
|
2617
|
+
suggestions: [
|
|
2618
|
+
{ label: "Um post sobre cuidados p\xF3s-procedimento" },
|
|
2619
|
+
{ label: "Cinco d\xFAvidas frequentes dos clientes, respondidas" },
|
|
2620
|
+
{ label: "Um post curto para divulgar a promo\xE7\xE3o do m\xEAs" }
|
|
2621
|
+
]
|
|
2622
|
+
}
|
|
2623
|
+
},
|
|
2583
2624
|
addLabel: "New post",
|
|
2584
2625
|
onRowClick: (row) => navigate(`blog-post:${row.id}`)
|
|
2585
2626
|
}
|
|
@@ -5247,6 +5288,16 @@ var en = {
|
|
|
5247
5288
|
"marketing.channels.noCampaigns": "No campaigns yet on this channel.",
|
|
5248
5289
|
// campaigns
|
|
5249
5290
|
"marketing.campaigns.subtitle": "All acquisition campaigns and their conversion performance",
|
|
5291
|
+
"marketing.campaigns.aiHint": "Describe the campaign and I set it up.",
|
|
5292
|
+
"marketing.campaigns.newByHand": "Create by hand",
|
|
5293
|
+
"marketing.campaigns.newByHandHint": "Fill in channel, budget and period.",
|
|
5294
|
+
"marketing.campaigns.askPlaceholder": "Describe the campaign\u2026",
|
|
5295
|
+
"marketing.campaigns.askPersona": "Campaign planner",
|
|
5296
|
+
"marketing.campaigns.askPitch": "Tell me the campaign you want to run.",
|
|
5297
|
+
"marketing.campaigns.askDescription": "Goal, channel, how much you mean to spend and for how long \u2014 tell me what you have and I fill the rest sensibly against your history. You confirm before it is created.",
|
|
5298
|
+
"marketing.campaigns.askSuggestion.0": "Instagram campaign for the month, $800",
|
|
5299
|
+
"marketing.campaigns.askSuggestion.1": "Win back clients who have not returned in 90 days",
|
|
5300
|
+
"marketing.campaigns.askSuggestion.2": "Weekend promo on Google",
|
|
5250
5301
|
"marketing.campaigns.new": "New campaign",
|
|
5251
5302
|
"marketing.campaigns.empty": "No campaigns yet \u2014 create your first one.",
|
|
5252
5303
|
"marketing.campaigns.delete": "Delete campaign",
|
|
@@ -5441,6 +5492,16 @@ var ptBR = {
|
|
|
5441
5492
|
"marketing.channels.noCampaigns": "Nenhuma campanha ainda neste canal.",
|
|
5442
5493
|
// campaigns
|
|
5443
5494
|
"marketing.campaigns.subtitle": "Todas as campanhas de aquisi\xE7\xE3o e seu desempenho de convers\xE3o",
|
|
5495
|
+
"marketing.campaigns.aiHint": "Descreva a campanha e eu monto.",
|
|
5496
|
+
"marketing.campaigns.newByHand": "Criar manualmente",
|
|
5497
|
+
"marketing.campaigns.newByHandHint": "Preencher canal, or\xE7amento e per\xEDodo.",
|
|
5498
|
+
"marketing.campaigns.askPlaceholder": "Descreva a campanha\u2026",
|
|
5499
|
+
"marketing.campaigns.askPersona": "Planejador de campanhas",
|
|
5500
|
+
"marketing.campaigns.askPitch": "Diga a campanha que voc\xEA quer rodar.",
|
|
5501
|
+
"marketing.campaigns.askDescription": "Objetivo, canal, quanto pretende gastar e por quanto tempo \u2014 diga o que tiver e eu completo o resto com o que faz sentido para o seu hist\xF3rico. Voc\xEA confirma antes de criar.",
|
|
5502
|
+
"marketing.campaigns.askSuggestion.0": "Campanha de Instagram para o m\xEAs, R$ 800",
|
|
5503
|
+
"marketing.campaigns.askSuggestion.1": "Reativar clientes que n\xE3o voltam h\xE1 90 dias",
|
|
5504
|
+
"marketing.campaigns.askSuggestion.2": "Promo\xE7\xE3o de fim de semana no Google",
|
|
5444
5505
|
"marketing.campaigns.new": "Nova campanha",
|
|
5445
5506
|
"marketing.campaigns.empty": "Nenhuma campanha ainda \u2014 crie a primeira.",
|
|
5446
5507
|
"marketing.campaigns.delete": "Excluir campanha",
|
|
@@ -5669,7 +5730,6 @@ function createMarketingPlugin(options) {
|
|
|
5669
5730
|
{ config, provider: provider2, store: store3 },
|
|
5670
5731
|
React9.createElement(PluginSettingsPanel, {
|
|
5671
5732
|
title: config.labels.settings ?? config.labels.pageTitle,
|
|
5672
|
-
subtitle: config.labels.pageSubtitle,
|
|
5673
5733
|
generalSettings: React9.createElement(SettingsView),
|
|
5674
5734
|
registries: marketingRegistries,
|
|
5675
5735
|
// Enables the "Integrações" tab (renders manifest connectors for this host).
|
|
@@ -5680,6 +5740,7 @@ function createMarketingPlugin(options) {
|
|
|
5680
5740
|
SettingsComponent.displayName = "MarketingSettings";
|
|
5681
5741
|
return {
|
|
5682
5742
|
id: "marketing",
|
|
5743
|
+
defaultAgentRole: "growth",
|
|
5683
5744
|
name: options?.navLabel ?? config.labels.pageTitle,
|
|
5684
5745
|
icon: "Megaphone",
|
|
5685
5746
|
version: "1.0.0",
|
|
@@ -5752,6 +5813,16 @@ function createMarketingPlugin(options) {
|
|
|
5752
5813
|
}
|
|
5753
5814
|
}
|
|
5754
5815
|
}] : [],
|
|
5816
|
+
// O post do blog é a única entidade daqui que o agente pode ESCREVER: é
|
|
5817
|
+
// um rascunho de texto, o formulário é o mesmo que a pessoa usaria, e a
|
|
5818
|
+
// permissão de create continua sendo cobrada pelas primitivas. Campanha e
|
|
5819
|
+
// post de conteúdo seguem só-leitura — campanha tem RPC própria e o
|
|
5820
|
+
// planner escreve por outro caminho.
|
|
5821
|
+
...config.modules.blog ? [{
|
|
5822
|
+
key: "marketing:blogPosts",
|
|
5823
|
+
writable: true,
|
|
5824
|
+
entity: buildBlogPostEntity()
|
|
5825
|
+
}] : [],
|
|
5755
5826
|
...config.modules.contentPlanner ? [{
|
|
5756
5827
|
key: "marketing:contentPosts",
|
|
5757
5828
|
writable: false,
|