# 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<T>(filename: string): Promise<T[]> {
     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<Country>('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<HTMLDivElement>(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<string, number>)
       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<Props, State> {
     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 <Fallback error={this.state.error!} reset={this.reset} />
         }
         
         return (
           <Card className="m-4">
             <CardHeader>
               <div className="flex items-center gap-2">
                 <AlertTriangle className="h-5 w-5 text-red-400" />
                 <CardTitle>Something went wrong</CardTitle>
               </div>
               <CardDescription>
                 An error occurred while loading infrastructure data
               </CardDescription>
             </CardHeader>
             <CardContent>
               {process.env.NODE_ENV === 'development' && this.state.error && (
                 <pre className="text-sm text-red-400 mb-4">
                   {this.state.error.message}
                   {this.state.error.stack}
                 </pre>
               )}
               <Button onClick={this.reset}>Try Again</Button>
             </CardContent>
           </Card>
         )
       }
       
       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 (
       <InfrastructureErrorBoundary>
         <div className="container mx-auto py-8 px-4">
           <NetworkTopologyDocs />
         </div>
       </InfrastructureErrorBoundary>
     )
   }
   ```

---

## 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<ComplianceRequirement>({
       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 (
       <Dialog open={open} onOpenChange={onOpenChange}>
         <DialogContent className="max-w-2xl">
           <DialogHeader>
             <DialogTitle>Edit Compliance Requirement</DialogTitle>
           </DialogHeader>
           
           <Form {...form}>
             <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
               <FormField
                 control={form.control}
                 name="country"
                 render={({ field }) => (
                   <FormItem>
                     <FormLabel>Country</FormLabel>
                     <FormControl>
                       <Input {...field} disabled />
                     </FormControl>
                   </FormItem>
                 )}
               />
               
               {/* Add all other fields similarly */}
               
               <DialogFooter>
                 <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                   Cancel
                 </Button>
                 <Button type="submit" disabled={loading}>
                   {loading ? 'Saving...' : 'Save'}
                 </Button>
               </DialogFooter>
             </form>
           </Form>
         </DialogContent>
       </Dialog>
     )
   }
   ```

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
   <Button onClick={() => {
     setEditingItem(requirement)
     setDialogOpen(true)
   }}>
     Edit
   </Button>
   ```
5. Add form component:
   ```typescript
   <EditComplianceForm
     open={dialogOpen}
     onOpenChange={setDialogOpen}
     requirement={editingItem!}
   />
   ```
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

