@oondemand/oon-core-front 0.4.28 → 0.4.29

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/index.js CHANGED
@@ -7,7 +7,7 @@ import { StrictMode } from "react";
7
7
  import { createRoot } from "react-dom/client";
8
8
 
9
9
  // src/app/OonApp.tsx
10
- import { useMemo as useMemo11 } from "react";
10
+ import { useMemo as useMemo12 } from "react";
11
11
  import { RouterProvider } from "react-router-dom";
12
12
 
13
13
  // src/api/createRestClient.ts
@@ -5089,147 +5089,750 @@ function CorePage2({ page, registry }) {
5089
5089
  }
5090
5090
 
5091
5091
  // src/components/CoreTransactionalEmail.tsx
5092
- import { useState as useState18 } from "react";
5092
+ import { useEffect as useEffect11, useMemo as useMemo11, useState as useState18 } from "react";
5093
5093
  import { Badge as Badge5, Box as Box22, Button as Button16, Flex as Flex15, Heading as Heading13, Input as Input10, Stack as Stack9, Text as Text23, Textarea as Textarea3 } from "@chakra-ui/react";
5094
5094
  import { useMutation as useMutation5, useQuery as useQuery11, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
5095
5095
  import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
5096
+ var EMPTY_SCHEMA = '{\n "type": "object",\n "additionalProperties": false,\n "properties": {}\n}';
5097
+ var EMPTY_DRAFT = {
5098
+ code: "",
5099
+ name: "",
5100
+ subject: "",
5101
+ htmlContent: "",
5102
+ textContent: "",
5103
+ variablesSchema: EMPTY_SCHEMA,
5104
+ locale: "pt-BR"
5105
+ };
5096
5106
  function errorMessage(error) {
5097
5107
  return error?.response?.data?.message || error?.message || "N\xE3o foi poss\xEDvel concluir a opera\xE7\xE3o.";
5098
5108
  }
5099
5109
  function color(status) {
5100
- if (["active", "provider_accepted"].includes(String(status))) return "green";
5101
- if (["degraded", "failed", "dead_letter"].includes(String(status))) return "red";
5110
+ if (["active", "provider_accepted", "valid"].includes(String(status))) return "green";
5111
+ if (["degraded", "invalid", "failed", "dead_letter"].includes(String(status))) return "red";
5102
5112
  return "yellow";
5103
5113
  }
5114
+ function prettyDate(value3) {
5115
+ return value3 ? new Intl.DateTimeFormat("pt-BR", { dateStyle: "short", timeStyle: "short" }).format(new Date(value3)) : "Ainda n\xE3o executado";
5116
+ }
5117
+ function sampleVariables(schema) {
5118
+ const properties = schema?.properties || {};
5119
+ const values = {};
5120
+ for (const [key, definition] of Object.entries(properties)) {
5121
+ if (definition.type === "number" || definition.type === "integer") values[key] = 0;
5122
+ else if (definition.type === "boolean") values[key] = false;
5123
+ else if (definition.type === "array") values[key] = [];
5124
+ else if (definition.type === "object") values[key] = {};
5125
+ else values[key] = "";
5126
+ }
5127
+ return JSON.stringify(values, null, 2);
5128
+ }
5129
+ function parseObject(source, message) {
5130
+ try {
5131
+ const value3 = JSON.parse(source);
5132
+ if (!value3 || typeof value3 !== "object" || Array.isArray(value3)) throw new Error(message);
5133
+ return value3;
5134
+ } catch {
5135
+ throw new Error(message);
5136
+ }
5137
+ }
5104
5138
  function CoreTransactionalEmail() {
5105
5139
  const { http } = useOonApi();
5106
5140
  const cache = useQueryClient7();
5107
5141
  const [tab, setTab] = useState18("config");
5108
- const [draft, setDraft] = useState18({ apiKey: "", senderEmail: "", senderName: "", replyTo: "", testRecipient: "" });
5109
5142
  const [error, setError] = useState18("");
5110
- const [templateDraft, setTemplateDraft] = useState18({ code: "", name: "", subject: "", htmlContent: "", textContent: "", variablesSchema: '{\n "type": "object",\n "additionalProperties": false\n}', locale: "pt-BR" });
5111
- const [templateTest, setTemplateTest] = useState18({ code: "", to: "", variables: "{}" });
5112
- const health = useQuery11({ queryKey: ["transactional-email", "health"], queryFn: async () => (await http.get("/core/transactional-email/health")).data });
5113
- const configuration = useQuery11({ queryKey: ["transactional-email", "configuration"], queryFn: async () => (await http.get("/core/transactional-email/configuration")).data.configuration });
5114
- const templates = useQuery11({ queryKey: ["transactional-email", "templates"], queryFn: async () => (await http.get("/core/transactional-email/templates")).data.results, enabled: tab === "templates" });
5115
- const dispatches = useQuery11({ queryKey: ["transactional-email", "dispatches"], queryFn: async () => (await http.get("/core/transactional-email/dispatches")).data.results, enabled: tab === "dispatches", refetchInterval: 1e4 });
5116
- const save = useMutation5({ mutationFn: async () => (await http.put("/core/transactional-email/configuration", { ...draft, enabled: true })).data, onSuccess: () => {
5117
- setDraft((value3) => ({ ...value3, apiKey: "" }));
5143
+ const [notice, setNotice] = useState18("");
5144
+ const [configurationDraft, setConfigurationDraft] = useState18({
5145
+ apiKey: "",
5146
+ senderEmail: "",
5147
+ senderName: "",
5148
+ replyTo: ""
5149
+ });
5150
+ const [configurationTestRecipient, setConfigurationTestRecipient] = useState18("");
5151
+ const [loadedConfigurationKey, setLoadedConfigurationKey] = useState18("");
5152
+ const [templateDraft, setTemplateDraft] = useState18(EMPTY_DRAFT);
5153
+ const [editingBase, setEditingBase] = useState18(null);
5154
+ const [previewTarget, setPreviewTarget] = useState18(null);
5155
+ const [previewVariables, setPreviewVariables] = useState18("{}");
5156
+ const [testTarget, setTestTarget] = useState18(null);
5157
+ const [templateTest, setTemplateTest] = useState18({ to: "", variables: "{}" });
5158
+ const health = useQuery11({
5159
+ queryKey: ["transactional-email", "health"],
5160
+ queryFn: async () => (await http.get("/core/transactional-email/health")).data
5161
+ });
5162
+ const configuration = useQuery11({
5163
+ queryKey: ["transactional-email", "configuration"],
5164
+ queryFn: async () => (await http.get("/core/transactional-email/configuration")).data.configuration
5165
+ });
5166
+ const templates = useQuery11({
5167
+ queryKey: ["transactional-email", "templates"],
5168
+ queryFn: async () => (await http.get("/core/transactional-email/templates")).data.results,
5169
+ enabled: tab === "templates"
5170
+ });
5171
+ const dispatches = useQuery11({
5172
+ queryKey: ["transactional-email", "dispatches"],
5173
+ queryFn: async () => (await http.get("/core/transactional-email/dispatches")).data.results,
5174
+ enabled: tab === "dispatches",
5175
+ refetchInterval: 1e4
5176
+ });
5177
+ const config = configuration.data;
5178
+ const configurationKey = [
5179
+ config?.updatedAt,
5180
+ config?.senderEmail,
5181
+ config?.senderName,
5182
+ config?.replyTo,
5183
+ config?.fingerprint
5184
+ ].join("|");
5185
+ useEffect11(() => {
5186
+ if (!config || configurationKey === loadedConfigurationKey) return;
5187
+ setConfigurationDraft({
5188
+ apiKey: "",
5189
+ senderEmail: config.senderEmail || "",
5190
+ senderName: config.senderName || "",
5191
+ replyTo: config.replyTo || ""
5192
+ });
5193
+ setConfigurationTestRecipient((value3) => value3 || config.senderEmail || "");
5194
+ setLoadedConfigurationKey(configurationKey);
5195
+ }, [config, configurationKey, loadedConfigurationKey]);
5196
+ const groupedTemplates = useMemo11(() => {
5197
+ var _a;
5198
+ const groups = {};
5199
+ for (const item of templates.data || []) (groups[_a = item.code] || (groups[_a] = [])).push(item);
5200
+ return Object.entries(groups);
5201
+ }, [templates.data]);
5202
+ const saveConfiguration = useMutation5({
5203
+ mutationFn: async () => {
5204
+ const payload = {
5205
+ senderEmail: configurationDraft.senderEmail,
5206
+ senderName: configurationDraft.senderName,
5207
+ replyTo: configurationDraft.replyTo,
5208
+ enabled: true
5209
+ };
5210
+ if (configurationDraft.apiKey.trim()) payload.apiKey = configurationDraft.apiKey.trim();
5211
+ return (await http.put("/core/transactional-email/configuration", payload)).data;
5212
+ },
5213
+ onSuccess: () => {
5214
+ setConfigurationDraft((value3) => ({ ...value3, apiKey: "" }));
5215
+ setError("");
5216
+ setNotice("Dados do remetente salvos. A credencial armazenada foi preservada.");
5217
+ cache.invalidateQueries({ queryKey: ["transactional-email"] });
5218
+ },
5219
+ onError: (reason) => {
5220
+ setNotice("");
5221
+ setError(errorMessage(reason));
5222
+ }
5223
+ });
5224
+ const testConfiguration = useMutation5({
5225
+ mutationFn: async () => (await http.post("/core/transactional-email/configuration/test", {
5226
+ recipient: configurationTestRecipient
5227
+ })).data,
5228
+ onSuccess: () => {
5229
+ setError("");
5230
+ setNotice("Teste enviado. Consulte a caixa do destinat\xE1rio e a aba Envios.");
5231
+ cache.invalidateQueries({ queryKey: ["transactional-email"] });
5232
+ },
5233
+ onError: (reason) => {
5234
+ setNotice("");
5235
+ setError(errorMessage(reason));
5236
+ cache.invalidateQueries({ queryKey: ["transactional-email"] });
5237
+ }
5238
+ });
5239
+ const createVersion = useMutation5({
5240
+ mutationFn: async () => http.post(
5241
+ "/core/transactional-email/templates/" + templateDraft.code + "/versions",
5242
+ {
5243
+ ...templateDraft,
5244
+ variablesSchema: parseObject(templateDraft.variablesSchema, "JSON Schema inv\xE1lido."),
5245
+ attachmentsPolicy: { allowed: false }
5246
+ }
5247
+ ),
5248
+ onSuccess: () => {
5249
+ setError("");
5250
+ setNotice("Nova vers\xE3o salva como rascunho. Ela ainda n\xE3o est\xE1 ativa.");
5251
+ setEditingBase(null);
5252
+ setTemplateDraft(EMPTY_DRAFT);
5253
+ cache.invalidateQueries({ queryKey: ["transactional-email", "templates"] });
5254
+ },
5255
+ onError: (reason) => {
5256
+ setNotice("");
5257
+ setError(errorMessage(reason));
5258
+ }
5259
+ });
5260
+ const activate = useMutation5({
5261
+ mutationFn: async (item) => http.post(
5262
+ "/core/transactional-email/templates/" + item.code + "/versions/" + item.version + "/activate"
5263
+ ),
5264
+ onSuccess: () => {
5265
+ setError("");
5266
+ setNotice("Vers\xE3o ativada manualmente.");
5267
+ cache.invalidateQueries({ queryKey: ["transactional-email", "templates"] });
5268
+ },
5269
+ onError: (reason) => {
5270
+ setNotice("");
5271
+ setError(errorMessage(reason));
5272
+ }
5273
+ });
5274
+ const preview = useMutation5({
5275
+ mutationFn: async (request) => (await http.post(
5276
+ "/core/transactional-email/templates/" + request.code + "/preview",
5277
+ {
5278
+ version: request.version,
5279
+ definition: request.definition,
5280
+ variables: request.variables
5281
+ }
5282
+ )).data,
5283
+ onSuccess: () => {
5284
+ setError("");
5285
+ setNotice("");
5286
+ },
5287
+ onError: (reason) => {
5288
+ setNotice("");
5289
+ setError(errorMessage(reason));
5290
+ }
5291
+ });
5292
+ const testTemplate = useMutation5({
5293
+ mutationFn: async () => {
5294
+ if (!testTarget) throw new Error("Selecione uma vers\xE3o para testar.");
5295
+ return http.post("/core/transactional-email/templates/" + testTarget.code + "/test", {
5296
+ version: testTarget.version,
5297
+ to: templateTest.to,
5298
+ variables: parseObject(templateTest.variables, "JSON de vari\xE1veis inv\xE1lido.")
5299
+ });
5300
+ },
5301
+ onSuccess: () => {
5302
+ setError("");
5303
+ setNotice("Teste da vers\xE3o " + testTarget?.version + " enfileirado sem alterar a vers\xE3o ativa.");
5304
+ cache.invalidateQueries({ queryKey: ["transactional-email", "dispatches"] });
5305
+ },
5306
+ onError: (reason) => {
5307
+ setNotice("");
5308
+ setError(errorMessage(reason));
5309
+ }
5310
+ });
5311
+ const retry = useMutation5({
5312
+ mutationFn: async (id) => http.post("/core/transactional-email/dispatches/" + id + "/retry"),
5313
+ onSuccess: () => cache.invalidateQueries({ queryKey: ["transactional-email", "dispatches"] }),
5314
+ onError: (reason) => setError(errorMessage(reason))
5315
+ });
5316
+ function useAsBase(item) {
5317
+ setEditingBase(item);
5318
+ setTemplateDraft({
5319
+ code: item.code,
5320
+ name: item.name,
5321
+ subject: item.subject,
5322
+ htmlContent: item.htmlContent,
5323
+ textContent: item.textContent,
5324
+ variablesSchema: JSON.stringify(item.variablesSchema || {}, null, 2),
5325
+ locale: item.locale || "pt-BR"
5326
+ });
5327
+ setNotice("Vers\xE3o " + item.version + " carregada como base. Ao salvar, uma nova vers\xE3o em rascunho ser\xE1 criada.");
5118
5328
  setError("");
5119
- cache.invalidateQueries({ queryKey: ["transactional-email"] });
5120
- }, onError: (reason) => setError(errorMessage(reason)) });
5121
- const retry = useMutation5({ mutationFn: async (id) => http.post(`/core/transactional-email/dispatches/${id}/retry`), onSuccess: () => cache.invalidateQueries({ queryKey: ["transactional-email", "dispatches"] }), onError: (reason) => setError(errorMessage(reason)) });
5122
- const createVersion = useMutation5({ mutationFn: async () => http.post(`/core/transactional-email/templates/${templateDraft.code}/versions`, { ...templateDraft, variablesSchema: JSON.parse(templateDraft.variablesSchema), attachmentsPolicy: { allowed: false } }), onSuccess: () => {
5329
+ }
5330
+ function selectPreview(item) {
5331
+ setPreviewTarget(item);
5332
+ setPreviewVariables(sampleVariables(item.variablesSchema));
5333
+ preview.reset();
5123
5334
  setError("");
5124
- cache.invalidateQueries({ queryKey: ["transactional-email", "templates"] });
5125
- }, onError: (reason) => setError(errorMessage(reason)) });
5126
- const activate = useMutation5({ mutationFn: async (item) => http.post(`/core/transactional-email/templates/${item.code}/versions/${item.version}/activate`), onSuccess: () => cache.invalidateQueries({ queryKey: ["transactional-email", "templates"] }), onError: (reason) => setError(errorMessage(reason)) });
5127
- const testTemplate = useMutation5({ mutationFn: async () => http.post(`/core/transactional-email/templates/${templateTest.code}/test`, { to: templateTest.to, variables: JSON.parse(templateTest.variables) }), onSuccess: () => {
5335
+ setNotice("");
5336
+ }
5337
+ function renderSavedPreview() {
5338
+ if (!previewTarget) return;
5339
+ try {
5340
+ preview.mutate({
5341
+ code: previewTarget.code,
5342
+ version: previewTarget.version,
5343
+ variables: parseObject(previewVariables, "JSON de vari\xE1veis inv\xE1lido.")
5344
+ });
5345
+ } catch (reason) {
5346
+ setError(errorMessage(reason));
5347
+ }
5348
+ }
5349
+ function renderDraftPreview() {
5350
+ try {
5351
+ const variablesSchema = parseObject(templateDraft.variablesSchema, "JSON Schema inv\xE1lido.");
5352
+ preview.mutate({
5353
+ code: templateDraft.code,
5354
+ definition: {
5355
+ ...templateDraft,
5356
+ variablesSchema,
5357
+ attachmentsPolicy: { allowed: false }
5358
+ },
5359
+ variables: parseObject(previewVariables, "JSON de vari\xE1veis inv\xE1lido.")
5360
+ });
5361
+ setPreviewTarget(null);
5362
+ } catch (reason) {
5363
+ setError(errorMessage(reason));
5364
+ }
5365
+ }
5366
+ function selectTest(item) {
5367
+ setTestTarget(item);
5368
+ setTemplateTest((value3) => ({
5369
+ to: value3.to || config?.senderEmail || "",
5370
+ variables: sampleVariables(item.variablesSchema)
5371
+ }));
5128
5372
  setError("");
5129
- cache.invalidateQueries({ queryKey: ["transactional-email", "dispatches"] });
5130
- }, onError: (reason) => setError(errorMessage(reason)) });
5131
- const config = configuration.data;
5373
+ setNotice("");
5374
+ }
5375
+ function activateVersion(item) {
5376
+ const confirmed = window.confirm(
5377
+ "Ativar " + item.code + " v" + item.version + "? A vers\xE3o ativa atual ser\xE1 arquivada."
5378
+ );
5379
+ if (confirmed) activate.mutate(item);
5380
+ }
5132
5381
  return /* @__PURE__ */ jsxs23(Stack9, { gap: 5, children: [
5133
5382
  /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", align: "center", wrap: "wrap", gap: 3, children: [
5134
5383
  /* @__PURE__ */ jsxs23(Box22, { children: [
5135
5384
  /* @__PURE__ */ jsx31(Heading13, { size: "lg", children: "E-mail transacional" }),
5136
- /* @__PURE__ */ jsx31(Text23, { color: "gray.600", children: "Configura\xE7\xE3o, templates e fila de envio deste App." })
5385
+ /* @__PURE__ */ jsx31(Text23, { color: "gray.600", children: "Configure o remetente, revise vers\xF5es e valide cada envio antes da ativa\xE7\xE3o." })
5137
5386
  ] }),
5138
5387
  /* @__PURE__ */ jsx31(Badge5, { colorPalette: color(health.data?.status), children: health.data?.status || "carregando" })
5139
5388
  ] }),
5140
- /* @__PURE__ */ jsx31(Flex15, { gap: 2, children: [["config", "Configura\xE7\xE3o"], ["templates", "Templates"], ["dispatches", "Envios"]].map(([id, label]) => /* @__PURE__ */ jsx31(Button16, { size: "sm", variant: tab === id ? "solid" : "outline", onClick: () => setTab(id), children: label }, id)) }),
5141
- error ? /* @__PURE__ */ jsx31(Box22, { borderWidth: "1px", borderColor: "red.200", bg: "red.50", p: 3, borderRadius: "md", children: /* @__PURE__ */ jsx31(Text23, { color: "red.700", children: error }) }) : null,
5142
- tab === "config" ? /* @__PURE__ */ jsx31(Box22, { borderWidth: "1px", borderRadius: "lg", p: 5, children: /* @__PURE__ */ jsxs23(Stack9, { gap: 4, children: [
5143
- /* @__PURE__ */ jsxs23(Flex15, { gap: 2, wrap: "wrap", children: [
5144
- /* @__PURE__ */ jsx31(Badge5, { colorPalette: config?.credentialConfigured ? "green" : "yellow", children: config?.credentialConfigured ? `Chave ${config.apiKeyMasked}` : "Chave pendente" }),
5145
- /* @__PURE__ */ jsx31(Badge5, { children: config?.connectionStatus || "n\xE3o testada" })
5389
+ /* @__PURE__ */ jsx31(Flex15, { gap: 2, wrap: "wrap", children: [
5390
+ ["config", "Configura\xE7\xE3o"],
5391
+ ["templates", "Templates"],
5392
+ ["dispatches", "Envios"]
5393
+ ].map(([id, label]) => /* @__PURE__ */ jsx31(Button16, { size: "sm", variant: tab === id ? "solid" : "outline", onClick: () => setTab(id), children: label }, id)) }),
5394
+ error ? /* @__PURE__ */ jsx31(Box22, { role: "alert", borderWidth: "1px", borderColor: "red.200", bg: "red.50", p: 3, borderRadius: "md", children: /* @__PURE__ */ jsx31(Text23, { color: "red.700", children: error }) }) : null,
5395
+ notice ? /* @__PURE__ */ jsx31(Box22, { role: "status", borderWidth: "1px", borderColor: "green.200", bg: "green.50", p: 3, borderRadius: "md", children: /* @__PURE__ */ jsx31(Text23, { color: "green.800", children: notice }) }) : null,
5396
+ tab === "config" ? /* @__PURE__ */ jsxs23(Stack9, { gap: 4, children: [
5397
+ /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: { base: 4, md: 5 }, children: [
5398
+ /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", align: "start", gap: 3, wrap: "wrap", mb: 5, children: [
5399
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5400
+ /* @__PURE__ */ jsx31(Heading13, { size: "sm", children: "Remetente e credencial" }),
5401
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", children: "Altere os dados abaixo sem informar novamente a API key j\xE1 protegida." })
5402
+ ] }),
5403
+ /* @__PURE__ */ jsxs23(Flex15, { gap: 2, wrap: "wrap", children: [
5404
+ /* @__PURE__ */ jsx31(Badge5, { colorPalette: config?.credentialConfigured ? "green" : "yellow", children: config?.credentialConfigured ? "Chave " + config.apiKeyMasked : "Chave pendente" }),
5405
+ /* @__PURE__ */ jsx31(Badge5, { colorPalette: color(config?.connectionStatus), children: config?.connectionStatus || "n\xE3o testada" })
5406
+ ] })
5407
+ ] }),
5408
+ /* @__PURE__ */ jsxs23(Stack9, { gap: 4, children: [
5409
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5410
+ /* @__PURE__ */ jsx31("label", { htmlFor: "transactional-sender-email", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "E-mail do remetente" }),
5411
+ /* @__PURE__ */ jsx31(
5412
+ Input10,
5413
+ {
5414
+ id: "transactional-sender-email",
5415
+ type: "email",
5416
+ mt: 1,
5417
+ value: configurationDraft.senderEmail,
5418
+ onChange: (event) => setConfigurationDraft({ ...configurationDraft, senderEmail: event.target.value })
5419
+ }
5420
+ )
5421
+ ] }),
5422
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5423
+ /* @__PURE__ */ jsx31("label", { htmlFor: "transactional-sender-name", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Nome do remetente" }),
5424
+ /* @__PURE__ */ jsx31(
5425
+ Input10,
5426
+ {
5427
+ id: "transactional-sender-name",
5428
+ mt: 1,
5429
+ value: configurationDraft.senderName,
5430
+ onChange: (event) => setConfigurationDraft({ ...configurationDraft, senderName: event.target.value })
5431
+ }
5432
+ )
5433
+ ] }),
5434
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5435
+ /* @__PURE__ */ jsx31("label", { htmlFor: "transactional-reply-to", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Responder para" }),
5436
+ /* @__PURE__ */ jsx31(
5437
+ Input10,
5438
+ {
5439
+ id: "transactional-reply-to",
5440
+ type: "email",
5441
+ mt: 1,
5442
+ placeholder: "Opcional",
5443
+ value: configurationDraft.replyTo,
5444
+ onChange: (event) => setConfigurationDraft({ ...configurationDraft, replyTo: event.target.value })
5445
+ }
5446
+ )
5447
+ ] }),
5448
+ /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "md", p: 4, bg: "gray.50", children: [
5449
+ /* @__PURE__ */ jsx31("label", { htmlFor: "transactional-api-key", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Trocar API key" }),
5450
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "xs", color: "gray.600", mb: 2, children: "Deixe em branco para manter a chave atual. O valor nunca ser\xE1 exibido depois de salvo." }),
5451
+ /* @__PURE__ */ jsx31(
5452
+ Input10,
5453
+ {
5454
+ id: "transactional-api-key",
5455
+ type: "password",
5456
+ autoComplete: "new-password",
5457
+ placeholder: "Nova API key SendGrid",
5458
+ bg: "white",
5459
+ value: configurationDraft.apiKey,
5460
+ onChange: (event) => setConfigurationDraft({ ...configurationDraft, apiKey: event.target.value })
5461
+ }
5462
+ )
5463
+ ] }),
5464
+ /* @__PURE__ */ jsx31(
5465
+ Button16,
5466
+ {
5467
+ alignSelf: "start",
5468
+ loading: saveConfiguration.isPending,
5469
+ onClick: () => saveConfiguration.mutate(),
5470
+ children: "Salvar altera\xE7\xF5es"
5471
+ }
5472
+ )
5473
+ ] })
5146
5474
  ] }),
5147
- /* @__PURE__ */ jsx31(Input10, { type: "password", autoComplete: "new-password", placeholder: "Nova API key SendGrid (write-only)", value: draft.apiKey, onChange: (event) => setDraft({ ...draft, apiKey: event.target.value }) }),
5148
- /* @__PURE__ */ jsx31(Input10, { placeholder: config?.senderEmail || "Remetente", value: draft.senderEmail, onChange: (event) => setDraft({ ...draft, senderEmail: event.target.value }) }),
5149
- /* @__PURE__ */ jsx31(Input10, { placeholder: config?.senderName || "Nome do remetente", value: draft.senderName, onChange: (event) => setDraft({ ...draft, senderName: event.target.value }) }),
5150
- /* @__PURE__ */ jsx31(Input10, { placeholder: config?.replyTo || "Reply-to", value: draft.replyTo, onChange: (event) => setDraft({ ...draft, replyTo: event.target.value }) }),
5151
- /* @__PURE__ */ jsx31(Input10, { placeholder: "Destinat\xE1rio do envio de teste", value: draft.testRecipient, onChange: (event) => setDraft({ ...draft, testRecipient: event.target.value }) }),
5152
- /* @__PURE__ */ jsx31(Button16, { alignSelf: "start", loading: save.isPending, onClick: () => save.mutate(), children: "Validar e ativar" })
5153
- ] }) }) : null,
5154
- tab === "templates" ? /* @__PURE__ */ jsxs23(Stack9, { gap: 4, children: [
5155
- /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: 5, children: [
5156
- /* @__PURE__ */ jsx31(Heading13, { size: "sm", mb: 3, children: "Nova vers\xE3o em rascunho" }),
5157
- /* @__PURE__ */ jsxs23(Stack9, { gap: 3, children: [
5158
- /* @__PURE__ */ jsxs23(Flex15, { gap: 3, wrap: "wrap", children: [
5159
- /* @__PURE__ */ jsx31(Input10, { flex: "1", minW: "180px", placeholder: "C\xF3digo declarado", value: templateDraft.code, onChange: (event) => setTemplateDraft({ ...templateDraft, code: event.target.value }) }),
5160
- /* @__PURE__ */ jsx31(Input10, { flex: "2", minW: "220px", placeholder: "Nome", value: templateDraft.name, onChange: (event) => setTemplateDraft({ ...templateDraft, name: event.target.value }) })
5475
+ /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: { base: 4, md: 5 }, children: [
5476
+ /* @__PURE__ */ jsx31(Heading13, { size: "sm", children: "Teste de entrega" }),
5477
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", mb: 4, children: "Refa\xE7a o teste com a chave e o remetente atualmente salvos." }),
5478
+ /* @__PURE__ */ jsxs23(Flex15, { gap: 3, align: "end", wrap: "wrap", children: [
5479
+ /* @__PURE__ */ jsxs23(Box22, { flex: "1", minW: "240px", children: [
5480
+ /* @__PURE__ */ jsx31("label", { htmlFor: "transactional-test-recipient", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Destinat\xE1rio do teste" }),
5481
+ /* @__PURE__ */ jsx31(
5482
+ Input10,
5483
+ {
5484
+ id: "transactional-test-recipient",
5485
+ type: "email",
5486
+ mt: 1,
5487
+ value: configurationTestRecipient,
5488
+ onChange: (event) => setConfigurationTestRecipient(event.target.value)
5489
+ }
5490
+ )
5491
+ ] }),
5492
+ /* @__PURE__ */ jsx31(
5493
+ Button16,
5494
+ {
5495
+ variant: "outline",
5496
+ loading: testConfiguration.isPending,
5497
+ disabled: !config?.credentialConfigured,
5498
+ onClick: () => testConfiguration.mutate(),
5499
+ children: "Enviar novo teste"
5500
+ }
5501
+ )
5502
+ ] }),
5503
+ /* @__PURE__ */ jsxs23(Text23, { mt: 3, fontSize: "xs", color: "gray.600", children: [
5504
+ "\xDAltimo teste: ",
5505
+ prettyDate(config?.lastTestAt),
5506
+ config?.lastError ? " \xB7 " + config.lastError : ""
5507
+ ] })
5508
+ ] })
5509
+ ] }) : null,
5510
+ tab === "templates" ? /* @__PURE__ */ jsxs23(Stack9, { gap: 5, children: [
5511
+ /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: { base: 4, md: 5 }, children: [
5512
+ /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", align: "start", gap: 3, wrap: "wrap", mb: 4, children: [
5513
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5514
+ /* @__PURE__ */ jsx31(Heading13, { size: "sm", children: "Templates e vers\xF5es" }),
5515
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", children: "Visualize, use uma vers\xE3o como base ou envie um teste sem alterar a publica\xE7\xE3o atual." })
5161
5516
  ] }),
5162
- /* @__PURE__ */ jsx31(Input10, { placeholder: "Assunto Handlebars", value: templateDraft.subject, onChange: (event) => setTemplateDraft({ ...templateDraft, subject: event.target.value }) }),
5163
- /* @__PURE__ */ jsx31(Textarea3, { placeholder: "HTML", value: templateDraft.htmlContent, onChange: (event) => setTemplateDraft({ ...templateDraft, htmlContent: event.target.value }) }),
5164
- /* @__PURE__ */ jsx31(Textarea3, { placeholder: "Texto simples", value: templateDraft.textContent, onChange: (event) => setTemplateDraft({ ...templateDraft, textContent: event.target.value }) }),
5165
- /* @__PURE__ */ jsx31(Textarea3, { "aria-label": "JSON Schema das vari\xE1veis", value: templateDraft.variablesSchema, onChange: (event) => setTemplateDraft({ ...templateDraft, variablesSchema: event.target.value }) }),
5166
- /* @__PURE__ */ jsx31(Button16, { alignSelf: "start", loading: createVersion.isPending, onClick: () => {
5167
- try {
5168
- JSON.parse(templateDraft.variablesSchema);
5169
- createVersion.mutate();
5170
- } catch {
5171
- setError("JSON Schema inv\xE1lido.");
5517
+ /* @__PURE__ */ jsx31(
5518
+ Button16,
5519
+ {
5520
+ size: "sm",
5521
+ variant: "outline",
5522
+ onClick: () => {
5523
+ setEditingBase(null);
5524
+ setTemplateDraft(EMPTY_DRAFT);
5525
+ setNotice("");
5526
+ },
5527
+ children: "Novo template"
5172
5528
  }
5173
- }, children: "Salvar rascunho" })
5529
+ )
5530
+ ] }),
5531
+ /* @__PURE__ */ jsxs23(Stack9, { gap: 4, children: [
5532
+ groupedTemplates.map(([code, versions]) => /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "md", overflow: "hidden", children: [
5533
+ /* @__PURE__ */ jsxs23(Flex15, { px: 4, py: 3, bg: "gray.50", justify: "space-between", align: "center", gap: 3, wrap: "wrap", children: [
5534
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5535
+ /* @__PURE__ */ jsx31(Text23, { fontWeight: "bold", children: versions[0]?.name || code }),
5536
+ /* @__PURE__ */ jsxs23(Text23, { fontSize: "xs", color: "gray.600", children: [
5537
+ code,
5538
+ " \xB7 ",
5539
+ versions.length,
5540
+ " vers\xE3o(\xF5es)"
5541
+ ] })
5542
+ ] }),
5543
+ versions.find((item) => item.status === "active") ? /* @__PURE__ */ jsxs23(Badge5, { colorPalette: "green", children: [
5544
+ "ativa v",
5545
+ versions.find((item) => item.status === "active")?.version
5546
+ ] }) : /* @__PURE__ */ jsx31(Badge5, { colorPalette: "yellow", children: "sem vers\xE3o ativa" })
5547
+ ] }),
5548
+ /* @__PURE__ */ jsx31(Stack9, { gap: 0, children: versions.map((item) => /* @__PURE__ */ jsxs23(
5549
+ Flex15,
5550
+ {
5551
+ px: 4,
5552
+ py: 3,
5553
+ borderTopWidth: "1px",
5554
+ justify: "space-between",
5555
+ align: "center",
5556
+ gap: 3,
5557
+ wrap: "wrap",
5558
+ children: [
5559
+ /* @__PURE__ */ jsxs23(Box22, { minW: "220px", flex: "1", children: [
5560
+ /* @__PURE__ */ jsxs23(Flex15, { gap: 2, align: "center", wrap: "wrap", children: [
5561
+ /* @__PURE__ */ jsxs23(Text23, { fontWeight: "semibold", children: [
5562
+ "Vers\xE3o ",
5563
+ item.version
5564
+ ] }),
5565
+ /* @__PURE__ */ jsx31(Badge5, { colorPalette: color(item.status), children: item.status }),
5566
+ /* @__PURE__ */ jsx31(Badge5, { variant: "outline", children: item.origin })
5567
+ ] }),
5568
+ /* @__PURE__ */ jsx31(Text23, { mt: 1, fontSize: "sm", color: "gray.700", children: item.subject }),
5569
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "xs", color: "gray.500", children: prettyDate(item.createdAt) })
5570
+ ] }),
5571
+ /* @__PURE__ */ jsxs23(Flex15, { gap: 2, wrap: "wrap", children: [
5572
+ /* @__PURE__ */ jsx31(Button16, { size: "xs", variant: "outline", onClick: () => selectPreview(item), children: "Visualizar" }),
5573
+ /* @__PURE__ */ jsx31(Button16, { size: "xs", variant: "outline", onClick: () => useAsBase(item), children: "Usar como base" }),
5574
+ /* @__PURE__ */ jsx31(Button16, { size: "xs", variant: "outline", onClick: () => selectTest(item), children: "Enviar teste" }),
5575
+ item.status !== "active" ? /* @__PURE__ */ jsx31(
5576
+ Button16,
5577
+ {
5578
+ size: "xs",
5579
+ loading: activate.isPending,
5580
+ onClick: () => activateVersion(item),
5581
+ children: "Ativar vers\xE3o"
5582
+ }
5583
+ ) : null
5584
+ ] })
5585
+ ]
5586
+ },
5587
+ item._id
5588
+ )) })
5589
+ ] }, code)),
5590
+ !templates.isLoading && !templates.data?.length ? /* @__PURE__ */ jsx31(Text23, { children: "Nenhum template declarado." }) : null
5174
5591
  ] })
5175
5592
  ] }),
5176
- templates.data?.map((item) => /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: 4, children: [
5177
- /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", gap: 3, children: [
5593
+ /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: { base: 4, md: 5 }, children: [
5594
+ /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", gap: 3, align: "start", wrap: "wrap", mb: 4, children: [
5178
5595
  /* @__PURE__ */ jsxs23(Box22, { children: [
5179
- /* @__PURE__ */ jsx31(Text23, { fontWeight: "semibold", children: item.name }),
5180
- /* @__PURE__ */ jsxs23(Text23, { fontSize: "sm", color: "gray.600", children: [
5181
- item.code,
5182
- " \xB7 vers\xE3o ",
5183
- item.version,
5184
- " \xB7 origem ",
5185
- item.origin
5596
+ /* @__PURE__ */ jsx31(Heading13, { size: "sm", children: editingBase ? "Nova vers\xE3o a partir de " + editingBase.code + " v" + editingBase.version : "Nova vers\xE3o em rascunho" }),
5597
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", children: "Salvar sempre cria uma nova vers\xE3o e nunca a ativa automaticamente." })
5598
+ ] }),
5599
+ editingBase ? /* @__PURE__ */ jsx31(Button16, { size: "sm", variant: "ghost", onClick: () => {
5600
+ setEditingBase(null);
5601
+ setTemplateDraft(EMPTY_DRAFT);
5602
+ }, children: "Cancelar edi\xE7\xE3o" }) : null
5603
+ ] }),
5604
+ /* @__PURE__ */ jsxs23(Stack9, { gap: 3, children: [
5605
+ /* @__PURE__ */ jsxs23(Flex15, { gap: 3, wrap: "wrap", children: [
5606
+ /* @__PURE__ */ jsxs23(Box22, { flex: "1", minW: "180px", children: [
5607
+ /* @__PURE__ */ jsx31("label", { htmlFor: "template-code", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "C\xF3digo" }),
5608
+ /* @__PURE__ */ jsx31(
5609
+ Input10,
5610
+ {
5611
+ id: "template-code",
5612
+ mt: 1,
5613
+ disabled: Boolean(editingBase),
5614
+ value: templateDraft.code,
5615
+ onChange: (event) => setTemplateDraft({ ...templateDraft, code: event.target.value })
5616
+ }
5617
+ )
5618
+ ] }),
5619
+ /* @__PURE__ */ jsxs23(Box22, { flex: "2", minW: "220px", children: [
5620
+ /* @__PURE__ */ jsx31("label", { htmlFor: "template-name", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Nome" }),
5621
+ /* @__PURE__ */ jsx31(
5622
+ Input10,
5623
+ {
5624
+ id: "template-name",
5625
+ mt: 1,
5626
+ value: templateDraft.name,
5627
+ onChange: (event) => setTemplateDraft({ ...templateDraft, name: event.target.value })
5628
+ }
5629
+ )
5186
5630
  ] })
5187
5631
  ] }),
5188
- /* @__PURE__ */ jsxs23(Stack9, { align: "end", children: [
5189
- /* @__PURE__ */ jsx31(Badge5, { colorPalette: color(item.status), children: item.status }),
5190
- item.status !== "active" ? /* @__PURE__ */ jsx31(Button16, { size: "xs", loading: activate.isPending, onClick: () => activate.mutate(item), children: item.status === "archived" ? "Reverter para esta vers\xE3o" : "Ativar" }) : null
5632
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5633
+ /* @__PURE__ */ jsx31("label", { htmlFor: "template-subject", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Assunto Handlebars" }),
5634
+ /* @__PURE__ */ jsx31(
5635
+ Input10,
5636
+ {
5637
+ id: "template-subject",
5638
+ mt: 1,
5639
+ value: templateDraft.subject,
5640
+ onChange: (event) => setTemplateDraft({ ...templateDraft, subject: event.target.value })
5641
+ }
5642
+ )
5643
+ ] }),
5644
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5645
+ /* @__PURE__ */ jsx31("label", { htmlFor: "template-html", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "HTML" }),
5646
+ /* @__PURE__ */ jsx31(
5647
+ Textarea3,
5648
+ {
5649
+ id: "template-html",
5650
+ mt: 1,
5651
+ minH: "240px",
5652
+ fontFamily: "mono",
5653
+ value: templateDraft.htmlContent,
5654
+ onChange: (event) => setTemplateDraft({ ...templateDraft, htmlContent: event.target.value })
5655
+ }
5656
+ ),
5657
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "xs", color: "gray.600", children: "Imagens embutidas com data:image/*;base64 s\xE3o aceitas; URLs remotas continuam bloqueadas." })
5658
+ ] }),
5659
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5660
+ /* @__PURE__ */ jsx31("label", { htmlFor: "template-text", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Texto simples" }),
5661
+ /* @__PURE__ */ jsx31(
5662
+ Textarea3,
5663
+ {
5664
+ id: "template-text",
5665
+ mt: 1,
5666
+ minH: "120px",
5667
+ value: templateDraft.textContent,
5668
+ onChange: (event) => setTemplateDraft({ ...templateDraft, textContent: event.target.value })
5669
+ }
5670
+ )
5671
+ ] }),
5672
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5673
+ /* @__PURE__ */ jsx31("label", { htmlFor: "template-schema", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "JSON Schema das vari\xE1veis" }),
5674
+ /* @__PURE__ */ jsx31(
5675
+ Textarea3,
5676
+ {
5677
+ id: "template-schema",
5678
+ mt: 1,
5679
+ minH: "180px",
5680
+ fontFamily: "mono",
5681
+ value: templateDraft.variablesSchema,
5682
+ onChange: (event) => setTemplateDraft({ ...templateDraft, variablesSchema: event.target.value })
5683
+ }
5684
+ )
5685
+ ] }),
5686
+ /* @__PURE__ */ jsxs23(Flex15, { gap: 2, wrap: "wrap", children: [
5687
+ /* @__PURE__ */ jsx31(
5688
+ Button16,
5689
+ {
5690
+ loading: createVersion.isPending,
5691
+ onClick: () => {
5692
+ try {
5693
+ parseObject(templateDraft.variablesSchema, "JSON Schema inv\xE1lido.");
5694
+ createVersion.mutate();
5695
+ } catch (reason) {
5696
+ setError(errorMessage(reason));
5697
+ }
5698
+ },
5699
+ children: "Salvar nova vers\xE3o"
5700
+ }
5701
+ ),
5702
+ /* @__PURE__ */ jsx31(
5703
+ Button16,
5704
+ {
5705
+ variant: "outline",
5706
+ loading: preview.isPending,
5707
+ disabled: !templateDraft.code,
5708
+ onClick: renderDraftPreview,
5709
+ children: "Pr\xE9-visualizar rascunho"
5710
+ }
5711
+ )
5191
5712
  ] })
5192
- ] }),
5193
- /* @__PURE__ */ jsx31(Text23, { mt: 2, fontSize: "sm", children: item.subject })
5194
- ] }, item._id)),
5195
- !templates.isLoading && !templates.data?.length ? /* @__PURE__ */ jsx31(Text23, { children: "Nenhum template declarado." }) : null,
5196
- /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: 5, children: [
5197
- /* @__PURE__ */ jsx31(Heading13, { size: "sm", mb: 3, children: "Envio de teste" }),
5713
+ ] })
5714
+ ] }),
5715
+ /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: { base: 4, md: 5 }, children: [
5716
+ /* @__PURE__ */ jsx31(Heading13, { size: "sm", children: "Pr\xE9-visualiza\xE7\xE3o" }),
5717
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", mb: 4, children: previewTarget ? previewTarget.code + " \xB7 vers\xE3o " + previewTarget.version : "Pr\xE9via do conte\xFAdo em edi\xE7\xE3o" }),
5718
+ /* @__PURE__ */ jsxs23(Stack9, { gap: 3, children: [
5719
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5720
+ /* @__PURE__ */ jsx31("label", { htmlFor: "preview-variables", style: { fontSize: "0.875rem", fontWeight: 600 }, children: "Vari\xE1veis de exemplo" }),
5721
+ /* @__PURE__ */ jsx31(
5722
+ Textarea3,
5723
+ {
5724
+ id: "preview-variables",
5725
+ mt: 1,
5726
+ minH: "120px",
5727
+ fontFamily: "mono",
5728
+ value: previewVariables,
5729
+ onChange: (event) => setPreviewVariables(event.target.value)
5730
+ }
5731
+ )
5732
+ ] }),
5733
+ previewTarget ? /* @__PURE__ */ jsx31(Button16, { alignSelf: "start", variant: "outline", loading: preview.isPending, onClick: renderSavedPreview, children: "Atualizar pr\xE9via" }) : null,
5734
+ preview.data ? /* @__PURE__ */ jsxs23(Stack9, { gap: 3, children: [
5735
+ /* @__PURE__ */ jsxs23(Box22, { bg: "gray.50", borderWidth: "1px", borderRadius: "md", p: 3, children: [
5736
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "xs", color: "gray.600", children: "Assunto renderizado" }),
5737
+ /* @__PURE__ */ jsx31(Text23, { fontWeight: "semibold", children: preview.data.subject })
5738
+ ] }),
5739
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5740
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", fontWeight: "semibold", mb: 1, children: "HTML" }),
5741
+ /* @__PURE__ */ jsx31(
5742
+ "iframe",
5743
+ {
5744
+ title: "Pr\xE9-visualiza\xE7\xE3o segura do template",
5745
+ sandbox: "",
5746
+ srcDoc: preview.data.html,
5747
+ style: { width: "100%", minHeight: 360, border: "1px solid #E2E8F0", borderRadius: 8, background: "white" }
5748
+ }
5749
+ )
5750
+ ] }),
5751
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5752
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", fontWeight: "semibold", mb: 1, children: "Texto simples" }),
5753
+ /* @__PURE__ */ jsx31(Box22, { as: "pre", whiteSpace: "pre-wrap", borderWidth: "1px", borderRadius: "md", p: 3, fontSize: "sm", children: preview.data.text })
5754
+ ] })
5755
+ ] }) : /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", children: "Selecione uma vers\xE3o ou use \u201CPr\xE9-visualizar rascunho\u201D." })
5756
+ ] })
5757
+ ] }),
5758
+ /* @__PURE__ */ jsxs23(Box22, { borderWidth: "1px", borderRadius: "lg", p: { base: 4, md: 5 }, children: [
5759
+ /* @__PURE__ */ jsx31(Heading13, { size: "sm", children: "Envio de teste da vers\xE3o" }),
5760
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", mb: 4, children: testTarget ? testTarget.code + " \xB7 vers\xE3o " + testTarget.version + " \xB7 " + testTarget.status : "Escolha \u201CEnviar teste\u201D em uma vers\xE3o da lista." }),
5198
5761
  /* @__PURE__ */ jsxs23(Stack9, { gap: 3, children: [
5199
- /* @__PURE__ */ jsx31(Input10, { placeholder: "C\xF3digo do template ativo", value: templateTest.code, onChange: (event) => setTemplateTest({ ...templateTest, code: event.target.value }) }),
5200
- /* @__PURE__ */ jsx31(Input10, { type: "email", placeholder: "Destinat\xE1rio", value: templateTest.to, onChange: (event) => setTemplateTest({ ...templateTest, to: event.target.value }) }),
5201
- /* @__PURE__ */ jsx31(Textarea3, { "aria-label": "Vari\xE1veis do teste", value: templateTest.variables, onChange: (event) => setTemplateTest({ ...templateTest, variables: event.target.value }) }),
5202
- /* @__PURE__ */ jsx31(Button16, { alignSelf: "start", loading: testTemplate.isPending, onClick: () => {
5203
- try {
5204
- JSON.parse(templateTest.variables);
5205
- testTemplate.mutate();
5206
- } catch {
5207
- setError("JSON de vari\xE1veis inv\xE1lido.");
5762
+ /* @__PURE__ */ jsx31(
5763
+ Input10,
5764
+ {
5765
+ type: "email",
5766
+ "aria-label": "Destinat\xE1rio do teste do template",
5767
+ placeholder: "Destinat\xE1rio",
5768
+ value: templateTest.to,
5769
+ onChange: (event) => setTemplateTest({ ...templateTest, to: event.target.value })
5770
+ }
5771
+ ),
5772
+ /* @__PURE__ */ jsx31(
5773
+ Textarea3,
5774
+ {
5775
+ "aria-label": "Vari\xE1veis do teste do template",
5776
+ minH: "120px",
5777
+ fontFamily: "mono",
5778
+ value: templateTest.variables,
5779
+ onChange: (event) => setTemplateTest({ ...templateTest, variables: event.target.value })
5780
+ }
5781
+ ),
5782
+ /* @__PURE__ */ jsx31(
5783
+ Button16,
5784
+ {
5785
+ alignSelf: "start",
5786
+ loading: testTemplate.isPending,
5787
+ disabled: !testTarget,
5788
+ onClick: () => {
5789
+ try {
5790
+ parseObject(templateTest.variables, "JSON de vari\xE1veis inv\xE1lido.");
5791
+ testTemplate.mutate();
5792
+ } catch (reason) {
5793
+ setError(errorMessage(reason));
5794
+ }
5795
+ },
5796
+ children: "Enfileirar teste desta vers\xE3o"
5208
5797
  }
5209
- }, children: "Enfileirar teste" })
5798
+ )
5210
5799
  ] })
5211
5800
  ] })
5212
5801
  ] }) : null,
5213
- tab === "dispatches" ? /* @__PURE__ */ jsx31(Stack9, { gap: 3, children: dispatches.data?.map((item) => /* @__PURE__ */ jsx31(Box22, { borderWidth: "1px", borderRadius: "lg", p: 4, children: /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", gap: 3, align: "start", children: [
5214
- /* @__PURE__ */ jsxs23(Box22, { children: [
5215
- /* @__PURE__ */ jsx31(Text23, { fontWeight: "semibold", children: item.templateCode }),
5216
- /* @__PURE__ */ jsxs23(Text23, { fontSize: "sm", color: "gray.600", children: [
5217
- item.correlationId,
5218
- " \xB7 ",
5219
- item.attempts,
5220
- " tentativa(s)"
5802
+ tab === "dispatches" ? /* @__PURE__ */ jsxs23(Stack9, { gap: 3, children: [
5803
+ /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", align: "center", gap: 3, wrap: "wrap", children: [
5804
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5805
+ /* @__PURE__ */ jsx31(Heading13, { size: "sm", children: "Envios recentes" }),
5806
+ /* @__PURE__ */ jsx31(Text23, { fontSize: "sm", color: "gray.600", children: "A lista \xE9 atualizada automaticamente a cada 10 segundos." })
5221
5807
  ] }),
5222
- item.lastError?.message ? /* @__PURE__ */ jsxs23(Text23, { color: "red.600", fontSize: "sm", children: [
5223
- item.lastError.code,
5224
- ": ",
5225
- item.lastError.message
5226
- ] }) : null
5808
+ /* @__PURE__ */ jsx31(Button16, { size: "sm", variant: "outline", onClick: () => dispatches.refetch(), children: "Atualizar agora" })
5227
5809
  ] }),
5228
- /* @__PURE__ */ jsxs23(Stack9, { align: "end", children: [
5229
- /* @__PURE__ */ jsx31(Badge5, { colorPalette: color(item.status), children: item.status }),
5230
- item.status === "dead_letter" ? /* @__PURE__ */ jsx31(Button16, { size: "xs", loading: retry.isPending, onClick: () => retry.mutate(item._id), children: "Reprocessar" }) : null
5231
- ] })
5232
- ] }) }, item._id)) }) : null
5810
+ dispatches.data?.map((item) => /* @__PURE__ */ jsx31(Box22, { borderWidth: "1px", borderRadius: "lg", p: 4, children: /* @__PURE__ */ jsxs23(Flex15, { justify: "space-between", gap: 3, align: "start", wrap: "wrap", children: [
5811
+ /* @__PURE__ */ jsxs23(Box22, { children: [
5812
+ /* @__PURE__ */ jsxs23(Text23, { fontWeight: "semibold", children: [
5813
+ item.templateCode,
5814
+ item.templateVersion ? " \xB7 vers\xE3o " + item.templateVersion : ""
5815
+ ] }),
5816
+ /* @__PURE__ */ jsxs23(Text23, { fontSize: "sm", color: "gray.600", children: [
5817
+ item.correlationId,
5818
+ " \xB7 ",
5819
+ item.attempts,
5820
+ " tentativa(s) \xB7 ",
5821
+ prettyDate(item.createdAt)
5822
+ ] }),
5823
+ item.lastError?.message ? /* @__PURE__ */ jsxs23(Text23, { color: "red.600", fontSize: "sm", children: [
5824
+ item.lastError.code,
5825
+ ": ",
5826
+ item.lastError.message
5827
+ ] }) : null
5828
+ ] }),
5829
+ /* @__PURE__ */ jsxs23(Stack9, { align: "end", children: [
5830
+ /* @__PURE__ */ jsx31(Badge5, { colorPalette: color(item.status), children: item.status }),
5831
+ item.status === "dead_letter" ? /* @__PURE__ */ jsx31(Button16, { size: "xs", loading: retry.isPending, onClick: () => retry.mutate(item._id), children: "Reprocessar" }) : null
5832
+ ] })
5833
+ ] }) }, item._id)),
5834
+ !dispatches.isLoading && !dispatches.data?.length ? /* @__PURE__ */ jsx31(Text23, { children: "Nenhum envio recente." }) : null
5835
+ ] }) : null
5233
5836
  ] });
5234
5837
  }
5235
5838
 
@@ -5545,7 +6148,7 @@ function Sidebar({ app, menu, registry }) {
5545
6148
  // package.json
5546
6149
  var package_default = {
5547
6150
  name: "@oondemand/oon-core-front",
5548
- version: "0.4.28",
6151
+ version: "0.4.29",
5549
6152
  repository: {
5550
6153
  type: "git",
5551
6154
  url: "git+https://github.com/oondemand/oon-platform.git",
@@ -6178,7 +6781,7 @@ function FirstAccessPage() {
6178
6781
  }
6179
6782
 
6180
6783
  // src/security/ActivationPage.tsx
6181
- import { useEffect as useEffect11, useState as useState22 } from "react";
6784
+ import { useEffect as useEffect12, useState as useState22 } from "react";
6182
6785
  import { Box as Box28, Button as Button21, Heading as Heading17, Input as Input13, Text as Text29, VStack as VStack7 } from "@chakra-ui/react";
6183
6786
  import { Fragment as Fragment6, jsx as jsx40, jsxs as jsxs29 } from "react/jsx-runtime";
6184
6787
  function encodeBasicCredentials2(email, password) {
@@ -6205,7 +6808,7 @@ function ActivationPage() {
6205
6808
  const [devResult, setDevResult] = useState22(null);
6206
6809
  const [error, setError] = useState22(null);
6207
6810
  const [submitting, setSubmitting] = useState22(false);
6208
- useEffect11(() => {
6811
+ useEffect12(() => {
6209
6812
  http.get("/ativacao/configuracao").then((response) => {
6210
6813
  setConfig(response.data);
6211
6814
  setGlobal(response.data.defaults || {});
@@ -6213,7 +6816,7 @@ function ActivationPage() {
6213
6816
  () => setError("N\xE3o foi poss\xEDvel carregar a configura\xE7\xE3o de ativa\xE7\xE3o.")
6214
6817
  );
6215
6818
  }, [http]);
6216
- useEffect11(() => {
6819
+ useEffect12(() => {
6217
6820
  if (activation.status === "active") {
6218
6821
  window.location.replace("/login");
6219
6822
  }
@@ -6687,7 +7290,7 @@ function localLoginUrl() {
6687
7290
  return `/login?redirect=${encodeURIComponent(current)}`;
6688
7291
  }
6689
7292
  function OonApp({ config }) {
6690
- const { http, storage, tenantStorage, router } = useMemo11(() => {
7293
+ const { http, storage, tenantStorage, router } = useMemo12(() => {
6691
7294
  const storage2 = createTokenStorage(config.app.id);
6692
7295
  const tenantStorage2 = createTenantStorage(config.app.id);
6693
7296
  const externalLoginUrl = config.auth?.loginUrl ?? config.api.meusAppsUrl;
@@ -6977,7 +7580,7 @@ function startFromManifest(manifest, runtime) {
6977
7580
  import { Stack as Stack16 } from "@chakra-ui/react";
6978
7581
 
6979
7582
  // src/components/CoreIntegration.tsx
6980
- import { useEffect as useEffect12, useState as useState23 } from "react";
7583
+ import { useEffect as useEffect13, useState as useState23 } from "react";
6981
7584
  import { Badge as Badge6, Box as Box29, Button as Button22, Flex as Flex21, Heading as Heading18, Input as Input14, Stack as Stack11, Text as Text30 } from "@chakra-ui/react";
6982
7585
  import { useMutation as useMutation6, useQuery as useQuery12 } from "@tanstack/react-query";
6983
7586
  import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
@@ -7161,7 +7764,7 @@ function ProviderConfigurationPanel({ provider }) {
7161
7764
  queryFn: async () => (await http.get(`/integrations/providers/${provider.key}/mappings`)).data
7162
7765
  });
7163
7766
  const selected = (configuration.data ?? []).find((item) => item.instanceId === draft.instanceId);
7164
- useEffect12(() => {
7767
+ useEffect13(() => {
7165
7768
  if (!selected) return;
7166
7769
  setDraft((current) => ({
7167
7770
  ...current,
@@ -7628,7 +8231,7 @@ function CoreIntegrationMappings() {
7628
8231
  }
7629
8232
 
7630
8233
  // src/components/CoreIntegrationTickets.tsx
7631
- import { useEffect as useEffect13, useMemo as useMemo12, useState as useState24 } from "react";
8234
+ import { useEffect as useEffect14, useMemo as useMemo13, useState as useState24 } from "react";
7632
8235
  import { Badge as Badge8, Box as Box31, Button as Button23, Flex as Flex23, Heading as Heading20, Input as Input15, Stack as Stack13, Text as Text32 } from "@chakra-ui/react";
7633
8236
  import { useMutation as useMutation7, useQuery as useQuery14 } from "@tanstack/react-query";
7634
8237
  import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
@@ -7861,7 +8464,7 @@ function CoreIntegrationTickets({ provider = "omie" }) {
7861
8464
  const [page, setPage] = useState24(1);
7862
8465
  const [expandedId, setExpandedId] = useState24(null);
7863
8466
  const limit = view === "board" ? 200 : 25;
7864
- useEffect13(() => {
8467
+ useEffect14(() => {
7865
8468
  const timeout = window.setTimeout(() => {
7866
8469
  setSearch(searchInput.trim());
7867
8470
  setPage(1);
@@ -7904,12 +8507,12 @@ function CoreIntegrationTickets({ provider = "omie" }) {
7904
8507
  await queue.refetch();
7905
8508
  }
7906
8509
  });
7907
- useEffect13(() => {
8510
+ useEffect14(() => {
7908
8511
  const totalPages2 = queue.data?.pagination?.totalPages ?? 1;
7909
8512
  if (page > totalPages2) setPage(Math.max(1, totalPages2));
7910
8513
  }, [page, queue.data?.pagination?.totalPages]);
7911
8514
  const tickets = queue.data?.results ?? [];
7912
- const grouped = useMemo12(() => Object.fromEntries(
8515
+ const grouped = useMemo13(() => Object.fromEntries(
7913
8516
  TICKET_STATUSES.map((ticketStatus) => [ticketStatus, tickets.filter((ticket) => ticket.status === ticketStatus)])
7914
8517
  ), [tickets]);
7915
8518
  if (queue.isLoading) return /* @__PURE__ */ jsx48(LoadingScreen, {});
@@ -8124,7 +8727,7 @@ import { useState as useState26 } from "react";
8124
8727
  import { Button as Button25, Flex as Flex25, Stack as Stack15 } from "@chakra-ui/react";
8125
8728
 
8126
8729
  // src/components/CoreOmieIntegration.tsx
8127
- import { useEffect as useEffect14, useState as useState25 } from "react";
8730
+ import { useEffect as useEffect15, useState as useState25 } from "react";
8128
8731
  import { Badge as Badge9, Box as Box32, Button as Button24, Flex as Flex24, Heading as Heading21, Input as Input16, Stack as Stack14, Text as Text33 } from "@chakra-ui/react";
8129
8732
  import { useMutation as useMutation8, useQuery as useQuery15 } from "@tanstack/react-query";
8130
8733
  import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
@@ -8206,7 +8809,7 @@ function OmieConfigurationTab() {
8206
8809
  appSecret: ""
8207
8810
  });
8208
8811
  const selected = (configuration.data ?? []).find((item) => item.instanceId === draft.instanceId) ?? configuration.data?.[0];
8209
- useEffect14(() => {
8812
+ useEffect15(() => {
8210
8813
  if (!selected) return;
8211
8814
  setDraft((current) => ({
8212
8815
  ...current,
@@ -8547,7 +9150,7 @@ function OmieWebhooksTab() {
8547
9150
  await Promise.all([access.refetch(), configuration.refetch()]);
8548
9151
  }
8549
9152
  });
8550
- useEffect14(() => {
9153
+ useEffect15(() => {
8551
9154
  const first = configuration.data?.[0]?.instanceId;
8552
9155
  if (first && !configuration.data?.some((item) => item.instanceId === instanceId)) setInstanceId(first);
8553
9156
  }, [configuration.data, instanceId]);