feat(agency): refactor agency sidebar to make clients selectable top-level items that render a dedicated client-management view instead of using inline collapsible accordions
This commit is contained in:
@@ -346,11 +346,6 @@ function SectionHeader({ children }: { children: React.ReactNode }) {
|
|||||||
export default function AgencyDashboard() {
|
export default function AgencyDashboard() {
|
||||||
const { workspace } = useParams();
|
const { workspace } = useParams();
|
||||||
const [activeTab, setActiveTab] = useState("find_clients");
|
const [activeTab, setActiveTab] = useState("find_clients");
|
||||||
const [clientOpen, setClientOpen] = useState<string | null>("apex");
|
|
||||||
|
|
||||||
const toggleClient = (id: string) => {
|
|
||||||
setClientOpen(clientOpen === id ? null : id);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -463,108 +458,22 @@ export default function AgencyDashboard() {
|
|||||||
<NavItem icon={Icons.FileText} label="Proposals & Contracts" />
|
<NavItem icon={Icons.FileText} label="Proposals & Contracts" />
|
||||||
<NavItem icon={Icons.Users} label="Contacts" />
|
<NavItem icon={Icons.Users} label="Contacts" />
|
||||||
|
|
||||||
<SectionHeader>Delivery (Projects)</SectionHeader>
|
<SectionHeader>Clients</SectionHeader>
|
||||||
|
|
||||||
{/* Nested Client Hub: Apex Plumbing */}
|
<div onClick={() => setActiveTab("client_apex")}>
|
||||||
<div style={{ marginBottom: 4 }}>
|
<NavItem
|
||||||
<button
|
icon={Icons.Folder}
|
||||||
onClick={() => toggleClient("apex")}
|
label="Apex Plumbing"
|
||||||
style={{
|
active={activeTab === "client_apex"}
|
||||||
display: "flex",
|
/>
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
width: "100%",
|
|
||||||
padding: "7px 10px",
|
|
||||||
borderRadius: 6,
|
|
||||||
background: "transparent",
|
|
||||||
color: "#1a1a1a",
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: "13px",
|
|
||||||
border: "none",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
|
||||||
<Icons.Folder />
|
|
||||||
Apex Plumbing
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
color: "#a09a90",
|
|
||||||
transform:
|
|
||||||
clientOpen === "apex" ? "rotate(180deg)" : "rotate(0deg)",
|
|
||||||
transition: "transform 0.15s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icons.ChevronDown />
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{clientOpen === "apex" && (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
marginTop: 2,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NavItem inset label="Projects (Live)" badge="1" />
|
|
||||||
<NavItem inset label="Infrastructure (Hosting)" />
|
|
||||||
<NavItem inset label="Secrets Manager" />
|
|
||||||
<NavItem inset label="Client Contacts" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Nested Client Hub: Barton Creek */}
|
<div onClick={() => setActiveTab("client_barton")}>
|
||||||
<div style={{ marginBottom: 4 }}>
|
<NavItem
|
||||||
<button
|
icon={Icons.Folder}
|
||||||
onClick={() => toggleClient("barton")}
|
label="Barton Creek HVAC"
|
||||||
style={{
|
active={activeTab === "client_barton"}
|
||||||
display: "flex",
|
/>
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
width: "100%",
|
|
||||||
padding: "7px 10px",
|
|
||||||
borderRadius: 6,
|
|
||||||
background: "transparent",
|
|
||||||
color: "#1a1a1a",
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: "13px",
|
|
||||||
border: "none",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
|
||||||
<Icons.Folder />
|
|
||||||
Barton Creek HVAC
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
color: "#a09a90",
|
|
||||||
transform:
|
|
||||||
clientOpen === "barton" ? "rotate(180deg)" : "rotate(0deg)",
|
|
||||||
transition: "transform 0.15s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icons.ChevronDown />
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{clientOpen === "barton" && (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
marginTop: 2,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NavItem inset label="Projects (Live)" />
|
|
||||||
<NavItem inset label="Infrastructure (Hosting)" />
|
|
||||||
<NavItem inset label="Secrets Manager" />
|
|
||||||
<NavItem inset label="Client Contacts" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SectionHeader>Finance & Ops</SectionHeader>
|
<SectionHeader>Finance & Ops</SectionHeader>
|
||||||
@@ -578,6 +487,183 @@ export default function AgencyDashboard() {
|
|||||||
{/* ── MAIN CONTENT AREA ── */}
|
{/* ── MAIN CONTENT AREA ── */}
|
||||||
<div style={{ flex: 1, overflowY: "auto" }}>
|
<div style={{ flex: 1, overflowY: "auto" }}>
|
||||||
{activeTab === "find_clients" && <FindClientsView />}
|
{activeTab === "find_clients" && <FindClientsView />}
|
||||||
|
{activeTab === "client_apex" && <ClientView name="Apex Plumbing" />}
|
||||||
|
{activeTab === "client_barton" && (
|
||||||
|
<ClientView name="Barton Creek HVAC" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── CLIENT VIEW (Projects, Infra, Secrets) ──
|
||||||
|
function ClientView({ name }: { name: string }) {
|
||||||
|
return (
|
||||||
|
<div style={{ padding: "40px 56px", maxWidth: 1100, margin: "0 auto" }}>
|
||||||
|
{/* Header */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "flex-start",
|
||||||
|
marginBottom: 32,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "11px",
|
||||||
|
fontWeight: 600,
|
||||||
|
color: "#a09a90",
|
||||||
|
textTransform: "uppercase",
|
||||||
|
letterSpacing: "0.04em",
|
||||||
|
marginBottom: 6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Client
|
||||||
|
</div>
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontSize: "28px",
|
||||||
|
fontWeight: 600,
|
||||||
|
color: "#1a1a1a",
|
||||||
|
letterSpacing: "-0.02em",
|
||||||
|
margin: "0 0 8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</h1>
|
||||||
|
<p style={{ color: "#6b6560", fontSize: "15px", margin: 0 }}>
|
||||||
|
Manage projects, infrastructure, and secrets for this client.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
padding: "8px 16px",
|
||||||
|
background: "var(--accent)",
|
||||||
|
color: "#fff",
|
||||||
|
borderRadius: 8,
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: "13px",
|
||||||
|
border: "none",
|
||||||
|
cursor: "pointer",
|
||||||
|
boxShadow: "0 2px 8px var(--accent-glow)",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ fontSize: 16, lineHeight: 0 }}>+</span> New project
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tabs */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: 24,
|
||||||
|
borderBottom: "1px solid #eae6de",
|
||||||
|
marginBottom: 24,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{["Projects", "Infrastructure", "Secrets Vault", "Contacts"].map(
|
||||||
|
(tab, i) => (
|
||||||
|
<div
|
||||||
|
key={tab}
|
||||||
|
style={{
|
||||||
|
paddingBottom: 12,
|
||||||
|
fontSize: "14px",
|
||||||
|
fontWeight: i === 0 ? 600 : 500,
|
||||||
|
color: i === 0 ? "#1a1a1a" : "#6b6560",
|
||||||
|
borderBottom:
|
||||||
|
i === 0 ? "2px solid var(--accent)" : "2px solid transparent",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tab}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Projects Grid */}
|
||||||
|
<div style={{ display: "grid", gridTemplateColumns: "1fr", gap: 16 }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: "#fff",
|
||||||
|
border: "1px solid #eae6de",
|
||||||
|
borderRadius: 12,
|
||||||
|
padding: "20px 24px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
boxShadow: "0 2px 8px rgba(0,0,0,0.02)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex", alignItems: "center", gap: 16 }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 8,
|
||||||
|
background: "#f6f4f0",
|
||||||
|
display: "grid",
|
||||||
|
placeItems: "center",
|
||||||
|
color: "#1a1a1a",
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{name.charAt(0)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3
|
||||||
|
style={{
|
||||||
|
fontSize: "16px",
|
||||||
|
fontWeight: 600,
|
||||||
|
color: "#1a1a1a",
|
||||||
|
margin: "0 0 4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Customer Portal
|
||||||
|
</h3>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: "13px",
|
||||||
|
color: "#6b6560",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "inline-block",
|
||||||
|
width: 6,
|
||||||
|
height: 6,
|
||||||
|
borderRadius: "50%",
|
||||||
|
background: "#2e7d32",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
Live on {name.toLowerCase().replace(/[^a-z0-9]/g, "")}.vibn.app
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
padding: "6px 12px",
|
||||||
|
border: "1px solid #eae6de",
|
||||||
|
background: "transparent",
|
||||||
|
borderRadius: 6,
|
||||||
|
fontSize: "13px",
|
||||||
|
fontWeight: 500,
|
||||||
|
color: "#1a1a1a",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Open Builder
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user