Compare commits

..

No commits in common. "652dc2745a1365d7916ec2d019e4f15ce9b488cf" and "36600e2b33208f1425110b221ff94d41759a3cfc" have entirely different histories.

5 changed files with 461 additions and 828 deletions

View File

@ -32,9 +32,6 @@ export default function DoctorLayout({ children }: PatientLayoutProps) {
const [doctorData, setDoctorData] = useState<DoctorData | null>(null); const [doctorData, setDoctorData] = useState<DoctorData | null>(null);
const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [showLogoutDialog, setShowLogoutDialog] = useState(false); const [showLogoutDialog, setShowLogoutDialog] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); // Novo estado para menu mobile
const [windowWidth, setWindowWidth] = useState(0);
const isMobile = windowWidth < 1024; // breakpoint lg
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
@ -47,21 +44,6 @@ export default function DoctorLayout({ children }: PatientLayoutProps) {
} }
}, [router]); }, [router]);
useEffect(() => {
const handleResize = () => setWindowWidth(window.innerWidth);
handleResize(); // inicializa com a largura atual
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
useEffect(() => {
if (isMobile) {
setSidebarCollapsed(true);
} else {
setSidebarCollapsed(false);
}
}, [isMobile]);
const handleLogout = () => { const handleLogout = () => {
setShowLogoutDialog(true); setShowLogoutDialog(true);
}; };
@ -76,10 +58,6 @@ useEffect(() => {
setShowLogoutDialog(false); setShowLogoutDialog(false);
}; };
const toggleMobileMenu = () => {
setIsMobileMenuOpen(!isMobileMenuOpen);
};
const menuItems = [ const menuItems = [
{ {
href: "#", href: "#",
@ -113,8 +91,8 @@ useEffect(() => {
return ( return (
<div className="min-h-screen bg-gray-50 flex"> <div className="min-h-screen bg-gray-50 flex">
{/* Sidebar para desktop */} {/* Sidebar */}
<div className={`bg-white border-r border-gray-200 transition-all duration-300 ${sidebarCollapsed ? "w-16" : "w-64"} fixed left-0 top-0 h-screen flex flex-col z-50`}> <div className={`bg-white border-r border-gray-200 transition-all duration-300 ${sidebarCollapsed ? "w-16" : "w-64"} fixed left-0 top-0 h-screen flex flex-col z-10`}>
<div className="p-4 border-b border-gray-200"> <div className="p-4 border-b border-gray-200">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
{!sidebarCollapsed && ( {!sidebarCollapsed && (
@ -147,121 +125,6 @@ useEffect(() => {
})} })}
</nav> </nav>
// ... (seu código anterior)
{/* Sidebar para desktop */}
<div className={`bg-white border-r border-gray-200 transition-all duration-300 ${sidebarCollapsed ? "w-16" : "w-64"} fixed left-0 top-0 h-screen flex flex-col z-50`}>
<div className="p-4 border-b border-gray-200">
<div className="flex items-center justify-between">
{!sidebarCollapsed && (
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
<div className="w-4 h-4 bg-white rounded-sm"></div>
</div>
<span className="font-semibold text-gray-900">Hospital System</span>
</div>
)}
<Button variant="ghost" size="sm" onClick={() => setSidebarCollapsed(!sidebarCollapsed)} className="p-1">
{sidebarCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
</Button>
</div>
</div>
<nav className="flex-1 p-2 overflow-y-auto">
{menuItems.map((item) => {
const Icon = item.icon;
const isActive = pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href));
return (
<Link key={item.href} href={item.href}>
<div className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${isActive ? "bg-blue-50 text-blue-600 border-r-2 border-blue-600" : "text-gray-600 hover:bg-gray-50"}`}>
<Icon className="w-5 h-5 flex-shrink-0" />
{!sidebarCollapsed && <span className="font-medium">{item.label}</span>}
</div>
</Link>
);
})}
</nav>
<div className="border-t p-4 mt-auto">
<div className="flex items-center space-x-3 mb-4">
{/* Se a sidebar estiver recolhida, o avatar e o texto do usuário também devem ser condensados ou ocultados */}
{!sidebarCollapsed && (
<>
<Avatar>
<AvatarImage src="/placeholder.svg?height=40&width=40" />
<AvatarFallback>
{doctorData.name
.split(" ")
.map((n) => n[0])
.join("")}
</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate">{doctorData.name}</p>
<p className="text-xs text-gray-500 truncate">{doctorData.specialty}</p>
</div>
</>
)}
{sidebarCollapsed && (
<Avatar className="mx-auto"> {/* Centraliza o avatar quando recolhido */}
<AvatarImage src="/placeholder.svg?height=40&width=40" />
<AvatarFallback>
{doctorData.name
.split(" ")
.map((n) => n[0])
.join("")}
</AvatarFallback>
</Avatar>
)}
</div>
{/* Novo botão de sair, usando a mesma estrutura dos itens de menu */}
<div
className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors text-gray-600 hover:bg-gray-50 cursor-pointer ${sidebarCollapsed ? "justify-center" : ""}`}
onClick={handleLogout}
>
<LogOut className="w-5 h-5 flex-shrink-0" />
{!sidebarCollapsed && <span className="font-medium">Sair</span>}
</div>
</div>
</div>
</div>
{/* Sidebar para mobile (apresentado como um menu overlay) */}
{isMobileMenuOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 z-40 md:hidden" onClick={toggleMobileMenu}></div>
)}
<div className={`bg-white border-r border-gray-200 fixed left-0 top-0 h-screen flex flex-col z-50 transition-transform duration-300 md:hidden ${isMobileMenuOpen ? "translate-x-0 w-64" : "-translate-x-full w-64"}`}>
<div className="p-4 border-b border-gray-200 flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
<div className="w-4 h-4 bg-white rounded-sm"></div>
</div>
<span className="font-semibold text-gray-900">Hospital System</span>
</div>
<Button variant="ghost" size="sm" onClick={toggleMobileMenu} className="p-1">
<X className="w-4 h-4" />
</Button>
</div>
<nav className="flex-1 p-2 overflow-y-auto">
{menuItems.map((item) => {
const Icon = item.icon;
const isActive = pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href));
return (
<Link key={item.href} href={item.href} onClick={toggleMobileMenu}> {/* Fechar menu ao clicar */}
<div className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${isActive ? "bg-blue-50 text-blue-600 border-r-2 border-blue-600" : "text-gray-600 hover:bg-gray-50"}`}>
<Icon className="w-5 h-5 flex-shrink-0" />
<span className="font-medium">{item.label}</span>
</div>
</Link>
);
})}
</nav>
<div className="border-t p-4 mt-auto"> <div className="border-t p-4 mt-auto">
<div className="flex items-center space-x-3 mb-4"> <div className="flex items-center space-x-3 mb-4">
<Avatar> <Avatar>
@ -278,21 +141,20 @@ useEffect(() => {
<p className="text-xs text-gray-500 truncate">{doctorData.specialty}</p> <p className="text-xs text-gray-500 truncate">{doctorData.specialty}</p>
</div> </div>
</div> </div>
<Button variant="outline" size="sm" className="w-full bg-transparent" onClick={() => { handleLogout(); toggleMobileMenu(); }}> {/* Fechar menu ao deslogar */} <Button variant="outline" size="sm" className="w-full bg-transparent" onClick={handleLogout}>
<LogOut className="mr-2 h-4 w-4" /> <LogOut className="mr-2 h-4 w-4" />
Sair Sair
</Button> </Button>
</div> </div>
</div> </div>
{/* Main Content */} {/* Main Content */}
<div className={`flex-1 flex flex-col transition-all duration-300 ${sidebarCollapsed ? "ml-16" : "ml-64"}`}> <div className={`flex-1 flex flex-col transition-all duration-300 ${sidebarCollapsed ? "ml-16" : "ml-64"}`}>
{/* Header */} {/* Header */}
<header className="bg-white border-b border-gray-200 px-6 py-4"> <header className="bg-white border-b border-gray-200 px-6 py-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-4 flex-1"> <div className="flex items-center gap-4 flex-1 max-w-md">
<div className="relative flex-1 max-w-md"> <div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" /> <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input placeholder="Buscar paciente" className="pl-10 bg-gray-50 border-gray-200" /> <Input placeholder="Buscar paciente" className="pl-10 bg-gray-50 border-gray-200" />
</div> </div>

View File

@ -1,6 +1,7 @@
"use client"; "use client";
import type React from "react"; import type React from "react";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useRouter, usePathname } from "next/navigation"; import { useRouter, usePathname } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
@ -8,279 +9,187 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
Dialog, import { Search, Bell, Calendar, Clock, User, LogOut, Menu, X, Home, FileText, ChevronLeft, ChevronRight } from "lucide-react";
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
Search,
Bell,
Calendar,
Clock,
User,
LogOut,
Menu,
X,
Home,
FileText,
ChevronLeft,
ChevronRight,
} from "lucide-react";
interface FinancierData { interface FinancierData {
id: string; id: string,
name: string; name: string,
email: string; email: string,
phone: string; phone: string,
cpf: string; cpf: string,
department: string; department: string,
permissions: object; permissions: object,
} }
interface PatientLayoutProps { interface PatientLayoutProps {
children: React.ReactNode; children: React.ReactNode;
} }
export default function FinancierLayout({ children }: PatientLayoutProps) { export default function FinancierLayout({ children }: PatientLayoutProps) {
const [financierData, setFinancierData] = useState<FinancierData | null>( const [financierData, setFinancierData] = useState<FinancierData | null>(null);
null const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
); const [showLogoutDialog, setShowLogoutDialog] = useState(false);
const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const router = useRouter();
const [showLogoutDialog, setShowLogoutDialog] = useState(false); const pathname = usePathname();
const router = useRouter();
const pathname = usePathname();
useEffect(() => { useEffect(() => {
const data = localStorage.getItem("financierData"); const data = localStorage.getItem("financierData");
if (data) { if (data) {
setFinancierData(JSON.parse(data)); setFinancierData(JSON.parse(data));
} else { } else {
router.push("/finance/login"); router.push("/finance/login");
} }
}, [router]); }, [router]);
// 🔥 Responsividade automática da sidebar const handleLogout = () => {
useEffect(() => { setShowLogoutDialog(true);
const handleResize = () => {
// Ajuste o breakpoint conforme necessário. 1024px (lg) ou 768px (md) são comuns.
if (window.innerWidth < 1024) {
setSidebarCollapsed(true);
} else {
setSidebarCollapsed(false);
}
}; };
handleResize(); // executa na primeira carga const confirmLogout = () => {
window.addEventListener("resize", handleResize); localStorage.removeItem("financierData");
setShowLogoutDialog(false);
router.push("/");
};
return () => window.removeEventListener("resize", handleResize); const cancelLogout = () => {
}, []); setShowLogoutDialog(false);
};
const handleLogout = () => { const menuItems = [
setShowLogoutDialog(true); {
}; href: "#",
icon: Home,
label: "Dashboard",
// Botão para o dashboard do médico
},
{
href: "#",
icon: Calendar,
label: "Relatórios financeiros",
// Botão para o dashboard do médico
},
const confirmLogout = () => { {
localStorage.removeItem("financierData"); href: "#",
setShowLogoutDialog(false); icon: User,
router.push("/"); label: "Finanças Gerais",
}; // Botão para página do editor de laudo
},
{
href: "#",
icon: Calendar,
label: "Configurações",
// Botão para página de consultas marcadas do médico atual
},
];
const cancelLogout = () => { if (!financierData) {
setShowLogoutDialog(false); return <div>Carregando...</div>;
}; }
const menuItems = [ return (
{ <div className="min-h-screen bg-gray-50 flex">
href: "#", {/* Sidebar */}
icon: Home, <div className={`bg-white border-r border-gray-200 transition-all duration-300 ${sidebarCollapsed ? "w-16" : "w-64"} fixed left-0 top-0 h-screen flex flex-col z-10`}>
label: "Dashboard", <div className="p-4 border-b border-gray-200">
}, <div className="flex items-center justify-between">
{ {!sidebarCollapsed && (
href: "#", <div className="flex items-center gap-2">
icon: Calendar, <div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
label: "Relatórios financeiros", <div className="w-4 h-4 bg-white rounded-sm"></div>
}, </div>
{ <span className="font-semibold text-gray-900">Hospital System</span>
href: "#", </div>
icon: User, )}
label: "Finanças Gerais", <Button variant="ghost" size="sm" onClick={() => setSidebarCollapsed(!sidebarCollapsed)} className="p-1">
}, {sidebarCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
{ </Button>
href: "#", </div>
icon: Calendar,
label: "Configurações",
},
];
if (!financierData) {
return <div>Carregando...</div>;
}
return (
<div className="min-h-screen bg-gray-50 flex">
{/* Sidebar */}
<div
className={`bg-white border-r border-gray-200 transition-all duration-300 ${
sidebarCollapsed ? "w-16" : "w-64"
} fixed left-0 top-0 h-screen flex flex-col z-10`}
>
<div className="p-4 border-b border-gray-200">
<div className="flex items-center justify-between">
{!sidebarCollapsed && (
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
<div className="w-4 h-4 bg-white rounded-sm"></div>
</div> </div>
<span className="font-semibold text-gray-900">
Hospital System
</span>
</div>
)}
<Button
variant="ghost"
size="sm"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="p-1"
>
{sidebarCollapsed ? (
<ChevronRight className="w-4 h-4" />
) : (
<ChevronLeft className="w-4 h-4" />
)}
</Button>
</div>
</div>
<nav className="flex-1 p-2 overflow-y-auto"> <nav className="flex-1 p-2 overflow-y-auto">
{menuItems.map((item) => { {menuItems.map((item) => {
const Icon = item.icon; const Icon = item.icon;
const isActive = const isActive = pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href));
pathname === item.href ||
(item.href !== "/" && pathname.startsWith(item.href));
return ( return (
<Link key={item.href} href={item.href}> <Link key={item.href} href={item.href}>
<div <div className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${isActive ? "bg-blue-50 text-blue-600 border-r-2 border-blue-600" : "text-gray-600 hover:bg-gray-50"}`}>
className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${ <Icon className="w-5 h-5 flex-shrink-0" />
isActive {!sidebarCollapsed && <span className="font-medium">{item.label}</span>}
? "bg-blue-50 text-blue-600 border-r-2 border-blue-600" </div>
: "text-gray-600 hover:bg-gray-50" </Link>
}`} );
> })}
<Icon className="w-5 h-5 flex-shrink-0" /> </nav>
{!sidebarCollapsed && (
<span className="font-medium">{item.label}</span> <div className="border-t p-4 mt-auto">
)} <div className="flex items-center space-x-3 mb-4">
<Avatar>
<AvatarImage src="/placeholder.svg?height=40&width=40" />
<AvatarFallback>
{financierData.name
.split(" ")
.map((n) => n[0])
.join("")}
</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate">{financierData.name}</p>
<p className="text-xs text-gray-500 truncate">{financierData.department}</p>
</div>
</div>
<Button variant="outline" size="sm" className="w-full bg-transparent" onClick={handleLogout}>
<LogOut className="mr-2 h-4 w-4" />
Sair
</Button>
</div> </div>
</Link>
);
})}
</nav>
{/* Footer user info */}
<div className="border-t p-4 mt-auto">
<div className="flex items-center space-x-3 mb-4">
<Avatar>
<AvatarImage src="/placeholder.svg?height=40&width=40" />
<AvatarFallback>
{financierData.name
.split(" ")
.map((n) => n[0])
.join("")}
</AvatarFallback>
</Avatar>
{!sidebarCollapsed && (
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate">
{financierData.name}
</p>
<p className="text-xs text-gray-500 truncate">
{financierData.department}
</p>
</div>
)}
</div>
{/* Botão Sair - ajustado para responsividade */}
<Button
variant="outline"
size="sm"
className={
sidebarCollapsed
? "w-full bg-transparent flex justify-center items-center p-2" // Centraliza o ícone quando colapsado
: "w-full bg-transparent"
}
onClick={handleLogout}
>
<LogOut
className={sidebarCollapsed ? "h-5 w-5" : "mr-2 h-4 w-4"}
/>{" "}
{/* Remove margem quando colapsado */}
{!sidebarCollapsed && "Sair"}{" "}
{/* Mostra o texto apenas quando não está colapsado */}
</Button>
</div>
</div>
{/* Main Content */}
<div
className={`flex-1 flex flex-col transition-all duration-300 ${
sidebarCollapsed ? "ml-16" : "ml-64"
}`}
>
{/* Header */}
<header className="bg-white border-b border-gray-200 px-6 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4 flex-1 max-w-md">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
placeholder="Buscar paciente"
className="pl-10 bg-gray-50 border-gray-200"
/>
</div>
</div> </div>
<div className="flex items-center gap-4"> {/* Main Content */}
<Button variant="ghost" size="sm" className="relative"> <div className={`flex-1 flex flex-col transition-all duration-300 ${sidebarCollapsed ? "ml-16" : "ml-64"}`}>
<Bell className="w-5 h-5" /> {/* Header */}
<Badge className="absolute -top-1 -right-1 w-5 h-5 p-0 flex items-center justify-center bg-red-500 text-white text-xs"> <header className="bg-white border-b border-gray-200 px-6 py-4">
1 <div className="flex items-center justify-between">
</Badge> <div className="flex items-center gap-4 flex-1 max-w-md">
</Button> <div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input placeholder="Buscar paciente" className="pl-10 bg-gray-50 border-gray-200" />
</div>
</div>
<div className="flex items-center gap-4">
<Button variant="ghost" size="sm" className="relative">
<Bell className="w-5 h-5" />
<Badge className="absolute -top-1 -right-1 w-5 h-5 p-0 flex items-center justify-center bg-red-500 text-white text-xs">1</Badge>
</Button>
</div>
</div>
</header>
{/* Page Content */}
<main className="flex-1 p-6">{children}</main>
</div> </div>
</div>
</header>
{/* Page Content */} {/* Logout confirmation dialog */}
<main className="flex-1 p-6">{children}</main> <Dialog open={showLogoutDialog} onOpenChange={setShowLogoutDialog}>
</div> <DialogContent className="sm:max-w-md">
<DialogHeader>
{/* Logout confirmation dialog */} <DialogTitle>Confirmar Saída</DialogTitle>
<Dialog open={showLogoutDialog} onOpenChange={setShowLogoutDialog}> <DialogDescription>Deseja realmente sair do sistema? Você precisará fazer login novamente para acessar sua conta.</DialogDescription>
<DialogContent className="sm:max-w-md"> </DialogHeader>
<DialogHeader> <DialogFooter className="flex gap-2">
<DialogTitle>Confirmar Saída</DialogTitle> <Button variant="outline" onClick={cancelLogout}>
<DialogDescription> Cancelar
Deseja realmente sair do sistema? Você precisará fazer login </Button>
novamente para acessar sua conta. <Button variant="destructive" onClick={confirmLogout}>
</DialogDescription> <LogOut className="mr-2 h-4 w-4" />
</DialogHeader> Sair
<DialogFooter className="flex gap-2"> </Button>
<Button variant="outline" onClick={cancelLogout}> </DialogFooter>
Cancelar </DialogContent>
</Button> </Dialog>
<Button variant="destructive" onClick={confirmLogout}> </div>
<LogOut className="mr-2 h-4 w-4" /> );
Sair
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
} }

View File

@ -1,6 +1,7 @@
"use client"; "use client";
import type React from "react"; import type React from "react";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useRouter, usePathname } from "next/navigation"; import { useRouter, usePathname } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
@ -8,251 +9,193 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
Dialog, import { Search, Bell, Calendar, Clock, User, LogOut, Menu, X, Home, FileText, ChevronLeft, ChevronRight } from "lucide-react";
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
Search,
Bell,
Calendar,
User,
LogOut,
ChevronLeft,
ChevronRight,
Home,
} from "lucide-react";
interface ManagerData { interface ManagerData {
id: string; id: string,
name: string; name: string,
email: string; email: string,
phone: string; phone: string,
cpf: string; cpf: string,
department: string; department: string,
permissions: object; permissions: object,
} }
interface PatientLayoutProps { interface PatientLayoutProps {
children: React.ReactNode; children: React.ReactNode;
} }
export default function ManagerLayout({ children }: PatientLayoutProps) { export default function ManagerLayout({ children }: PatientLayoutProps) {
const [managerData, setManagerData] = useState<ManagerData | null>(null); const [managerData, setManagerData] = useState<ManagerData | null>(null);
const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [showLogoutDialog, setShowLogoutDialog] = useState(false); const [showLogoutDialog, setShowLogoutDialog] = useState(false);
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
useEffect(() => { useEffect(() => {
const data = localStorage.getItem("managerData"); const data = localStorage.getItem("managerData");
if (data) { if (data) {
setManagerData(JSON.parse(data)); setManagerData(JSON.parse(data));
} else { } else {
router.push("/manager/login"); router.push("/manager/login");
} }
}, [router]); }, [router]);
// 🔥 Responsividade automática da sidebar const handleLogout = () => {
useEffect(() => { setShowLogoutDialog(true);
const handleResize = () => {
if (window.innerWidth < 1024) {
setSidebarCollapsed(true); // colapsa em telas pequenas (lg breakpoint ~ 1024px)
} else {
setSidebarCollapsed(false); // expande em desktop
}
}; };
handleResize(); // roda na primeira carga const confirmLogout = () => {
window.addEventListener("resize", handleResize); localStorage.removeItem("managerData");
setShowLogoutDialog(false);
router.push("/");
};
return () => window.removeEventListener("resize", handleResize); const cancelLogout = () => {
}, []); setShowLogoutDialog(false);
};
const handleLogout = () => setShowLogoutDialog(true); const menuItems = [
{
href: "#",
icon: Home,
label: "Dashboard",
// Botão para o dashboard do médico
},
{
href: "#",
icon: Calendar,
label: "Relatórios gerenciais",
// Botão para o dashboard do médico
},
const confirmLogout = () => { {
localStorage.removeItem("managerData"); href: "#",
setShowLogoutDialog(false); icon: User,
router.push("/"); label: "Gestão de Usuários",
}; // Botão para página do editor de laudo
},
{
href: "#",
icon: User,
label: "Gestão de Médicos",
// Botão para a página de visualização de todos os pacientes
},
{
href: "#",
icon: Calendar,
label: "Configurações",
// Botão para página de consultas marcadas do médico atual
},
];
const cancelLogout = () => setShowLogoutDialog(false); if (!managerData) {
return <div>Carregando...</div>;
}
const menuItems = [ return (
{ href: "#", icon: Home, label: "Dashboard" }, <div className="min-h-screen bg-gray-50 flex">
{ href: "#", icon: Calendar, label: "Relatórios gerenciais" }, {/* Sidebar */}
{ href: "#", icon: User, label: "Gestão de Usuários" }, <div className={`bg-white border-r border-gray-200 transition-all duration-300 ${sidebarCollapsed ? "w-16" : "w-64"} fixed left-0 top-0 h-screen flex flex-col z-10`}>
{ href: "#", icon: User, label: "Gestão de Médicos" }, <div className="p-4 border-b border-gray-200">
{ href: "#", icon: Calendar, label: "Configurações" }, <div className="flex items-center justify-between">
]; {!sidebarCollapsed && (
<div className="flex items-center gap-2">
if (!managerData) { <div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
return <div>Carregando...</div>; <div className="w-4 h-4 bg-white rounded-sm"></div>
} </div>
<span className="font-semibold text-gray-900">Hospital System</span>
return ( </div>
<div className="min-h-screen bg-gray-50 flex"> )}
{/* Sidebar */} <Button variant="ghost" size="sm" onClick={() => setSidebarCollapsed(!sidebarCollapsed)} className="p-1">
<div {sidebarCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
className={`bg-white border-r border-gray-200 transition-all duration-300 fixed top-0 h-screen flex flex-col z-30 </Button>
${sidebarCollapsed ? "w-16" : "w-64"}`} </div>
>
{/* Logo + collapse button */}
<div className="p-4 border-b border-gray-200 flex items-center justify-between">
{!sidebarCollapsed && (
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
<div className="w-4 h-4 bg-white rounded-sm"></div>
</div>
<span className="font-semibold text-gray-900">
Hospital System
</span>
</div>
)}
<Button
variant="ghost"
size="sm"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="p-1"
>
{sidebarCollapsed ? (
<ChevronRight className="w-4 h-4" />
) : (
<ChevronLeft className="w-4 h-4" />
)}
</Button>
</div>
{/* Menu Items */}
<nav className="flex-1 p-2 overflow-y-auto">
{menuItems.map((item) => {
const Icon = item.icon;
const isActive =
pathname === item.href ||
(item.href !== "/" && pathname.startsWith(item.href));
return (
<Link key={item.href} href={item.href}>
<div
className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${
isActive
? "bg-blue-50 text-blue-600 border-r-2 border-blue-600"
: "text-gray-600 hover:bg-gray-50"
}`}
>
<Icon className="w-5 h-5 flex-shrink-0" />
{!sidebarCollapsed && (
<span className="font-medium">{item.label}</span>
)}
</div> </div>
</Link>
);
})}
</nav>
{/* Perfil no rodapé */} <nav className="flex-1 p-2 overflow-y-auto">
<div className="border-t p-4 mt-auto"> {menuItems.map((item) => {
<div className="flex items-center space-x-3 mb-4"> const Icon = item.icon;
<Avatar> const isActive = pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href));
<AvatarImage src="/placeholder.svg?height=40&width=40" />
<AvatarFallback>
{managerData.name
.split(" ")
.map((n) => n[0])
.join("")}
</AvatarFallback>
</Avatar>
{!sidebarCollapsed && (
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate">
{managerData.name}
</p>
<p className="text-xs text-gray-500 truncate">
{managerData.department}
</p>
</div>
)}
</div>
{/* Botão Sair - ajustado para responsividade */}
<Button
variant="outline"
size="sm"
className={
sidebarCollapsed
? "w-full bg-transparent flex justify-center items-center p-2" // Centraliza o ícone quando colapsado
: "w-full bg-transparent"
}
onClick={handleLogout}
>
<LogOut
className={sidebarCollapsed ? "h-5 w-5" : "mr-2 h-4 w-4"}
/>{" "}
{/* Remove margem quando colapsado */}
{!sidebarCollapsed && "Sair"}{" "}
{/* Mostra o texto apenas quando não está colapsado */}
</Button>
</div>
</div>
{/* Conteúdo principal */} return (
<div <Link key={item.href} href={item.href}>
className={`flex-1 flex flex-col transition-all duration-300 w-full <div className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${isActive ? "bg-blue-50 text-blue-600 border-r-2 border-blue-600" : "text-gray-600 hover:bg-gray-50"}`}>
${sidebarCollapsed ? "ml-16" : "ml-64"}`} <Icon className="w-5 h-5 flex-shrink-0" />
> {!sidebarCollapsed && <span className="font-medium">{item.label}</span>}
{/* Header */} </div>
<header className="bg-white border-b border-gray-200 px-4 md:px-6 py-4 flex items-center justify-between"> </Link>
{/* Search */} );
<div className="flex items-center gap-4 flex-1 max-w-md"> })}
<div className="relative flex-1"> </nav>
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input <div className="border-t p-4 mt-auto">
placeholder="Buscar paciente" <div className="flex items-center space-x-3 mb-4">
className="pl-10 bg-gray-50 border-gray-200" <Avatar>
/> <AvatarImage src="/placeholder.svg?height=40&width=40" />
<AvatarFallback>
{managerData.name
.split(" ")
.map((n) => n[0])
.join("")}
</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-gray-900 truncate">{managerData.name}</p>
<p className="text-xs text-gray-500 truncate">{managerData.department}</p>
</div>
</div>
<Button variant="outline" size="sm" className="w-full bg-transparent" onClick={handleLogout}>
<LogOut className="mr-2 h-4 w-4" />
Sair
</Button>
</div>
</div> </div>
</div>
{/* Notifications */} {/* Main Content */}
<div className="flex items-center gap-4 ml-auto"> <div className={`flex-1 flex flex-col transition-all duration-300 ${sidebarCollapsed ? "ml-16" : "ml-64"}`}>
<Button variant="ghost" size="sm" className="relative"> {/* Header */}
<Bell className="w-5 h-5" /> <header className="bg-white border-b border-gray-200 px-6 py-4">
<Badge className="absolute -top-1 -right-1 w-5 h-5 p-0 flex items-center justify-center bg-red-500 text-white text-xs"> <div className="flex items-center justify-between">
1 <div className="flex items-center gap-4 flex-1 max-w-md">
</Badge> <div className="relative flex-1">
</Button> <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
</div> <Input placeholder="Buscar paciente" className="pl-10 bg-gray-50 border-gray-200" />
</header> </div>
</div>
{/* Page Content */} <div className="flex items-center gap-4">
<main className="flex-1 p-4 md:p-6">{children}</main> <Button variant="ghost" size="sm" className="relative">
</div> <Bell className="w-5 h-5" />
<Badge className="absolute -top-1 -right-1 w-5 h-5 p-0 flex items-center justify-center bg-red-500 text-white text-xs">1</Badge>
</Button>
</div>
</div>
</header>
{/* Logout confirmation dialog */} {/* Page Content */}
<Dialog open={showLogoutDialog} onOpenChange={setShowLogoutDialog}> <main className="flex-1 p-6">{children}</main>
<DialogContent className="sm:max-w-md"> </div>
<DialogHeader>
<DialogTitle>Confirmar Saída</DialogTitle> {/* Logout confirmation dialog */}
<DialogDescription> <Dialog open={showLogoutDialog} onOpenChange={setShowLogoutDialog}>
Deseja realmente sair do sistema? Você precisará fazer login <DialogContent className="sm:max-w-md">
novamente para acessar sua conta. <DialogHeader>
</DialogDescription> <DialogTitle>Confirmar Saída</DialogTitle>
</DialogHeader> <DialogDescription>Deseja realmente sair do sistema? Você precisará fazer login novamente para acessar sua conta.</DialogDescription>
<DialogFooter className="flex gap-2"> </DialogHeader>
<Button variant="outline" onClick={cancelLogout}> <DialogFooter className="flex gap-2">
Cancelar <Button variant="outline" onClick={cancelLogout}>
</Button> Cancelar
<Button variant="destructive" onClick={confirmLogout}> </Button>
<LogOut className="mr-2 h-4 w-4" /> <Button variant="destructive" onClick={confirmLogout}>
Sair <LogOut className="mr-2 h-4 w-4" />
</Button> Sair
</DialogFooter> </Button>
</DialogContent> </DialogFooter>
</Dialog> </DialogContent>
</div> </Dialog>
); </div>
);
} }

View File

@ -1,6 +1,7 @@
"use client" "use client"
import type React from "react" import type React from "react"
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import Link from "next/link" import Link from "next/link"
import { useRouter, usePathname } from "next/navigation" import { useRouter, usePathname } from "next/navigation"
@ -11,11 +12,15 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { import {
Search, Search,
Bell, Bell,
Settings,
Users,
UserCheck,
Calendar,
Clock,
User, User,
LogOut, LogOut,
FileText, FileText,
Clock, BarChart3,
Calendar,
Home, Home,
ChevronLeft, ChevronLeft,
ChevronRight, ChevronRight,
@ -50,21 +55,6 @@ export default function HospitalLayout({ children }: HospitalLayoutProps) {
const router = useRouter() const router = useRouter()
const pathname = usePathname() const pathname = usePathname()
// 🔹 Ajuste automático no resize
useEffect(() => {
const handleResize = () => {
if (window.innerWidth < 1024) {
setSidebarCollapsed(true) // colapsa no mobile
} else {
setSidebarCollapsed(false) // expande no desktop
}
}
handleResize()
window.addEventListener("resize", handleResize)
return () => window.removeEventListener("resize", handleResize)
}, [])
useEffect(() => { useEffect(() => {
const data = localStorage.getItem("patientData") const data = localStorage.getItem("patientData")
if (data) { if (data) {
@ -74,7 +64,9 @@ export default function HospitalLayout({ children }: HospitalLayoutProps) {
} }
}, [router]) }, [router])
const handleLogout = () => setShowLogoutDialog(true) const handleLogout = () => {
setShowLogoutDialog(true)
}
const confirmLogout = () => { const confirmLogout = () => {
localStorage.removeItem("patientData") localStorage.removeItem("patientData")
@ -82,14 +74,36 @@ export default function HospitalLayout({ children }: HospitalLayoutProps) {
router.push("/") router.push("/")
} }
const cancelLogout = () => setShowLogoutDialog(false) const cancelLogout = () => {
setShowLogoutDialog(false)
}
const menuItems = [ const menuItems = [
{ href: "/patient/dashboard", icon: Home, label: "Dashboard" }, {
{ href: "/patient/appointments", icon: Calendar, label: "Minhas Consultas" }, href: "/patient/dashboard",
{ href: "/patient/schedule", icon: Clock, label: "Agendar Consulta" }, icon: Home,
{ href: "/patient/reports", icon: FileText, label: "Meus Laudos" }, label: "Dashboard",
{ href: "/patient/profile", icon: User, label: "Meus Dados" }, },
{
href: "/patient/appointments",
icon: Calendar,
label: "Minhas Consultas",
},
{
href: "/patient/schedule",
icon: Clock,
label: "Agendar Consulta",
},
{
href: "/patient/reports",
icon: FileText,
label: "Meus Laudos",
},
{
href: "/patient/profile",
icon: User,
label: "Meus Dados",
},
] ]
if (!patientData) { if (!patientData) {
@ -99,12 +113,7 @@ export default function HospitalLayout({ children }: HospitalLayoutProps) {
return ( return (
<div className="min-h-screen bg-gray-50 flex"> <div className="min-h-screen bg-gray-50 flex">
{/* Sidebar */} {/* Sidebar */}
<div <div className={`bg-white border-r border-gray-200 transition-all duration-300 ${sidebarCollapsed ? "w-16" : "w-64"} fixed left-0 top-0 h-screen flex flex-col z-10`}>
className={`bg-white border-r border-gray-200 transition-all duration-300 ${
sidebarCollapsed ? "w-16" : "w-64"
} fixed left-0 top-0 h-screen flex flex-col z-10`}
>
{/* Header da Sidebar */}
<div className="p-4 border-b border-gray-200"> <div className="p-4 border-b border-gray-200">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
{!sidebarCollapsed && ( {!sidebarCollapsed && (
@ -112,54 +121,35 @@ export default function HospitalLayout({ children }: HospitalLayoutProps) {
<div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center"> <div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
<div className="w-4 h-4 bg-white rounded-sm"></div> <div className="w-4 h-4 bg-white rounded-sm"></div>
</div> </div>
<span className="font-semibold text-gray-900"> <span className="font-semibold text-gray-900">Hospital System</span>
Hospital System
</span>
</div> </div>
)} )}
<Button <Button variant="ghost" size="sm" onClick={() => setSidebarCollapsed(!sidebarCollapsed)} className="p-1">
variant="ghost" {sidebarCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
size="sm"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="p-1"
>
{sidebarCollapsed ? (
<ChevronRight className="w-4 h-4" />
) : (
<ChevronLeft className="w-4 h-4" />
)}
</Button> </Button>
</div> </div>
</div> </div>
{/* Menu */}
<nav className="flex-1 p-2 overflow-y-auto"> <nav className="flex-1 p-2 overflow-y-auto">
{menuItems.map((item) => { {menuItems.map((item) => {
const Icon = item.icon const Icon = item.icon
const isActive = const isActive = pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href))
pathname === item.href ||
(item.href !== "/" && pathname.startsWith(item.href))
return ( return (
<Link key={item.href} href={item.href}> <Link key={item.href} href={item.href}>
<div <div
className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${ className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${
isActive isActive ? "bg-blue-50 text-blue-600 border-r-2 border-blue-600" : "text-gray-600 hover:bg-gray-50"
? "bg-blue-50 text-blue-600 border-r-2 border-blue-600"
: "text-gray-600 hover:bg-gray-50"
}`} }`}
> >
<Icon className="w-5 h-5 flex-shrink-0" /> <Icon className="w-5 h-5 flex-shrink-0" />
{!sidebarCollapsed && ( {!sidebarCollapsed && <span className="font-medium">{item.label}</span>}
<span className="font-medium">{item.label}</span>
)}
</div> </div>
</Link> </Link>
) )
})} })}
</nav> </nav>
{/* Rodapé com Avatar e Logout */}
<div className="border-t p-4 mt-auto"> <div className="border-t p-4 mt-auto">
<div className="flex items-center space-x-3 mb-4"> <div className="flex items-center space-x-3 mb-4">
<Avatar> <Avatar>
@ -171,54 +161,27 @@ export default function HospitalLayout({ children }: HospitalLayoutProps) {
.join("")} .join("")}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
{!sidebarCollapsed && ( <div className="flex-1 min-w-0">
<div className="flex-1 min-w-0"> <p className="text-sm font-medium text-gray-900 truncate">{patientData.name}</p>
<p className="text-sm font-medium text-gray-900 truncate"> <p className="text-xs text-gray-500 truncate">{patientData.email}</p>
{patientData.name} </div>
</p>
<p className="text-xs text-gray-500 truncate">
{patientData.email}
</p>
</div>
)}
</div> </div>
{/* Botão Sair - ajustado para responsividade */} <Button variant="outline" size="sm" className="w-full bg-transparent" onClick={handleLogout}>
<Button <LogOut className="mr-2 h-4 w-4" />
variant="outline" Sair
size="sm"
className={
sidebarCollapsed
? "w-full bg-transparent flex justify-center items-center p-2" // Centraliza o ícone quando colapsado
: "w-full bg-transparent"
}
onClick={handleLogout}
>
<LogOut
className={sidebarCollapsed ? "h-5 w-5" : "mr-2 h-4 w-4"}
/>{" "}
{/* Remove margem quando colapsado */}
{!sidebarCollapsed && "Sair"}{" "}
{/* Mostra o texto apenas quando não está colapsado */}
</Button> </Button>
</div> </div>
</div> </div>
{/* Main Content */} {/* Main Content */}
<div <div className={`flex-1 flex flex-col transition-all duration-300 ${sidebarCollapsed ? "ml-16" : "ml-64"}`}>
className={`flex-1 flex flex-col transition-all duration-300 ${
sidebarCollapsed ? "ml-16" : "ml-64"
}`}
>
{/* Header */} {/* Header */}
<header className="bg-white border-b border-gray-200 px-6 py-4"> <header className="bg-white border-b border-gray-200 px-6 py-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-4 flex-1 max-w-md"> <div className="flex items-center gap-4 flex-1 max-w-md">
<div className="relative flex-1"> <div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" /> <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input <Input placeholder="Buscar paciente" className="pl-10 bg-gray-50 border-gray-200" />
placeholder="Buscar paciente"
className="pl-10 bg-gray-50 border-gray-200"
/>
</div> </div>
</div> </div>
@ -243,8 +206,7 @@ export default function HospitalLayout({ children }: HospitalLayoutProps) {
<DialogHeader> <DialogHeader>
<DialogTitle>Confirmar Saída</DialogTitle> <DialogTitle>Confirmar Saída</DialogTitle>
<DialogDescription> <DialogDescription>
Deseja realmente sair do sistema? Você precisará fazer login Deseja realmente sair do sistema? Você precisará fazer login novamente para acessar sua conta.
novamente para acessar sua conta.
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<DialogFooter className="flex gap-2"> <DialogFooter className="flex gap-2">

View File

@ -1,10 +1,10 @@
"use client" "use client"
import type React from "react" import type React from "react"
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import { useRouter, usePathname } from "next/navigation" import { useRouter, usePathname } from "next/navigation"
import Link from "next/link" import Link from "next/link"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge" import { Badge } from "@/components/ui/badge"
@ -17,28 +17,17 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog" } from "@/components/ui/dialog"
import { Search, Bell, Calendar, Clock, User, LogOut, Menu, X, Home, FileText, ChevronLeft, ChevronRight } from "lucide-react"
import {
Search,
Bell,
Calendar,
Clock,
User,
LogOut,
Home,
ChevronLeft,
ChevronRight,
} from "lucide-react"
interface SecretaryData { interface SecretaryData {
id: string id: string,
name: string name: string,
email: string email: string,
phone: string phone: string,
cpf: string cpf: string,
employeeId: string employeeId: string,
department: string department: string,
permissions: object permissions: object,
} }
interface PatientLayoutProps { interface PatientLayoutProps {
@ -46,58 +35,70 @@ interface PatientLayoutProps {
} }
export default function SecretaryLayout({ children }: PatientLayoutProps) { export default function SecretaryLayout({ children }: PatientLayoutProps) {
const [secretaryData, setSecretaryData] = useState<SecretaryData | null>(null)
const [sidebarCollapsed, setSidebarCollapsed] = useState(false) const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
const [showLogoutDialog, setShowLogoutDialog] = useState(false) const [showLogoutDialog, setShowLogoutDialog] = useState(false)
const router = useRouter() const router = useRouter()
const pathname = usePathname() const pathname = usePathname()
// 🔹 Colapsar no mobile e expandir no desktop automaticamente
useEffect(() => { useEffect(() => {
const handleResize = () => { const data = localStorage.getItem("secretaryData")
if (window.innerWidth < 1024) { if (data) {
setSidebarCollapsed(true) setSecretaryData(JSON.parse(data))
} else { } else {
setSidebarCollapsed(false) router.push("/patient/login")
}
} }
handleResize() }, [router])
window.addEventListener("resize", handleResize)
return () => window.removeEventListener("resize", handleResize) const handleLogout = () => {
}, []) setShowLogoutDialog(true)
}
const handleLogout = () => setShowLogoutDialog(true)
const confirmLogout = () => { const confirmLogout = () => {
localStorage.removeItem("secretaryData")
setShowLogoutDialog(false) setShowLogoutDialog(false)
router.push("/") router.push("/")
} }
const cancelLogout = () => setShowLogoutDialog(false)
const cancelLogout = () => {
setShowLogoutDialog(false)
}
const menuItems = [ const menuItems = [
{ href: "##", icon: Home, label: "Dashboard" }, {
{ href: "###", icon: Calendar, label: "Consultas" }, href: "##",
{ href: "#", icon: Clock, label: "Agendar Consulta" }, icon: Home,
{ href: "/secretary/pacientes", icon: User, label: "Pacientes" }, label: "Dashboard",
// Botão para o dashboard da secretária
},
{
href: "###",
icon: Calendar,
label: "Consultas",
// Botão para página de consultas marcadas
},
{
href: "#",
icon: Clock,
label: "Agendar Consulta",
// Botão para página de agendamento da consulta para o paciente
},
{
href: "/secretary/pacientes",
icon: User,
label: "Pacientes",
// Botão para a página de visualização de todos os pacientes
},
] ]
const secretaryData: SecretaryData = { if (!secretaryData) {
id: "1", return <div>Carregando...</div>
name: "Secretária Exemplo",
email: "secretaria@hospital.com",
phone: "999999999",
cpf: "000.000.000-00",
employeeId: "12345",
department: "Atendimento",
permissions: {},
} }
return ( return (
<div className="min-h-screen bg-gray-50 flex"> <div className="min-h-screen bg-gray-50 flex">
{/* Sidebar */} {/* Sidebar */}
<div <div className={`bg-white border-r border-gray-200 transition-all duration-300 ${sidebarCollapsed ? "w-16" : "w-64"} fixed left-0 top-0 h-screen flex flex-col z-10`}>
className={`bg-white border-r border-gray-200 transition-all duration-300
${sidebarCollapsed ? "w-16" : "w-64"}
fixed left-0 top-0 h-screen flex flex-col z-10`}
>
<div className="p-4 border-b border-gray-200"> <div className="p-4 border-b border-gray-200">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
{!sidebarCollapsed && ( {!sidebarCollapsed && (
@ -108,17 +109,8 @@ export default function SecretaryLayout({ children }: PatientLayoutProps) {
<span className="font-semibold text-gray-900">Hospital System</span> <span className="font-semibold text-gray-900">Hospital System</span>
</div> </div>
)} )}
<Button <Button variant="ghost" size="sm" onClick={() => setSidebarCollapsed(!sidebarCollapsed)} className="p-1">
variant="ghost" {sidebarCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
size="sm"
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
className="p-1"
>
{sidebarCollapsed ? (
<ChevronRight className="w-4 h-4" />
) : (
<ChevronLeft className="w-4 h-4" />
)}
</Button> </Button>
</div> </div>
</div> </div>
@ -126,16 +118,13 @@ export default function SecretaryLayout({ children }: PatientLayoutProps) {
<nav className="flex-1 p-2 overflow-y-auto"> <nav className="flex-1 p-2 overflow-y-auto">
{menuItems.map((item) => { {menuItems.map((item) => {
const Icon = item.icon const Icon = item.icon
const isActive = const isActive = pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href))
pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href))
return ( return (
<Link key={item.href} href={item.href}> <Link key={item.href} href={item.href}>
<div <div
className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${ className={`flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors ${
isActive isActive ? "bg-blue-50 text-blue-600 border-r-2 border-blue-600" : "text-gray-600 hover:bg-gray-50"
? "bg-blue-50 text-blue-600 border-r-2 border-blue-600"
: "text-gray-600 hover:bg-gray-50"
}`} }`}
> >
<Icon className="w-5 h-5 flex-shrink-0" /> <Icon className="w-5 h-5 flex-shrink-0" />
@ -157,63 +146,31 @@ export default function SecretaryLayout({ children }: PatientLayoutProps) {
.join("")} .join("")}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
{!sidebarCollapsed && ( <div className="flex-1 min-w-0">
<div className="flex-1 min-w-0"> <p className="text-sm font-medium text-gray-900 truncate">{secretaryData.name}</p>
<p className="text-sm font-medium text-gray-900 truncate"> <p className="text-xs text-gray-500 truncate">{secretaryData.email}</p>
{secretaryData.name} </div>
</p>
<p className="text-xs text-gray-500 truncate">{secretaryData.email}</p>
</div>
)}
</div> </div>
{/* Botão Sair - ajustado para responsividade */} <Button variant="outline" size="sm" className="w-full bg-transparent" onClick={handleLogout}>
<Button <LogOut className="mr-2 h-4 w-4" />
variant="outline" Sair
size="sm"
className={
sidebarCollapsed
? "w-full bg-transparent flex justify-center items-center p-2" // Centraliza o ícone quando colapsado
: "w-full bg-transparent"
}
onClick={handleLogout}
>
<LogOut
className={sidebarCollapsed ? "h-5 w-5" : "mr-2 h-4 w-4"}
/>{" "}
{/* Remove margem quando colapsado */}
{!sidebarCollapsed && "Sair"}{" "}
{/* Mostra o texto apenas quando não está colapsado */}
</Button> </Button>
</div> </div>
</div> </div>
{/* Main Content */} {/* Main Content */}
<div <div className={`flex-1 flex flex-col transition-all duration-300 ${sidebarCollapsed ? "ml-16" : "ml-64"}`}>
className={`flex-1 flex flex-col transition-all duration-300 ${
sidebarCollapsed ? "ml-16" : "ml-64"
}`}
>
{/* Header */} {/* Header */}
<header className="bg-white border-b border-gray-200 px-6 py-4"> <header className="bg-white border-b border-gray-200 px-6 py-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-4 flex-1 max-w-md"> <div className="flex items-center gap-4 flex-1 max-w-md">
<div className="relative flex-1"> <div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" /> <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input <Input placeholder="Buscar paciente" className="pl-10 bg-gray-50 border-gray-200" />
placeholder="Buscar paciente"
className="pl-10 bg-gray-50 border-gray-200"
/>
</div> </div>
</div> </div>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
{/* Este botão no header parece ter sido uma cópia do botão "Sair" da sidebar.
Removi a lógica de sidebarCollapsed aqui, pois o header é independente.
Se a intenção era ter um botão de logout no header, ele não deve ser afetado pela sidebar.
Ajustei para ser um botão de sino de notificação, como nos exemplos anteriores,
que você tem o ícone Bell importado e uma badge para notificação.
Se você quer um botão de LogOut aqui, por favor, me avise!
*/}
<Button variant="ghost" size="sm" className="relative"> <Button variant="ghost" size="sm" className="relative">
<Bell className="w-5 h-5" /> <Bell className="w-5 h-5" />
<Badge className="absolute -top-1 -right-1 w-5 h-5 p-0 flex items-center justify-center bg-red-500 text-white text-xs"> <Badge className="absolute -top-1 -right-1 w-5 h-5 p-0 flex items-center justify-center bg-red-500 text-white text-xs">