2026-01-07 09:31:02 +00:00
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import { AdminDashboardView } from '../admin/AdminDashboardView';
|
|
|
|
|
import { AdminUsersView } from '../admin/AdminUsersView';
|
|
|
|
|
import { AdminModerationView } from '../admin/AdminModerationView';
|
2026-01-26 13:12:17 +00:00
|
|
|
import { AdminAuditLogsView } from '../admin/AdminAuditLogsView';
|
2026-01-07 09:31:02 +00:00
|
|
|
import { AdminSettingsView } from '../admin/AdminSettingsView';
|
2026-01-26 13:12:17 +00:00
|
|
|
import { LayoutDashboard, Users, ShieldAlert, Settings, History } from 'lucide-react';
|
2026-01-07 09:31:02 +00:00
|
|
|
|
|
|
|
|
interface AdminViewProps {
|
2026-01-26 13:12:17 +00:00
|
|
|
currentSubView?: string; // 'dashboard' | 'users' | 'moderation' | 'audit' | 'settings'
|
2026-01-07 09:31:02 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
export const AdminView: React.FC<AdminViewProps> = ({
|
|
|
|
|
currentSubView = 'dashboard',
|
|
|
|
|
}) => {
|
2026-01-07 09:31:02 +00:00
|
|
|
// Local state for internal navigation if not driven by props, but props is better for deep linking simulation
|
|
|
|
|
const [activeTab, setActiveTab] = useState(currentSubView);
|
|
|
|
|
|
|
|
|
|
const renderContent = () => {
|
2026-01-13 18:47:57 +00:00
|
|
|
switch (activeTab) {
|
|
|
|
|
case 'users':
|
|
|
|
|
return <AdminUsersView />;
|
|
|
|
|
case 'moderation':
|
|
|
|
|
return <AdminModerationView />;
|
2026-01-26 13:12:17 +00:00
|
|
|
case 'audit':
|
|
|
|
|
return <AdminAuditLogsView />;
|
2026-01-13 18:47:57 +00:00
|
|
|
case 'settings':
|
|
|
|
|
return <AdminSettingsView />;
|
|
|
|
|
case 'dashboard':
|
|
|
|
|
default:
|
|
|
|
|
return <AdminDashboardView />;
|
|
|
|
|
}
|
2026-01-07 09:31:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex flex-col lg:flex-row gap-8 animate-fadeIn h-[calc(100vh-140px)]">
|
2026-01-13 18:47:57 +00:00
|
|
|
{/* Admin Sidebar */}
|
|
|
|
|
<div className="w-full lg:w-64 flex-shrink-0">
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="bg-kodo-red/10 border border-kodo-red/30 p-4 rounded-xl mb-6 flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<ShieldAlert className="w-6 h-6 text-kodo-red" />
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="font-bold text-white text-sm">Admin Area</h3>
|
2026-01-16 00:47:43 +00:00
|
|
|
<p className="text-[10px] text-kodo-content-dim">Restricted Access</p>
|
2026-01-13 18:47:57 +00:00
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
|
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
<div className="space-y-1">
|
|
|
|
|
{[
|
|
|
|
|
{
|
|
|
|
|
id: 'dashboard',
|
|
|
|
|
label: 'Dashboard',
|
|
|
|
|
icon: <LayoutDashboard className="w-4 h-4" />,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'users',
|
|
|
|
|
label: 'Users',
|
|
|
|
|
icon: <Users className="w-4 h-4" />,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'moderation',
|
|
|
|
|
label: 'Moderation',
|
|
|
|
|
icon: <ShieldAlert className="w-4 h-4" />,
|
|
|
|
|
},
|
2026-01-26 13:12:17 +00:00
|
|
|
{
|
|
|
|
|
id: 'audit',
|
|
|
|
|
label: 'Audit Logs',
|
|
|
|
|
icon: <History className="w-4 h-4" />,
|
|
|
|
|
},
|
2026-01-13 18:47:57 +00:00
|
|
|
{
|
|
|
|
|
id: 'settings',
|
|
|
|
|
label: 'Settings',
|
|
|
|
|
icon: <Settings className="w-4 h-4" />,
|
|
|
|
|
},
|
|
|
|
|
].map((item) => (
|
|
|
|
|
<button
|
|
|
|
|
key={item.id}
|
|
|
|
|
onClick={() => setActiveTab(item.id)}
|
2026-01-26 13:12:17 +00:00
|
|
|
className={`w-full flex items-center gap-4 px-4 py-4 rounded-lg text-sm font-medium transition-all ${activeTab === item.id
|
|
|
|
|
? 'bg-white/10 text-white border-l-2 border-kodo-red'
|
|
|
|
|
: 'text-kodo-content-dim hover:text-white hover:bg-white/5 border-l-2 border-transparent'
|
|
|
|
|
}`}
|
2026-01-13 18:47:57 +00:00
|
|
|
>
|
|
|
|
|
{item.icon}
|
|
|
|
|
{item.label}
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Content Area */}
|
|
|
|
|
<div className="flex-1 overflow-y-auto pr-2 pb-10 custom-scrollbar">
|
|
|
|
|
{renderContent()}
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|