feat(OnlyOffice): Ajustes diversos no editor

This commit is contained in:
Keven 2025-12-26 15:52:08 -03:00
parent c3511a7065
commit b664221d5d
32 changed files with 1134 additions and 90 deletions

View file

@ -0,0 +1,5 @@
import TAtoForm from '@/packages/servicos/components/TAto/TAtoForm';
export default function TAtoFormPage() {
return <TAtoForm />;
}

View file

@ -0,0 +1,5 @@
import TAtoIndex from '@/packages/servicos/components/TAto/TAtoIndex';
export default function TServicoAToPag() {
return <TAtoIndex />;
}

View file

@ -57,6 +57,10 @@ const data = {
title: 'Pedidos',
url: '/servicos/pedidos/',
},
{
title: 'Atos',
url: '/servicos/atos/',
},
],
},
{

View file

@ -17,7 +17,6 @@ export function middleware(request: NextRequest) {
return NextResponse.next();
}
// -----------------------------------------
const publicRoute = publicRoutes.find((route) => route.path === path);
const authToken = request.cookies.get('access_token');

View file

@ -0,0 +1,138 @@
import { ColumnDef } from '@tanstack/react-table';
import { EllipsisIcon, EyeIcon, PencilIcon, Trash2Icon } from 'lucide-react';
import Link from 'next/link';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime';
import { SortableHeader } from '@/shared/components/dataTable/SortableHeader';
import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge';
import TAtoInterface from '../../interfaces/TAto/TAtoInterface';
export default function TAtoColumns(
onEdit: (item: TAtoInterface, isEditingFormStatus: boolean) => void,
onDelete: (item: TAtoInterface, isEditingFormStatus: boolean) => void,
): ColumnDef<TAtoInterface>[] {
return [
// ID
{
accessorKey: 'ato_id',
header: ({ column }) => SortableHeader('#', column),
cell: ({ row }) => Number(row.getValue('ato_id')),
enableSorting: true,
},
// Usuário
{
accessorKey: 'protocolo',
header: ({ column }) => SortableHeader('Protocolo', column),
cell: ({ row }) => row.getValue('protocolo'),
},
// Situação
{
accessorKey: 'situacao',
header: ({ column }) => SortableHeader('Situação', column),
cell: ({ row }) => {
return (
<ServicosPedidosSituacoesBadge situacao={row.getValue('situacao') as 'A' | 'F' | 'C' | null | undefined}
/>
);
},
},
// Data Pedido
{
accessorKey: 'data_abertura',
header: ({ column }) => SortableHeader('Abertura', column),
cell: ({ row }) => FormatDateTime(row.getValue('data_abertura')),
},
// Data Pedido
{
accessorKey: 'data_lavratura',
header: ({ column }) => SortableHeader('Lavratura', column),
cell: ({ row }) => FormatDateTime(row.getValue('data_lavratura')),
},
// Descrição
{
accessorKey: 'descricao',
header: ({ column }) => SortableHeader('Situação', column),
cell: ({ row }) => {
return <div className="font-semibold">{row.getValue('descricao') || '---'}</div>
},
},
// Descrição
{
accessorKey: 'numero_livro',
header: ({ column }) => SortableHeader('Livro', column),
cell: ({ row }) => row.getValue('numero_livro'),
},
// Descrição
{
accessorKey: 'folha_inicial',
header: ({ column }) => SortableHeader('Fl. Inicial', column),
cell: ({ row }) => row.getValue('folha_inicial'),
},
// Descrição
{
accessorKey: 'folha_final',
header: ({ column }) => SortableHeader('Fl. Final', column),
cell: ({ row }) => row.getValue('folha_final'),
},
// Ações
{
id: 'actions',
header: 'Ações',
cell: ({ row }) => {
const servicoPedido = row.original;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<EllipsisIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="left" align="start">
<DropdownMenuGroup>
<DropdownMenuItem asChild>
<Link href={`/servicos/pedidos/detalhes/${row.getValue('ato_id')}`}>
<EyeIcon className="mr-2 h-4 w-4" />
Detalhes
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link href={`/servicos/pedidos/pedido/${row.getValue('ato_id')}`}>
<PencilIcon className="mr-2 h-4 w-4" />
Editar
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onSelect={() => onDelete(servicoPedido, true)}>
<Trash2Icon className="mr-2 h-4 w-4" />
Remover
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
);
},
enableSorting: false,
enableHiding: false,
},
];
}

View file

@ -0,0 +1,406 @@
'use client';
import { CreditCardIcon, PackageIcon, UserSquare2Icon } from 'lucide-react';
import { useMemo } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import {
Form,
FormField,
FormItem,
FormLabel,
FormMessage
} from '@/components/ui/form';
import { Separator } from '@/components/ui/separator';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import GUsuarioSelect from '@/packages/administrativo/components/GUsuario/GUsuarioSelect';
import useTAtoFormControllerHook from '@/packages/servicos/hooks/TAto/useTAtoFormControllerHook';
import TAtoFormInterface from '@/packages/servicos/interfaces/TAto/TAtoFormInterface';
import OnlyOfficeEditor from '@/shared/components/editor/onlyoffice/OnlyOfficeEditor';
import { StepNavigator, StepSection } from '@/shared/components/step/stepNavigator';
export default function TAtoForm({ ato_id }: TAtoFormInterface) {
const tAtoController = useTAtoFormControllerHook()
const { form } = tAtoController
const configAto = useMemo(() => {
return {
documentType: "word",
document: {
fileType: 'docx',
title: 'modelo.docx',
key: 'Ato',
permissions: {
edit: true,
download: true,
}
},
editorConfig: {
mode: "edit",
lang: "pt-BR"
},
};
}, []);
// Memoriza os dados para não renderizar novamente
const sections: StepSection[] = useMemo(
() => [
{
key: 'pedido',
id: 'selectPedido',
icon: <PackageIcon className="h-4 w-4" />,
title: 'Pedido',
description: 'Dados gerais do pedido.',
},
{
key: 'servicoPedidoItem',
id: 'selectAtoItem',
icon: <UserSquare2Icon className="h-4 w-4" />,
title: 'Itens',
description: 'Itens/serviços do pedido.',
},
{
key: 'payment',
id: 'selectPayment',
icon: <CreditCardIcon className="h-4 w-4" />,
title: 'Pagamento',
description: 'Forma e dados de pagamento.',
},
{
key: 'imoveis',
id: 'selectedImoveis',
icon: <CreditCardIcon className="h-4 w-4" />,
title: 'Imóveis',
description: 'Forma e dados de pagamento.',
},
{
key: 'divisao',
id: 'selectedDivisao',
icon: <CreditCardIcon className="h-4 w-4" />,
title: 'Divisão',
description: 'Forma e dados de pagamento.',
},
{
key: 'emolumentos',
id: 'selectedEmolumento',
icon: <CreditCardIcon className="h-4 w-4" />,
title: 'Emolumentos',
description: 'Forma e dados de pagamento.',
},
],
[],
);
// Memoriza os dados para não renderizar novamente
const sectionsText: StepSection[] = useMemo(
() => [
{
key: 'texto',
id: 'selectedAto',
icon: <PackageIcon className="h-4 w-4" />,
title: 'Ato',
description: 'Dados gerais do pedido.',
},
{
key: 'finalizacaoLivro',
id: 'selectedFinalizacaoLivro',
icon: <UserSquare2Icon className="h-4 w-4" />,
title: 'Livro',
description: 'Itens/serviços do pedido.',
},
{
key: 'finalizacaoTraslado',
id: 'selectedFinalizacaoTraslado',
icon: <CreditCardIcon className="h-4 w-4" />,
title: 'Traslado',
description: 'Forma e dados de pagamento.',
},
],
[],
);
return (
<div>
<h3 className="mb-4 text-4xl font-bold">Ato</h3>
<Tabs defaultValue="account">
<TabsList>
<TabsTrigger value="account">Ato</TabsTrigger>
<TabsTrigger value="password">Texto</TabsTrigger>
<TabsTrigger value="image">Imagem</TabsTrigger>
<TabsTrigger value="andamento">Andamento</TabsTrigger>
<TabsTrigger value="lavratura">Lavratura</TabsTrigger>
</TabsList>
<TabsContent value="account">
<Form {...form}>
<form>
<div className="flex gap-4">
{/* Seção1 */}
<main className="flex-1">
<div className="flex flex-col gap-4">
<Card role="presentation" id="selectPedido" className="scroll-mt-6">
<CardHeader>
<CardTitle>
<h4 className="text-3xl">Dados Inicias</h4>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-12 gap-4">
{/* Escrevente */}
<div className="col-span-12 md:col-span-12">
<FormField
control={form.control}
name="ato_id"
render={({ field }) => (
<FormItem>
<FormLabel className="font-semibold">Escrevente/Tabelião</FormLabel>
<GUsuarioSelect field={field} />
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
</CardContent>
</Card>
{/* Seção 2 */}
<Card role="presentation" id="selectAtoItem" className="scroll-mt-6">
<CardHeader>
<CardTitle>
<h4 className="text-3xl">Dados Adicionais</h4>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4"></CardContent>
</Card>
{/* Seção 3 */}
<Card role="presentation" id="selectPayment" className="scroll-mt-6">
<CardHeader>
<CardTitle>
<h4 className="text-3xl">Partes</h4>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4"></CardContent>
</Card>
{/* Seção 3 */}
<Card role="presentation" id="selectedImoveis" className="scroll-mt-6">
<CardHeader>
<CardTitle>
<h4 className="text-3xl">Imóveis</h4>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4"></CardContent>
</Card>
{/* Seção 3 */}
<Card role="presentation" id="selectedDivisao" className="scroll-mt-6">
<CardHeader>
<CardTitle>
<h4 className="text-3xl">Divisao</h4>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4"></CardContent>
</Card>
{/* Seção 3 */}
<Card role="presentation" id="selectedEmolumento" className="scroll-mt-6">
<CardHeader>
<CardTitle>
<h4 className="text-3xl">Emolumentos</h4>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4"></CardContent>
</Card>
</div>
</main>
{/* Sidebar */}
<aside className="hidden w-[360px] lg:block">
<div className="sticky top-4 z-10 flex max-h-[calc(100vh-2rem)] flex-col gap-4 overflow-auto">
<Card className="card-border">
<CardContent>
<StepNavigator
ref={tAtoController.ref}
sections={sections}
defaultActive="pedido"
scrollOffset={16}
spyLockMs={600}
/>
</CardContent>
</Card>
</div>
</aside>
</div>
</form>
</Form>
</TabsContent>
<TabsContent value="password">
<div className="flex gap-4">
<div className='flex-1 h-screen'>
<OnlyOfficeEditor
id={`AtoEditor`}
config={configAto}
/>
</div>
{/* Sidebar */}
<aside className="hidden w-[360px] lg:block">
<div className="sticky top-4 z-10 flex max-h-[calc(100vh-2rem)] flex-col gap-4 overflow-auto">
<Card className="card-border">
<CardContent>
<StepNavigator
ref={tAtoController.ref}
sections={sectionsText}
defaultActive="texto"
scrollOffset={16}
spyLockMs={600}
/>
</CardContent>
</Card>
</div>
</aside>
</div>
</TabsContent>
<TabsContent value="image">Imagem</TabsContent>
<TabsContent value="andamento">andamento</TabsContent>
<TabsContent value="lavratura">
<div className="flex gap-4">
{/* Seção1 */}
<main className="flex-1">
<Card role="presentation" id="selectPedido">
<CardHeader>
<CardTitle>
<h4 className="text-3xl">Lavratura</h4>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="mx-auto">
<Card>
<CardContent className="space-y-8 p-6">
{/* ================= HEADER ================= */}
<div className="flex flex-col justify-between gap-6 lg:flex-row">
{/* Left */}
<div>
<p className="font-medium">Cecilia Chapman</p>
<p className="text-sm text-muted-foreground">
P.O. Box 283 8562 Fusce Rd., 20620
</p>
<p className="text-sm text-muted-foreground">
ypurdomain@example.com
</p>
</div>
{/* Right */}
<div className="text-left lg:text-right">
<h2 className="text-2xl font-semibold uppercase text-primary">
Invoice
</h2>
<p className="mt-1">
<span className="font-semibold">#INV-0033970</span>
</p>
<p className="text-sm">
Created Date:{" "}
<span className="font-medium">September 28 2022</span>
</p>
<p className="text-sm">
Due Date:{" "}
<span className="font-medium">September 28 2022</span>
</p>
</div>
</div>
<Separator />
{/* ================= ADDRESSES ================= */}
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
<div>
<h3 className="text-lg font-semibold">Billed To</h3>
<address className="not-italic text-sm text-muted-foreground">
Cecilia Chapman
<br />
P.O. Box 283 8562 Fusce Rd., 20620
<br />
ypurdomain@example.com
</address>
</div>
<div className="text-left lg:text-right">
<h3 className="text-lg font-semibold">Shipped To</h3>
<address className="not-italic text-sm text-muted-foreground">
Cecilia Chapman
<br />
P.O. Box 283 8562 Fusce Rd., 20620
<br />
ypurdomain@example.com
</address>
</div>
</div>
{/* ================= TABLE ================= */}
<div className="overflow-x-auto">
<Table>
<TableHeader>
<TableRow className="bg-muted/50">
<TableHead>S.No</TableHead>
<TableHead>Product</TableHead>
<TableHead>Quantity</TableHead>
<TableHead>Unit</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>1</TableCell>
<TableCell>
<p className="font-medium">Logo Creation</p>
<p className="text-sm text-muted-foreground">
Photoshop
</p>
</TableCell>
<TableCell className="font-medium">2</TableCell>
<TableCell>$60.00</TableCell>
<TableCell className="text-right font-medium">
$120.00
</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
</CardContent>
</Card>
</div>
</CardContent>
</Card>
</main>
{/* Sidebar */}
<aside className="hidden w-[360px] lg:block">
<div className="sticky top-4 z-10 flex max-h-[calc(100vh-2rem)] flex-col gap-4 overflow-auto">
<Card className="card-border">
<CardContent>
<StepNavigator
ref={tAtoController.ref}
sections={sections}
defaultActive="pedido"
scrollOffset={16}
spyLockMs={600}
/>
</CardContent>
</Card>
</div>
</aside>
</div>
</TabsContent>
</Tabs>
</div>
);
}

View file

@ -0,0 +1,143 @@
'use client';
import { useCallback, useEffect, useState } from 'react';
import { useTAtoDeleteHook } from '@/packages/servicos/hooks/TAto/useTAtoDeleteHook';
import { useTAtoIndexHook } from '@/packages/servicos/hooks/TAto/useTAtoIndexHook';
import { useTAtoSaveHook } from '@/packages/servicos/hooks/TAto/useTAtoSaveHook';
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog';
import { useConfirmDialog } from '@/shared/components/confirmDialog/useConfirmDialog';
import Header from '@/shared/components/structure/Header';
import TAtoTable from './TAtoTable';
export default function TAtoIndex() {
// Controle de estado do botão
const [buttonIsLoading, setButtonIsLoading] = useState(false);
// Hooks para leitura e salvamento
const { TAto, indexTAto } = useTAtoIndexHook();
const { saveTAto } = useTAtoSaveHook();
const { deleteTAto } = useTAtoDeleteHook();
// Estados
const [selectedData, setSelectedData] = useState<TAtoInterface | null>(null);
const [isFormOpen, setIsFormOpen] = useState(false);
// Estado para saber qual item será deletado
const [itemToDelete, setItemToDelete] = useState<TAtoInterface | null>(null);
/**
* Hook do modal de confirmação
*/
const { isOpen: isConfirmOpen, openDialog: openConfirmDialog, handleCancel } = useConfirmDialog();
/**
* Abre o formulário no modo de edição ou criação
*/
const handleOpenForm = useCallback((data: TAtoInterface | null) => {
setSelectedData(data);
setIsFormOpen(true);
}, []);
/**
* Fecha o formulário e limpa o andamento selecionado
*/
const handleCloseForm = useCallback(() => {
setSelectedData(null);
setIsFormOpen(false);
}, []);
/**
* Salva os dados do formulário
*/
const handleSave = useCallback(
async (formData: TAtoInterface) => {
// Coloca o botão em estado de loading
setButtonIsLoading(true);
// Aguarda salvar o registro
await saveTAto(formData);
// Remove o botão em estado de loading
setButtonIsLoading(false);
// Atualiza a lista de dados
indexTAto();
},
[saveTAto, indexTAto, handleCloseForm],
);
/**
* Quando o usuário clica em "remover" na tabela
*/
const handleConfirmDelete = useCallback(
(item: TAtoInterface) => {
// Define o item atual para remoção
setItemToDelete(item);
// Abre o modal de confirmação
openConfirmDialog();
},
[openConfirmDialog],
);
/**
* Executa a exclusão de fato quando o usuário confirma
*/
const handleDelete = useCallback(async () => {
// Protege contra null
if (!itemToDelete) return;
// Executa o Hook de remoção
await deleteTAto(itemToDelete);
// Atualiza a lista
await indexTAto();
// Limpa o item selecionado
setItemToDelete(null);
// Fecha o modal
handleCancel();
}, [itemToDelete, indexTAto, handleCancel]);
/**
* Busca inicial dos dados
*/
useEffect(() => {
indexTAto();
}, []);
return (
<div>
{/* Cabeçalho */}
<Header
title={'Atos'}
description={'Cadastro de atos'}
buttonText={'Novo Ato'}
href="/servicos/atos/ato"
/>
{/* Tabela de andamentos */}
<TAtoTable
data={TAto}
onEdit={handleOpenForm}
onDelete={handleConfirmDelete}
/>
{/* Modal de confirmação */}
{isConfirmOpen && (
<ConfirmDialog
isOpen={isConfirmOpen}
title="Confirmar exclusão"
description="Atenção"
message={`Deseja realmente excluir o valor "${itemToDelete?.protocolo}"?`}
confirmText="Sim, excluir"
cancelText="Cancelar"
onConfirm={handleDelete}
onCancel={handleCancel}
/>
)}
</div>
);
}

View file

@ -0,0 +1,32 @@
'use client';
import { Card, CardContent } from '@/components/ui/card';
import TAtoTableInterface from '@/packages/servicos/interfaces/TAto/TAtoTableInterface';
import { DataTable } from '@/shared/components/dataTable/DataTable';
import TAtoColumns from './TAtoColumns';
/**
* Componente principal da tabela de Naturezas
*/
export default function TAtoTable({
data,
onEdit,
onDelete,
}: TAtoTableInterface) {
const columns = TAtoColumns(onEdit, onDelete);
return (
<div>
<Card>
<CardContent>
<DataTable
data={data}
columns={columns}
filterColumn="descricao"
filterPlaceholder="Buscar por apresentante..."
/>
</CardContent>
</Card>
</div>
);
}

View file

@ -35,19 +35,19 @@ export default function TAtoTableFormDialog({
const formCertidao = useTServicoItemPedidoCertidaoFormHook({});
const { tAto, fetchTAto } = useTAtoIndexHook();
const [atos, setAtos] = useState<any>();
const { TAto, indexTAto } = useTAtoIndexHook();
const [atos, seTAtos] = useState<any>();
const [selectedAto, setSelectedAto] = useState<TPessoaInterface | null>(null);
// Atualiza a variavel de pessoa quando tiver alteração na variavel de pessoas fisicas
useEffect(() => {
setAtos(tAto);
}, [tAto]);
seTAtos(TAto);
}, [TAto]);
// Executa o hook correspondente ao tipo de pessoa, sempre que o tipo pessoa mudar
useEffect(() => {
// Dispara o carregamento de informações
fetchTAto()
indexTAto()
}, []);
const columns = TAtoTableFormColumnsDialog(setSelectedAto);

View file

@ -23,15 +23,18 @@ export default function TServicoItemPedidoCertidaForm({
return {
documentType: "word",
document: {
fileType: GetFileExtension(selectedItem?.certidao_texto,),
title: selectedItem?.certidao_texto,
name: selectedItem?.certidao_texto,
key: `etiqueta_${selectedItem?.servico_itempedido_id}_${new Date().getTime()}`,
key: selectedItem?.certidao_texto,
permissions: {
edit: true,
download: true,
}
},
editorConfig: {
mode: "edit",
lang: "pt-BR",
orius_api_endpoint: `servicos/pedidos/t_servico_itempedido/${selectedItem?.servico_itempedido_id}/certidao/salvar`
},
};
@ -53,7 +56,7 @@ export default function TServicoItemPedidoCertidaForm({
{/* Só renderiza o Editor se o config estiver pronto */}
{isOpen && config && (
<OnlyOfficeEditor
id={`ServicoItemPedidoEtiquetaEditor_${selectedItem?.servico_itempedido_id}`}
id={`ServicoItemPedidoCertidaoEditor_${selectedItem?.servico_itempedido_id}`}
config={config}
/>
)}

View file

@ -0,0 +1,19 @@
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
import API from '@/shared/services/api/Api';
import { Methods } from '@/shared/services/api/enums/ApiMethodEnum';
import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface';
async function executeTAtoDeleteData(
data: TAtoInterface,
): Promise<ApiResponseInterface> {
const api = new API();
return api.send({
method: Methods.DELETE,
endpoint: `administrativo/g_gramatica/${data.ato_id}`,
});
}
export const TAtoDeleteData = withClientErrorHandler(executeTAtoDeleteData);

View file

@ -0,0 +1,23 @@
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
import API from '@/shared/services/api/Api';
import { Methods } from '@/shared/services/api/enums/ApiMethodEnum';
import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface';
async function executeTAtoSaveData(data: TAtoInterface): Promise<ApiResponseInterface> {
// Verifica se existe ID para decidir se é atualização (PUT) ou criação (POST)
const isUpdate = Boolean(data.ato_id);
// Instancia o cliente da API
const api = new API();
// Executa a requisição para a API com o método apropriado e envia os dados no corpo
return api.send({
method: isUpdate ? Methods.PUT : Methods.POST, // PUT se atualizar, POST se criar
endpoint: `administrativo/g_gramatica/${data.ato_id || ''}`, // endpoint dinâmico
body: data, // payload enviado para a API
});
}
export const TAtoSaveData = withClientErrorHandler(executeTAtoSaveData);

View file

@ -0,0 +1,21 @@
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
import API from '@/shared/services/api/Api';
import { Methods } from '@/shared/services/api/enums/ApiMethodEnum';
import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface';
import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
async function executeTServicoItemPedidoSaveCertidaoData(
data: TServicoItemPedidoInterface,
): Promise<ApiResponseInterface> {
const api = new API();
return api.send({
method: Methods.PUT,
endpoint: `servicos/pedidos/t_servico_itempedido/${data.servico_itempedido_id || ''}/certidao/salvar`, // endpoint dinâmico
body: data,
});
}
export const TServicoItemPedidoSaveCertidaoData = withClientErrorHandler(executeTServicoItemPedidoSaveCertidaoData);

View file

@ -0,0 +1,21 @@
import { useState } from 'react';
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import { TAtoDeleteService } from '@/packages/servicos/services/TAto/TAtoDeleteService';
import { useResponse } from '@/shared/components/response/ResponseContext';
export const useTAtoDeleteHook = () => {
const { setResponse } = useResponse();
const [gGramatica, setTAto] = useState<TAtoInterface>();
const deleteTAto = async (data: TAtoInterface) => {
const response = await TAtoDeleteService(data);
setTAto(data);
setResponse(response);
};
return { gGramatica, deleteTAto };
};

View file

@ -0,0 +1,69 @@
'use client';
import { useRouter } from 'next/navigation';
import { useCallback, useRef, useState } from 'react';
import { useTAtoFormHook } from '@/packages/servicos/hooks/TAto/useTAtoFormHook';
import { useTAtoSaveHook } from '@/packages/servicos/hooks/TAto/useTAtoSaveHook';
import { useTServicoItemPedidoCalculoHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook';
import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
import { useTServicoItemPedidoLocalHandleHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalHandleHook';
import { useResponse } from '@/shared/components/response/ResponseContext';
import { StepNavigatorRef } from '@/shared/components/step/stepNavigator';
export default function useTAtoFormControllerHook(ato_id?: number) {
const router = useRouter();
const form = useTAtoFormHook({});
const { setValue, reset, watch } = form;
const [isSaving, setIsSaving] = useState(false);
const [isAdding, setIsAdding] = useState(false);
const [isPessoaFormOpen, setIsPessoaFormOpen] = useState(false);
const [isAtoFormOpen, setAtoFormOpen] = useState(false);
const [isSaveConfirmOpen, setIsSaveConfirmOpen] = useState(false);
const [isCancelDialogOpen, setIsCancelDialogOpen] = useState(false);
const [selectedPessoaTipo, setSelectedPessoaTipo] = useState('');
const [shouldKeepFormOpen, setShouldKeepFormOpen] = useState(false);
const ref = useRef<StepNavigatorRef>(null);
// Controles de formulário
const handleClosePessoaForm = useCallback(() => setIsPessoaFormOpen(false), []);
const handleCloseAtoForm = useCallback(() => setAtoFormOpen(false), []);
const handleOpenSaveConfirm = useCallback(() => setIsSaveConfirmOpen(true), []);
const handleCloseSaveConfirm = useCallback(() => setIsSaveConfirmOpen(false), []);
// const playSuccess = useSoundHook("/sounds/success.mp3");
const { setResponse } = useResponse();
const { saveTAto } = useTAtoSaveHook();
const { TServicoItemPedidoLocal, localAddTServicoItemPedido, localRemoveTServicoItemPedido, setLocalTServicoItemPedido } = useTServicoItemPedidoLocalHandleHook(setValue);
const { calculoTServicoItemPedido } = useTServicoItemPedidoCalculoHook(setValue);
const { indexTServicoItemPedido } = useTServicoItemPedidoIndexHook();
return {
form,
ref,
isSaving,
isAdding,
isPessoaFormOpen,
isAtoFormOpen,
isSaveConfirmOpen,
isCancelDialogOpen,
shouldKeepFormOpen,
selectedPessoaTipo,
TServicoItemPedidoLocal,
// setters diretos
setIsSaveConfirmOpen,
setIsCancelDialogOpen,
setShouldKeepFormOpen,
// handlers principais
handleCloseSaveConfirm,
handleClosePessoaForm,
handleCloseAtoForm,
handleOpenSaveConfirm,
};
}

View file

@ -0,0 +1,17 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import {
TAtoFormValues,
TAtoSchema,
} from '@/packages/servicos/schemas/TAto/TAtoSchema';
export function useTAtoFormHook(defaults?: Partial<TAtoFormValues>) {
return useForm<TAtoFormValues>({
resolver: zodResolver(TAtoSchema),
defaultValues: {
ato_id: 0,
...defaults,
},
});
}

View file

@ -7,9 +7,9 @@ import { useResponse } from '@/shared/components/response/ResponseContext';
export const useTAtoIndexHook = () => {
const { setResponse } = useResponse();
const [tAto, setTAto] = useState<TAtoInterface[]>([]);
const [TAto, setTAto] = useState<TAtoInterface[]>([]);
const fetchTAto = async () => {
const indexTAto = async () => {
const response = await TAtoIndexService();
setTAto(response.data);
@ -19,5 +19,5 @@ export const useTAtoIndexHook = () => {
return response.data;
};
return { tAto, fetchTAto };
return { TAto, indexTAto };
};

View file

@ -0,0 +1,35 @@
'use client';
import { useState } from 'react';
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import { TAtoSaveService } from '@/packages/servicos/services/TAto/TAtoSaveService';
import { useResponse } from '@/shared/components/response/ResponseContext';
export const useTAtoSaveHook = () => {
const { setResponse } = useResponse();
const [gGramatica, setTAto] = useState<TAtoInterface | null>(null);
// controla se o formulário está aberto ou fechado
const [isOpen, setIsOpen] = useState(false);
const saveTAto = async (data: TAtoInterface) => {
const response = await TAtoSaveService(data);
// Armazena os dados da resposta
setTAto(response.data);
// Define os dados da resposta (toast, modal, etc.)
setResponse(response);
// Fecha o formulário automaticamente após salvar
setIsOpen(false);
// Retorna os valores de forma imediata
return response.data;
};
return { gGramatica, saveTAto, isOpen, setIsOpen };
};

View file

@ -0,0 +1,39 @@
'use client';
import { useState } from 'react';
import { useResponse } from '@/shared/components/response/ResponseContext';
import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
import { TServicoItemPedidoSaveCertidaoService } from '../../services/TServicoItemPedido/TServicoItemPedidoSaveCertidaoService';
export const useTServicoItemPedidoCertidaoSaveHook = () => {
const { setResponse } = useResponse();
const [TServicoItemPedido, setTServicoItemPedido] = useState<TServicoItemPedidoInterface | null>(
null,
);
// controla se o formulário está aberto ou fechado
const [isOpen, setIsOpen] = useState(false);
const saveCertidaoTServicoItemPedido = async (data: TServicoItemPedidoInterface) => {
const response = await TServicoItemPedidoSaveCertidaoService(data);
// Armazena os dados da resposta
setTServicoItemPedido(response.data);
// Define os dados da resposta (toast, modal, etc.)
setResponse(response);
// Fecha o formulário automaticamente após salvar
setIsOpen(false);
// Retorna os valores de forma imediata
return response.data;
};
return { TServicoItemPedido, saveCertidaoTServicoItemPedido, isOpen, setIsOpen };
};

View file

@ -0,0 +1,3 @@
export default interface TAtoFormInterface {
ato_id?: number
}

View file

@ -0,0 +1,7 @@
import TAtoInterface from './TAtoInterface';
export default interface TAtoTableInterface {
data?: TAtoInterface[];
onEdit: (item: TAtoInterface, isEditingFormStatus: boolean) => void;
onDelete: (item: TAtoInterface, isEditingFormStatus: boolean) => void;
}

View file

@ -1,17 +1,17 @@
import z from "zod";
export const TAtoSchema = z.object({
ato_id: z.string().optional(),
ato_tipo_id: z.string().optional(),
escrevente_ato_id: z.string().optional(),
escrevente_assina_id: z.string().optional(),
livro_andamento_id: z.string().optional(),
ato_id: z.number().optional(),
ato_tipo_id: z.number().optional(),
escrevente_ato_id: z.number().optional(),
escrevente_assina_id: z.number().optional(),
livro_andamento_id: z.number().optional(),
data_abertura: z.string().optional(),
data_lavratura: z.string().optional(),
usuario_id: z.string().optional(),
usuario_id: z.number().optional(),
protocolo: z.string().optional(),
alienacao_data: z.string().optional(),
qualificacao_imovel_id: z.string().optional(),
qualificacao_imovel_id: z.number().optional(),
folha_inicial: z.string().optional(),
folha_final: z.string().optional(),
folha_total: z.string().optional(),
@ -19,7 +19,7 @@ export const TAtoSchema = z.object({
grs_numero: z.string().optional(),
texto: z.string().optional(),
texto_finalizacao: z.string().optional(),
natureza_id: z.string().optional(),
natureza_id: z.number().optional(),
valor_pagamento: z.string().optional(),
situacao_ato: z.string().optional(),
texto_imovel_geral: z.string().optional(),
@ -27,16 +27,16 @@ export const TAtoSchema = z.object({
cancelado_data: z.string().optional(),
cancelado_motivo: z.string().optional(),
cancelado_observacao: z.string().optional(),
cancelado_usuario_id: z.string().optional(),
cancelado_usuario_id: z.number().optional(),
data_cancelamento: z.string().optional(),
alienacao_datalavratura: z.string().optional(),
ato_antigo: z.string().optional(),
folha_letra: z.string().optional(),
qtd_imovel: z.string().optional(),
minuta_protegida: z.string().optional(),
havido_marcacao_id: z.string().optional(),
havido_marcacao_id: z.number().optional(),
observacao: z.string().optional(),
selo_livro_id: z.string().optional(),
selo_livro_id: z.number().optional(),
usar_tabela_auxiliar: z.string().optional(),
ato_antigo_ocorrencia: z.string().optional(),
fonte_tamanho: z.string().optional(),
@ -45,13 +45,13 @@ export const TAtoSchema = z.object({
ato_anterior_origem: z.string().optional(),
ato_anterior_livro: z.string().optional(),
ato_anterior_finicial: z.string().optional(),
ato_anterior_tb_cartorio_id: z.string().optional(),
ato_anterior_tb_cartorio_id: z.number().optional(),
ato_anterior_outorgante: z.string().optional(),
ato_anterior_observacao: z.string().optional(),
ato_anterior_ato_id: z.string().optional(),
ato_anterior_ato_id: z.number().optional(),
ato_anterior_data: z.string().optional(),
ato_anterior_anotacao_adicional: z.string().optional(),
ato_anterior_ato_tipo_id: z.string().optional(),
ato_anterior_ato_tipo_id: z.number().optional(),
ato_anterior_valor_documento: z.string().optional(),
cadastrar_imovel: z.string().optional(),
filho_maior_qtd: z.string().optional(),
@ -59,16 +59,16 @@ export const TAtoSchema = z.object({
filho_menor_qtd: z.string().optional(),
filho_menor_descricao: z.string().optional(),
casamento_data: z.string().optional(),
casamento_tb_regime_id: z.string().optional(),
casamento_tb_regime_id: z.number().optional(),
ato_anterior_ffinal: z.string().optional(),
resp_filhos_maiores: z.string().optional(),
resp_filhos_menores: z.string().optional(),
censec_naturezalitigio_id: z.string().optional(),
censec_naturezalitigio_id: z.number().optional(),
censec_acordo: z.string().optional(),
nlote: z.string().optional(),
especie_pagamento: z.string().optional(),
fora_cartorio: z.string().optional(),
nfse_id: z.string().optional(),
nfse_id: z.number().optional(),
acao: z.string().optional(),
data_protocolo: z.string().optional(),
frente_verso: z.string().optional(),
@ -83,3 +83,5 @@ export const TAtoSchema = z.object({
mne: z.string().optional(),
eh_restrito: z.string().optional(),
})
export type TAtoFormValues = z.infer<typeof TAtoSchema>;

View file

@ -0,0 +1,14 @@
'use server';
import { TAtoDeleteData } from '@/packages/servicos/data/TAto/TAtoDeleteData';
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
async function executeTAtoDeleteService(data: TAtoInterface) {
const response = await TAtoDeleteData(data);
return response;
}
export const TAtoDeleteService = withClientErrorHandler(executeTAtoDeleteService);

View file

@ -0,0 +1,14 @@
'use server';
import { TAtoSaveData } from '@/packages/servicos/data/TAto/TAtoSaveData';
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
async function executeTAtoSaveService(data: TAtoInterface) {
const response = await TAtoSaveData(data);
return response;
}
export const TAtoSaveService = withClientErrorHandler(executeTAtoSaveService);

View file

@ -0,0 +1,13 @@
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
import { TServicoItemPedidoSaveCertidaoData } from '../../data/TServicoItemPedido/TServicoItemPedidoSaveCertidaoData';
import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
async function executeTServicoItemPedidoSaveCertidaoService(data: TServicoItemPedidoInterface) {
const response = await TServicoItemPedidoSaveCertidaoData(data);
return response;
}
export const TServicoItemPedidoSaveCertidaoService = withClientErrorHandler(
executeTServicoItemPedidoSaveCertidaoService,
);

View file

@ -1,12 +1,16 @@
import { DocumentEditor } from "@onlyoffice/document-editor-react";
import { useEffect, useState } from "react";
import GetCallbackUrl from "./actions/GetCallbackUrl";
import GetServerUrl from "./actions/GetServerUrl";
import { usePrepareOnlyOfficeEditorHook } from "./hooks/usePrepareOnlyOfficeEditorHook";
import { useTokenOnlyOfficeEditorHook } from "./hooks/useTokenOnlyOfficeEditorHook";
import OnlyOfficeInteface from "./interface/OnlyOfficeInterface";
export default function OnlyOfficeEditor({ id, config }: OnlyOfficeInteface) {
const { tokenOnlyOfficeEditorHook } = useTokenOnlyOfficeEditorHook()
const { prepareOnlyOfficeEditorHook } = usePrepareOnlyOfficeEditorHook();
const [serverUrl, setServerUrl] = useState<null>(null);
@ -22,9 +26,13 @@ export default function OnlyOfficeEditor({ id, config }: OnlyOfficeInteface) {
setServerUrl(GetServerUrl(response.data, 1))
// Atualiza o caminho do documento
config.document.url = GetServerUrl(response.data, 2) + '/temp/' + config.document.name
config.document.url = GetServerUrl(response.data, 2) + '/temp/' + config.document.title
console.log('config', config)
// Configura a url de callback
config.editorConfig.callbackUrl = GetCallbackUrl(response.data) + config.editorConfig.orius_api_endpoint
// Obtem o token assinado, deve ser sempre a ultima etapa
config.token = await tokenOnlyOfficeEditorHook(config);
};

View file

@ -0,0 +1,5 @@
export default function GetCallbackUrl(data) {
return `http://${data.ip}:${data.port_api}/${data.prefix_api}`;
}

View file

@ -10,6 +10,7 @@ async function executeOnlyOfficeEditorPrepareData(): Promise<ApiResponseInterfac
ip: process.env.NEXT_PUBLIC_ORIUS_ONLYOFFICE_IP,
port_only_office: process.env.NEXT_PUBLIC_ORIUS_ONLYOFFICE_PORT,
port_api: process.env.NEXT_PUBLIC_ORIUS_APP_API_PORT,
prefix_api: process.env.NEXT_PUBLIC_ORIUS_APP_API_PREFIX,
}
}

View file

@ -1,40 +0,0 @@
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface';
// Adicionei url como parâmetro para tornar a função reutilizável e testável
async function executeOnlyOfficeEditorServiceUpData(url: string): Promise<ApiResponseInterface> {
const timeoutMs = 2000; // Defina o tempo limite desejado
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, {
method: 'HEAD',
signal: controller.signal
});
// O fetch nativo não lança erro em 404 ou 500, então verificamos manualmente.
if (!response.ok) {
throw new Error(`Serviço indisponível. Status: ${response.status}`);
}
return {
status: 200,
message: "Editor inicializado com sucesso",
data: {
online: true,
status: response.status
}
};
} finally {
// Isso garante que o timer seja limpo, quer a requisição funcione ou falhe (erro propagado)
clearTimeout(timeoutId);
}
}
export const OnlyOfficeEditorServiceUpData = withClientErrorHandler(executeOnlyOfficeEditorServiceUpData);

View file

@ -1,12 +1,10 @@
'use client';
import { useState } from 'react';
import { object } from 'zod';
import GGramaticaInterface from '@/packages/administrativo/interfaces/GGramatica/GGramaticaInterface';
import { useResponse } from '@/shared/components/response/ResponseContext';
import { OnlyOfficeEditorServiceUpData } from '../data/OnlyOfficeEditorServiceUpData';
import { OnlyOfficeEditorPrepareService } from '../services/OnlyOfficeEditorPrepareService';
export const usePrepareOnlyOfficeEditorHook = () => {
@ -14,27 +12,12 @@ export const usePrepareOnlyOfficeEditorHook = () => {
const { setResponse } = useResponse();
const [onlyOfficeEditor, setOnlyOfficeEditor] = useState<GGramaticaInterface[]>([]);
const [serviceUpData, setServiceUpData] = useState<object>(object);
const prepareOnlyOfficeEditorHook = async () => {
// Busca as confgiurações do editor
const response = await OnlyOfficeEditorPrepareService();
// Define a url do editor
const urlServer = `http://${response.data.ip}:${response.data.port_only_office}`
// Busca as confgiurações do editor
const responseServiceUp = await OnlyOfficeEditorServiceUpData(urlServer);
if (responseServiceUp.status != 200) {
setResponse({
status: responseServiceUp.status,
detail: 'Não foi possivel conectar ao editor',
message: 'Não foi possivel conectar ao editor'
})
}
// Armazena os dados consultados
setOnlyOfficeEditor(response.data);

View file

@ -0,0 +1,36 @@
'use client';
import { useState } from 'react';
import { useResponse } from '@/shared/components/response/ResponseContext';
import { OnlyOfficeEditorTokenService } from '../services/OnlyOfficeEditorTokenService';
export const useTokenOnlyOfficeEditorHook = () => {
const { setResponse } = useResponse();
const [onlyOfficeToken, setOnlyOfficeToken] = useState<string>();
const tokenOnlyOfficeEditorHook = async (data: object) => {
// Busca as confgiurações do editor
const response = await OnlyOfficeEditorTokenService(data);
// Armazena os dados consultados
setOnlyOfficeToken(response.data);
// Define a resposta (toast, modal, feedback, etc.)
setResponse(response);
// Retorna os dados imediatamente
return response;
};
return {
onlyOfficeToken,
tokenOnlyOfficeEditorHook,
};
};

View file

@ -0,0 +1,19 @@
'use server';
import jwt from 'jsonwebtoken';
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
export default async function executeOnlyOfficeEditorTokenService(data: object) {
const response = jwt.sign(data, 'WYe1zwtlDkh39_X3X3qTSICFDxts4VQrMyGLxnEpGUg', {
algorithm: 'HS256',
expiresIn: '5m',
})
return response;
}
export const OnlyOfficeEditorTokenService = withClientErrorHandler(executeOnlyOfficeEditorTokenService);