feat: Adiciona EventManager e conecta à API de agendamentos

This commit is contained in:
Jonas Francisco 2025-10-31 01:43:20 -03:00
parent fbdeb7e462
commit ac66a68c04
4 changed files with 299 additions and 71 deletions

View File

@ -38,6 +38,7 @@ export default function AgendamentoPage() {
// --- NOVO ESTADO ---
// Estado para alimentar o NOVO EventManager com dados da API
const [managerEvents, setManagerEvents] = useState<Event[]>([]);
const [managerLoading, setManagerLoading] = useState<boolean>(true);
useEffect(() => {
document.addEventListener("keydown", (event) => {
@ -57,6 +58,7 @@ export default function AgendamentoPage() {
let mounted = true;
(async () => {
try {
setManagerLoading(true);
const api = await import('@/lib/api');
const arr = await api.listarAgendamentos('select=*&order=scheduled_at.desc&limit=500').catch(() => []);
if (!mounted) return;
@ -64,6 +66,7 @@ export default function AgendamentoPage() {
setAppointments([]);
setThreeDEvents([]);
setManagerEvents([]); // Limpa o novo calendário
setManagerLoading(false);
return;
}
@ -98,6 +101,7 @@ export default function AgendamentoPage() {
};
});
setManagerEvents(newManagerEvents);
setManagerLoading(false);
// --- FIM DA LÓGICA ---
// Convert to 3D calendar events (MANTIDO 100%)
@ -121,6 +125,7 @@ export default function AgendamentoPage() {
setAppointments([]);
setThreeDEvents([]);
setManagerEvents([]); // Limpa o novo calendário
setManagerLoading(false);
}
})();
return () => { mounted = false; };
@ -216,9 +221,19 @@ export default function AgendamentoPage() {
{/* --- AQUI ESTÁ A SUBSTITUIÇÃO --- */}
{activeTab === "calendar" ? (
<div className="flex w-full">
{/* O FullCalendar foi substituído pelo EventManager,
agora alimentado pelo estado dinâmico 'managerEvents' */}
<EventManager events={managerEvents} />
{/* mostra loading até managerEvents ser preenchido (API integrada desde a entrada) */}
<div className="w-full">
{managerLoading ? (
<div className="flex items-center justify-center w-full min-h-[70vh]">
<div className="text-sm text-muted-foreground">Conectando ao calendário carregando agendamentos...</div>
</div>
) : (
// EventManager ocupa a área principal e já recebe events da API
<div className="w-full min-h-[70vh]">
<EventManager events={managerEvents} className="compact-event-manager" />
</div>
)}
</div>
</div>
) : activeTab === "3d" ? (
// O calendário 3D (ThreeDWallCalendar) foi MANTIDO 100%

View File

@ -0,0 +1,118 @@
import React, { useState, useCallback, useMemo } from "react";
import { EventCard } from "./EventCard";
import { Card } from "@/components/ui/card";
// Types
import { Event } from "@/components/event-manager";
// Week View Component
export function WeekView({
currentDate,
events,
onEventClick,
onDragStart,
onDragEnd,
onDrop,
getColorClasses,
}: {
currentDate: Date;
events: Event[];
onEventClick: (event: Event) => void;
onDragStart: (event: Event) => void;
onDragEnd: () => void;
onDrop: (date: Date, hour: number) => void;
getColorClasses: (color: string) => { bg: string; text: string };
}) {
const startOfWeek = new Date(currentDate);
startOfWeek.setDate(currentDate.getDay());
const weekDays = Array.from({ length: 7 }, (_, i) => {
const day = new Date(startOfWeek);
day.setDate(startOfWeek.getDate() + i);
return day;
});
const hours = Array.from({ length: 24 }, (_, i) => i);
const getEventsForDayAndHour = (date: Date, hour: number) => {
return events.filter((event) => {
const eventDate = new Date(event.startTime);
const eventHour = eventDate.getHours();
return (
eventDate.getDate() === date.getDate() &&
eventDate.getMonth() === date.getMonth() &&
eventDate.getFullYear() === date.getFullYear() &&
eventHour === hour
);
});
};
// dias da semana em pt-BR (abreviações)
const weekDayNames = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"];
return (
<Card className="overflow-auto">
<div className="grid grid-cols-8 border-b">
<div className="border-r p-2 text-center text-xs font-medium sm:text-sm">
Hora
</div>
{weekDays.map((day) => (
<div
key={day.toISOString()}
className="border-r p-2 text-center text-xs font-medium last:border-r-0 sm:text-sm"
>
<div className="hidden sm:block">
{day.toLocaleDateString("pt-BR", { weekday: "short" })}
</div>
<div className="sm:hidden">
{day.toLocaleDateString("pt-BR", { weekday: "narrow" })}
</div>
<div className="text-[10px] text-muted-foreground sm:text-xs">
{day.toLocaleDateString("pt-BR", {
month: "short",
day: "numeric",
})}
</div>
</div>
))}
</div>
<div className="grid grid-cols-8">
{hours.map((hour) => (
<React.Fragment key={`hour-${hour}`}>
<div
key={`time-${hour}`}
className="border-b border-r p-1 text-[10px] text-muted-foreground sm:p-2 sm:text-xs"
>
{hour.toString().padStart(2, "0")}:00
</div>
{weekDays.map((day) => {
const dayEvents = getEventsForDayAndHour(day, hour);
return (
<div
key={`${day.toISOString()}-${hour}`}
className="min-h-12 border-b border-r p-0.5 transition-colors hover:bg-accent/50 last:border-r-0 sm:min-h-16 sm:p-1"
onDragOver={(e) => e.preventDefault()}
onDrop={() => onDrop(day, hour)}
>
<div className="space-y-1">
{dayEvents.map((event) => (
<EventCard
key={event.id}
event={event}
onEventClick={onEventClick}
onDragStart={onDragStart}
onDragEnd={onDragEnd}
getColorClasses={getColorClasses}
variant="default"
/>
))}
</div>
</div>
);
})}
</React.Fragment>
))}
</div>
</Card>
);
}

View File

@ -0,0 +1,103 @@
import React, { useState } from "react";
import { Event } from "@/components/event-manager";
import { cn } from "@/lib/utils";
/*
Componente leve para representar um evento no calendário.
Compatível com o uso em Calendar.tsx (WeekView / DayView).
*/
export function EventCard({
event,
onEventClick,
onDragStart,
onDragEnd,
getColorClasses,
variant = "default",
}: {
event: Event;
onEventClick: (e: Event) => void;
onDragStart: (e: Event) => void;
onDragEnd: () => void;
getColorClasses: (color: string) => { bg: string; text: string };
variant?: "default" | "compact" | "detailed";
}) {
const [hover, setHover] = useState(false);
const color = getColorClasses?.(event.color) ?? { bg: "bg-slate-400", text: "text-white" };
const handleDragStart = (e: React.DragEvent) => {
e.dataTransfer.setData("text/plain", event.id);
onDragStart && onDragStart(event);
};
const handleClick = () => {
onEventClick && onEventClick(event);
};
if (variant === "compact") {
return (
<div
draggable
onDragStart={handleDragStart}
onDragEnd={() => onDragEnd && onDragEnd()}
onClick={handleClick}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
className={cn(
"rounded px-2 py-0.5 text-xs font-medium truncate",
color.bg,
color.text,
"cursor-pointer transition-all",
hover && "shadow-md scale-105"
)}
>
{event.title}
</div>
);
}
if (variant === "detailed") {
return (
<div
draggable
onDragStart={handleDragStart}
onDragEnd={() => onDragEnd && onDragEnd()}
onClick={handleClick}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
className={cn(
"rounded-lg p-2 text-sm cursor-pointer transition-all",
color.bg,
color.text,
hover && "shadow-lg scale-[1.02]"
)}
>
<div className="font-semibold">{event.title}</div>
{event.description && <div className="text-xs opacity-90 mt-1 line-clamp-2">{event.description}</div>}
<div className="mt-1 text-[11px] opacity-80">
{event.startTime?.toLocaleTimeString?.("pt-BR", { hour: "2-digit", minute: "2-digit" }) ?? ""} - {event.endTime?.toLocaleTimeString?.("pt-BR", { hour: "2-digit", minute: "2-digit" }) ?? ""}
</div>
</div>
);
}
// default
return (
<div
draggable
onDragStart={handleDragStart}
onDragEnd={() => onDragEnd && onDragEnd()}
onClick={handleClick}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
className={cn(
"relative rounded px-2 py-1 text-xs font-medium cursor-pointer transition-all",
color.bg,
color.text,
hover && "shadow-md scale-105"
)}
>
<div className="truncate">{event.title}</div>
</div>
);
}

View File

@ -1,6 +1,6 @@
"use client"
import { useState, useCallback, useMemo } from "react"
import React, { useState, useCallback, useMemo } from "react"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
@ -263,30 +263,30 @@ export function EventManager({
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-4">
<h2 className="text-xl font-semibold sm:text-2xl">
{view === "month" &&
currentDate.toLocaleDateString("en-US", {
currentDate.toLocaleDateString("pt-BR", {
month: "long",
year: "numeric",
})}
{view === "week" &&
`Week of ${currentDate.toLocaleDateString("en-US", {
`Semana de ${currentDate.toLocaleDateString("pt-BR", {
month: "short",
day: "numeric",
})}`}
{view === "day" &&
currentDate.toLocaleDateString("en-US", {
currentDate.toLocaleDateString("pt-BR", {
weekday: "long",
month: "long",
day: "numeric",
year: "numeric",
})}
{view === "list" && "All Events"}
{view === "list" && "Todos os eventos"}
</h2>
<div className="flex items-center gap-2">
<Button variant="outline" size="icon" onClick={() => navigateDate("prev")} className="h-8 w-8">
<ChevronLeft className="h-4 w-4" />
</Button>
<Button variant="outline" size="sm" onClick={() => setCurrentDate(new Date())}>
Today
Hoje
</Button>
<Button variant="outline" size="icon" onClick={() => navigateDate("next")} className="h-8 w-8">
<ChevronRight className="h-4 w-4" />
@ -305,25 +305,25 @@ export function EventManager({
<SelectItem value="month">
<div className="flex items-center gap-2">
<Calendar className="h-4 w-4" />
Month View
Mês
</div>
</SelectItem>
<SelectItem value="week">
<div className="flex items-center gap-2">
<Grid3x3 className="h-4 w-4" />
Week View
Semana
</div>
</SelectItem>
<SelectItem value="day">
<div className="flex items-center gap-2">
<Clock className="h-4 w-4" />
Day View
Dia
</div>
</SelectItem>
<SelectItem value="list">
<div className="flex items-center gap-2">
<List className="h-4 w-4" />
List View
Lista
</div>
</SelectItem>
</SelectContent>
@ -339,7 +339,7 @@ export function EventManager({
className="h-8"
>
<Calendar className="h-4 w-4" />
<span className="ml-1">Month</span>
<span className="ml-1">Mês</span>
</Button>
<Button
variant={view === "week" ? "secondary" : "ghost"}
@ -348,7 +348,7 @@ export function EventManager({
className="h-8"
>
<Grid3x3 className="h-4 w-4" />
<span className="ml-1">Week</span>
<span className="ml-1">Semana</span>
</Button>
<Button
variant={view === "day" ? "secondary" : "ghost"}
@ -357,7 +357,7 @@ export function EventManager({
className="h-8"
>
<Clock className="h-4 w-4" />
<span className="ml-1">Day</span>
<span className="ml-1">Dia</span>
</Button>
<Button
variant={view === "list" ? "secondary" : "ghost"}
@ -366,7 +366,7 @@ export function EventManager({
className="h-8"
>
<List className="h-4 w-4" />
<span className="ml-1">List</span>
<span className="ml-1">Lista</span>
</Button>
</div>
@ -378,7 +378,7 @@ export function EventManager({
className="w-full sm:w-auto"
>
<Plus className="mr-2 h-4 w-4" />
New Event
Novo Evento
</Button>
</div>
</div>
@ -387,7 +387,7 @@ export function EventManager({
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
placeholder="Search events..."
placeholder="Buscar eventos..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-9"
@ -412,7 +412,7 @@ export function EventManager({
<DropdownMenuTrigger asChild>
<Button variant="outline" size="sm" className="gap-2 whitespace-nowrap flex-shrink-0 bg-transparent">
<Filter className="h-4 w-4" />
Colors
Cores
{selectedColors.length > 0 && (
<Badge variant="secondary" className="ml-1 h-5 px-1.5">
{selectedColors.length}
@ -421,7 +421,7 @@ export function EventManager({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-48">
<DropdownMenuLabel>Filter by Color</DropdownMenuLabel>
<DropdownMenuLabel>Filtrar por Cor</DropdownMenuLabel>
<DropdownMenuSeparator />
{colors.map((color) => (
<DropdownMenuCheckboxItem
@ -456,7 +456,7 @@ export function EventManager({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-48">
<DropdownMenuLabel>Filter by Tag</DropdownMenuLabel>
<DropdownMenuLabel>Filtrar por Tag</DropdownMenuLabel>
<DropdownMenuSeparator />
{availableTags.map((tag) => (
<DropdownMenuCheckboxItem
@ -477,7 +477,7 @@ export function EventManager({
<DropdownMenuTrigger asChild>
<Button variant="outline" size="sm" className="gap-2 whitespace-nowrap flex-shrink-0 bg-transparent">
<Filter className="h-4 w-4" />
Categories
Categorias
{selectedCategories.length > 0 && (
<Badge variant="secondary" className="ml-1 h-5 px-1.5">
{selectedCategories.length}
@ -486,7 +486,7 @@ export function EventManager({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-48">
<DropdownMenuLabel>Filter by Category</DropdownMenuLabel>
<DropdownMenuLabel>Filtrar por Categoria</DropdownMenuLabel>
<DropdownMenuSeparator />
{categories.map((category) => (
<DropdownMenuCheckboxItem
@ -512,7 +512,7 @@ export function EventManager({
className="gap-2 whitespace-nowrap flex-shrink-0"
>
<X className="h-4 w-4" />
Clear Filters
Limpar Filtros
</Button>
)}
</div>
@ -525,7 +525,7 @@ export function EventManager({
<DropdownMenuTrigger asChild>
<Button variant="outline" size="sm" className="gap-2 bg-transparent">
<Filter className="h-4 w-4" />
Colors
Cores
{selectedColors.length > 0 && (
<Badge variant="secondary" className="ml-1 h-5 px-1">
{selectedColors.length}
@ -534,7 +534,7 @@ export function EventManager({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuLabel>Filter by Color</DropdownMenuLabel>
<DropdownMenuLabel>Filtrar por Cor</DropdownMenuLabel>
<DropdownMenuSeparator />
{colors.map((color) => (
<DropdownMenuCheckboxItem
@ -569,7 +569,7 @@ export function EventManager({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuLabel>Filter by Tag</DropdownMenuLabel>
<DropdownMenuLabel>Filtrar por Tag</DropdownMenuLabel>
<DropdownMenuSeparator />
{availableTags.map((tag) => (
<DropdownMenuCheckboxItem
@ -590,7 +590,7 @@ export function EventManager({
<DropdownMenuTrigger asChild>
<Button variant="outline" size="sm" className="gap-2 bg-transparent">
<Filter className="h-4 w-4" />
Categories
Categorias
{selectedCategories.length > 0 && (
<Badge variant="secondary" className="ml-1 h-5 px-1">
{selectedCategories.length}
@ -599,7 +599,7 @@ export function EventManager({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuLabel>Filter by Category</DropdownMenuLabel>
<DropdownMenuLabel>Filtrar por Categoria</DropdownMenuLabel>
<DropdownMenuSeparator />
{categories.map((category) => (
<DropdownMenuCheckboxItem
@ -620,7 +620,7 @@ export function EventManager({
{hasActiveFilters && (
<Button variant="ghost" size="sm" onClick={clearFilters} className="gap-2">
<X className="h-4 w-4" />
Clear
Limpar
</Button>
)}
</div>
@ -628,7 +628,7 @@ export function EventManager({
{hasActiveFilters && (
<div className="flex flex-wrap items-center gap-2">
<span className="text-sm text-muted-foreground">Active filters:</span>
<span className="text-sm text-muted-foreground">Filtros ativos:</span>
{selectedColors.map((colorValue) => {
const color = getColorClasses(colorValue)
return (
@ -678,8 +678,8 @@ export function EventManager({
setSelectedEvent(event)
setIsDialogOpen(true)
}}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragStart={(event) => handleDragStart(event)}
onDragEnd={() => handleDragEnd()}
onDrop={handleDrop}
getColorClasses={getColorClasses}
/>
@ -693,8 +693,8 @@ export function EventManager({
setSelectedEvent(event)
setIsDialogOpen(true)
}}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragStart={(event) => handleDragStart(event)}
onDragEnd={() => handleDragEnd()}
onDrop={handleDrop}
getColorClasses={getColorClasses}
/>
@ -708,8 +708,8 @@ export function EventManager({
setSelectedEvent(event)
setIsDialogOpen(true)
}}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragStart={(event) => handleDragStart(event)}
onDragEnd={() => handleDragEnd()}
onDrop={handleDrop}
getColorClasses={getColorClasses}
/>
@ -730,15 +730,15 @@ export function EventManager({
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
<DialogContent className="max-w-md max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>{isCreating ? "Create Event" : "Event Details"}</DialogTitle>
<DialogTitle>{isCreating ? "Criar Evento" : "Detalhes do Evento"}</DialogTitle>
<DialogDescription>
{isCreating ? "Add a new event to your calendar" : "View and edit event details"}
{isCreating ? "Adicione um novo evento ao seu calendário" : "Visualizar e editar detalhes do evento"}
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="title">Title</Label>
<Label htmlFor="title">Título</Label>
<Input
id="title"
value={isCreating ? newEvent.title : selectedEvent?.title}
@ -747,12 +747,12 @@ export function EventManager({
? setNewEvent((prev) => ({ ...prev, title: e.target.value }))
: setSelectedEvent((prev) => (prev ? { ...prev, title: e.target.value } : null))
}
placeholder="Event title"
placeholder="Título do evento"
/>
</div>
<div className="space-y-2">
<Label htmlFor="description">Description</Label>
<Label htmlFor="description">Descrição</Label>
<Textarea
id="description"
value={isCreating ? newEvent.description : selectedEvent?.description}
@ -764,14 +764,14 @@ export function EventManager({
}))
: setSelectedEvent((prev) => (prev ? { ...prev, description: e.target.value } : null))
}
placeholder="Event description"
placeholder="Descrição do evento"
rows={3}
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="startTime">Start Time</Label>
<Label htmlFor="startTime">Início</Label>
<Input
id="startTime"
type="datetime-local"
@ -800,7 +800,7 @@ export function EventManager({
</div>
<div className="space-y-2">
<Label htmlFor="endTime">End Time</Label>
<Label htmlFor="endTime">Fim</Label>
<Input
id="endTime"
type="datetime-local"
@ -829,7 +829,7 @@ export function EventManager({
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="category">Category</Label>
<Label htmlFor="category">Categoria</Label>
<Select
value={isCreating ? newEvent.category : selectedEvent?.category}
onValueChange={(value) =>
@ -839,7 +839,7 @@ export function EventManager({
}
>
<SelectTrigger id="category">
<SelectValue placeholder="Select category" />
<SelectValue placeholder="Selecione a categoria" />
</SelectTrigger>
<SelectContent>
{categories.map((cat) => (
@ -852,7 +852,7 @@ export function EventManager({
</div>
<div className="space-y-2">
<Label htmlFor="color">Color</Label>
<Label htmlFor="color">Cor</Label>
<Select
value={isCreating ? newEvent.color : selectedEvent?.color}
onValueChange={(value) =>
@ -862,7 +862,7 @@ export function EventManager({
}
>
<SelectTrigger id="color">
<SelectValue placeholder="Select color" />
<SelectValue placeholder="Selecione a cor" />
</SelectTrigger>
<SelectContent>
{colors.map((color) => (
@ -901,7 +901,7 @@ export function EventManager({
<DialogFooter>
{!isCreating && (
<Button variant="destructive" onClick={() => selectedEvent && handleDeleteEvent(selectedEvent.id)}>
Delete
Deletar
</Button>
)}
<Button
@ -912,10 +912,10 @@ export function EventManager({
setSelectedEvent(null)
}}
>
Cancel
Cancelar
</Button>
<Button onClick={isCreating ? handleCreateEvent : handleUpdateEvent}>
{isCreating ? "Create" : "Save"}
{isCreating ? "Criar" : "Salvar"}
</Button>
</DialogFooter>
</DialogContent>
@ -1160,7 +1160,7 @@ function MonthView({
return (
<Card className="overflow-hidden">
<div className="grid grid-cols-7 border-b">
{["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((day) => (
{["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"].map((day) => (
<div key={day} className="border-r p-2 text-center text-xs font-medium last:border-r-0 sm:text-sm">
<span className="hidden sm:inline">{day}</span>
<span className="sm:hidden">{day.charAt(0)}</span>
@ -1204,8 +1204,8 @@ function MonthView({
variant="compact"
/>
))}
{dayEvents.length > 3 && (
<div className="text-[10px] text-muted-foreground sm:text-xs">+{dayEvents.length - 3} more</div>
{dayEvents.length > 3 && (
<div className="text-[10px] text-muted-foreground sm:text-xs">+{dayEvents.length - 3} mais</div>
)}
</div>
</div>
@ -1261,16 +1261,16 @@ function WeekView({
return (
<Card className="overflow-auto">
<div className="grid grid-cols-8 border-b">
<div className="border-r p-2 text-center text-xs font-medium sm:text-sm">Time</div>
<div className="border-r p-2 text-center text-xs font-medium sm:text-sm">Hora</div>
{weekDays.map((day) => (
<div
key={day.toISOString()}
className="border-r p-2 text-center text-xs font-medium last:border-r-0 sm:text-sm"
>
<div className="hidden sm:block">{day.toLocaleDateString("en-US", { weekday: "short" })}</div>
<div className="sm:hidden">{day.toLocaleDateString("en-US", { weekday: "narrow" })}</div>
<div className="hidden sm:block">{day.toLocaleDateString("pt-BR", { weekday: "short" })}</div>
<div className="sm:hidden">{day.toLocaleDateString("pt-BR", { weekday: "narrow" })}</div>
<div className="text-[10px] text-muted-foreground sm:text-xs">
{day.toLocaleDateString("en-US", { month: "short", day: "numeric" })}
{day.toLocaleDateString("pt-BR", { month: "short", day: "numeric" })}
</div>
</div>
))}
@ -1401,7 +1401,7 @@ function ListView({
const groupedEvents = sortedEvents.reduce(
(acc, event) => {
const dateKey = event.startTime.toLocaleDateString("en-US", {
const dateKey = event.startTime.toLocaleDateString("pt-BR", {
weekday: "long",
year: "numeric",
month: "long",
@ -1456,15 +1456,7 @@ function ListView({
<div className="mt-2 flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground sm:gap-4 sm:text-xs">
<div className="flex items-center gap-1">
<Clock className="h-3 w-3" />
{event.startTime.toLocaleTimeString("en-US", {
hour: "2-digit",
minute: "2-digit",
})}{" "}
-{" "}
{event.endTime.toLocaleTimeString("en-US", {
hour: "2-digit",
minute: "2-digit",
})}
{event.startTime.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })} - {event.endTime.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })}
</div>
{event.tags && event.tags.length > 0 && (
<div className="flex flex-wrap gap-1">
@ -1485,7 +1477,7 @@ function ListView({
</div>
))}
{sortedEvents.length === 0 && (
<div className="py-12 text-center text-sm text-muted-foreground sm:text-base">No events found</div>
<div className="py-12 text-center text-sm text-muted-foreground sm:text-base">Nenhum evento encontrado</div>
)}
</div>
</Card>