File size: 6,874 Bytes
89a11b6
 
a79917c
 
 
 
 
 
d7fe8fb
a79917c
89a11b6
ae6419f
 
a79917c
89a11b6
ae6419f
a79917c
19a0889
 
 
 
 
a79917c
 
ae6419f
a79917c
 
 
89a11b6
d7fe8fb
a79917c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0e29296
 
19a0889
0e29296
 
19a0889
 
 
 
0e29296
a79917c
 
 
 
 
bb09573
a79917c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89a11b6
a79917c
 
 
 
 
89a11b6
 
 
a79917c
 
 
 
 
89a11b6
a79917c
 
 
 
 
 
 
 
 
7312b0b
 
57c6d6d
7312b0b
 
 
 
 
 
 
 
c94d5d9
 
 
 
7312b0b
 
 
 
 
 
ae6419f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a79917c
 
89a11b6
a79917c
 
 
 
 
 
 
 
 
 
 
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
173
174
175
176
177
178
179
180
181
182
183
184
185
// frontend/src/Layout.jsx

import React, { useState } from "react";
import { Link } from "react-router-dom";
import { createPageUrl } from "./utils";
import {
  LayoutDashboard,
  History as HistoryIcon,
  Key,
  ChevronLeft,
  Sparkles,
  LogOut,
  User,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { useAuth } from "./contexts/AuthContext";

// Import logo - Vite will process this and handle the path correctly
// For production, the logo should be in frontend/public/logo.png
// Vite will copy it to dist/logo.png during build
const logoPath = "/logo.png";

export default function Layout({ children, currentPageName }) {
  const [collapsed, setCollapsed] = useState(false);
  const { user, logout } = useAuth();

  const navItems = [
    { name: "Dashboard", icon: LayoutDashboard, page: "Dashboard" },
    { name: "History", icon: HistoryIcon, page: "History" },
    { name: "API Keys", icon: Key, page: "API Keys" },
  ];

  return (
    <div className="min-h-screen bg-[#FAFAFA] flex">
      {/* Sidebar */}
      <aside
        className={cn(
          "fixed left-0 top-0 h-screen bg-white border-r border-slate-200/80 z-50 transition-all duration-300 ease-out flex flex-col",
          collapsed ? "w-[72px]" : "w-[260px]"
        )}
      >
        {/* Logo */}
        <div
          className={cn(
            "h-16 flex items-center border-b border-slate-100 px-4",
            collapsed ? "justify-center" : "justify-between"
          )}
        >
          <Link to={createPageUrl("Dashboard")} className="flex items-center gap-3">
            <div className="h-9 w-9 flex items-center justify-center flex-shrink-0">
              <img 
                src={logoPath}
                alt="EZOFIS AI Logo" 
                className="h-full w-full object-contain"
                onError={(e) => {
                  // Fallback: hide image and show placeholder if logo not found
                  e.target.style.display = 'none';
                }}
              />
            </div>
            {!collapsed && (
              <div className="flex flex-col">
                <span className="font-semibold text-slate-900 tracking-tight">EZOFIS AI</span>
                <span className="text-[10px] text-slate-400 font-medium tracking-wide uppercase">
                  VRP Intelligence
                </span>
              </div>
            )}
          </Link>
          {!collapsed && (
            <button
              onClick={() => setCollapsed(true)}
              className="h-7 w-7 rounded-lg hover:bg-slate-100 flex items-center justify-center text-slate-400 hover:text-slate-600 transition-colors"
            >
              <ChevronLeft className="h-4 w-4" />
            </button>
          )}
        </div>

        {/* Navigation */}
        <nav className="flex-1 p-3 space-y-1">
          {navItems.map((item) => {
            const isActive = currentPageName === item.page;
            return (
              <Link
                key={item.name}
                to={createPageUrl(item.page)}
                className={cn(
                  "flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 group",
                  isActive
                    ? "bg-gradient-to-r from-indigo-50 to-violet-50 text-indigo-600"
                    : "text-slate-500 hover:bg-slate-50 hover:text-slate-700"
                )}
              >
                <item.icon
                  className={cn(
                    "h-5 w-5 flex-shrink-0",
                    isActive ? "text-indigo-600" : "text-slate-400 group-hover:text-slate-600"
                  )}
                />
                {!collapsed && (
                  <span className="font-medium text-sm">{item.name}</span>
                )}
              </Link>
            );
          })}
        </nav>

        {/* Collapse Toggle (when collapsed) */}
        {collapsed && (
          <button
            onClick={() => setCollapsed(false)}
            className="m-3 h-10 rounded-xl bg-slate-50 hover:bg-slate-100 flex items-center justify-center text-slate-400 hover:text-slate-600 transition-colors"
          >
            <ChevronLeft className="h-4 w-4 rotate-180" />
          </button>
        )}

        {/* Pro Badge */}
        {!collapsed && (
          <div className="p-3">
            <div className="p-4 rounded-2xl bg-gradient-to-br from-slate-900 to-slate-800 text-white">
              <div className="flex items-center gap-2 mb-2">
                <Sparkles className="h-4 w-4 text-amber-400" />
                <span className="text-xs font-semibold tracking-wide">DEPLOY CUSTOM AGENT</span>
              </div>
              <p className="text-xs text-slate-400 mb-3">
              Batch extractions, custom model, field mapping, complex lineitems, tables, workflows,  &amp; API access
              </p>
              <button 
                className="w-full py-2 px-3 rounded-lg bg-white text-slate-900 text-sm font-semibold hover:bg-slate-100 transition-colors"
                onClick={() => window.open("https://calendar.app.google/UTx9ZiBXhpMqCVyaA", "_blank", "noopener,noreferrer")}
              >
                Book a Custom Demo
              </button>
            </div>
          </div>
        )}

        {/* User Profile */}
        {!collapsed && user && (
          <div className="p-3 border-t border-slate-200">
            <div className="flex items-center gap-3 p-3 rounded-xl bg-slate-50 hover:bg-slate-100 transition-colors">
              {user.picture ? (
                <img
                  src={user.picture}
                  alt={user.name || user.email}
                  className="h-10 w-10 rounded-lg object-cover"
                />
              ) : (
                <div className="h-10 w-10 rounded-lg bg-indigo-100 flex items-center justify-center">
                  <User className="h-5 w-5 text-indigo-600" />
                </div>
              )}
              <div className="flex-1 min-w-0">
                <p className="text-sm font-medium text-slate-900 truncate">
                  {user.name || "User"}
                </p>
                <p className="text-xs text-slate-500 truncate">{user.email}</p>
              </div>
            </div>
            <button
              onClick={logout}
              className="mt-2 w-full flex items-center gap-2 px-3 py-2 rounded-xl text-sm text-slate-600 hover:bg-red-50 hover:text-red-600 transition-colors"
            >
              <LogOut className="h-4 w-4" />
              <span>Sign Out</span>
            </button>
          </div>
        )}
      </aside>

      {/* Main Content */}
      <main
        className={cn(
          "flex-1 transition-all duration-300",
          collapsed ? "ml-[72px]" : "ml-[260px]"
        )}
      >
        {children}
      </main>
    </div>
  );
}