diff --git a/susconecta/app/(main-routes)/calendar/page.tsx b/susconecta/app/(main-routes)/calendar/page.tsx
index bed1d79..0509adf 100644
--- a/susconecta/app/(main-routes)/calendar/page.tsx
+++ b/susconecta/app/(main-routes)/calendar/page.tsx
@@ -93,11 +93,15 @@ export default function AgendamentoPage() {
const threeDEvents: CalendarEvent[] = (arr || []).map((obj: any) => {
const scheduled = obj.scheduled_at || obj.scheduledAt || obj.time || null;
const patient = (patientsById[String(obj.patient_id)]?.full_name) || obj.patient_name || obj.patient_full_name || obj.patient || 'Paciente';
- const title = `${patient}: ${obj.appointment_type ?? obj.type ?? ''}`.trim();
+ const appointmentType = obj.appointment_type ?? obj.type ?? 'Consulta';
+ const title = `${patient}: ${appointmentType}`.trim();
return {
id: obj.id || String(Date.now()),
title,
date: scheduled ? new Date(scheduled).toISOString() : new Date().toISOString(),
+ status: obj.status || 'pending',
+ patient,
+ type: appointmentType,
};
});
setThreeDEvents(threeDEvents);
@@ -225,7 +229,7 @@ export default function AgendamentoPage() {
/>
) : activeTab === "3d" ? (
-
+
(new Date())
const [title, setTitle] = React.useState("")
const [newDate, setNewDate] = React.useState("")
+ const [selectedDay, setSelectedDay] = React.useState(null)
+ const [isDialogOpen, setIsDialogOpen] = React.useState(false)
const wallRef = React.useRef(null)
// 3D tilt state
@@ -44,6 +50,7 @@ export function ThreeDWallCalendar({
const [tiltY, setTiltY] = React.useState(0)
const isDragging = React.useRef(false)
const dragStart = React.useRef<{ x: number; y: number } | null>(null)
+ const hasDragged = React.useRef(false)
// month days
const days = eachDayOfInterval({
@@ -54,6 +61,16 @@ export function ThreeDWallCalendar({
const eventsForDay = (d: Date) =>
events.filter((ev) => format(new Date(ev.date), "yyyy-MM-dd") === format(d, "yyyy-MM-dd"))
+ const selectedDayEvents = selectedDay ? eventsForDay(selectedDay) : []
+
+ const handleDayClick = (day: Date) => {
+ // Só abre o dialog se não foi um drag
+ if (!hasDragged.current) {
+ setSelectedDay(day)
+ setIsDialogOpen(true)
+ }
+ }
+
// Add event handler
const handleAdd = () => {
if (!title.trim() || !newDate) return
@@ -75,18 +92,26 @@ export function ThreeDWallCalendar({
// drag tilt
const onPointerDown = (e: React.PointerEvent) => {
isDragging.current = true
+ hasDragged.current = false
dragStart.current = { x: e.clientX, y: e.clientY }
- ;(e.currentTarget as Element).setPointerCapture(e.pointerId) // ✅ Correct element
+ ;(e.currentTarget as Element).setPointerCapture(e.pointerId)
}
const onPointerMove = (e: React.PointerEvent) => {
if (!isDragging.current || !dragStart.current) return
const dx = e.clientX - dragStart.current.x
const dy = e.clientY - dragStart.current.y
+
+ // Se moveu mais de 5 pixels, considera como drag
+ if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
+ hasDragged.current = true
+ }
+
setTiltY((t) => Math.max(-60, Math.min(60, t + dx * 0.1)))
setTiltX((t) => Math.max(0, Math.min(60, t - dy * 0.1)))
dragStart.current = { x: e.clientX, y: e.clientY }
}
+
const onPointerUp = () => {
isDragging.current = false
dragStart.current = null
@@ -98,27 +123,53 @@ export function ThreeDWallCalendar({
return (
-
-
-
{format(dateRef, "MMMM yyyy", { locale: ptBR })}
-
+
+
+
+
{format(dateRef, "MMMM yyyy", { locale: ptBR })}
+
+
+
+ {/* Legenda de cores */}
+
{/* Wall container */}
-
+
+
+ 💡 Arraste para rotacionar • Scroll para inclinar
+
+
handleDayClick(day)}
>
-
-
-
-
{format(day, "d")}
-
{format(day, "EEE", { locale: ptBR })}
+
+
+
+
{format(day, "d")}
+
+ {dayEvents.length > 0 && `${dayEvents.length} ${dayEvents.length === 1 ? 'paciente' : 'pacientes'}`}
+
+ {format(day, "EEE", { locale: ptBR })}
{/* events */}
-
+
{dayEvents.map((ev, i) => {
- const left = 8 + (i * 34) % (panelWidth - 40)
- const top = 8 + Math.floor((i * 34) / (panelWidth - 40)) * 28
+ // Calcular tamanho da bolinha baseado na quantidade de eventos
+ const eventCount = dayEvents.length
+ const ballSize = eventCount <= 3 ? 20 :
+ eventCount <= 6 ? 16 :
+ eventCount <= 10 ? 14 :
+ eventCount <= 15 ? 12 : 10
+
+ const spacing = ballSize + 4
+ const maxPerRow = Math.floor((panelWidth - 16) / spacing)
+ const col = i % maxPerRow
+ const row = Math.floor(i / maxPerRow)
+ const left = 4 + (col * spacing)
+ const top = 4 + (row * spacing)
+
+ // Cores baseadas no status
+ const getStatusColor = () => {
+ switch(ev.status) {
+ case 'confirmed': return 'bg-green-500 dark:bg-green-600'
+ case 'pending': return 'bg-yellow-500 dark:bg-yellow-600'
+ case 'cancelled': return 'bg-red-500 dark:bg-red-600'
+ default: return 'bg-blue-500 dark:bg-blue-600'
+ }
+ }
+
return (
-
-
-
-
-
+
+
+ •
+
+
+
+
+
{ev.title}
+ {ev.patient && ev.type && (
+
+
Paciente: {ev.patient}
+
Tipo: {ev.type}
+
+ )}
+
+ {format(new Date(ev.date), "PPP 'às' p", { locale: ptBR })}
+
+ {ev.status && (
+
+ Status:{' '}
+
+ {ev.status === 'confirmed' ? 'Confirmado' :
+ ev.status === 'pending' ? 'Pendente' :
+ ev.status === 'cancelled' ? 'Cancelado' : ev.status}
+
+
+ )}
+ {onRemoveEvent && (
+
-
-
- {ev.title}
-
-
-
-
-
-
-
-
{ev.title}
-
- {format(new Date(ev.date), "PPP p", { locale: ptBR })}
-
-
- {onRemoveEvent && (
-
- )}
-
-
-
-
+
+ Remover
+
+ )}
+
+
+
)
})}
-
-
- {dayEvents.length} evento(s)
-
@@ -220,13 +311,101 @@ export function ThreeDWallCalendar({
})}
+
+ {/* Dialog de detalhes do dia */}
+
+
{/* Add event form */}
- setTitle(e.target.value)} />
+ setTitle(e.target.value)} />
setNewDate(e.target.value)} />
-
+
)