@fayz-ai/admin 0.61.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/dist/{CommandPalette-B5PMQFDG.js → CommandPalette-XDJJ5E3O.js} +3 -3
  2. package/dist/{CommandPalette-B5PMQFDG.js.map → CommandPalette-XDJJ5E3O.js.map} +1 -1
  3. package/dist/ConnectedBrandingSettings-43ZM3HCI.js +680 -0
  4. package/dist/ConnectedBrandingSettings-43ZM3HCI.js.map +1 -0
  5. package/dist/ConnectedCompanySettings-I4MALI2Q.js +197 -0
  6. package/dist/ConnectedCompanySettings-I4MALI2Q.js.map +1 -0
  7. package/dist/ConnectedModulesSettings-A2VJ5BMJ.js +563 -0
  8. package/dist/ConnectedModulesSettings-A2VJ5BMJ.js.map +1 -0
  9. package/dist/ConnectedSecuritySettings-25AHA4HJ.js +189 -0
  10. package/dist/ConnectedSecuritySettings-25AHA4HJ.js.map +1 -0
  11. package/dist/ConnectedUserProfile-E7USJRUE.js +424 -0
  12. package/dist/ConnectedUserProfile-E7USJRUE.js.map +1 -0
  13. package/dist/FieldRulesEditor-YGIPKI5T.js +129 -0
  14. package/dist/FieldRulesEditor-YGIPKI5T.js.map +1 -0
  15. package/dist/GettingStartedWidget-HMIJ3Y24.js +12 -0
  16. package/dist/GettingStartedWidget-HMIJ3Y24.js.map +1 -0
  17. package/dist/PermissionProfilesTab-3ZPRCHMZ.js +548 -0
  18. package/dist/PermissionProfilesTab-3ZPRCHMZ.js.map +1 -0
  19. package/dist/PersonTimeline-HQZT527S.js +3 -0
  20. package/dist/{PersonTimeline-X7JTPUWJ.js.map → PersonTimeline-HQZT527S.js.map} +1 -1
  21. package/dist/ProjectsSettings-7O2F27MD.js +5 -0
  22. package/dist/ProjectsSettings-7O2F27MD.js.map +1 -0
  23. package/dist/ScheduleEditor-54ELWR45.js +8 -0
  24. package/dist/{ScheduleEditor-L2UJXKMY.js.map → ScheduleEditor-54ELWR45.js.map} +1 -1
  25. package/dist/SeuSiteWidget-QLSUVC63.js +6 -0
  26. package/dist/SeuSiteWidget-QLSUVC63.js.map +1 -0
  27. package/dist/SubscriptionPage-5GE5HFJK.js +17 -0
  28. package/dist/{SubscriptionPage-IDVEFLZ5.js.map → SubscriptionPage-5GE5HFJK.js.map} +1 -1
  29. package/dist/TeamTab-6RAULFLW.js +502 -0
  30. package/dist/TeamTab-6RAULFLW.js.map +1 -0
  31. package/dist/TrialWidget-Z6CLUCU3.js +7 -0
  32. package/dist/TrialWidget-Z6CLUCU3.js.map +1 -0
  33. package/dist/app/AdminShell.d.ts.map +1 -1
  34. package/dist/app/admin-app.d.ts.map +1 -1
  35. package/dist/app/config.d.ts +14 -0
  36. package/dist/app/config.d.ts.map +1 -1
  37. package/dist/app/routing.d.ts +6 -0
  38. package/dist/app/routing.d.ts.map +1 -1
  39. package/dist/app/scaffold.d.ts.map +1 -1
  40. package/dist/billing/index.js +9 -4
  41. package/dist/chunk-2H46WDG5.js +53 -0
  42. package/dist/chunk-2H46WDG5.js.map +1 -0
  43. package/dist/chunk-3HLX7YB2.js +94 -0
  44. package/dist/chunk-3HLX7YB2.js.map +1 -0
  45. package/dist/chunk-3OUD4XBK.js +3 -0
  46. package/dist/chunk-3OUD4XBK.js.map +1 -0
  47. package/dist/{chunk-IXSY4GPK.js → chunk-5D5QLMOQ.js} +5 -3
  48. package/dist/chunk-5D5QLMOQ.js.map +1 -0
  49. package/dist/chunk-5WR62X2R.js +1081 -0
  50. package/dist/chunk-5WR62X2R.js.map +1 -0
  51. package/dist/{chunk-KPYRTOCK.js → chunk-6CQFGMEO.js} +4 -140
  52. package/dist/chunk-6CQFGMEO.js.map +1 -0
  53. package/dist/chunk-6MMSYC2I.js +116 -0
  54. package/dist/chunk-6MMSYC2I.js.map +1 -0
  55. package/dist/chunk-6QFOE3UD.js +1466 -0
  56. package/dist/chunk-6QFOE3UD.js.map +1 -0
  57. package/dist/chunk-6UUFVQ2E.js +283 -0
  58. package/dist/chunk-6UUFVQ2E.js.map +1 -0
  59. package/dist/chunk-7WNLL3F6.js +7889 -0
  60. package/dist/chunk-7WNLL3F6.js.map +1 -0
  61. package/dist/chunk-A74IHAQE.js +439 -0
  62. package/dist/chunk-A74IHAQE.js.map +1 -0
  63. package/dist/{chunk-JOBRLBIQ.js → chunk-AFA6IO23.js} +4 -3
  64. package/dist/chunk-AFA6IO23.js.map +1 -0
  65. package/dist/{chunk-P5UIGQFY.js → chunk-ALCSIN3Z.js} +5 -5
  66. package/dist/chunk-ALCSIN3Z.js.map +1 -0
  67. package/dist/chunk-AWM4AMBS.js +39 -0
  68. package/dist/chunk-AWM4AMBS.js.map +1 -0
  69. package/dist/{chunk-OQARLKZN.js → chunk-BG5Z6KLN.js} +6 -18
  70. package/dist/chunk-BG5Z6KLN.js.map +1 -0
  71. package/dist/chunk-DPNFZONC.js +19 -0
  72. package/dist/chunk-DPNFZONC.js.map +1 -0
  73. package/dist/chunk-DRCV643L.js +193 -0
  74. package/dist/chunk-DRCV643L.js.map +1 -0
  75. package/dist/chunk-E6DF3VR6.js +206 -0
  76. package/dist/chunk-E6DF3VR6.js.map +1 -0
  77. package/dist/chunk-ENHCVGXZ.js +120 -0
  78. package/dist/chunk-ENHCVGXZ.js.map +1 -0
  79. package/dist/chunk-FK6RHGI7.js +56 -0
  80. package/dist/chunk-FK6RHGI7.js.map +1 -0
  81. package/dist/chunk-G5HNA5QK.js +233 -0
  82. package/dist/chunk-G5HNA5QK.js.map +1 -0
  83. package/dist/chunk-HCFO4Z6A.js +53 -0
  84. package/dist/chunk-HCFO4Z6A.js.map +1 -0
  85. package/dist/chunk-JFIU6NQP.js +51 -0
  86. package/dist/chunk-JFIU6NQP.js.map +1 -0
  87. package/dist/chunk-JRZJBMOY.js +3 -0
  88. package/dist/chunk-JRZJBMOY.js.map +1 -0
  89. package/dist/{chunk-3YP7KW47.js → chunk-JVVOL4BB.js} +41 -512
  90. package/dist/chunk-JVVOL4BB.js.map +1 -0
  91. package/dist/chunk-KAQ3UIAA.js +415 -0
  92. package/dist/chunk-KAQ3UIAA.js.map +1 -0
  93. package/dist/{chunk-P6XUDT2P.js → chunk-KJELMULA.js} +4 -51
  94. package/dist/chunk-KJELMULA.js.map +1 -0
  95. package/dist/chunk-KLO7DKXX.js +1651 -0
  96. package/dist/chunk-KLO7DKXX.js.map +1 -0
  97. package/dist/chunk-M2CMDWUI.js +75 -0
  98. package/dist/chunk-M2CMDWUI.js.map +1 -0
  99. package/dist/chunk-PQ47MLTH.js +255 -0
  100. package/dist/chunk-PQ47MLTH.js.map +1 -0
  101. package/dist/{chunk-VX3WJLKK.js → chunk-QD7BMUDF.js} +17 -8
  102. package/dist/chunk-QD7BMUDF.js.map +1 -0
  103. package/dist/{chunk-E4MESMNR.js → chunk-QTSKCPSW.js} +7 -10
  104. package/dist/chunk-QTSKCPSW.js.map +1 -0
  105. package/dist/chunk-S56FQKPL.js +186 -0
  106. package/dist/chunk-S56FQKPL.js.map +1 -0
  107. package/dist/chunk-SGAFPNMA.js +75 -0
  108. package/dist/chunk-SGAFPNMA.js.map +1 -0
  109. package/dist/{chunk-OD7P4L3D.js → chunk-SOKCLVM4.js} +3 -3
  110. package/dist/{chunk-OD7P4L3D.js.map → chunk-SOKCLVM4.js.map} +1 -1
  111. package/dist/chunk-TL42NKTH.js +3 -0
  112. package/dist/chunk-TL42NKTH.js.map +1 -0
  113. package/dist/chunk-U6ZCO2PS.js +2964 -0
  114. package/dist/chunk-U6ZCO2PS.js.map +1 -0
  115. package/dist/chunk-VSXNROYH.js +16 -0
  116. package/dist/chunk-VSXNROYH.js.map +1 -0
  117. package/dist/chunk-WPFZCYZL.js +619 -0
  118. package/dist/chunk-WPFZCYZL.js.map +1 -0
  119. package/dist/chunk-XFTNIBDW.js +23 -0
  120. package/dist/chunk-XFTNIBDW.js.map +1 -0
  121. package/dist/chunk-Y66JDL6I.js +1020 -0
  122. package/dist/chunk-Y66JDL6I.js.map +1 -0
  123. package/dist/chunk-YEHIBPIX.js +137 -0
  124. package/dist/chunk-YEHIBPIX.js.map +1 -0
  125. package/dist/chunk-YKPPCV2Z.js +53 -0
  126. package/dist/chunk-YKPPCV2Z.js.map +1 -0
  127. package/dist/components/chat/markdown.d.ts.map +1 -1
  128. package/dist/components/plugins/PluginSettingsPanel.d.ts.map +1 -1
  129. package/dist/components/settings/SettingsPage.d.ts.map +1 -1
  130. package/dist/components/shared/ConnectionIndicator.d.ts.map +1 -1
  131. package/dist/connect-XKQJOWR7.js +18 -0
  132. package/dist/connect-XKQJOWR7.js.map +1 -0
  133. package/dist/crud/CrudDetailPage.d.ts.map +1 -1
  134. package/dist/crud/CrudListView.d.ts.map +1 -1
  135. package/dist/crud/CrudPage.d.ts.map +1 -1
  136. package/dist/crud/RelatedListTab.d.ts.map +1 -1
  137. package/dist/crud/archetypes/EntityLink.d.ts +1 -1
  138. package/dist/crud/archetypes/EntityLink.d.ts.map +1 -1
  139. package/dist/crud/record-chrome.d.ts.map +1 -1
  140. package/dist/entity-routes-PGU7EHAD.js +4 -0
  141. package/dist/{entity-routes-LXOBW5IB.js.map → entity-routes-PGU7EHAD.js.map} +1 -1
  142. package/dist/hooks/useModuleNavigation.d.ts.map +1 -1
  143. package/dist/impersonation/ImpersonateDialog.d.ts.map +1 -1
  144. package/dist/impersonation/session.d.ts.map +1 -1
  145. package/dist/index.d.ts +2 -2
  146. package/dist/index.d.ts.map +1 -1
  147. package/dist/index.js +11922 -33564
  148. package/dist/index.js.map +1 -1
  149. package/dist/lib/connection.d.ts +14 -0
  150. package/dist/lib/connection.d.ts.map +1 -1
  151. package/dist/lib/entity-routes.d.ts.map +1 -1
  152. package/dist/org/index.js +4 -2
  153. package/dist/plugins/PluginRegistryManager.d.ts.map +1 -1
  154. package/dist/settings/MessageTemplateRow.d.ts.map +1 -1
  155. package/dist/timeline/PersonTimeline.d.ts.map +1 -1
  156. package/dist/timeline/TimelineList.d.ts.map +1 -1
  157. package/dist/units/UnitRailPage.d.ts.map +1 -1
  158. package/dist/units/useUnitFilter.d.ts.map +1 -1
  159. package/package.json +5 -5
  160. package/dist/PersonTimeline-X7JTPUWJ.js +0 -3
  161. package/dist/ScheduleEditor-L2UJXKMY.js +0 -6
  162. package/dist/SubscriptionPage-IDVEFLZ5.js +0 -8
  163. package/dist/chunk-3YP7KW47.js.map +0 -1
  164. package/dist/chunk-E4MESMNR.js.map +0 -1
  165. package/dist/chunk-IXSY4GPK.js.map +0 -1
  166. package/dist/chunk-JOBRLBIQ.js.map +0 -1
  167. package/dist/chunk-KPYRTOCK.js.map +0 -1
  168. package/dist/chunk-OQARLKZN.js.map +0 -1
  169. package/dist/chunk-P5UIGQFY.js.map +0 -1
  170. package/dist/chunk-P6XUDT2P.js.map +0 -1
  171. package/dist/chunk-VX3WJLKK.js.map +0 -1
  172. package/dist/entity-routes-LXOBW5IB.js +0 -4
@@ -0,0 +1,439 @@
1
+ import { useFayzProjectsStore, updateFayzProject, editorUrlOf, deleteFayzProject, createFayzProject } from './chunk-6MMSYC2I.js';
2
+ import { useOrganizationStore } from './chunk-YKPPCV2Z.js';
3
+ import * as React from 'react';
4
+ import { Plus, Globe, ExternalLink, PenSquare, Star, Link2Off, Search, Sparkles, Loader2 } from 'lucide-react';
5
+ import { PageHeaderActions, Button, Modal, ModalContent, ModalHeader, ModalTitle, ModalDescription, ModalBody, Input, Textarea, ModalFooter } from '@fayz-ai/ui';
6
+ import { describeError } from '@fayz-ai/core';
7
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
+
9
+ // src/projects/platform.ts
10
+ function env(key) {
11
+ const bag = import.meta.env;
12
+ const value = bag?.[key];
13
+ return value && value.trim() ? value.trim() : void 0;
14
+ }
15
+ function apiRoot(value) {
16
+ const trimmed = value.replace(/\/+$/, "");
17
+ return /\/api$/.test(trimmed) ? trimmed : `${trimmed}/api`;
18
+ }
19
+ function resolveConfig() {
20
+ const apiUrl = env("VITE_FAYZ_API_URL") ?? env("VITE_FAYZ_API_BASE_URL");
21
+ const token = env("VITE_FAYZ_API_TOKEN");
22
+ if (!apiUrl || !token) return null;
23
+ return { apiUrl, token };
24
+ }
25
+ function isPlatformConnected() {
26
+ return resolveConfig() !== null;
27
+ }
28
+ var PlatformError = class extends Error {
29
+ constructor(message, status) {
30
+ super(message);
31
+ this.status = status;
32
+ this.name = "PlatformError";
33
+ }
34
+ };
35
+ async function call(path, init) {
36
+ const config = resolveConfig();
37
+ if (!config) throw new PlatformError("Fayz platform not configured");
38
+ let response;
39
+ try {
40
+ response = await fetch(`${apiRoot(config.apiUrl)}${path}`, {
41
+ ...init,
42
+ headers: {
43
+ Accept: "application/json",
44
+ ...init?.body ? { "Content-Type": "application/json" } : {},
45
+ Authorization: `Bearer ${config.token}`,
46
+ ...init?.headers
47
+ }
48
+ });
49
+ } catch (cause) {
50
+ throw new PlatformError(`Could not reach the fayz platform at ${config.apiUrl}`);
51
+ }
52
+ if (!response.ok) {
53
+ const detail = await response.text().catch(() => "");
54
+ throw new PlatformError(
55
+ detail?.slice(0, 300) || `Platform returned ${response.status}`,
56
+ response.status
57
+ );
58
+ }
59
+ return await response.json();
60
+ }
61
+ async function listPlatformProjects(options) {
62
+ const params = new URLSearchParams({ limit: String(options?.limit ?? 50) });
63
+ if (options?.search) params.set("search", options.search);
64
+ if (options?.publishedOnly) params.set("publishedOnly", "true");
65
+ const body = await call(`/v1/projects?${params}`);
66
+ return body.projects ?? [];
67
+ }
68
+ var PROMPT_MIN_CHARS = 10;
69
+ async function createPlatformProject(input) {
70
+ const body = await call("/v1/generations", {
71
+ method: "POST",
72
+ body: JSON.stringify({
73
+ prompt: input.prompt,
74
+ ...input.name ? { projectName: input.name } : {}
75
+ })
76
+ });
77
+ return { projectId: body.projectId };
78
+ }
79
+ async function getPreview(projectId, options) {
80
+ const query = options?.checkHealth ? "?checkHealth=true" : "";
81
+ return call(`/v1/previews/${encodeURIComponent(projectId)}${query}`);
82
+ }
83
+ async function startPreview(projectId, options) {
84
+ return call(`/v1/previews/${encodeURIComponent(projectId)}/start`, {
85
+ method: "POST",
86
+ body: JSON.stringify({ ...options?.forceRestart ? { forceRestart: true } : {} })
87
+ });
88
+ }
89
+ async function stopPreview(projectId) {
90
+ return call(`/v1/previews/${encodeURIComponent(projectId)}/stop`, {
91
+ method: "POST",
92
+ body: JSON.stringify({})
93
+ });
94
+ }
95
+ async function requestProjectChange(projectId, prompt) {
96
+ return call(
97
+ `/v1/generations/${encodeURIComponent(projectId)}/messages`,
98
+ { method: "POST", body: JSON.stringify({ prompt }) }
99
+ );
100
+ }
101
+ async function getGenerationStatus(projectId) {
102
+ const body = await call(`/v1/generations/${encodeURIComponent(projectId)}`);
103
+ const status = body.generationStatus ?? null;
104
+ if (body.registry?.hasActiveGeneration) return { status, building: true };
105
+ if (typeof body.isTerminal === "boolean") return { status, building: !body.isTerminal };
106
+ return { status, building: status !== null && !TERMINAL_STATUSES.has(status) };
107
+ }
108
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["READY", "ERROR", "ABANDONED", "MODERATED"]);
109
+ function ProjectsSettings() {
110
+ const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
111
+ const projects = useFayzProjectsStore((s) => s.projects);
112
+ const load = useFayzProjectsStore((s) => s.load);
113
+ const refresh = useFayzProjectsStore((s) => s.refresh);
114
+ const [linking, setLinking] = React.useState(false);
115
+ const connected = isPlatformConnected();
116
+ React.useEffect(() => {
117
+ void load(currentOrgId);
118
+ }, [currentOrgId, load]);
119
+ React.useEffect(() => {
120
+ if (!connected || projects.length === 0) return;
121
+ let cancelled = false;
122
+ void (async () => {
123
+ try {
124
+ const remote = await listPlatformProjects();
125
+ if (cancelled) return;
126
+ const byId = new Map(remote.map((p) => [p.id, p]));
127
+ const stale = projects.filter((p) => {
128
+ const match = p.fayzProjectId ? byId.get(p.fayzProjectId) : void 0;
129
+ return match && (match.url ?? null) !== (p.previewUrl ?? null);
130
+ });
131
+ if (stale.length === 0) return;
132
+ await Promise.all(
133
+ stale.map(
134
+ (p) => updateFayzProject(p.id, { previewUrl: byId.get(p.fayzProjectId).url })
135
+ )
136
+ );
137
+ await refresh();
138
+ } catch {
139
+ }
140
+ })();
141
+ return () => {
142
+ cancelled = true;
143
+ };
144
+ }, [connected, projects.map((p) => p.fayzProjectId).join(","), refresh]);
145
+ const onLinked = async () => {
146
+ setLinking(false);
147
+ await refresh();
148
+ };
149
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
150
+ /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: () => setLinking(true), disabled: !connected, children: [
151
+ /* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-4 w-4" }),
152
+ " Vincular site"
153
+ ] }) }),
154
+ !connected && /* @__PURE__ */ jsxs("p", { className: "rounded-card border border-dashed border-border p-4 text-sm text-muted-foreground", children: [
155
+ "Este app ainda n\xE3o est\xE1 ligado \xE0 sua conta fayz. Defina",
156
+ " ",
157
+ /* @__PURE__ */ jsx("code", { className: "rounded bg-muted px-1 py-0.5 text-xs", children: "VITE_FAYZ_API_URL" }),
158
+ " e",
159
+ " ",
160
+ /* @__PURE__ */ jsx("code", { className: "rounded bg-muted px-1 py-0.5 text-xs", children: "VITE_FAYZ_API_TOKEN" }),
161
+ " para escolher um site da sua conta."
162
+ ] }),
163
+ projects.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { connected, onStart: () => setLinking(true) }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: projects.map((p) => /* @__PURE__ */ jsx(
164
+ SiteRow,
165
+ {
166
+ project: p,
167
+ showDefaultAction: projects.length > 1,
168
+ onChanged: refresh
169
+ },
170
+ p.id
171
+ )) }),
172
+ linking && /* @__PURE__ */ jsx(LinkSiteModal, { onClose: () => setLinking(false), onLinked })
173
+ ] });
174
+ }
175
+ function EmptyState({ connected, onStart }) {
176
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-card border border-dashed border-border p-8 text-center", children: [
177
+ /* @__PURE__ */ jsx("span", { className: "mx-auto mb-3 flex h-10 w-10 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx(Globe, { className: "h-5 w-5 text-primary" }) }),
178
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "Nenhum site ainda" }),
179
+ /* @__PURE__ */ jsx("p", { className: "mx-auto mt-1 max-w-sm text-xs text-muted-foreground", children: "Escolha um site que j\xE1 existe na sua conta fayz, ou descreva o que voc\xEA quer e a gente cria." }),
180
+ connected && /* @__PURE__ */ jsxs(Button, { size: "sm", className: "mt-4", onClick: onStart, children: [
181
+ /* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-4 w-4" }),
182
+ " Vincular site"
183
+ ] })
184
+ ] });
185
+ }
186
+ function SiteRow({
187
+ project,
188
+ showDefaultAction,
189
+ onChanged
190
+ }) {
191
+ const [busy, setBusy] = React.useState(false);
192
+ const editorUrl = editorUrlOf(project);
193
+ const run = async (action) => {
194
+ setBusy(true);
195
+ try {
196
+ await action();
197
+ await onChanged();
198
+ } finally {
199
+ setBusy(false);
200
+ }
201
+ };
202
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-card border border-border bg-card p-3", children: [
203
+ /* @__PURE__ */ jsx("span", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-primary/10", children: /* @__PURE__ */ jsx(Globe, { className: "h-4 w-4 text-primary" }) }),
204
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
205
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
206
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium text-foreground", children: project.name }),
207
+ project.isDefault && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-emerald-100 px-2 py-0.5 text-[10px] font-semibold text-emerald-800", children: "padr\xE3o" })
208
+ ] }),
209
+ project.previewUrl ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: project.previewUrl }) : (
210
+ // Not an error and not "no site": the project exists and is being
211
+ // built. Saying "sem URL" here read as something went wrong.
212
+ /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: "Ainda n\xE3o publicado" })
213
+ )
214
+ ] }),
215
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
216
+ project.previewUrl && /* @__PURE__ */ jsx(
217
+ Button,
218
+ {
219
+ size: "sm",
220
+ variant: "ghost",
221
+ title: "Abrir",
222
+ onClick: () => window.open(project.previewUrl, "_blank", "noopener,noreferrer"),
223
+ children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" })
224
+ }
225
+ ),
226
+ editorUrl && /* @__PURE__ */ jsx(
227
+ Button,
228
+ {
229
+ size: "sm",
230
+ variant: "ghost",
231
+ title: "Editar",
232
+ onClick: () => window.open(editorUrl, "_blank", "noopener,noreferrer"),
233
+ children: /* @__PURE__ */ jsx(PenSquare, { className: "h-4 w-4" })
234
+ }
235
+ ),
236
+ showDefaultAction && !project.isDefault && /* @__PURE__ */ jsx(
237
+ Button,
238
+ {
239
+ size: "sm",
240
+ variant: "ghost",
241
+ title: "Definir como padr\xE3o",
242
+ disabled: busy,
243
+ onClick: () => run(() => updateFayzProject(project.id, { isDefault: true })),
244
+ children: /* @__PURE__ */ jsx(Star, { className: "h-4 w-4" })
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsx(
248
+ Button,
249
+ {
250
+ size: "sm",
251
+ variant: "ghost",
252
+ title: "Desvincular deste painel",
253
+ disabled: busy,
254
+ onClick: () => run(() => deleteFayzProject(project.id)),
255
+ children: /* @__PURE__ */ jsx(Link2Off, { className: "h-4 w-4 text-muted-foreground" })
256
+ }
257
+ )
258
+ ] })
259
+ ] });
260
+ }
261
+ function LinkSiteModal({ onClose, onLinked }) {
262
+ const [mode, setMode] = React.useState("import");
263
+ return /* @__PURE__ */ jsx(Modal, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(ModalContent, { size: "lg", children: [
264
+ /* @__PURE__ */ jsxs(ModalHeader, { children: [
265
+ /* @__PURE__ */ jsx(ModalTitle, { children: "Vincular um site" }),
266
+ /* @__PURE__ */ jsx(ModalDescription, { children: "Escolha um site da sua conta fayz, ou descreva o que voc\xEA quer." })
267
+ ] }),
268
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
269
+ /* @__PURE__ */ jsxs(ModeTab, { active: mode === "import", onClick: () => setMode("import"), children: [
270
+ /* @__PURE__ */ jsx(Search, { className: "h-3.5 w-3.5" }),
271
+ " Escolher um existente"
272
+ ] }),
273
+ /* @__PURE__ */ jsxs(ModeTab, { active: mode === "create", onClick: () => setMode("create"), children: [
274
+ /* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5" }),
275
+ " Criar com IA"
276
+ ] })
277
+ ] }),
278
+ mode === "import" ? /* @__PURE__ */ jsx(ImportPane, { onLinked }) : /* @__PURE__ */ jsx(CreatePane, { onLinked, onCancel: onClose })
279
+ ] }) });
280
+ }
281
+ function ModeTab({
282
+ active,
283
+ onClick,
284
+ children
285
+ }) {
286
+ return /* @__PURE__ */ jsx(
287
+ Button,
288
+ {
289
+ variant: "bare",
290
+ size: "bare",
291
+ type: "button",
292
+ onClick,
293
+ className: `flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-medium transition-colors ${active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"}`,
294
+ children
295
+ }
296
+ );
297
+ }
298
+ function ImportPane({ onLinked }) {
299
+ const linked = useFayzProjectsStore((s) => s.projects);
300
+ const [search, setSearch] = React.useState("");
301
+ const [remote, setRemote] = React.useState(null);
302
+ const [error, setError] = React.useState(null);
303
+ const [linkingId, setLinkingId] = React.useState(null);
304
+ React.useEffect(() => {
305
+ let cancelled = false;
306
+ setError(null);
307
+ const timer = setTimeout(() => {
308
+ void (async () => {
309
+ try {
310
+ const list = await listPlatformProjects({ search: search || void 0 });
311
+ if (!cancelled) setRemote(list);
312
+ } catch (cause) {
313
+ if (!cancelled) {
314
+ setRemote([]);
315
+ setError(cause instanceof PlatformError ? cause.message : "N\xE3o foi poss\xEDvel listar os sites");
316
+ }
317
+ }
318
+ })();
319
+ }, search ? 300 : 0);
320
+ return () => {
321
+ cancelled = true;
322
+ clearTimeout(timer);
323
+ };
324
+ }, [search]);
325
+ const alreadyLinked = new Set(linked.map((p) => p.fayzProjectId).filter(Boolean));
326
+ const link = async (project) => {
327
+ setLinkingId(project.id);
328
+ try {
329
+ await createFayzProject({
330
+ name: project.name,
331
+ fayzProjectId: project.id,
332
+ previewUrl: project.url,
333
+ // The first site a tenant links is its default; there is nothing to
334
+ // choose between yet, and asking would be a checkbox with one option.
335
+ isDefault: linked.length === 0
336
+ });
337
+ onLinked();
338
+ } catch (cause) {
339
+ setError(describeError(cause, "N\xE3o foi poss\xEDvel vincular"));
340
+ setLinkingId(null);
341
+ }
342
+ };
343
+ return /* @__PURE__ */ jsxs(ModalBody, { className: "space-y-3", children: [
344
+ /* @__PURE__ */ jsx(
345
+ Input,
346
+ {
347
+ value: search,
348
+ placeholder: "Buscar pelo nome\u2026",
349
+ onChange: (e) => setSearch(e.target.value)
350
+ }
351
+ ),
352
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: error }),
353
+ remote === null ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 py-8 text-sm text-muted-foreground", children: [
354
+ /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
355
+ " Carregando seus sites\u2026"
356
+ ] }) : remote.length === 0 ? /* @__PURE__ */ jsx("p", { className: "py-8 text-center text-sm text-muted-foreground", children: search ? "Nenhum site com esse nome." : "Sua conta fayz ainda n\xE3o tem sites." }) : /* @__PURE__ */ jsx("div", { className: "max-h-72 space-y-1.5 overflow-y-auto", children: remote.map((project) => {
357
+ const isLinked = alreadyLinked.has(project.id);
358
+ return /* @__PURE__ */ jsxs(
359
+ "div",
360
+ {
361
+ className: "flex items-center gap-3 rounded-md border border-border bg-card p-2.5",
362
+ children: [
363
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
364
+ /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-foreground", children: project.name }),
365
+ /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: project.moderated ? "Site suspenso" : project.url ?? "Ainda n\xE3o publicado" })
366
+ ] }),
367
+ /* @__PURE__ */ jsx(
368
+ Button,
369
+ {
370
+ size: "sm",
371
+ variant: isLinked ? "ghost" : "outline",
372
+ disabled: isLinked || linkingId !== null,
373
+ onClick: () => link(project),
374
+ children: isLinked ? "Vinculado" : linkingId === project.id ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : "Vincular"
375
+ }
376
+ )
377
+ ]
378
+ },
379
+ project.id
380
+ );
381
+ }) })
382
+ ] });
383
+ }
384
+ function CreatePane({ onLinked, onCancel }) {
385
+ const linked = useFayzProjectsStore((s) => s.projects);
386
+ const [prompt, setPrompt] = React.useState("");
387
+ const [busy, setBusy] = React.useState(false);
388
+ const [error, setError] = React.useState(null);
389
+ const tooShort = prompt.trim().length < PROMPT_MIN_CHARS;
390
+ const submit = async () => {
391
+ setBusy(true);
392
+ setError(null);
393
+ try {
394
+ const { projectId } = await createPlatformProject({ prompt: prompt.trim() });
395
+ await createFayzProject({
396
+ // The platform names the project from the prompt while it builds; the
397
+ // reconcile pass on the settings screen picks the real name up. Until
398
+ // then the row needs something a person recognises.
399
+ name: prompt.trim().slice(0, 60),
400
+ fayzProjectId: projectId,
401
+ // Nothing is published yet — the row is deliberately linked without a
402
+ // URL rather than waiting for one.
403
+ previewUrl: null,
404
+ isDefault: linked.length === 0
405
+ });
406
+ onLinked();
407
+ } catch (cause) {
408
+ setError(describeError(cause, "N\xE3o foi poss\xEDvel criar o site"));
409
+ setBusy(false);
410
+ }
411
+ };
412
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
413
+ /* @__PURE__ */ jsxs(ModalBody, { className: "space-y-3", children: [
414
+ /* @__PURE__ */ jsx(
415
+ Textarea,
416
+ {
417
+ value: prompt,
418
+ onChange: (e) => setPrompt(e.target.value),
419
+ rows: 5,
420
+ placeholder: "Uma loja de caf\xE9 especial, com cat\xE1logo, p\xE1gina de assinatura e blog.",
421
+ className: "px-2 py-1.5"
422
+ }
423
+ ),
424
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "O site \xE9 criado na sua conta fayz e come\xE7a a ser constru\xEDdo. Ele aparece aqui na hora, e a URL publicada chega quando a primeira publica\xE7\xE3o terminar." }),
425
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: error })
426
+ ] }),
427
+ /* @__PURE__ */ jsxs(ModalFooter, { children: [
428
+ /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: onCancel, disabled: busy, children: "Cancelar" }),
429
+ /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: submit, disabled: busy || tooShort, children: [
430
+ busy && /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }),
431
+ " Criar site"
432
+ ] })
433
+ ] })
434
+ ] });
435
+ }
436
+
437
+ export { PlatformError, ProjectsSettings, createPlatformProject, getGenerationStatus, getPreview, isPlatformConnected, listPlatformProjects, requestProjectChange, startPreview, stopPreview };
438
+ //# sourceMappingURL=chunk-A74IHAQE.js.map
439
+ //# sourceMappingURL=chunk-A74IHAQE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/projects/platform.ts","../src/projects/ProjectsSettings.tsx"],"names":[],"mappings":"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","file":"chunk-A74IHAQE.js","sourcesContent":["// The fayz platform, as much of it as the site screen needs: list the projects\n// in an organization, and start a new one from a prompt.\n//\n// Why this exists at all: `published_sites` rows used to be filled in by hand —\n// the merchant transcribed a project id and typed the published URL, because\n// nothing in the app could look either of them up. Both facts belong to the\n// platform, so the screen now asks it instead of asking the person.\n//\n// Auth is an API token (`ApiToken` on the platform), read from the environment.\n// That is a PROOF-OF-CONCEPT posture and the reason nothing here reads a token\n// from the UI: a Vite variable is baked into the bundle, so this credential is\n// visible to anyone who opens devtools on the admin. Fine while it is izzy's\n// own token against his own org; not something to hand a merchant. The eventual\n// shape is an account authorization the merchant grants, at which point only\n// `resolveConfig` changes.\n\n/** A project as the platform describes it — no field here is typed by a human. */\nexport interface PlatformProject {\n id: string\n name: string\n /** Canonical public origin, or null when the project has never been published. */\n url: string | null\n publishedAt: string | null\n updatedAt: string\n /** A takedown is in force; the URL serves a placeholder. */\n moderated: boolean\n}\n\nexport interface PlatformConfig {\n /** Origin or `origin/api` — both spellings resolve to the same root. */\n apiUrl: string\n token: string\n}\n\nfunction env(key: string): string | undefined {\n const bag = (import.meta as unknown as { env?: Record<string, string | undefined> }).env\n const value = bag?.[key]\n return value && value.trim() ? value.trim() : undefined\n}\n\n/**\n * `VITE_FAYZ_API_URL` is written both ways in the wild (`https://host` and\n * `https://host/api`, which is how the platform provisions `FAYZ_API_URL` into\n * functions). Normalising here means a hand-set variable missing the segment\n * cannot 404 at the one moment someone is trying to link a site.\n */\nfunction apiRoot(value: string): string {\n const trimmed = value.replace(/\\/+$/, '')\n return /\\/api$/.test(trimmed) ? trimmed : `${trimmed}/api`\n}\n\nexport function resolveConfig(): PlatformConfig | null {\n // Two variables, because they are two different planes and they do NOT have\n // to be the same host.\n //\n // `VITE_FAYZ_API_BASE_URL` is the app's RUNTIME address: the agent broker its\n // own assistant talks through, and the connector redemption path. That plane\n // is keyed to a published project and its publishable key, so it only answers\n // on the deployment those were issued by.\n //\n // This module is the ACCOUNT plane — which of the merchant's projects exist,\n // and their containers. It authenticates with an API token instead, and can\n // legitimately point somewhere else (a staging platform while the endpoints\n // are being built).\n //\n // Collapsing them broke the admin's own chat with \"Invalid agent key\": moving\n // the base URL to reach a new endpoint took the assistant's channel with it.\n // `VITE_FAYZ_API_BASE_URL` stays as the fallback for the common case where\n // one deployment serves both.\n const apiUrl = env('VITE_FAYZ_API_URL') ?? env('VITE_FAYZ_API_BASE_URL')\n const token = env('VITE_FAYZ_API_TOKEN')\n if (!apiUrl || !token) return null\n return { apiUrl, token }\n}\n\n/**\n * Whether this app can talk to the platform at all.\n *\n * The screen branches on it rather than showing a broken picker: an app with no\n * token still has a working \"link a site\" story through whatever rows already\n * exist, and an empty modal that fails on open teaches nothing.\n */\nexport function isPlatformConnected(): boolean {\n return resolveConfig() !== null\n}\n\nexport class PlatformError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message)\n this.name = 'PlatformError'\n }\n}\n\nasync function call<T>(path: string, init?: RequestInit): Promise<T> {\n const config = resolveConfig()\n if (!config) throw new PlatformError('Fayz platform not configured')\n\n let response: Response\n try {\n response = await fetch(`${apiRoot(config.apiUrl)}${path}`, {\n ...init,\n headers: {\n Accept: 'application/json',\n ...(init?.body ? { 'Content-Type': 'application/json' } : {}),\n Authorization: `Bearer ${config.token}`,\n ...init?.headers,\n },\n })\n } catch (cause) {\n // A CORS refusal and an offline browser are the same rejection here, and\n // \"failed to fetch\" tells a merchant nothing — name the reachable cause.\n throw new PlatformError(`Could not reach the fayz platform at ${config.apiUrl}`)\n }\n\n if (!response.ok) {\n const detail = await response.text().catch(() => '')\n throw new PlatformError(\n detail?.slice(0, 300) || `Platform returned ${response.status}`,\n response.status,\n )\n }\n return (await response.json()) as T\n}\n\nexport interface ListProjectsOptions {\n search?: string\n /** Keep only projects that have been published at least once. */\n publishedOnly?: boolean\n limit?: number\n}\n\n/** The organization's projects, newest activity first. */\nexport async function listPlatformProjects(\n options?: ListProjectsOptions,\n): Promise<PlatformProject[]> {\n const params = new URLSearchParams({ limit: String(options?.limit ?? 50) })\n if (options?.search) params.set('search', options.search)\n if (options?.publishedOnly) params.set('publishedOnly', 'true')\n\n const body = await call<{ projects: PlatformProject[] }>(`/v1/projects?${params}`)\n return body.projects ?? []\n}\n\n/** The platform's floor for a generation prompt — shorter is rejected server-side. */\nexport const PROMPT_MIN_CHARS = 10\n\n/**\n * Start a new site from a prompt.\n *\n * This is `POST /api/v1/generations`, not a project-create endpoint, because on\n * the platform those are the same act: the generations kickoff creates the\n * project AND starts building it, metering credits and capping concurrency on\n * the way. A separate create would make a project nothing is building.\n *\n * The returned project has no published URL yet — it has never been published.\n * Callers must link it in that state rather than waiting for a URL.\n */\nexport async function createPlatformProject(input: {\n prompt: string\n name?: string\n}): Promise<{ projectId: string }> {\n const body = await call<{ projectId: string }>('/v1/generations', {\n method: 'POST',\n body: JSON.stringify({\n prompt: input.prompt,\n ...(input.name ? { projectName: input.name } : {}),\n }),\n })\n return { projectId: body.projectId }\n}\n\n// ---------------------------------------------------------------------------\n// Preview containers\n// ---------------------------------------------------------------------------\n\nexport type PreviewStatus = 'PENDING' | 'STARTING' | 'RUNNING' | 'STOPPING' | 'STOPPED' | 'ERROR'\n\nexport interface PreviewState {\n projectId: string\n status: PreviewStatus\n /** Public preview origin, once a port exists to proxy to. */\n url: string | null\n /** Whether the dev server answered. Only present when asked for. */\n healthy?: boolean\n}\n\n/**\n * Read the preview's state — and keep it alive.\n *\n * The platform touches the container's `lastActiveAt` on this call, which is\n * what its idle reaper reads. So a client polling while the preview is on\n * screen is also the heartbeat: there is no separate keepalive to remember, and\n * no way to hold a container open without also watching it.\n */\nexport async function getPreview(\n projectId: string,\n options?: { checkHealth?: boolean },\n): Promise<PreviewState> {\n const query = options?.checkHealth ? '?checkHealth=true' : ''\n return call<PreviewState>(`/v1/previews/${encodeURIComponent(projectId)}${query}`)\n}\n\n/**\n * Start the project's preview container.\n *\n * Answers 202 as soon as the container exists, NOT when the app is reachable —\n * a cold start syncs the files and runs an npm install, which took ~24s on a\n * small project and no HTTP request should be held open for. `healthy` on\n * {@link getPreview} is the readiness signal.\n */\nexport async function startPreview(\n projectId: string,\n options?: { forceRestart?: boolean },\n): Promise<PreviewState> {\n return call<PreviewState>(`/v1/previews/${encodeURIComponent(projectId)}/start`, {\n method: 'POST',\n body: JSON.stringify({ ...(options?.forceRestart ? { forceRestart: true } : {}) }),\n })\n}\n\n/** Stop the container. Not called on unmount — see usePreviewContainer. */\nexport async function stopPreview(projectId: string): Promise<PreviewState> {\n return call<PreviewState>(`/v1/previews/${encodeURIComponent(projectId)}/stop`, {\n method: 'POST',\n body: JSON.stringify({}),\n })\n}\n\n// ---------------------------------------------------------------------------\n// Asking the platform's agent to change a project\n// ---------------------------------------------------------------------------\n\nexport interface ProjectChangeResult {\n projectId: string\n conversationId: string\n userMessageId: string\n acceptedAt: string\n}\n\n/**\n * Hand an instruction to the project's build agent.\n *\n * This is the seam between two assistants. The one in this admin knows the\n * merchant's business and is looking at the canvas with them; the one on the\n * platform is the only thing that can edit the app's source. Rather than\n * putting a second chat window on screen, the admin's assistant relays the\n * intent in one sentence and reports back — which is why the tool that calls\n * this is `builder_request_change` and not \"open the fayz editor\".\n *\n * Returns as soon as the build is ACCEPTED, not when it is done: a change takes\n * minutes. Callers watch {@link getGenerationStatus} and reload the canvas when\n * it goes quiet.\n */\nexport async function requestProjectChange(\n projectId: string,\n prompt: string,\n): Promise<ProjectChangeResult> {\n return call<ProjectChangeResult>(\n `/v1/generations/${encodeURIComponent(projectId)}/messages`,\n { method: 'POST', body: JSON.stringify({ prompt }) },\n )\n}\n\nexport interface GenerationStatus {\n /** READY / ERROR / GENERATING / … as the platform reports it. */\n status: string | null\n /** True while the agent is working. The signal to keep waiting. */\n building: boolean\n}\n\n/** Where a project's build has got to. Used to know when to reload the canvas. */\nexport async function getGenerationStatus(projectId: string): Promise<GenerationStatus> {\n const body = await call<{\n generationStatus?: string | null\n isTerminal?: boolean\n registry?: { hasActiveGeneration?: boolean } | null\n }>(`/v1/generations/${encodeURIComponent(projectId)}`)\n\n const status = body.generationStatus ?? null\n\n // Two sources, and the in-memory one is the more current: `registry` is the\n // live run, `isTerminal` is the row. A follow-up accepted seconds ago still\n // reads READY on the row for a moment, so trusting only that would reload the\n // canvas before the agent has written anything.\n if (body.registry?.hasActiveGeneration) return { status, building: true }\n if (typeof body.isTerminal === 'boolean') return { status, building: !body.isTerminal }\n\n return { status, building: status !== null && !TERMINAL_STATUSES.has(status) }\n}\n\nconst TERMINAL_STATUSES = new Set(['READY', 'ERROR', 'ABANDONED', 'MODERATED'])\n","import * as React from 'react'\nimport { Globe, Plus, ExternalLink, PenSquare, Star, Link2Off, Loader2, Sparkles, Search } from 'lucide-react'\nimport {\n Button,\n Input,\n PageHeaderActions,\n Modal,\n ModalContent,\n ModalHeader,\n ModalTitle,\n ModalDescription,\n ModalBody,\n ModalFooter,\n Textarea,\n} from '@fayz-ai/ui'\nimport { useOrganizationStore } from '../org/store'\nimport { useFayzProjectsStore, editorUrlOf } from './store'\nimport { createFayzProject, updateFayzProject, deleteFayzProject } from './provider'\nimport {\n isPlatformConnected,\n listPlatformProjects,\n createPlatformProject,\n PROMPT_MIN_CHARS,\n PlatformError,\n type PlatformProject,\n} from './platform'\nimport type { FayzProject } from './types'\nimport { describeError } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Sites — the tenant's fayz projects.\n//\n// This screen used to be a form: name, project id, preview URL, a kind pill row\n// and two checkboxes. Every one of those asked the merchant for something the\n// platform already knows, and two of them did nothing at all — `kind` only\n// chose the row's icon, and `storefront_enabled` had no reader anywhere in the\n// SDK. Typing a UUID and a URL by hand is also how a row ends up pointing at a\n// site that does not exist.\n//\n// So there is no form here any more. A site is either PICKED from the projects\n// the organization already has, or CREATED from a prompt — and in both cases\n// the id, the name and the published URL arrive from the platform. What remains\n// on the row is only what a person can genuinely decide: which site is the\n// default, and whether to stop tracking one.\n//\n// `preview_url` survives in the table as a CACHE, not an input: the sidebar\n// widget and the builder canvas read it synchronously, before any network call\n// could answer. `reconcile()` below refreshes it whenever this screen is open.\n// ---------------------------------------------------------------------------\n\nexport function ProjectsSettings() {\n const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id)\n const projects = useFayzProjectsStore((s) => s.projects)\n const load = useFayzProjectsStore((s) => s.load)\n const refresh = useFayzProjectsStore((s) => s.refresh)\n const [linking, setLinking] = React.useState(false)\n const connected = isPlatformConnected()\n\n React.useEffect(() => {\n void load(currentOrgId)\n }, [currentOrgId, load])\n\n // A published URL can change after the row was written — first publish, a\n // custom domain, a takedown. The row is a cache of the platform's answer, so\n // opening this screen is the moment to re-ask.\n React.useEffect(() => {\n if (!connected || projects.length === 0) return\n let cancelled = false\n void (async () => {\n try {\n const remote = await listPlatformProjects()\n if (cancelled) return\n const byId = new Map(remote.map((p) => [p.id, p]))\n const stale = projects.filter((p) => {\n const match = p.fayzProjectId ? byId.get(p.fayzProjectId) : undefined\n return match && (match.url ?? null) !== (p.previewUrl ?? null)\n })\n if (stale.length === 0) return\n await Promise.all(\n stale.map((p) =>\n updateFayzProject(p.id, { previewUrl: byId.get(p.fayzProjectId!)!.url }),\n ),\n )\n await refresh()\n } catch {\n // A refresh that fails leaves the cached URL in place, which is the\n // right outcome: the screen still works with yesterday's answer.\n }\n })()\n return () => {\n cancelled = true\n }\n // Keyed by the linked ids, not the array: refresh() replaces the array on\n // every write and would otherwise re-enter this effect forever.\n }, [connected, projects.map((p) => p.fayzProjectId).join(','), refresh])\n\n const onLinked = async () => {\n setLinking(false)\n await refresh()\n }\n\n return (\n <div className=\"space-y-4\">\n <PageHeaderActions>\n <Button size=\"sm\" onClick={() => setLinking(true)} disabled={!connected}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Vincular site\n </Button>\n </PageHeaderActions>\n\n {!connected && (\n <p className=\"rounded-card border border-dashed border-border p-4 text-sm text-muted-foreground\">\n Este app ainda não está ligado à sua conta fayz. Defina{' '}\n <code className=\"rounded bg-muted px-1 py-0.5 text-xs\">VITE_FAYZ_API_URL</code> e{' '}\n <code className=\"rounded bg-muted px-1 py-0.5 text-xs\">VITE_FAYZ_API_TOKEN</code> para\n escolher um site da sua conta.\n </p>\n )}\n\n {projects.length === 0 ? (\n <EmptyState connected={connected} onStart={() => setLinking(true)} />\n ) : (\n <div className=\"space-y-2\">\n {projects.map((p) => (\n <SiteRow\n key={p.id}\n project={p}\n showDefaultAction={projects.length > 1}\n onChanged={refresh}\n />\n ))}\n </div>\n )}\n\n {linking && <LinkSiteModal onClose={() => setLinking(false)} onLinked={onLinked} />}\n </div>\n )\n}\n\nfunction EmptyState({ connected, onStart }: { connected: boolean; onStart: () => void }) {\n return (\n <div className=\"rounded-card border border-dashed border-border p-8 text-center\">\n <span className=\"mx-auto mb-3 flex h-10 w-10 items-center justify-center rounded-full bg-primary/10\">\n <Globe className=\"h-5 w-5 text-primary\" />\n </span>\n <p className=\"text-sm font-medium text-foreground\">Nenhum site ainda</p>\n <p className=\"mx-auto mt-1 max-w-sm text-xs text-muted-foreground\">\n Escolha um site que já existe na sua conta fayz, ou descreva o que você quer e a gente cria.\n </p>\n {connected && (\n <Button size=\"sm\" className=\"mt-4\" onClick={onStart}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Vincular site\n </Button>\n )}\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\nfunction SiteRow({\n project,\n showDefaultAction,\n onChanged,\n}: {\n project: FayzProject\n showDefaultAction: boolean\n onChanged: () => Promise<void>\n}) {\n const [busy, setBusy] = React.useState(false)\n const editorUrl = editorUrlOf(project)\n\n const run = async (action: () => Promise<unknown>) => {\n setBusy(true)\n try {\n await action()\n await onChanged()\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <div className=\"flex items-center gap-3 rounded-card border border-border bg-card p-3\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-primary/10\">\n <Globe className=\"h-4 w-4 text-primary\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium text-foreground\">{project.name}</span>\n {project.isDefault && (\n <span className=\"rounded-full bg-emerald-100 px-2 py-0.5 text-[10px] font-semibold text-emerald-800\">\n padrão\n </span>\n )}\n </div>\n {project.previewUrl ? (\n <p className=\"truncate text-xs text-muted-foreground\">{project.previewUrl}</p>\n ) : (\n // Not an error and not \"no site\": the project exists and is being\n // built. Saying \"sem URL\" here read as something went wrong.\n <p className=\"truncate text-xs text-muted-foreground\">Ainda não publicado</p>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {project.previewUrl && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n title=\"Abrir\"\n onClick={() => window.open(project.previewUrl!, '_blank', 'noopener,noreferrer')}\n >\n <ExternalLink className=\"h-4 w-4\" />\n </Button>\n )}\n {editorUrl && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n title=\"Editar\"\n onClick={() => window.open(editorUrl, '_blank', 'noopener,noreferrer')}\n >\n <PenSquare className=\"h-4 w-4\" />\n </Button>\n )}\n {showDefaultAction && !project.isDefault && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n title=\"Definir como padrão\"\n disabled={busy}\n onClick={() => run(() => updateFayzProject(project.id, { isDefault: true }))}\n >\n <Star className=\"h-4 w-4\" />\n </Button>\n )}\n <Button\n size=\"sm\"\n variant=\"ghost\"\n // \"Desvincular\", never \"Excluir\": this removes the link from this\n // admin. The project keeps existing on fayz, and a label that implies\n // otherwise is the kind of thing nobody clicks twice.\n title=\"Desvincular deste painel\"\n disabled={busy}\n onClick={() => run(() => deleteFayzProject(project.id))}\n >\n <Link2Off className=\"h-4 w-4 text-muted-foreground\" />\n </Button>\n </div>\n </div>\n )\n}\n\n// ---------------------------------------------------------------------------\n// Link modal — pick one, or describe one\n// ---------------------------------------------------------------------------\n\ntype LinkMode = 'import' | 'create'\n\nfunction LinkSiteModal({ onClose, onLinked }: { onClose: () => void; onLinked: () => void }) {\n const [mode, setMode] = React.useState<LinkMode>('import')\n\n return (\n <Modal open onOpenChange={(open) => !open && onClose()}>\n <ModalContent size=\"lg\">\n <ModalHeader>\n <ModalTitle>Vincular um site</ModalTitle>\n <ModalDescription>\n Escolha um site da sua conta fayz, ou descreva o que você quer.\n </ModalDescription>\n </ModalHeader>\n\n <div className=\"flex gap-2\">\n <ModeTab active={mode === 'import'} onClick={() => setMode('import')}>\n <Search className=\"h-3.5 w-3.5\" /> Escolher um existente\n </ModeTab>\n <ModeTab active={mode === 'create'} onClick={() => setMode('create')}>\n <Sparkles className=\"h-3.5 w-3.5\" /> Criar com IA\n </ModeTab>\n </div>\n\n {mode === 'import' ? (\n <ImportPane onLinked={onLinked} />\n ) : (\n <CreatePane onLinked={onLinked} onCancel={onClose} />\n )}\n </ModalContent>\n </Modal>\n )\n}\n\nfunction ModeTab({\n active,\n onClick,\n children,\n}: {\n active: boolean\n onClick: () => void\n children: React.ReactNode\n}) {\n return (\n <Button\n variant=\"bare\"\n size=\"bare\"\n type=\"button\"\n onClick={onClick}\n className={`flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-medium transition-colors ${\n active ? 'bg-primary text-primary-foreground' : 'bg-muted text-muted-foreground hover:text-foreground'\n }`}\n >\n {children}\n </Button>\n )\n}\n\nfunction ImportPane({ onLinked }: { onLinked: () => void }) {\n const linked = useFayzProjectsStore((s) => s.projects)\n const [search, setSearch] = React.useState('')\n const [remote, setRemote] = React.useState<PlatformProject[] | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n const [linkingId, setLinkingId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let cancelled = false\n setError(null)\n // Debounced so typing does not fire a request per keystroke.\n const timer = setTimeout(() => {\n void (async () => {\n try {\n const list = await listPlatformProjects({ search: search || undefined })\n if (!cancelled) setRemote(list)\n } catch (cause) {\n if (!cancelled) {\n setRemote([])\n setError(cause instanceof PlatformError ? cause.message : 'Não foi possível listar os sites')\n }\n }\n })()\n }, search ? 300 : 0)\n return () => {\n cancelled = true\n clearTimeout(timer)\n }\n }, [search])\n\n const alreadyLinked = new Set(linked.map((p) => p.fayzProjectId).filter(Boolean) as string[])\n\n const link = async (project: PlatformProject) => {\n setLinkingId(project.id)\n try {\n await createFayzProject({\n name: project.name,\n fayzProjectId: project.id,\n previewUrl: project.url,\n // The first site a tenant links is its default; there is nothing to\n // choose between yet, and asking would be a checkbox with one option.\n isDefault: linked.length === 0,\n })\n onLinked()\n } catch (cause) {\n setError(describeError(cause, 'Não foi possível vincular'))\n setLinkingId(null)\n }\n }\n\n return (\n <ModalBody className=\"space-y-3\">\n <Input\n value={search}\n placeholder=\"Buscar pelo nome…\"\n onChange={(e) => setSearch(e.target.value)}\n />\n\n {error && <p className=\"text-xs text-destructive\">{error}</p>}\n\n {remote === null ? (\n <div className=\"flex items-center justify-center gap-2 py-8 text-sm text-muted-foreground\">\n <Loader2 className=\"h-4 w-4 animate-spin\" /> Carregando seus sites…\n </div>\n ) : remote.length === 0 ? (\n <p className=\"py-8 text-center text-sm text-muted-foreground\">\n {search ? 'Nenhum site com esse nome.' : 'Sua conta fayz ainda não tem sites.'}\n </p>\n ) : (\n <div className=\"max-h-72 space-y-1.5 overflow-y-auto\">\n {remote.map((project) => {\n const isLinked = alreadyLinked.has(project.id)\n return (\n <div\n key={project.id}\n className=\"flex items-center gap-3 rounded-md border border-border bg-card p-2.5\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-foreground\">{project.name}</p>\n <p className=\"truncate text-xs text-muted-foreground\">\n {project.moderated\n ? 'Site suspenso'\n : (project.url ?? 'Ainda não publicado')}\n </p>\n </div>\n <Button\n size=\"sm\"\n variant={isLinked ? 'ghost' : 'outline'}\n disabled={isLinked || linkingId !== null}\n onClick={() => link(project)}\n >\n {isLinked ? (\n 'Vinculado'\n ) : linkingId === project.id ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n 'Vincular'\n )}\n </Button>\n </div>\n )\n })}\n </div>\n )}\n </ModalBody>\n )\n}\n\nfunction CreatePane({ onLinked, onCancel }: { onLinked: () => void; onCancel: () => void }) {\n const linked = useFayzProjectsStore((s) => s.projects)\n const [prompt, setPrompt] = React.useState('')\n const [busy, setBusy] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const tooShort = prompt.trim().length < PROMPT_MIN_CHARS\n\n const submit = async () => {\n setBusy(true)\n setError(null)\n try {\n const { projectId } = await createPlatformProject({ prompt: prompt.trim() })\n await createFayzProject({\n // The platform names the project from the prompt while it builds; the\n // reconcile pass on the settings screen picks the real name up. Until\n // then the row needs something a person recognises.\n name: prompt.trim().slice(0, 60),\n fayzProjectId: projectId,\n // Nothing is published yet — the row is deliberately linked without a\n // URL rather than waiting for one.\n previewUrl: null,\n isDefault: linked.length === 0,\n })\n onLinked()\n } catch (cause) {\n setError(describeError(cause, 'Não foi possível criar o site'))\n setBusy(false)\n }\n }\n\n return (\n <>\n <ModalBody className=\"space-y-3\">\n <Textarea\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n rows={5}\n placeholder=\"Uma loja de café especial, com catálogo, página de assinatura e blog.\"\n className=\"px-2 py-1.5\"\n />\n <p className=\"text-xs text-muted-foreground\">\n O site é criado na sua conta fayz e começa a ser construído. Ele aparece aqui na hora, e a\n URL publicada chega quando a primeira publicação terminar.\n </p>\n {error && <p className=\"text-xs text-destructive\">{error}</p>}\n </ModalBody>\n <ModalFooter>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel} disabled={busy}>\n Cancelar\n </Button>\n <Button size=\"sm\" onClick={submit} disabled={busy || tooShort}>\n {busy && <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />} Criar site\n </Button>\n </ModalFooter>\n </>\n )\n}\n"]}
@@ -1,4 +1,5 @@
1
- import { getFayzSupabaseClient, useOrganizationStore } from './chunk-P6XUDT2P.js';
1
+ import { getFayzSupabaseClient } from './chunk-KJELMULA.js';
2
+ import { useOrganizationStore } from './chunk-YKPPCV2Z.js';
2
3
  import React3, { useState, useCallback, useEffect, useSyncExternalStore, useRef } from 'react';
3
4
  import { toast, Skeleton, Button, TooltipProvider, Badge, DatePicker, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Input, Modal, ModalContent, ModalHeader, ModalTitle, ModalDescription, ModalBody, Checkbox, ModalFooter, Tabs, TabsList, TabsTrigger, TimePicker, Tooltip, TooltipTrigger, TooltipContent, Card, CardContent, TabsContent, Switch, Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from '@fayz-ai/ui';
4
5
  import { getSupabaseClientOptional, globalCache, stableKey, useTranslation, todayLocal, localDateKey } from '@fayz-ai/core';
@@ -1715,5 +1716,5 @@ function ScheduleEditor({ assigneeId, onSaved, hideBookable }) {
1715
1716
  }
1716
1717
 
1717
1718
  export { ScheduleDateExceptions, ScheduleEditor, ScheduleGridPanel, createArchetypeLookup, deleteSchedule, getPersonBookable, getPersonLookup, getScheduleBlockConfig, getSchedules, mergeBlockSettings, parseBlockSettings, registerPersonLookup, replaceWeeklySchedules, saveSchedule, setPersonBookable, setScheduleBlockConfig, subscribeScheduleBlockConfig };
1718
- //# sourceMappingURL=chunk-JOBRLBIQ.js.map
1719
- //# sourceMappingURL=chunk-JOBRLBIQ.js.map
1719
+ //# sourceMappingURL=chunk-AFA6IO23.js.map
1720
+ //# sourceMappingURL=chunk-AFA6IO23.js.map