nova sidebar
This commit is contained in:
parent
01aecc4485
commit
cfc6a105b5
@ -5,271 +5,331 @@ import type React from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Cookies from "js-cookie"; // Mantido apenas para a limpeza de segurança no logout
|
||||
import Cookies from "js-cookie";
|
||||
import { api } from "@/services/api.mjs";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
import { LogOut, ChevronLeft, ChevronRight, Home, CalendarCheck2, ClipboardPlus, CalendarClock, Users, SquareUser, ClipboardList, Stethoscope, ClipboardMinus } from "lucide-react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
|
||||
import {
|
||||
LogOut,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Home,
|
||||
CalendarCheck2,
|
||||
ClipboardPlus,
|
||||
CalendarClock,
|
||||
Users,
|
||||
SquareUser,
|
||||
ClipboardList,
|
||||
Stethoscope,
|
||||
ClipboardMinus,
|
||||
} from "lucide-react";
|
||||
|
||||
import SidebarUserSection from "@/components/ui/userToolTip";
|
||||
|
||||
interface UserData {
|
||||
id: string;
|
||||
email: string;
|
||||
app_metadata: {
|
||||
user_role: string;
|
||||
};
|
||||
user_metadata: {
|
||||
cpf: string;
|
||||
email_verified: boolean;
|
||||
full_name: string;
|
||||
phone_mobile: string;
|
||||
role: string;
|
||||
};
|
||||
identities: {
|
||||
identity_id: string;
|
||||
id: string;
|
||||
email: string;
|
||||
app_metadata: {
|
||||
user_role: string;
|
||||
};
|
||||
user_metadata: {
|
||||
cpf: string;
|
||||
email_verified: boolean;
|
||||
full_name: string;
|
||||
phone_mobile: string;
|
||||
role: string;
|
||||
};
|
||||
identities: {
|
||||
identity_id: string;
|
||||
id: string;
|
||||
user_id: string;
|
||||
provider: string;
|
||||
}[];
|
||||
is_anonymous: boolean;
|
||||
user_id: string;
|
||||
provider: string;
|
||||
}[];
|
||||
is_anonymous: boolean;
|
||||
}
|
||||
|
||||
interface MenuItem {
|
||||
href: string;
|
||||
icon: React.ElementType;
|
||||
label: string;
|
||||
href: string;
|
||||
icon: React.ElementType;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface SidebarProps {
|
||||
children: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function Sidebar({ children }: SidebarProps) {
|
||||
const [userData, setUserData] = useState<UserData>();
|
||||
const [role, setRole] = useState<string>();
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
||||
const [showLogoutDialog, setShowLogoutDialog] = useState(false);
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const [userData, setUserData] = useState<UserData>();
|
||||
const [role, setRole] = useState<string>();
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
||||
const [showLogoutDialog, setShowLogoutDialog] = useState(false);
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
const userInfoString = localStorage.getItem("user_info");
|
||||
// --- ALTERAÇÃO 1: Buscando o token no localStorage ---
|
||||
const token = localStorage.getItem("token");
|
||||
useEffect(() => {
|
||||
const userInfoString = localStorage.getItem("user_info");
|
||||
const token = localStorage.getItem("token");
|
||||
|
||||
if (userInfoString && token) {
|
||||
const userInfo = JSON.parse(userInfoString);
|
||||
if (userInfoString && token) {
|
||||
const userInfo = JSON.parse(userInfoString);
|
||||
|
||||
setUserData({
|
||||
id: userInfo.id ?? "",
|
||||
email: userInfo.email ?? "",
|
||||
app_metadata: {
|
||||
user_role: userInfo.app_metadata?.user_role ?? "patient",
|
||||
},
|
||||
user_metadata: {
|
||||
cpf: userInfo.user_metadata?.cpf ?? "",
|
||||
email_verified: userInfo.user_metadata?.email_verified ?? false,
|
||||
full_name: userInfo.user_metadata?.full_name ?? "",
|
||||
phone_mobile: userInfo.user_metadata?.phone_mobile ?? "",
|
||||
role: userInfo.user_metadata?.role ?? "",
|
||||
},
|
||||
identities:
|
||||
userInfo.identities?.map((identity: any) => ({
|
||||
identity_id: identity.identity_id ?? "",
|
||||
id: identity.id ?? "",
|
||||
user_id: identity.user_id ?? "",
|
||||
provider: identity.provider ?? "",
|
||||
})) ?? [],
|
||||
is_anonymous: userInfo.is_anonymous ?? false,
|
||||
});
|
||||
setRole(userInfo.user_metadata?.role);
|
||||
} else {
|
||||
// O redirecionamento para /login já estava correto. Ótimo!
|
||||
router.push("/login");
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth < 1024) {
|
||||
setSidebarCollapsed(true);
|
||||
} else {
|
||||
setSidebarCollapsed(false);
|
||||
}
|
||||
};
|
||||
handleResize();
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
|
||||
const handleLogout = () => setShowLogoutDialog(true);
|
||||
|
||||
// --- ALTERAÇÃO 2: A função de logout agora é MUITO mais simples ---
|
||||
const confirmLogout = async () => {
|
||||
try {
|
||||
// Chama a função centralizada para fazer o logout no servidor
|
||||
await api.logout();
|
||||
} catch (error) {
|
||||
// O erro já é logado dentro da função api.logout, não precisamos fazer nada aqui
|
||||
} finally {
|
||||
// A responsabilidade do componente é apenas limpar o estado local e redirecionar
|
||||
localStorage.removeItem("user_info");
|
||||
localStorage.removeItem("token");
|
||||
Cookies.remove("access_token"); // Limpeza de segurança
|
||||
|
||||
setShowLogoutDialog(false);
|
||||
router.push("/"); // Redireciona para a home
|
||||
}
|
||||
};
|
||||
|
||||
const cancelLogout = () => setShowLogoutDialog(false);
|
||||
|
||||
const SetMenuItems = (role: any) => {
|
||||
const patientItems: MenuItem[] = [
|
||||
{ href: "/patient/dashboard", icon: Home, label: "Dashboard" },
|
||||
{
|
||||
href: "/patient/schedule",
|
||||
icon: CalendarClock,
|
||||
label: "Agendar Consulta",
|
||||
},
|
||||
{
|
||||
href: "/patient/appointments",
|
||||
icon: CalendarCheck2,
|
||||
label: "Minhas Consultas",
|
||||
},
|
||||
{ href: "/patient/reports", icon: ClipboardPlus, label: "Meus Laudos" },
|
||||
{ href: "/patient/profile", icon: SquareUser, label: "Meus Dados" },
|
||||
];
|
||||
|
||||
const doctorItems: MenuItem[] = [
|
||||
{ href: "/doctor/dashboard", icon: Home, label: "Dashboard" },
|
||||
{ href: "/doctor/medicos", icon: Users, label: "Gestão de Pacientes" },
|
||||
{ href: "/doctor/consultas", icon: CalendarCheck2, label: "Consultas" },
|
||||
{
|
||||
href: "/doctor/disponibilidade",
|
||||
icon: ClipboardList,
|
||||
label: "Disponibilidade",
|
||||
},
|
||||
];
|
||||
|
||||
const secretaryItems: MenuItem[] = [
|
||||
{ href: "/secretary/dashboard", icon: Home, label: "Dashboard" },
|
||||
{
|
||||
href: "/secretary/appointments",
|
||||
icon: CalendarCheck2,
|
||||
label: "Consultas",
|
||||
},
|
||||
{
|
||||
href: "/secretary/schedule",
|
||||
icon: CalendarClock,
|
||||
label: "Agendar Consulta",
|
||||
},
|
||||
{
|
||||
href: "/secretary/pacientes",
|
||||
icon: Users,
|
||||
label: "Gestão de Pacientes",
|
||||
},
|
||||
];
|
||||
|
||||
const managerItems: MenuItem[] = [
|
||||
{ href: "/manager/dashboard", icon: Home, label: "Dashboard" },
|
||||
{ href: "#", icon: ClipboardMinus, label: "Relatórios gerenciais" },
|
||||
{ href: "/manager/usuario", icon: Users, label: "Gestão de Usuários" },
|
||||
{ href: "/manager/home", icon: Stethoscope, label: "Gestão de Médicos" },
|
||||
{ href: "/manager/pacientes", icon: Users, label: "Gestão de Pacientes" },
|
||||
{ href: "/secretary/appointments", icon: CalendarCheck2, label: "Consultas" }, //adicionar botão de voltar pra pagina anterior
|
||||
];
|
||||
|
||||
let menuItems: MenuItem[];
|
||||
switch (role) {
|
||||
case "gestor":
|
||||
menuItems = managerItems;
|
||||
break;
|
||||
case "admin":
|
||||
menuItems = managerItems;
|
||||
break;
|
||||
case "medico":
|
||||
menuItems = doctorItems;
|
||||
break;
|
||||
case "secretaria":
|
||||
menuItems = secretaryItems;
|
||||
break;
|
||||
case "paciente":
|
||||
menuItems = patientItems;
|
||||
break;
|
||||
default:
|
||||
menuItems = patientItems;
|
||||
break;
|
||||
}
|
||||
return menuItems;
|
||||
};
|
||||
|
||||
const menuItems = SetMenuItems(role);
|
||||
|
||||
if (!userData) {
|
||||
return <div className="flex h-screen w-full items-center justify-center">Carregando...</div>;
|
||||
setUserData({
|
||||
id: userInfo.id ?? "",
|
||||
email: userInfo.email ?? "",
|
||||
app_metadata: {
|
||||
user_role: userInfo.app_metadata?.user_role ?? "patient",
|
||||
},
|
||||
user_metadata: {
|
||||
cpf: userInfo.user_metadata?.cpf ?? "",
|
||||
email_verified: userInfo.user_metadata?.email_verified ?? false,
|
||||
full_name: userInfo.user_metadata?.full_name ?? "",
|
||||
phone_mobile: userInfo.user_metadata?.phone_mobile ?? "",
|
||||
role: userInfo.user_metadata?.role ?? "",
|
||||
},
|
||||
identities:
|
||||
userInfo.identities?.map((identity: any) => ({
|
||||
identity_id: identity.identity_id ?? "",
|
||||
id: identity.id ?? "",
|
||||
user_id: identity.user_id ?? "",
|
||||
provider: identity.provider ?? "",
|
||||
})) ?? [],
|
||||
is_anonymous: userInfo.is_anonymous ?? false,
|
||||
});
|
||||
setRole(userInfo.user_metadata?.role);
|
||||
} else {
|
||||
router.push("/login");
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth < 1024) {
|
||||
setSidebarCollapsed(true);
|
||||
} else {
|
||||
setSidebarCollapsed(false);
|
||||
}
|
||||
};
|
||||
handleResize();
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
|
||||
const handleLogout = () => setShowLogoutDialog(true);
|
||||
|
||||
const confirmLogout = async () => {
|
||||
try {
|
||||
await api.logout();
|
||||
} catch (error) {
|
||||
} finally {
|
||||
localStorage.removeItem("user_info");
|
||||
localStorage.removeItem("token");
|
||||
Cookies.remove("access_token");
|
||||
|
||||
setShowLogoutDialog(false);
|
||||
router.push("/");
|
||||
}
|
||||
};
|
||||
|
||||
const cancelLogout = () => setShowLogoutDialog(false);
|
||||
|
||||
const SetMenuItems = (role: any) => {
|
||||
const patientItems: MenuItem[] = [
|
||||
{ href: "/patient/dashboard", icon: Home, label: "Dashboard" },
|
||||
{
|
||||
href: "/patient/schedule",
|
||||
icon: CalendarClock,
|
||||
label: "Agendar Consulta",
|
||||
},
|
||||
{
|
||||
href: "/patient/appointments",
|
||||
icon: CalendarCheck2,
|
||||
label: "Minhas Consultas",
|
||||
},
|
||||
{ href: "/patient/reports", icon: ClipboardPlus, label: "Meus Laudos" },
|
||||
{ href: "/patient/profile", icon: SquareUser, label: "Meus Dados" },
|
||||
];
|
||||
|
||||
const doctorItems: MenuItem[] = [
|
||||
{ href: "/doctor/dashboard", icon: Home, label: "Dashboard" },
|
||||
{ href: "/doctor/medicos", icon: Users, label: "Gestão de Pacientes" },
|
||||
{ href: "/doctor/consultas", icon: CalendarCheck2, label: "Consultas" },
|
||||
{
|
||||
href: "/doctor/disponibilidade",
|
||||
icon: ClipboardList,
|
||||
label: "Disponibilidade",
|
||||
},
|
||||
];
|
||||
|
||||
const secretaryItems: MenuItem[] = [
|
||||
{ href: "/secretary/dashboard", icon: Home, label: "Dashboard" },
|
||||
{
|
||||
href: "/secretary/appointments",
|
||||
icon: CalendarCheck2,
|
||||
label: "Consultas",
|
||||
},
|
||||
{
|
||||
href: "/secretary/schedule",
|
||||
icon: CalendarClock,
|
||||
label: "Agendar Consulta",
|
||||
},
|
||||
{
|
||||
href: "/secretary/pacientes",
|
||||
icon: Users,
|
||||
label: "Gestão de Pacientes",
|
||||
},
|
||||
];
|
||||
|
||||
const managerItems: MenuItem[] = [
|
||||
{ href: "/manager/dashboard", icon: Home, label: "Dashboard" },
|
||||
{ href: "#", icon: ClipboardMinus, label: "Relatórios gerenciais" },
|
||||
{ href: "/manager/usuario", icon: Users, label: "Gestão de Usuários" },
|
||||
{ href: "/manager/home", icon: Stethoscope, label: "Gestão de Médicos" },
|
||||
{ href: "/manager/pacientes", icon: Users, label: "Gestão de Pacientes" },
|
||||
{
|
||||
href: "/secretary/appointments",
|
||||
icon: CalendarCheck2,
|
||||
label: "Consultas",
|
||||
},
|
||||
];
|
||||
|
||||
switch (role) {
|
||||
case "gestor":
|
||||
case "admin":
|
||||
return managerItems;
|
||||
case "medico":
|
||||
return doctorItems;
|
||||
case "secretaria":
|
||||
return secretaryItems;
|
||||
case "paciente":
|
||||
default:
|
||||
return patientItems;
|
||||
}
|
||||
};
|
||||
|
||||
const menuItems = SetMenuItems(role);
|
||||
|
||||
if (!userData) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex">
|
||||
<div className={`bg-white border-r border-gray-200 transition-all duration-300 fixed top-0 h-screen flex flex-col z-30 ${sidebarCollapsed ? "w-16" : "w-64"}`}>
|
||||
<div className="p-4 border-b border-gray-200 flex items-center justify-between">
|
||||
{!sidebarCollapsed && (
|
||||
<div className="flex items-center gap-2">
|
||||
{/* 🛑 SUBSTITUIÇÃO: Usando a tag <img> com o caminho da logo */}
|
||||
<img
|
||||
src="/Logo MedConnect.png" // Use o arquivo da logo (ou /android-chrome-512x512.png)
|
||||
alt="Logo MediConnect"
|
||||
className="w-12 h-12 object-contain" // Define o tamanho para w-8 h-8 (32px)
|
||||
/>
|
||||
<span className="font-semibold text-gray-900">MedConnect</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>
|
||||
|
||||
<nav className="flex-1 p-2 overflow-y-auto">
|
||||
{menuItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const isActive = pathname === item.href;
|
||||
return (
|
||||
<Link key={item.label} 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>
|
||||
<SidebarUserSection userData={userData} sidebarCollapsed={false} handleLogout={handleLogout} isActive={role === "paciente" ? false : true}></SidebarUserSection>
|
||||
</div>
|
||||
|
||||
<div className={`flex-1 flex flex-col transition-all duration-300 w-full ${sidebarCollapsed ? "ml-16" : "ml-64"}`}>
|
||||
<header className="bg-gray-50 px-4 md:px-6 py-4 flex items-center justify-between"></header>
|
||||
<main className="flex-1 p-4 md:p-6">{children}</main>
|
||||
</div>
|
||||
|
||||
<Dialog open={showLogoutDialog} onOpenChange={setShowLogoutDialog}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Confirmar Saída</DialogTitle>
|
||||
<DialogDescription>Deseja realmente sair do sistema? Você precisará fazer login novamente para acessar sua conta.</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter className="flex gap-2">
|
||||
<Button variant="outline" onClick={cancelLogout}>
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={confirmLogout}>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
Sair
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
<div className="flex h-screen w-full items-center justify-center">
|
||||
Carregando...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex">
|
||||
<div
|
||||
className={`fixed top-0 h-screen flex flex-col z-30 transition-all duration-300
|
||||
${sidebarCollapsed ? "w-16" : "w-64"}
|
||||
bg-[#123965] text-white`}
|
||||
>
|
||||
{/* TOPO */}
|
||||
<div className="p-4 border-b border-white/10 flex items-center justify-between">
|
||||
{!sidebarCollapsed && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="bg-white p-1 rounded-lg">
|
||||
<img
|
||||
src="/Logo MedConnect.png"
|
||||
alt="Logo MedConnect"
|
||||
className="w-10 h-10 object-contain"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span className="font-semibold text-white text-lg">
|
||||
MedConnect
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
|
||||
className="p-1 text-white hover:bg-white/10 cursor-pointer"
|
||||
>
|
||||
{sidebarCollapsed ? (
|
||||
<ChevronRight className="w-5 h-5" />
|
||||
) : (
|
||||
<ChevronLeft className="w-5 h-5" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* MENU */}
|
||||
<nav className="flex-1 p-3 overflow-y-auto">
|
||||
{menuItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const isActive = pathname === item.href;
|
||||
|
||||
return (
|
||||
<Link key={item.label} href={item.href}>
|
||||
<div
|
||||
className={`
|
||||
flex items-center gap-3 px-3 py-2 rounded-lg mb-1 transition-colors
|
||||
${
|
||||
isActive
|
||||
? "bg-white/20 text-white font-semibold"
|
||||
: "text-white/80 hover:bg-white/10 hover:text-white"
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Icon className="w-5 h-5 flex-shrink-0" />
|
||||
{!sidebarCollapsed && (
|
||||
<span className="font-medium">{item.label}</span>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
|
||||
{/* PERFIL ORIGINAL + NOME BRANCO */}
|
||||
<div className="mt-auto p-3 border-t border-white/10">
|
||||
<SidebarUserSection
|
||||
userData={userData}
|
||||
sidebarCollapsed={sidebarCollapsed}
|
||||
handleLogout={handleLogout}
|
||||
isActive={role !== "paciente"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`flex-1 flex flex-col transition-all duration-300 ${
|
||||
sidebarCollapsed ? "ml-16" : "ml-64"
|
||||
}`}
|
||||
>
|
||||
<main className="flex-1 p-4 md:p-6">{children}</main>
|
||||
</div>
|
||||
<Dialog open={showLogoutDialog} onOpenChange={setShowLogoutDialog}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Confirmar Saída</DialogTitle>
|
||||
<DialogDescription>
|
||||
Deseja realmente sair do sistema? Você precisará fazer login
|
||||
novamente.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter className="flex gap-2">
|
||||
<Button variant="outline" onClick={cancelLogout}>
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={confirmLogout}>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
Sair
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,7 +2,14 @@
|
||||
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CalendarCheck2, CalendarClock, ClipboardPlus, Home, LogOut, SquareUser } from "lucide-react";
|
||||
import {
|
||||
CalendarCheck2,
|
||||
CalendarClock,
|
||||
ClipboardPlus,
|
||||
Home,
|
||||
LogOut,
|
||||
SquareUser,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
@ -34,45 +41,52 @@ export default function SidebarUserSection({
|
||||
handleLogout,
|
||||
isActive,
|
||||
}: Props) {
|
||||
const pathname = usePathname();
|
||||
const menuItems: any[] = [
|
||||
{ href: "/patient/schedule", icon: CalendarClock, label: "Agendar Consulta" },
|
||||
{ href: "/patient/appointments", icon: CalendarCheck2, label: "Minhas Consultas" },
|
||||
{ href: "/patient/reports", icon: ClipboardPlus, label: "Meus Laudos" },
|
||||
{ href: "/patient/profile", icon: SquareUser, label: "Meus Dados" },
|
||||
]
|
||||
const pathname = usePathname();
|
||||
const menuItems: any[] = [
|
||||
{
|
||||
href: "/patient/schedule",
|
||||
icon: CalendarClock,
|
||||
label: "Agendar Consulta",
|
||||
},
|
||||
{
|
||||
href: "/patient/appointments",
|
||||
icon: CalendarCheck2,
|
||||
label: "Minhas Consultas",
|
||||
},
|
||||
{ href: "/patient/reports", icon: ClipboardPlus, label: "Meus Laudos" },
|
||||
{ href: "/patient/profile", icon: SquareUser, label: "Meus Dados" },
|
||||
];
|
||||
return (
|
||||
<div className="border-t p-4 mt-auto">
|
||||
{/* POPUP DE INFORMAÇÕES DO USUÁRIO */}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<div
|
||||
className={`flex items-center space-x-3 mb-4 p-2 rounded-md transition-colors ${
|
||||
isActive
|
||||
? "cursor-pointer hover:bg-gray-100"
|
||||
: "cursor-default pointer-events-none"
|
||||
}`}>
|
||||
<Avatar>
|
||||
<AvatarImage src="/placeholder.svg?height=40&width=40" />
|
||||
<AvatarFallback>
|
||||
{userData.user_metadata.full_name
|
||||
.split(" ")
|
||||
.map((n) => n[0])
|
||||
.join("")}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div
|
||||
className={`flex items-center space-x-3 mb-4 p-2 rounded-md transition-colors ${
|
||||
isActive ? "cursor-pointer" : "cursor-default pointer-events-none"
|
||||
}`}
|
||||
>
|
||||
<Avatar>
|
||||
<AvatarImage src="/placeholder.svg?height=40&width=40" />
|
||||
<AvatarFallback>
|
||||
{userData.user_metadata.full_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">
|
||||
{userData.user_metadata.full_name}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 truncate">
|
||||
{userData.app_metadata.user_role}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!sidebarCollapsed && (
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium text-white truncate">
|
||||
{userData.user_metadata.full_name}
|
||||
</p>
|
||||
<p className="text-xs text-white truncate">
|
||||
{userData.app_metadata.user_role}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</PopoverTrigger>
|
||||
|
||||
{/* Card flutuante */}
|
||||
@ -83,43 +97,47 @@ export default function SidebarUserSection({
|
||||
>
|
||||
<nav>
|
||||
{menuItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const isActive = pathname === item.href;
|
||||
return (
|
||||
<Link key={item.label} 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>
|
||||
);
|
||||
})}
|
||||
const Icon = item.icon;
|
||||
const isActive = pathname === item.href;
|
||||
return (
|
||||
<Link key={item.label} 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>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
{/* Botão de sair */}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className={
|
||||
sidebarCollapsed
|
||||
? "w-full bg-transparent flex justify-center items-center p-2"
|
||||
: "w-full bg-transparent"
|
||||
? "w-full bg-white text-black flex justify-center items-center p-2 hover:bg-gray-200"
|
||||
: "w-full bg-white text-black hover:bg-gray-200"
|
||||
}
|
||||
onClick={handleLogout}
|
||||
>
|
||||
<LogOut className={sidebarCollapsed ? "h-5 w-5" : "mr-2 h-4 w-4"} />
|
||||
{sidebarCollapsed && "Sair"}
|
||||
<LogOut
|
||||
className={
|
||||
sidebarCollapsed ? "h-5 w-5 text-black" : "mr-2 h-4 w-4 text-black"
|
||||
}
|
||||
/>
|
||||
{!sidebarCollapsed && "Sair"}
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user