diff --git a/susconecta/app/(main-routes)/calendar/page.tsx b/susconecta/app/(main-routes)/calendar/page.tsx index f1ce1b3..869ccc4 100644 --- a/susconecta/app/(main-routes)/calendar/page.tsx +++ b/susconecta/app/(main-routes)/calendar/page.tsx @@ -170,6 +170,7 @@ export default function AgendamentoPage() { plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]} initialView="dayGridMonth" locale={pt_br_locale} + timeZone={"America/Sao_Paulo"} events={requestsList} headerToolbar={{ left: "prev,next today", diff --git a/susconecta/components/agendamento/AgendaCalendar.tsx b/susconecta/components/agendamento/AgendaCalendar.tsx index da0abe1..983e49d 100644 --- a/susconecta/components/agendamento/AgendaCalendar.tsx +++ b/susconecta/components/agendamento/AgendaCalendar.tsx @@ -66,7 +66,8 @@ export default function AgendaCalendar({ weekday: 'long', day: 'numeric', month: 'long', - year: 'numeric' + year: 'numeric', + timeZone: 'America/Sao_Paulo' }); }; @@ -205,18 +206,22 @@ export default function AgendaCalendar({
- {currentDate.toLocaleDateString('pt-BR', { weekday: 'long' })} -
+ {currentDate.toLocaleDateString('pt-BR', { weekday: 'long', timeZone: 'America/Sao_Paulo' })} +
{timeSlots.map(time => (
))} {filteredAppointments.map(app => { - const [date, timeStr] = app.time.split('T'); - const [hours, minutes] = timeStr.split(':'); - const hour = parseInt(hours); - const minute = parseInt(minutes); + // parse appointment time in Brazil timezone + const d = new Date(app.time); + // extract hour/minute in America/Sao_Paulo using Intl.DateTimeFormat + const parts = new Intl.DateTimeFormat('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', timeZone: 'America/Sao_Paulo' }).formatToParts(d); + const hourPart = parts.find(p => p.type === 'hour')?.value ?? '00'; + const minutePart = parts.find(p => p.type === 'minute')?.value ?? '00'; + const hour = parseInt(hourPart, 10); + const minute = parseInt(minutePart, 10); return (
- {hours}:{minutes} - {app.type} {getTypeIcon(app.type)} + {String(hour).padStart(2,'0')}:{String(minute).padStart(2,'0')} - {app.type} {getTypeIcon(app.type)}
{professionals.find(p => p.id === app.professional)?.name} @@ -260,9 +265,13 @@ export default function AgendaCalendar({ {view === 'month' && (
- {filteredAppointments.map(app => { - const [date, timeStr] = app.time.split('T'); - const [hours, minutes] = timeStr.split(':'); + {filteredAppointments.map(app => { + const d = new Date(app.time); + const parts = new Intl.DateTimeFormat('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', timeZone: 'America/Sao_Paulo' }).formatToParts(d); + const hourPart = parts.find(p => p.type === 'hour')?.value ?? '00'; + const minutePart = parts.find(p => p.type === 'minute')?.value ?? '00'; + const hours = String(hourPart).padStart(2,'0'); + const minutes = String(minutePart).padStart(2,'0'); return (
diff --git a/susconecta/components/ui/calendar.tsx b/susconecta/components/ui/calendar.tsx index 4d7c46a..5479c11 100644 --- a/susconecta/components/ui/calendar.tsx +++ b/susconecta/components/ui/calendar.tsx @@ -35,9 +35,9 @@ function Calendar({ className )} captionLayout={captionLayout} - formatters={{ + formatters={{ formatMonthDropdown: (date) => - date.toLocaleString("default", { month: "short" }), + date.toLocaleString("default", { month: "short", timeZone: 'America/Sao_Paulo' }), ...formatters, }} classNames={{ @@ -155,7 +155,7 @@ function Calendar({ ) }, - DayButton: CalendarDayButton, + DayButton: CalendarDayButton, WeekNumber: ({ children, ...props }) => { return ( @@ -190,7 +190,7 @@ function CalendarDayButton({ ref={ref} variant="ghost" size="icon" - data-day={day.date.toLocaleDateString()} + data-day={day.date.toLocaleDateString(undefined, { timeZone: 'America/Sao_Paulo' })} data-selected-single={ modifiers.selected && !modifiers.range_start &&