# Infrastructure Documentation Dashboard - Complete Implementation Steps ## Overview This document provides step-by-step implementation instructions for all enhancements, organized by phase and priority. Each step includes specific actions, file paths, code structure, and time estimates. --- ## Phase 1: Critical Foundation (Weeks 1-2) - 80-120 hours ### Step 1.1: Install Dependencies **Time:** 15 minutes **Action:** Add required packages to package.json ```bash npm install html2canvas jspdf xlsx mapbox-gl react-map-gl @tanstack/react-virtual ``` **Files to Modify:** - `package.json` **Verification:** - Run `npm install` - Verify packages in node_modules --- ### Step 1.2: Create Validation Schemas **Time:** 2-3 hours **File:** `src/lib/validation/schemas/infrastructure.ts` **Implementation Steps:** 1. Import Zod 2. Create `countrySchema`: ```typescript export const countrySchema = z.object({ name: z.string().min(1), region: z.enum(['Africa (Sub-Saharan)', 'Middle East & North Africa', 'Americas', 'Asia-Pacific', 'Europe']), relationshipType: z.enum(['Full Diplomatic Relations', 'Official (Non-Diplomatic)', 'Ambassador Level', 'Full Diplomatic Relations (Special Mission)']), priority: z.enum(['Critical', 'High', 'Medium', 'Low']), cloudflareCoverage: z.boolean(), networkInfrastructurePriority: z.string(), notes: z.string().optional(), coordinates: z.object({ lat: z.number().min(-90).max(90), lng: z.number().min(-180).max(180) }).optional() }) ``` 3. Create `topologyNodeSchema`: ```typescript export const topologyNodeSchema = z.object({ id: z.string(), type: z.enum(['region', 'datacenter', 'tunnel', 'vm', 'service']), label: z.string().min(1), region: z.string(), entity: z.string(), position: z.object({ x: z.number(), y: z.number() }), metadata: z.record(z.any()) }) ``` 4. Create `topologyEdgeSchema`: ```typescript export const topologyEdgeSchema = z.object({ id: z.string(), source: z.string(), target: z.string(), type: z.enum(['tunnel', 'peering', 'network-route']), metadata: z.record(z.any()) }) ``` 5. Create `networkTopologySchema`: ```typescript export const networkTopologySchema = z.object({ nodes: z.array(topologyNodeSchema), edges: z.array(topologyEdgeSchema), region: z.string(), entity: z.string(), lastUpdated: z.string().datetime() }) ``` 6. Create `complianceRequirementSchema`: ```typescript export const complianceRequirementSchema = z.object({ country: z.string().min(1), region: z.string(), frameworks: z.array(z.string()).min(1), status: z.enum(['Compliant', 'Partial', 'Pending', 'Non-Compliant']), requirements: z.array(z.string()), lastAuditDate: z.string().datetime().optional(), notes: z.string().optional() }) ``` 7. Create `deploymentMilestoneSchema`: ```typescript export const deploymentMilestoneSchema = z.object({ id: z.string(), title: z.string().min(1), region: z.string(), entity: z.string(), priority: z.enum(['Critical', 'High', 'Medium', 'Low']), startDate: z.string().datetime(), endDate: z.string().datetime(), status: z.enum(['Planned', 'In Progress', 'Complete', 'Blocked']), dependencies: z.array(z.string()).optional(), cost: z.number().min(0).optional(), description: z.string().optional() }).refine((data) => new Date(data.endDate) > new Date(data.startDate), { message: "End date must be after start date", path: ["endDate"] }) ``` 8. Create `costEstimateSchema`: ```typescript export const costEstimateSchema = z.object({ region: z.string(), entity: z.string(), category: z.enum(['Infrastructure', 'Network', 'Compliance', 'Operations']), monthly: z.number().min(0), annual: z.number().min(0), breakdown: z.object({ compute: z.number().min(0).optional(), storage: z.number().min(0).optional(), network: z.number().min(0).optional(), licenses: z.number().min(0).optional(), personnel: z.number().min(0).optional() }), currency: z.string().optional(), lastUpdated: z.string().datetime().optional() }).refine((data) => { const breakdownSum = (data.breakdown.compute || 0) + (data.breakdown.storage || 0) + (data.breakdown.network || 0) + (data.breakdown.licenses || 0) + (data.breakdown.personnel || 0) return Math.abs(breakdownSum - data.monthly) < 0.01 }, { message: "Breakdown sum must equal monthly cost", path: ["breakdown"] }) ``` 9. Create input schemas for mutations: - `updateTopologyInputSchema` - `createMilestoneInputSchema` - `updateMilestoneInputSchema` - `updateComplianceInputSchema` - `updateCostEstimateInputSchema` 10. Export all schemas **Testing:** - Test each schema with valid data - Test each schema with invalid data - Verify error messages --- ### Step 1.3: Create Data Serving API Route **Time:** 1-2 hours **File:** `src/app/api/infrastructure/data/[filename]/route.ts` **Implementation Steps:** 1. Create route handler: ```typescript import { NextRequest, NextResponse } from 'next/server' import * as fs from 'fs' import * as path from 'path' export async function GET( request: NextRequest, { params }: { params: { filename: string } } ) { try { const filePath = path.join(process.cwd(), 'docs/infrastructure/data', params.filename) if (!fs.existsSync(filePath)) { return NextResponse.json( { error: 'File not found' }, { status: 404 } ) } const fileContent = fs.readFileSync(filePath, 'utf-8') const data = JSON.parse(fileContent) const stats = fs.statSync(filePath) const response = NextResponse.json({ data, metadata: { lastModified: stats.mtime.toISOString(), filename: params.filename } }) // Add caching headers response.headers.set('ETag', `"${stats.mtime.getTime()}"`) response.headers.set('Last-Modified', stats.mtime.toUTCString()) response.headers.set('Cache-Control', 'public, max-age=3600') return response } catch (error) { return NextResponse.json( { error: 'Failed to load file' }, { status: 500 } ) } } ``` 2. Add error handling for invalid JSON 3. Add security checks (prevent directory traversal) 4. Add rate limiting (optional) 5. Test with various filenames 6. Test error cases **Testing:** - Test with valid filename - Test with invalid filename - Test with missing file - Test caching headers --- ### Step 1.4: Update Data Loading Hook **Time:** 2-3 hours **File:** `src/lib/hooks/useInfrastructureData.ts` **Implementation Steps:** 1. Import React Query: ```typescript import { useQuery } from '@tanstack/react-query' ``` 2. Update DATA_BASE_PATH: ```typescript const DATA_BASE_PATH = '/api/infrastructure/data' ``` 3. Create data fetcher function: ```typescript async function fetchJSONData(filename: string): Promise { const response = await fetch(`${DATA_BASE_PATH}/${filename}`) if (!response.ok) { throw new Error(`Failed to load ${filename}: ${response.statusText}`) } const result = await response.json() return result.data || [] } ``` 4. Update useCountries hook: ```typescript export function useCountries(filter?: {...}) { return useQuery({ queryKey: ['countries', filter], queryFn: () => fetchJSONData('smom_countries.json'), staleTime: 5 * 60 * 1000, // 5 minutes retry: 3, retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000) }) } ``` 5. Apply same pattern to all hooks: - useNetworkTopologies - useComplianceRequirements - useDeploymentMilestones - useCostEstimates - useInfrastructureSummary 6. Add filtering logic after data fetch 7. Add error handling 8. Test all hooks **Testing:** - Test data loading - Test filtering - Test error handling - Test caching --- ### Step 1.5: Implement Topology PNG Export **Time:** 1-2 hours **File:** `src/components/infrastructure/NetworkTopologyDocs.tsx` **Implementation Steps:** 1. Import html2canvas: ```typescript import html2canvas from 'html2canvas' ``` 2. Add ref to topology container: ```typescript const topologyRef = useRef(null) ``` 3. Implement handleExportPNG: ```typescript const handleExportPNG = async () => { if (!topologyRef.current) return setExporting(true) try { const canvas = await html2canvas(topologyRef.current, { backgroundColor: '#000000', scale: 2, // High resolution logging: false }) canvas.toBlob((blob) => { if (!blob) return const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `topology-${selectedRegion}-${Date.now()}.png` a.click() URL.revokeObjectURL(url) toast({ title: 'Export successful', description: 'Topology exported as PNG', variant: 'success' }) }, 'image/png') } catch (error) { toast({ title: 'Export failed', description: error instanceof Error ? error.message : 'Unknown error', variant: 'error' }) } finally { setExporting(false) } } ``` 4. Add exporting state 5. Add loading indicator to button 6. Test export functionality **Testing:** - Test PNG export - Test with different topologies - Test error handling - Verify file download --- ### Step 1.6: Implement Topology SVG Export **Time:** 1 hour **File:** `src/components/infrastructure/NetworkTopologyDocs.tsx` **Implementation Steps:** 1. Implement handleExportSVG: ```typescript const handleExportSVG = () => { const svgElement = topologyRef.current?.querySelector('svg') if (!svgElement) return try { const svgData = new XMLSerializer().serializeToString(svgElement) const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' }) const url = URL.createObjectURL(svgBlob) const a = document.createElement('a') a.href = url a.download = `topology-${selectedRegion}-${Date.now()}.svg` a.click() URL.revokeObjectURL(url) toast({ title: 'Export successful', description: 'Topology exported as SVG', variant: 'success' }) } catch (error) { toast({ title: 'Export failed', description: error instanceof Error ? error.message : 'Unknown error', variant: 'error' }) } } ``` 2. Test SVG export 3. Verify SVG quality --- ### Step 1.7: Implement Timeline PDF Export **Time:** 3-4 hours **File:** `src/components/infrastructure/DeploymentTimeline.tsx` **Implementation Steps:** 1. Import libraries: ```typescript import jsPDF from 'jspdf' import html2canvas from 'html2canvas' ``` 2. Create handleExportPDF function: ```typescript const handleExportPDF = async () => { setExporting(true) try { const pdf = new jsPDF('landscape', 'mm', 'a4') // Page 1: Title and metadata pdf.setFontSize(20) pdf.text('Deployment Timeline', 20, 20) pdf.setFontSize(12) pdf.text(`Region: ${selectedRegion}`, 20, 30) pdf.text(`Entity: ${selectedEntity}`, 20, 35) pdf.text(`Export Date: ${new Date().toLocaleDateString()}`, 20, 40) // Page 2: Gantt chart const chartElement = document.getElementById('gantt-chart') if (chartElement) { const canvas = await html2canvas(chartElement) const imgData = canvas.toDataURL('image/png') pdf.addPage() pdf.addImage(imgData, 'PNG', 10, 10, 277, 190) } // Page 3: Milestone list pdf.addPage() pdf.setFontSize(16) pdf.text('Milestone List', 20, 20) let y = 30 milestones.forEach((milestone, index) => { if (y > 270) { pdf.addPage() y = 20 } pdf.setFontSize(12) pdf.text(`${index + 1}. ${milestone.title}`, 20, y) pdf.setFontSize(10) pdf.text(`Status: ${milestone.status} | Priority: ${milestone.priority}`, 20, y + 5) y += 15 }) pdf.save(`deployment-timeline-${Date.now()}.pdf`) toast({ title: 'Export successful', description: 'Timeline exported as PDF', variant: 'success' }) } catch (error) { toast({ title: 'Export failed', description: error instanceof Error ? error.message : 'Unknown error', variant: 'error' }) } finally { setExporting(false) } } ``` 3. Add exporting state 4. Test PDF generation 5. Adjust layout and formatting --- ### Step 1.8: Implement Cost Estimates Excel Export **Time:** 3-4 hours **File:** `src/components/infrastructure/CostEstimates.tsx` **Implementation Steps:** 1. Import xlsx: ```typescript import * as XLSX from 'xlsx' ``` 2. Create handleExportExcel function: ```typescript const handleExportExcel = () => { try { const workbook = XLSX.utils.book_new() // Summary sheet const summaryData = [ ['Total Monthly', (totalMonthly / 1000).toFixed(0) + 'K'], ['Total Annual', (totalAnnual / 1000000).toFixed(1) + 'M'], ['Number of Estimates', estimates.length] ] const summarySheet = XLSX.utils.aoa_to_sheet(summaryData) XLSX.utils.book_append_sheet(workbook, summarySheet, 'Summary') // Detailed breakdown sheet const detailData = estimates.map(e => ({ Region: e.region, Entity: e.entity, Category: e.category, 'Monthly (USD)': e.monthly, 'Annual (USD)': e.annual, 'Compute': e.breakdown.compute || 0, 'Storage': e.breakdown.storage || 0, 'Network': e.breakdown.network || 0, 'Licenses': e.breakdown.licenses || 0, 'Personnel': e.breakdown.personnel || 0 })) const detailSheet = XLSX.utils.json_to_sheet(detailData) // Format currency columns const range = XLSX.utils.decode_range(detailSheet['!ref'] || 'A1') for (let C = 3; C <= 4; ++C) { for (let R = 1; R <= range.e.r; ++R) { const cellAddress = XLSX.utils.encode_cell({ r: R, c: C }) if (!detailSheet[cellAddress]) continue detailSheet[cellAddress].z = '$#,##0.00' } } XLSX.utils.book_append_sheet(workbook, detailSheet, 'Detailed Breakdown') // By region sheet const byRegion = estimates.reduce((acc, e) => { acc[e.region] = (acc[e.region] || 0) + e.annual return acc }, {} as Record) const regionData = Object.entries(byRegion).map(([region, annual]) => ({ Region: region, 'Annual Cost (USD)': annual })) const regionSheet = XLSX.utils.json_to_sheet(regionData) XLSX.utils.book_append_sheet(workbook, regionSheet, 'By Region') XLSX.writeFile(workbook, `cost-estimates-${Date.now()}.xlsx`) toast({ title: 'Export successful', description: 'Cost estimates exported as Excel', variant: 'success' }) } catch (error) { toast({ title: 'Export failed', description: error instanceof Error ? error.message : 'Unknown error', variant: 'error' }) } } ``` 3. Test Excel export 4. Verify formatting --- ### Step 1.9: Create Error Boundary Component **Time:** 1-2 hours **File:** `src/components/infrastructure/InfrastructureErrorBoundary.tsx` **Implementation Steps:** 1. Create error boundary class component: ```typescript 'use client' import React from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { AlertTriangle } from 'lucide-react' interface Props { children: React.ReactNode fallback?: React.ComponentType<{ error: Error; reset: () => void }> } interface State { hasError: boolean error: Error | null } export class InfrastructureErrorBoundary extends React.Component { constructor(props: Props) { super(props) this.state = { hasError: false, error: null } } static getDerivedStateFromError(error: Error): State { return { hasError: true, error } } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { console.error('Infrastructure error:', error, errorInfo) // Log to Sentry if available if (typeof window !== 'undefined' && (window as any).Sentry) { (window as any).Sentry.captureException(error, { contexts: { react: errorInfo } }) } } reset = () => { this.setState({ hasError: false, error: null }) } render() { if (this.state.hasError) { if (this.props.fallback) { const Fallback = this.props.fallback return } return (
Something went wrong
An error occurred while loading infrastructure data
{process.env.NODE_ENV === 'development' && this.state.error && (
                   {this.state.error.message}
                   {this.state.error.stack}
                 
)}
) } return this.props.children } } ``` 2. Test error boundary 3. Add to all page components --- ### Step 1.10: Wrap Views with Error Boundary **Time:** 30 minutes **Files:** All page components **Implementation:** 1. Import InfrastructureErrorBoundary 2. Wrap each view: ```typescript export default function TopologyPage() { return (
) } ``` --- ## Phase 2: Edit Mode Implementation (Weeks 2-3) - 60-80 hours ### Step 2.1: Create Edit Compliance Form **Time:** 3-4 hours **File:** `src/components/infrastructure/forms/EditComplianceForm.tsx` **Implementation Steps:** 1. Create form component structure: ```typescript 'use client' import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog' import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@/components/ui/form' import { Input } from '@/components/ui/input' import { Button } from '@/components/ui/button' import { useUpdateComplianceRequirement } from '@/lib/graphql/hooks/useInfrastructure' import { useToast } from '@/components/ui/use-toast' import { complianceRequirementSchema } from '@/lib/validation/schemas/infrastructure' import type { ComplianceRequirement } from '@/lib/types/infrastructure' interface EditComplianceFormProps { open: boolean onOpenChange: (open: boolean) => void requirement: ComplianceRequirement } export function EditComplianceForm({ open, onOpenChange, requirement }: EditComplianceFormProps) { const { updateCompliance, loading, error } = useUpdateComplianceRequirement() const { toast } = useToast() const form = useForm({ resolver: zodResolver(complianceRequirementSchema), defaultValues: requirement }) const onSubmit = async (data: ComplianceRequirement) => { try { await updateCompliance({ variables: { country: requirement.country, input: { frameworks: data.frameworks, status: data.status, requirements: data.requirements, lastAuditDate: data.lastAuditDate, notes: data.notes } } }) toast({ title: 'Success', description: 'Compliance requirement updated', variant: 'success' }) onOpenChange(false) } catch (err) { toast({ title: 'Error', description: err instanceof Error ? err.message : 'Failed to update', variant: 'error' }) } } return ( Edit Compliance Requirement
( Country )} /> {/* Add all other fields similarly */}
) } ``` 2. Add all form fields with proper types 3. Add multi-select for frameworks 4. Add date picker for lastAuditDate 5. Add textarea for requirements (one per line) 6. Test form validation 7. Test form submission --- ### Step 2.2: Create Edit Milestone Form **Time:** 4-5 hours **File:** `src/components/infrastructure/forms/EditMilestoneForm.tsx` **Implementation Steps:** 1. Create form with all fields 2. Add date range validation 3. Add dependency selector (multi-select of other milestones) 4. Add dependency validation (no circular refs) 5. Add cost field with currency formatting 6. Handle create vs edit modes 7. Show dependency graph preview 8. Test all validations --- ### Step 2.3: Create Edit Cost Estimate Form **Time:** 3-4 hours **File:** `src/components/infrastructure/forms/EditCostEstimateForm.tsx` **Implementation Steps:** 1. Create form with cost fields 2. Add auto-calculation (monthly * 12 = annual) 3. Add breakdown fields 4. Add validation (breakdown sum = monthly) 5. Add currency selector 6. Test calculations 7. Test validation --- ### Step 2.4: Create Edit Topology Node Form **Time:** 3-4 hours **File:** `src/components/infrastructure/forms/EditTopologyNodeForm.tsx` **Implementation Steps:** 1. Create form with node fields 2. Add position X/Y fields 3. Add metadata editor (JSON or key-value) 4. Add validation (unique label, valid coordinates) 5. Integrate with topology update 6. Test node editing --- ### Step 2.5: Wire Up Edit Forms **Time:** 2-3 hours per component **Files:** All infrastructure component files **Implementation Steps:** 1. Import form components 2. Add state for dialog open/close 3. Add state for item being edited 4. Connect edit buttons: ```typescript ``` 5. Add form component: ```typescript ``` 6. Refresh data after successful edit 7. Test edit workflow --- ### Step 2.6: Implement Topology Edit Mode **Time:** 6-8 hours **File:** `src/components/infrastructure/NetworkTopologyDocs.tsx` **Implementation Steps:** 1. Add edit mode state management 2. Implement node dragging: ```typescript const onNodeDrag = useCallback((event: NodeDragEvent, node: Node) => { // Update node position in state setTopology(prev => ({ ...prev, nodes: prev.nodes.map(n => n.id === node.id ? { ...n, position: { x: node.position.x, y: node.position.y } } : n ) })) }, []) ``` 3. Add "Add Node" button and dialog 4. Implement edge creation (click source, then target) 5. Add delete functionality 6. Add context menu 7. Implement bulk selection 8. Add save button 9. Integrate with mutation 10. Add undo/redo --- ### Step 2.7: Implement Timeline Drag-and-Drop **Time:** 4-5 hours **File:** `src/components/infrastructure/DeploymentTimeline.tsx` **Implementation Steps:** 1. Set up @dnd-kit: ```typescript import { DndContext, DragEndEvent } from '@dnd-kit/core' import { SortableContext, useSortable } from '@dnd-kit/sortable' ``` 2. Make milestones draggable 3. Implement drop handler 4. Validate date constraints 5. Check dependencies 6. Auto-save on drop 7. Show loading state --- ## Phase 3: React Flow Integration (Week 3) - 20-25 hours ### Step 3.1: Create React Flow Topology Component **Time:** 4-5 hours **File:** `src/components/infrastructure/topology/ReactFlowTopology.tsx` **Implementation Steps:** 1. Import React Flow: ```typescript import ReactFlow, { Background, Controls, MiniMap, Node, Edge, Connection, useNodesState, useEdgesState, addEdge, onNodesChange, onEdgesChange } from 'reactflow' import 'reactflow/dist/style.css' ``` 2. Convert topology data: ```typescript const nodes: Node[] = topology.nodes.map(node => ({ id: node.id, type: node.type, position: node.position, data: { label: node.label, ...node.metadata } })) const edges: Edge[] = topology.edges.map(edge => ({ id: edge.id, source: edge.source, target: edge.target, type: edge.type, label: edge.metadata.bandwidth || edge.type })) ``` 3. Set up React Flow component 4. Add minimap and controls 5. Add background grid 6. Implement zoom/pan 7. Add fit view --- ### Step 3.2-3.4: Create Custom Nodes and Edges **Time:** 8-10 hours **Files:** Multiple files **Implementation Steps:** 1. Create base node component 2. Create specialized nodes (5 files) 3. Create custom edge component 4. Register node/edge types 5. Integrate into main component 6. Test all node types 7. Test edit mode with React Flow --- ## Phase 4: Map Visualization (Week 4) - 8-10 hours ### Step 4.1-4.3: Mapbox Integration **Time:** 8-10 hours **Files:** Multiple files **Implementation Steps:** 1. Set up Mapbox token 2. Create ComplianceMapView component 3. Load country coordinates 4. Create markers 5. Add popups 6. Implement clustering 7. Add layer controls 8. Integrate into compliance component --- ## Phase 5-8: Additional Phases (Continue with similar detailed steps for remaining phases...) --- ## Testing Checklist After each phase, test: - [ ] All exports work correctly - [ ] Forms validate properly - [ ] Mutations succeed and update UI - [ ] Error handling works - [ ] Loading states display - [ ] Empty states display - [ ] Filters work correctly - [ ] No console errors - [ ] Responsive design works - [ ] Accessibility features work --- ## Deployment Checklist Before deploying: - [ ] All dependencies installed - [ ] Environment variables set - [ ] API routes tested - [ ] Error boundaries tested - [ ] Performance tested - [ ] Security reviewed - [ ] Documentation complete - [ ] Tests passing