[MVPTN-88] feat(CRUD) implementações diversas

This commit is contained in:
Keven Willian Pereira de Souza 2025-10-09 15:50:20 -03:00
parent 0d5ee71975
commit 37f0f8713d
29 changed files with 245 additions and 312 deletions

View file

@ -37,7 +37,7 @@ import GetCapitalize from '@/shared/actions/text/GetCapitalize';
import { TImovelFormInterface } from '../../interfaces/TImovel/TImovelFormInterface';
import { useTImovelFormHook } from '../../hooks/TImovel/useTImovelFormHook';
import TImovelUnidadeUrbanoPage from '../TImovelUnidade/TImovelUnidadeUrbano/TImovelUnidadeUrbanoPage';
import TImovelUnidadeRuralPage from '../TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRuralPage';
import TImovelUnidadeRuralIndex from '../TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRuralIndex';
import { parseNumberInput } from '@/shared/actions/form/parseNumberInput';
export default function TImovelForm({ isOpen, data, onClose, onSave, buttonIsLoading, tipoClasse }: TImovelFormInterface) {
@ -83,21 +83,21 @@ export default function TImovelForm({ isOpen, data, onClose, onSave, buttonIsLoa
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSave)} className="space-y-6">
{/* Tabs */}
<Tabs defaultValue="dadosDoImovel" className="space-y-4">
<TabsList className="flex w-full">
<TabsTrigger className="flex-1 text-center cursor-pointer" value="dadosDoImovel">
<HouseIcon className="me-1 inline" />
Dados do Imóvel
</TabsTrigger>
<TabsTrigger className="flex-1 text-center cursor-pointer" value="unidades">
<IdCardIcon className="inline" />
Unidades
</TabsTrigger>
</TabsList>
{/* Dados do Imóvel */}
<TabsContent value="dadosDoImovel" className="space-y-4">
{/* Tabs */}
<Tabs defaultValue="dadosDoImovel" className="space-y-4">
<TabsList className="flex w-full">
<TabsTrigger className="flex-1 text-center cursor-pointer" value="dadosDoImovel">
<HouseIcon className="me-1 inline" />
Dados do Imóvel
</TabsTrigger>
<TabsTrigger className="flex-1 text-center cursor-pointer" value="unidades">
<IdCardIcon className="inline" />
Unidades
</TabsTrigger>
</TabsList>
{/* Dados do Imóvel */}
<TabsContent value="dadosDoImovel" className="space-y-4">
<form onSubmit={form.handleSubmit(onSave)} className="space-y-6">
<div className="grid w-full grid-cols-12 gap-4">
{/* UF */}
<div className="col-span-12 sm:col-span-6 md:col-span-2">
@ -299,7 +299,7 @@ export default function TImovelForm({ isOpen, data, onClose, onSave, buttonIsLoa
<FormItem>
<FormLabel>Número</FormLabel>
<FormControl>
<Input {...field} type="number" placeholder="Digite o número" />
<Input {...field} type="number" placeholder="Digite o número" onChange={e => field.onChange(parseNumberInput(e))} />
</FormControl>
<FormMessage />
</FormItem>
@ -352,34 +352,34 @@ export default function TImovelForm({ isOpen, data, onClose, onSave, buttonIsLoa
/>
</div>
</div>
</TabsContent>
{/* Unidades */}
<TabsContent value="unidades" className="space-y-4">
{/* Conteúdo das unidades */}
{tipoClasse === 1 ? <TImovelUnidadeUrbanoPage imovel_id={data?.imovel_id} /> : null}
{/* Conteúdo das unidades */}
{tipoClasse === 3 ? <TImovelUnidadeRuralPage /> : null}
</TabsContent>
</Tabs>
{/* Rodapé do Dialog */}
<DialogFooter className="mt-4 flex flex-col sm:flex-row gap-2 justify-end">
<DialogClose asChild>
<Button variant="outline" type="button" onClick={() => onClose(null, false)}>
Cancelar
</Button>
</DialogClose>
<LoadingButton
text="Salvar"
textLoading="Aguarde..."
type="submit"
loading={buttonIsLoading}
/>
</DialogFooter>
{/* Campo oculto */}
<input type="hidden" {...form.register("imovel_id")} />
</form>
{/* Rodapé do Dialog */}
<DialogFooter className="mt-4 flex flex-col sm:flex-row gap-2 justify-end">
<DialogClose asChild>
<Button variant="outline" type="button" onClick={() => onClose(null, false)}>
Cancelar
</Button>
</DialogClose>
<LoadingButton
text="Salvar"
textLoading="Aguarde..."
type="submit"
loading={buttonIsLoading}
/>
</DialogFooter>
<input type="hidden" {...form.register("imovel_id")} />
</form>
</TabsContent>
{/* Unidades */}
<TabsContent value="unidades" className="space-y-4">
{/* Conteúdo das unidades */}
{tipoClasse === 1 ? <TImovelUnidadeUrbanoPage imovel_id={data?.imovel_id} /> : null}
{/* Conteúdo das unidades */}
{tipoClasse === 3 ? <TImovelUnidadeRuralIndex imovel_id={data?.imovel_id} /> : null}
</TabsContent>
</Tabs>
{/* Campo oculto */}
</Form>
</DialogContent>
</Dialog>
</Dialog >
);
}

View file

@ -19,6 +19,10 @@ import TImovelForm from './TImovelForm';
export default function TImovelIndex({ pageTitle, pageDescription, tipoClasse }: TImovelIndexInterface) {
const TImovelIndexInterface: TImovelIndexInterface = {
tipoClasse: tipoClasse
}
// Controle de estado do botão
const [buttonIsLoading, setButtonIsLoading] = useState(false);
@ -75,7 +79,7 @@ export default function TImovelIndex({ pageTitle, pageDescription, tipoClasse }:
setButtonIsLoading(false);
// Atualiza a lista de dados
indexTImovel();
indexTImovel(TImovelIndexInterface);
},
[saveTImovel, indexTImovel, handleCloseForm],
);
@ -105,7 +109,7 @@ export default function TImovelIndex({ pageTitle, pageDescription, tipoClasse }:
await deleteTImovel(itemToDelete);
// Atualiza a lista
await indexTImovel();
await indexTImovel(TImovelIndexInterface);
// Limpa o item selecionado
setItemToDelete(null);
@ -118,7 +122,7 @@ export default function TImovelIndex({ pageTitle, pageDescription, tipoClasse }:
* Busca inicial dos dados
*/
useEffect(() => {
indexTImovel();
indexTImovel(TImovelIndexInterface);
}, []);
/**

View file

@ -33,7 +33,8 @@ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, Command
import { ImovelTipoEnum } from '@/shared/enums/ImovelTipoEnum';
import { cn } from '@/lib/utils';
import { ImovelConstrucaoEnum } from '@/shared/enums/ImovelConstrucaoEnum';
import { Checkbox } from '@/components/ui/checkbox';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { SituacoesEnum } from '@/shared/enums/SituacoesEnum';
export default function TImovelUnidadeRuralForm({ isOpen, data, onClose, onSave, buttonIsLoading }: TImovelUnidadeRuralFormInterface) {
@ -61,6 +62,10 @@ export default function TImovelUnidadeRuralForm({ isOpen, data, onClose, onSave,
}, [data, form]);
function onErro(errors: any) {
console.log(errors);
}
return (
<Dialog
open={isOpen}
@ -78,7 +83,7 @@ export default function TImovelUnidadeRuralForm({ isOpen, data, onClose, onSave,
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSave)} className="space-y-6">
<form onSubmit={form.handleSubmit(onSave, onErro)} className="space-y-6">
<div className="grid grid-cols-12 sm:grid-cols-12 lg:grid-cols-12 gap-4">
{/* Tipo Imóvel */}
<div className="col-span-12 sm:col-span-6 md:col-span-6">
@ -306,56 +311,59 @@ export default function TImovelUnidadeRuralForm({ isOpen, data, onClose, onSave,
/>
</div>
{/* Geo Referenciamento */}
<div className="col-span-12 sm:col-span-6 md:col-span-12">
<div className="col-span-12 sm:col-span-6 md:col-span-6">
<FormField
control={form.control}
name="geo_referenciamento"
render={({ field }) => (
<FormItem>
<div className="flex items-center gap-3">
<FormControl>
<Checkbox
id="geo_referenciamento"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<FormLabel htmlFor="geo_referenciamento">
Geo Referenciamento
</FormLabel>
</div>
<FormItem className='w-full'>
<FormLabel>Geo Referenciamento</FormLabel>
<FormControl>
<Select
onValueChange={field.onChange}
value={field.value}
>
<SelectTrigger id="geo_referenciamento" className='w-full'>
<SelectValue placeholder="Selecione..." />
</SelectTrigger>
<SelectContent>
<SelectItem value={SituacoesEnum.A}>Ativo</SelectItem>
<SelectItem value={SituacoesEnum.I}>Inativo</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Reserva Florestal */}
<div className="col-span-12 sm:col-span-6 md:col-span-12">
<div className="col-span-12 sm:col-span-6 md:col-span-6">
<FormField
control={form.control}
name="reserva_florestal"
render={({ field }) => (
<FormItem>
<div className="flex items-center gap-3">
<FormControl>
<Checkbox
id="reserva_florestal"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<FormLabel htmlFor="reserva_florestal">
Reserva Florestal
</FormLabel>
</div>
<FormItem className='w-full'>
<FormLabel>Reserva Florestal</FormLabel>
<FormControl>
<Select
onValueChange={field.onChange}
value={field.value}
>
<SelectTrigger id="reserva_florestal" className='w-full'>
<SelectValue placeholder="Selecione..." />
</SelectTrigger>
<SelectContent>
<SelectItem value={SituacoesEnum.A}>Ativo</SelectItem>
<SelectItem value={SituacoesEnum.I}>Inativo</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Campo oculto */}
<input type="hidden" {...form.register("imovel_unidade_id")} />
<input type="hidden" {...form.register("imovel_id")} />
</div>
{/* Rodapé do Dialog */}
<DialogFooter className="mt-4 flex flex-col sm:flex-row gap-2 justify-end">

View file

@ -3,7 +3,7 @@
import { useEffect, useState, useCallback } from 'react';
import Loading from '@/shared/components/loading/loading';
import TImovelUnidadeTable from './TImovelUnidadeRuralTable';
import TImovelUnidadeRuralTable from './TImovelUnidadeRuralTable';
import TImovelUnidadeRuralForm from './TImovelUnidadeRuralForm';
import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog';
@ -14,8 +14,14 @@ import { useTImovelUnidadeRuralIndexHook } from '@/packages/administrativo/hooks
import { useTImovelUnidadeRuralSaveHook } from '@/packages/administrativo/hooks/TImovelUnidade/TImovelUnidadeRural/useTImovelUnidadeRuralSaveHook';
import { useTImovelUnidadeRuralDeleteHook } from '@/packages/administrativo/hooks/TImovelUnidade/TImovelUnidadeRural/useTImovelUnidadeRuralDeleteHook';
import { TImovelUnidadeRuralInterface } from '@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRural';
import TImovelUnidadePageInterface from '@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadePageInterface';
export default function TImovelUnidadeRuralIndex({ imovel_id }: TImovelUnidadePageInterface) {
const TImovelUnidadePage: TImovelUnidadePageInterface = {
imovel_id: imovel_id
}
export default function TImovelUnidadePage() {
// Controle de estado do botão
const [buttonIsLoading, setButtonIsLoading] = useState(false);
@ -45,6 +51,8 @@ export default function TImovelUnidadePage() {
* Abre o formulário no modo de edição ou criação
*/
const handleOpenForm = useCallback((data: TImovelUnidadeRuralInterface | null) => {
// Se não houver dados (criação), cria um objeto inicial com imovel_id
const initialData: TImovelUnidadeRuralInterface = data ?? { imovel_id } as TImovelUnidadeRuralInterface;
setSelectedData(data);
setIsFormOpen(true);
}, []);
@ -72,7 +80,7 @@ export default function TImovelUnidadePage() {
setButtonIsLoading(false);
// Atualiza a lista de dados
indexTImovelUnidadeRural();
indexTImovelUnidadeRural(TImovelUnidadePage);
},
[saveTImovelUnidadeRural, indexTImovelUnidadeRural, handleCloseForm],
);
@ -102,7 +110,7 @@ export default function TImovelUnidadePage() {
await deleteTImovelUnidadeRural(itemToDelete);
// Atualiza a lista
await indexTImovelUnidadeRural();
await indexTImovelUnidadeRural(TImovelUnidadePage);
// Limpa o item selecionado
setItemToDelete(null);
@ -115,7 +123,7 @@ export default function TImovelUnidadePage() {
* Busca inicial dos dados
*/
useEffect(() => {
indexTImovelUnidadeRural();
indexTImovelUnidadeRural(TImovelUnidadePage);
}, []);
/**
@ -137,7 +145,7 @@ export default function TImovelUnidadePage() {
}}
/>
{/* Tabela de andamentos */}
<TImovelUnidadeTable
<TImovelUnidadeRuralTable
data={tImovelUnidadeRural}
onEdit={handleOpenForm}
onDelete={handleConfirmDelete} />

View file

@ -7,7 +7,7 @@ import TImovelUnidadeRuralTableInterface from '@/packages/administrativo/interfa
/**
* Componente principal da tabela
*/
export default function TImovelUnidadeTable({ data, onEdit, onDelete }: TImovelUnidadeRuralTableInterface) {
export default function TImovelUnidadeRuralTable({ data, onEdit, onDelete }: TImovelUnidadeRuralTableInterface) {
const columns = TImovelUnidadeColumns(onEdit, onDelete);
return (
<div className="max-h-[40vh] overflow-y-auto">

View file

@ -272,7 +272,7 @@ export default function TImovelUnidadeUrbanoForm({ isOpen, data, onClose, onSave
key={item.value}
value={item.label.toLowerCase()}
onSelect={() => {
field.onChange(item.value); // salva o número (id)
field.onChange(item.value);
setOpen(false);
}}
>
@ -366,7 +366,7 @@ export default function TImovelUnidadeUrbanoForm({ isOpen, data, onClose, onSave
/>
</div>
{/* Iptu */}
<div className="col-span-12 sm:col-span-6 md:col-span-3">
<div className="col-span-12 sm:col-span-6 md:col-span-2">
<FormField
control={form.control}
name="iptu"
@ -388,7 +388,7 @@ export default function TImovelUnidadeUrbanoForm({ isOpen, data, onClose, onSave
name="numero_unidade"
render={({ field }) => (
<FormItem>
<FormLabel>UnidadeUrbano</FormLabel>
<FormLabel>Unidade Urbano</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@ -432,7 +432,7 @@ export default function TImovelUnidadeUrbanoForm({ isOpen, data, onClose, onSave
/>
</div>
{/* Loteamento */}
<div className="col-span-12 sm:col-span-6 md:col-span-3">
<div className="col-span-12 sm:col-span-6 md:col-span-2">
<FormField
control={form.control}
name="nomeloteamento"
@ -447,6 +447,22 @@ export default function TImovelUnidadeUrbanoForm({ isOpen, data, onClose, onSave
)}
/>
</div>
{/* Numero */}
<div className="col-span-12 sm:col-span-6 md:col-span-2">
<FormField
control={form.control}
name="numero"
render={({ field }) => (
<FormItem>
<FormLabel>Numero</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* CNM */}
<div className="col-span-12 sm:col-span-6 md:col-span-6">
<FormField
@ -496,6 +512,7 @@ export default function TImovelUnidadeUrbanoForm({ isOpen, data, onClose, onSave
)}
/>
</div>
{/* Complemento */}
<div className="col-span-12 sm:col-span-6 md:col-span-8">
<FormField
@ -527,9 +544,6 @@ export default function TImovelUnidadeUrbanoForm({ isOpen, data, onClose, onSave
loading={buttonIsLoading}
/>
</DialogFooter>
{/* Campo oculto */}
<input type="hidden" {...form.register("imovel_unidade_id")} />
<input type="hidden" {...form.register("imovel_id")} />
</form>
</Form>
</DialogContent>

View file

@ -16,7 +16,7 @@ import TImovelUnidadeUrbanoTable from './TImovelUnidadeUrbanoTable';
import TImovelUnidadeUrbanoForm from './TImovelUnidadeUrbanoForm';
import TImovelUnidadePageInterface from '@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadePageInterface';
export default function TImovelUnidadeUrbanoPage({imovel_id}: TImovelUnidadePageInterface) {
export default function TImovelUnidadeUrbanoPage({ imovel_id }: TImovelUnidadePageInterface) {
const TImovelUnidadePage: TImovelUnidadePageInterface = {
imovel_id: imovel_id
@ -31,7 +31,7 @@ export default function TImovelUnidadeUrbanoPage({imovel_id}: TImovelUnidadePage
const { deleteTImovelUnidadeUrbano } = useTImovelUnidadeUrbanoDeleteHook();
// Estados
const [selectedAndamento, setSelectedAndamento] = useState<TImovelUnidadeUrbanoInterface | null>(null);
const [selectedData, setSelectedData] = useState<TImovelUnidadeUrbanoInterface | null>(null);
const [isFormOpen, setIsFormOpen] = useState(false);
// Estado para saber qual item será deletado
@ -51,7 +51,9 @@ export default function TImovelUnidadeUrbanoPage({imovel_id}: TImovelUnidadePage
* Abre o formulário no modo de edição ou criação
*/
const handleOpenForm = useCallback((data: TImovelUnidadeUrbanoInterface | null) => {
setSelectedAndamento(data);
// Se não houver dados (criação), cria um objeto inicial com imovel_id
const initialData: TImovelUnidadeUrbanoInterface = data ?? { imovel_id } as TImovelUnidadeUrbanoInterface;
setSelectedData(initialData);
setIsFormOpen(true);
}, []);
@ -59,7 +61,7 @@ export default function TImovelUnidadeUrbanoPage({imovel_id}: TImovelUnidadePage
* Fecha o formulário e limpa o andamento selecionado
*/
const handleCloseForm = useCallback(() => {
setSelectedAndamento(null);
setSelectedData(null);
setIsFormOpen(false);
}, []);
@ -146,7 +148,8 @@ export default function TImovelUnidadeUrbanoPage({imovel_id}: TImovelUnidadePage
<TImovelUnidadeUrbanoTable
data={tImovelUnidadeUrbano}
onEdit={handleOpenForm}
onDelete={handleConfirmDelete} />
onDelete={handleConfirmDelete}
/>
{/* Modal de confirmação */}
<ConfirmDialog
isOpen={isConfirmOpen}
@ -161,7 +164,7 @@ export default function TImovelUnidadeUrbanoPage({imovel_id}: TImovelUnidadePage
{/* Formulário de criação/edição */}
<TImovelUnidadeUrbanoForm
isOpen={isFormOpen}
data={selectedAndamento}
data={selectedData}
onClose={handleCloseForm}
onSave={handleSave}
buttonIsLoading={buttonIsLoading}

View file

@ -2,14 +2,15 @@ import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/
import API from "@/shared/services/api/Api";
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
import ApiResponseInterface from "@/shared/services/api/interfaces/ApiResponseInterface";
import { TImovelIndexInterface } from "../../interfaces/TImovel/TImovelIndexInterface";
async function executeTImovelIndexData(): Promise<ApiResponseInterface> {
async function executeTImovelIndexData(data: TImovelIndexInterface): Promise<ApiResponseInterface> {
const api = new API();
return api.send({
method: Methods.GET,
endpoint: `administrativo/t_imovel/classe/1`
endpoint: `administrativo/t_imovel/classe/${data.tipoClasse}`
});
}

View file

@ -1,13 +1,14 @@
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
import { TImovelUnidadeRuralInterface } from "@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRural";
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
import API from "@/shared/services/api/Api";
async function executeTImovelUnidadeRuralDeleteData(data: TImovelUnidadeRuralInterface) {
return Promise.resolve({
status: 200,
message: 'Dados Removidos'
const api = new API();
return api.send({
method: Methods.DELETE,
endpoint: `administrativo/t_imovel_unidade/${data.imovel_unidade_id}`
});
}
export const TImovelUnidadeRuralDeleteData = withClientErrorHandler(executeTImovelUnidadeRuralDeleteData);

View file

@ -1,160 +1,14 @@
import TImovelUnidadePageInterface from "@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadePageInterface";
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
import API from "@/shared/services/api/Api";
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
async function executeTImovelUnidadeRuralIndexData() {
async function executeTImovelUnidadeRuralIndexData(data: TImovelUnidadePageInterface) {
return Promise.resolve({
status: 200,
message: 'Dados Salvos',
data: [
{
"imovel_unidade_id": 3921.00,
"imovel_id": 5459.00,
"numero_unidade": "asdfasd",
"quadra": null,
"area": null,
"superquadra": null,
"conjunto": null,
"bloco": null,
"area_descritiva": null,
"caracteristica": null,
"reserva_florestal": null,
"geo_referenciamento": null,
"logradouro": null,
"tb_tipologradouro_id": null,
"selecionado": "S",
"complemento": null,
"tipo_imovel": 67.00,
"tipo_construcao": 0.00,
"texto": null,
"numero_edificacao": null,
"iptu": "",
"ccir": null,
"nirf": null,
"lote": null,
"torre": null,
"nomeloteamento": null,
"nomecondominio": null,
"numero": null,
"cnm_numero": null,
"imovel_publico_uniao": null,
"spu_rip": null,
"cat": null,
"inscricao_municipal": null,
"cib": null,
"area_construida": null
},
{
"imovel_unidade_id": 3918.00,
"imovel_id": 5456.00,
"numero_unidade": null,
"quadra": "45",
"area": null,
"superquadra": null,
"conjunto": null,
"bloco": null,
"area_descritiva": null,
"caracteristica": null,
"reserva_florestal": null,
"geo_referenciamento": null,
"logradouro": null,
"tb_tipologradouro_id": null,
"selecionado": "S",
"complemento": null,
"tipo_imovel": 67.00,
"tipo_construcao": 0.00,
"texto": null,
"numero_edificacao": null,
"iptu": null,
"ccir": null,
"nirf": null,
"lote": null,
"torre": null,
"nomeloteamento": null,
"nomecondominio": null,
"numero": null,
"cnm_numero": null,
"imovel_publico_uniao": null,
"spu_rip": null,
"cat": null,
"inscricao_municipal": null,
"cib": null,
"area_construida": null
},
{
"imovel_unidade_id": 3917.00,
"imovel_id": 5454.00,
"numero_unidade": null,
"quadra": "45",
"area": 160.00,
"superquadra": null,
"conjunto": null,
"bloco": null,
"area_descritiva": null,
"caracteristica": null,
"reserva_florestal": null,
"geo_referenciamento": null,
"logradouro": "RUA P 3",
"tb_tipologradouro_id": 1.00,
"selecionado": "",
"complemento": null,
"tipo_imovel": 67.00,
"tipo_construcao": 0.00,
"texto": null,
"numero_edificacao": null,
"iptu": "1200",
"ccir": null,
"nirf": null,
"lote": "12",
"torre": null,
"nomeloteamento": null,
"nomecondominio": null,
"numero": 125.00,
"cnm_numero": null,
"imovel_publico_uniao": null,
"spu_rip": null,
"cat": null,
"inscricao_municipal": null,
"cib": null,
"area_construida": null
},
{
"imovel_unidade_id": 3916.00,
"imovel_id": 5453.00,
"numero_unidade": null,
"quadra": "06",
"area": 461.51,
"superquadra": null,
"conjunto": null,
"bloco": null,
"area_descritiva": null,
"caracteristica": null,
"reserva_florestal": null,
"geo_referenciamento": null,
"logradouro": "Mariana Vilela",
"tb_tipologradouro_id": 3.00,
"selecionado": "S",
"complemento": null,
"tipo_imovel": 71.00,
"tipo_construcao": 2.00,
"texto": "{...}",
"numero_edificacao": null,
"iptu": "001.211.0006.0012.0001",
"ccir": null,
"nirf": null,
"lote": "12",
"torre": null,
"nomeloteamento": null,
"nomecondominio": null,
"numero": null,
"cnm_numero": null,
"imovel_publico_uniao": null,
"spu_rip": null,
"cat": null,
"inscricao_municipal": null,
"cib": null,
"area_construida": null
}
]
const api = new API();
return await api.send({
method: Methods.GET,
endpoint: `administrativo/t_imovel_unidade/imovel/${data.imovel_id}`
});
}

View file

@ -1,13 +1,23 @@
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
import { TImovelUnidadeRuralInterface } from "@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRural";
import API from "@/shared/services/api/Api";
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
async function executeTImovelUnidadeRuralDeleteData(data: TImovelUnidadeRuralInterface) {
async function executeTImovelUnidadeRuralSaveData(data: TImovelUnidadeRuralInterface) {
return Promise.resolve({
status: 200,
message: 'Dados Removidos'
// Verifica se existe ID da cidade para decidir se é atualização (PUT) ou criação (POST)
const isUpdate = Boolean(data.imovel_unidade_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/t_imovel_unidade/${data.imovel_unidade_id || ''}`, // endpoint dinâmico
body: data, // payload enviado para a API
});
}
export const TImovelUnidadeRuralSaveData = withClientErrorHandler(executeTImovelUnidadeRuralDeleteData);
export const TImovelUnidadeRuralSaveData = withClientErrorHandler(executeTImovelUnidadeRuralSaveData);

View file

@ -6,7 +6,6 @@ import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
async function executeTImovelUnidadeUrbanoDeleteData(data: TImovelUnidadeUrbanoInterface) {
const api = new API();
return api.send({
method: Methods.DELETE,
endpoint: `administrativo/t_imovel_unidade/${data.imovel_unidade_id}`

View file

@ -4,14 +4,11 @@ import API from "@/shared/services/api/Api";
import { Methods } from "@/shared/services/api/enums/ApiMethodEnum";
async function executeTImovelUnidadeUrbanoIndexData(data: TImovelUnidadePageInterface) {
const api = new API();
return api.send({
method: Methods.GET,
endpoint: `administrativo/t_imovel_unidade/imovel/${data.imovel_id}`
});
}
export const TImovelUnidadeUrbanoIndexData = withClientErrorHandler(executeTImovelUnidadeUrbanoIndexData);

View file

@ -6,6 +6,7 @@ export function useTImovelFormHook(defaults?: Partial<TImovelFormValues>) {
return useForm<TImovelFormValues>({
resolver: zodResolver(TImovelSchema),
defaultValues: {
imovel_id: 0,
...defaults,
},
});

View file

@ -4,18 +4,17 @@ import { useResponse } from '@/shared/components/response/ResponseContext';
import { useState } from 'react';
import TImovelInterface from '../../interfaces/TImovel/TImovelInterface';
import { TImovelIndexData } from '../../data/TImovel/TImovelIndexData';
import { TImovelIndexInterface } from '../../interfaces/TImovel/TImovelIndexInterface';
export const useTImovelIndexHook = () => {
const { setResponse } = useResponse();
const [tImovel, setTImovel] = useState<TImovelInterface[]>([]);
const indexTImovel = async () => {
const response = await TImovelIndexData();
const indexTImovel = async (data: TImovelIndexInterface) => {
const response = await TImovelIndexData(data);
// Armazena os dados consultados
setTImovel(response.data);
// Define os dados do componente de resposta (toast, modal, etc)
setResponse(response);
};

View file

@ -6,6 +6,7 @@ export function useTImovelUnidadeRuralFormHook(defaults?: Partial<TImovelUnidade
return useForm<TImovelUnidadeRuralFormValues>({
resolver: zodResolver(TImovelUnidadeRuralSchema),
defaultValues: {
imovel_unidade_id: 0,
...defaults,
},
});

View file

@ -1,17 +1,18 @@
'use client';
import { useResponse } from '@/shared/components/response/ResponseContext';
import { TImovelUnidadeRuralIndexData } from '@/packages/administrativo/data/TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRuralIndexData';
import { TImovelUnidadeRuralInterface } from '@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRural';
import { useState } from 'react';
import { TImovelUnidadeRuralIndexService } from '@/packages/administrativo/services/TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRuralIndexService';
import TImovelUnidadeInterface from '@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadeInterface';
export const useTImovelUnidadeRuralIndexHook = () => {
const { setResponse } = useResponse();
const [tImovelUnidadeRural, setTImovelUnidadeRural] = useState<TImovelUnidadeRuralInterface[]>([]);
const indexTImovelUnidadeRural = async () => {
const response = await TImovelUnidadeRuralIndexData();
const indexTImovelUnidadeRural = async (data: TImovelUnidadeInterface) => {
const response = await TImovelUnidadeRuralIndexService(data);
// Armazena os dados consultados
setTImovelUnidadeRural(response.data);

View file

@ -6,7 +6,26 @@ export function useTImovelUnidadeUrbanoFormHook(defaults?: Partial<TImovelUnidad
return useForm<TImovelUnidadeUrbanoFormValues>({
resolver: zodResolver(TImovelUnidadeUrbanoSchema),
defaultValues: {
...defaults,
imovel_unidade_id: 0,
imovel_id: 0,
quadra: '',
lote: '',
area: 0,
inscricao_municipal: '',
logradouro: '',
tipo_imovel: 0,
tipo_construcao: 0,
iptu: '',
numero_unidade: '',
torre: '',
nomecondominio: '',
nomeloteamento: '',
cib: '',
cnm_numero: '',
numero_edificacao: '',
complemento: '',
tb_tipologradouro_id: 0,
...defaults, // sobrescreve com dados reais se houver
},
});
}

View file

@ -1,5 +1,5 @@
export interface TImovelIndexInterface {
pageTitle: string,
pageDescription: string,
tipoClasse: number
pageTitle?: string,
pageDescription?: string,
tipoClasse?: number
}

View file

@ -1,3 +1,3 @@
export default interface TImovelUnidadePageInterface {
imovel_id? : number;
imovel_id?: number;
}

View file

@ -5,7 +5,7 @@ export interface TImovelUnidadeUrbanoInterface extends TImovelUnidadeInterface {
lote?: string;
inscricao_municipal?: string;
tb_tipologradouro_id?: number;
logradouro: string;
logradouro?: string;
tipo_imovel?: number;
tipo_construcao?: number;
iptu?: string;
@ -13,7 +13,7 @@ export interface TImovelUnidadeUrbanoInterface extends TImovelUnidadeInterface {
torre?: string;
nomecondominio?: string;
nomeloteamento?: string;
numero?: number;
numero?: string;
complemento?: string;
numero_edificacao?: string;
cnm_numero?: string;

View file

@ -1,11 +1,12 @@
import { z } from "zod";
import { TImovelUnidadeSchema } from "../TImovelUnidadeSchema";
import { SituacoesEnum } from "@/shared/enums/SituacoesEnum";
export const TImovelUnidadeRuralSchema = TImovelUnidadeSchema.extend({
galpao: z.string().optional(),
nao_se_aplica: z.boolean().optional(),
reserva_florestal: z.boolean().optional(),
geo_referenciamento: z.boolean().optional(),
reserva_florestal: z.enum(SituacoesEnum),
geo_referenciamento: z.enum(SituacoesEnum),
nome_identificacao: z.string().optional(),
ccir: z.string().optional(),
denominacao: z.string().optional(),

View file

@ -6,13 +6,13 @@ export const TImovelUnidadeUrbanoSchema = TImovelUnidadeSchema.extend({
lote: z.string().optional(),
inscricao_municipal: z.string().optional(),
tb_tipologradouro_id: z.number().optional(),
logradouro: z.string().min(1, "O logradouro é obrigatório"),
logradouro: z.string().optional(),
iptu: z.string().optional(),
numero_unidade: z.string().optional(),
torre: z.string().optional(),
nomecondominio: z.string().optional(),
nomeloteamento: z.string().optional(),
numero: z.number().optional(),
numero: z.string().optional(),
complemento: z.string().optional(),
numero_edificacao: z.string().optional(),
cnm_numero: z.string().optional(),

View file

@ -1,10 +1,13 @@
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
import { TImovelUnidadeRuralIndexData } from '@/packages/administrativo/data/TImovelUnidade/TImovelUnidadeRural/TImovelUnidadeRuralIndexData';
import TImovelUnidadeInterface from '@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadeInterface';
export default async function executeTImovelUnidadeRuralIndexService() {
const response = await TImovelUnidadeRuralIndexData();
return response;
export default async function executeTImovelUnidadeRuralIndexService(data: TImovelUnidadeInterface) {
let response = null
if (data.imovel_id) {
response = await TImovelUnidadeRuralIndexData(data);
return response;
}
}
export const TImovelUnidadeRuralIndexService = withClientErrorHandler(executeTImovelUnidadeRuralIndexService);

View file

@ -4,7 +4,6 @@ import { TImovelUnidadeRuralInterface } from '@/packages/administrativo/interfac
async function executeTImovelUnidadeRuralSaveService(data: TImovelUnidadeRuralInterface) {
const response = await TImovelUnidadeRuralSaveData(data);
return response;
}

View file

@ -3,11 +3,13 @@ import { TImovelUnidadeUrbanoIndexData } from '@/packages/administrativo/data/TI
import TImovelUnidadePageInterface from '@/packages/administrativo/interfaces/TImovelUnidade/TImovelUnidadePageInterface';
export default async function executeTImovelUnidadeUrbanoIndexService(data: TImovelUnidadePageInterface) {
const response = await TImovelUnidadeUrbanoIndexData(data);
if (response.status === 200) {
return response;
if (!data.imovel_id) {
return {
status: 1000,
message: 'Não existe ID de imóvel para consultas.',
};
}
return await TImovelUnidadeUrbanoIndexData(data);
}
export const TImovelUnidadeUrbanoIndexService = withClientErrorHandler(executeTImovelUnidadeUrbanoIndexService);
export const TImovelUnidadeUrbanoIndexService = withClientErrorHandler(executeTImovelUnidadeUrbanoIndexService);

View file

@ -1,4 +1,5 @@
import { UseFormReturn, FieldValues } from "react-hook-form";
import normalizeFormData from "./normalizeFormData";
/**
* Reseta o formulário com os dados recebidos (se existirem)
@ -10,6 +11,6 @@ export function ResetFormIfData<T extends FieldValues>(
data: T | null
) {
if (data) {
form.reset(data);
form.reset(normalizeFormData(data));
}
}
}

View file

@ -0,0 +1,19 @@
/**
* Normaliza os dados do formulário, substituindo null por valores padrão
* Strings: ''
* Numbers: 0
* Boolean: false
*/
export default function normalizeFormData<T extends Record<string, any>>(data: T): T {
const normalized: Record<string, any> = {};
for (const key in data) {
if (data[key] === null || data[key] === undefined) {
// Detecta tipo baseado em chave ou regra padrão
normalized[key] =
typeof data[key] === 'number' ? 0 : '';
} else {
normalized[key] = data[key];
}
}
return normalized as T;
}

View file

@ -7,39 +7,27 @@ import { toast } from 'sonner';
export default function Response() {
const { response, clearResponse } = useResponse();
useEffect(() => {
switch (Number(response?.status)) {
case 201:
toast.success(response.message);
break;
case 422:
toast.error(response.error, {
description: response.detail,
});
break;
case 400:
toast.error(response.error, {
description: response.message,
});
break;
case 600:
toast.error(response.error, {
description: response.message,
});
break;
default:
if (response.status !== 0 && response.status !== 200 && response.status !== 201) {
toast.warning(JSON.stringify(response));
}
break;
}
}, [response, clearResponse]);
return <div></div>;
}