first commit

This commit is contained in:
rodrigo committed 2025-04-10 23:07:21 -03:00
commit c9fb67e751
423 files changed
+53287

No files matched your search

+152
View File
@@ -0,0 +1,152 @@
import React from 'react';
import { Tarefa } from '../../types/entities';
import { format } from 'date-fns';
import { ptBR } from 'date-fns/locale';
import { PencilIcon, CheckIcon, XMarkIcon, ExclamationTriangleIcon, TrashIcon } from '@heroicons/react/24/outline';
import { useAuth } from '../../contexts/AuthContext';
import { useTarefas } from '../../hooks/useTarefas';
interface TarefaCardProps {
tarefa: Tarefa;
onEdit: (tarefa: Tarefa) => void;
onStatusChange: (id: string, status: string, progresso?: number) => void;
}
export const TarefaCard: React.FC<TarefaCardProps> = ({ tarefa, onEdit, onStatusChange }) => {
const { user } = useAuth();
const { deleteTarefa } = useTarefas();
const canDelete = user && ['ADVOGADO_ADMIN', 'ADVOGADO'].includes(user.perfil);
const handleDelete = async (e: React.MouseEvent) => {
e.stopPropagation();
if (!window.confirm('Tem certeza que deseja excluir esta tarefa?')) return;
try {
await deleteTarefa.mutateAsync(tarefa.id);
} catch (error) {
console.error('Erro ao excluir tarefa:', error);
alert('Erro ao excluir tarefa');
}
};
const getPrioridadeColor = () => {
switch (tarefa.prioridade) {
case 'BAIXA': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200';
case 'MEDIA': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200';
case 'ALTA': return 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200';
case 'URGENTE': return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';
}
};
return (
<div className="bg-white dark:bg-gray-700 rounded-lg shadow p-4">
<div className="flex justify-between items-start mb-3">
<h3 className="text-gray-900 dark:text-white font-medium">
{tarefa.titulo}
</h3>
<div className="flex items-center space-x-2">
<button
onClick={() => onEdit(tarefa)}
className="text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300"
title="Editar tarefa"
>
<PencilIcon className="h-5 w-5" />
</button>
<span className={`px-2 py-1 text-xs rounded-full ${getPrioridadeColor()}`}>
{tarefa.prioridade}
</span>
</div>
</div>
<p className="mt-2 text-sm text-gray-600 dark:text-gray-300 line-clamp-2">
{tarefa.descricao}
</p>
<div className="mt-4">
<div className="w-full bg-gray-200 dark:bg-gray-600 rounded-full h-2">
<div
className="bg-blue-600 h-2 rounded-full"
style={{ width: `${tarefa.progresso}%` }}
/>
</div>
</div>
<div className="mt-4 flex items-center justify-between text-sm">
<div className="flex items-center space-x-4">
<div className="flex -space-x-2">
{tarefa.subtarefas.map((subtarefa, index) => (
<div
key={subtarefa.id}
className={`h-6 w-6 rounded-full flex items-center justify-center text-xs
${subtarefa.concluida
? 'bg-green-100 text-green-600 dark:bg-green-900 dark:text-green-200'
: 'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400'}`}
>
{subtarefa.concluida ? <CheckIcon className="h-3 w-3" /> : index + 1}
</div>
))}
</div>
<span className="text-gray-500 dark:text-gray-400">
{format(new Date(tarefa.dataVencimento), "dd/MM/yyyy", { locale: ptBR })}
</span>
</div>
<button
onClick={(e) => {
e.stopPropagation();
onEdit(tarefa);
}}
className="text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300"
>
<PencilIcon className="h-4 w-4" />
</button>
</div>
<div className="mt-4 flex items-center justify-between">
<div className="flex space-x-2">
{tarefa.status !== 'CONCLUIDA' && tarefa.status !== 'CANCELADA' && (
<>
<button
onClick={() => onStatusChange(tarefa.id, 'CONCLUIDA', 100)}
className="p-2 text-green-600 hover:bg-green-50 rounded-lg"
title="Concluir tarefa"
>
<CheckIcon className="h-5 w-5" />
</button>
<button
onClick={() => onStatusChange(tarefa.id, 'CANCELADA', 0)}
className="p-2 text-red-600 hover:bg-red-50 rounded-lg"
title="Cancelar tarefa"
>
<XMarkIcon className="h-5 w-5" />
</button>
<button
onClick={() => {
const novoProgresso = prompt('Digite o percentual de conclusão (0-100):', tarefa.progresso?.toString());
if (novoProgresso !== null) {
const progresso = Math.min(100, Math.max(0, parseInt(novoProgresso)));
onStatusChange(tarefa.id, 'EM_ANDAMENTO', progresso);
}
}}
className="p-2 text-yellow-600 hover:bg-yellow-50 rounded-lg"
title="Atualizar progresso"
>
<ExclamationTriangleIcon className="h-5 w-5" />
</button>
</>
)}
{canDelete && (
<button
onClick={handleDelete}
className="p-2 text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg"
title="Excluir tarefa"
>
<TrashIcon className="h-5 w-5" />
</button>
)}
</div>
</div>
</div>
);
};