refactor: strip sidebar down to project name + status only
Removed all product layer sections (Build, Layouts, Infrastructure, Growth, Monetize, Support, Analytics) from the left sidebar — these are now handled by the in-page left nav inside each tab. Sidebar now shows: logo, Projects/Activity/Settings global nav, project name + colored status dot when inside a project, and the user avatar/sign out at the bottom. Nothing else. Cleaned up all dead code: SectionHeading, SectionRow, SectionDivider, SURFACE_LABELS, SURFACE_ICONS, AppEntry interface, apps state, apps fetch, surfaces/infraApps variables. Made-with: Cursor
This commit is contained in:
@@ -14,104 +14,8 @@ interface ProjectData {
|
||||
productName?: string;
|
||||
name?: string;
|
||||
status?: string;
|
||||
giteaRepo?: string;
|
||||
giteaRepoUrl?: string;
|
||||
surfaces?: string[];
|
||||
surfaceThemes?: Record<string, string>;
|
||||
apps?: Array<{ name: string; path: string; coolifyServiceUuid?: string | null; domain?: string | null }>;
|
||||
}
|
||||
|
||||
interface AppEntry {
|
||||
name: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
// ── Section helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
function SectionHeading({ label, collapsed }: { label: string; collapsed: boolean }) {
|
||||
if (collapsed) return null;
|
||||
return (
|
||||
<div style={{
|
||||
fontSize: "0.58rem", fontWeight: 700, color: "#b5b0a6",
|
||||
letterSpacing: "0.1em", textTransform: "uppercase",
|
||||
padding: "14px 12px 5px",
|
||||
}}>
|
||||
{label}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function SectionRow({
|
||||
icon, label, href, dim, collapsed,
|
||||
}: {
|
||||
icon: string;
|
||||
label: string;
|
||||
href?: string;
|
||||
dim?: boolean;
|
||||
collapsed: boolean;
|
||||
}) {
|
||||
const style: React.CSSProperties = {
|
||||
display: "flex", alignItems: "center",
|
||||
justifyContent: collapsed ? "center" : "flex-start",
|
||||
gap: 8, padding: collapsed ? "7px 0" : "5px 12px",
|
||||
borderRadius: 5, textDecoration: "none",
|
||||
color: dim ? "#c5c0b8" : "#4a4640",
|
||||
fontSize: "0.78rem", fontWeight: 450,
|
||||
transition: "background 0.1s",
|
||||
width: "100%", boxSizing: "border-box" as const,
|
||||
};
|
||||
|
||||
const inner = (
|
||||
<>
|
||||
<span style={{ fontSize: "0.72rem", opacity: 0.6, flexShrink: 0, width: collapsed ? "auto" : 14, textAlign: "center" }}>
|
||||
{icon}
|
||||
</span>
|
||||
{!collapsed && (
|
||||
<span style={{
|
||||
overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
|
||||
fontStyle: dim ? "italic" : "normal",
|
||||
}}>
|
||||
{label}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<Link href={href} title={collapsed ? label : undefined} style={style}
|
||||
onMouseEnter={e => { if (!dim) (e.currentTarget as HTMLElement).style.background = "#f6f4f0"; }}
|
||||
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = "transparent"; }}
|
||||
>
|
||||
{inner}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div title={collapsed ? label : undefined} style={{ ...style, cursor: "default" }}>
|
||||
{inner}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function SectionDivider() {
|
||||
return <div style={{ height: 1, background: "#eae6de", margin: "8px 12px" }} />;
|
||||
}
|
||||
|
||||
// ── Surface label map ────────────────────────────────────────────────────────
|
||||
const SURFACE_LABELS: Record<string, string> = {
|
||||
"marketing": "Marketing site",
|
||||
"web-app": "Web app",
|
||||
"admin": "Admin panel",
|
||||
"api": "API layer",
|
||||
};
|
||||
|
||||
const SURFACE_ICONS: Record<string, string> = {
|
||||
"marketing": "◎",
|
||||
"web-app": "⬡",
|
||||
"admin": "◫",
|
||||
"api": "⌁",
|
||||
};
|
||||
|
||||
// ── Main sidebar ─────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -128,13 +32,11 @@ export function VIBNSidebar({ workspace }: VIBNSidebarProps) {
|
||||
|
||||
// Project-specific data
|
||||
const [project, setProject] = useState<ProjectData | null>(null);
|
||||
const [apps, setApps] = useState<AppEntry[]>([]);
|
||||
|
||||
// Global projects list (used when NOT inside a project)
|
||||
const [projects, setProjects] = useState<Array<{ id: string; productName: string; status?: string }>>([]);
|
||||
|
||||
const activeProjectId = pathname?.match(/\/project\/([^/]+)/)?.[1] ?? null;
|
||||
const activeTab = pathname?.match(/\/project\/[^/]+\/([^/]+)/)?.[1] ?? null;
|
||||
|
||||
// Restore collapse state
|
||||
useEffect(() => {
|
||||
@@ -161,17 +63,12 @@ export function VIBNSidebar({ workspace }: VIBNSidebarProps) {
|
||||
|
||||
// Fetch project-specific data when inside a project
|
||||
useEffect(() => {
|
||||
if (!activeProjectId) { setProject(null); setApps([]); return; }
|
||||
if (!activeProjectId) { setProject(null); return; }
|
||||
|
||||
fetch(`/api/projects/${activeProjectId}`)
|
||||
.then(r => r.json())
|
||||
.then(d => setProject(d.project ?? null))
|
||||
.catch(() => {});
|
||||
|
||||
fetch(`/api/projects/${activeProjectId}/apps`)
|
||||
.then(r => r.json())
|
||||
.then(d => setApps(d.apps ?? []))
|
||||
.catch(() => {});
|
||||
}, [activeProjectId]);
|
||||
|
||||
const isProjects = !activeProjectId && (pathname?.includes("/projects") || pathname?.includes("/project"));
|
||||
@@ -193,11 +90,6 @@ export function VIBNSidebar({ workspace }: VIBNSidebarProps) {
|
||||
|
||||
const base = `/${workspace}/project/${activeProjectId}`;
|
||||
|
||||
// Surfaces locked in on design page
|
||||
const surfaces = project?.surfaces ?? [];
|
||||
// Coolify/monorepo apps
|
||||
const infraApps = project?.apps ?? [];
|
||||
|
||||
return (
|
||||
<nav style={{
|
||||
width: w, height: "100vh",
|
||||
@@ -287,135 +179,36 @@ export function VIBNSidebar({ workspace }: VIBNSidebarProps) {
|
||||
<div style={{ flex: 1, overflow: "auto", paddingBottom: 8 }}>
|
||||
|
||||
{activeProjectId && project ? (
|
||||
/* ── PROJECT VIEW: 7 product layer sections ── */
|
||||
/* ── PROJECT VIEW: name + status only ── */
|
||||
<>
|
||||
{/* Project name */}
|
||||
{!collapsed && (
|
||||
<div style={{ padding: "4px 12px 10px" }}>
|
||||
<div style={{ padding: "6px 12px 8px" }}>
|
||||
<div style={{ fontSize: "0.82rem", fontWeight: 700, color: "#1a1a1a", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
|
||||
{project.productName || project.name || "Project"}
|
||||
</div>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 5, marginTop: 3 }}>
|
||||
<span style={{
|
||||
width: 6, height: 6, borderRadius: "50%", flexShrink: 0,
|
||||
width: 6, height: 6, borderRadius: "50%", flexShrink: 0, display: "inline-block",
|
||||
background: project.status === "live" ? "#2e7d32"
|
||||
: project.status === "building" ? "#3d5afe"
|
||||
: "#d4a04a",
|
||||
display: "inline-block",
|
||||
}} />
|
||||
<span style={{ fontSize: "0.68rem", color: "#8a8478" }}>
|
||||
{project.status === "live" ? "Live"
|
||||
: project.status === "building" ? "Building"
|
||||
: "Defining"}
|
||||
{project.status === "live" ? "Live" : project.status === "building" ? "Building" : "Defining"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── Build ── */}
|
||||
<SectionHeading label="Build" collapsed={collapsed} />
|
||||
{apps.length > 0 ? (
|
||||
apps.map(app => (
|
||||
<SectionRow
|
||||
key={app.name}
|
||||
icon="▢"
|
||||
label={app.name}
|
||||
href={`${base}/build?app=${encodeURIComponent(app.name)}&root=${encodeURIComponent(app.path)}`}
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<SectionRow icon="▢" label="No apps yet" dim href={`${base}/build`} collapsed={collapsed} />
|
||||
{collapsed && (
|
||||
<div style={{ display: "flex", justifyContent: "center", paddingTop: 8 }}>
|
||||
<span style={{
|
||||
width: 7, height: 7, borderRadius: "50%", display: "inline-block",
|
||||
background: project.status === "live" ? "#2e7d32"
|
||||
: project.status === "building" ? "#3d5afe"
|
||||
: "#d4a04a",
|
||||
}} title={project.productName || project.name} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<SectionDivider />
|
||||
|
||||
{/* ── Layouts ── */}
|
||||
<SectionHeading label="Layouts" collapsed={collapsed} />
|
||||
{surfaces.length > 0 ? (
|
||||
surfaces.map(s => (
|
||||
<SectionRow
|
||||
key={s}
|
||||
icon={SURFACE_ICONS[s] ?? "◌"}
|
||||
label={SURFACE_LABELS[s] ?? s}
|
||||
href={`${base}/design?surface=${encodeURIComponent(s)}`}
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<SectionRow icon="◌" label="Not configured" dim href={`${base}/design`} collapsed={collapsed} />
|
||||
)}
|
||||
|
||||
<SectionDivider />
|
||||
|
||||
{/* ── Infrastructure ── */}
|
||||
<SectionHeading label="Infrastructure" collapsed={collapsed} />
|
||||
<SectionRow
|
||||
icon="⬡"
|
||||
label="Builds"
|
||||
href={`${base}/infrastructure?tab=builds`}
|
||||
dim={infraApps.length === 0}
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
<SectionRow
|
||||
icon="◫"
|
||||
label="Databases"
|
||||
href={`${base}/infrastructure?tab=databases`}
|
||||
dim
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
<SectionRow
|
||||
icon="◎"
|
||||
label="Services"
|
||||
href={`${base}/infrastructure?tab=services`}
|
||||
dim
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
<SectionRow
|
||||
icon="≡"
|
||||
label="Environment"
|
||||
href={`${base}/infrastructure?tab=environment`}
|
||||
dim
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
<SectionRow
|
||||
icon="◬"
|
||||
label="Domains"
|
||||
href={`${base}/infrastructure?tab=domains`}
|
||||
dim={!infraApps.some(a => a.domain)}
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
<SectionRow
|
||||
icon="≈"
|
||||
label="Logs"
|
||||
href={`${base}/infrastructure?tab=logs`}
|
||||
dim={infraApps.length === 0}
|
||||
collapsed={collapsed}
|
||||
/>
|
||||
|
||||
<SectionDivider />
|
||||
|
||||
{/* ── Growth ── */}
|
||||
<SectionHeading label="Growth" collapsed={collapsed} />
|
||||
<SectionRow icon="↗" label="Not set up" dim href={`${base}/grow`} collapsed={collapsed} />
|
||||
|
||||
<SectionDivider />
|
||||
|
||||
{/* ── Monetize ── */}
|
||||
<SectionHeading label="Monetize" collapsed={collapsed} />
|
||||
<SectionRow icon="◉" label="Not set up" dim collapsed={collapsed} />
|
||||
|
||||
<SectionDivider />
|
||||
|
||||
{/* ── Support ── */}
|
||||
<SectionHeading label="Support" collapsed={collapsed} />
|
||||
<SectionRow icon="?" label="Not set up" dim collapsed={collapsed} />
|
||||
|
||||
<SectionDivider />
|
||||
|
||||
{/* ── Analytics ── */}
|
||||
<SectionHeading label="Analytics" collapsed={collapsed} />
|
||||
<SectionRow icon="∿" label="Not set up" dim href={`${base}/insights`} collapsed={collapsed} />
|
||||
</>
|
||||
) : (
|
||||
/* ── GLOBAL VIEW: projects list ── */
|
||||
|
||||
Reference in New Issue
Block a user