From 3db0fe0d9a2d7857f3401688690b8d4bcb907de9 Mon Sep 17 00:00:00 2001 From: VPS 4 Builder Date: Tue, 9 Jun 2026 22:12:55 +0200 Subject: [PATCH] feat(agenda+ui): responsividade mobile da agenda - PageHeader empilha no mobile, titulo menor, acoes com flex-wrap - AgendaView: toolbar de acoes com wrap; botao NOVO vira so icone no mobile - FullCalendar: view de DIA no mobile (timeGridDay), toolbar enxuta + footer com Dia/Mes, altura por viewport (100dvh), CSS responsivo da toolbar/celulas, nowIndicator Co-Authored-By: Claude Opus 4.8 --- frontend/components/PageHeader.tsx | 6 +++--- frontend/views/AgendaView.tsx | 34 ++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/frontend/components/PageHeader.tsx b/frontend/components/PageHeader.tsx index 2a77104..1caa883 100644 --- a/frontend/components/PageHeader.tsx +++ b/frontend/components/PageHeader.tsx @@ -9,12 +9,12 @@ interface PageHeaderProps { export const PageHeader: React.FC = ({ title, description, children }) => { return ( -
+
-

{title}

+

{title}

{description &&

{description}

}
-
+
{children}
diff --git a/frontend/views/AgendaView.tsx b/frontend/views/AgendaView.tsx index 316093e..aa5e17f 100644 --- a/frontend/views/AgendaView.tsx +++ b/frontend/views/AgendaView.tsx @@ -369,6 +369,12 @@ export const AgendaView: React.FC<{ onNavigate?: (view: string) => void }> = ({ const loadAtividade = useCallback(async () => { try { setAtividade(await HybridBackend.getAtividadeAgenda()); } catch { /* ignore */ } }, []); + const [isMobile, setIsMobile] = useState(typeof window !== 'undefined' && window.innerWidth < 640); + useEffect(() => { + const onResize = () => setIsMobile(window.innerWidth < 640); + window.addEventListener('resize', onResize); + return () => window.removeEventListener('resize', onResize); + }, []); const [importando, setImportando] = useState(false); const handleImportarGoogle = async () => { if (!confirm('Importar os agendamentos do Google (última semana + próximos) para o sistema? Eles passam a ser editáveis aqui.')) return; @@ -553,7 +559,7 @@ export const AgendaView: React.FC<{ onNavigate?: (view: string) => void }> = ({ return (
-
+
{(provided) => ( @@ -616,17 +622,21 @@ export const AgendaView: React.FC<{ onNavigate?: (view: string) => void }> = ({ )} {(currentRole !== 'paciente') && ( - )}
-
+
void }> = ({ dateClick={handleDateClick} eventClick={handleEventClick} height="100%" + nowIndicator={true} slotLabelFormat={{ hour: '2-digit', minute: '2-digit', hour12: false }} eventContent={(eventInfo) => { const isGoogle = eventInfo.event.extendedProps.isGoogle; @@ -745,6 +756,17 @@ export const AgendaView: React.FC<{ onNavigate?: (view: string) => void }> = ({ .custom-scrollbar::-webkit-scrollbar { width: 4px; } .custom-scrollbar::-webkit-scrollbar-track { background: #f1f1f1; } .custom-scrollbar::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; } + /* FullCalendar — responsividade mobile */ + @media (max-width: 639px) { + .fc .fc-toolbar.fc-header-toolbar { margin-bottom: .5rem; flex-wrap: wrap; gap: .4rem; } + .fc .fc-toolbar-title { font-size: .95rem; } + .fc .fc-button { padding: .25rem .55rem; font-size: .72rem; } + .fc .fc-toolbar-chunk { display: flex; align-items: center; } + .fc .fc-col-header-cell-cushion { font-size: .65rem; padding: 2px; } + .fc .fc-timegrid-slot-label-cushion, .fc .fc-timegrid-axis-cushion { font-size: .6rem; } + .fc .fc-timegrid-event .fc-event-main { padding: 1px 2px; } + .fc-footer-toolbar.fc-toolbar { margin-top: .5rem; } + } `}