fix atendimentos.ts
Signed-off-by: Rodrigo Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
1 parent
ea0481e09e
commit
3763229e0a
2 files changed
+232
-143
No files matched your search
@@ -0,0 +1,120 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { Calendar } from '@fullcalendar/react';
|
||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||
import interactionPlugin from '@fullcalendar/interaction';
|
||||
import ptBrLocale from '@fullcalendar/core/locales/pt-br';
|
||||
import { format } from 'date-fns';
|
||||
import { api } from '../services/api';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
interface Agendamento {
|
||||
id: string;
|
||||
data: string;
|
||||
observacoes?: string;
|
||||
status: string;
|
||||
cliente: {
|
||||
id: string;
|
||||
nome: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CalendarEvent {
|
||||
id: string;
|
||||
title: string;
|
||||
start: string;
|
||||
end: string;
|
||||
backgroundColor?: string;
|
||||
borderColor?: string;
|
||||
extendedProps: {
|
||||
agendamento: Agendamento;
|
||||
};
|
||||
}
|
||||
|
||||
interface AgendamentoCalendarioProps {
|
||||
onEventClick?: (event: any) => void;
|
||||
onDateSelect?: (selectInfo: any) => void;
|
||||
}
|
||||
|
||||
export const AgendamentoCalendario: React.FC<AgendamentoCalendarioProps> = ({
|
||||
onEventClick,
|
||||
onDateSelect
|
||||
}) => {
|
||||
const [eventos, setEventos] = useState<CalendarEvent[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const formatEventos = useCallback((agendamentos: Agendamento[]): CalendarEvent[] => {
|
||||
return agendamentos.map(ag => ({
|
||||
id: ag.id,
|
||||
title: `${ag.cliente.nome} ${ag.observacoes ? `- ${ag.observacoes}` : ''}`,
|
||||
start: ag.data,
|
||||
end: ag.data,
|
||||
backgroundColor: ag.status === 'CANCELADO' ? '#FEE2E2' : '#E0F2FE',
|
||||
borderColor: ag.status === 'CANCELADO' ? '#EF4444' : '#0EA5E9',
|
||||
extendedProps: {
|
||||
agendamento: ag
|
||||
}
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const loadAgendamentos = useCallback(async ({ start, end }: { start: Date, end: Date }) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const response = await api.get('/atendimentos/agendamentos', {
|
||||
params: {
|
||||
inicio: format(start, 'yyyy-MM-dd'),
|
||||
fim: format(end, 'yyyy-MM-dd')
|
||||
}
|
||||
});
|
||||
|
||||
setEventos(formatEventos(response.data));
|
||||
} catch (err: any) {
|
||||
const mensagem = err.response?.data?.error || 'Erro ao carregar agendamentos';
|
||||
setError(mensagem);
|
||||
toast.error(mensagem);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [formatEventos]);
|
||||
|
||||
return (
|
||||
<div className="relative h-full">
|
||||
{loading && (
|
||||
<div className="absolute inset-0 bg-white/50 flex items-center justify-center z-10">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="absolute top-0 left-0 right-0 p-4 bg-red-100 text-red-700">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Calendar
|
||||
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
|
||||
initialView="dayGridMonth"
|
||||
locale={ptBrLocale}
|
||||
events={eventos}
|
||||
editable={false}
|
||||
selectable={true}
|
||||
selectMirror={true}
|
||||
dayMaxEvents={3}
|
||||
weekends={true}
|
||||
datesSet={({ start, end }) => loadAgendamentos({ start, end })}
|
||||
eventClick={({ event }) => onEventClick?.(event)}
|
||||
select={(selectInfo) => onDateSelect?.(selectInfo)}
|
||||
headerToolbar={{
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'dayGridMonth,timeGridWeek,timeGridDay'
|
||||
}}
|
||||
slotMinTime="08:00:00"
|
||||
slotMaxTime="18:00:00"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user