diff --git a/package-lock.json b/package-lock.json index 2cc4f8d..4c0e5d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2255,12 +2255,6 @@ "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, "node_modules/js-cookie": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", @@ -2270,6 +2264,12 @@ "node": ">=14" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", diff --git a/src/app/(protected)/(cadastros)/cadastros/(g_cidade)/cidades/page.tsx b/src/app/(protected)/(cadastros)/cadastros/(g_cidade)/cidades/page.tsx new file mode 100644 index 0000000..92a0ba3 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/(g_cidade)/cidades/page.tsx @@ -0,0 +1,164 @@ +'use client'; + +import { useEffect, useState, useCallback } from "react"; +import { Card, CardContent } from "@/components/ui/card"; + +import Loading from "@/app/_components/loading/loading"; +import GCidadeTable from "../../_components/g_cidade/GCidadeTable"; +import GCidadeForm from "../../_components/g_cidade/GCidadeForm"; + +import { useGCidadeReadHook } from "../../_hooks/g_cidade/useGCidadeReadHook"; +import { useGCidadeSaveHook } from "../../_hooks/g_cidade/useGCidadeSaveHook"; +import { useGCidadeRemoveHook } from "../../_hooks/g_cidade/useGCidadeRemoveHook"; + +import ConfirmDialog from "@/app/_components/confirm_dialog/ConfirmDialog"; +import { useConfirmDialog } from "@/app/_components/confirm_dialog/useConfirmDialog"; + +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; +import Header from "@/app/_components/structure/Header"; + +export default function GCidadePage() { + + // Hooks para leitura e salvamento + const { gCidade, fetchGCidade } = useGCidadeReadHook(); + const { saveGCidade } = useGCidadeSaveHook(); + const { removeGCidade } = useGCidadeRemoveHook(); + + // Estados + const [selectedCidade, setSelectedCidade] = useState(null); + const [isFormOpen, setIsFormOpen] = useState(false); + + // Estado para saber qual item será deletado + const [itemToDelete, setItemToDelete] = useState(null); + + /** + * Hook do modal de confirmação + */ + const { + isOpen: isConfirmOpen, + openDialog: openConfirmDialog, + handleConfirm, + handleCancel, + } = useConfirmDialog(); + + /** + * Abre o formulário no modo de edição ou criação + */ + const handleOpenForm = useCallback((data: GCidadeInterface | null) => { + setSelectedCidade(data); + setIsFormOpen(true); + }, []); + + /** + * Fecha o formulário e limpa o andamento selecionado + */ + const handleCloseForm = useCallback(() => { + setSelectedCidade(null); + setIsFormOpen(false); + }, []); + + /** + * Salva os dados do formulário + */ + const handleSave = useCallback(async (formData: GCidadeInterface) => { + + // Aguarda salvar o registro + await saveGCidade(formData); + + // Atualiza a lista de dados + fetchGCidade(); + + }, [saveGCidade, fetchGCidade]); + + /** + * Quando o usuário clica em "remover" na tabela + */ + const handleConfirmDelete = useCallback((item: GCidadeInterface) => { + + // Define o item atual para remoção + setItemToDelete(item); + + // Abre o modal de confirmação + openConfirmDialog(); + + }, [openConfirmDialog]); + + /** + * Executa a exclusão de fato quando o usuário confirma + */ + const handleDelete = useCallback(async () => { + + // Protege contra null + if (!itemToDelete) return; + + // Executa o Hook de remoção + await removeGCidade(itemToDelete); + + // Atualiza a lista + await fetchGCidade(); + + // Limpa o item selecionado + setItemToDelete(null); + + // Fecha o modal + handleCancel(); + + }, [itemToDelete, fetchGCidade, handleCancel]); + + /** + * Busca inicial dos dados + */ + useEffect(() => { + fetchGCidade(); + }, []); + + /** + * Tela de loading enquanto carrega os dados + */ + if (!gCidade) { + return ; + } + + return ( +
+ {/* Cabeçalho */} +
{ handleOpenForm(null) }} + /> + + {/* Tabela de andamentos */} + + + + + + + {/* Modal de confirmação */} + + + {/* Formulário de criação/edição */} + +
+ ); 4 +} \ No newline at end of file diff --git a/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeForm.tsx b/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeForm.tsx new file mode 100644 index 0000000..ebb0778 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeForm.tsx @@ -0,0 +1,152 @@ +'use client'; + +import z from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; + +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle +} from "@/components/ui/dialog"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; + +import { GCidadeSchema } from "../../_schemas/GCidadeSchema"; +import { useEffect } from "react"; + +// Define o tipo do formulário com base no schema Zod +type FormValues = z.infer; + +// Propriedades esperadas pelo componente +interface Props { + isOpen: boolean; // controla se o Dialog está aberto + data: FormValues | null; // dados para edição (se existirem) + onClose: (item: null, isFormStatus: boolean) => void; // callback para fechar + onSave: (data: FormValues) => void; // callback para salvar +} + +// Componente principal do formulário +export default function GCidadeForm({ isOpen, data, onClose, onSave }: Props) { + + // Inicializa o react-hook-form integrado ao Zod para validação + const form = useForm({ + resolver: zodResolver(GCidadeSchema), + defaultValues: { + cidade_id: 0, + uf: "", + cidade_nome: "", + codigo_ibge: "", + codigo_gyn: "" + }, + }); + + // Quando recebe dados para edição, atualiza os valores do formulário + useEffect(() => { + if (data) form.reset(data); + }, [data, form]); + + return ( + { + if (!open) onClose(null, false); + }} + > + + {/* Cabeçalho do diálogo */} + + Cidades + Controle de Cidades + + + {/* Estrutura do formulário */} +
+ + + {/* Campo: Nome da cidade */} + ( + + Descrição + + + + + + )} + /> + + {/* Campo: Código IBGE */} + ( + + Código IBGE + + + + + + )} + /> + + {/* Campo: UF (Estado) */} + ( + + Estado + + + + + + )} + /> + + {/* Rodapé do diálogo com botões */} + + {/* Botão de cancelar */} + + + + + {/* Botão de salvar */} + + + + {/* Campo oculto: ID da cidade */} + + + +
+
+ ); +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeTable.tsx b/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeTable.tsx new file mode 100644 index 0000000..65f34b5 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_components/g_cidade/GCidadeTable.tsx @@ -0,0 +1,150 @@ +'use client'; + +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger +} from "@/components/ui/dropdown-menu"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow +} from "@/components/ui/table"; + +import { EllipsisIcon, PencilIcon, Trash2Icon } from "lucide-react"; +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; + +// Tipagem das props do componente da tabela +interface GCidadeTableProps { + data: GCidadeInterface[]; // lista de cidades + onEdit: (item: GCidadeInterface, isEditingFormStatus: boolean) => void; // callback para edição + onDelete: (item: GCidadeInterface, isEditingFormStatus: boolean) => void; // callback para exclusão +} + +/** + * Renderiza o "badge" de status da cidade (Ativo/Inativo) + */ +function StatusBadge({ situacao }: { situacao: string }) { + const isActive = situacao === "A"; // define se está ativo ou inativo + + // Estilos base + const baseClasses = + "text-xs font-medium px-2.5 py-0.5 rounded-sm me-2"; + + // Estilo para ativo + const activeClasses = + "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300"; + + // Estilo para inativo + const inactiveClasses = + "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300"; + + // Retorna o badge com classe condicional + return ( + + {isActive ? "Ativo" : "Inativo"} + + ); +} + +/** + * Componente principal da tabela de cidades + */ +export default function GCidadeTable({ + data, + onEdit, + onDelete +}: GCidadeTableProps) { + return ( + + {/* Cabeçalho da tabela */} + + + # + IBGE + UF + Descrição + + + + + {/* Corpo da tabela */} + + {data.map((item) => ( + + {/* ID da cidade */} + + {item.cidade_id} + + + {/* Código IBGE */} + + {item.codigo_ibge} + + + {/* UF */} + + {item.uf} + + + {/* Nome/descrição da cidade */} + + {item.cidade_nome} + + + {/* Ações (menu dropdown) */} + + + {/* Botão de disparo do menu */} + + + + + {/* Conteúdo do menu */} + + + {/* Opção editar */} + onEdit(item, true)} + > + + Editar + + + + + {/* Opção remover */} + onDelete(item, true)} + > + + Remover + + + + + + + ))} + +
+ ); +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeIndexData.ts b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeIndexData.ts new file mode 100644 index 0000000..d22d3c3 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeIndexData.ts @@ -0,0 +1,86 @@ +import API from "@/services/api/Api"; +import { Methods } from "@/services/api/enums/ApiMethodEnum"; + +export default async function GCidadeIndexData() { + + return Promise.resolve({ + status: 200, + message: "Dados localizados", + data: [ + { + "cidade_id": 1, + "uf": "AC", + "cidade_nome": "Acrelândia", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 2, + "uf": "AC", + "cidade_nome": "Assis Brasil", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 3, + "uf": "AC", + "cidade_nome": "Brasiléia", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 4, + "uf": "AC", + "cidade_nome": "Bujari", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 5, + "uf": "AC", + "cidade_nome": "Capixaba", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 6, + "uf": "AC", + "cidade_nome": "Cruzeiro do Sul", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 7, + "uf": "AC", + "cidade_nome": "Epitaciolândia", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 8, + "uf": "AC", + "cidade_nome": "Feijó", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 9, + "uf": "AC", + "cidade_nome": "Jordão", + "codigo_ibge": null, + "codigo_gyn": null + }, + { + "cidade_id": 10, + "uf": "AC", + "cidade_nome": "Mâncio Lima", + "codigo_ibge": null, + "codigo_gyn": null + } + ] + + }); + +} + + diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeRemoveData.ts b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeRemoveData.ts new file mode 100644 index 0000000..abcf2aa --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeRemoveData.ts @@ -0,0 +1,14 @@ +import API from "@/services/api/Api"; +import { Methods } from "@/services/api/enums/ApiMethodEnum"; + +export default async function GCidadeRemoveData() { + + return Promise.resolve({ + status: 200, + message: "Dados removidos", + data: null + }); + +} + + diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeSaveData.ts b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeSaveData.ts new file mode 100644 index 0000000..9bd2a52 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_data/GCidade/GCidadeSaveData.ts @@ -0,0 +1,15 @@ +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) + +// Função assíncrona responsável por salvar dados de cidades +export default async function GCidadeSaveData() { + + // Log para indicar que a função foi chamada + console.log("chegou"); + + // 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 + }); +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeReadHook.ts b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeReadHook.ts new file mode 100644 index 0000000..03eb83a --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeReadHook.ts @@ -0,0 +1,32 @@ +import { useResponse } from "@/app/_response/ResponseContext"; // Contexto global para gerenciar respostas da API +import { useState } from "react"; +import { GCidadeIndexService } from "../../_services/g_cidade/GCidadeIndexService"; // Serviço que busca a lista de cidades +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; // Interface tipada da cidade + +// Hook customizado para leitura de dados de cidades +export const useGCidadeReadHook = () => { + + // Hook do contexto de resposta para feedback global (alertas, mensagens etc.) + const { setResponse } = useResponse(); + + // Estado local que armazena a lista de cidades retornada da API + const [gCidade, setGCidade] = useState([]); + + // Função assíncrona que busca os dados de cidades + const fetchGCidade = async () => { + // Chama o serviço responsável por consultar a API + const response = await GCidadeIndexService(); + + // Atualiza o estado local com os dados retornados + setGCidade(response.data); + + // Atualiza o contexto global de resposta + setResponse(response); + + // Retorna a resposta para quem chamou o hook + return response; + } + + // Retorna os dados e a função de busca para serem usados no componente + return { gCidade, fetchGCidade } +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeRemoveHook.ts b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeRemoveHook.ts new file mode 100644 index 0000000..c63f53b --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeRemoveHook.ts @@ -0,0 +1,22 @@ +import { useResponse } from "@/app/_response/ResponseContext"; // Contexto global para gerenciar respostas da API +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; // Interface tipada da cidade +import GCidadeRemoveData from "../../_data/GCidade/GCidadeRemoveData"; // Função que remove a cidade via API + +// Hook customizado para remoção de cidades +export const useGCidadeRemoveHook = () => { + + // Hook do contexto de resposta para feedback global (alertas, mensagens etc.) + const { setResponse } = useResponse(); + + // Função assíncrona que remove uma cidade + const removeGCidade = async (data: GCidadeInterface) => { + // Chama a função de remoção passando os dados da cidade + const response = await GCidadeRemoveData(data); + + // Atualiza o contexto global com a resposta da API + setResponse(response); + } + + // Retorna a função de remoção para ser usada no componente + return { removeGCidade } +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeSaveHook.ts b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeSaveHook.ts new file mode 100644 index 0000000..0a0c1c4 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_cidade/useGCidadeSaveHook.ts @@ -0,0 +1,34 @@ +import { useState } from "react"; +import { useResponse } from "@/app/_response/ResponseContext" +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; +import { GCidadeSaveService } from "../../_services/g_cidade/GCidadeSaveService"; + +export const useGCidadeSaveHook = () => { + + const { setResponse } = useResponse(); + const [gCidade, setGCidade] = useState(null); + + // controla se o formulário está aberto ou fechado + const [isOpen, setIsOpen] = useState(false); + + const saveGCidade = async (data: GCidadeInterface) => { + + const response = await GCidadeSaveService(data); + + // Guardar os dados localizados + setGCidade(response.data); + + // Manda a resposta para o verificador de resposta + setResponse(response); + + // Fecha o formulário automaticamente após salvar + setIsOpen(false); + + // Retorna os dados imediatamente + return response; + + } + + return { gCidade, saveGCidade } + +} \ No newline at end of file diff --git a/src/app/(protected)/(cadastros)/cadastros/_interfaces/GCidadeInterface.ts b/src/app/(protected)/(cadastros)/cadastros/_interfaces/GCidadeInterface.ts new file mode 100644 index 0000000..537f03a --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_interfaces/GCidadeInterface.ts @@ -0,0 +1,9 @@ +export default interface GCidadeInterface { + + cidade_id?: number, + uf: string, + cidade_nome: string, + codigo_ibge?: string, + codigo_gyn?: string + +} diff --git a/src/app/(protected)/(cadastros)/cadastros/_schemas/GCidadeSchema.ts b/src/app/(protected)/(cadastros)/cadastros/_schemas/GCidadeSchema.ts new file mode 100644 index 0000000..3aaa189 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_schemas/GCidadeSchema.ts @@ -0,0 +1,11 @@ +import z from "zod"; + +export const GCidadeSchema = z.object({ + + cidade_id: z.number().optional(), + uf: z.string().min(1, "A UF é obrigatória").max(2, "A UF deve ter no máximo 2 caracteres"), + 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/GCidadeIndexService.ts b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeIndexService.ts new file mode 100644 index 0000000..c42a22f --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeIndexService.ts @@ -0,0 +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 GCidadeIndexData from "../../_data/GCidade/GCidadeIndexData"; +// Função que retorna os dados da lista de cidades (chamada à API ou mock) + +// Função assíncrona que executa a chamada para buscar os dados de cidades +async function executeGCidadeIndexService() { + // Chama a função que retorna os dados da cidade + const response = await GCidadeIndexData(); + + // Retorna a resposta para o chamador + return response; +} + +// Exporta o serviço de índice de cidades já encapsulado com tratamento de erros +export const GCidadeIndexService = withClientErrorHandler(executeGCidadeIndexService); diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeRemoveService.ts b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeRemoveService.ts new file mode 100644 index 0000000..3a48ead --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeRemoveService.ts @@ -0,0 +1,18 @@ +import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler"; +// Função que envolve qualquer ação assíncrona para capturar e tratar erros do cliente +import GCidadeRemoveData from "../../_data/GCidade/GCidadeRemoveData"; +// Função que remove os dados da cidade via API +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; +// Interface tipada da cidade + +// Função assíncrona que executa a remoção de uma cidade +async function executeGCidadeRemoveService(data: GCidadeInterface) { + // Chama a função que remove os dados da cidade + const response = await GCidadeRemoveData(data); + + // Retorna a resposta da remoção + return response; +} + +// Exporta o serviço de remoção de cidade já encapsulado com tratamento de erros +export const GCidadeRemoveService = withClientErrorHandler(executeGCidadeRemoveService); diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeSaveService.ts b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeSaveService.ts new file mode 100644 index 0000000..d764292 --- /dev/null +++ b/src/app/(protected)/(cadastros)/cadastros/_services/g_cidade/GCidadeSaveService.ts @@ -0,0 +1,18 @@ +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"; +// Função que salva os dados da cidade via API (ou mock) +import GCidadeInterface from "../../_interfaces/GCidadeInterface"; +// Interface tipada da cidade + +// 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); + + // Retorna a resposta do salvamento + return response; +} + +// Exporta o serviço de salvamento de cidade já encapsulado com tratamento de erros +export const GCidadeSaveService = withClientErrorHandler(executeGCidadeSaveService); diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index aa0e027..a0f03f6 100644 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -121,8 +121,8 @@ const data = { url: "/cadastros/pessoas/complementos/", }, { - title: "Regimes/Bens", - url: "/cadastros/regime-bens/", + title: "Cidades", + url: "/cadastros/cidades/", }, { title: "Regimes/Comunhão",