forked from RiseUP/riseup-squad20
ajuste no calendario
This commit is contained in:
parent
2729fdc868
commit
93e7b20390
@ -72,11 +72,6 @@ export function EventManager({
|
|||||||
availableTags = ["Important", "Urgent", "Work", "Personal", "Team", "Client"],
|
availableTags = ["Important", "Urgent", "Work", "Personal", "Team", "Client"],
|
||||||
}: EventManagerProps) {
|
}: EventManagerProps) {
|
||||||
const [events, setEvents] = useState<Event[]>(initialEvents)
|
const [events, setEvents] = useState<Event[]>(initialEvents)
|
||||||
// controla dias expandidos no MonthView (key = YYYY-MM-DD)
|
|
||||||
const [expandedDays, setExpandedDays] = useState<Record<string, boolean>>({})
|
|
||||||
const toggleExpandedDay = useCallback((dayKey: string) => {
|
|
||||||
setExpandedDays((prev) => ({ ...prev, [dayKey]: !prev[dayKey] }))
|
|
||||||
}, [])
|
|
||||||
const [currentDate, setCurrentDate] = useState(new Date())
|
const [currentDate, setCurrentDate] = useState(new Date())
|
||||||
const [view, setView] = useState<"month" | "week" | "day" | "list">(defaultView)
|
const [view, setView] = useState<"month" | "week" | "day" | "list">(defaultView)
|
||||||
const [selectedEvent, setSelectedEvent] = useState<Event | null>(null)
|
const [selectedEvent, setSelectedEvent] = useState<Event | null>(null)
|
||||||
@ -96,6 +91,16 @@ export function EventManager({
|
|||||||
const [selectedTags, setSelectedTags] = useState<string[]>([])
|
const [selectedTags, setSelectedTags] = useState<string[]>([])
|
||||||
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
|
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
|
||||||
|
|
||||||
|
// Dialog: lista completa de pacientes do dia
|
||||||
|
const [dayDialogEvents, setDayDialogEvents] = useState<Event[] | null>(null)
|
||||||
|
const [isDayDialogOpen, setIsDayDialogOpen] = useState(false)
|
||||||
|
const openDayDialog = useCallback((eventsForDay: Event[]) => {
|
||||||
|
// ordena por horário antes de abrir
|
||||||
|
const ordered = [...eventsForDay].sort((a, b) => a.startTime.getTime() - b.startTime.getTime())
|
||||||
|
setDayDialogEvents(ordered)
|
||||||
|
setIsDayDialogOpen(true)
|
||||||
|
}, [])
|
||||||
|
|
||||||
const filteredEvents = useMemo(() => {
|
const filteredEvents = useMemo(() => {
|
||||||
return events.filter((event) => {
|
return events.filter((event) => {
|
||||||
// Search filter
|
// Search filter
|
||||||
@ -707,11 +712,49 @@ export function EventManager({
|
|||||||
onDragEnd={() => handleDragEnd()}
|
onDragEnd={() => handleDragEnd()}
|
||||||
onDrop={handleDrop}
|
onDrop={handleDrop}
|
||||||
getColorClasses={getColorClasses}
|
getColorClasses={getColorClasses}
|
||||||
expandedDays={expandedDays}
|
openDayDialog={openDayDialog}
|
||||||
toggleExpandedDay={toggleExpandedDay}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Dialog com todos os pacientes do dia */}
|
||||||
|
<Dialog open={isDayDialogOpen} onOpenChange={setIsDayDialogOpen}>
|
||||||
|
<DialogContent className="max-w-lg max-h-[80vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Pacientes do dia</DialogTitle>
|
||||||
|
<DialogDescription>Todos os agendamentos do dia selecionado.</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="space-y-3 py-2">
|
||||||
|
{dayDialogEvents?.map((ev) => (
|
||||||
|
<div key={ev.id} className="flex items-start gap-3 p-2 border-b last:border-b-0">
|
||||||
|
<div className={cn("mt-1 h-3 w-3 rounded-full", getColorClasses(ev.color).bg)} />
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
<div className="font-semibold truncate">{ev.title}</div>
|
||||||
|
<div className="text-xs text-muted-foreground">
|
||||||
|
{ev.startTime.toLocaleTimeString("pt-BR",{hour:"2-digit",minute:"2-digit"})}
|
||||||
|
{" - "}
|
||||||
|
{ev.endTime.toLocaleTimeString("pt-BR",{hour:"2-digit",minute:"2-digit"})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{ev.description && (
|
||||||
|
<div className="text-xs text-muted-foreground line-clamp-2">{ev.description}</div>
|
||||||
|
)}
|
||||||
|
<div className="mt-1 flex flex-wrap gap-1">
|
||||||
|
{ev.category && <Badge variant="secondary" className="text-[11px] h-5">{ev.category}</Badge>}
|
||||||
|
{ev.tags?.map((t) => (
|
||||||
|
<Badge key={t} variant="outline" className="text-[11px] h-5">{t}</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{!dayDialogEvents?.length && (
|
||||||
|
<div className="py-6 text-center text-sm text-muted-foreground">Nenhum evento</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
{view === "week" && (
|
{view === "week" && (
|
||||||
<WeekView
|
<WeekView
|
||||||
currentDate={currentDate}
|
currentDate={currentDate}
|
||||||
@ -1151,8 +1194,7 @@ function MonthView({
|
|||||||
onDragEnd,
|
onDragEnd,
|
||||||
onDrop,
|
onDrop,
|
||||||
getColorClasses,
|
getColorClasses,
|
||||||
expandedDays,
|
openDayDialog,
|
||||||
toggleExpandedDay,
|
|
||||||
}: {
|
}: {
|
||||||
currentDate: Date
|
currentDate: Date
|
||||||
events: Event[]
|
events: Event[]
|
||||||
@ -1161,8 +1203,7 @@ function MonthView({
|
|||||||
onDragEnd: () => void
|
onDragEnd: () => void
|
||||||
onDrop: (date: Date) => void
|
onDrop: (date: Date) => void
|
||||||
getColorClasses: (color: string) => { bg: string; text: string }
|
getColorClasses: (color: string) => { bg: string; text: string }
|
||||||
expandedDays: Record<string, boolean>
|
openDayDialog: (eventsForDay: Event[]) => void
|
||||||
toggleExpandedDay: (dayKey: string) => void
|
|
||||||
}) {
|
}) {
|
||||||
const firstDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1)
|
const firstDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1)
|
||||||
const lastDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0)
|
const lastDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0)
|
||||||
@ -1188,9 +1229,6 @@ function MonthView({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const formatTime = (date: Date) =>
|
|
||||||
date.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="overflow-hidden">
|
<Card className="overflow-hidden">
|
||||||
<div className="grid grid-cols-7 border-b">
|
<div className="grid grid-cols-7 border-b">
|
||||||
@ -1204,6 +1242,15 @@ function MonthView({
|
|||||||
<div className="grid grid-cols-7">
|
<div className="grid grid-cols-7">
|
||||||
{days.map((day, index) => {
|
{days.map((day, index) => {
|
||||||
const dayEvents = getEventsForDay(day)
|
const dayEvents = getEventsForDay(day)
|
||||||
|
// dedup por título para evitar repetidos
|
||||||
|
const uniqueMap = new Map<string, Event>()
|
||||||
|
dayEvents.forEach((ev) => {
|
||||||
|
const k = (ev.title || "").trim().toLowerCase()
|
||||||
|
if (!uniqueMap.has(k)) uniqueMap.set(k, ev)
|
||||||
|
})
|
||||||
|
const uniqueEvents = Array.from(uniqueMap.values())
|
||||||
|
const eventsToShow = uniqueEvents.slice(0, 3)
|
||||||
|
const moreCount = Math.max(0, uniqueEvents.length - 3)
|
||||||
const isCurrentMonth = day.getMonth() === currentDate.getMonth()
|
const isCurrentMonth = day.getMonth() === currentDate.getMonth()
|
||||||
const isToday = day.toDateString() === new Date().toDateString()
|
const isToday = day.toDateString() === new Date().toDateString()
|
||||||
|
|
||||||
@ -1218,16 +1265,11 @@ function MonthView({
|
|||||||
onDragOver={(e) => e.preventDefault()}
|
onDragOver={(e) => e.preventDefault()}
|
||||||
onDrop={() => onDrop(day)}
|
onDrop={() => onDrop(day)}
|
||||||
>
|
>
|
||||||
<div
|
{/* Número do dia padronizado (sem destaque azul no 'hoje') */}
|
||||||
className={cn(
|
<div className="mb-1 text-xs sm:text-sm">{day.getDate()}</div>
|
||||||
"mb-1 flex h-5 w-5 items-center justify-center rounded-full text-xs sm:h-6 sm:w-6 sm:text-sm",
|
|
||||||
isToday && "bg-primary text-primary-foreground font-semibold",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{day.getDate()}
|
|
||||||
</div>
|
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{dayEvents.slice(0, 3).map((event) => (
|
{eventsToShow.map((event) => (
|
||||||
<EventCard
|
<EventCard
|
||||||
key={event.id}
|
key={event.id}
|
||||||
event={event}
|
event={event}
|
||||||
@ -1238,48 +1280,24 @@ function MonthView({
|
|||||||
variant="compact"
|
variant="compact"
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{dayEvents.length > 3 && (
|
{moreCount > 0 && (
|
||||||
<div className="text-[10px] text-muted-foreground sm:text-xs">+{dayEvents.length - 3} mais</div>
|
<div className="text-[10px] sm:text-xs">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => openDayDialog(uniqueEvents)}
|
||||||
|
className="text-primary underline"
|
||||||
|
>
|
||||||
|
+{moreCount} mais
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{(() => {
|
</div>
|
||||||
const dayKey = day.toISOString().slice(0, 10)
|
</div>
|
||||||
const isExpanded = !!expandedDays?.[dayKey]
|
)
|
||||||
const eventsToShow = isExpanded ? dayEvents : dayEvents.slice(0, 3)
|
})}
|
||||||
return (
|
</div>
|
||||||
<>
|
</Card>
|
||||||
{eventsToShow.map((event) => (
|
)
|
||||||
<EventCard
|
|
||||||
key={event.id}
|
|
||||||
event={event}
|
|
||||||
onEventClick={onEventClick}
|
|
||||||
onDragStart={onDragStart}
|
|
||||||
onDragEnd={onDragEnd}
|
|
||||||
getColorClasses={getColorClasses}
|
|
||||||
variant="compact"
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{dayEvents.length > 3 && (
|
|
||||||
<div className="text-[10px] text-muted-foreground sm:text-xs">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => toggleExpandedDay(dayKey)}
|
|
||||||
className="text-primary underline hover:text-primary/80"
|
|
||||||
>
|
|
||||||
{isExpanded ? "Mostrar menos" : `+${dayEvents.length - 3} mais`}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
})()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Week View Component
|
// Week View Component
|
||||||
@ -1343,7 +1361,7 @@ function WeekView({
|
|||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-8">
|
<div className="grid grid-cols-8">
|
||||||
{hours.map((hour) => (
|
{hours.map((hour) => (
|
||||||
<>
|
<React.Fragment key={`hour-${hour}`}>
|
||||||
<div
|
<div
|
||||||
key={`time-${hour}`}
|
key={`time-${hour}`}
|
||||||
className="border-b border-r p-1 text-[10px] text-muted-foreground sm:p-2 sm:text-xs"
|
className="border-b border-r p-1 text-[10px] text-muted-foreground sm:p-2 sm:text-xs"
|
||||||
@ -1375,7 +1393,7 @@ function WeekView({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user