Files
microdao-daarion/src/pages/GovernancePage.tsx
Apple bef55b2aa6 feat(governance): Frontend integration and pages
- Integrate GovernanceRolesBlock into AgentCabinet
- Add ReportButton component for creating incidents
- Add GovernancePage with tabs (City/Audit/Incidents)
- Add /governance route to App.tsx
- Export governance components from index.ts
2025-11-29 16:06:17 -08:00

117 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Governance Page
* Main governance dashboard with tabs for City, Audit, Incidents
*/
import React, { useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { CityGovernancePanel } from '../features/governance/components/CityGovernancePanel';
import { AuditDashboard } from '../features/governance/components/AuditDashboard';
import { IncidentsList } from '../features/governance/components/IncidentsList';
type Tab = 'city' | 'audit' | 'incidents';
export function GovernancePage() {
const [searchParams, setSearchParams] = useSearchParams();
const initialTab = (searchParams.get('tab') as Tab) || 'city';
const [activeTab, setActiveTab] = useState<Tab>(initialTab);
const handleTabChange = (tab: Tab) => {
setActiveTab(tab);
setSearchParams({ tab });
};
// TODO: Get actual actorDaisId from auth context
const actorDaisId = 'dais-demo-user';
return (
<div className="min-h-screen bg-slate-950 text-white">
{/* Header */}
<div className="bg-gradient-to-r from-slate-900 to-slate-800 border-b border-slate-700">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<h1 className="text-3xl font-bold text-white flex items-center gap-3">
🏛 DAARION.city Governance
</h1>
<p className="text-slate-400 mt-2">
Управління агентами, ролями, інцидентами та аудит подій
</p>
</div>
</div>
{/* Tabs */}
<div className="bg-slate-900 border-b border-slate-700 sticky top-0 z-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex gap-1">
<TabButton
active={activeTab === 'city'}
onClick={() => handleTabChange('city')}
icon="🏛️"
label="City Governance"
/>
<TabButton
active={activeTab === 'audit'}
onClick={() => handleTabChange('audit')}
icon="📊"
label="Audit"
/>
<TabButton
active={activeTab === 'incidents'}
onClick={() => handleTabChange('incidents')}
icon="⚠️"
label="Incidents"
/>
</div>
</div>
</div>
{/* Content */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{activeTab === 'city' && (
<CityGovernancePanel actorId={actorDaisId} />
)}
{activeTab === 'audit' && (
<AuditDashboard />
)}
{activeTab === 'incidents' && (
<IncidentsList
actorDaisId={actorDaisId}
showCreateButton
/>
)}
</div>
</div>
);
}
// Tab Button Component
function TabButton({
active,
onClick,
icon,
label
}: {
active: boolean;
onClick: () => void;
icon: string;
label: string;
}) {
return (
<button
onClick={onClick}
className={`px-6 py-4 text-sm font-medium flex items-center gap-2 border-b-2 transition-colors ${
active
? 'text-white border-purple-500 bg-slate-800/50'
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-800/30'
}`}
>
<span>{icon}</span>
<span>{label}</span>
</button>
);
}
export default GovernancePage;