File size: 8,210 Bytes
5e52bd7
 
 
f353f19
5e52bd7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6314c8a
5e52bd7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
"use client";
import { translations, Language } from "../lib/translations";
import { avatarBase64 } from "../lib/avatar";
import { userPhotoBase64 } from "../lib/user_photo";

import { useState, type Dispatch, type SetStateAction } from "react";

type SidebarTab =
  | "Dashboard"
  | "Tender Search"
  | "My Portfolio"
  | "Market Monitor"
  | "Company Profile"
  | "Agent Analysis"
  | "Proposal Draft"
  | "History"
  | "Documentation"
  | "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 "Documentation": return { label: t.documentation, 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.7 • AMD Hackathon Final</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 space-y-4 pt-6 border-t border-white/5">
        {/* User Profile Section */}
        <div className={`flex items-center gap-3 transition-all duration-300 ${isExpanded ? 'px-2' : 'justify-center'}`}>
          <div className="relative group">
            <div className="absolute -inset-0.5 bg-gradient-to-r from-purple-600 to-cyan-600 rounded-xl blur opacity-20 group-hover:opacity-40 transition"></div>
            <div className="relative w-10 h-10 rounded-xl overflow-hidden border border-white/10 bg-slate-900">
              <img 
                src={avatarBase64} 
                alt="Profile" 
                className="w-full h-full object-cover"
              />
            </div>
          </div>
          {isExpanded && (
            <div className="flex-1 min-w-0 animate-in fade-in slide-in-from-left-2 duration-500 text-left">
              <p className="text-white font-bold text-sm tracking-tight truncate">Álvaro Valenzuela</p>
              <p className="text-[9px] font-black uppercase tracking-widest text-cyan opacity-60">Architect & CEO @ <a href="https://www.rew.cl" target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors underline decoration-cyan/30">REW.cl</a></p>
            </div>
          )}
        </div>

        <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" : 
                  status === "listening" ? "bg-blue-500 animate-bounce" : 
                  status === "warning" ? "bg-yellow-500 animate-pulse" :
                  "bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.5)]"
                }`} />
                <span className={`text-xs font-medium ${
                  status === "connected" ? "text-green-300" : 
                  status === "listening" ? "text-blue-300" : 
                  status === "warning" ? "text-yellow-300" :
                  "text-red-300"
                }`}>
                  {status === "connected" ? "Systems Nominal" : 
                   status === "listening" ? "Synchronizing..." : 
                   status === "warning" ? "Limited Connectivity" :
                   "Connection Offline"}
                </span>
              </div>
            </>
          ) : (
            <div className={`w-3 h-3 rounded-full ${
              status === "connected" ? "bg-green-500 animate-pulse" : 
              status === "listening" ? "bg-blue-500 animate-bounce" : 
              status === "warning" ? "bg-yellow-500 animate-pulse" :
              "bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.5)]"
            }`} />
          )}
        </div>
      </div>
    </aside>
  );
}