Álvaro Valenzuela Valdes
feat: implement local database management system with admin stats and clear functions
9c9cca9
"use client";
import { translations, Language } from "../lib/translations";
import { useState, type Dispatch, type SetStateAction } from "react";
type SidebarTab =
| "Dashboard"
| "Tender Search"
| "My Portfolio"
| "Market Monitor"
| "Company Profile"
| "Agent Analysis"
| "Proposal Draft"
| "History"
| "Database"
| "About";
type Props = {
tabs: readonly SidebarTab[];
activeTab: SidebarTab;
onTabSelect: Dispatch<SetStateAction<SidebarTab>>;
status: string;
lang: Language;
forceExpanded?: boolean;
};
export default function Sidebar({ tabs, activeTab, onTabSelect, status, lang, forceExpanded = false }: Props) {
const t = translations[lang];
const [isHovered, setIsHovered] = useState(false);
const isExpanded = forceExpanded || isHovered;
const getTabLabel = (tab: SidebarTab) => {
switch(tab) {
case "Dashboard": return { label: t.dashboard, icon: "📊" };
case "Tender Search": return { label: t.tenderSearch, icon: "📡" };
case "My Portfolio": return { label: t.myPortfolio, icon: "★" };
case "Market Monitor": return { label: "Market Monitor", icon: "🛒" };
case "Company Profile": return { label: t.companyProfile, icon: "🏢" };
case "Agent Analysis": return { label: t.agentAnalysis, icon: "🤖" };
case "Proposal Draft": return { label: t.proposalDraft, icon: "✍️" };
case "History": return { label: t.history, icon: "🕒" };
case "Database": return { label: "Local DB", icon: "🗄️" };
case "About": return { label: t.about, icon: "ℹ️" };
default: return { label: tab, icon: "•" };
}
};
return (
<aside
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
className={`glass-card rounded-2xl md:rounded-3xl h-full md:h-[calc(100vh-3rem)] md:sticky md:top-6 p-3 md:p-4 flex flex-col gap-4 md:gap-8 transition-all duration-500 ease-in-out z-50 border-white/10 ${isExpanded ? 'w-full md:w-72 shadow-2xl shadow-purple-500/10 bg-black/60' : 'w-[84px] shadow-none border-white/5 bg-white/[0.02]'}`}
>
<div className={`flex items-center gap-3 px-2 transition-all duration-300 ${isExpanded ? 'justify-start' : 'justify-center'}`}>
<div className="w-10 h-10 premium-gradient rounded-xl flex-shrink-0 flex items-center justify-center shadow-lg shadow-purple-500/20">
<span className="text-white font-bold text-xl">A</span>
</div>
{isExpanded && (
<div className="animate-in fade-in duration-500">
<h1 className="text-xl font-bold tracking-tight text-white whitespace-nowrap">AndesOps</h1>
<p className="text-[8px] font-black uppercase tracking-[0.3em] text-cyan opacity-50">v1.2.0 • MONOLITH</p>
</div>
)}
</div>
<nav className="flex-1 flex flex-col gap-2 overflow-y-auto overflow-x-hidden custom-scrollbar pr-1">
{tabs.map((tab) => {
const isActive = activeTab === tab;
const { label, icon } = getTabLabel(tab);
const tabSlug = tab.toLowerCase().replace(/ /g, "_");
return (
<button
key={tab}
onClick={() => {
onTabSelect(tab);
window.history.pushState({}, '', `?tab=${tabSlug}`);
}}
className={`flex items-center rounded-2xl transition-all duration-300 active:scale-90 group relative ${
isActive
? "bg-white/10 text-white shadow-[inset_0_0_20px_rgba(255,255,255,0.05)] border border-white/10"
: "text-slate-400 hover:bg-white/5 hover:text-white"
} ${isExpanded ? 'px-5 py-4 gap-4' : 'px-0 py-4 w-full justify-center'}`}
>
<span className={`text-xl transition-all duration-300 ${isActive ? 'scale-110' : 'group-hover:scale-110 opacity-70 group-hover:opacity-100'}`}>
{icon}
</span>
{isExpanded && (
<span className="font-medium text-sm whitespace-nowrap animate-in slide-in-from-left-2 duration-300">
{label}
</span>
)}
{!isExpanded && isActive && (
<div className="absolute right-0 top-1/2 -translate-y-1/2 w-1 h-6 bg-purple-500 rounded-l-full shadow-[0_0_12px_rgba(168,85,247,0.8)]" />
)}
{/* Tooltip for collapsed mode */}
{!isExpanded && (
<div className="absolute left-full ml-4 px-3 py-2 bg-slate-900 text-white text-[10px] font-bold rounded-lg opacity-0 pointer-events-none group-hover:opacity-100 transition-opacity border border-white/10 whitespace-nowrap z-50">
{label}
</div>
)}
</button>
);
})}
</nav>
<div className="mt-auto pt-6 border-t border-white/5">
<div className={`rounded-xl transition-all duration-500 bg-gradient-to-br from-indigo-500/10 to-purple-500/10 border border-indigo-500/20 ${isExpanded ? 'px-4 py-3' : 'p-2 flex justify-center'}`}>
{isExpanded ? (
<>
<p className="text-[10px] uppercase tracking-widest text-indigo-300 font-bold mb-1">Status</p>
<div className="flex items-center gap-2">
<div className={`w-2 h-2 rounded-full ${status === "connected" ? "bg-green-500 animate-pulse" : "bg-yellow-500"}`} />
<span className={`text-xs font-medium ${status === "connected" ? "text-green-300" : "text-yellow-300"}`}>
{status === "connected" ? "Systems Nominal" : "Connection Warning"}
</span>
</div>
</>
) : (
<div className={`w-3 h-3 rounded-full ${status === "connected" ? "bg-green-500 animate-pulse" : "bg-yellow-500"}`} />
)}
</div>
</div>
</aside>
);
}