first commit
This commit is contained in:
commit
c9fb67e751
423 files changed
+53287
No files matched your search
@@ -0,0 +1,251 @@
|
||||
import { useState } from 'react';
|
||||
import { useQuery, useQueryClient } from 'react-query';
|
||||
import { formatCurrency } from '../../utils/format';
|
||||
import { Dialog } from '@headlessui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { FormInput, FormSelect } from '../forms';
|
||||
import { PencilIcon, TrashIcon } from '@heroicons/react/24/outline';
|
||||
import api from '../../services/api';
|
||||
|
||||
// Função auxiliar para retornar as cores do status
|
||||
const getStatusColor = (status: string) => {
|
||||
const colors = {
|
||||
PENDENTE: 'bg-yellow-100 text-yellow-800',
|
||||
PAGO: 'bg-green-100 text-green-800',
|
||||
VENCIDO: 'bg-red-100 text-red-800',
|
||||
CANCELADO: 'bg-gray-100 text-gray-800',
|
||||
PARCIALMENTE_PAGO: 'bg-blue-100 text-blue-800'
|
||||
};
|
||||
return colors[status] || colors.PENDENTE;
|
||||
};
|
||||
|
||||
const TIPOS_CUSTA = [
|
||||
{ value: 'TAXA_ADMINISTRATIVA', label: 'Taxa Administrativa' },
|
||||
{ value: 'RECURSO', label: 'Recurso' },
|
||||
{ value: 'DILIGENCIA', label: 'Diligência' },
|
||||
{ value: 'CERTIDAO', label: 'Certidão' },
|
||||
{ value: 'COPIA', label: 'Cópia' },
|
||||
{ value: 'OUTROS', label: 'Outros' }
|
||||
];
|
||||
|
||||
export function CustaAdministrativaPanel({ processoId }) {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [selectedCusta, setSelectedCusta] = useState(null);
|
||||
const { register, handleSubmit, reset, setValue } = useForm();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { data: custas, isLoading } = useQuery(
|
||||
['custas-administrativas', processoId],
|
||||
async () => {
|
||||
const response = await api.get(`/processos-administrativos/${processoId}/custas`);
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
|
||||
const handleEdit = (custa) => {
|
||||
setSelectedCusta(custa);
|
||||
Object.keys(custa).forEach(key => {
|
||||
if (key === 'vencimento' || key === 'dataPagamento') {
|
||||
setValue(key, custa[key] ? new Date(custa[key]).toISOString().split('T')[0] : '');
|
||||
} else {
|
||||
setValue(key, custa[key]);
|
||||
}
|
||||
});
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
const handleDelete = async (id) => {
|
||||
if (window.confirm('Tem certeza que deseja excluir esta custa?')) {
|
||||
try {
|
||||
await api.delete(`/processos-administrativos/${processoId}/custas/${id}`);
|
||||
queryClient.invalidateQueries(['custas-administrativas', processoId]);
|
||||
} catch (error) {
|
||||
console.error('Erro ao excluir custa:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
try {
|
||||
// Formatar as datas antes de enviar
|
||||
const formattedData = {
|
||||
...data,
|
||||
vencimento: data.vencimento ? new Date(data.vencimento).toISOString() : null,
|
||||
dataPagamento: data.dataPagamento ? new Date(data.dataPagamento).toISOString() : null,
|
||||
valor: Number(data.valor)
|
||||
};
|
||||
|
||||
if (selectedCusta) {
|
||||
await api.put(`/processos-administrativos/${processoId}/custas/${selectedCusta.id}`, formattedData);
|
||||
} else {
|
||||
await api.post(`/processos-administrativos/${processoId}/custas`, formattedData);
|
||||
}
|
||||
|
||||
queryClient.invalidateQueries(['custas-administrativas', processoId]);
|
||||
setIsModalOpen(false);
|
||||
setSelectedCusta(null);
|
||||
reset();
|
||||
} catch (error) {
|
||||
console.error('Erro ao salvar custa:', error);
|
||||
}
|
||||
};
|
||||
|
||||
if (isLoading) return <div>Carregando...</div>;
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<h3 className="text-lg font-medium">Custas e Despesas</h3>
|
||||
<button
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
className="px-4 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded-lg"
|
||||
>
|
||||
Nova Custa
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-gray-300">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Tipo</th>
|
||||
<th className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Descrição</th>
|
||||
<th className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Valor</th>
|
||||
<th className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Status</th>
|
||||
<th className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Vencimento</th>
|
||||
<th className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Ações</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200 bg-white">
|
||||
{custas?.map((custa) => (
|
||||
<tr key={custa.id}>
|
||||
<td className="px-3 py-4 text-sm text-gray-900">{custa.tipo}</td>
|
||||
<td className="px-3 py-4 text-sm text-gray-500">{custa.descricao}</td>
|
||||
<td className="px-3 py-4 text-sm text-gray-900">{formatCurrency(custa.valor)}</td>
|
||||
<td className="px-3 py-4 text-sm">
|
||||
<span className={`px-2 py-1 rounded-full text-xs ${getStatusColor(custa.status)}`}>
|
||||
{custa.status}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-4 text-sm text-gray-500">
|
||||
{custa.vencimento ? new Date(custa.vencimento).toLocaleDateString() : '-'}
|
||||
</td>
|
||||
<td className="px-3 py-4 text-sm">
|
||||
<div className="flex space-x-2">
|
||||
<button
|
||||
onClick={() => handleEdit(custa)}
|
||||
className="text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
<PencilIcon className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleDelete(custa.id)}
|
||||
className="text-red-600 hover:text-red-800"
|
||||
>
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* Modal de Custa */}
|
||||
<Dialog open={isModalOpen} onClose={() => {
|
||||
setIsModalOpen(false);
|
||||
setSelectedCusta(null);
|
||||
reset();
|
||||
}}>
|
||||
<div className="fixed inset-0 bg-black/30" aria-hidden="true" />
|
||||
|
||||
<div className="fixed inset-0 flex items-center justify-center p-4">
|
||||
<Dialog.Panel className="mx-auto max-w-2xl w-full bg-white rounded-xl p-6">
|
||||
<Dialog.Title className="text-lg font-semibold mb-4">
|
||||
{selectedCusta ? 'Editar Custa' : 'Nova Custa'}
|
||||
</Dialog.Title>
|
||||
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<FormSelect
|
||||
label="Tipo"
|
||||
required
|
||||
{...register("tipo")}
|
||||
options={TIPOS_CUSTA}
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
label="Valor"
|
||||
type="number"
|
||||
step="0.01"
|
||||
required
|
||||
{...register("valor")}
|
||||
/>
|
||||
|
||||
<div className="col-span-2">
|
||||
<FormInput
|
||||
label="Descrição"
|
||||
required
|
||||
{...register("descricao")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<FormSelect
|
||||
label="Status"
|
||||
{...register("status")}
|
||||
options={[
|
||||
{ value: 'PENDENTE', label: 'Pendente' },
|
||||
{ value: 'PAGO', label: 'Pago' },
|
||||
{ value: 'VENCIDO', label: 'Vencido' },
|
||||
{ value: 'CANCELADO', label: 'Cancelado' }
|
||||
]}
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
label="Vencimento"
|
||||
type="date"
|
||||
{...register("vencimento")}
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
label="Data Pagamento"
|
||||
type="date"
|
||||
{...register("dataPagamento")}
|
||||
/>
|
||||
|
||||
<div className="col-span-2">
|
||||
<FormInput
|
||||
label="Observações"
|
||||
multiline
|
||||
{...register("observacoes")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end space-x-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setIsModalOpen(false);
|
||||
setSelectedCusta(null);
|
||||
reset();
|
||||
}}
|
||||
className="px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 rounded-md"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-md"
|
||||
>
|
||||
Salvar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</Dialog.Panel>
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user