Some checks failed
API CI / API Lint (push) Successful in 38s
API CI / API Type Check (push) Failing after 43s
API CI / API Test (push) Successful in 56s
API CI / API Build (push) Failing after 45s
API CI / Build Docker Image (push) Has been skipped
CD Pipeline / Deploy to Staging (push) Failing after 23s
CI Pipeline / Lint and Type Check (push) Failing after 33s
CI Pipeline / Build (push) Has been skipped
CI Pipeline / Test Backend (push) Failing after 1m21s
CI Pipeline / Test Frontend (push) Failing after 32s
CI Pipeline / Security Scan (push) Failing after 1m19s
Deploy to Staging / Deploy to Staging (push) Failing after 27s
Portal CI / Portal Lint (push) Failing after 23s
Portal CI / Portal Type Check (push) Failing after 20s
Portal CI / Portal Test (push) Failing after 23s
Portal CI / Portal Build (push) Failing after 23s
Test Suite / frontend-tests (push) Failing after 31s
Test Suite / api-tests (push) Failing after 45s
Test Suite / blockchain-tests (push) Failing after 31s
Type Check / type-check (map[directory:. name:root]) (push) Failing after 19s
Type Check / type-check (map[directory:api name:api]) (push) Failing after 19s
Type Check / type-check (map[directory:portal name:portal]) (push) Failing after 21s
CD Pipeline / Deploy to Production (push) Has been skipped
104 lines
3.9 KiB
TypeScript
104 lines
3.9 KiB
TypeScript
'use client';
|
|
|
|
import { Building2, Users, CreditCard, Shield, ArrowRight, Landmark } from 'lucide-react';
|
|
import Link from 'next/link';
|
|
import { useSession } from 'next-auth/react';
|
|
|
|
import { RoleGate } from '@/components/auth/RoleGate';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
|
|
|
|
export default function AdminPortalPage() {
|
|
const { data: session } = useSession();
|
|
|
|
const adminSections = [
|
|
{
|
|
title: 'Organization Management',
|
|
description: 'Manage multi-tenant organizations, tenant isolation, and resource quotas',
|
|
icon: Building2,
|
|
href: '/admin/organizations',
|
|
features: ['Multi-tenant view', 'Tenant isolation', 'Resource quotas'],
|
|
},
|
|
{
|
|
title: 'User Management',
|
|
description: 'Manage users, roles, and permissions across your organization',
|
|
icon: Users,
|
|
href: '/admin/users',
|
|
features: ['User list', 'Role assignment', 'Permission management'],
|
|
},
|
|
{
|
|
title: 'Billing & Subscriptions',
|
|
description: 'View subscriptions, usage-based billing, invoices, and payment methods',
|
|
icon: CreditCard,
|
|
href: '/admin/billing',
|
|
features: ['Subscriptions', 'Usage billing', 'Invoice history'],
|
|
},
|
|
{
|
|
title: 'Compliance & Reporting',
|
|
description: 'Compliance dashboard, audit logs, and export reports',
|
|
icon: Shield,
|
|
href: '/admin/compliance',
|
|
features: ['Compliance dashboard', 'Audit logs', 'Export reports'],
|
|
},
|
|
{
|
|
title: 'OpenPayd Connector',
|
|
description: 'Manage OpenPayd credentials, probes, lifecycle gates, evidence packs, and incidents',
|
|
icon: Landmark,
|
|
href: '/admin/openpayd',
|
|
features: ['Sandbox probes', 'Production gates', 'Evidence export'],
|
|
},
|
|
];
|
|
|
|
return (
|
|
<RoleGate
|
|
allowedRoles={['admin', 'tenant-admin', 'ADMIN', 'TENANT_ADMIN']}
|
|
callbackUrl="/admin"
|
|
badge="Admin"
|
|
title="Welcome to Admin Portal"
|
|
subtitle="Sign in with a client-admin or internal-admin account to continue."
|
|
>
|
|
<div className="container mx-auto px-4 py-8">
|
|
<div className="mb-8">
|
|
<h1 className="text-3xl font-bold text-white mb-2">Customer / Tenant Admin Portal</h1>
|
|
<p className="text-gray-400">Manage your organization, users, billing, and compliance</p>
|
|
{session?.user?.email && (
|
|
<p className="text-sm text-gray-500 mt-2">Signed in as {session.user.email}</p>
|
|
)}
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
{adminSections.map((section) => {
|
|
const Icon = section.icon;
|
|
return (
|
|
<Card key={section.href} className="bg-gray-800 border-gray-700 hover:border-orange-500 transition-colors">
|
|
<CardHeader>
|
|
<div className="flex items-center gap-3 mb-2">
|
|
<Icon className="h-6 w-6 text-orange-500" />
|
|
<CardTitle className="text-white">{section.title}</CardTitle>
|
|
</div>
|
|
<p className="text-sm text-gray-400">{section.description}</p>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ul className="space-y-2 mb-4">
|
|
{section.features.map((feature) => (
|
|
<li key={feature} className="flex items-center gap-2 text-sm text-gray-300">
|
|
<span className="text-orange-500">•</span>
|
|
<span>{feature}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<Link
|
|
href={section.href}
|
|
className="inline-flex items-center gap-2 text-sm text-orange-500 hover:text-orange-400 transition-colors"
|
|
>
|
|
Manage <ArrowRight className="h-4 w-4" />
|
|
</Link>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</RoleGate>
|
|
);
|
|
}
|