[MVPTN-23] feat(CRUD): Adiciona CRUD para manipular o G_NATUREZA
This commit is contained in:
parent
d3f8bebe1d
commit
4559de0187
26 changed files with 1385 additions and 371 deletions
916
package-lock.json
generated
916
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -23,6 +23,7 @@
|
|||
"@radix-ui/react-select": "^2.2.6",
|
||||
"@radix-ui/react-separator": "^1.1.7",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@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",
|
||||
|
|
@ -68,6 +69,6 @@
|
|||
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||
"tailwindcss": "^4",
|
||||
"tw-animate-css": "^1.3.7",
|
||||
"typescript": "^5"
|
||||
"typescript": "5.9.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import GNaturezaIndex from "@/packages/administrativo/components/GNatureza/GNaturezaIndex";
|
||||
|
||||
export default function GNaturezaPage() {
|
||||
|
||||
return (
|
||||
<GNaturezaIndex
|
||||
sistema_id={2}
|
||||
/>
|
||||
);
|
||||
|
||||
}
|
||||
|
|
@ -125,6 +125,10 @@ const data = {
|
|||
title: 'Minuta',
|
||||
url: '/cadastros/minuta/',
|
||||
},
|
||||
{
|
||||
title: 'Minuta/Naturezas',
|
||||
url: '/administrativo/minutas/naturezas',
|
||||
},
|
||||
{
|
||||
title: "Censec/Tipo do Ato",
|
||||
url: "/cadastros/censec-tipoato"
|
||||
|
|
|
|||
31
src/components/ui/switch.tsx
Normal file
31
src/components/ui/switch.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SwitchPrimitive from "@radix-ui/react-switch"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Switch({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
||||
return (
|
||||
<SwitchPrimitive.Root
|
||||
data-slot="switch"
|
||||
className={cn(
|
||||
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<SwitchPrimitive.Thumb
|
||||
data-slot="switch-thumb"
|
||||
className={cn(
|
||||
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitive.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export { Switch }
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
EllipsisIcon,
|
||||
PencilIcon,
|
||||
Trash2Icon,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { SortableHeader } from "@/shared/components/dataTable/SortableHeader";
|
||||
import GetCapitalize from "@/shared/actions/text/GetCapitalize";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
|
||||
export default function GNaturezaColumns(
|
||||
onEdit: (item: GNaturezaInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: GNaturezaInterface, isEditingFormStatus: boolean) => void
|
||||
): ColumnDef<GNaturezaInterface>[] {
|
||||
return [
|
||||
// ID
|
||||
{
|
||||
accessorKey: "natureza_id",
|
||||
header: ({ column }) => SortableHeader("ID", column),
|
||||
cell: ({ row }) => Number(row.getValue("natureza_id")),
|
||||
enableSorting: true,
|
||||
},
|
||||
|
||||
// Descrição
|
||||
{
|
||||
accessorKey: "descricao",
|
||||
header: ({ column }) => SortableHeader("Descrição", column),
|
||||
cell: ({ row }) =>
|
||||
GetCapitalize(String(row.getValue("descricao") || "")),
|
||||
},
|
||||
|
||||
// Situação
|
||||
{
|
||||
accessorKey: "situacao",
|
||||
header: ({ column }) => SortableHeader("Situação", column),
|
||||
cell: ({ row }) => {
|
||||
const value = String(row.getValue("situacao") || "").toUpperCase();
|
||||
if (value === "A") return "Ativo";
|
||||
if (value === "I") return "Inativo";
|
||||
return "-";
|
||||
},
|
||||
},
|
||||
|
||||
// Sistema ID
|
||||
{
|
||||
accessorKey: "sistema_id",
|
||||
header: ({ column }) => SortableHeader("Sistema ID", column),
|
||||
cell: ({ row }) => {
|
||||
const value = row.getValue("sistema_id");
|
||||
return value ? Number(value) : "-";
|
||||
},
|
||||
},
|
||||
|
||||
// Pedir Número Imóvel
|
||||
{
|
||||
accessorKey: "pedir_numero_imovel",
|
||||
header: ({ column }) => SortableHeader("Pedir Nº Imóvel", column),
|
||||
cell: ({ row }) => {
|
||||
const value = String(row.getValue("pedir_numero_imovel") || "").toUpperCase();
|
||||
return value === "S" ? "Sim" : "Não";
|
||||
},
|
||||
},
|
||||
|
||||
// Controle Frente/Verso
|
||||
{
|
||||
accessorKey: "controle_frenteverso",
|
||||
header: ({ column }) => SortableHeader("Controle Frente/Verso", column),
|
||||
cell: ({ row }) => {
|
||||
const value = String(row.getValue("controle_frenteverso") || "").toUpperCase();
|
||||
return value === "S" ? "Sim" : "Não";
|
||||
},
|
||||
},
|
||||
|
||||
// Ações
|
||||
{
|
||||
id: "actions",
|
||||
header: "Ações",
|
||||
cell: ({ row }) => {
|
||||
const natureza = row.original;
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<EllipsisIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent side="left" align="start">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onSelect={() => onEdit(natureza, true)}>
|
||||
<PencilIcon className="mr-2 h-4 w-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuItem
|
||||
className="text-red-600"
|
||||
onSelect={() => onDelete(natureza, true)}
|
||||
>
|
||||
<Trash2Icon className="mr-2 h-4 w-4" />
|
||||
Remover
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
'use client';
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
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 { Switch } from "@/components/ui/switch";
|
||||
|
||||
import LoadingButton from "@/shared/components/loadingButton/LoadingButton";
|
||||
import { ResetFormIfData } from "@/shared/actions/form/ResetFormIfData";
|
||||
import { useGNaturezaFormHook } from "../../hooks/GNatureza/useGNaturezaFormHook";
|
||||
import { GNaturezaFormInterface } from "../../interfaces/GNatureza/GNaturezaFormInterface";
|
||||
import SituacoesSelect from "@/shared/components/situacoes/SituacoesSelect";
|
||||
|
||||
/**
|
||||
* Formulário de cadastro/edição de Natureza
|
||||
* Baseado nos campos da tabela G_NATUREZA
|
||||
*/
|
||||
export default function GNaturezaForm({
|
||||
isOpen,
|
||||
data,
|
||||
onClose,
|
||||
onSave,
|
||||
buttonIsLoading,
|
||||
}: GNaturezaFormInterface) {
|
||||
const form = useGNaturezaFormHook({});
|
||||
|
||||
// Atualiza o formulário quando recebe dados para edição
|
||||
useEffect(() => {
|
||||
ResetFormIfData(form, data);
|
||||
}, [data, form]);
|
||||
|
||||
function onError(error: any) {
|
||||
console.log("Erro no formulário:", error);
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) onClose(null, false);
|
||||
}}
|
||||
>
|
||||
<DialogContent className="w-full max-w-full p-6 sm:max-w-3xl md:max-w-2xl lg:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-lg sm:text-xl">
|
||||
Natureza de Minutas
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-sm text-muted-foreground">
|
||||
Natureza de MInutas
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{/* Formulário principal */}
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSave, onError)}
|
||||
className="space-y-6"
|
||||
>
|
||||
{/* GRID MOBILE FIRST */}
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
{/* DESCRIÇÃO */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="descricao"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Descrição</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
placeholder="Digite a descrição da natureza"
|
||||
maxLength={60}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* SITUAÇÃO */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="situacao"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Situação</FormLabel>
|
||||
<SituacoesSelect field={field} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* PEDIR_NUMERO_IMOVEL */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-6">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="pedir_numero_imovel"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col space-y-1">
|
||||
<FormLabel>Pedir Nº do Imóvel</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value === 'S'}
|
||||
onCheckedChange={(checked: boolean) =>
|
||||
field.onChange(checked ? 'S' : 'N')
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* CONTROLE_FRENTEVERSO */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-6">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="controle_frenteverso"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col space-y-1">
|
||||
<FormLabel>Controle Frente/Verso</FormLabel>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value === 'S'}
|
||||
onCheckedChange={(checked: boolean) =>
|
||||
field.onChange(checked ? 'S' : 'N')
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* Rodapé */}
|
||||
<DialogFooter className="flex flex-col sm:flex-row gap-2 justify-end mt-6">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button">
|
||||
Cancelar
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<LoadingButton
|
||||
text="Salvar"
|
||||
textLoading="Salvando..."
|
||||
type="submit"
|
||||
loading={buttonIsLoading}
|
||||
/>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
|
||||
import Loading from '@/shared/components/loading/loading';
|
||||
|
||||
import { useGNaturezaIndexHook } from '@/packages/administrativo/hooks/GNatureza/useGNaturezaIndexHook';
|
||||
import { useGNaturezaSaveHook } from '@/packages/administrativo/hooks/GNatureza/useGNaturezaSaveHook';
|
||||
import { useGNaturezaDeleteHook } from '@/packages/administrativo/hooks/GNatureza/useGNaturezaDeleteHook';
|
||||
|
||||
import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog';
|
||||
import { useConfirmDialog } from '@/shared/components/confirmDialog/useConfirmDialog';
|
||||
|
||||
import GNaturezaInterface from '@/packages/administrativo/interfaces/GNatureza/GNaturezaInterface';
|
||||
import Header from '@/shared/components/structure/Header';
|
||||
import GNaturezaTable from './GNaturezaTable';
|
||||
import GNaturezaForm from './GNaturezaForm';
|
||||
import { GNaturezaIndexInterface } from '../../interfaces/GNatureza/GNaturezaIndexInterface';
|
||||
|
||||
export default function GNaturezaIndex({ sistema_id }: GNaturezaIndexInterface) {
|
||||
|
||||
const GNaturezaIndexParams: GNaturezaIndexInterface = {
|
||||
sistema_id: sistema_id
|
||||
}
|
||||
|
||||
// Controle de estado do botão
|
||||
const [buttonIsLoading, setButtonIsLoading] = useState(false);
|
||||
|
||||
// Hooks para leitura e salvamento
|
||||
const { gNatureza, indexGNatureza } = useGNaturezaIndexHook();
|
||||
const { saveGNatureza } = useGNaturezaSaveHook();
|
||||
const { deleteGNatureza } = useGNaturezaDeleteHook();
|
||||
|
||||
// Estados
|
||||
const [selectedData, setSelectedData] = useState<GNaturezaInterface | null>(null);
|
||||
const [isFormOpen, setIsFormOpen] = useState(false);
|
||||
|
||||
// Estado para saber qual item será deletado
|
||||
const [itemToDelete, setItemToDelete] = useState<GNaturezaInterface | null>(null);
|
||||
|
||||
/**
|
||||
* Hook do modal de confirmação
|
||||
*/
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
openDialog: openConfirmDialog,
|
||||
handleCancel,
|
||||
} = useConfirmDialog();
|
||||
|
||||
/**
|
||||
* Abre o formulário no modo de edição ou criação
|
||||
*/
|
||||
const handleOpenForm = useCallback((data: GNaturezaInterface | null) => {
|
||||
// Se não houver dados (criação), cria um objeto inicial com pessoa_tipo
|
||||
const initialData: GNaturezaInterface = data ?? { sistema_id: GNaturezaIndexParams.sistema_id } as GNaturezaInterface;
|
||||
setSelectedData(initialData);
|
||||
setIsFormOpen(true);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Fecha o formulário e limpa o andamento selecionado
|
||||
*/
|
||||
const handleCloseForm = useCallback(() => {
|
||||
setSelectedData(null);
|
||||
setIsFormOpen(false);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Salva os dados do formulário
|
||||
*/
|
||||
const handleSave = useCallback(
|
||||
async (formData: GNaturezaInterface) => {
|
||||
// Coloca o botão em estado de loading
|
||||
setButtonIsLoading(true);
|
||||
|
||||
// Aguarda salvar o registro
|
||||
await saveGNatureza(formData);
|
||||
|
||||
// Remove o botão em estado de loading
|
||||
setButtonIsLoading(false);
|
||||
|
||||
// Atualiza a lista de dados
|
||||
indexGNatureza(GNaturezaIndexParams);
|
||||
},
|
||||
[saveGNatureza, indexGNatureza, handleCloseForm],
|
||||
);
|
||||
|
||||
/**
|
||||
* Quando o usuário clica em "remover" na tabela
|
||||
*/
|
||||
const handleConfirmDelete = useCallback(
|
||||
(item: GNaturezaInterface) => {
|
||||
// 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 deleteGNatureza(itemToDelete);
|
||||
|
||||
// Atualiza a lista
|
||||
await indexGNatureza(GNaturezaIndexParams);
|
||||
|
||||
// Limpa o item selecionado
|
||||
setItemToDelete(null);
|
||||
|
||||
// Fecha o modal
|
||||
handleCancel();
|
||||
}, [itemToDelete, indexGNatureza, handleCancel]);
|
||||
|
||||
/**
|
||||
* Busca inicial dos dados
|
||||
*/
|
||||
useEffect(() => {
|
||||
indexGNatureza(GNaturezaIndexParams);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Tela de loading enquanto carrega os dados
|
||||
*/
|
||||
if (gNatureza?.length == 0) {
|
||||
return <Loading type={2} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Cabeçalho */}
|
||||
<Header
|
||||
title={'Naturezas de Minutas'}
|
||||
description={'Naturezas de Minutas'}
|
||||
buttonText={'Novo imóvel'}
|
||||
buttonAction={() => {
|
||||
handleOpenForm(null);
|
||||
}}
|
||||
/>
|
||||
{/* Tabela de andamentos */}
|
||||
<GNaturezaTable
|
||||
data={gNatureza}
|
||||
onEdit={handleOpenForm}
|
||||
onDelete={handleConfirmDelete}
|
||||
/>
|
||||
{/* Modal de confirmação */}
|
||||
{isConfirmOpen && (
|
||||
<ConfirmDialog
|
||||
isOpen={isConfirmOpen}
|
||||
title="Confirmar exclusão"
|
||||
description="Atenção"
|
||||
message={`Deseja realmente excluir o imóvel "${itemToDelete?.descricao}"?`}
|
||||
confirmText="Sim, excluir"
|
||||
cancelText="Cancelar"
|
||||
onConfirm={handleDelete}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
)}
|
||||
{/* Formulário de criação/edição */}
|
||||
{isFormOpen && (
|
||||
<GNaturezaForm
|
||||
isOpen={isFormOpen}
|
||||
data={selectedData}
|
||||
onClose={handleCloseForm}
|
||||
onSave={handleSave}
|
||||
buttonIsLoading={buttonIsLoading}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
'use client';
|
||||
|
||||
import { DataTable } from "@/shared/components/dataTable/DataTable";
|
||||
import GNaturezaColumns from "./GNaturezaColumns";
|
||||
import GNaturezaTableInterface from "../../interfaces/GNatureza/GNaturezaTableInterface";
|
||||
|
||||
/**
|
||||
* Componente principal da tabela de Naturezas
|
||||
*/
|
||||
export default function GNaturezaTable({
|
||||
data,
|
||||
onEdit,
|
||||
onDelete,
|
||||
}: GNaturezaTableInterface) {
|
||||
const columns = GNaturezaColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div>
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="descricao"
|
||||
filterPlaceholder="Buscar por descrição da natureza..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import ApiResponseInterface from "@/shared/services/api/interfaces/ApiResponseInterface";
|
||||
import API from "@/shared/services/api/Api";
|
||||
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
|
||||
async function executeGNaturezaDeleteData(
|
||||
data: GNaturezaInterface
|
||||
): Promise<ApiResponseInterface> {
|
||||
const api = new API();
|
||||
|
||||
return api.send({
|
||||
method: Methods.DELETE,
|
||||
endpoint: `administrativo/g_natureza/${data.natureza_id}`,
|
||||
});
|
||||
}
|
||||
|
||||
export const GNaturezaDeleteData = withClientErrorHandler(executeGNaturezaDeleteData);
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import ApiResponseInterface from "@/shared/services/api/interfaces/ApiResponseInterface";
|
||||
import API from "@/shared/services/api/Api";
|
||||
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
|
||||
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
|
||||
async function executeGNaturezaIndexData(
|
||||
data: GNaturezaInterface
|
||||
): Promise<ApiResponseInterface> {
|
||||
const api = new API();
|
||||
|
||||
return api.send({
|
||||
method: Methods.GET,
|
||||
endpoint: `administrativo/g_natureza/sistema/${data.sistema_id}`,
|
||||
});
|
||||
}
|
||||
|
||||
export const GNaturezaIndexData = withClientErrorHandler(executeGNaturezaIndexData);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import ApiResponseInterface from "@/shared/services/api/interfaces/ApiResponseInterface";
|
||||
import API from "@/shared/services/api/Api";
|
||||
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
|
||||
async function executeGNaturezaSaveData(
|
||||
data: GNaturezaInterface
|
||||
): Promise<ApiResponseInterface> {
|
||||
// Verifica se existe ID para decidir se é atualização (PUT) ou criação (POST)
|
||||
const isUpdate = Boolean(data.natureza_id);
|
||||
|
||||
// Instancia o cliente da API
|
||||
const api = new API();
|
||||
|
||||
// Executa a requisição para a API com o método apropriado e envia os dados no corpo
|
||||
return api.send({
|
||||
method: isUpdate ? Methods.PUT : Methods.POST, // PUT se atualizar, POST se criar
|
||||
endpoint: `administrativo/g_natureza/${data.natureza_id || ""}`, // endpoint dinâmico
|
||||
body: data, // payload enviado para a API
|
||||
});
|
||||
}
|
||||
|
||||
export const GNaturezaSaveData = withClientErrorHandler(executeGNaturezaSaveData);
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import { useResponse } from "@/shared/components/response/ResponseContext";
|
||||
import { useState } from "react";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
import { GNaturezaDeleteService } from "../../services/GNatureza/GNaturezaDeleteService";
|
||||
|
||||
export const useGNaturezaDeleteHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [gNatureza, setGNatureza] = useState<GNaturezaInterface>();
|
||||
|
||||
const deleteGNatureza = async (data: GNaturezaInterface) => {
|
||||
const response = await GNaturezaDeleteService(data);
|
||||
|
||||
setGNatureza(data);
|
||||
setResponse(response);
|
||||
};
|
||||
|
||||
return { gNatureza, deleteGNatureza };
|
||||
};
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { useForm } from "react-hook-form";
|
||||
import { GNaturezaFormValues, GNaturezaSchema } from "../../schemas/GNatureza/GNaturezaSchema";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
|
||||
export function useGNaturezaFormHook(defaults?: Partial<GNaturezaFormValues>) {
|
||||
return useForm<GNaturezaFormValues>({
|
||||
resolver: zodResolver(GNaturezaSchema),
|
||||
defaultValues: {
|
||||
natureza_id: 0,
|
||||
...defaults,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
'use client';
|
||||
|
||||
import { useResponse } from "@/shared/components/response/ResponseContext";
|
||||
import { useState } from "react";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
import { GNaturezaIndexService } from "../../services/GNatureza/GNaturezaIndexService";
|
||||
|
||||
export const useGNaturezaIndexHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [gNatureza, setGNatureza] = useState<GNaturezaInterface[]>([]);
|
||||
|
||||
const indexGNatureza = async (data: GNaturezaInterface) => {
|
||||
const response = await GNaturezaIndexService(data);
|
||||
// Armazena os dados consultados
|
||||
setGNatureza(response.data);
|
||||
// Define a resposta (toast, modal, feedback, etc.)
|
||||
setResponse(response);
|
||||
};
|
||||
|
||||
return {
|
||||
gNatureza,
|
||||
indexGNatureza,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
'use client';
|
||||
|
||||
import { useResponse } from "@/shared/components/response/ResponseContext";
|
||||
import { useState } from "react";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
import { GNaturezaSaveService } from "../../services/GNatureza/GNaturezaSaveService";
|
||||
|
||||
export const useGNaturezaSaveHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [gNatureza, setGNatureza] = useState<GNaturezaInterface>();
|
||||
|
||||
// controla se o formulário está aberto ou fechado
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const saveGNatureza = async (data: GNaturezaInterface) => {
|
||||
const response = await GNaturezaSaveService(data);
|
||||
|
||||
// Armazena os dados da resposta
|
||||
setGNatureza(response.data);
|
||||
|
||||
// Define os dados da resposta (toast, modal, etc.)
|
||||
setResponse(response);
|
||||
|
||||
// Fecha o formulário automaticamente após salvar
|
||||
setIsOpen(false);
|
||||
|
||||
// Retorna os valores de forma imediata
|
||||
return response.data;
|
||||
};
|
||||
|
||||
return { gNatureza, saveGNatureza, isOpen, setIsOpen };
|
||||
};
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { GNaturezaFormValues } from "../../schemas/GNatureza/GNaturezaSchema";
|
||||
|
||||
export interface GNaturezaFormInterface {
|
||||
isOpen: boolean;
|
||||
data: GNaturezaFormValues | null;
|
||||
onClose: (item: null, isFormStatus: boolean) => void;
|
||||
onSave: (data: GNaturezaFormValues) => void;
|
||||
buttonIsLoading: boolean;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export interface GNaturezaIndexInterface {
|
||||
sistema_id: number
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export default interface GNaturezaInterface {
|
||||
natureza_id?: number;
|
||||
descricao?: string;
|
||||
situacao?: string;
|
||||
sistema_id?: number;
|
||||
pedir_numero_imovel?: string;
|
||||
controle_frenteverso?: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import GNaturezaInterface from "./GNaturezaInterface";
|
||||
|
||||
export default interface GNaturezaTableInterface {
|
||||
data?: GNaturezaInterface[];
|
||||
onEdit: (item: GNaturezaInterface, isEditingFormStatus: boolean) => void;
|
||||
onDelete: (item: GNaturezaInterface, isEditingFormStatus: boolean) => void;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import z from "zod";
|
||||
|
||||
export const GNaturezaSchema = z.object({
|
||||
natureza_id: z.number().optional(),
|
||||
descricao: z.string().optional(),
|
||||
situacao: z.string().optional(),
|
||||
sistema_id: z.number().optional(),
|
||||
pedir_numero_imovel: z.string().optional(),
|
||||
controle_frenteverso: z.string().optional(),
|
||||
});
|
||||
|
||||
export type GNaturezaFormValues = z.infer<typeof GNaturezaSchema>;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import { GNaturezaDeleteData } from "../../data/GNatureza/GNaturezaDeleteData";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
|
||||
async function executeGNaturezaDeleteService(data: GNaturezaInterface) {
|
||||
const response = await GNaturezaDeleteData(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const GNaturezaDeleteService = withClientErrorHandler(executeGNaturezaDeleteService);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import { GNaturezaIndexData } from "../../data/GNatureza/GNaturezaIndexData";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
|
||||
export default async function executeGNaturezaIndexService(data: GNaturezaInterface) {
|
||||
const response = await GNaturezaIndexData(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const GNaturezaIndexService = withClientErrorHandler(executeGNaturezaIndexService);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import { GNaturezaSaveData } from "../../data/GNatureza/GNaturezaSaveData";
|
||||
import GNaturezaInterface from "../../interfaces/GNatureza/GNaturezaInterface";
|
||||
|
||||
async function executeGNaturezaSaveService(data: GNaturezaInterface) {
|
||||
const response = await GNaturezaSaveData(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const GNaturezaSaveService = withClientErrorHandler(executeGNaturezaSaveService);
|
||||
62
src/shared/components/situacoes/SituacoesSelect.tsx
Normal file
62
src/shared/components/situacoes/SituacoesSelect.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
|
||||
import { FormControl } from "@/components/ui/form";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { SituacoesEnum } from "@/shared/enums/SituacoesEnum";
|
||||
import { Command } from "cmdk";
|
||||
import { CheckIcon, ChevronsUpDownIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function SituacoesSelect({ field }: any) {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
// ✅ Corrigido para enums string-based
|
||||
const options = Object.entries(SituacoesEnum).map(([value, label]) => ({
|
||||
value,
|
||||
label,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl className="w-full">
|
||||
<Button variant="outline" role="combobox" aria-expanded={open} className="justify-between">
|
||||
{field.value
|
||||
? options.find((item) => item.value === field.value)?.label
|
||||
: "Selecione..."}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar situação..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((item) => (
|
||||
<CommandItem
|
||||
key={item.value}
|
||||
value={item.label.toLowerCase()}
|
||||
onSelect={() => {
|
||||
field.onChange(item.value);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
field.value === item.value ? "opacity-100" : "opacity-0"
|
||||
)}
|
||||
/>
|
||||
{item.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
export enum SituacoesEnum {
|
||||
A = 'A',
|
||||
I = 'I',
|
||||
A = 'Ativo',
|
||||
I = 'Inativo',
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue