@oondemand/oon-core-front 0.3.29 → 0.3.31

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
@@ -1837,12 +1837,23 @@ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1837
1837
  function messageOf2(error) {
1838
1838
  return error instanceof Error ? error.message : typeof error === "string" ? error : "N\xE3o foi poss\xEDvel executar a a\xE7\xE3o.";
1839
1839
  }
1840
- function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh }) {
1840
+ function unwrap2(value) {
1841
+ if (!value || typeof value !== "object") return {};
1842
+ const record = value;
1843
+ const data = record.data;
1844
+ if (data && typeof data === "object") return data;
1845
+ return record;
1846
+ }
1847
+ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate }) {
1841
1848
  const { http } = useOonApi();
1842
1849
  const [loading, setLoading] = useState6(false);
1843
1850
  const [error, setError] = useState6(null);
1851
+ const [formOpen, setFormOpen] = useState6(false);
1852
+ const [formInitialValues, setFormInitialValues] = useState6({});
1853
+ const pipelineAction = action;
1844
1854
  if (evaluateCondition(action.hiddenWhen, row)) return null;
1845
1855
  const disabled = evaluateCondition(action.disabledWhen, row) || loading;
1856
+ const confirmAction = () => action.confirm ? window.confirm(action.confirm.description ?? action.confirm.title ?? `Executar ${action.label}?`) : true;
1846
1857
  const run = async () => {
1847
1858
  setError(null);
1848
1859
  if (action.type === "openDetailModal") return onOpenDetail?.(row, action.initialTab);
@@ -1851,9 +1862,38 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh }) {
1851
1862
  if (href) window.location.assign(interpolateEndpoint(href, row, parent));
1852
1863
  return;
1853
1864
  }
1854
- if (action.type !== "apiAction" || !action.endpoint) return;
1855
- const ok = action.confirm ? window.confirm(action.confirm.description ?? action.confirm.title ?? `Executar ${action.label}?`) : true;
1856
- if (!ok) return;
1865
+ if (pipelineAction.type === "formAction") {
1866
+ if (!confirmAction()) return;
1867
+ setLoading(true);
1868
+ try {
1869
+ let loaded = {};
1870
+ if (pipelineAction.loadEndpoint) {
1871
+ const url = interpolateEndpoint(pipelineAction.loadEndpoint, row, parent);
1872
+ loaded = unwrap2(await http.request({ url, method: "GET" }));
1873
+ }
1874
+ setFormInitialValues({ ...pipelineAction.initialValues ?? {}, ...loaded });
1875
+ setFormOpen(true);
1876
+ } catch (err) {
1877
+ setError(err);
1878
+ } finally {
1879
+ setLoading(false);
1880
+ }
1881
+ return;
1882
+ }
1883
+ if (pipelineAction.type === "setField" || pipelineAction.type === "transition") {
1884
+ if (!pipelineAction.field || !onUpdate || !confirmAction()) return;
1885
+ setLoading(true);
1886
+ try {
1887
+ await onUpdate({ [pipelineAction.field]: pipelineAction.value });
1888
+ onRefresh?.(pipelineAction.refresh);
1889
+ } catch (err) {
1890
+ setError(err);
1891
+ } finally {
1892
+ setLoading(false);
1893
+ }
1894
+ return;
1895
+ }
1896
+ if (action.type !== "apiAction" || !action.endpoint || !confirmAction()) return;
1857
1897
  setLoading(true);
1858
1898
  try {
1859
1899
  const url = interpolateEndpoint(action.endpoint, row, parent);
@@ -1867,13 +1907,50 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh }) {
1867
1907
  };
1868
1908
  return /* @__PURE__ */ jsxs8("span", { children: [
1869
1909
  /* @__PURE__ */ jsx12(Button5, { type: "button", size: "xs", minH: "28px", px: "9px", borderRadius: "6px", fontSize: "10px", loading, disabled, onClick: run, children: action.label }),
1870
- error ? /* @__PURE__ */ jsx12(Text7, { mt: "3px", color: "#B42318", fontSize: "9px", children: messageOf2(error) }) : null
1910
+ error ? /* @__PURE__ */ jsx12(Text7, { mt: "3px", color: "#B42318", fontSize: "9px", children: messageOf2(error) }) : null,
1911
+ formOpen && pipelineAction.type === "formAction" ? /* @__PURE__ */ jsx12(
1912
+ DynamicForm,
1913
+ {
1914
+ title: pipelineAction.title ?? pipelineAction.label,
1915
+ eyebrow: "A\xE7\xE3o",
1916
+ fields: pipelineAction.fields ?? [],
1917
+ initialValues: formInitialValues,
1918
+ submitting: loading,
1919
+ error,
1920
+ onSubmit: async (values) => {
1921
+ if (!pipelineAction.endpoint) return;
1922
+ setLoading(true);
1923
+ setError(null);
1924
+ try {
1925
+ const url = interpolateEndpoint(pipelineAction.endpoint, row, parent);
1926
+ await http.request({ url, method: pipelineAction.method ?? "POST", data: values });
1927
+ setFormOpen(false);
1928
+ onRefresh?.(pipelineAction.refresh);
1929
+ } catch (err) {
1930
+ setError(err);
1931
+ } finally {
1932
+ setLoading(false);
1933
+ }
1934
+ },
1935
+ onFieldChange: () => setError(null),
1936
+ onCancel: () => {
1937
+ if (!loading) setFormOpen(false);
1938
+ }
1939
+ }
1940
+ ) : null
1871
1941
  ] });
1872
1942
  }
1873
1943
 
1874
1944
  // src/components/internal/CoreRelatedGrid.tsx
1875
1945
  import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1876
- function CoreRelatedGrid({ tab, parent, relations, refreshToken, onRefresh }) {
1946
+ function CoreRelatedGrid({
1947
+ tab: rawTab,
1948
+ parent,
1949
+ relations,
1950
+ refreshToken,
1951
+ onRefresh
1952
+ }) {
1953
+ const tab = rawTab;
1877
1954
  const relation = relationFrom(tab.relation, relations);
1878
1955
  const schemaQuery = useModelSchema(relation?.model ?? "");
1879
1956
  const schema = schemaQuery.data;
@@ -1881,60 +1958,143 @@ function CoreRelatedGrid({ tab, parent, relations, refreshToken, onRefresh }) {
1881
1958
  const queryClient = useQueryClient();
1882
1959
  const parentValue = relation ? parent[relation.parentKey ?? "_id"] : void 0;
1883
1960
  const key = ["oon", "related", relation?.model, relation?.foreignKey, parentValue, refreshToken];
1884
- const query = useQuery5({ queryKey: key, enabled: !!relation && parentValue != null, queryFn: () => resource.list({ [relation.foreignKey]: parentValue, pageSize: 1e3 }) });
1885
- const columns = useMemo5(() => (tab.columns?.length ? tab.columns : schema?.fields.slice(0, 8).map((f) => f.name) ?? []).map((column) => normalizeColumn(column, schema)).filter((column) => !column.hidden), [tab.columns, schema]);
1961
+ const query = useQuery5({
1962
+ queryKey: key,
1963
+ enabled: !!relation && parentValue != null,
1964
+ queryFn: () => resource.list({ [relation.foreignKey]: parentValue, pageSize: 1e3 })
1965
+ });
1966
+ const columns = useMemo5(
1967
+ () => (tab.columns?.length ? tab.columns : schema?.fields.slice(0, 8).map((field) => field.name) ?? []).map((column) => normalizeColumn(column, schema)).filter((column) => !column.hidden),
1968
+ [tab.columns, schema]
1969
+ );
1886
1970
  const [drafts, setDrafts] = useState7({});
1887
1971
  const [errors, setErrors] = useState7({});
1972
+ const [creating, setCreating] = useState7(false);
1973
+ const [createError, setCreateError] = useState7(null);
1888
1974
  const editable = tab.type === "relatedGrid" && tab.editable && tab.editMode === "inline";
1889
- const mutation = useMutation({ mutationFn: ({ id, values }) => resource.update(id, values), onSuccess: () => {
1890
- queryClient.invalidateQueries({ queryKey: key });
1975
+ const canCreate = tab.type === "relatedGrid" && tab.create?.enabled !== false && !!tab.create;
1976
+ const canDelete = tab.type === "relatedGrid" && tab.delete?.enabled === true;
1977
+ const hasActions = editable || canDelete || !!tab.rowActions?.length;
1978
+ const invalidate = async () => {
1979
+ await queryClient.invalidateQueries({ queryKey: key });
1891
1980
  onRefresh?.(["self"]);
1892
- } });
1981
+ };
1982
+ const updateMutation = useMutation({
1983
+ mutationFn: ({ id, values }) => resource.update(id, values),
1984
+ onSuccess: invalidate
1985
+ });
1986
+ const createMutation = useMutation({
1987
+ mutationFn: (values) => resource.create({
1988
+ ...tab.create?.initialValues ?? {},
1989
+ ...values,
1990
+ ...relation && parentValue != null ? { [relation.foreignKey]: parentValue } : {}
1991
+ }),
1992
+ onSuccess: async () => {
1993
+ await invalidate();
1994
+ setCreating(false);
1995
+ setCreateError(null);
1996
+ },
1997
+ onError: setCreateError
1998
+ });
1999
+ const deleteMutation = useMutation({
2000
+ mutationFn: (id) => resource.delete(id),
2001
+ onSuccess: invalidate
2002
+ });
1893
2003
  if (!relation) return /* @__PURE__ */ jsx13(Text8, { color: "#B42318", children: "Rela\xE7\xE3o n\xE3o encontrada." });
1894
- if (query.isLoading) return /* @__PURE__ */ jsx13(Text8, { color: "#667085", children: "Carregando..." });
2004
+ if (query.isLoading || schemaQuery.isLoading) return /* @__PURE__ */ jsx13(Text8, { color: "#667085", children: "Carregando..." });
1895
2005
  const rows = query.data?.results ?? [];
1896
- const setDraft = (id, field, value) => setDrafts((current) => ({ ...current, [id]: { ...current[id] ?? {}, [field]: value } }));
1897
- return /* @__PURE__ */ jsx13(Box6, { overflowX: "auto", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "10px", children: /* @__PURE__ */ jsxs9(Table2.Root, { size: "sm", minW: "760px", children: [
1898
- /* @__PURE__ */ jsx13(Table2.Header, { children: /* @__PURE__ */ jsxs9(Table2.Row, { bg: "#F4F7F9", children: [
1899
- columns.map((c) => /* @__PURE__ */ jsx13(Table2.ColumnHeader, { fontSize: "10px", children: c.label ?? c.field }, c.field)),
1900
- editable || tab.rowActions?.length ? /* @__PURE__ */ jsx13(Table2.ColumnHeader, { children: "A\xE7\xF5es" }) : null
2006
+ const setDraft = (id, field, value) => setDrafts((current) => ({
2007
+ ...current,
2008
+ [id]: { ...current[id] ?? {}, [field]: value }
2009
+ }));
2010
+ const createFields = tab.create?.fields?.length ? tab.create.fields : formFieldsFromMeta(schema?.fields ?? []).filter((field) => ![relation.foreignKey, "_id", "createdAt", "updatedAt"].includes(field.field));
2011
+ return /* @__PURE__ */ jsxs9(Box6, { children: [
2012
+ canCreate ? /* @__PURE__ */ jsx13(Flex5, { justify: "flex-end", mb: "10px", children: /* @__PURE__ */ jsx13(Button6, { size: "sm", colorPalette: "brand", onClick: () => {
2013
+ setCreateError(null);
2014
+ setCreating(true);
2015
+ }, children: tab.create?.label ?? "Novo registro" }) }) : null,
2016
+ /* @__PURE__ */ jsx13(Box6, { overflowX: "auto", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "10px", children: /* @__PURE__ */ jsxs9(Table2.Root, { size: "sm", minW: "760px", children: [
2017
+ /* @__PURE__ */ jsx13(Table2.Header, { children: /* @__PURE__ */ jsxs9(Table2.Row, { bg: "#F4F7F9", children: [
2018
+ columns.map((column) => /* @__PURE__ */ jsx13(Table2.ColumnHeader, { fontSize: "10px", children: column.label ?? column.field }, column.field)),
2019
+ hasActions ? /* @__PURE__ */ jsx13(Table2.ColumnHeader, { children: "A\xE7\xF5es" }) : null
2020
+ ] }) }),
2021
+ /* @__PURE__ */ jsxs9(Table2.Body, { children: [
2022
+ rows.map((row, index) => {
2023
+ const id = String(row._id ?? row.id ?? index);
2024
+ const draft = drafts[id] ?? {};
2025
+ const dirty = Object.keys(draft).length > 0;
2026
+ return /* @__PURE__ */ jsxs9(Table2.Row, { bg: dirty ? "#FFFBEB" : index % 2 ? "#FBFCFD" : "white", children: [
2027
+ columns.map((column) => {
2028
+ const value = column.field in draft ? draft[column.field] : row[column.field];
2029
+ const meta = schema?.fields.find((field) => field.name === column.field);
2030
+ const canEdit = editable && column.readonly !== true && (column.editable === true || !column.readonly);
2031
+ return /* @__PURE__ */ jsx13(Table2.Cell, { fontSize: "11px", children: canEdit ? /* @__PURE__ */ jsx13(CoreInlineEditableCell, { column, meta, value, onChange: (next) => setDraft(id, column.field, next) }) : column.display === "badgeExists" ? /* @__PURE__ */ jsx13(Badge3, { colorPalette: value ? "green" : "gray", children: value ? "Sim" : "N\xE3o" }) : formatCell(value, column.kind) }, column.field);
2032
+ }),
2033
+ hasActions ? /* @__PURE__ */ jsx13(Table2.Cell, { children: /* @__PURE__ */ jsxs9(Flex5, { gap: "5px", align: "center", wrap: "wrap", children: [
2034
+ dirty ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
2035
+ /* @__PURE__ */ jsx13(
2036
+ Button6,
2037
+ {
2038
+ size: "xs",
2039
+ loading: updateMutation.isPending,
2040
+ onClick: () => {
2041
+ setErrors((current) => ({ ...current, [id]: void 0 }));
2042
+ updateMutation.mutate({ id, values: draft }, {
2043
+ onSuccess: () => setDrafts((current) => {
2044
+ const next = { ...current };
2045
+ delete next[id];
2046
+ return next;
2047
+ }),
2048
+ onError: (error) => setErrors((current) => ({ ...current, [id]: error }))
2049
+ });
2050
+ },
2051
+ children: "Salvar"
2052
+ }
2053
+ ),
2054
+ /* @__PURE__ */ jsx13(Button6, { size: "xs", variant: "outline", onClick: () => setDrafts((current) => {
2055
+ const next = { ...current };
2056
+ delete next[id];
2057
+ return next;
2058
+ }), children: "Cancelar" })
2059
+ ] }) : null,
2060
+ tab.rowActions?.map((action) => /* @__PURE__ */ jsx13(CoreRowAction, { action, row, parent, onRefresh }, action.id ?? action.label)),
2061
+ canDelete ? /* @__PURE__ */ jsx13(
2062
+ Button6,
2063
+ {
2064
+ size: "xs",
2065
+ variant: "outline",
2066
+ loading: deleteMutation.isPending,
2067
+ onClick: () => {
2068
+ const message = tab.delete?.confirm ?? "Excluir este registro relacionado?";
2069
+ if (window.confirm(message)) deleteMutation.mutate(id);
2070
+ },
2071
+ children: "Excluir"
2072
+ }
2073
+ ) : null,
2074
+ errors[id] ? /* @__PURE__ */ jsx13(Text8, { color: "#B42318", fontSize: "9px", children: "Erro ao salvar." }) : null
2075
+ ] }) }) : null
2076
+ ] }, id);
2077
+ }),
2078
+ rows.length === 0 ? /* @__PURE__ */ jsx13(Table2.Row, { children: /* @__PURE__ */ jsx13(Table2.Cell, { colSpan: columns.length + (hasActions ? 1 : 0), children: /* @__PURE__ */ jsx13(Text8, { p: "8", textAlign: "center", color: "#98A2B3", children: "Nenhum registro relacionado." }) }) }) : null
2079
+ ] })
1901
2080
  ] }) }),
1902
- /* @__PURE__ */ jsxs9(Table2.Body, { children: [
1903
- rows.map((row, index) => {
1904
- const id = String(row._id ?? row.id ?? index);
1905
- const draft = drafts[id] ?? {};
1906
- const dirty = Object.keys(draft).length > 0;
1907
- return /* @__PURE__ */ jsxs9(Table2.Row, { bg: dirty ? "#FFFBEB" : index % 2 ? "#FBFCFD" : "white", children: [
1908
- columns.map((column) => {
1909
- const value = column.field in draft ? draft[column.field] : row[column.field];
1910
- const meta = schema?.fields.find((f) => f.name === column.field);
1911
- const canEdit = editable && column.readonly !== true && (column.editable === true || !column.readonly);
1912
- return /* @__PURE__ */ jsx13(Table2.Cell, { fontSize: "11px", children: canEdit ? /* @__PURE__ */ jsx13(CoreInlineEditableCell, { column, meta, value, onChange: (next) => setDraft(id, column.field, next) }) : column.display === "badgeExists" ? /* @__PURE__ */ jsx13(Badge3, { colorPalette: value ? "green" : "gray", children: value ? "Sim" : "N\xE3o" }) : formatCell(value, column.kind) }, column.field);
1913
- }),
1914
- editable || tab.rowActions?.length ? /* @__PURE__ */ jsx13(Table2.Cell, { children: /* @__PURE__ */ jsxs9(Flex5, { gap: "5px", align: "center", wrap: "wrap", children: [
1915
- dirty ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
1916
- /* @__PURE__ */ jsx13(Button6, { size: "xs", loading: mutation.isPending, onClick: () => {
1917
- setErrors((e) => ({ ...e, [id]: void 0 }));
1918
- mutation.mutate({ id, values: draft }, { onSuccess: () => setDrafts((d) => {
1919
- const n = { ...d };
1920
- delete n[id];
1921
- return n;
1922
- }), onError: (err) => setErrors((e) => ({ ...e, [id]: err })) });
1923
- }, children: "Salvar" }),
1924
- /* @__PURE__ */ jsx13(Button6, { size: "xs", variant: "outline", onClick: () => setDrafts((d) => {
1925
- const n = { ...d };
1926
- delete n[id];
1927
- return n;
1928
- }), children: "Cancelar" })
1929
- ] }) : null,
1930
- tab.rowActions?.map((action) => /* @__PURE__ */ jsx13(CoreRowAction, { action, row, parent, onRefresh }, action.id ?? action.label)),
1931
- errors[id] ? /* @__PURE__ */ jsx13(Text8, { color: "#B42318", fontSize: "9px", children: "Erro ao salvar." }) : null
1932
- ] }) }) : null
1933
- ] }, id);
1934
- }),
1935
- rows.length === 0 ? /* @__PURE__ */ jsx13(Table2.Row, { children: /* @__PURE__ */ jsx13(Table2.Cell, { colSpan: columns.length + 1, children: /* @__PURE__ */ jsx13(Text8, { p: "8", textAlign: "center", color: "#98A2B3", children: "Nenhum registro relacionado." }) }) }) : null
1936
- ] })
1937
- ] }) });
2081
+ creating ? /* @__PURE__ */ jsx13(
2082
+ DynamicForm,
2083
+ {
2084
+ title: tab.create?.label ?? `Novo ${schema?.singular ?? relation.model}`,
2085
+ eyebrow: "Registro relacionado",
2086
+ fields: createFields,
2087
+ initialValues: tab.create?.initialValues,
2088
+ submitting: createMutation.isPending,
2089
+ error: createError,
2090
+ onSubmit: (values) => createMutation.mutate(values),
2091
+ onFieldChange: () => setCreateError(null),
2092
+ onCancel: () => {
2093
+ if (!createMutation.isPending) setCreating(false);
2094
+ }
2095
+ }
2096
+ ) : null
2097
+ ] });
1938
2098
  }
1939
2099
 
1940
2100
  // src/components/internal/CoreTabbedDetail.tsx
@@ -2337,6 +2497,7 @@ function CoreDetailModal({
2337
2497
  initialRecord,
2338
2498
  initialTab,
2339
2499
  relations,
2500
+ actions,
2340
2501
  onClose,
2341
2502
  onSaved
2342
2503
  }) {
@@ -2363,7 +2524,6 @@ function CoreDetailModal({
2363
2524
  const list = targets?.length ? targets : ["self"];
2364
2525
  if (list.includes("parent") || list.includes("all")) {
2365
2526
  if (recordId) queryClient.invalidateQueries({ queryKey: ["oon", "detail", model, recordId] });
2366
- onSaved?.();
2367
2527
  }
2368
2528
  setRefreshTokens((current) => {
2369
2529
  const next = { ...current };
@@ -2383,12 +2543,15 @@ function CoreDetailModal({
2383
2543
  const width = config.size === "full" ? "98vw" : config.size === "md" ? "760px" : config.size === "lg" ? "980px" : "1180px";
2384
2544
  const displayTitle = parent?.[config.titleField ?? ""] ? String(parent[config.titleField ?? ""]) : title;
2385
2545
  return /* @__PURE__ */ jsx15(Flex7, { position: "fixed", inset: 0, zIndex: 1e3, align: "center", justify: "center", p: 4, bg: "rgba(15,23,42,.48)", children: /* @__PURE__ */ jsxs11(Box8, { role: "dialog", "aria-modal": "true", w: `min(${width}, 98vw)`, maxH: "94vh", overflow: "hidden", bg: "white", borderRadius: "14px", boxShadow: "0 24px 70px rgba(15,23,42,.24)", children: [
2386
- /* @__PURE__ */ jsxs11(Flex7, { minH: "72px", px: "20px", align: "center", justify: "space-between", borderBottomWidth: "1px", borderColor: "#E5E9ED", children: [
2546
+ /* @__PURE__ */ jsxs11(Flex7, { minH: "72px", px: "20px", align: "center", justify: "space-between", gap: 4, borderBottomWidth: "1px", borderColor: "#E5E9ED", children: [
2387
2547
  /* @__PURE__ */ jsxs11(Box8, { children: [
2388
2548
  /* @__PURE__ */ jsx15(Text10, { color: "#0474AF", fontSize: "10px", fontWeight: "700", textTransform: "uppercase", children: "Detalhe" }),
2389
2549
  /* @__PURE__ */ jsx15(Heading3, { size: "md", children: recordId ? displayTitle : `Novo ${title}` })
2390
2550
  ] }),
2391
- /* @__PURE__ */ jsx15(Button8, { onClick: onClose, children: "Fechar" })
2551
+ /* @__PURE__ */ jsxs11(Flex7, { align: "center", justify: "flex-end", gap: "6px", wrap: "wrap", children: [
2552
+ recordId ? actions : null,
2553
+ /* @__PURE__ */ jsx15(Button8, { onClick: onClose, children: "Fechar" })
2554
+ ] })
2392
2555
  ] }),
2393
2556
  /* @__PURE__ */ jsx15(Box8, { maxH: "calc(94vh - 73px)", p: "20px", overflowY: "auto", children: schemaQuery.isLoading || parentQuery.isLoading ? /* @__PURE__ */ jsx15(Text10, { children: "Carregando..." }) : /* @__PURE__ */ jsx15(
2394
2557
  CoreTabbedDetail,
@@ -2404,7 +2567,7 @@ function CoreDetailModal({
2404
2567
  onRefresh: refresh,
2405
2568
  onParentSaved: (saved) => {
2406
2569
  setParent(saved);
2407
- onSaved?.();
2570
+ onSaved?.(saved);
2408
2571
  refresh(["parent"]);
2409
2572
  }
2410
2573
  }
@@ -2554,7 +2717,7 @@ function CoreDocument({ model, label, endpoint, columns, form }) {
2554
2717
 
2555
2718
  // src/components/CorePipeline.tsx
2556
2719
  import { useState as useState11 } from "react";
2557
- import { Badge as Badge4, Box as Box10, Button as Button9, Flex as Flex8, Heading as Heading5, Stack as Stack5, Text as Text12 } from "@chakra-ui/react";
2720
+ import { Badge as Badge4, Box as Box10, Button as Button9, Flex as Flex8, Heading as Heading5, Input as Input6, NativeSelect as NativeSelect5, Stack as Stack5, Text as Text12 } from "@chakra-ui/react";
2558
2721
  import { useMutation as useMutation3, useQuery as useQuery7, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2559
2722
  import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2560
2723
  function ticketId(row) {
@@ -2571,6 +2734,49 @@ function mergeFormFields2(metadataFields, overrides) {
2571
2734
  });
2572
2735
  return merged;
2573
2736
  }
2737
+ function PipelineFilterControl({
2738
+ filter,
2739
+ value,
2740
+ meta,
2741
+ onChange
2742
+ }) {
2743
+ if (filter.type === "ref" && meta?.ref) {
2744
+ return /* @__PURE__ */ jsx18(Box10, { w: "220px", children: /* @__PURE__ */ jsx18(
2745
+ ReferenceSelect,
2746
+ {
2747
+ field: filter.field,
2748
+ inputId: `pipeline-filter-${filter.field}`,
2749
+ label: filter.label ?? filter.field,
2750
+ refModel: meta.ref,
2751
+ value: String(value ?? ""),
2752
+ initialValue: value,
2753
+ required: false,
2754
+ invalid: false,
2755
+ filters: {},
2756
+ disabled: false,
2757
+ onChange: (next) => onChange(next)
2758
+ }
2759
+ ) });
2760
+ }
2761
+ if (filter.type === "select") {
2762
+ return /* @__PURE__ */ jsxs13(NativeSelect5.Root, { size: "sm", w: "190px", children: [
2763
+ /* @__PURE__ */ jsx18(NativeSelect5.Field, { value: String(value ?? ""), onChange: (event) => onChange(event.currentTarget.value), children: (filter.options ?? []).map((option) => /* @__PURE__ */ jsx18("option", { value: String(option.value ?? ""), children: option.label }, String(option.value ?? ""))) }),
2764
+ /* @__PURE__ */ jsx18(NativeSelect5.Indicator, {})
2765
+ ] });
2766
+ }
2767
+ return /* @__PURE__ */ jsx18(
2768
+ Input6,
2769
+ {
2770
+ w: "190px",
2771
+ h: "35px",
2772
+ fontSize: "11px",
2773
+ type: filter.type === "date" ? "date" : "text",
2774
+ placeholder: filter.placeholder ?? filter.label ?? filter.field,
2775
+ value: String(value ?? ""),
2776
+ onChange: (event) => onChange(event.currentTarget.value)
2777
+ }
2778
+ );
2779
+ }
2574
2780
  function CorePipeline({
2575
2781
  model,
2576
2782
  label,
@@ -2580,116 +2786,196 @@ function CorePipeline({
2580
2786
  titleField,
2581
2787
  form,
2582
2788
  relations,
2583
- ticketModal
2789
+ ticketModal,
2790
+ filters = [],
2791
+ create,
2792
+ viewModes = ["board"],
2793
+ defaultView,
2794
+ list,
2795
+ ticketActions = []
2584
2796
  }) {
2585
2797
  const schemaQuery = useModelSchema(model);
2586
2798
  const schema = schemaQuery.data;
2587
2799
  const basePath = endpoint ?? schema?.basePath ?? `/${model.toLowerCase()}s`;
2588
2800
  const resource = useOonResource(basePath);
2589
2801
  const queryClient = useQueryClient4();
2802
+ const allowedViewModes = viewModes.length ? viewModes : ["board"];
2803
+ const initialView = defaultView && allowedViewModes.includes(defaultView) ? defaultView : allowedViewModes[0] ?? "board";
2804
+ const [viewMode, setViewMode] = useState11(initialView);
2805
+ const [filterValues, setFilterValues] = useState11(
2806
+ () => Object.fromEntries(filters.map((filter) => [filter.field, filter.defaultValue ?? ""]))
2807
+ );
2590
2808
  const [selectedTicket, setSelectedTicket] = useState11(null);
2809
+ const [creating, setCreating] = useState11(false);
2591
2810
  const [formError, setFormError] = useState11(null);
2811
+ const effectiveFilters = Object.fromEntries(
2812
+ Object.entries(filterValues).filter(([, value]) => value !== "" && value != null)
2813
+ );
2592
2814
  const listQuery = useQuery7({
2593
- queryKey: ["oon", "pipeline", basePath],
2594
- queryFn: () => resource.list({ pageSize: 200 }),
2595
- enabled: !!schema
2815
+ queryKey: ["oon", "pipeline", basePath, effectiveFilters],
2816
+ queryFn: () => resource.list({ pageSize: 200, ...effectiveFilters }),
2817
+ enabled: !!schema && viewMode === "board"
2596
2818
  });
2597
- const invalidate = () => queryClient.invalidateQueries({ queryKey: ["oon", "pipeline", basePath] });
2819
+ const invalidate = async () => {
2820
+ await Promise.all([
2821
+ queryClient.invalidateQueries({ queryKey: ["oon", "pipeline", basePath] }),
2822
+ queryClient.invalidateQueries({ queryKey: ["oon", "list", basePath] })
2823
+ ]);
2824
+ };
2598
2825
  const saveMutation = useMutation3({
2599
2826
  mutationFn: (values) => {
2600
2827
  const id = selectedTicket ? ticketId(selectedTicket) : void 0;
2601
- if (!id) throw new Error("N\xE3o foi poss\xEDvel identificar o ticket selecionado.");
2602
- return resource.update(id, values);
2828
+ return id ? resource.update(id, values) : resource.create(values);
2603
2829
  },
2604
2830
  onSuccess: async () => {
2605
2831
  await invalidate();
2606
2832
  setSelectedTicket(null);
2833
+ setCreating(false);
2607
2834
  setFormError(null);
2608
2835
  },
2609
2836
  onError: (error) => setFormError(error)
2610
2837
  });
2611
- if (schemaQuery.isLoading || listQuery.isLoading) return /* @__PURE__ */ jsx18(LoadingScreen, {});
2838
+ if (schemaQuery.isLoading || viewMode === "board" && listQuery.isLoading) return /* @__PURE__ */ jsx18(LoadingScreen, {});
2612
2839
  if (schemaQuery.isError) return /* @__PURE__ */ jsx18(ErrorState, { error: schemaQuery.error });
2613
- if (listQuery.isError) return /* @__PURE__ */ jsx18(ErrorState, { error: listQuery.error });
2840
+ if (viewMode === "board" && listQuery.isError) return /* @__PURE__ */ jsx18(ErrorState, { error: listQuery.error });
2614
2841
  const stageFieldMeta = schema?.fields.find((field) => field.name === stageField);
2615
2842
  const resolvedStages = stages ?? (stageFieldMeta?.options ?? []).map((option) => ({ id: option, label: option }));
2616
2843
  const resolvedTitleField = titleField ?? ticketModal?.titleField ?? schema?.fields.find((field) => field.kind === "string")?.name ?? schema?.searchable[0] ?? "_id";
2617
- const detailFields = (schema?.fields ?? []).filter((field) => field.name !== stageField && field.name !== resolvedTitleField && !["raw"].includes(field.kind)).slice(0, 3);
2844
+ const detailFields = (schema?.fields ?? []).filter((field) => field.name !== stageField && field.name !== resolvedTitleField && field.kind !== "raw").slice(0, 3);
2618
2845
  const formFields = mergeFormFields2(formFieldsFromMeta(schema?.fields ?? []), form);
2846
+ const resolvedListColumns = list?.columns?.length ? list.columns.map((column) => normalizeColumn(column, schema)) : columnsFromMeta(schema?.fields ?? []).slice(0, 10);
2619
2847
  const rows = listQuery.data?.results ?? [];
2620
2848
  const byStage = /* @__PURE__ */ new Map();
2621
2849
  for (const stage of resolvedStages) byStage.set(stage.id, []);
2622
2850
  for (const row of rows) {
2623
2851
  const key = String(row[stageField] ?? "");
2624
2852
  if (!byStage.has(key)) byStage.set(key, []);
2625
- byStage.get(key).push(row);
2853
+ byStage.get(key)?.push(row);
2626
2854
  }
2855
+ const openCreate = () => {
2856
+ const defaultStage = create?.defaultStage ?? resolvedStages[0]?.id;
2857
+ setFormError(null);
2858
+ setCreating(true);
2859
+ setSelectedTicket({
2860
+ ...create?.defaultValues ?? {},
2861
+ ...defaultStage ? { [stageField]: defaultStage } : {}
2862
+ });
2863
+ };
2864
+ const modalActions = selectedTicket && !creating ? /* @__PURE__ */ jsx18(Flex8, { gap: "5px", align: "center", wrap: "wrap", children: ticketActions.map((action, index) => /* @__PURE__ */ jsx18(
2865
+ CoreRowAction,
2866
+ {
2867
+ action,
2868
+ row: selectedTicket,
2869
+ onUpdate: async (values) => {
2870
+ const id = ticketId(selectedTicket);
2871
+ if (!id) throw new Error("Ticket sem identificador.");
2872
+ const saved = await resource.update(id, values);
2873
+ setSelectedTicket((current) => ({ ...current ?? {}, ...saved, ...values }));
2874
+ await invalidate();
2875
+ return saved;
2876
+ },
2877
+ onRefresh: () => {
2878
+ void invalidate();
2879
+ }
2880
+ },
2881
+ action.id ?? `${action.label}-${index}`
2882
+ )) }) : null;
2627
2883
  return /* @__PURE__ */ jsxs13(Stack5, { gap: 5, children: [
2628
- /* @__PURE__ */ jsxs13(Box10, { children: [
2629
- /* @__PURE__ */ jsx18(Text12, { fontSize: "11px", fontWeight: "700", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", mb: 1, children: "Esteira de processo" }),
2630
- /* @__PURE__ */ jsx18(Heading5, { size: "lg", color: "#24323A", letterSpacing: "-0.02em", children: label ?? schema?.name ?? model }),
2631
- /* @__PURE__ */ jsx18(Text12, { mt: 1, fontSize: "13px", color: "gray.500", children: "Acompanhe os tickets por etapa e visualize os principais dados de cada item." })
2884
+ /* @__PURE__ */ jsxs13(Flex8, { align: { base: "stretch", md: "flex-end" }, justify: "space-between", gap: 4, direction: { base: "column", md: "row" }, children: [
2885
+ /* @__PURE__ */ jsxs13(Box10, { children: [
2886
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "11px", fontWeight: "700", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", mb: 1, children: "Esteira de processo" }),
2887
+ /* @__PURE__ */ jsx18(Heading5, { size: "lg", color: "#24323A", letterSpacing: "-0.02em", children: label ?? schema?.name ?? model }),
2888
+ /* @__PURE__ */ jsx18(Text12, { mt: 1, fontSize: "13px", color: "gray.500", children: "Acompanhe os tickets por etapa e visualize os principais dados de cada item." })
2889
+ ] }),
2890
+ /* @__PURE__ */ jsxs13(Flex8, { gap: "8px", align: "center", wrap: "wrap", children: [
2891
+ allowedViewModes.length > 1 ? allowedViewModes.map((mode) => /* @__PURE__ */ jsx18(Button9, { size: "sm", variant: viewMode === mode ? "solid" : "outline", colorPalette: "brand", onClick: () => setViewMode(mode), children: mode === "board" ? "Quadro" : "Lista" }, mode)) : null,
2892
+ create?.enabled ? /* @__PURE__ */ jsx18(Button9, { size: "sm", colorPalette: "brand", onClick: openCreate, children: create.label ?? "Novo ticket" }) : null
2893
+ ] })
2632
2894
  ] }),
2633
- /* @__PURE__ */ jsx18(Flex8, { gap: 4, align: "stretch", overflowX: "auto", pb: 3, minH: "420px", children: Array.from(byStage.entries()).map(([stageId, items]) => {
2634
- const stageLabel = resolvedStages.find((stage) => stage.id === stageId)?.label ?? (stageId || "Sem etapa");
2635
- return /* @__PURE__ */ jsxs13(
2636
- Box10,
2895
+ filters.length ? /* @__PURE__ */ jsxs13(Flex8, { p: "12px", gap: "10px", align: "flex-end", wrap: "wrap", bg: "white", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "10px", children: [
2896
+ filters.map((filter) => {
2897
+ const meta = schema?.fields.find((field) => field.name === filter.field);
2898
+ return /* @__PURE__ */ jsxs13(Box10, { children: [
2899
+ /* @__PURE__ */ jsx18(Text12, { mb: "4px", fontSize: "10px", color: "#667085", fontWeight: "600", children: filter.label ?? fieldLabel({ name: filter.field }) }),
2900
+ /* @__PURE__ */ jsx18(
2901
+ PipelineFilterControl,
2902
+ {
2903
+ filter,
2904
+ value: filterValues[filter.field],
2905
+ meta,
2906
+ onChange: (value) => setFilterValues((current) => ({ ...current, [filter.field]: value }))
2907
+ }
2908
+ )
2909
+ ] }, filter.field);
2910
+ }),
2911
+ /* @__PURE__ */ jsx18(
2912
+ Button9,
2637
2913
  {
2638
- minW: "300px",
2639
- maxW: "340px",
2640
- flex: "1 0 300px",
2641
- bg: "#E8ECEF",
2642
- borderRadius: "12px",
2643
- p: 3,
2644
- borderWidth: "1px",
2645
- borderColor: "#DDE3E7",
2646
- children: [
2647
- /* @__PURE__ */ jsxs13(Flex8, { align: "center", justify: "space-between", mb: 3, px: 1, children: [
2648
- /* @__PURE__ */ jsx18(Text12, { fontWeight: "700", fontSize: "12px", color: "#33434C", textTransform: "uppercase", letterSpacing: "0.03em", children: stageLabel }),
2649
- /* @__PURE__ */ jsx18(Badge4, { colorPalette: "brand", variant: "solid", borderRadius: "full", minW: "24px", justifyContent: "center", children: items.length })
2650
- ] }),
2651
- /* @__PURE__ */ jsx18(Stack5, { gap: 2, children: items.length === 0 ? /* @__PURE__ */ jsx18(Box10, { borderWidth: "1px", borderStyle: "dashed", borderColor: "#C8D0D5", borderRadius: "10px", p: 5, textAlign: "center", children: /* @__PURE__ */ jsx18(Text12, { fontSize: "12px", color: "gray.500", children: "Nenhum ticket nesta etapa." }) }) : items.map((row, index) => {
2652
- const ticketTitle = formatCell(row[resolvedTitleField], "string");
2653
- return /* @__PURE__ */ jsxs13(
2654
- Button9,
2655
- {
2656
- type: "button",
2657
- variant: "plain",
2658
- display: "block",
2659
- w: "100%",
2660
- h: "auto",
2661
- minH: "auto",
2662
- p: 3,
2663
- bg: "white",
2664
- borderRadius: "10px",
2665
- borderWidth: "1px",
2666
- borderColor: "#DDE3E7",
2667
- boxShadow: "0 3px 10px rgba(7, 38, 46, 0.05)",
2668
- textAlign: "left",
2669
- whiteSpace: "normal",
2670
- transition: "all 0.15s ease",
2671
- "aria-label": `Abrir ticket ${ticketTitle}`,
2672
- onClick: () => {
2673
- setFormError(null);
2674
- setSelectedTicket(row);
2675
- },
2676
- _hover: { borderColor: "brand.300", transform: "translateY(-1px)", boxShadow: "0 7px 18px rgba(7, 38, 46, 0.09)" },
2677
- _focusVisible: { borderColor: "brand.500", boxShadow: "0 0 0 3px rgba(4, 116, 175, 0.16)" },
2678
- children: [
2679
- /* @__PURE__ */ jsx18(Text12, { fontSize: "13px", fontWeight: "700", color: "#24323A", mb: 2, lineClamp: 2, children: ticketTitle }),
2680
- /* @__PURE__ */ jsx18(Stack5, { gap: 1, children: detailFields.map((field) => /* @__PURE__ */ jsxs13(Flex8, { gap: 2, align: "baseline", justify: "space-between", children: [
2681
- /* @__PURE__ */ jsx18(Text12, { fontSize: "10px", color: "gray.500", textTransform: "uppercase", letterSpacing: "0.03em", children: fieldLabel(field) }),
2682
- /* @__PURE__ */ jsx18(Text12, { fontSize: "11px", color: "#46545C", fontWeight: "500", textAlign: "right", lineClamp: 1, children: formatCell(row[field.name], field.kind) })
2683
- ] }, field.name)) })
2684
- ]
2685
- },
2686
- ticketId(row) ?? index
2687
- );
2688
- }) })
2689
- ]
2690
- },
2691
- stageId
2692
- );
2914
+ size: "sm",
2915
+ variant: "outline",
2916
+ onClick: () => setFilterValues(Object.fromEntries(filters.map((filter) => [filter.field, filter.defaultValue ?? ""]))),
2917
+ children: "Limpar filtros"
2918
+ }
2919
+ )
2920
+ ] }) : null,
2921
+ viewMode === "list" ? /* @__PURE__ */ jsx18(
2922
+ DataGrid,
2923
+ {
2924
+ resource,
2925
+ resourceKey: basePath,
2926
+ columns: resolvedListColumns,
2927
+ filters: [],
2928
+ queryExtra: effectiveFilters,
2929
+ onEdit: (row) => {
2930
+ setCreating(false);
2931
+ setSelectedTicket(row);
2932
+ }
2933
+ }
2934
+ ) : /* @__PURE__ */ jsx18(Flex8, { gap: 4, align: "stretch", overflowX: "auto", pb: 3, minH: "420px", children: Array.from(byStage.entries()).map(([stageId, items]) => {
2935
+ const stageLabel = resolvedStages.find((stage) => stage.id === stageId)?.label ?? (stageId || "Sem etapa");
2936
+ return /* @__PURE__ */ jsxs13(Box10, { minW: "300px", maxW: "340px", flex: "1 0 300px", bg: "#E8ECEF", borderRadius: "12px", p: 3, borderWidth: "1px", borderColor: "#DDE3E7", children: [
2937
+ /* @__PURE__ */ jsxs13(Flex8, { align: "center", justify: "space-between", mb: 3, px: 1, children: [
2938
+ /* @__PURE__ */ jsx18(Text12, { fontWeight: "700", fontSize: "12px", color: "#33434C", textTransform: "uppercase", letterSpacing: "0.03em", children: stageLabel }),
2939
+ /* @__PURE__ */ jsx18(Badge4, { colorPalette: "brand", variant: "solid", borderRadius: "full", minW: "24px", justifyContent: "center", children: items.length })
2940
+ ] }),
2941
+ /* @__PURE__ */ jsx18(Stack5, { gap: 2, children: items.length === 0 ? /* @__PURE__ */ jsx18(Box10, { borderWidth: "1px", borderStyle: "dashed", borderColor: "#C8D0D5", borderRadius: "10px", p: 5, textAlign: "center", children: /* @__PURE__ */ jsx18(Text12, { fontSize: "12px", color: "gray.500", children: "Nenhum ticket nesta etapa." }) }) : items.map((row, index) => {
2942
+ const ticketTitle = formatCell(row[resolvedTitleField], "string");
2943
+ return /* @__PURE__ */ jsxs13(
2944
+ Button9,
2945
+ {
2946
+ type: "button",
2947
+ variant: "plain",
2948
+ display: "block",
2949
+ w: "100%",
2950
+ h: "auto",
2951
+ minH: "auto",
2952
+ p: 3,
2953
+ bg: "white",
2954
+ borderRadius: "10px",
2955
+ borderWidth: "1px",
2956
+ borderColor: "#DDE3E7",
2957
+ boxShadow: "0 3px 10px rgba(7, 38, 46, 0.05)",
2958
+ textAlign: "left",
2959
+ whiteSpace: "normal",
2960
+ "aria-label": `Abrir ticket ${ticketTitle}`,
2961
+ onClick: () => {
2962
+ setFormError(null);
2963
+ setCreating(false);
2964
+ setSelectedTicket(row);
2965
+ },
2966
+ _hover: { borderColor: "brand.300", transform: "translateY(-1px)", boxShadow: "0 7px 18px rgba(7, 38, 46, 0.09)" },
2967
+ children: [
2968
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "13px", fontWeight: "700", color: "#24323A", mb: 2, lineClamp: 2, children: ticketTitle }),
2969
+ /* @__PURE__ */ jsx18(Stack5, { gap: 1, children: detailFields.map((field) => /* @__PURE__ */ jsxs13(Flex8, { gap: 2, align: "baseline", justify: "space-between", children: [
2970
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "10px", color: "gray.500", textTransform: "uppercase", letterSpacing: "0.03em", children: fieldLabel(field) }),
2971
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "11px", color: "#46545C", fontWeight: "500", textAlign: "right", lineClamp: 1, children: formatCell(row[field.name], field.kind) })
2972
+ ] }, field.name)) })
2973
+ ]
2974
+ },
2975
+ ticketId(row) ?? index
2976
+ );
2977
+ }) })
2978
+ ] }, stageId);
2693
2979
  }) }),
2694
2980
  selectedTicket && ticketModal && ticketModal.enabled !== false ? /* @__PURE__ */ jsx18(
2695
2981
  CoreDetailModal,
@@ -2698,19 +2984,28 @@ function CorePipeline({
2698
2984
  title: schema?.singular ?? label ?? model,
2699
2985
  config: { ...ticketModal, titleField: ticketModal.titleField ?? resolvedTitleField },
2700
2986
  formFields,
2701
- recordId: ticketId(selectedTicket),
2987
+ recordId: creating ? void 0 : ticketId(selectedTicket),
2702
2988
  initialRecord: selectedTicket,
2989
+ initialTab: creating ? create?.initialTab : void 0,
2703
2990
  relations,
2991
+ actions: modalActions,
2704
2992
  onClose: () => {
2705
2993
  setSelectedTicket(null);
2994
+ setCreating(false);
2706
2995
  setFormError(null);
2707
2996
  },
2708
- onSaved: invalidate
2997
+ onSaved: async () => {
2998
+ await invalidate();
2999
+ if (creating) {
3000
+ setSelectedTicket(null);
3001
+ setCreating(false);
3002
+ }
3003
+ }
2709
3004
  }
2710
3005
  ) : selectedTicket ? /* @__PURE__ */ jsx18(
2711
3006
  DynamicForm,
2712
3007
  {
2713
- title: `Editar ${schema?.singular ?? label ?? model}`,
3008
+ title: `${creating ? "Novo" : "Editar"} ${schema?.singular ?? label ?? model}`,
2714
3009
  eyebrow: "Ticket",
2715
3010
  fields: formFields,
2716
3011
  initialValues: selectedTicket,
@@ -2722,9 +3017,11 @@ function CorePipeline({
2722
3017
  },
2723
3018
  onFieldChange: () => setFormError(null),
2724
3019
  onCancel: () => {
2725
- if (saveMutation.isPending) return;
2726
- setSelectedTicket(null);
2727
- setFormError(null);
3020
+ if (!saveMutation.isPending) {
3021
+ setSelectedTicket(null);
3022
+ setCreating(false);
3023
+ setFormError(null);
3024
+ }
2728
3025
  }
2729
3026
  }
2730
3027
  ) : null
@@ -2980,7 +3277,13 @@ function renderView(view, registry) {
2980
3277
  titleField: v.titleField,
2981
3278
  form: v.form,
2982
3279
  relations: v.relations,
2983
- ticketModal: v.ticketModal
3280
+ ticketModal: v.ticketModal,
3281
+ filters: v.filters,
3282
+ create: v.create,
3283
+ viewModes: v.viewModes,
3284
+ defaultView: v.defaultView,
3285
+ list: v.list,
3286
+ ticketActions: v.ticketActions
2984
3287
  }
2985
3288
  );
2986
3289
  }
@@ -3345,7 +3648,7 @@ import {
3345
3648
  Button as Button13,
3346
3649
  Flex as Flex13,
3347
3650
  Heading as Heading10,
3348
- Input as Input6,
3651
+ Input as Input7,
3349
3652
  Text as Text20,
3350
3653
  VStack as VStack2
3351
3654
  } from "@chakra-ui/react";
@@ -3420,7 +3723,7 @@ function LoginPage({ app }) {
3420
3723
  /* @__PURE__ */ jsxs21(Box18, { children: [
3421
3724
  /* @__PURE__ */ jsx30(Text20, { mb: 2, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "E-mail" }),
3422
3725
  /* @__PURE__ */ jsx30(
3423
- Input6,
3726
+ Input7,
3424
3727
  {
3425
3728
  type: "email",
3426
3729
  value: email,
@@ -3434,7 +3737,7 @@ function LoginPage({ app }) {
3434
3737
  /* @__PURE__ */ jsxs21(Box18, { children: [
3435
3738
  /* @__PURE__ */ jsx30(Text20, { mb: 2, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "Senha" }),
3436
3739
  /* @__PURE__ */ jsx30(
3437
- Input6,
3740
+ Input7,
3438
3741
  {
3439
3742
  type: "password",
3440
3743
  value: password,
@@ -3477,7 +3780,7 @@ function LoginPage({ app }) {
3477
3780
 
3478
3781
  // src/security/ActivationPage.tsx
3479
3782
  import { useEffect as useEffect7, useState as useState13 } from "react";
3480
- import { Box as Box19, Button as Button14, Heading as Heading11, Input as Input7, Text as Text21, VStack as VStack3 } from "@chakra-ui/react";
3783
+ import { Box as Box19, Button as Button14, Heading as Heading11, Input as Input8, Text as Text21, VStack as VStack3 } from "@chakra-ui/react";
3481
3784
  import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
3482
3785
  function encodeBasicCredentials2(email, password) {
3483
3786
  const bytes = new TextEncoder().encode(`${email}:${password}`);
@@ -3618,7 +3921,7 @@ function ActivationPage() {
3618
3921
  field.required ? " *" : ""
3619
3922
  ] }),
3620
3923
  /* @__PURE__ */ jsx31(
3621
- Input7,
3924
+ Input8,
3622
3925
  {
3623
3926
  type: field.type === "password" || field.type === "secret" ? "password" : field.type === "email" ? "email" : field.type === "url" ? "url" : field.type === "number" || field.type === "integer" ? "number" : "text",
3624
3927
  value: String(values[field.name] ?? field.defaultValue ?? ""),
@@ -3638,7 +3941,7 @@ function ActivationPage() {
3638
3941
  /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3639
3942
  /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "Nome do usu\xE1rio" }),
3640
3943
  /* @__PURE__ */ jsx31(
3641
- Input7,
3944
+ Input8,
3642
3945
  {
3643
3946
  value: devName,
3644
3947
  onChange: (event) => setDevName(event.target.value),
@@ -3650,7 +3953,7 @@ function ActivationPage() {
3650
3953
  /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3651
3954
  /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "E-mail *" }),
3652
3955
  /* @__PURE__ */ jsx31(
3653
- Input7,
3956
+ Input8,
3654
3957
  {
3655
3958
  type: "email",
3656
3959
  value: devEmail,
@@ -3663,7 +3966,7 @@ function ActivationPage() {
3663
3966
  /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3664
3967
  /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "Senha *" }),
3665
3968
  /* @__PURE__ */ jsx31(
3666
- Input7,
3969
+ Input8,
3667
3970
  {
3668
3971
  type: "password",
3669
3972
  value: devPassword,
@@ -3741,7 +4044,7 @@ function ActivationPage() {
3741
4044
  /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3742
4045
  /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "E-mail do administrador *" }),
3743
4046
  /* @__PURE__ */ jsx31(
3744
- Input7,
4047
+ Input8,
3745
4048
  {
3746
4049
  type: "email",
3747
4050
  autoComplete: "email",
@@ -3754,7 +4057,7 @@ function ActivationPage() {
3754
4057
  /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3755
4058
  /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "Senha *" }),
3756
4059
  /* @__PURE__ */ jsx31(
3757
- Input7,
4060
+ Input8,
3758
4061
  {
3759
4062
  type: "password",
3760
4063
  minLength: 8,
@@ -3810,7 +4113,7 @@ function ActivationPage() {
3810
4113
  step === 1 && (!isDevelopmentMember || showCodeFlow) && /* @__PURE__ */ jsxs22(Fragment6, { children: [
3811
4114
  /* @__PURE__ */ jsx31(Text21, { children: "Informe o c\xF3digo de ativa\xE7\xE3o para validar tenant, aplicativo e licen\xE7a antes de consumir o c\xF3digo." }),
3812
4115
  /* @__PURE__ */ jsx31(
3813
- Input7,
4116
+ Input8,
3814
4117
  {
3815
4118
  "aria-label": "C\xF3digo de ativa\xE7\xE3o",
3816
4119
  value: code,
@@ -4112,7 +4415,13 @@ function manifestToConfig(manifest, runtime) {
4112
4415
  section: p.section,
4113
4416
  form: p.form,
4114
4417
  relations: p.relations,
4115
- ticketModal: p.ticketModal
4418
+ ticketModal: p.ticketModal,
4419
+ filters: p.filters,
4420
+ create: p.create,
4421
+ viewModes: p.viewModes,
4422
+ defaultView: p.defaultView,
4423
+ list: p.list,
4424
+ ticketActions: p.ticketActions
4116
4425
  };
4117
4426
  views.push(view);
4118
4427
  }
@@ -4247,7 +4556,7 @@ function CoreCurrency({ model = "Moeda", label = "Multi-moedas", endpoint = "/mo
4247
4556
 
4248
4557
  // src/components/CoreAssistant.tsx
4249
4558
  import { useState as useState14 } from "react";
4250
- import { Box as Box21, Button as Button17, Flex as Flex16, Heading as Heading14, Input as Input8, Stack as Stack11, Text as Text24 } from "@chakra-ui/react";
4559
+ import { Box as Box21, Button as Button17, Flex as Flex16, Heading as Heading14, Input as Input9, Stack as Stack11, Text as Text24 } from "@chakra-ui/react";
4251
4560
  import { useMutation as useMutation6 } from "@tanstack/react-query";
4252
4561
  import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
4253
4562
  function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint = "/assistant-runs" }) {
@@ -4299,7 +4608,7 @@ function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint =
4299
4608
  ] }) }),
4300
4609
  /* @__PURE__ */ jsxs25(Flex16, { gap: 2, children: [
4301
4610
  /* @__PURE__ */ jsx39(
4302
- Input8,
4611
+ Input9,
4303
4612
  {
4304
4613
  size: "sm",
4305
4614
  value: input,