'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { PageHeader } from '@/components/navigation/page-header'; import { RefreshCw, Network, Globe, Smartphone, Radio, AlertTriangle, Workflow, GitBranch, Sparkles, Zap, Bell, Sun, BarChart3, ScrollText, Database, SlidersHorizontal, Activity, Tv, Users, ShieldCheck, Settings as SettingsIcon, Shield, DollarSign, CalendarClock, } from 'lucide-react'; interface AdminCounts { linkConflicts: number; schedules: { enabled: number; total: number }; unmappedAuvik: number; unmappedRmm: number; unmappedAddigy: number; } interface NavTile { title: string; href: string; icon: React.ElementType; description?: string; badge?: { label: string; tone: 'warn' | 'info' | 'muted' }; } interface Section { title: string; tiles: NavTile[]; } function tone(badge?: NavTile['badge']) { if (!badge) return null; const variant: 'destructive' | 'secondary' | 'outline' = badge.tone === 'warn' ? 'destructive' : badge.tone === 'info' ? 'secondary' : 'outline'; return ( {badge.label} ); } export default function AdminIndexPage() { const [counts, setCounts] = useState(null); useEffect(() => { void (async () => { try { const [overviewRes, mappingsRes] = await Promise.all([ fetch('/api/dashboard/overview'), fetch('/api/dashboard/stats'), ]); const overview = overviewRes.ok ? await overviewRes.json() : null; const mappings = mappingsRes.ok ? await mappingsRes.json() : null; setCounts({ linkConflicts: overview?.attention?.linkConflicts ?? 0, schedules: overview?.attention?.schedules ?? { enabled: 0, total: 0 }, unmappedAuvik: mappings?.mappings?.auvik?.unmapped ?? 0, unmappedRmm: mappings?.mappings?.rmm?.unmapped ?? 0, unmappedAddigy: 0, }); } catch { // Counts are decorative — fail quiet. } })(); }, []); const sections: Section[] = [ { title: 'Sync', tiles: [ { title: 'Integrations & Sync', href: '/admin/sync', icon: RefreshCw, description: 'Overview of sync status across all integrations', badge: counts ? { label: `${counts.schedules.enabled}/${counts.schedules.total} schedules on`, tone: 'muted', } : undefined, }, { title: 'Autotask', href: '/admin/sync/autotask', icon: RefreshCw }, { title: 'Datto RMM', href: '/admin/sync/datto-rmm', icon: Globe }, { title: 'IT Glue', href: '/admin/sync/itglue', icon: Shield }, { title: 'SentinelOne', href: '/admin/sync/sentinelone', icon: Shield }, { title: 'Veeam', href: '/admin/sync/veeam', icon: Activity }, { title: 'Auvik', href: '/admin/sync/auvik', icon: Network }, { title: 'Addigy', href: '/admin/sync/addigy', icon: Smartphone }, { title: 'Mimecast', href: '/admin/sync/mimecast', icon: Shield }, { title: 'Duo', href: '/admin/sync/duo', icon: Shield }, { title: 'QuickBooks Online', href: '/admin/qbo', icon: DollarSign }, ], }, { title: 'Mappings', tiles: [ { title: 'Device-Link Conflicts', href: '/admin/device-link-conflicts', icon: AlertTriangle, description: 'Resolve cases where one external device matches multiple Autotask CIs', badge: counts && counts.linkConflicts > 0 ? { label: counts.linkConflicts.toLocaleString(), tone: 'warn' } : undefined, }, { title: 'NMS Mapping (Auvik)', href: '/auvik-mappings', icon: Network, description: 'Map Auvik tenants to companies', badge: counts && counts.unmappedAuvik > 0 ? { label: `${counts.unmappedAuvik} unmapped`, tone: 'info' } : undefined, }, { title: 'RMM Mapping (Datto)', href: '/rmm-mappings', icon: Globe, description: 'Map RMM sites to companies', badge: counts && counts.unmappedRmm > 0 ? { label: `${counts.unmappedRmm} unmapped`, tone: 'info' } : undefined, }, { title: 'Apple RMM (Addigy)', href: '/addigy-mappings', icon: Smartphone, description: 'Map Addigy devices to companies', }, { title: 'SentinelOne Mappings', href: '/sentinelone/mappings', icon: Shield, description: 'Map S1 sites to companies (gap blocks reconciler)', }, { title: 'Zabbix WAN Monitor', href: '/admin/zabbix-wan', icon: Radio, description: 'Sync RMM site WAN IPs to Zabbix with Autotask routing', }, ], }, { title: 'Workflow', tiles: [ { title: 'Ticket Workflows', href: '/admin/workflow', icon: Workflow, description: 'Automated ticket triage and classification', }, { title: 'Classification Rules', href: '/admin/workflow/classification-rules', icon: GitBranch, description: 'Keyword-based classification rules', }, { title: 'AI Templates', href: '/admin/workflow/ai-templates', icon: Sparkles, description: 'AI prompt templates for enhancement', }, { title: 'Webhook Pipelines', href: '/admin/workflow/pipelines', icon: Zap, description: 'Automated webhook processing workflows', }, { title: 'Notification Channels', href: '/admin/workflow/channels', icon: Bell, description: 'Teams, Telegram, and webhook notifications', }, ], }, { title: 'Reports', tiles: [ { title: 'Morning NOC Summary', href: '/admin/morning-summary', icon: Sun, description: 'Daily Zabbix overnight summary posted to Teams', }, { title: 'Ticket Digest Reports', href: '/admin/ticket-digest', icon: BarChart3, description: 'LLM-analyzed ticket reports — daily/weekly/monthly', }, { title: 'IT Glue Writes', href: '/admin/itglue-writes', icon: ScrollText, description: 'History of audit-driven IT Glue field writes', }, { title: 'Audit Log', href: '/admin/audit-log', icon: ScrollText, description: 'System audit trail', }, ], }, { title: 'Tools & Data', tiles: [ { title: 'RMM Overshell', href: '/admin/rmm-overshell', icon: Database, description: 'Datto RMM PowerShell discovery — settings, executions, evidence pipeline', }, { title: 'Data Browser', href: '/admin/data-browser', icon: Database, description: 'Browse and query system data', }, { title: 'Display Settings', href: '/admin/display-settings', icon: SlidersHorizontal, description: 'Configure company filters for Kiosk and Mobile dashboards', }, { title: 'Kiosk Settings', href: '/kiosk/settings', icon: Tv, description: 'Configure executive dashboard for TV display', }, ], }, { title: 'Access', tiles: [ { title: 'Users', href: '/admin/users', icon: Users }, { title: 'Roles', href: '/admin/roles', icon: ShieldCheck }, { title: 'Settings', href: '/admin/settings', icon: SettingsIcon }, ], }, ]; return ( <>
{sections.map((section) => ( {section.title}
{section.tiles.map((tile) => (
{tile.title} {tone(tile.badge)}
{tile.description && (

{tile.description}

)}
))}
))}
); }