feat(agenda): layout em 2 colunas no desktop + sidebar recolhível
- AgendaView: controles migrados do header horizontal para uma coluna lateral esquerda (AGENDAR, ícones de ação em faixa horizontal de tamanho igual, presença, legenda de dentistas); calendário em flex-1 ocupando a altura toda - Mobile revisto: cabeçalho compacto (título + AGENDAR) e calendário flex-1 - Sidebar do sistema recolhível no desktop (App: estado persistido + botão flutuante para reexibir); toggle fica ao lado do título "AGENDA CLÍNICA" - Toolbar do FullCalendar compactada (título/botões/cabeçalhos menores) - Título da agenda responsivo (não gera scroll horizontal na coluna estreita) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+23
-3
@@ -4,7 +4,7 @@ import { HybridBackend } from './services/backend.ts';
|
||||
import { Sidebar } from './components/Sidebar.tsx';
|
||||
import {
|
||||
Menu, LayoutDashboard, Users, Calendar as CalendarIcon,
|
||||
DollarSign, Activity, ClipboardList, Bell, Settings, MoreHorizontal, Eye, X
|
||||
DollarSign, Activity, ClipboardList, Bell, Settings, MoreHorizontal, Eye, X, PanelLeftOpen
|
||||
} from 'lucide-react';
|
||||
|
||||
import { ToastContainer } from './components/Toast.tsx';
|
||||
@@ -315,6 +315,14 @@ const MobileBottomNav: React.FC<{
|
||||
const App: React.FC = () => {
|
||||
const ver = useAppVersion();
|
||||
const [isSidebarOpen, setSidebarOpen] = useState(false);
|
||||
// Recolher a sidebar no DESKTOP (persistente) — dá largura ao conteúdo (ex.: agenda).
|
||||
const [isSidebarCollapsed, setSidebarCollapsed] = useState<boolean>(() => {
|
||||
try { return localStorage.getItem('scoreodonto:sidebar-collapsed') === '1'; } catch { return false; }
|
||||
});
|
||||
const toggleSidebarCollapsed = (v: boolean) => {
|
||||
setSidebarCollapsed(v);
|
||||
try { localStorage.setItem('scoreodonto:sidebar-collapsed', v ? '1' : '0'); } catch { /* ignore */ }
|
||||
};
|
||||
const [, forcePwRerender] = useState(0); // re-avalia o modal de troca obrigatória de senha
|
||||
const currentRole = HybridBackend.getCurrentRole();
|
||||
const activeWorkspace = HybridBackend.getActiveWorkspace();
|
||||
@@ -500,7 +508,7 @@ const App: React.FC = () => {
|
||||
case 'leads': return <LeadsView />;
|
||||
case 'public': return <PublicContactForm />;
|
||||
case 'pacientes': return <PatientsView />;
|
||||
case 'agenda': return <AgendaView onNavigate={handleNavigate} />;
|
||||
case 'agenda': return <AgendaView onNavigate={handleNavigate} sidebarCollapsed={isSidebarCollapsed} onToggleSidebar={() => toggleSidebarCollapsed(!isSidebarCollapsed)} />;
|
||||
case 'ortodontia': return <OrthoView />;
|
||||
case 'financeiro': return <FinanceiroView />;
|
||||
case 'dentistas': return <DentistasView />;
|
||||
@@ -591,7 +599,7 @@ const App: React.FC = () => {
|
||||
></div>
|
||||
)}
|
||||
|
||||
<div className={`fixed inset-y-0 left-0 z-30 transform transition-transform duration-300 md:relative md:translate-x-0 ${isSidebarOpen ? 'translate-x-0' : '-translate-x-full'}`}>
|
||||
<div className={`fixed inset-y-0 left-0 z-30 transform transition-transform duration-300 ${isSidebarCollapsed ? 'md:hidden' : 'md:relative md:translate-x-0'} ${isSidebarOpen ? 'translate-x-0' : '-translate-x-full'}`}>
|
||||
<Sidebar
|
||||
activeTab={currentView}
|
||||
setActiveTab={(t) => handleNavigate(t as ViewKey)}
|
||||
@@ -600,6 +608,18 @@ const App: React.FC = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Botão flutuante para reexibir a sidebar (desktop, quando recolhida).
|
||||
Na agenda NÃO aparece — ela já tem o próprio toggle ao lado do título. */}
|
||||
{!isStandaloneView && isSidebarCollapsed && currentView !== 'agenda' && (
|
||||
<button
|
||||
onClick={() => toggleSidebarCollapsed(false)}
|
||||
title="Mostrar menu"
|
||||
className="hidden md:flex fixed top-3 left-3 z-40 items-center justify-center w-9 h-9 bg-white border border-gray-200 rounded-lg text-gray-500 hover:text-gray-800 hover:border-gray-300 shadow-sm transition-colors"
|
||||
>
|
||||
<PanelLeftOpen size={18} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
<main className={`flex-1 h-full relative flex flex-col min-w-0`}>
|
||||
{HybridBackend.isPreviewMode() && (
|
||||
<div className="bg-red-600 text-white px-4 py-2 flex items-center justify-between gap-3 shadow-md z-30">
|
||||
|
||||
Reference in New Issue
Block a user