Compare commits

...
Sign in to create a new pull request.

270 commits

Author SHA1 Message Date
Keven
b664221d5d feat(OnlyOffice): Ajustes diversos no editor 2025-12-26 15:52:08 -03:00
Keven
c3511a7065 fix(Editor): Realiza ajustes no editor 2025-12-23 09:04:00 -03:00
Keven
5ef46780a5 feat(Certidao): Adiciona recursos para manipular certidões 2025-12-22 18:03:49 -03:00
Keven
fd79837fdc feat(TServicoPedido): Implementa a solicitação de certidão na tela de pedido 2025-12-18 16:11:53 -03:00
Keven
b5ea5a75a8 feat(TAto): Implementa a listagem de atos para realizar o pedido de certidão 2025-12-17 10:12:42 -03:00
Keven
4561194b6b del(): Remove os arquivos de certidão 2025-12-16 15:13:06 -03:00
Keven
c8863e573f feat(): Ajustes na tela de detalhes do pedido 2025-12-16 15:07:01 -03:00
Keven
fca1d0c293 refactor(): Ajustes diversos na tela de pedidos 2025-12-15 19:45:29 -03:00
Keven
32937c9501 refactor(TServicoPedido): Refatoração da tela, otimizando e separando as responsabilidades 2025-12-10 18:10:45 -03:00
Keven
790dbe2df3 refactor(Importações): Refatora as importações de componentes, fixa através do prettier e corrigi através do eslint 2025-12-09 18:03:53 -03:00
Keven
4770c42596 1735 2025-12-09 17:35:31 -03:00
Keven
aceb17b235 fix(UseServer): Ajusta as Services para serem executados lado servidor 2025-12-09 17:17:33 -03:00
Keven
21d5d94197 1655 2025-12-09 16:55:30 -03:00
Keven
8f9659ea5b 1641 2025-12-09 16:41:39 -03:00
Keven
e39970587b 1635 2025-12-09 16:35:45 -03:00
Keven
bcbcc8557b 1612 2025-12-09 16:12:53 -03:00
Keven
f6f4892d09 1610 2025-12-09 16:10:41 -03:00
Keven
1e9627e924 1603 2025-12-09 16:03:24 -03:00
Keven
f23decf071 1558 2025-12-09 15:58:15 -03:00
Keven
43d0863342 1552 2025-12-09 15:52:46 -03:00
Keven
e24a35709b 1545 2025-12-09 15:45:32 -03:00
Keven
3eb0bd6f0e 1541 2025-12-09 15:41:51 -03:00
Keven
c6217b0520 15:20 2025-12-09 15:20:16 -03:00
Keven
7a2305c918 15:19 2025-12-09 15:19:43 -03:00
Keven
26f0016813 1514 2025-12-09 15:14:49 -03:00
Keven
0ec57bd6f8 fix(Deploy): Ajustes para deploy 2025-12-09 14:51:30 -03:00
Keven
50814c9b14 Remove as variaveis locais 2025-12-09 14:50:59 -03:00
Keven
2f891ffc38 1418 2025-12-09 14:18:31 -03:00
Keven
52d16a1548 1413 2025-12-09 14:13:38 -03:00
Keven
26df474611 1406 2025-12-09 14:06:21 -03:00
Keven
cdc5e953a5 1310 2025-12-09 13:10:42 -03:00
Keven
f1abddb383 1309 2025-12-09 13:09:10 -03:00
Keven
824ac5da24 1306 2025-12-09 13:06:55 -03:00
Keven
386b8b0307 fix(Dockerfile): Ajusta o dockerfile 2025-12-09 13:04:37 -03:00
Keven
a400bd233e fix(Dockerfile): Ajusta o dockerfile 2025-12-09 13:01:01 -03:00
Keven
60dce3876a fix(Dockerfile): Ajusta o dockerfile 2025-12-09 12:45:20 -03:00
Keven
7745961ff6 fix(Env): Ajusta a requisição para usar variavel de ambiente 2025-12-09 12:25:25 -03:00
Keven
69d34c713e fix(Dockerfile): Ajusta o dockerfile 2025-12-09 12:13:23 -03:00
Keven
91346bfb19 fix(Dockerfile): Ajusta o dockerfile 2025-12-09 11:59:59 -03:00
Keven
d2494f20b7 Ajusta as variaveis de ambiente 2025-12-09 11:44:45 -03:00
Keven
4ef0517cb7 feat(Env): Ajusta para a api usar as varaiveis de ambiente 2025-12-09 11:39:08 -03:00
Keven
714a0e1f97 fix(TServicoPedido): Ajustes diversos na tela de pedido 2025-12-08 17:40:36 -03:00
Keven
df46a60b81 fix(Prettier): Fix automático do código 2025-12-08 16:32:37 -03:00
Keven
0dc065d9bb fix(EsLint): Ajuste automáticos do LINT 2025-12-08 16:28:15 -03:00
Keven
99791bd06f deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:56:58 -03:00
Keven
5f8d2cf670 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:46:39 -03:00
Keven
369dfcdfc3 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:43:45 -03:00
Keven
f4b0118b36 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:41:15 -03:00
Keven
053b86ee69 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:36:27 -03:00
Keven
f7b13648a1 fix(Chart): Ajusta o chart 2025-12-08 11:33:42 -03:00
Keven
744e51d215 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:28:27 -03:00
Keven
41f31ed2f1 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:19:50 -03:00
Keven
0e3cb35309 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:18:14 -03:00
Keven
24e259fc16 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 11:14:59 -03:00
Keven
6fc76254c0 Merge branch 'release(MVP/Sprint2)' 2025-12-08 10:33:15 -03:00
Keven
1c4d52ebe9 Merge remote-tracking branch 'origin/MVPTN-1' into release(MVP/Sprint2) 2025-12-08 10:30:16 -03:00
Keven
6e4646c96b Merge remote-tracking branch 'origin/MVPTN-2' into release(MVP/Sprint2) 2025-12-08 10:29:40 -03:00
Keven
f09b152192 fix(): Ajustes para deploy 2025-12-08 10:26:15 -03:00
Keven
ff3ff6c2e0 Merge branch 'release(DSAAS)' 2025-12-08 10:03:33 -03:00
Keven
dfee9eb752 feat(Merge): Realiza o mege de todas as demandas 2025-12-08 09:58:34 -03:00
Keven
e01fa690a3 Merge remote-tracking branch 'origin/DSAAS-23' into release(DSAAS) 2025-12-08 09:57:53 -03:00
Keven
f9df3cd8a3 fix(Deploy): Ajustes para build de versão 2025-12-08 09:46:23 -03:00
Keven
e98a293286 Merge branch 'release(MVP/Sprint11)' 2025-12-05 16:13:02 -03:00
Keven
4c16b19184 fix(Icon): Ajusta o icone do menu 2025-12-05 16:09:41 -03:00
Keven
de3a022800 Merge remote-tracking branch 'origin/release(MVP/Sprint10)' 2025-12-05 16:07:39 -03:00
Keven
4da16c3fe2 Merge remote-tracking branch 'origin/release(MVP/Sprint9)' 2025-12-05 16:06:13 -03:00
Keven
d1732558ff Merge remote-tracking branch 'origin/release(MVP/Sprint8)' 2025-12-05 16:05:49 -03:00
Keven
58630f8602 [MVPTN-37] feat(Pedido): Cria endpoints e recursos para estornar e ativar um item do pedido 2025-12-05 16:03:26 -03:00
Keven
6b6f2e4fc8 [MVPTN-37] feat(Pedido): Cria endpoints e recursos para estornar e ativar um item do pedido 2025-12-05 11:14:03 -03:00
Keven
2d37d4d421 [MVPTN-37] feat(Pesquisa): Adiciona query params nas urls 2025-12-02 18:23:41 -03:00
Keven
fdd4cf7cfc [MVPTN-37] fix(Pedido): Ajustes diversos na tela de pedido 2025-11-17 17:39:04 -03:00
Keven
bc2c2ef3dd [MVPTN-37] feat(Subview): Ajusta diversos pontos da aplicação para trabalhar com subviews sem sobrecarga 2025-11-17 14:46:39 -03:00
Keven
b2e0d50dd6 [MVPTN-37] refactor(): Ajustes diversos 2025-11-15 12:30:33 -03:00
Keven
97c958cb00 [MVPTN-37] feat(Pedido): Implementa 90% da tela de pedido de serviço 2025-11-15 10:08:15 -03:00
Keven
6fe6c86b5d [MVPTN-37] feat(Item): Finaliza o vinculo de pessoa ao item de pedido 2025-11-11 13:58:27 -03:00
Keven
b85cd6aeb9 [MVPTN-37] feat(ItensPedido): Implementa parcialmente os pessoas vinculadas aos itens dos pedidos 2025-11-10 18:21:14 -03:00
Keven
88cb6f67c8 [MVPTN-37] feat(Balcão): Ajusta a tela de balcão para trabalhar com itens de pedido 2025-11-09 19:03:15 -03:00
Keven
790c79ede6 [MVPTN-37] feat(Itens): Implementa a inserção de itens ao pedido 2025-11-08 20:35:25 -03:00
Keven
06d55ec125 [MVPTN-37] feat(Pedido): Ajusta o forumlário para utilizar o endpoint para salvar o pedido 2025-11-06 17:32:40 -03:00
e50818e52a backup: Backup de código 2025-11-04 08:16:28 -03:00
79f2092882 Merge remote-tracking branch 'origin/release(MVP/Sprint6)' into MVPTN-37 2025-10-30 16:10:25 -03:00
8d44686717 [MVPTN-37] feat(CRUD): Criar parcialmente o formulário e implementa a listagem de dados 2025-10-30 15:58:48 -03:00
7162a20d1f [MVPTN-117] fix(Build): Realiza correções diversas para build 2025-10-29 10:00:23 -03:00
b362968a4f [MVPTN-117] feat(CRUD): Cria o crud de manipular o cálculo rápido 2025-10-28 18:11:13 -03:00
23604033fe fix(eslint): Correção automática de código 2025-10-28 17:18:05 -03:00
4b7afd6a8f [MVPTN-86] feat(crud): Conclusão do CRUD Tipos de Serviço - t_servico_tipo 2025-10-28 15:40:08 -03:00
feab092f6e fix(ESLint): Corrige partes diversas do código usando ESLint 2025-10-27 15:58:58 -03:00
e39422776e [MVPTN-37] feat(CRUD): Implementação inicial do CRUD de serviços de balcão 2025-10-27 15:29:51 -03:00
8e035546e9 [MVPTN-122] feat(CRUD): Habiltia o CRUD 2025-10-25 16:58:42 -03:00
6051afc3e0 [MVPTN-122] feat(CRUD): Implementa parcialmente o CRUD par amanipular a tabela GEmolumentoItem 2025-10-24 17:15:11 -03:00
9b9f8b9454 [MVPTN-119] feat(CRUD): Cria cruds para manipular GEmolumento e GSeloGrupo 2025-10-24 10:52:34 -03:00
2340cee82a [MVPTN-116] 2025-10-22 14:58:14 -03:00
0e21ebfe5b [MVPTN-112] feat(CRUD): Cria o CRUD de cadastor de Cartório 2025-10-21 12:05:26 -03:00
3faf0ebe5e fix(Build): Ajusta a tipagem para build 2025-10-20 16:46:20 -03:00
b9318f1059 [MVPTN-114] feat(CRUD): Cria o CRUD de Gramatica 2025-10-20 16:33:55 -03:00
64b897e7e9 [MVPTN-27] feat(CRUD): Cria o CRUD inicial da Natureza de Títulos 2025-10-20 14:58:28 -03:00
77ea800aaa Merge remote-tracking branch 'origin/release(MVP)' into MVPTN-86 2025-10-20 09:24:00 -03:00
2810abecf5 [MVPTN-86] feat(form) : Ajustado seletct Categoria e Serviço Caixa 2025-10-20 09:13:00 -03:00
325ca69317 fix(ESLint): aplica correções do eslint 2025-10-18 13:16:15 -03:00
d5b8aad221 fix(ESLint): Ajusta para ser aprovado no eslint 2025-10-18 12:49:41 -03:00
d3d8ac4a28 fix(ESlint): Ajusta importações 2025-10-18 12:37:44 -03:00
8d5e786f74 fix(Formatter): Formata o código utilizando o prettier 2025-10-18 12:27:02 -03:00
5297d6ab2e refactor(Arch): Refatora a arquitetura de pastas do projeto 2025-10-18 12:23:47 -03:00
56bca3ba41 [MVPTN-86] feat(CRUD): Adicionado recursos dinâmicos de select 2025-10-17 18:21:30 -03:00
ab45ac32bf Merge branch 'MVPTN-109' into release(MVP/Sprint8) 2025-10-17 15:02:24 -03:00
36cbd43ee4 [MVPTN-109] fix(Enum): Correção dos códigos do ENUM 2025-10-17 15:02:09 -03:00
b48ffc4bd5 [MVPTN-120] feat(CRUD): Cria o Crud de Vincular as qualidades ao ato 2025-10-17 09:04:27 -03:00
3bd3134d33 [MVPTN-109] feat(CRUD): Cria o CRUD de T_CENSEC_TIPONATUREZA 2025-10-16 12:54:13 -03:00
aaaa04975e [MVPTN-100] feat(CRUD): Criar o CRUD de T_ATO_PARTETIPO 2025-10-15 15:37:17 -03:00
519dbf969a fix(Build): Realiza ajustes diversos para build 2025-10-14 09:42:11 -03:00
4559de0187 [MVPTN-23] feat(CRUD): Adiciona CRUD para manipular o G_NATUREZA 2025-10-14 08:05:21 -03:00
6c7967587a [MVPTN-86] feat(endpoint): Foi criado o acesso ao endpoint responsável em trazer g_marcacao_tipo com filtro 2025-10-13 17:00:01 -03:00
742c9bc38f Merge remote-tracking branch 'origin/release(MVP/Sprint6)' into MVPTN-86 2025-10-13 13:54:16 -03:00
a26fc881b2 [MVPTN-86] feat(CRUD): Criação do CRUD configuração de serviços de balcão 2025-10-13 13:51:42 -03:00
d3f8bebe1d [MVPTN-88] fix(Render): Ajuste de renderização 2025-10-13 10:27:42 -03:00
11578438bf [MVPTN-88] fix(Render): Melhoria na performance de renderização dos componentes da tela 2025-10-13 10:03:59 -03:00
cbaf19af0b [MVPTN-88] fix(CRUD): Ajustes diversos no CRUD de Imóveis e Unidades dos Imóveis 2025-10-10 18:05:34 -03:00
ff28fe1f58 [MVPTN] feat(CRUD): Finalização do CRUD De pessoas Fisicas e Jurídicas 2025-10-10 13:55:51 -03:00
9e37520615 [MVPTN-86] feat(CRUD): Crud completo configuração de serviço de balcão 1ª parte 2025-10-10 09:01:52 -03:00
79370f83f1 Merge branch 'MVPTN-88' into MVPTN-99 2025-10-09 17:46:40 -03:00
cb3f1ffcba [MVPTN-88] fix(Build): Ajustes diversos para realizar a build 2025-10-09 16:15:16 -03:00
37f0f8713d [MVPTN-88] feat(CRUD) implementações diversas 2025-10-09 15:50:20 -03:00
0d5ee71975 fix(Limpeza): Remove console.log perdidos 2025-10-08 18:30:12 -03:00
27d0b7e2de fix(Diversos): Ajusta diversos pequenos pontos da aplicação 2025-10-08 18:23:39 -03:00
3b38337358 [MVPTN-99] feat(CRUD): Implmenta os endpoints reais para manipular pessoa fisica e juridica 2025-10-08 17:45:26 -03:00
36dba45995 fix(Deploy): Realiza ajustes diversos para realizar o build da aplicação 2025-10-07 18:17:06 -03:00
=
7db6d27035 [DSAAS-22] refactor(frontend): corrigindo alguns erros do componente 2025-10-07 16:36:26 -03:00
aa8553b3fe Merge remote-tracking branch 'origin/MVPTN-90' into release(MVP) 2025-10-07 16:23:32 -03:00
75086c6103 [MVPTN-88] fix(CRUD): Ajusta o crud para utilizar os endpoints reais 2025-10-07 16:16:54 -03:00
3e68efe7ec [MVPTN-87] feat(CRUD): Adiciona os endpoints funcionais do backend 2025-10-07 11:59:32 -03:00
847a1f0758 [MVPTN-87] fix e feat: Faz correções diversas e implementa alguns endpoints reais 2025-10-06 18:26:57 -03:00
67453f1f99 fix(Titulo): Ajuste nos títulos dos formulários 2025-10-06 10:14:26 -03:00
ae382f5399 feat(ApiInterface): Cria uma interface de resposta de API, padronizado os recebimentos e saídas de dados 2025-10-06 10:02:47 -03:00
4b0c7e651d refactor(Component): Ajuste em componentes diversos 2025-10-06 09:45:09 -03:00
f2b2181136 refactor(Pastas): Reestrutura pastas do projeto 2025-10-06 09:34:45 -03:00
8cb0de2928 Merge branch 'MVPTN-87' into release(MVP/Sprint6) 2025-10-06 09:18:56 -03:00
89d12b26b5 [MVPTN-87] refactor e crud (TImovel): Refatora os arquivos de TImovel para ficar na estrutura correta e cria o crud do timovel e timovel unidade 2025-10-06 09:16:41 -03:00
8d9eed3c48 [MVPTN-87] fix(Menu): Ajusta as opções do menu 2025-10-03 15:19:05 -03:00
=
32924cd8da [DSAAS-22] feat(Frontend): implementação do modal de confirmação de exclusão via código de verificação 2025-10-03 14:28:51 -03:00
=
46d51e3316 [MVPTN-90] refactor(Correção): corrigindo observações passadas relacionadas a utilizar Enum de situações, retirar trycatch, arrumando coluna de situação com badges 2025-10-03 13:57:09 -03:00
=
66f285ba74 [MVPTN-90] refactor(Correção): corrigindo observações passadas relacionadas a utilizar Enum de situações, retirar trycatch, arrumando coluna de situação com badges 2025-10-03 13:48:49 -03:00
3633628bc5 [MVPTN-99] fix(Imports): Corrige a importação dearquivos 2025-10-03 13:24:35 -03:00
8c5b847d37 [MVPTN-99] refactor(Arquitetura): Reorganizado a arquitetura de pastas 2025-10-03 13:13:30 -03:00
b3dc6c87f2 Merge branch 'MVPTN-99' into release(MVP/Sprint6) 2025-10-03 10:36:09 -03:00
f5ffe5739c [MVPTN-99] refactor(Arquitetura): Refatoração da arquiteturação do Tpessoa 2025-10-03 10:35:43 -03:00
f6faae900d Merge branch 'MVPTN-89' into release(MVP/Sprint6) 2025-10-02 18:14:43 -03:00
7f9b7944db [MVPTN-99] refactor(Estrutura): Refatoração de estrutura do projeto, adicionado favicon 2025-10-02 18:13:06 -03:00
eed113590c [MVPTN-89] feat(CRUD): conclusão do CRUD g_cidade 2025-10-02 18:06:44 -03:00
3aa4c73453 [MVPTN-87] refactor(Dir): Reestruturação de Pastas 2025-10-02 15:47:06 -03:00
1fcc5e442d [MVPTN-87] feat(CRUD): Ajustes diversos no crud de imovel e unidade 2025-10-02 15:30:15 -03:00
7af4c82dd1 [DSAAS-23] feat(Chart): Criação de g´rafico demo para exibição 2025-10-02 09:00:30 -03:00
4eabe19ee3 [MVPTN-87] feat(CRUD): Cria crud de dados mocados da Imovel e da Unidade do Imóvel 2025-10-01 18:11:21 -03:00
1f8892e639 Merge branch 'release(MVP)' into release(MVP/Sprint6) 2025-10-01 14:31:11 -03:00
6f07d8493c Merge remote-tracking branch 'origin/MVPTN-90' into release(MVP/Sprint6) 2025-10-01 14:00:56 -03:00
8579387c53 format(Prettier): Configuração e Execução do prettier como formatador de código 2025-10-01 11:36:28 -03:00
b91ce54475 [MVPTN-99] feat(CRUD): Inicio do formulário de cadastro de pessoa juridica com representantes 2025-10-01 11:15:02 -03:00
=
727e665db4 [MVPTN-90] feat(CRUD): implementada tela de cadastro de tipo de atos censec, com dados mockados por enquanto 2025-10-01 08:53:51 -03:00
=
ce6f6e3c59 [MVPTN-90] feat(CRUD): implementada tela de cadastro de tipo de atos censec, com dados mockados por enquanto 2025-10-01 08:48:46 -03:00
fb35c19a84 Merge remote-tracking branch 'origin/release(MVP/Sprint6)' into MVPTN-88 2025-09-30 09:24:34 -03:00
175dff5ded [MVPTN-92] feat(SelectUF): Criado carregamento de estados de forma dinâmica 2025-09-30 08:20:50 -03:00
426a74f6f6 Merge branch 'release(MVP)' into MVPTN-88 2025-09-29 15:40:18 -03:00
9b34ef16ac [MVPTN-88] feat(ComboBox): Adiciona combobox com pesquisa de campos de muita seleção 2025-09-29 11:05:37 -03:00
=
3df00e38bc refactor(geral): implementando gerenciador de erro nos datas 2025-09-29 09:27:12 -03:00
=
7fe725bdeb refactor(geral): implementando gerenciador de erro nos datas 2025-09-29 09:24:10 -03:00
47dfcf509f [MVPTN-80] deploy 2025-09-26 17:17:28 -03:00
de86ba1e7f fix(Redirect): Corrije o redirecionamento após o login 2025-09-26 16:45:43 -03:00
931fb7e158 Merge remote-tracking branch 'origin/release(MVP/Sprint6)' into release(MVP) 2025-09-26 15:45:48 -03:00
b7f35889a6 [MVPTN-88] feat(Form): Formulário de cadastro estático 2025-09-26 15:42:54 -03:00
3fe6ed8c08 [MVPTN-88] feat(DataTable): Cria componentes da DataTable para sere reutilizados por outras partes do sistema 2025-09-26 11:33:17 -03:00
a045b3ca72 [MVPTN-88] commit de backup 2025-09-26 09:04:44 -03:00
13aea0e161 [MVPTN-89] feat(CRUD): Adiciona CRUD Cidade 2025-09-25 17:03:30 -03:00
8f8050ff09 [MVPTN-80] fix(Deploy): Ajustes para build 2025-09-25 11:57:00 -03:00
127a8c235a Merge branch 'release(MVP/Sprint5)' into release(MVP) 2025-09-25 11:48:52 -03:00
aa540f8fca Merge branch 'release(MVP/Sprint4)' into release(MVP) 2025-09-25 11:48:43 -03:00
595f690366 Merge remote-tracking branch 'origin/MVPTN-9' into release(MVP/Sprint4) 2025-09-25 11:47:59 -03:00
428322f32e Merge remote-tracking branch 'origin/MVPTN-70' into release(MVP/Sprint4) 2025-09-25 11:47:37 -03:00
d801ef1a70 Merge remote-tracking branch 'origin/MVPTN-77' into release(MVP/Sprint5) 2025-09-25 11:45:41 -03:00
2c25f52994 Merge remote-tracking branch 'origin/MVPTN-75' into release(MVP/Sprint5) 2025-09-25 11:45:08 -03:00
94cc5d97aa Merge remote-tracking branch 'origin/MVPTN-74' into release(MVP/Sprint5) 2025-09-25 11:38:50 -03:00
920b9d8aa6 [MVPTN-88] Backup de código 2025-09-25 11:35:35 -03:00
=
295b9b4d69 [MVPTN-77] refactor(geral): implementando gerenciador de erro nos datas 2025-09-25 11:29:09 -03:00
=
cc91b6a559 [MVPTN-75] refactor(geral): implementando gerenciador de erro nos datas 2025-09-25 11:25:15 -03:00
=
936ef7764e [MVPTN-77] refactor(geral): implementando gerenciador de erro nos datas 2025-09-25 09:21:18 -03:00
=
18c61c49e8 [MVPTN-9] refactor(geral): implementando gerenciador de erro nos datas 2025-09-25 09:18:23 -03:00
=
d3757c8ce3 [MVPTN-70] refactor(geral): implementando gerenciador de erro nos datas 2025-09-25 09:14:16 -03:00
=
04307a0aa4 [MVPTN-70] refactor(geral): implementando gerenciador de erro nos datas 2025-09-25 09:13:34 -03:00
1441789fe3 Merge branch 'release(MVP/Sprint5)' into release(MVP) 2025-09-24 14:36:40 -03:00
fdec6a4768 Merge remote-tracking branch 'origin/MVPTN-9' into release(MVP/Sprint4) 2025-09-24 14:36:05 -03:00
7546ec90b3 Merge remote-tracking branch 'origin/MVPTN-77' into release(MVP/Sprint5) 2025-09-24 14:34:55 -03:00
c7ff7f4aa4 Merge remote-tracking branch 'origin/MVPTN-75' into release(MVP/Sprint5) 2025-09-24 14:34:21 -03:00
2fd7af509f [MVPTN-88] fix(Menu): Ajusta a listagem de itens do menu 2025-09-24 14:32:10 -03:00
f7ac0eb9df Merge branch 'release(MVP)' into MVPTN-88 2025-09-24 08:44:28 -03:00
4ec2799fdc [MVPTN-88] feat(CRUD): Cria a listagem de pessoas com dados mocados 2025-09-24 08:13:14 -03:00
af51c1b8d8 [MVPTN-88] feat(CRUD): Cria a listagem de pessoas com dados mocados 2025-09-24 08:12:16 -03:00
=
daeb956ef8 [MVPTN-74] refactor(geral): implementando gerenciador de erro, removendo mock de dados e usando o botao de loading 2025-09-23 17:11:00 -03:00
=
6c1e91035d [MVPTN-75] refactor(geral): implementando gerenciador de erro, removendo mock de dados e usando o botao de loading 2025-09-23 17:00:41 -03:00
=
46296ec8a9 [MVPTN-77] refactor(geral): implementando gerenciador de erro, removendo mock de dados e usando o botao de loading 2025-09-23 16:07:16 -03:00
=
6e80b5409a [MVPTN-77] refactor(geral): implementando gerenciador de erro, removendo mock de dados e usando o botao de loading 2025-09-23 16:04:39 -03:00
=
fefe94f7b1 [MVPTN-9] refactor(geral): implementando gerenciador de erro, removendo mock de dados e usando o botao de loading 2025-09-23 15:56:44 -03:00
eeab66149f [MVPTN-72] refactor(Geral): Conecta o crud com os endpoints definitivos, aplica o botão de loading, encapsula as funções para trativas de erros 2025-09-23 15:56:14 -03:00
=
0e35db30c0 [MVPTN-70] refactor(geral): implementando gerenciador de erro e removendo mock 2025-09-23 15:37:29 -03:00
c7f86522fb fix(Review): Revisão de código para refatoração 2025-09-23 14:14:26 -03:00
634fe16331 fix(Build): Ajusta partes do sistema para ser possivel realizar a build do mesmo 2025-09-22 16:55:57 -03:00
0e77302b21 Merge branch 'release(DSAAS)' into release(MVP) 2025-09-22 15:51:36 -03:00
bc61cb8fde Merge branch 'MVPTN-76' into release(MVP) 2025-09-22 15:40:26 -03:00
9b6b9a754e Merge branch 'release(MVP/Sprint5)' into release(MVP) 2025-09-22 15:37:32 -03:00
083317b897 Merge branch 'release(MVP/Sprint3)' into release(MVP) 2025-09-22 15:37:15 -03:00
4f03c65517 [DSAAS-15] feat(Handler): Cria um handle de funções executadas de forma assincrona 2025-09-22 15:30:51 -03:00
=
156784f836 [MVPTN-76] feat(CRUD): implementada nova tela de cadastro de minuta, e corrigido os dados mockados nas telas que estavam usando os dados mockados 2025-09-22 14:44:22 -03:00
33b90afbe1 Merge branch 'release(DSAAS)' into release(MVP) 2025-09-22 11:29:07 -03:00
f46c05ab97 [DSAAS-11] feat(LoadingButton): Cria componente de botão que controla o estado de loading de requisição 2025-09-22 11:23:30 -03:00
957bb86be1 feat(LoadingButton): Implementa parcialmente botão de loading 2025-09-19 17:08:35 -03:00
de4a2dafdb feat(logout/Info): Aidiciona dados do usuário no menu. Adiciona a opção de realizar logout da aplicação 2025-09-19 16:36:41 -03:00
=
b2d1388da7 [MVPTN-75] feat(CRUD): Implementação cadastro de Natureza Litígio do CENSEC 2025-09-19 10:10:44 -03:00
59f8578eaf Merge remote-tracking branch 'origin/MVPTN-74' into release(MVP/Sprint5) 2025-09-19 09:29:04 -03:00
b81ef13ae9 Merge remote-tracking branch 'origin/MVPTN-77' into release(MVP/Sprint5) 2025-09-19 09:28:26 -03:00
2945d8b1f1 Merge remote-tracking branch 'origin/MVPTN-70' into release(MVP/Sprint4) 2025-09-19 08:14:14 -03:00
=
08889a914a [MVPTN-74] feat(CRUD): Implementando Tipo de Medida 2025-09-18 17:55:01 -03:00
=
d4a8488489 [MVPTN-77] feat(CRUD): Implementando Cadastro de Estado Civil 2025-09-18 16:50:01 -03:00
=
96f591f02f [MVPTN-70] feat(CRUD): Implementando Cadastro de Bairros 2025-09-18 15:32:10 -03:00
aecd665654 [MVPTN-68] feat(CRUD): Cria o crud de Regime de Bens 2025-09-18 12:10:56 -03:00
=
51dbdad191 [MVPTN-9] feat(CRUD): Implementando Cadastro de tipos de logradouro 2025-09-17 16:51:09 -03:00
7eafc9439b [MVPTN-72] feat(CRUD): Cria CRUD para manipular as centrais do CENSEC 2025-09-17 15:57:26 -03:00
01b61781b3 fix(Menu): Ajusta o menu para que as páginas sejam carregadas de forma assincrona 2025-09-17 12:52:15 -03:00
bbc5cd7410 feat(Config): Adiciona o config de exemplo 2025-09-17 11:57:29 -03:00
d61e0ad75b fix(Config): Remove o config do versionamento 2025-09-17 11:55:47 -03:00
5e82d47c6a fix(Menu): ajuste na url de navegação do menu 2025-09-17 11:51:31 -03:00
0f0121d543 fix(Response): Ajuste de tipagem no componente de resposta 2025-09-17 10:13:55 -03:00
247371c2d4 Merge branch 'MVPTN-68' into release(MVP/Sprint3) 2025-09-17 10:02:54 -03:00
e241b4062c Merge branch 'MVPTN-64' into release(MVP/Sprint3) 2025-09-17 10:02:49 -03:00
409b61a86e [MVPTN-64] fix(Tipagem): Remoção das tipagem de saída 2025-09-17 10:01:28 -03:00
c20f3ee64a [MVPTN-68] fix(Tipagem): Remove as tipagem de saída 2025-09-17 09:57:38 -03:00
639fc5e9fd [MVPTN-68] feat(CRUD): Finalização do crud com os ednpoints reais 2025-09-16 14:58:34 -03:00
debe30dc71 fix(Response): Ajuste do controle de resposta inesperadas vindas do servidor 2025-09-16 11:19:36 -03:00
87f4a40d9f Merge branch 'MVPTN-64' into release(MVP/Sprint3) 2025-09-15 17:09:55 -03:00
5e899442a2 [MVPTN-64] feat(CRUD): Adiciona os endpoints ao crud de Regime Comunhão 2025-09-15 17:09:28 -03:00
b1e39a1518 [MVPTN-62] fix(Schema): Ajusta o schema do formulário para abrir corretamente 2025-09-15 15:20:38 -03:00
b7c5f670df [MVPTN-62] feat(CRUD): Integração do crud com os endpoints 2025-09-15 15:08:19 -03:00
611f00b5d0 [MVPTN-64] feat(CRUD): Cria o CRUD de Regime de Comunhão com dados mocados 2025-09-15 12:00:14 -03:00
7ecf79e8a3 [MVPTN-62] feat(CRUD): Cria CRUD para Profissões trabalhando com dados em mock 2025-09-15 10:23:59 -03:00
43116214ff fix(Diversos): Ajustes no config e gitignore 2025-09-15 09:16:02 -03:00
af63a59c2f Merge branch 'release(MVP/Sprint2)' into homologacao 2025-09-15 09:04:04 -03:00
2256dd367f refactor(API): Ajusta os endpoints para consultar o usuário 2025-09-15 08:55:42 -03:00
477c1cd22a fix(Build): ajuste nos crud de andamento e tipo de reconhecimento para realizar a build da versão 2025-09-14 12:29:19 -03:00
bdf982fe38 [MVPTN-1] feat(CRUD): Finalização do CRUD de cadastro de Tipos de Reconhecimentos 2025-09-14 11:33:44 -03:00
a80c8f0095 Merge branch 'release(MVP/Sprint2)' into MVPTN-1 2025-09-14 10:51:19 -03:00
44d20d6f81 [MVPTN-2] feat(CRUD): Finalização de ações do CRUD 2025-09-14 10:49:05 -03:00
0407483d23 [MVPTN-2] refacto(AndamentoServico): Refaz o CRUD de AndamentoServico implementando componeização 2025-09-13 13:14:00 -03:00
c6cb1368c4 feat(Debug): DEbug de url 2025-09-12 17:53:28 -03:00
557ad241d1 feat(Debug): DEbug de url 2025-09-12 17:32:03 -03:00
025dd6a0c2 feat(Debug): Removendo debug 2025-09-12 17:29:59 -03:00
b936df520a feat(Debug) Debugando url do fetch 2025-09-12 17:26:33 -03:00
c95380c932 feat(Debug) Debugando url do fetch 2025-09-12 17:22:34 -03:00
e782085ed0 feat(app.json): Ajustando arquivo app.json 2025-09-12 17:15:51 -03:00
06678901d4 feat(app.json): Ajustando arquivo app.json 2025-09-12 16:47:21 -03:00
f0f02634b5 feat(app.json): Ajustando arquivo app.json 2025-09-12 16:33:05 -03:00
b6274f1cf3 feat(app.json): Ajustando arquivo app.json 2025-09-12 16:25:22 -03:00
e3a29dd5d0 feat(app.json): Ajustando arquivo app.json 2025-09-12 15:59:56 -03:00
261144e45f feat(Dockerfile): Ajustando Dockerfile para depuração 2025-09-12 15:02:48 -03:00
e199327234 feat(Dockerfile): Ajustando Dockerfile 2025-09-12 14:38:02 -03:00
3abde1e7cd feat(Dockerfile): Ajustando Dockerfile 2025-09-12 13:51:27 -03:00
3c033c2c44 feat(DockerFileNextConfig): Ajustando Dockerfile + next.config.ts 2025-09-12 13:34:23 -03:00
cb066a514b feat(Dockerfile): Nova criação do Dockerfile 2025-09-12 13:23:12 -03:00
affa2bc213 feat(Dockerfile): Criação do arquivo Dockerfile 2025-09-12 12:44:28 -03:00
60af379e4f fix(Config): Ajuste ao acesso ao banco de dados via conteiner 2025-09-12 12:34:59 -03:00
46918249a2 [MVPTN-1] feat(Componentes): Separado a página em componentes que compoêm a página 2025-09-12 11:32:34 -03:00
3355c98164 [MVPTN-2] feat(CRUD): Atualização no crud de gerenciamento de andamentos 2025-09-12 10:31:16 -03:00
11aff8e15a [MVPTN-2] feat(CRUD): CRUD com Mock para gerenciar a tabela t_tb_andamentoservico 2025-09-11 17:13:55 -03:00
02ae936c87 [MVPTN] feat(dialog): Implementado formulário em dialog e confirmação de exclusão de registro 2025-09-10 16:59:00 -03:00
12a2c62af8 [MVPTN-1] feat(Listagem): implementa a listagem de tipos de reconhecimento, atualmente usando dados 'mockados' 2025-09-09 15:15:23 -03:00
1027 changed files with 50414 additions and 2738 deletions

117
.code-workspace Normal file
View file

@ -0,0 +1,117 @@
{
"folders": [{ "path": "D:/IIS/Orius/app" }],
"settings": {
// === GERAL ===
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit",
},
"editor.formatOnPaste": false,
"editor.formatOnType": false,
"editor.minimap.enabled": false,
"files.trimTrailingWhitespace": true,
"files.autoSave": "onFocusChange",
"telemetry.telemetryLevel": "off",
"update.mode": "manual",
// === PERFORMANCE ===
"files.watcherExclude": {
"**/node_modules/**": true,
"**/dist/**": true,
"**/build/**": true,
"**/.next/**": true,
"**/.git/**": true,
},
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/.next": true,
"**/.git": true,
},
// === FRONTEND ===
"editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
},
"[typescriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
},
// === TAILWIND ===
"files.associations": {
"*.css": "tailwindcss",
},
"tailwindCSS.includeLanguages": {
"plaintext": "html",
"javascript": "javascript",
"typescriptreact": "typescriptreact",
},
// === TERMINAIS ===
"terminal.integrated.profiles.windows": {
"Next.js Dev": {
"path": "cmd.exe",
"args": ["/k", "cd D:\\IIS\\Orius\\app && npm run dev"],
},
"Build & Preview": {
"path": "cmd.exe",
"args": ["/k", "cd D:\\IIS\\Orius\\app && npm run build && npm run start"],
},
"Git Bash": {
"path": "C:\\Program Files\\Git\\bin\\bash.exe",
},
},
"terminal.integrated.defaultProfile.windows": "Git Bash",
// === GIT ===
"git.enabled": true,
"git.autorefresh": false,
"git.fetchOnPull": true,
"git.confirmSync": false,
// === VISUAL ===
"workbench.colorTheme": "Default Dark Modern",
"window.zoomLevel": 0,
"breadcrumbs.enabled": true,
"explorer.compactFolders": false,
// === MISC ===
"files.exclude": {
"**/.DS_Store": true,
"**/*.log": true,
},
},
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: Debug Development Server",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"cwd": "${workspaceFolder}",
"port": 9229,
},
],
},
"extensions": {
"recommendations": [
// === FRONTEND CORE ===
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"bradlc.vscode-tailwindcss",
"ms-vscode.vscode-typescript-next",
// === DEV EXPERIENCE ===
"formulahendry.code-runner",
"streetsidesoftware.code-spell-checker",
"eamodio.gitlens",
"mhutchie.git-graph",
"donjayamanne.githistory",
],
},
}

2
.gitignore vendored
View file

@ -39,3 +39,5 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
/src/config/app.json

9
.prettierrc Normal file
View file

@ -0,0 +1,9 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"arrowParens": "always",
"plugins": ["prettier-plugin-tailwindcss"]
}

59
Dockerfile Normal file
View file

@ -0,0 +1,59 @@
# ============================
# STAGE 1 Build
# ============================
FROM node:20-alpine AS builder
WORKDIR /app
# Copia pacotes e instala dependências
COPY package*.json ./
RUN npm ci
# Copia o restante do código
COPY . .
# ---------- Variáveis de build ----------
# Estas variáveis são usadas pelo Next.js durante o "build"
# para embutir no bundle do frontend.
ARG NEXT_PUBLIC_ORIUS_APP_STATE
ARG NEXT_PUBLIC_ORIUS_APP_API_URL
ARG NEXT_PUBLIC_ORIUS_APP_API_PREFIX
ARG NEXT_PUBLIC_ORIUS_APP_API_CONTENT_TYPE
ENV NEXT_PUBLIC_ORIUS_APP_STATE=$NEXT_PUBLIC_ORIUS_APP_STATE
ENV NEXT_PUBLIC_ORIUS_APP_API_URL=$NEXT_PUBLIC_ORIUS_APP_API_URL
ENV NEXT_PUBLIC_ORIUS_APP_API_PREFIX=$NEXT_PUBLIC_ORIUS_APP_API_PREFIX
ENV NEXT_PUBLIC_ORIUS_APP_API_CONTENT_TYPE=$NEXT_PUBLIC_ORIUS_APP_API_CONTENT_TYPE
# ---------- Build ----------
ENV NODE_ENV=production
RUN npm run build
# ============================
# STAGE 2 Runner (standalone)
# ============================
FROM node:20-alpine AS runner
WORKDIR /app
# ---------- Variáveis em runtime ----------
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Copia apenas o necessário do build
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
COPY --from=builder /app/package*.json ./
# ---------- Corrige permissões ----------
RUN addgroup -S nodejs && adduser -S nextjs -G nodejs \
&& mkdir -p .next/cache/images \
&& chown -R nextjs:nodejs /app
USER nextjs
EXPOSE 3000
# ---------- Executa o servidor ----------
CMD ["node", "server.js"]

View file

@ -1,2 +1,58 @@
# saas_app
Criar envlocal para usar variaveis de ambiente no em desenvolvimento
NEXT_PUBLIC_ORIUS_APP_STATE=GO
NEXT_PUBLIC_ORIUS_APP_API_URL=<http://localhost:8000/>
NEXT_PUBLIC_ORIUS_APP_API_PREFIX=api/v1/
NEXT_PUBLIC_ORIUS_APP_API_CONTENT_TYPE=application/json
## Modo Debug
Abra Run → Add Configuration… → Attach to Node.js
Configure:
{
"name": "Attach Next.js (9230)",
"type": "node",
"request": "attach",
"port": 9230,
"restart": true,
"smartStep": true,
"skipFiles": ["<node_internals>/**"]
}
npm run dev:debug
## onlyoffice
docker run -i -t -d -p 8081:80 --restart=always -e JWT_ENABLED=false onlyoffice/documentserver
## next em rede
```
npx next dev -H 0.0.0.0
```
```
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"dev:lan": "next dev -H 0.0.0.0" <-- Adicione esta linha
},
```
Como acessar no outro dispositivo
Descubra seu IP Local:
No Windows (seu caso), abra um terminal (CMD ou PowerShell) e digite:
Bash
ipconfig
Procure por Endereço IPv4 (geralmente começa com 192.168.x.x ou 10.0.x.x).
Acesse no navegador: No celular ou outro computador, digite: http://SEU_IP_AQUI:3000
Exemplo: <http://192.168.0.15:3000>

View file

@ -18,4 +18,4 @@
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
}

70
eslint.config.mjs Normal file
View file

@ -0,0 +1,70 @@
import js from '@eslint/js';
import reactPlugin from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import jsxA11y from 'eslint-plugin-jsx-a11y';
import importPlugin from 'eslint-plugin-import';
import tseslint from 'typescript-eslint';
export default [
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.ts', '**/*.tsx'],
ignores: ['node_modules/**', '.next/**', 'out/**', 'dist/**'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parser: tseslint.parser,
parserOptions: {
project: './tsconfig.json',
},
globals: {
React: true,
JSX: true,
},
},
plugins: {
react: reactPlugin,
'react-hooks': reactHooks,
'jsx-a11y': jsxA11y,
import: importPlugin,
},
settings: {
react: { version: 'detect' },
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: './tsconfig.json',
},
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
rules: {
'react/react-in-jsx-scope': 'off',
'react/jsx-uses-react': 'off',
'react/jsx-uses-vars': 'warn',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'import/order': [
'error',
{
groups: [['builtin', 'external'], ['internal'], ['parent', 'sibling', 'index']],
pathGroups: [
{
pattern: '@/**',
group: 'internal',
position: 'after',
},
],
alphabetize: { order: 'asc', caseInsensitive: true },
'newlines-between': 'always',
},
],
'import/no-duplicates': 'error',
'import/newline-after-import': ['error', { count: 1 }],
'no-unused-vars': 'warn',
},
},
];

View file

@ -1,7 +1,17 @@
import type { NextConfig } from "next";
/** @type {import('next').NextConfig} */
const nextConfig = {
// Gera build autônomo para rodar com "node server.js"
output: 'standalone',
// Configurações gerais
reactStrictMode: true,
poweredByHeader: false,
compress: true,
// Desativa verificações no build de produção
eslint: { ignoreDuringBuilds: true },
typescript: { ignoreBuildErrors: true },
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;
module.exports = nextConfig;

7251
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,45 +1,89 @@
{
"name": "app",
"version": "0.1.0",
"type": "module",
"name": "saas",
"version": "25.9.1",
"private": true,
"scripts": {
"dev": "next dev",
"dev:debug": "cross-env NEXT_USE_TURBOPACK=0 NODE_OPTIONS=\"--inspect=9230\" next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"postinstall": "shx mkdir -p public/libs && shx cp -r node_modules/tinymce public/libs/tinymce"
},
"dependencies": {
"@faker-js/faker": "^10.0.0",
"@hookform/resolvers": "^5.2.1",
"@onlyoffice/document-editor-react": "^2.1.1",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-table": "^8.21.3",
"@tinymce/tinymce-react": "^6.3.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"cookies-next": "^6.1.0",
"date-fns": "^3.6.0",
"faker-js": "^1.0.0",
"framer-motion": "^12.23.24",
"input-otp": "^1.4.2",
"js-cookie": "^3.0.5",
"jsonwebtoken": "^9.0.2",
"jwt-decode": "^4.0.0",
"lucide-react": "^0.540.0",
"next": "15.4.6",
"next": "^15.5.3",
"next-themes": "^0.4.6",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-hook-form": "^7.62.0",
"react-masked-text": "^1.0.5",
"recharts": "^3.3.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tinymce": "^8.1.2",
"zod": "^4.0.17"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/date-fns": "^2.5.3",
"@types/js-cookie": "^3.0.6",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@typescript-eslint/eslint-plugin": "^8.46.1",
"@typescript-eslint/parser": "^8.46.1",
"cross-env": "^10.1.0",
"eslint": "^9.38.0",
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.0",
"eslint-plugin-unused-imports": "^4.2.0",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"shx": "^0.4.0",
"tailwindcss": "^4",
"tw-animate-css": "^1.3.7",
"typescript": "^5"
"typescript": "5.9.3",
"typescript-eslint": "^8.46.1"
}
}

View file

@ -1,5 +1,5 @@
const config = {
plugins: ["@tailwindcss/postcss"],
plugins: ['@tailwindcss/postcss'],
};
export default config;

BIN
public/images/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
public/images/logo-abb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

27
public/images/logo.svg Normal file
View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW 2018 (64 Bit) -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="109.504mm" height="32.45mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 4674.85 1385.32"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style type="text/css">
<![CDATA[
.fil0 {fill:#FF6600}
.fil1 {fill:white;fill-rule:nonzero}
]]>
</style>
</defs>
<g id="Camada_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<g id="_2536796572048">
<path class="fil0" d="M444.51 337.84c440.36,-70.7 476.63,243.79 383.3,374.93 -121.36,170.53 -504.61,132.14 -589.48,-37.21 -31.1,-62.05 -10.18,-188.76 23.33,-238.81 35.98,-53.73 97.41,-85.19 182.85,-98.91zm-444.51 192.86c0,156.21 12.26,277.5 171.92,375.2 214.59,131.32 589.63,134.32 795.72,-31.29 174.6,-140.3 173.88,-487.9 -30.87,-624.12 -52.36,-34.83 -93.57,-53.67 -162.11,-73.16 -236.65,-67.31 -582.01,-30.52 -720.03,178.21 -25.47,38.51 -54.62,111.65 -54.62,175.17z"/>
<path class="fil0" d="M3818.84 393.91c0,148.34 145.5,201.77 263.73,234.14 93.01,25.46 365.44,57.71 365.44,126.96 0,66.65 -152.26,76.59 -224.32,76.59 -221.11,0 -348.08,-81.05 -399.39,-93.01l0 196.95 192.2 43.05c87.27,14.66 138.58,22.6 234.54,22.6 441.47,0 507.61,-275.63 337.69,-419.75 -140.93,-119.53 -545.59,-120.82 -545.59,-203.95 0,-95.45 359.81,-45.21 409.3,-31.8l154.22 53.68 0 -186.02 -176.42 -42.42c-214.47,-43.37 -611.42,-48.39 -611.42,222.96z"/>
<path class="fil0" d="M2631.61 755.01c0,86.12 62.34,149.87 115.84,185.07 127.76,84.05 323.75,68.39 463.32,16.58 29.5,-10.95 61.1,-25 91.99,-39.32 39.53,-18.31 67.28,-41.35 94.8,-41.97l0 103.95 218.85 0 0 -809.72 -218.85 0 0 492.39c0,18.46 -54.62,47.33 -68.92,56.91 -26.89,18 -50.44,32.94 -78.73,47.11 -130.98,65.59 -399.45,116.59 -399.45,-114.96l0 -481.45 -218.85 0 0 585.41z"/>
<path class="fil0" d="M1515.5 289.97c0,-46.34 -5.47,-72.07 -5.47,-120.37l-218.84 0 0 809.72 218.84 0 0 -475.99c0,-25.16 113.08,-106.37 136.96,-120.18 84.99,-49.19 220.78,-69.84 320.2,-46.99 23.36,5.37 43.45,15 62.61,19.46l0 -186.02c-126.58,-10.54 -178.34,-55.19 -359.3,29.15 -83.29,38.81 -108.59,66.67 -154.99,91.22z"/>
<polygon class="fil0" points="2166.56,979.32 2385.41,979.32 2385.41,169.6 2166.56,169.6 "/>
<path class="fil0" d="M2172.04 131.3l218.85 0 0 -131.3c-30.09,7.01 -146.3,65.43 -180.57,82.04 -33.64,16.3 -38.27,6.4 -38.27,49.26z"/>
</g>
<path class="fil1" d="M99.26 1380.26l0 -225.54 -81.33 0 0 -27.47 193.01 0 0 27.47 -81.33 0 0 225.54 -30.36 0zm433.68 0l0 -253.02 155.79 0 0 27.47 -125.43 0 0 84.58 115.3 0 0 27.47 -115.3 0 0 86.02 127.23 0 0 27.47 -157.59 0zm578.27 5.06c-30.12,0 -54.1,-8.73 -71.93,-26.2 -17.83,-17.47 -26.75,-42.95 -26.75,-76.45l0 -57.83c0,-33.5 8.91,-58.98 26.75,-76.45 17.83,-17.47 41.81,-26.2 71.93,-26.2 29.88,0 52.83,8.31 68.86,24.94 16.03,16.62 24.04,39.4 24.04,68.31l0 1.81 -30 0 0 -2.89c0,-19.04 -5.12,-34.64 -15.36,-46.81 -10.24,-12.17 -26.08,-18.25 -47.53,-18.25 -21.44,0 -38.19,6.57 -50.24,19.7 -12.05,13.13 -18.07,31.51 -18.07,55.12l0 59.28c0,23.62 6.02,41.99 18.07,55.12 12.05,13.13 28.8,19.7 50.24,19.7 21.45,0 37.29,-6.08 47.53,-18.25 10.24,-12.17 15.36,-27.77 15.36,-46.81l0 -5.78 30 0 0 4.7c0,28.92 -8.01,51.69 -24.04,68.31 -16.02,16.63 -38.98,24.94 -68.86,24.94zm423.92 -5.06l0 -253.02 58.92 0 88.2 233.86 4.7 0 0 -233.86 30 0 0 253.02 -58.92 0 -87.83 -234.22 -5.06 0 0 234.22 -30 0zm615.13 5.06c-30.12,0 -54.16,-8.73 -72.11,-26.2 -17.95,-17.47 -26.93,-42.95 -26.93,-76.45l0 -57.83c0,-33.5 8.98,-58.98 26.93,-76.45 17.95,-17.47 41.99,-26.2 72.11,-26.2 30.36,0 54.52,8.73 72.47,26.2 17.95,17.47 26.93,42.95 26.93,76.45l0 57.83c0,33.5 -8.97,58.98 -26.93,76.45 -17.96,17.47 -42.11,26.2 -72.47,26.2zm0 -27.11c21.93,0 38.92,-6.57 50.96,-19.7 12.05,-13.13 18.07,-31.39 18.07,-54.76l0 -60c0,-23.37 -6.02,-41.63 -18.07,-54.76 -12.05,-13.13 -29.04,-19.7 -50.96,-19.7 -21.69,0 -38.55,6.57 -50.61,19.7 -12.05,13.13 -18.07,31.39 -18.07,54.76l0 60c0,23.37 6.02,41.63 18.07,54.76 12.05,13.13 28.92,19.7 50.61,19.7zm433.32 22.05l0 -253.02 30.36 0 0 225.54 127.96 0 0 27.47 -158.32 0zm565.25 5.06c-30.12,0 -54.16,-8.73 -72.11,-26.2 -17.95,-17.47 -26.93,-42.95 -26.93,-76.45l0 -57.83c0,-33.5 8.98,-58.98 26.93,-76.45 17.95,-17.47 41.99,-26.2 72.11,-26.2 30.36,0 54.52,8.73 72.47,26.2 17.95,17.47 26.93,42.95 26.93,76.45l0 57.83c0,33.5 -8.97,58.98 -26.93,76.45 -17.96,17.47 -42.11,26.2 -72.47,26.2zm0 -27.11c21.93,0 38.92,-6.57 50.96,-19.7 12.05,-13.13 18.07,-31.39 18.07,-54.76l0 -60c0,-23.37 -6.02,-41.63 -18.07,-54.76 -12.05,-13.13 -29.04,-19.7 -50.96,-19.7 -21.69,0 -38.55,6.57 -50.61,19.7 -12.05,13.13 -18.07,31.39 -18.07,54.76l0 60c0,23.37 6.02,41.63 18.07,54.76 12.05,13.13 28.92,19.7 50.61,19.7zm521.51 27.11c-18.8,0 -35.36,-3.91 -49.7,-11.74 -14.34,-7.83 -25.54,-19.34 -33.61,-34.52 -8.07,-15.18 -12.11,-33.98 -12.11,-56.39l0 -57.83c0,-33.5 8.91,-58.98 26.75,-76.45 17.83,-17.47 41.81,-26.2 71.93,-26.2 29.88,0 52.65,8.19 68.31,24.58 15.66,16.38 23.5,38.32 23.5,65.79l0 1.81 -30 0 0 -2.53c0,-12.05 -2.17,-22.77 -6.51,-32.17 -4.34,-9.4 -11.08,-16.81 -20.24,-22.23 -9.16,-5.42 -20.85,-8.13 -35.06,-8.13 -21.44,0 -38.19,6.57 -50.24,19.7 -12.05,13.13 -18.07,31.51 -18.07,55.12l0 59.28c0,23.62 6.02,41.99 18.07,55.12 12.05,13.13 28.92,19.7 50.61,19.7 21.2,0 36.81,-6.02 46.81,-18.07 10,-12.05 15,-28.07 15,-48.07l0 -6.14 -76.63 0 0 -26.02 106.27 0 0 120.36 -27.47 0 0 -27.47 -5.06 0c-2.65,5.3 -6.38,10.48 -11.2,15.54 -4.82,5.06 -11.33,9.16 -19.52,12.29 -8.19,3.13 -18.8,4.7 -31.81,4.7zm433.68 -5.06l0 -253.02 30.36 0 0 253.02 -30.36 0zm351.64 0l78.07 -253.02 53.49 0 78.08 253.02 -31.45 0 -19.52 -63.98 -107.71 0 -19.52 63.98 -31.45 0zm58.55 -91.45l92.17 0 -43.37 -143.13 -5.06 0 -43.73 143.13z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
public/modelo.docx Normal file

Binary file not shown.

BIN
public/sounds/success.mp3 Normal file

Binary file not shown.

View file

@ -1,14 +0,0 @@
export default class Schema {
private _errors: any[] = []
get errors(): any {
return this._errors;
}
set errors(value: any) {
this._errors.push(value);
}
}

View file

@ -1,11 +0,0 @@
'use client'
import { cookies } from "next/headers";
export default async function CookiesGet() {
const cookieStore = await cookies();
const token = cookieStore.get('access_token');
return token?.value;
}

View file

@ -1,16 +0,0 @@
export default class Json {
static execute(path: string) {
return {
"state": "go",
"api": {
"url": "http://localhost:8000/",
"prefix": "api/v1",
"content_type": "application/json"
}
}
}
}

View file

@ -1,11 +0,0 @@
'use server'
import { cookies } from "next/headers";
export default async function TokenGet() {
const cookieStore = await cookies();
const token = cookieStore.get('access_token');
return token?.value;
}

View file

@ -1,9 +0,0 @@
export default function empty(data: any) {
if (!data || !data === null || !data === undefined) {
return true;
}
return false;
}

View file

@ -1,72 +0,0 @@
'use client'
import { useEffect } from "react";
import { useParams } from "next/navigation";
import {
Card,
CardContent
} from "@/components/ui/card";
import { useGUsuarioReadHooks } from "@/app/(protected)/(administrativo)/_hooks/g_usuario/useGUsuarioReadHooks";
import Usuario from "@/app/(protected)/(administrativo)/_interfaces/IGUsuario";
import Loading from "@/app/_components/loading/loading";
export default function UsuarioDetalhes() {
const params = useParams();
const { usuario, fetchUsuario } = useGUsuarioReadHooks();
useEffect(() => {
if (params.id) {
fetchUsuario({ usuario_id: Number(params.id) } as Usuario);
}
}, []);
if (!usuario) return <Loading type={1} />;
return (
<div>
<Card>
<CardContent>
<div className="mb-4 grid gap-4 grid-cols-4">
<div>
<div className="text-2xl font-semibold">
Nome
</div>
<div className="text-xl">
{usuario?.nome_completo}
</div>
</div>
<div>
<div className="text-2xl font-semibold">
CPF
</div>
<div className="text-xl">
{usuario?.cpf}
</div>
</div>
<div>
<div className="text-2xl font-semibold">
Função
</div>
<div className="text-xl">
{usuario?.funcao}
</div>
</div>
<div>
<div className="text-2xl font-semibold">
Email
</div>
<div className="text-xl">
{usuario?.email}
</div>
</div>
</div>
</CardContent>
</Card>
</div>
);
}

View file

@ -1,136 +0,0 @@
'use client'
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Input } from "@/components/ui/input"
import { UsuarioFormSchema } from "../../../_schemas/GUsuarioSchema"
import {
Button
} from "@/components/ui/button"
import {
Card,
CardContent
} from "@/components/ui/card";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { useGUsuarioSaveHook } from "../../../_hooks/g_usuario/useGUsuarioSaveHook"
type FormValues = z.infer<typeof UsuarioFormSchema>
export default function UsuarioFormularioPage() {
const { usuario, saveUsuario } = useGUsuarioSaveHook();
const form = useForm<FormValues>({
resolver: zodResolver(UsuarioFormSchema),
defaultValues: {
login: '',
nome_completo: '',
funcao: '',
email: '',
cpf: ''
},
});
async function onSubmit(values: FormValues) {
saveUsuario(values);
}
return (
<div>
<Card>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="login"
render={({ field }) => (
<FormItem>
<FormLabel>Login</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="nome_completo"
render={({ field }) => (
<FormItem>
<FormLabel>Nome Completo</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="funcao"
render={({ field }) => (
<FormItem>
<FormLabel>Função</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="cpf"
render={({ field }) => (
<FormItem>
<FormLabel>Cpf</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">
Salvar
</Button>
</form>
</Form>
</CardContent>
</Card>
</div>
);
}

View file

@ -1,112 +0,0 @@
'use client'
import {
Card,
CardContent,
} from "@/components/ui/card"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import Usuario from "../../_interfaces/IGUsuario";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { useGUsuarioIndexHook } from "../../_hooks/g_usuario/useGUsuarioIndexHook";
import { useEffect } from "react";
import Loading from "@/app/_components/loading/loading";
export default function UsuarioPage() {
const { usuarios, fetchUsuarios } = useGUsuarioIndexHook();
useEffect(() => {
fetchUsuarios();
}, []);
if (!usuarios) return <Loading type={2} />;
return (
<div>
<Card>
<CardContent>
<div className="grid grid-cols-2">
<div className="text-2xl font-semibold">
Usuarios
</div>
<div className="text-right">
<Button asChild>
<Link href="/usuarios/formulario">
+ Usuário
</Link>
</Button>
</div>
</div>
<Table>
<TableHeader>
<TableRow>
<TableHead className="text-center">
#
</TableHead>
<TableHead>
Situação
</TableHead>
<TableHead>
CPF
</TableHead>
<TableHead>
Login / Sigla / Nome
</TableHead>
<TableHead>
Função
</TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{usuarios.map((usuario: Usuario) => (
<TableRow key={usuario.usuario_id} className="cursor-pointer">
<TableCell className="text-center">
{usuario.usuario_id}
</TableCell>
<TableCell className="font-medium">
{usuario.situacao}
</TableCell>
<TableCell className="font-medium">
{usuario.cpf}
</TableCell>
<TableCell>
<div className="font-semibold text-xs">
{usuario.login} - {usuario.sigla}
</div>
<div className="text-base">
{usuario.nome_completo}
</div>
</TableCell>
<TableCell>
<div className="text-base">
{usuario.funcao}
</div>
</TableCell>
<TableCell>
<Button asChild>
<Link href={`/usuarios/${usuario.usuario_id}/detalhes`}>
Detalhes
</Link>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
</div>
);
}

View file

@ -1,17 +0,0 @@
'use server'
import API from "@/services/api/Api";
import { Methods } from "@/services/api/enums/ApiMethodEnum";
export default async function GUsuarioDeleteData(usuarioId: number) {
const api = new API();
const response = await api.send({
'method': Methods.DELETE,
'endpoint': `administrativo/usuarios/${usuarioId}`
});
return response;
}

View file

@ -1,17 +0,0 @@
'use server'
import API from "@/services/api/Api";
import { Methods } from "@/services/api/enums/ApiMethodEnum";
export default async function GUsuarioIndexData() {
const api = new API();
const response = await api.send({
'method': Methods.GET,
'endpoint': `administrativo/usuarios/`
});
return response;
}

View file

@ -1,19 +0,0 @@
'use server'
import { Methods } from "@/services/api/enums/ApiMethodEnum";
import API from "@/services/api/Api";
export default async function GUsuarioLoginData(form: any) {
const api = new API();
// Realiza o envio dos dados
const response = await api.send({
method: Methods.POST,
endpoint: `administrativo/usuarios/login`,
body: form
});
return response;
}

View file

@ -1,17 +0,0 @@
'use server'
import API from "@/services/api/Api";
import { Methods } from "@/services/api/enums/ApiMethodEnum";
export default async function GUsuarioReadData(usuarioId: number) {
const api = new API();
const response = await api.send({
'method': Methods.GET,
'endpoint': `administrativo/usuarios/${usuarioId}`
});
return response
}

View file

@ -1,18 +0,0 @@
'use server'
import API from "@/services/api/Api";
import { Methods } from "@/services/api/enums/ApiMethodEnum";
export default async function GUsuarioSaveData(form: any) {
const api = new API();
const response = await api.send({
'method': Methods.POST,
'endpoint': `administrativo/usuarios/`,
'body': form
});
return response;
}

View file

@ -1,27 +0,0 @@
'use client'
import { useState } from "react"
import Usuario from "../../_interfaces/IGUsuario"
import GUsuarioIndex from "../../_services/g_usuario/GUsuarioIndex";
import { useResponse } from "@/app/_response/ResponseContext";
export const useGUsuarioIndexHook = () => {
const { setResponse } = useResponse();
const [usuarios, setUsuarios] = useState<Usuario[] | null>(null);
const fetchUsuarios = async () => {
const response = await GUsuarioIndex();
setUsuarios(response.data);
// Define os dados do componente de resposta (toast, modal, etc)
setResponse(response);
}
return { usuarios, fetchUsuarios }
}

View file

@ -1,26 +0,0 @@
'use client'
import { useState } from "react"
import Usuario from "../../_interfaces/IGUsuario"
import GUsuarioRead from "../../_services/g_usuario/GUsuarioRead";
import { useResponse } from "@/app/_response/ResponseContext";
export const useGUsuarioReadHooks = () => {
const { setResponse } = useResponse();
const [usuario, setUsuario] = useState<Usuario>();
const fetchUsuario = async (Usuario: Usuario) => {
const response = await GUsuarioRead(Usuario.usuario_id);
setUsuario(response.data);
setResponse(response);
}
return { usuario, fetchUsuario }
}

View file

@ -1,26 +0,0 @@
'use client'
import { useState } from "react"
import Usuario from "../../_interfaces/IGUsuario"
import GUsuarioSave from "../../_services/g_usuario/GUsuarioSave";
import { useResponse } from "@/app/_response/ResponseContext";
export const useGUsuarioSaveHook = () => {
const { setResponse } = useResponse();
const [usuario, setUsuario] = useState<Usuario>();
const saveUsuario = async (Usuario: any) => {
const response = await GUsuarioSave(Usuario);
setUsuario(response.data);
setResponse(response);
}
return { usuario, saveUsuario }
}

View file

@ -1,34 +0,0 @@
export default interface Usuario {
usuario_id: number,
trocarsenha: string,
login: string,
senha: string,
situacao: string,
nome_completo: string,
funcao: string,
assina: string,
sigla: string,
usuario_tab: string,
ultimo_login: string,
ultimo_login_regs: string,
data_expiracao: string,
senha_anterior: string,
andamento_padrao: string,
lembrete_pergunta: string,
lembrete_resposta: string,
andamento_padrao2: string,
receber_mensagem_arrolamento: string,
email: string,
assina_certidao: string,
receber_email_penhora: string,
foto: string,
nao_receber_chat_todos: string,
pode_alterar_caixa: string,
receber_chat_certidao_online: string,
receber_chat_cancelamento: string,
cpf: string,
somente_leitura: string,
receber_chat_envio_onr: string,
tipo_usuario: string,
senha_api: string,
}

View file

@ -1,35 +0,0 @@
import { z } from "zod";
export const UsuarioFormSchema = z.object({
trocarsenha: z.string().optional(),
login: z.string().optional(),
senha: z.string().optional(),
situacao: z.string().optional(),
nome_completo: z.string().optional(),
funcao: z.string().optional(),
assina: z.string().optional(),
sigla: z.string().optional(),
usuario_tab: z.string().optional(),
ultimo_login: z.string().optional(),
ultimo_login_regs: z.string().optional(),
data_expiracao: z.string().optional(),
senha_anterior: z.string().optional(),
andamento_padrao: z.string().optional(),
lembrete_pergunta: z.string().optional(),
lembrete_resposta: z.string().optional(),
andamento_padrao2: z.string().optional(),
receber_mensagem_arrolamento: z.string().optional(),
email: z.string().optional(),
assina_certidao: z.string().optional(),
receber_email_penhora: z.string().optional(),
foto: z.string().optional(),
nao_receber_chat_todos: z.string().optional(),
pode_alterar_caixa: z.string().optional(),
receber_chat_certidao_online: z.string().optional(),
receber_chat_cancelamento: z.string().optional(),
cpf: z.string().optional(),
somente_leitura: z.string().optional(),
receber_chat_envio_onr: z.string().optional(),
tipo_usuario: z.string().optional(),
senha_api: z.string().optional(),
});

View file

@ -1,11 +0,0 @@
'use server'
import GUsuarioIndexData from "../../_data/g_usuario/GUsuarioIndexData"
export default async function GUsuarioIndex() {
const response = await GUsuarioIndexData();
return response;
}

View file

@ -1,36 +0,0 @@
'use server'
import {
cookies
} from "next/headers";
import GUsuarioLoginData from "../../_data/g_usuario/GUsuarioLoginData"
import { redirect } from "next/navigation";
import empty from "@/actions/validations/empty";
export default async function GUsuarioLoginService(form: any) {
const response = await GUsuarioLoginData(form);
// Verifica se localizou o usuário
if (response.data.usuario_id <= 0) {
return {
'code': 404,
'message': 'Não foi localizado o usuário'
}
}
const cookieStore = await cookies();
cookieStore.set("access_token", response.data.token, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
path: "/",
maxAge: 60 * 60 * 24,
});
redirect("/usuarios");
}

View file

@ -1,17 +0,0 @@
'use server'
import GUsuarioReadData from "../../_data/g_usuario/GUsuarioReadData";
export default async function GUsuarioRead(usuarioId: number) {
// Verifica se o id informado é válido
if (usuarioId <= 0) {
return {
'code': 400,
'message': 'Usuário informado inválido',
}
}
return await GUsuarioReadData(usuarioId);
}

View file

@ -1,9 +0,0 @@
'use server'
import GUsuarioSaveData from "../../_data/g_usuario/GUsuarioSaveData";
export default async function GUsuarioSave(form: any) {
return await GUsuarioSaveData(form);
}

View file

@ -0,0 +1,5 @@
import TTBAndamentoServicoIndex from '@/packages/administrativo/components/TTBAndamentoServico/TTBAndamentoServicoIndex';
export default function TAtoParteTipo() {
return <TTBAndamentoServicoIndex />;
}

View file

@ -0,0 +1,5 @@
import TAtoParteTipoIndex from '@/packages/administrativo/components/TAtoParteTipo/TAtoParteTipoIndex';
export default function TAtoParteTipo() {
return <TAtoParteTipoIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import GTBBairroIndex from '@/packages/administrativo/components/GTBBairro/GTBBairroIndex';
export default function GCidadePage() {
return <GTBBairroIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import GCartorioIndex from '@/packages/administrativo/components/GCartorio/GCartorioIndex';
export default function GCartorioPage() {
return <GCartorioIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TCensecTipoNaturezaIndex from '@/packages/administrativo/components/TCensecTipoNatureza/TCensecTipoNaturezaIndex';
export default function TCensecTipoNaturezaPage() {
return <TCensecTipoNaturezaIndex />;
}

View file

@ -0,0 +1,3 @@
export default function TCensecPage() {
return <div></div>;
}

View file

@ -0,0 +1,7 @@
'use client';
import TCensecQualidadeIndex from '@/packages/administrativo/components/TCensecQualidade/TCensecQualidadeIndex';
export default function TCensecQualidadePage() {
return <TCensecQualidadeIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TCensecIndex from '@/packages/administrativo/components/TCensec/TCensecIndex';
export default function GTBEstadoCivilPage() {
return <TCensecIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TCensecNaturezaLitigioIndex from '@/packages/administrativo/components/TCensecNaturezaLitigio/TCensecNaturezaLitigioIndex';
export default function GCidadePage() {
return <TCensecNaturezaLitigioIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TCensecQualidadeIndex from '@/packages/administrativo/components/TCensecQualidade/TCensecQualidadeIndex';
export default function GTBEstadoCivilPage() {
return <TCensecQualidadeIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TCensecTipoAtoIndex from '@/packages/administrativo/components/TCensecTipoAto/TCensecTipoAtoIndex';
export default function GTBEstadoCivilPage() {
return <TCensecTipoAtoIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import GCidadeIndex from '@/packages/administrativo/components/GCidade/GCidadeIndex';
export default function GCidadePage() {
return <GCidadeIndex />;
}

View file

@ -0,0 +1,5 @@
import GCalculoIndex from '@/packages/administrativo/components/GCalculo/GCalculoIndex';
export default function GEmolumentoPeriodoPage() {
return <GCalculoIndex />;
}

View file

@ -0,0 +1,16 @@
'use client';
import { useParams } from 'next/navigation';
import GEmolumentoItemIndex from '@/packages/administrativo/components/GEmolumentoItem/GEmolumentoItemIndex';
export default function GGramaticaPage() {
const params = useParams();
return (
<GEmolumentoItemIndex
emolumento_id={Number(params.emolumentoId)}
emolumento_periodo_id={Number(params.emolumentoPeriodoId)}
/>
);
}

View file

@ -0,0 +1,5 @@
import GEmolumentoIndex from '@/packages/administrativo/components/GEmolumento/GEmolumentoIndex';
export default function GEmolumentoPeriodoPage() {
return <GEmolumentoIndex />;
}

View file

@ -0,0 +1,5 @@
import GEmolumentoPeriodoIndex from '@/packages/administrativo/components/GEmolumentoPeriodo/GEmolumentoPeriodoIndex';
export default function GEmolumentoPeriodoPage() {
return <GEmolumentoPeriodoIndex />;
}

View file

@ -0,0 +1,5 @@
import GGramaticaIndex from '@/packages/administrativo/components/GGramatica/GGramaticaIndex';
export default function GGramaticaPage() {
return <GGramaticaIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TImovelDashboard from '@/packages/administrativo/components/TImovel/TImovelDashboard';
export default function TImovelDashboardPage() {
return <TImovelDashboard />;
}

View file

@ -0,0 +1,13 @@
'use client';
import TImovelIndex from '@/packages/administrativo/components/TImovel/TImovelIndex';
export default function TImovelRuralPage() {
return (
<TImovelIndex
pageTitle="Imóveis Rurais"
pageDescription="Gerenciamento de imóveis rurais"
tipoClasse={3}
/>
);
}

View file

@ -0,0 +1,7 @@
'use client';
import GTBTipoLogradouroIndex from '@/packages/administrativo/components/GTBTipoLogradouro/GTBTipoLogradouroIndex';
export default function GMedidaTipoPage() {
return <GTBTipoLogradouroIndex />;
}

View file

@ -0,0 +1,13 @@
'use client';
import TImovelIndex from '@/packages/administrativo/components/TImovel/TImovelIndex';
export default function TImovelUrbanoPage() {
return (
<TImovelIndex
pageTitle="Imóveis Urbanos"
pageDescription="Gerenciamento de imóveis urbanos"
tipoClasse={1}
/>
);
}

View file

@ -0,0 +1,7 @@
'use client';
import GMedidaTipoIndex from '@/packages/administrativo/components/GMedidaTipo/GMedidaTipoIndex';
export default function GMedidaTipoPage() {
return <GMedidaTipoIndex />;
}

View file

@ -0,0 +1,5 @@
import GNaturezaIndex from '@/packages/administrativo/components/GNatureza/GNaturezaIndex';
export default function GNaturezaPage() {
return <GNaturezaIndex sistema_id={2} />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TPessoaDashboard from '@/packages/administrativo/components/TPessoa/TPessoaDashboard';
export default function TPessoaDashboardPage() {
return <TPessoaDashboard />;
}

View file

@ -0,0 +1,7 @@
'use client';
import GTBEstadoCivilIndex from '@/packages/administrativo/components/GTBEstadoCivil/GTBEstadoCivilIndex';
export default function GTBEstadoCivilPage() {
return <GTBEstadoCivilIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TPessoaFisicaIndex from '@/packages/administrativo/components/TPessoa/TPessoaFisica/TPessoaFisicaIndex';
export default function TPessoaFisica() {
return <TPessoaFisicaIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import TPessoaJuridicaIndex from '@/packages/administrativo/components/TPessoa/TPessoaJuridica/TPessoaJuridicaIndex';
export default function TPessoaFisica() {
return <TPessoaJuridicaIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import GTBProfissaoIndex from '@/packages/administrativo/components/GTBProfissao/GTBProfissaoIndex';
export default function GTBEstadoCivilPage() {
return <GTBProfissaoIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import GTBRegimeBensIndex from '@/packages/administrativo/components/GTBRegimeBens/GTBRegimeBensIndex';
export default function GTBRegimeBensPage() {
return <GTBRegimeBensIndex />;
}

View file

@ -0,0 +1,7 @@
'use client';
import GTBRegimeComunhaoIndex from '@/packages/administrativo/components/GTBRegimeComunhao/GTBRegimeComunhaoIndex';
export default function GTBRegimeBensPage() {
return <GTBRegimeComunhaoIndex />;
}

View file

@ -0,0 +1,5 @@
import TTBReconhecimentoTipoIndex from '@/packages/administrativo/components/TTBReconhecimentoTipo/TTBReconhecimentoTipoIndex';
export default function TAtoParteTipo() {
return <TTBReconhecimentoTipoIndex />;
}

View file

@ -0,0 +1,5 @@
import GSeloGrupoIndex from '@/packages/administrativo/components/GSeloGrupo/GSeloGrupoIndex';
export default function GSeloGrupoPage() {
return <GSeloGrupoIndex />;
}

View file

@ -0,0 +1,5 @@
import TServicoTipoIndex from '@/packages/administrativo/components/TServicoTipo/TServicoTipoIndex';
export default function TServicoTipoPage() {
return <TServicoTipoIndex />;
}

View file

@ -0,0 +1,5 @@
import GNaturezaTituloIndex from '@/packages/administrativo/components/GNaturezaTitulo/GNaturezaTituloIndex';
export default function GNaturezaPage() {
return <GNaturezaTituloIndex sistema_id={2} />;
}

View file

@ -0,0 +1,72 @@
'use client';
import { useParams } from 'next/navigation';
import { useEffect, useState } from 'react';
import MainEditor from '@/components/MainEditor';
import { Card, CardContent } from '@/components/ui/card';
import { useTMinutaReadHook } from '@/packages/administrativo/hooks/TMinuta/useTMinutaReadHook';
import { TMinutaInterface } from '@/packages/administrativo/interfaces/TMinuta/TMinutaInterface';
import Loading from '@/shared/components/loading/loading';
export default function TMinutaDetalhes() {
const params = useParams();
const { tMinuta, fetchTMinuta } = useTMinutaReadHook();
const [editorContent, setEditorContent] = useState<string | null>(null); // Inicialmente nulo até o texto ser carregado
useEffect(() => {
if (params.id) {
fetchTMinuta({ t_minuta_id: Number(params.id) } as TMinutaInterface);
}
}, []);
useEffect(() => {
if (tMinuta?.texto) {
setEditorContent(tMinuta.texto); // Atualiza o conteúdo assim que estiver disponível
}
}, [tMinuta]); // Dependência de `tMinuta` para que a atualização aconteça quando os dados chegarem
const handleEditorChange = (content: string) => {
setEditorContent(content); // Atualiza o estado com o conteúdo do editor
};
if (!tMinuta) return <Loading type={1} />;
// Renderiza o editor apenas se o texto foi carregado
if (editorContent === null) {
return <Loading type={1} />; // Pode mostrar um carregando ou qualquer outra coisa enquanto o conteúdo não está disponível
}
return (
<div>
<Card>
<CardContent>
<div className="mb-4 grid grid-cols-2 gap-4">
<div>
<div className="text-2xl font-semibold">Descrição</div>
<div className="text-xl">{tMinuta.descricao}</div>
</div>
<div>
<div className="text-2xl font-semibold">Situação</div>
<div className="text-xl">{tMinuta.situacao === 'A' ? 'Ativo' : 'Inativo'}</div>
</div>
<div className="col-span-2">
<div className="text-2xl font-semibold">Texto</div>
<MainEditor
initialValue={editorContent} // Passa o conteúdo do editor
onEditorChange={handleEditorChange} // Função que atualiza o estado
margins={{
top: '2',
bottom: '2',
left: '2',
right: '2',
}}
size={{ width: 794, height: 1123 }} // Você pode ajustar o tamanho aqui
/>
</div>
</div>
</CardContent>
</Card>
</div>
);
}

View file

@ -0,0 +1,107 @@
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect } from 'react';
import { useForm, Controller } from 'react-hook-form';
import z from 'zod';
import MainEditor from '@/components/MainEditor';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useTMinutaSaveHook } from '@/packages/administrativo/hooks/TMinuta/useTMinutaSaveHook';
import { TMinutaSchema } from '@/packages/administrativo/schemas/TMinuta/TMinutaSchema';
type FormValues = z.infer<typeof TMinutaSchema>;
export default function TMinutaForm() {
const { tMinuta, saveTMinuta } = useTMinutaSaveHook();
const form = useForm<FormValues>({
resolver: zodResolver(TMinutaSchema),
defaultValues: {
natureza_id: undefined,
descricao: '',
situacao: 'A',
texto: '',
},
});
async function onSubmit(values: FormValues) {
saveTMinuta(values);
}
return (
<div>
<Card>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
{/* Descrição */}
<FormField
control={form.control}
name="descricao"
render={({ field }) => (
<FormItem>
<FormLabel>Descrição</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a descrição da minuta" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{/* Situação */}
<Controller
name="situacao"
control={form.control}
render={({ field }) => (
<div className="flex items-center space-x-2">
<Checkbox
checked={field.value === 'A'}
onCheckedChange={(checked) => field.onChange(checked ? 'A' : 'I')}
/>
<Label>{field.value === 'A' ? 'Ativo' : 'Inativo'}</Label>
</div>
)}
/>
{/* Editor de Texto */}
<Controller
name="texto"
control={form.control}
render={({ field }) => (
<div>
<MainEditor
initialValue={field.value || ''}
onEditorChange={field.onChange}
margins={{ top: '0', bottom: '0', left: '0', right: '0' }}
size={{ width: 794, height: 1123 }}
/>
{form.formState.errors.texto && (
<p className="mt-2 text-sm text-red-500">
{form.formState.errors.texto.message}
</p>
)}
</div>
)}
/>
<Button type="submit">Salvar</Button>
</form>
</Form>
</CardContent>
</Card>
</div>
);
}

View file

@ -0,0 +1,102 @@
'use client';
import { useEffect, useState, useCallback } from 'react';
import { Card, CardContent } from '@/components/ui/card';
import TMinutaForm from '@/packages/administrativo/components/TMinuta/TMinutaForm';
import TMinutaTable from '@/packages/administrativo/components/TMinuta/TMinutaTable';
import { useTMinutaIndexHook } from '@/packages/administrativo/hooks/TMinuta/useTMinutaIndexHook';
import { useTMinutaReadHook } from '@/packages/administrativo/hooks/TMinuta/useTMinutaReadHook';
import { useTMinutaRemoveHook } from '@/packages/administrativo/hooks/TMinuta/useTMinutaRemoveHook';
import { useTMinutaSaveHook } from '@/packages/administrativo/hooks/TMinuta/useTMinutaSaveHook';
import { TMinutaInterface } from '@/packages/administrativo/interfaces/TMinuta/TMinutaInterface';
import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog';
import { useConfirmDialog } from '@/shared/components/confirmDialog/useConfirmDialog';
import Loading from '@/shared/components/loading/loading';
import Header from '@/shared/components/structure/Header';
export default function TMinutaPage() {
// Hooks de leitura e escrita
const { tMinuta, fetchTMinuta } = useTMinutaIndexHook();
const { saveTMinuta } = useTMinutaSaveHook();
const { removeTMinuta } = useTMinutaRemoveHook();
// Estados
const [selectedMinuta, setSelectedMinuta] = useState<TMinutaInterface | null>(null);
const [isFormOpen, setIsFormOpen] = useState(false);
const [itemToDelete, setItemToDelete] = useState<TMinutaInterface | null>(null);
// Hook de confirmação
const {
isOpen: isConfirmOpen,
openDialog: openConfirmDialog,
handleConfirm,
handleCancel,
} = useConfirmDialog();
// Abertura do formulário
const handleOpenForm = useCallback((data: TMinutaInterface | null) => {
setSelectedMinuta(data);
setIsFormOpen(true);
}, []);
// Ação de clique em remover
const handleConfirmDelete = useCallback(
(item: TMinutaInterface) => {
setItemToDelete(item);
openConfirmDialog();
},
[openConfirmDialog],
);
// Remoção da minuta após confirmação
const handleDelete = useCallback(async () => {
if (!itemToDelete) return;
await removeTMinuta(itemToDelete);
await fetchTMinuta();
setItemToDelete(null);
handleCancel();
}, [itemToDelete, removeTMinuta, fetchTMinuta, handleCancel]);
// Fetch inicial
useEffect(() => {
fetchTMinuta();
}, []);
// Loading enquanto carrega
if (tMinuta === undefined) {
return <Loading type={2} />;
}
return (
<div>
{/* Cabeçalho */}
<Header
title="Minutas"
description="Gerenciamento de minutas de atos notariais"
buttonText="Nova Minuta"
buttonAction={() => handleOpenForm(null)}
/>
{/* Tabela */}
<Card>
<CardContent>
<TMinutaTable data={tMinuta} onEdit={handleOpenForm} onDelete={handleConfirmDelete} />
</CardContent>
</Card>
{/* Diálogo de confirmação */}
<ConfirmDialog
isOpen={isConfirmOpen}
title="Confirmar exclusão"
description="Atenção"
message={`Deseja realmente excluir a minuta "${itemToDelete?.descricao}"?`}
confirmText="Sim, excluir"
cancelText="Cancelar"
onConfirm={handleDelete}
onCancel={handleCancel}
/>
</div>
);
}

View file

@ -1,9 +1,9 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "../globals.css";
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import '../globals.css';
import { ResponseProvider } from '../_response/ResponseContext';
import { AppSidebar } from "@/components/app-sidebar"
import { AppSidebar } from '@/components/app-sidebar';
import { ThemeProvider } from '@/components/theme-provider';
import {
Breadcrumb,
BreadcrumbItem,
@ -11,75 +11,72 @@ import {
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Separator } from "@/components/ui/separator"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar"
import { Toaster } from "@/components/ui/sonner";
import Response from "../_response/response";
} from '@/components/ui/breadcrumb';
import { Separator } from '@/components/ui/separator';
import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
import { Toaster } from '@/components/ui/sonner';
import Response from '../../shared/components/response/response';
import { ResponseProvider } from '../../shared/components/response/ResponseContext';
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
variable: '--font-geist-sans',
subsets: ['latin'],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
variable: '--font-geist-mono',
subsets: ['latin'],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: 'SAAS - Orius Tecnologia',
description: 'Evolução tecnológica com toque humano',
icons: {
icon: '/images/favicon.ico',
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
<Separator
orientation="vertical"
className="mr-2 data-[orientation=vertical]:h-4"
/>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<ResponseProvider>
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
{children}
<Toaster position="top-center" />
<Response />
</div>
</ResponseProvider>
</SidebarInset>
</SidebarProvider>
<html lang="en" suppressHydrationWarning>
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<ThemeProvider>
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="mb-4 flex h-16 shrink-0 items-center gap-2 border-b-1 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
<Separator
orientation="vertical"
className="mr-2 data-[orientation=vertical]:h-4"
/>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">Building Your Application</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
</header>
<ResponseProvider>
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">
{children}
<Toaster richColors position="top-center" />
<Response />
</div>
</ResponseProvider>
</SidebarInset>
</SidebarProvider>
</ThemeProvider>
</body>
</html>
);

View file

@ -0,0 +1,51 @@
'use client';
import { useEffect, useState } from 'react';
import useGUsuarioGetJWTHook from '@/shared/hooks/auth/useGUsuarioGetJWTHook';
export default function Page() {
const { userAuthenticated } = useGUsuarioGetJWTHook();
// Inicializa time como null para renderizar só no cliente
const [time, setTime] = useState<Date | null>(null);
useEffect(() => {
setTime(new Date()); // define data inicial no cliente
const interval = setInterval(() => setTime(new Date()), 1000);
return () => clearInterval(interval);
}, []);
// Se ainda não temos a hora, renderiza nada para evitar mismatch
if (!time || !userAuthenticated?.data) return null;
const hours = time.getHours();
const greeting = hours < 12 ? 'Bom dia' : hours < 18 ? 'Boa tarde' : 'Boa noite';
const formattedDate = time.toLocaleDateString('pt-BR', {
weekday: 'long',
day: '2-digit',
month: 'long',
});
const formattedTime = time.toLocaleTimeString('pt-BR');
return (
<main className="fixed inset-0 flex flex-col items-center justify-center overflow-hidden text-gray-800 select-none">
<section className="max-w-md px-4 text-center">
<h1 className="mb-2 text-4xl font-bold">
{greeting}, <span className="text-blue-600">{userAuthenticated.data.nome}</span> 👋
</h1>
<p className="mb-6 text-sm text-gray-600">
Hoje é <strong>{formattedDate}</strong>, {formattedTime}
</p>
<div className="rounded-2xl p-6">
<p className="leading-relaxed text-gray-700">
Que bom ter você de volta! 🎉 Aproveite o seu dia e continue alcançando seus objetivos.
</p>
</div>
</section>
</main>
);
}

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

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

View file

@ -0,0 +1,11 @@
'use client';
import { useParams } from 'next/navigation';
import TServicoPedidoDetails from '@/packages/servicos/components/TServicoPedido/TServicoPedidoDetails';
export default function TServicoPedidoDetailsPage() {
const params = useParams();
return <TServicoPedidoDetails servico_pedido_id={Number(params.servicoPedidoId)} />;
}

View file

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

View file

@ -0,0 +1,11 @@
'use client';
import { useParams } from 'next/navigation';
import TServicoPedidoForm from '@/packages/servicos/components/TServicoPedido/TServicoPedidoForm';
export default function TServicoPedidoPage() {
const params = useParams();
return <TServicoPedidoForm servico_pedido_id={Number(params.servicoPedidoId)} />;
}

View file

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

View file

@ -1,21 +1,21 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "../../globals.css";
import { Suspense } from "react";
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import '../../globals.css';
import { Suspense } from 'react';
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
variable: '--font-geist-sans',
subsets: ['latin'],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
variable: '--font-geist-mono',
subsets: ['latin'],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout({
@ -25,9 +25,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
{children}
</body>
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
</html>
);
}

View file

@ -1,4 +1,4 @@
import { LoginForm } from "@/components/login-form"
import { LoginForm } from '@/components/login-form';
export default function LoginPage() {
return (
@ -7,5 +7,5 @@ export default function LoginPage() {
<LoginForm />
</div>
</div>
)
}
);
}

View file

@ -0,0 +1,111 @@
'use client';
import React, { useState } from 'react';
import {
AlertDialog,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogAction,
} from '@/components/ui/alert-dialog';
import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp';
interface ConfirmExclusionProps {
isOpen: boolean;
title: string;
description?: string;
expectedCode: string;
confirmText?: string;
cancelText?: string;
onConfirm: () => void;
onCancel: () => void;
onResendCode: () => void; // Função para reenviar o código
}
export default function ConfirmExclusion({
isOpen,
title,
description,
expectedCode,
confirmText = 'Continuar',
cancelText = 'Cancelar',
onConfirm,
onCancel,
onResendCode, // A função para reenvio do código
}: ConfirmExclusionProps) {
const [code, setCode] = useState('');
const [isValid, setIsValid] = useState(false);
const [isResending, setIsResending] = useState(false); // Novo estado para controle de envio do código
const handleChange = (value: string) => {
setCode(value);
setIsValid(value === expectedCode);
};
const handleResendCode = async () => {
setIsResending(true);
try {
await onResendCode(); // Chamando a função de reenvio
} catch (error) {
console.error('Erro ao reenviar código', error);
} finally {
setIsResending(false); // Resetando o estado de envio
}
};
return (
<AlertDialog open={isOpen} onOpenChange={(open) => !open && onCancel()}>
<AlertDialogContent className="mx-auto max-w-lg p-6">
<AlertDialogHeader className="text-center">
<AlertDialogTitle className="text-center text-xl font-semibold">{title}</AlertDialogTitle>
{description && (
<AlertDialogDescription className="text-muted-foreground mt-2 text-center text-sm">
{description}
</AlertDialogDescription>
)}
</AlertDialogHeader>
<div className="text-muted-foreground space-y-4 py-4 text-sm">
<div className="flex justify-center">
<InputOTP maxLength={expectedCode.length} value={code} onChange={handleChange}>
<InputOTPGroup className="flex gap-4">
{expectedCode.split('').map((_, index) => (
<InputOTPSlot
key={index}
index={index}
className="h-12 w-12 rounded-lg border-2 border-gray-300 text-center text-lg focus:ring-2 focus:ring-blue-500"
/>
))}
</InputOTPGroup>
</InputOTP>
</div>
{/* Botão "Reenviar Código" */}
<div className="mt-4 flex items-center justify-center gap-2 text-center">
<AlertDialogDescription>Não recebeu o código?</AlertDialogDescription>
<button
onClick={handleResendCode}
className={`cursor-pointer font-semibold text-blue-500 ${isResending ? 'cursor-not-allowed text-gray-400' : 'hover:text-blue-600'}`}
disabled={isResending} // Desabilita o botão enquanto o código está sendo reenviado
>
{isResending ? 'Enviando...' : 'Reenviar Código'}
</button>
</div>
</div>
<AlertDialogFooter>
<AlertDialogCancel onClick={onCancel} className="text-gray-600 hover:text-gray-800">
{cancelText}
</AlertDialogCancel>
<AlertDialogAction onClick={onConfirm} disabled={!isValid}>
{confirmText}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}

View file

@ -0,0 +1,55 @@
import { useCallback, useState } from 'react';
interface UseConfirmExclusionOptions {
onConfirm?: () => void;
onCancel?: () => void;
expectedCode: string; // código que o usuário precisa digitar
}
export function useConfirmExclusion({
onConfirm,
onCancel,
expectedCode,
}: UseConfirmExclusionOptions) {
const [isOpen, setIsOpen] = useState(false);
const [code, setCode] = useState('');
const [isValid, setIsValid] = useState(false);
const openDialog = useCallback(() => setIsOpen(true), []);
const closeDialog = useCallback(() => {
setIsOpen(false);
setCode(''); // limpa o código quando fecha
setIsValid(false);
}, []);
const handleConfirm = useCallback(() => {
if (isValid) {
onConfirm?.();
closeDialog();
}
}, [isValid, onConfirm, closeDialog]);
const handleCancel = useCallback(() => {
onCancel?.();
closeDialog();
}, [onCancel, closeDialog]);
const handleChange = useCallback(
(value: string) => {
setCode(value);
setIsValid(value === expectedCode);
},
[expectedCode],
);
return {
isOpen,
code,
isValid,
openDialog,
closeDialog,
handleConfirm,
handleCancel,
handleChange,
};
}

View file

@ -1,18 +0,0 @@
import React from "react";
import SkeletonCard from "./skeletonCard";
import SkeletonTable from "./skeletonTable";
export default function Loading({ type }: any) {
switch (type) {
case 1:
return <SkeletonCard />;
break;
case 2:
return <SkeletonTable />
break;
}
}

View file

@ -1,35 +0,0 @@
export default function SkeletonCard() {
return (
<div className="space-y-6">
<div className="space-y-2">
<div className="h-4 w-24 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
<div className="h-10 w-full bg-gray-200 dark:bg-slate-700 rounded-md animate-pulse"></div>
</div>
<div className="space-y-2">
<div className="h-4 w-32 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
<div className="h-10 w-full bg-gray-200 dark:bg-slate-700 rounded-md animate-pulse"></div>
</div>
<div className="space-y-2">
<div className="h-4 w-28 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
<div className="h-20 w-full bg-gray-200 dark:bg-slate-700 rounded-md animate-pulse"></div>
</div>
<div className="space-y-2">
<div className="h-4 w-20 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
<div className="h-10 w-full bg-gray-200 dark:bg-slate-700 rounded-md animate-pulse"></div>
</div>
<div>
<div className="h-10 w-32 bg-gray-200 dark:bg-slate-700 rounded-full animate-pulse"></div>
</div>
</div>
);
}

View file

@ -1,81 +0,0 @@
export default function SkeletonTable() {
return (
<div>
<div role="status" aria-busy="true" aria-label="Carregando tabela" className="p-4 w-full">
<div className="overflow-x-auto">
<table className="w-full border-collapse">
<thead>
<tr>
<th className="px-4 py-2 text-left">
<div className="h-4 w-20 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</th>
<th className="px-4 py-2 text-left">
<div className="h-4 w-28 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</th>
<th className="px-4 py-2 text-left">
<div className="h-4 w-24 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</th>
<th className="px-4 py-2 text-left">
<div className="h-4 w-16 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</th>
</tr>
</thead>
<tbody>
<tr className="border-t">
<td className="px-4 py-3">
<div className="h-4 w-24 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-32 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-20 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-16 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
</tr>
<tr className="border-t">
<td className="px-4 py-3">
<div className="h-4 w-20 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-24 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-28 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-16 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
</tr>
<tr className="border-t">
<td className="px-4 py-3">
<div className="h-4 w-28 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-20 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-24 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
<td className="px-4 py-3">
<div className="h-4 w-16 bg-gray-200 dark:bg-slate-700 rounded animate-pulse"></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
);
}

View file

@ -1,20 +0,0 @@
// app/src/app/_response/response.tsx
"use client";
import { useResponse } from "./ResponseContext";
import { useEffect } from "react";
import { toast } from "sonner";
export default function Response() {
const { response, clearResponse } = useResponse();
useEffect(() => {
switch (Number(response?.status)) {
case 200:
toast(response.message);
break;
}
}, [response, clearResponse]);
return <div></div>;
}

View file

@ -1,115 +1,204 @@
@import "tailwindcss";
@import "tw-animate-css";
@import 'tailwindcss';
@import 'tw-animate-css';
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--background: oklch(0.9911 0 0);
--foreground: oklch(0.2988 0.0123 222.4429);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--card-foreground: oklch(0.2988 0.0123 222.4429);
--popover: oklch(0.9881 0 0);
--popover-foreground: oklch(0.2988 0.0123 222.4429);
--primary: oklch(0.721 0.1873 47.564);
--primary-foreground: oklch(1 0 0);
--secondary: oklch(0.2988 0.0123 222.4429);
--secondary-foreground: oklch(1 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--accent: oklch(0.9551 0 0);
--accent-foreground: oklch(0.2988 0.0123 222.4429);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(1 0 0);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--chart-1: oklch(0.81 0.1 252);
--chart-2: oklch(0.62 0.19 260);
--chart-3: oklch(0.55 0.22 263);
--chart-4: oklch(0.49 0.22 264);
--chart-5: oklch(0.42 0.18 266);
--sidebar: oklch(1 0 0);
--sidebar-foreground: oklch(0.2988 0.0123 222.4429);
--sidebar-primary: oklch(0.2364 0.0083 240.2365);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
--font-sans:
ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
--font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
--font-mono:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
monospace;
--radius: 0.625rem;
--shadow-x: 0;
--shadow-y: 1px;
--shadow-blur: 3px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: oklch(0 0 0);
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
--shadow-offset-x: 0;
--shadow-offset-y: 1px;
--letter-spacing: 0em;
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--background: oklch(0.1934 0.0062 236.9149);
--foreground: oklch(0.9881 0 0);
--card: oklch(0.2364 0.0083 240.2365);
--card-foreground: oklch(0.9881 0 0);
--popover: oklch(0.2988 0.0123 222.4429);
--popover-foreground: oklch(0.9881 0 0);
--primary: oklch(0.721 0.1873 47.564);
--primary-foreground: oklch(0.2988 0.0123 222.4429);
--secondary: oklch(0.2988 0.0123 222.4429);
--secondary-foreground: oklch(1 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--accent: oklch(0.2988 0.0123 222.4429);
--accent-foreground: oklch(1 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--destructive-foreground: oklch(0.985 0 0);
--border: oklch(0.275 0 0);
--input: oklch(0.325 0 0);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--chart-1: oklch(0.81 0.1 252);
--chart-2: oklch(0.62 0.19 260);
--chart-3: oklch(0.55 0.22 263);
--chart-4: oklch(0.49 0.22 264);
--chart-5: oklch(0.42 0.18 266);
--sidebar: oklch(0.2364 0.0083 240.2365);
--sidebar-foreground: oklch(0.9881 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
--sidebar-border: oklch(0.275 0 0);
--sidebar-ring: oklch(0.439 0 0);
--font-sans:
ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
--font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
--font-mono:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
monospace;
--radius: 0.625rem;
--shadow-x: 0;
--shadow-y: 1px;
--shadow-blur: 3px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: oklch(0 0 0);
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
--shadow-offset-x: 0;
--shadow-offset-y: 1px;
--letter-spacing: 0em;
--spacing: 0.25rem;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--font-sans:
ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
--font-mono:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
monospace;
--font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--shadow-2xs: var(--shadow-2xs);
--shadow-xs: var(--shadow-xs);
--shadow-sm: var(--shadow-sm);
--shadow: var(--shadow);
--shadow-md: var(--shadow-md);
--shadow-lg: var(--shadow-lg);
--shadow-xl: var(--shadow-xl);
--shadow-2xl: var(--shadow-2xl);
--radius: 0.625rem;
--tracking-tighter: calc(var(--tracking-normal) - 0.05em);
--tracking-tight: calc(var(--tracking-normal) - 0.025em);
--tracking-wide: calc(var(--tracking-normal) + 0.025em);
--tracking-wider: calc(var(--tracking-normal) + 0.05em);
--tracking-widest: calc(var(--tracking-normal) + 0.1em);
--tracking-normal: var(--tracking-normal);
--spacing: var(--spacing);
--letter-spacing: var(--letter-spacing);
--shadow-offset-y: var(--shadow-offset-y);
--shadow-offset-x: var(--shadow-offset-x);
--shadow-spread: var(--shadow-spread);
--shadow-blur: var(--shadow-blur);
--shadow-opacity: var(--shadow-opacity);
--color-shadow-color: var(--shadow-color);
}
@layer base {
@ -118,8 +207,9 @@
}
body {
@apply bg-background text-foreground;
letter-spacing: var(--tracking-normal);
}
.bg-brand{
background-color: #1A292F;
.bg-brand {
background-color: #1a292f;
}
}

View file

@ -1,6 +1,4 @@
// components/Loading.tsx
export default function Loading() {
return (
<span className="loading loading-spinner loading-xs"></span>
)
return <span className="loading loading-spinner loading-xs"></span>;
}

View file

@ -0,0 +1,160 @@
import { Editor } from '@tinymce/tinymce-react';
import React from 'react';
// 1. Define as propriedades que nosso componente vai receber
interface MainEditorProps {
initialValue: string;
onEditorChange: (content: string) => void;
margins: {
top: string;
bottom: string;
left: string;
right: string;
};
size: {
width: number;
height: number;
};
}
const MainEditor: React.FC<MainEditorProps> = ({ initialValue, onEditorChange, margins, size }) => {
return (
<div className="flex justify-center">
<Editor
apiKey="sny4ncto4hf42akdz2eqss2tqd0loo439vfttpuydjc2kqpi"
value={initialValue}
onEditorChange={onEditorChange}
init={{
width: size.width,
height: size.height,
menubar: false,
browser_spellcheck: true,
contextmenu: false,
plugins: [
'advlist',
'autolink',
'lists',
'link',
'image',
'charmap',
'preview',
'anchor',
'searchreplace',
'visualblocks',
'fullscreen',
'insertdatetime',
'media',
'table',
'code',
'codesample',
'help',
'wordcount',
'autosave',
'quickbars',
'quickbars link',
'quickbars image editimage',
'pagebreak',
'nonbreaking',
'advlist',
'autolink',
],
autosave_ask_before_unload: true,
toolbar:
'undo redo styles removeformat formatselect fontfamily fontsize forecolor link quickimage bold italic underline align bullist numlist outdent indent removeformat preview fullscreen searchreplace help code codesample quicktable pagebreak nonbreaking charmap customTemplates',
formats: {
linhatopo: {
selector: 'div',
classes: 'borda-superior',
},
linhainferior: {
selector: 'div',
classes: 'borda-inferior',
},
},
style_formats: [
{
title: 'Estilos de Borda',
items: [
{ title: 'Linha Superior', format: 'linhatopo' },
{ title: 'Linha Inferior', format: 'linhainferior' },
],
},
],
setup: (editor: any) => {
const customTemplates = [
{
title: 'Qualificação das Partes (Casamento)',
description: 'Insere o bloco de qualificação para contraentes.',
content: `<p><strong>QUALIFICAÇÃO DOS CONTRAENTES:</strong> Ele, brasileiro, solteiro, maior, [Profissão], portador da CI nº [RG], inscrito no CPF sob o nº [CPF], residente e domiciliado em [Endereço]. Ela, brasileira, solteira, maior, [Profissão], portadora da CI nº [RG], inscrita no CPF sob o nº [CPF], residente e domiciliada em [Endereço].</p><br>`,
},
{
title: 'Cláusula de Regime de Bens',
description: 'Cláusula padrão de Comunhão Parcial de Bens.',
content:
'<p>O regime de bens adotado é o da <strong>Comunhão Parcial de Bens</strong>, nos termos dos artigos 1.658 e seguintes do Código Civil brasileiro.</p><br>',
},
{
title: 'Cláusula de Encerramento (Selo)',
description: 'Texto final com espaço para o selo digital.',
content:
'<p>O referido é verdade e dou fé. Emitida nesta data. Selo Digital de Fiscalização: [Número do Selo]</p>',
},
];
editor.ui.registry.addMenuButton('customTemplates', {
text: 'Modelos', // O texto que aparecerá no botão
fetch: (callback: any) => {
const items = customTemplates.map((template) => ({
type: 'menuitem',
text: template.title,
onAction: () => {
// 3. Ação que acontece ao clicar no item do menu: insere o conteúdo
editor.insertContent(template.content);
},
}));
callback(items);
},
});
},
quickbars_selection_toolbar:
'bold italic underline | fontfamily | fontsize | quicklink blockquote | quicklink',
quickbars_insert_toolbar:
'bold italic underline fontfamily fontsize quicklink blockquote quicklink quickimage quicktable hr',
quickbars_image_toolbar:
'alignleft aligncenter alignright | rotateleft rotateright | imageoptions',
fontsize_formats:
'4pt 5pt 6pt 7pt 8pt 9pt 10pt 12pt 14pt 16pt 18pt 20pt 22pt 24pt 26pt 28pt 30pt 32pt 34pt 36pt',
font_family_formats: ` Times New Roman=Times New Roman, Times, serif; Arial=Arial, Helvetica, sans-serif; Calibri=Calibri, sans-serif; Courier New=Courier New, Courier, monospace; Georgia=Georgia, serif; Verdana=Verdana, Geneva, sans-serif;`,
fullscreen_native: true,
content_style: `
body {
font-family: 'Times New Roman', Times, serif;
font-size: 12pt;
background: #fff;
margin: ${margins.top}cm ${margins.right}cm ${margins.bottom}cm ${margins.left}cm;
}
.mce-pagebreak { /* Estiliza a linha da quebra de página no editor */
border-top: 1px dashed #bbb;
width: 100%;
margin-top: 15px;
cursor: default;
}
.borda-superior {
border-top: 1px solid #000;
padding-top: 5px;
margin-top: 5px;
}
.borda-inferior {
border-bottom: 1px solid #000;
padding-bottom: 5px;
margin-bottom: 5px;
}
`,
}}
/>
</div>
);
};
export default MainEditor;

View file

@ -1,167 +1,261 @@
"use client"
'use client';
import * as React from "react"
import {
AudioWaveform,
BookOpen,
Bot,
Command,
Frame,
GalleryVerticalEnd,
Map,
PieChart,
Settings2,
HouseIcon,
SquareMousePointer,
SquareTerminal,
} from "lucide-react"
UsersIcon,
} from 'lucide-react';
import Image from 'next/image';
import * as React from 'react';
import { NavMain } from "@/components/nav-main"
import { NavProjects } from "@/components/nav-projects"
import { NavUser } from "@/components/nav-user"
import { TeamSwitcher } from "@/components/team-switcher"
import { NavMain } from '@/components/nav-main';
import { NavProjects } from '@/components/nav-projects';
import { NavUser } from '@/components/nav-user';
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
} from "@/components/ui/sidebar"
} from '@/components/ui/sidebar';
import useGUsuarioGetJWTHook from '@/shared/hooks/auth/useGUsuarioGetJWTHook';
// This is sample data.
const data = {
user: {
name: "shadcn",
email: "m@example.com",
avatar: "/avatars/shadcn.jpg",
},
teams: [
{
name: "Acme Inc",
logo: GalleryVerticalEnd,
plan: "Enterprise",
},
{
name: "Acme Corp.",
logo: AudioWaveform,
plan: "Startup",
},
{
name: "Evil Corp.",
logo: Command,
plan: "Free",
},
],
teams: [],
navMain: [
{
title: "Administrativo",
url: "#",
title: 'Administrativo',
url: '#',
icon: SquareTerminal,
isActive: true,
isActive: false,
items: [
{
title: "Usuários",
url: "/usuarios/",
title: 'Usuários',
url: '/usuarios/',
},
],
},
{
title: "Models",
url: "#",
title: 'Servicos',
url: '#',
icon: SquareMousePointer,
isActive: false,
items: [
{
title: 'Dashboard',
url: '/servicos/dashboard/',
},
{
title: 'Pedidos',
url: '/servicos/pedidos/',
},
{
title: 'Atos',
url: '/servicos/atos/',
},
],
},
{
title: 'Pessoas',
url: '#',
icon: UsersIcon,
isActive: false,
items: [
{
title: 'Dashboard',
url: '/administrativo/pessoas/dashboard',
},
{
title: 'Físicas',
url: '/administrativo/pessoas/fisicas',
},
{
title: 'Jurídicas',
url: '/administrativo/pessoas/juridicas',
},
],
},
{
title: 'Imóveis',
url: '#',
icon: HouseIcon,
isActive: false,
items: [
{
title: 'Dashboard',
url: '/administrativo/imoveis/dashboard',
},
{
title: 'Urbanos',
url: '/administrativo/imoveis/urbanos',
},
{
title: 'Rurais',
url: '/administrativo/imoveis/rurais',
},
],
},
{
title: 'Cadastros',
url: '#',
icon: Bot,
items: [
{
title: "Genesis",
url: "#",
title: 'Reconhecimentos',
url: '/administrativo/reconhecimentos/',
},
{
title: "Explorer",
url: "#",
title: 'Andamentos',
url: '/administrativo/andamentos/',
},
{
title: "Quantum",
url: "#",
},
],
},
{
title: "Documentation",
url: "#",
icon: BookOpen,
items: [
{
title: "Introduction",
url: "#",
title: 'Profissões',
url: '/administrativo/pessoas/profissoes/',
},
{
title: "Get Started",
url: "#",
title: 'Regimes/Bens',
url: '/administrativo/pessoas/regimes-bens/',
},
{
title: "Tutorials",
url: "#",
title: 'Tipos de Logradouros',
url: '/administrativo/imoveis/tipos-logradouro',
},
{
title: "Changelog",
url: "#",
},
],
},
{
title: "Settings",
url: "#",
icon: Settings2,
items: [
{
title: "General",
url: "#",
title: 'Estado Civil',
url: '/administrativo/pessoas/estados-civis',
},
{
title: "Team",
url: "#",
title: 'Regimes/Comunhão',
url: '/administrativo/pessoas/regimes-comunhao/',
},
{
title: "Billing",
url: "#",
title: 'Tipo de Medida',
url: '/administrativo/medidas/tipos',
},
{
title: "Limits",
url: "#",
title: 'Cidades',
url: '/administrativo/cidades/',
},
{
title: 'Bairro',
url: '/administrativo/bairros',
},
{
title: 'Minuta',
url: '/administrativo/minutas/',
},
{
title: 'Minuta/Naturezas',
url: '/administrativo/minutas/naturezas',
},
{
title: 'Censec/Tipo do Ato',
url: '/administrativo/centrais/censec/tipos-atos',
},
{
title: 'Censec/Qualidades',
url: '/administrativo/centrais/censec/qualidades',
},
{
title: 'Censec/Centrais',
url: '/administrativo/centrais/censec/centrais',
},
{
title: 'Censec/Natureza Litígio',
url: '/administrativo/centrais/censec/naturezas-litigios',
},
{
title: 'Tipos/Serviços',
url: '/administrativo/tipos-servicos',
},
{
title: 'Atos/Partes Tipos',
url: '/administrativo/atos/partes-tipos',
},
{
title: 'Valores de Serviços',
url: '/administrativo/valores-de-servicos',
},
{
title: 'Gramatica',
url: '/administrativo/gramatica',
},
{
title: 'Cartório',
url: '/administrativo/cartorio',
},
{
title: 'Financeiro/Periodo',
url: '/administrativo/financeiro/periodos',
},
{
title: 'Financeiro/Emolumentos',
url: '/administrativo/financeiro/emolumentos',
},
{
title: 'Selos/Grupos',
url: '/administrativo/selos/grupos',
},
{
title: 'Financeiro/Cálculo Rápido',
url: '/administrativo/financeiro/calculo-rapido',
},
],
},
],
projects: [
{
name: "Design Engineering",
url: "#",
name: 'Escritura Publica de Compra e Venda',
url: '#',
icon: Frame,
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChart,
},
{
name: "Travel",
url: "#",
icon: Map,
},
],
}
};
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
const { userAuthenticated } = useGUsuarioGetJWTHook();
return (
<Sidebar collapsible="icon" {...props}>
<SidebarHeader>
<TeamSwitcher teams={data.teams} />
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
<a href="#">
<div className="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg">
<GalleryVerticalEnd className="size-4" />
<Image
src="/images/logo-abb.png"
alt="Logo do site"
width={100}
height={100}
className="rounded-lg"
/>
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">Orius Tecnologia</span>
<span className="">25.9.1</span>
</div>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<NavMain items={data.navMain} />
<NavProjects projects={data.projects} />
</SidebarContent>
<SidebarFooter>
<NavUser user={data.user} />
{userAuthenticated?.data ? <NavUser user={userAuthenticated.data} /> : 'Carregando...'}
</SidebarFooter>
<SidebarRail />
</Sidebar>
)
);
}

View file

@ -1,171 +1,113 @@
'use client'
'use client';
import Image from "next/image";
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { UsuarioFormSchema } from "@/app/(protected)/(administrativo)/_schemas/GUsuarioSchema"
import z from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
import GUsuarioLoginService from "@/app/(protected)/(administrativo)/_services/g_usuario/GUsuarioLogin"
import { useForm } from "react-hook-form"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage
} from "./ui/form"
import { zodResolver } from '@hookform/resolvers/zod';
import Image from 'next/image';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import z from 'zod';
type FormValues = z.infer<typeof UsuarioFormSchema>
import { Card, CardContent } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';
import { GUsuarioLoginSchema } from '@/packages/administrativo/schemas/GUsuario/GUsuarioLoginSchema';
import GUsuarioLoginService from '@/packages/administrativo/services/GUsuario/GUsuarioLogin';
import LoadingButton from '@/shared/components/loadingButton/LoadingButton';
export function LoginForm({
className,
...props
}: React.ComponentProps<"div">) {
import { Button } from './ui/button';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from './ui/form';
type FormValues = z.infer<typeof GUsuarioLoginSchema>;
export function LoginForm({ className, ...props }: React.ComponentProps<'div'>) {
const [loading, setLoading] = useState(false);
const form = useForm<FormValues>({
resolver: zodResolver(UsuarioFormSchema),
resolver: zodResolver(GUsuarioLoginSchema),
defaultValues: {
login: '',
senha_api: ''
senha_api: '',
},
});
async function onSubmit(values: FormValues) {
const data = await GUsuarioLoginService(values);
}
// onSubmit agora recebe o evento do form através do handleSubmit
const onSubmit = async (values: FormValues) => {
// Ativa o estado de loading do botão
setLoading(true);
// Realiza o login
await GUsuarioLoginService(values);
// Removo o estado de loading do botão
setLoading(false);
};
return (
<div className={cn("flex flex-col gap-6", className)} {...props}>
<div className={cn('flex flex-col gap-6', className)} {...props}>
<Card className="overflow-hidden p-0">
<CardContent className="grid p-0 md:grid-cols-2">
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="p-6 md:p-8 gap-3">
<div className="flex flex-col gap-6">
<div className="flex flex-col items-center text-center">
<h1 className="text-2xl font-bold">
Bem vindo de volta!
</h1>
<p className="text-muted-foreground text-balance">
Entre na sua conta Orius Tecnologia.
</p>
</div>
<div className="grid gap-3">
<FormField
control={form.control}
name="login"
render={({ field }) => (
<FormItem>
<FormLabel>
Login
</FormLabel>
<FormControl>
<Input type="text" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="grid gap-3">
<FormField
control={form.control}
name="senha_api"
render={({ field }) => (
<FormItem>
<FormLabel>
Senha
</FormLabel>
<FormControl>
<Input type="password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-3 p-6 md:p-8">
<div className="mb-6 flex flex-col items-center text-center">
<h1 className="text-2xl font-bold">Bem vindo de volta!</h1>
<p className="text-muted-foreground text-balance">
Entre na sua conta Orius Tecnologia.
</p>
</div>
<Button type="submit" className="w-full my-3">
Entrar
</Button>
<FormField
control={form.control}
name="login"
render={({ field }) => (
<FormItem>
<FormLabel>Login</FormLabel>
<FormControl>
<Input type="text" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t">
<FormField
control={form.control}
name="senha_api"
render={({ field }) => (
<FormItem>
<FormLabel>Senha</FormLabel>
<FormControl>
<Input type="password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{/* Botão de loading */}
<LoadingButton
text="Entrar"
textLoading="Aguarde..."
type="submit"
loading={loading}
/>
<div className="after:border-border relative my-4 text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t">
<span className="bg-card text-muted-foreground relative z-10 px-2">
Ou entre em contato
</span>
</div>
<div className="grid grid-cols-2 gap-4">
<Button variant="outline" type="button" className="w-full">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-smartphone-icon lucide-smartphone">
<rect width="14" height="20" x="5" y="2" rx="2" ry="2" /><path d="M12 18h.01" />
</svg>
<span className="sr-only">
Chamar no Whatsapp
</span>
Chamar no Whatsapp
</Button>
<Button variant="outline" type="button" className="w-full">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-map-pin-icon lucide-map-pin">
<path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0" /><circle cx="12" cy="10" r="3" />
</svg>
<span className="sr-only">
Chamar no Whatsapp
</span>
Chamar no Local
</Button>
</div>
</form>
</Form>
<div className="bg-brand relative hidden md:flex items-center justify-center">
<div className="bg-brand relative hidden items-center justify-center md:flex">
<Image
src="/images/logo-login.svg"
alt="Logo"
@ -174,18 +116,13 @@ export function LoginForm({
className="object-contain dark:brightness-[0.2] dark:grayscale"
/>
</div>
</CardContent>
</Card>
<div className="text-muted-foreground *:[a]:hover:text-primary text-center text-xs text-balance *:[a]:underline *:[a]:underline-offset-4">
Ao clicar você concordar com <a href="#">Nossos termos de serviços</a>{" "}e <a href="#">Políticas de Privacidade</a>.
<div className="text-muted-foreground text-center text-xs">
Ao clicar você concorda com <a href="#">Nossos termos de serviços</a> e{' '}
<a href="#">Políticas de Privacidade</a>.
</div>
</div>
)
);
}

View file

@ -1,12 +1,9 @@
"use client"
'use client';
import { ChevronRight, type LucideIcon } from "lucide-react"
import { ChevronRight, type LucideIcon } from 'lucide-react';
import Link from 'next/link';
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import {
SidebarGroup,
SidebarGroupLabel,
@ -16,25 +13,25 @@ import {
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
} from "@/components/ui/sidebar"
} from '@/components/ui/sidebar';
export function NavMain({
items,
}: {
items: {
title: string
url: string
icon?: LucideIcon
isActive?: boolean
title: string;
url: string;
icon?: LucideIcon;
isActive?: boolean;
items?: {
title: string
url: string
}[]
}[]
title: string;
url: string;
}[];
}[];
}) {
return (
<SidebarGroup>
<SidebarGroupLabel>Platform</SidebarGroupLabel>
<SidebarGroupLabel>SAAS</SidebarGroupLabel>
<SidebarMenu>
{items.map((item) => (
<Collapsible
@ -56,9 +53,9 @@ export function NavMain({
{item.items?.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton asChild>
<a href={subItem.url}>
<Link href={subItem.url}>
<span>{subItem.title}</span>
</a>
</Link>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
@ -69,5 +66,5 @@ export function NavMain({
))}
</SidebarMenu>
</SidebarGroup>
)
);
}

View file

@ -1,12 +1,6 @@
"use client"
'use client';
import {
Folder,
Forward,
MoreHorizontal,
Trash2,
type LucideIcon,
} from "lucide-react"
import { Folder, Forward, MoreHorizontal, Trash2, type LucideIcon } from 'lucide-react';
import {
DropdownMenu,
@ -14,7 +8,7 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
} from '@/components/ui/dropdown-menu';
import {
SidebarGroup,
SidebarGroupLabel,
@ -23,22 +17,22 @@ import {
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar"
} from '@/components/ui/sidebar';
export function NavProjects({
projects,
}: {
projects: {
name: string
url: string
icon: LucideIcon
}[]
name: string;
url: string;
icon: LucideIcon;
}[];
}) {
const { isMobile } = useSidebar()
const { isMobile } = useSidebar();
return (
<SidebarGroup className="group-data-[collapsible=icon]:hidden">
<SidebarGroupLabel>Projects</SidebarGroupLabel>
<SidebarGroupLabel>Escrituras</SidebarGroupLabel>
<SidebarMenu>
{projects.map((item) => (
<SidebarMenuItem key={item.name}>
@ -57,8 +51,8 @@ export function NavProjects({
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-48 rounded-lg"
side={isMobile ? "bottom" : "right"}
align={isMobile ? "end" : "start"}
side={isMobile ? 'bottom' : 'right'}
align={isMobile ? 'end' : 'start'}
>
<DropdownMenuItem>
<Folder className="text-muted-foreground" />
@ -85,5 +79,5 @@ export function NavProjects({
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroup>
)
);
}

View file

@ -1,19 +1,10 @@
"use client"
'use client';
import {
BadgeCheck,
Bell,
ChevronsUpDown,
CreditCard,
LogOut,
Sparkles,
} from "lucide-react"
import { ChevronsUpDown, LogOut, Moon, Sparkles, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';
import { useCallback, useState } from 'react';
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar"
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import {
DropdownMenu,
DropdownMenuContent,
@ -22,93 +13,131 @@ import {
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
} from '@/components/ui/dropdown-menu';
import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar"
} from '@/components/ui/sidebar';
import { useGUsuarioLogoutHook } from '@/packages/administrativo/hooks/GUsuario/useGUsuarioLogoutHook';
import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog';
import GUsuarioAuthenticatedInterface from '@/shared/interfaces/GUsuarioAuthenticatedInterface';
export function NavUser({
user,
}: {
user: {
name: string
email: string
avatar: string
export function NavUser({ user }: { user: GUsuarioAuthenticatedInterface }) {
// Hook para encerrar sessão
const { logoutUsuario } = useGUsuarioLogoutHook();
// Controle de exibição do formulário de confirmação
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
const { isMobile } = useSidebar();
// Tema (claro/escuro) - next-themes
const { theme, setTheme } = useTheme();
const isDark = theme === 'dark';
const handleConfirmOpen = useCallback(() => {
setIsConfirmOpen(true);
}, []);
const handleLogoutConfirm = useCallback(() => {
logoutUsuario();
}, [logoutUsuario]);
const handleLogoutCancel = useCallback(() => {
setIsConfirmOpen(false);
}, []);
const handleToggleTheme = useCallback(() => {
setTheme(isDark ? 'light' : 'dark');
}, [isDark, setTheme]);
if (!user) {
return 'Carregando...';
}
}) {
const { isMobile } = useSidebar()
return (
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{user.name}</span>
<span className="truncate text-xs">{user.email}</span>
</div>
<ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
side={isMobile ? "bottom" : "right"}
align="end"
sideOffset={4}
>
<DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground cursor-pointer"
>
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
<AvatarImage src={user.sigla} alt={user.nome} />
<AvatarFallback className="rounded-lg">{user.sigla}</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{user.name}</span>
<span className="truncate font-medium">{user.nome}</span>
<span className="truncate text-xs">{user.email}</span>
</div>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<Sparkles />
Upgrade to Pro
<ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
side={isMobile ? 'bottom' : 'right'}
align="end"
sideOffset={4}
>
<DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.sigla} alt={user.nome} />
<AvatarFallback className="rounded-lg">{user.sigla}</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{user.nome}</span>
<span className="truncate text-xs">{user.email}</span>
</div>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
{/* Alternância de tema */}
<DropdownMenuItem className="cursor-pointer" onClick={handleToggleTheme}>
{isDark ? <Sun className="mr-2 h-4 w-4" /> : <Moon className="mr-2 h-4 w-4" />}
{isDark ? 'Modo claro' : 'Modo escuro'}
</DropdownMenuItem>
<DropdownMenuItem className="cursor-pointer">
<Sparkles className="mr-2 h-4 w-4" />
Configurações
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem className="cursor-pointer" onClick={handleConfirmOpen}>
<LogOut className="mr-2 h-4 w-4" />
Log out
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<BadgeCheck />
Account
</DropdownMenuItem>
<DropdownMenuItem>
<CreditCard />
Billing
</DropdownMenuItem>
<DropdownMenuItem>
<Bell />
Notifications
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
<LogOut />
Log out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
)
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
{/* Modal de confirmação */}
<ConfirmDialog
isOpen={isConfirmOpen}
title="Log-out"
description="Atenção"
message="Deseja realmente encerrar a sessão? Dados não salvos serão perdidos."
confirmText="Sim, sair"
cancelText="Cancelar"
onConfirm={handleLogoutConfirm}
onCancel={handleLogoutCancel}
/>
</>
);
}

Some files were not shown because too many files have changed in this diff Show more