From 175dff5dedfe1b0fb5a0dbc49fe57fc11329b0d3 Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Tue, 30 Sep 2025 08:20:50 -0300 Subject: [PATCH] =?UTF-8?q?[MVPTN-92]=20feat(SelectUF):=20Criado=20carrega?= =?UTF-8?q?mento=20de=20estados=20de=20forma=20din=C3=A2mica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components/g_cidade/GCidadeForm.tsx | 59 ++++++++++++++++--- .../_data/GCidade/GCidadeSaveData.ts | 39 ++++++++---- .../cadastros/_data/GUf/GUfIndexData.ts | 19 ++++++ .../_hooks/g_cidade/useGCidadeSaveHook.ts | 2 + .../cadastros/_hooks/g_uf/useGUfReadHook.ts | 30 ++++++++++ .../cadastros/_interfaces/GUfInterface.ts | 8 +++ .../cadastros/_schemas/GCidadeSchema.ts | 1 - .../_services/g_cidade/GCidadeSaveService.ts | 10 +++- .../_services/g_uf/GUfIndexService.ts | 9 +++ src/app/_response/ResponseContext.tsx | 1 + src/app/_response/response.tsx | 2 + 11 files changed, 157 insertions(+), 23 deletions(-) create mode 100644 src/app/(protected)/(cadastros)/cadastros/_data/GUf/GUfIndexData.ts create mode 100644 src/app/(protected)/(cadastros)/cadastros/_hooks/g_uf/useGUfReadHook.ts create mode 100644 src/app/(protected)/(cadastros)/cadastros/_interfaces/GUfInterface.ts create mode 100644 src/app/(protected)/(cadastros)/cadastros/_services/g_uf/GUfIndexService.ts diff --git a/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeForm.tsx b/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeForm.tsx index ebb0778..856903e 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeForm.tsx +++ b/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeForm.tsx @@ -27,6 +27,16 @@ import { Input } from "@/components/ui/input"; import { GCidadeSchema } from "../../_schemas/GCidadeSchema"; import { useEffect } from "react"; +// Hook responsável em trazer todos os estados brasileiros +import { useGUfReadHook } from "../../_hooks/g_uf/useGUfReadHook"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from "@/components/ui/select"; + // Define o tipo do formulário com base no schema Zod type FormValues = z.infer; @@ -41,6 +51,9 @@ interface Props { // Componente principal do formulário export default function GCidadeForm({ isOpen, data, onClose, onSave }: Props) { + // + const { gUf, fetchGUf } = useGUfReadHook(); + // Inicializa o react-hook-form integrado ao Zod para validação const form = useForm({ resolver: zodResolver(GCidadeSchema), @@ -55,7 +68,19 @@ export default function GCidadeForm({ isOpen, data, onClose, onSave }: Props) { // Quando recebe dados para edição, atualiza os valores do formulário useEffect(() => { - if (data) form.reset(data); + + // Se existir dados, reseta o formulário com os dados informados + if (data) form.reset(data); + + const loadData = async () => { + + // Aguarda a busca terminar + await fetchGUf(); + }; + + // Dispara a função + loadData(); + }, [data, form]); return ( @@ -107,20 +132,38 @@ export default function GCidadeForm({ isOpen, data, onClose, onSave }: Props) { )} /> - {/* Campo: UF (Estado) */} + {/* Tipo */} ( - Estado - - - + + UF + + )} - /> + /> {/* Rodapé do diálogo com botões */} diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeSaveData.ts b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeSaveData.ts index 9bd2a52..8ab0c4f 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeSaveData.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeSaveData.ts @@ -1,15 +1,32 @@ -import API from "@/services/api/Api"; // Importa o serviço de API (ainda não utilizado aqui) -import { Methods } from "@/services/api/enums/ApiMethodEnum"; // Importa enum de métodos HTTP (também não usado neste trecho) +// Importa o serviço de API que será utilizado para realizar requisições HTTP +import API from "@/services/api/Api"; -// Função assíncrona responsável por salvar dados de cidades -export default async function GCidadeSaveData() { +// Importa o enum que contém os métodos HTTP disponíveis (GET, POST, PUT, DELETE) +import { Methods } from "@/services/api/enums/ApiMethodEnum"; - // Log para indicar que a função foi chamada - console.log("chegou"); +// Importa a interface tipada que define a estrutura dos dados de uma cidade +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; - // Retorna uma Promise resolvida simulando resposta da API - return Promise.resolve({ - status: 200, // Código de status fictício - message: "Dados salvos" // Mensagem de sucesso - }); +// Importa função que encapsula chamadas assíncronas e trata erros automaticamente +import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler"; + + +// Função assíncrona que implementa a lógica de salvar (criar/atualizar) uma cidade +async function executeGcidadeSaveData(data: GCidadeInterface) { + + // Verifica se existe ID da cidade para decidir se é atualização (PUT) ou criação (POST) + const isUpdate = Boolean(data.cidade_id); + + // Instancia o cliente da API para enviar a requisição + const api = new API(); + + // Executa a requisição para a API com o método apropriado e envia os dados no corpo + return await api.send({ + method: isUpdate ? Methods.PUT : Methods.POST, // PUT se atualizar, POST se criar + endpoint: `administrativo/g_cidade/${data.cidade_id || ''}`, // endpoint dinâmico + body: data // payload enviado para a API + }); } + +// Exporta a função de salvar cidade já encapsulada com tratamento de erros +export const GCidadeSaveData = withClientErrorHandler(executeGcidadeSaveData); diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/GUf/GUfIndexData.ts b/src/app/(protected)/(cadastros)/cadastros/_data/GUf/GUfIndexData.ts new file mode 100644 index 0000000..ffca36d --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_data/GUf/GUfIndexData.ts @@ -0,0 +1,19 @@ +// Importa a classe API responsável por centralizar chamadas HTTP +import API from "@/services/api/Api"; + +// Importa o enum de métodos HTTP (GET, POST, PUT, DELETE, etc.) +import { Methods } from "@/services/api/enums/ApiMethodEnum"; + +// Exporta por padrão a função assíncrona GUfIndexData +export default async function GUfIndexData() { + + // Cria uma instância da classe API para executar a requisição + const api = new API(); + + // Executa a chamada GET para o endpoint "administrativo/g_uf/" e retorna a resposta + return await api.send({ + method: Methods.GET, // Define que o método HTTP é GET + endpoint: `administrativo/g_uf/` // Define o endpoint a ser acessado + }); + +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeSaveHook.ts b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeSaveHook.ts index 0a0c1c4..63c057e 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeSaveHook.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeSaveHook.ts @@ -18,6 +18,8 @@ export const useGCidadeSaveHook = () => { // Guardar os dados localizados setGCidade(response.data); + console.log(response) + // Manda a resposta para o verificador de resposta setResponse(response); diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_uf/useGUfReadHook.ts b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_uf/useGUfReadHook.ts new file mode 100644 index 0000000..9097e3c --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_uf/useGUfReadHook.ts @@ -0,0 +1,30 @@ +'use client' + +import { useResponse } from "@/app/_response/ResponseContext" +import { use, useState } from "react"; +import GUfInterface from "../../_interfaces/GUfInterface"; +import GUfIndexService from "../../_services/g_uf/GUfIndexService"; + +export const useGUfReadHook = () => { + + const { setResponse } = useResponse(); + + // Controle dos dados obtidos via API + const [gUf, setGUf] = useState([]); + + const fetchGUf = async () => { + + // Realiza a requisição para a api + const response = await GUfIndexService(); + + // Armazena os dados da resposta + setGUf(response.data); + + // Envia os dados da resposta para ser tratado + setResponse(response); + + } + + return { gUf, fetchGUf } + +} \ No newline at end of file diff --git a/src/app/(protected)/(cadastros)/cadastros/_interfaces/GUfInterface.ts b/src/app/(protected)/(cadastros)/cadastros/_interfaces/GUfInterface.ts new file mode 100644 index 0000000..6ed585c --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_interfaces/GUfInterface.ts @@ -0,0 +1,8 @@ +export default interface GUfInterface { + + g_uf_id?: number, + sigla: string, + nome: string, + codigo_uf_ibge?: string, + +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_schemas/GCidadeSchema.ts b/src/app/(protected)/(cadastros)/cadastros/_schemas/GCidadeSchema.ts index 3aaa189..2089394 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_schemas/GCidadeSchema.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_schemas/GCidadeSchema.ts @@ -7,5 +7,4 @@ export const GCidadeSchema = z.object({ cidade_nome: z.string().min(1, "O nome da cidade é obrigatório"), codigo_ibge: z.string().optional(), codigo_gyn: z.string().optional() - }) \ No newline at end of file diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeSaveService.ts b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeSaveService.ts index d764292..331719b 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeSaveService.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeSaveService.ts @@ -1,12 +1,16 @@ -import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler"; // Função que envolve qualquer ação assíncrona para capturar e tratar erros do cliente -import GCidadeSaveData from "../../_data/GCidade/GCidadeSaveData"; +import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler"; + // Função que salva os dados da cidade via API (ou mock) -import GCidadeInterface from "../../_interfaces/GCidadeInterface"; +import { GCidadeSaveData } from "../../_data/GCidade/GCidadeSaveData"; + // Interface tipada da cidade +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; + // Função assíncrona que executa o salvamento de uma cidade async function executeGCidadeSaveService(data: GCidadeInterface) { + // Chama a função que salva os dados da cidade const response = await GCidadeSaveData(data); diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/g_uf/GUfIndexService.ts b/src/app/(protected)/(cadastros)/cadastros/_services/g_uf/GUfIndexService.ts new file mode 100644 index 0000000..6703ab7 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_services/g_uf/GUfIndexService.ts @@ -0,0 +1,9 @@ +import GUfIndexData from "../../_data/GUf/GUfIndexData"; + +export default async function GUfIndexService() { + + const response = await GUfIndexData(); + + return response; + +} \ No newline at end of file diff --git a/src/app/_response/ResponseContext.tsx b/src/app/_response/ResponseContext.tsx index b387176..75ec27a 100644 --- a/src/app/_response/ResponseContext.tsx +++ b/src/app/_response/ResponseContext.tsx @@ -32,6 +32,7 @@ export const ResponseProvider: React.FC<{ children: ReactNode }> = ({ children } }; export const useResponse = () => { + const context = useContext(ResponseContext); if (!context) throw new Error('useResponse must be used within ResponseProvider'); return context; diff --git a/src/app/_response/response.tsx b/src/app/_response/response.tsx index fad1bec..c6a04dc 100644 --- a/src/app/_response/response.tsx +++ b/src/app/_response/response.tsx @@ -17,6 +17,8 @@ export default function Response() { clearResponse } = useResponse(); + console.log(response) + useEffect(() => { switch (Number(response?.status)) {