Files
ddtracker/mockup.tsx
Alexander Domene b056725f02 Initial commit: Due Diligence Tracker project
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-28 10:14:13 +02:00

231 lines
12 KiB
TypeScript

import React, { useState } from 'react';
import { ChevronDown, ChevronRight, Target, Users, Building, Code, Shield, DollarSign, Briefcase, Heart, TrendingUp } from 'lucide-react';
const ExecutiveDashboard = () => {
const [expandedDimension, setExpandedDimension] = useState(null);
const data = {
strategy: { kpis: 6, open: 15, completed: 15, progress: 50 },
operational: {
sales: { kpis: 3, open: 5, completed: 3, progress: 38, icon: TrendingUp, shade: '#10B981' },
product: { kpis: 5, open: 19, completed: 5, progress: 21, icon: Target, shade: '#3B82F6' },
organization: { kpis: 5, open: 5, completed: 5, progress: 50, icon: Building, shade: '#8B5CF6' },
engineering: { kpis: 5, open: 28, completed: 4, progress: 13, icon: Code, shade: '#F59E0B' },
devops: { kpis: 3, open: 6, completed: 3, progress: 33, icon: Shield, shade: '#EF4444' },
cyber: { kpis: 6, open: 29, completed: 6, progress: 17, icon: Shield, shade: '#6B7280' },
finance: { kpis: 13, open: 3, completed: 13, progress: 81, icon: DollarSign, shade: '#059669' }
},
foundation: {
people: { kpis: 5, open: 7, completed: 5, progress: 42, icon: Users, shade: '#DC2626' },
culture: { kpis: 3, open: 2, completed: 3, progress: 60, icon: Heart, shade: '#7C3AED' }
}
};
const toggleDimension = (dimension) => {
setExpandedDimension(expandedDimension === dimension ? null : dimension);
};
const ProgressBar = ({ progress, shade = '#333333', height = '8px' }) => {
return (
<div
className="bg-gray-200 rounded-full relative overflow-hidden"
style={{ height, width: '96px' }}
>
<div
className="h-full rounded-full transition-all duration-300 ease-in-out"
style={{
width: `${Math.min(progress, 100)}%`,
backgroundColor: shade
}}
/>
</div>
);
};
const DetailedView = () => (
<div className="space-y-6">
{/* Strategy Section */}
<div className="bg-white rounded-xl border-2 border-gray-300 p-6 shadow-sm">
<div className="border-2 border-gray-400 rounded-lg">
<button
onClick={() => toggleDimension('strategy')}
className="w-full p-4 flex items-center justify-between hover:bg-gray-100 rounded-lg transition-colors"
>
<div className="flex items-center space-x-4">
<div className="p-2 border-2 border-gray-400 rounded-full bg-gray-100">
<Briefcase className="w-5 h-5 text-gray-700" />
</div>
<div className="text-left">
<h4 className="font-bold text-gray-900 text-lg">Strategy</h4>
<p className="text-sm text-gray-700 font-medium">{data.strategy.kpis} KPIs {data.strategy.open + data.strategy.completed} total items</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="text-right">
<div className="font-bold text-xl text-gray-900">{Math.round(data.strategy.progress)}%</div>
<div className="w-24">
<ProgressBar progress={data.strategy.progress} shade="#4F46E5" height="6px" />
</div>
</div>
{expandedDimension === 'strategy' ? <ChevronDown className="w-5 h-5 text-gray-600" /> : <ChevronRight className="w-5 h-5 text-gray-600" />}
</div>
</button>
{expandedDimension === 'strategy' && (
<div className="px-4 pb-4 border-t-2 border-gray-300 bg-gray-50 rounded-b-lg">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-4">
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold text-gray-900">{data.strategy.kpis}</div>
<div className="text-sm text-gray-700 font-medium">Key Performance Indicators</div>
</div>
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold text-gray-700">{data.strategy.open}</div>
<div className="text-sm text-gray-700 font-medium">Open Items</div>
</div>
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold text-gray-900">{data.strategy.completed}</div>
<div className="text-sm text-gray-700 font-medium">Completed Items</div>
</div>
</div>
</div>
)}
</div>
</div>
{/* All Operational Dimensions */}
<div className="bg-white rounded-xl border-2 border-gray-300 p-6 shadow-sm">
<div className="space-y-4">
{Object.entries(data.operational).map(([name, dim]) => {
const Icon = dim.icon;
const isExpanded = expandedDimension === name;
return (
<div key={name} className="border-2 border-gray-400 rounded-lg">
<button
onClick={() => toggleDimension(name)}
className="w-full p-4 flex items-center justify-between hover:bg-gray-100 rounded-lg transition-colors"
>
<div className="flex items-center space-x-4">
<div className="p-2 border-2 border-gray-400 rounded-full bg-gray-100">
<Icon className="w-5 h-5" style={{ color: dim.shade }} />
</div>
<div className="text-left">
<h4 className="font-bold text-gray-900 capitalize">{name}</h4>
<p className="text-sm text-gray-700 font-medium">{dim.kpis} KPIs {dim.open + dim.completed} total items</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="text-right">
<div className="font-bold text-lg" style={{ color: dim.shade }}>{Math.round(dim.progress)}%</div>
<div className="w-24">
<ProgressBar progress={dim.progress} shade={dim.shade} height="4px" />
</div>
</div>
{isExpanded ? <ChevronDown className="w-5 h-5 text-gray-600" /> : <ChevronRight className="w-5 h-5 text-gray-600" />}
</div>
</button>
{isExpanded && (
<div className="px-4 pb-4 border-t-2 border-gray-300 bg-gray-50 rounded-b-lg">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-4">
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold" style={{ color: dim.shade }}>{dim.kpis}</div>
<div className="text-sm text-gray-700 font-medium">Key Performance Indicators</div>
</div>
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold text-gray-700">{dim.open}</div>
<div className="text-sm text-gray-700 font-medium">Open Items</div>
</div>
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold text-gray-900">{dim.completed}</div>
<div className="text-sm text-gray-700 font-medium">Completed Items</div>
</div>
</div>
</div>
)}
</div>
);
})}
</div>
</div>
{/* Foundation Dimensions */}
<div className="bg-white rounded-xl border-2 border-gray-300 p-6 shadow-sm">
<div className="space-y-4">
{Object.entries(data.foundation).map(([name, dim]) => {
const Icon = dim.icon;
const isExpanded = expandedDimension === name;
return (
<div key={name} className="border-2 border-gray-400 rounded-lg">
<button
onClick={() => toggleDimension(name)}
className="w-full p-4 flex items-center justify-between hover:bg-gray-100 rounded-lg transition-colors"
>
<div className="flex items-center space-x-4">
<div className="p-2 border-2 border-gray-400 rounded-full bg-gray-100">
<Icon className="w-5 h-5" style={{ color: dim.shade }} />
</div>
<div className="text-left">
<h4 className="font-bold text-gray-900 capitalize">{name}</h4>
<p className="text-sm text-gray-700 font-medium">{dim.kpis} KPIs {dim.open + dim.completed} total items</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="text-right">
<div className="font-bold text-lg" style={{ color: dim.shade }}>{Math.round(dim.progress)}%</div>
<div className="w-24">
<ProgressBar progress={dim.progress} shade={dim.shade} height="4px" />
</div>
</div>
{isExpanded ? <ChevronDown className="w-5 h-5 text-gray-600" /> : <ChevronRight className="w-5 h-5 text-gray-600" />}
</div>
</button>
{isExpanded && (
<div className="px-4 pb-4 border-t-2 border-gray-300 bg-gray-50 rounded-b-lg">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-4">
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold" style={{ color: dim.shade }}>{dim.kpis}</div>
<div className="text-sm text-gray-700 font-medium">Key Performance Indicators</div>
</div>
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold text-gray-700">{dim.open}</div>
<div className="text-sm text-gray-700 font-medium">Open Items</div>
</div>
<div className="text-center p-4 bg-white rounded-lg border-2 border-gray-300">
<div className="text-3xl font-bold text-gray-900">{dim.completed}</div>
<div className="text-sm text-gray-700 font-medium">Completed Items</div>
</div>
</div>
</div>
)}
</div>
);
})}
</div>
</div>
</div>
);
return (
<div className="min-h-screen bg-gray-50 p-6 print:bg-white print:p-4">
<div className="max-w-7xl mx-auto">
<style jsx>{`
@media print {
body { -webkit-print-color-adjust: exact; }
.shadow-sm { box-shadow: none !important; }
.shadow-lg { box-shadow: none !important; }
.hover\\:bg-gray-100:hover { background-color: transparent !important; }
button { cursor: default !important; }
}
`}</style>
{/* Content */}
<DetailedView />
</div>
</div>
);
};
export default ExecutiveDashboard;