diff --git a/client/pages/dashboards/LabsDashboard.tsx b/client/pages/dashboards/LabsDashboard.tsx index cdf8a6a5..b5e890e0 100644 --- a/client/pages/dashboards/LabsDashboard.tsx +++ b/client/pages/dashboards/LabsDashboard.tsx @@ -24,99 +24,159 @@ import { ArrowRight, AlertCircle, Send, + Briefcase, + TrendingUp, + Code2, } from "lucide-react"; -import { ResearchWidget } from "@/components/ResearchWidget"; const API_BASE = import.meta.env.VITE_API_BASE || ""; +interface ResearchTrack { + id: string; + title: string; + description: string; + status: "scoping" | "research" | "in-development" | "testing" | "released"; + progress: number; + lead_name: string; + team_size: number; +} + +interface IPPortfolioItem { + id: string; + name: string; + type: "patent" | "trademark" | "trade-secret" | "copyright"; + status: "filed" | "pending" | "secured" | "expired"; + filing_date: string; + licensed_to: string; +} + +interface Publication { + id: string; + title: string; + description: string; + status: "drafting" | "review" | "published"; + author: string; + published_date: string; + url?: string; +} + +interface ResearchBounty { + id: string; + title: string; + description: string; + reward: number; + difficulty: "intermediate" | "advanced" | "expert"; + applicants_count: number; +} + export default function LabsDashboard() { const navigate = useNavigate(); const { user, loading: authLoading } = useAuth(); const { theme } = useArmTheme(); const [activeTab, setActiveTab] = useState("overview"); - const [researchTracks, setResearchTracks] = useState([]); - const [bounties, setBounties] = useState([]); - const [publications, setPublications] = useState([]); - const [ipPortfolio, setIpPortfolio] = useState(null); + const [isAccessible, setIsAccessible] = useState(false); + const [researchTracks, setResearchTracks] = useState([]); + const [ipPortfolio, setIpPortfolio] = useState([]); + const [publications, setPublications] = useState([]); + const [bounties, setBounties] = useState([]); const [loading, setLoading] = useState(true); - const [isAdmin, setIsAdmin] = useState(false); useEffect(() => { if (!authLoading && user) { - loadDashboardData(); + checkAccessAndLoadData(); + } else if (!authLoading && !user) { + setLoading(false); } }, [user, authLoading]); - const loadDashboardData = async () => { + const checkAccessAndLoadData = async () => { try { setLoading(true); + + // Check if user has labs affiliation const { data: { session }, } = await supabase.auth.getSession(); const token = session?.access_token; + if (!token) throw new Error("No auth token"); - try { - const tracksRes = await fetch(`${API_BASE}/api/labs/research-tracks`, { + // Check arm affiliations + const affiliationRes = await fetch( + `${API_BASE}/api/user/arm-affiliations`, + { headers: { Authorization: `Bearer ${token}` }, - }); - if ( - tracksRes.ok && - tracksRes.headers.get("content-type")?.includes("application/json") - ) { - const data = await tracksRes.json(); - setResearchTracks(Array.isArray(data) ? data : []); - } - } catch (err) { - // Silently ignore API errors + }, + ); + + let hasLabsAccess = false; + if (affiliationRes.ok) { + const data = await affiliationRes.json(); + hasLabsAccess = + data.arms?.includes("labs") || + data.role === "admin" || + data.verified; } - try { - const bountiesRes = await fetch(`${API_BASE}/api/labs/bounties`, { - headers: { Authorization: `Bearer ${token}` }, - }); - if ( - bountiesRes.ok && - bountiesRes.headers.get("content-type")?.includes("application/json") - ) { - const data = await bountiesRes.json(); - setBounties(Array.isArray(data) ? data : []); - } - } catch (err) { - // Silently ignore API errors - } + setIsAccessible(hasLabsAccess); - try { - const pubRes = await fetch(`${API_BASE}/api/labs/publications`, { - headers: { Authorization: `Bearer ${token}` }, - }); - if ( - pubRes.ok && - pubRes.headers.get("content-type")?.includes("application/json") - ) { - const data = await pubRes.json(); - setPublications(Array.isArray(data) ? data : []); + if (hasLabsAccess) { + // Load research tracks + try { + const tracksRes = await fetch( + `${API_BASE}/api/labs/research-tracks`, + { + headers: { Authorization: `Bearer ${token}` }, + }, + ); + if (tracksRes.ok) { + const data = await tracksRes.json(); + setResearchTracks(Array.isArray(data) ? data : []); + } + } catch { + // Silently ignore } - } catch (err) { - // Silently ignore API errors - } - try { - const ipRes = await fetch(`${API_BASE}/api/labs/ip-portfolio`, { - headers: { Authorization: `Bearer ${token}` }, - }); - if ( - ipRes.ok && - ipRes.headers.get("content-type")?.includes("application/json") - ) { - const data = await ipRes.json(); - setIpPortfolio(data); - setIsAdmin(data?.is_admin || false); + // Load IP portfolio + try { + const ipRes = await fetch(`${API_BASE}/api/labs/ip-portfolio`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (ipRes.ok) { + const data = await ipRes.json(); + setIpPortfolio(Array.isArray(data) ? data : []); + } + } catch { + // Silently ignore + } + + // Load publications (all) + try { + const pubRes = await fetch(`${API_BASE}/api/labs/publications`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (pubRes.ok) { + const data = await pubRes.json(); + setPublications(Array.isArray(data) ? data : []); + } + } catch { + // Silently ignore + } + + // Load bounties + try { + const bountiesRes = await fetch(`${API_BASE}/api/labs/bounties`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (bountiesRes.ok) { + const data = await bountiesRes.json(); + setBounties(Array.isArray(data) ? data : []); + } + } catch { + // Silently ignore } - } catch (err) { - // Silently ignore API errors } - } catch (error) { + } catch { // Silently ignore errors } finally { setLoading(false); @@ -132,15 +192,23 @@ export default function LabsDashboard() {
-

- Research LABS -

-

Discover cutting-edge R&D

+
+ +

+ AeThex LABS +

+
+

+ Our proprietary R&D skunkworks +

+

+ Access our cutting-edge research, IP portfolio, and publications +

@@ -148,6 +216,69 @@ export default function LabsDashboard() { ); } + if (!isAccessible) { + return ( + +
+
+ + +
+ +

+ Join LABS? +

+

+ LABS is our internal R&D department for A-Corp employees +

+
+ +
+

+ What is LABS? +

+

+ LABS is our proprietary, for-profit R&D department that takes + the open-source Axiom Protocol and builds competitive, + closed-source "secret weapons" on top of it. +

+

+ We house active research tracks, manage our IP portfolio, + publish technical whitepapers, and post high-difficulty + research bounties to our elite architect community. +

+
+ +
+ + +
+ +

+ To join LABS, you must be a verified A-Corp employee or + architect with proven expertise +

+
+
+
+
+
+ ); + } + + // Main dashboard - user has access return (
{/* Header */}
-

- Research LABS -

-

- R&D Workshop | Blueprint Technical +

+ +

+ LABS +

+
+

+ R&D Workshop | Proprietary Research & IP Management

@@ -175,264 +309,513 @@ export default function LabsDashboard() { > Overview - Tracks + Research Tracks + Publications Bounties - Publications {/* Overview Tab */} -
+ {/* Quick Stats */} +
-

Active Tracks

-

+

+

+ Active Tracks +

+ +
+

{researchTracks.length}

+ -

Available Bounties

-

- {bounties.length} +

+

+ IP Assets +

+ +
+

+ {ipPortfolio.length}

+ -

Publications

-

+

+

+ Publications +

+ +
+

{publications.length}

+ + + +
+

+ Bounties +

+ +
+

+ {bounties.length} +

+
+
- {/* Recent Publications */} - {publications.length > 0 && ( + {/* Featured Research Track */} + {researchTracks.length > 0 && ( - Recent Publications + Featured Research Track + + Our current flagship R&D initiative + - - {publications.slice(0, 3).map((pub: any) => ( - -
- -
-

- {pub.title} -

-

- {new Date( - pub.published_date, - ).toLocaleDateString()} + + {(() => { + const featured = researchTracks[0]; + return ( +

+
+

+ {featured.title} +

+

+ {featured.description}

- + +
+
+

+ Lead +

+

+ {featured.lead_name} +

+
+
+

+ Team Size +

+

+ {featured.team_size} members +

+
+
+

+ Progress +

+

+ {featured.progress}% +

+
+
+ +
+
+ Overall Progress + + {featured.progress}% + +
+
+
+
+
+ + + {featured.status.replace("-", " ")} +
-
- ))} + ); + })()} )} - {/* Submit Research Proposal CTA */} - - -

- Have a Research Idea? -

-

- Submit your research proposal for the LABS pipeline -

- -
-
- - - {/* Research Tracks Tab */} - - ({ - id: t.id, - title: t.title, - description: t.description, - status: t.status, - progress: t.progress || 0, - publications: t.publications || [], - whitepaper_url: t.whitepaper_url, - lead: t.lead?.full_name, - }))} - title="Active Research Tracks" - description="Internal R&D projects" - accentColor="amber" - /> - - - {/* Bounties Tab */} - - - - Research Bounties - - High-difficulty opportunities from NEXUS - - - - {bounties.length === 0 ? ( -
- -

No bounties available

-
- ) : ( -
- {bounties.map((bounty: any) => ( -
-
-

- {bounty.title} -

-

- ${bounty.reward?.toLocaleString()} -

-
-

- {bounty.description} -

- -
- ))} -
- )} -
-
-
- - {/* Publications Tab */} - - - - Publication Pipeline - - Upcoming whitepapers and technical blog posts - - - - {publications.length === 0 ? ( -
- -

No publications

-
- ) : ( -
- {publications.map((pub: any) => ( + {/* Recent Publications */} + {publications.filter((p) => p.status === "published").length > 0 && ( + + + Recent Publications + + Latest technical whitepapers and blog posts + + + + {publications + .filter((p) => p.status === "published") + .slice(0, 3) + .map((pub) => ( - - )} - - + + + )} + + {/* CTA Section */} +
+ + +

+ Submit Research Proposal +

+

+ Propose a new R&D initiative for LABS +

+ +
+
+ + + +

+ Browse LABS Bounties +

+

+ High-difficulty research opportunities from NEXUS +

+ +
+
+
- {/* IP Dashboard - Admin Only */} - {isAdmin && ( + {/* Research Tracks Tab */} + + {researchTracks.length === 0 ? ( + + + +

No active research tracks

+
+
+ ) : ( +
+ {researchTracks.map((track) => ( + + +
+
+ + {track.title} + +
+ + {track.status.replace("-", " ")} + +
+
+ +

+ {track.description} +

+ +
+
+

+ Lead +

+

+ {track.lead_name} +

+
+
+

+ Team +

+

+ {track.team_size} members +

+
+
+ +
+
+ Progress + + {track.progress}% + +
+
+
+
+
+ + + + + ))} +
+ )} + + + {/* Publications Tab */} + + {publications.length === 0 ? ( + + + +

No publications yet

+
+
+ ) : ( + + )} +
+ + {/* Bounties Tab */} + + {bounties.length === 0 ? ( + + + +

+ No active research bounties at this time +

+ +
+
+ ) : ( +
+ {bounties.map((bounty) => ( + + +
+
+

+ {bounty.title} +

+
+
+

+ ${bounty.reward.toLocaleString()} +

+
+
+ +

+ {bounty.description} +

+ +
+ + {bounty.difficulty} + + + {bounty.applicants_count} applicants + +
+ + +
+
+ ))} +
+ )} +
+ + {/* IP Portfolio - Admin Only */} + {ipPortfolio.length > 0 && ( - IP Dashboard (Admin Only) + IP Portfolio + + Proprietary intellectual property assets + - - {ipPortfolio ? ( -
-
-

Patents Filed

-

- {ipPortfolio.patents_count || 0} -

-
-
-

Trademarks

-

- {ipPortfolio.trademarks_count || 0} -

-
-
-

Trade Secrets

-

- {ipPortfolio.trade_secrets_count || 0} -

-
-
-

Copyrights

-

- {ipPortfolio.copyrights_count || 0} -

-
-
- ) : ( -

- IP portfolio data not available -

- )} + +
+ + + + + + + + + + + {ipPortfolio.map((item) => ( + + + + + + + ))} + +
+ IP Name + + Type + + Status + + Licensed To +
+ {item.name} + + + {item.type.replace("-", " ")} + + + + {item.status} + + + {item.licensed_to} +
+
)}