diff --git a/src/components/BottomRow.tsx b/src/components/BottomRow.tsx index 54ce9ec..223cd19 100644 --- a/src/components/BottomRow.tsx +++ b/src/components/BottomRow.tsx @@ -70,7 +70,7 @@ export default function BottomRow() { ) : integrations.length === 0 ? (

No integrations added yet — add one in Settings.

) : ( -
+
{integrations.map((i) => (
diff --git a/src/components/ProgressRing.tsx b/src/components/ProgressRing.tsx index bca4d76..c0c8a17 100644 --- a/src/components/ProgressRing.tsx +++ b/src/components/ProgressRing.tsx @@ -49,3 +49,53 @@ export default function ProgressRing({ percentage, size = 56, strokeWidth = 4 }:
) } + +interface RingSegment { + color: string + value: number +} + +interface MultiSegmentRingProps { + segments: RingSegment[] + total: number + size?: number + strokeWidth?: number + centerLabel?: string +} + +export function MultiSegmentRing({ segments, total, size = 64, strokeWidth = 10, centerLabel }: MultiSegmentRingProps) { + const radius = (size - strokeWidth) / 2 + const circumference = 2 * Math.PI * radius + + let cumulative = 0 + const drawn = segments.filter((s) => s.value > 0) + + return ( +
+ + + {total > 0 && + drawn.map((seg, i) => { + const segLen = (seg.value / total) * circumference + const offset = circumference - cumulative + cumulative += segLen + return ( + + ) + })} + + {centerLabel && {centerLabel}} +
+ ) +} diff --git a/src/components/StatusCards.tsx b/src/components/StatusCards.tsx index 302288c..18c957a 100644 --- a/src/components/StatusCards.tsx +++ b/src/components/StatusCards.tsx @@ -1,7 +1,8 @@ import { useEffect, useState } from 'react' import { Server, Plug, BookMarked } from 'lucide-react' -import ProgressRing from './ProgressRing' +import { MultiSegmentRing } from './ProgressRing' import { api, type Integration, type Resource, type Bookmark } from '../lib/api' +import { getIntegrationTypeColors } from '../lib/integrationColors' const cardStyle: React.CSSProperties = { backgroundColor: 'rgba(10, 10, 12, 0.55)', @@ -47,17 +48,34 @@ export default function StatusCards() { const systemLabel = errored > 0 ? 'Issues Detected' : total === 0 ? 'Not Configured' : 'All Systems Operational' const systemPercent = total === 0 ? 0 : Math.round((connected / total) * 100) + const typeColors = getIntegrationTypeColors(integrations ?? []) + const typeCounts = new Map() + for (const i of integrations ?? []) { + typeCounts.set(i.type, (typeCounts.get(i.type) ?? 0) + 1) + } + const typeSegments = [...typeCounts.entries()].map(([type, value]) => ({ type, value, color: typeColors[type] })) + return (
{/* System Status */}
-
+

System Status

0 ? '#E74C3C' : '#2ECC71', lineHeight: 1.3 }}>{systemLabel}

{connected} of {total} integrations connected

+ {typeSegments.length > 0 && ( +
+ {typeSegments.map((s) => ( + + + {s.type} ({s.value}) + + ))} +
+ )}
- +
diff --git a/src/lib/integrationColors.ts b/src/lib/integrationColors.ts new file mode 100644 index 0000000..2dc2404 --- /dev/null +++ b/src/lib/integrationColors.ts @@ -0,0 +1,24 @@ +import type { Integration } from './api' + +// Color-blind-friendly palette (Blue/Orange/Green/Brown/Purple/Red/Teal/Yellow), +// assigned to integration *types* in first-come-first-served order (by integration +// id, i.e. whichever type was connected to ArchNest first). Once a type has a +// color it keeps it everywhere — System Status breakdown, Infrastructure, etc. +const PALETTE = ['#4A90E2', '#E67E22', '#2ECC71', '#8B5E3C', '#9B59B6', '#E74C3C', '#1ABC9C', '#F1C40F'] + +export function getIntegrationTypeColors(integrations: Integration[]): Record { + const sorted = [...integrations].sort((a, b) => a.id - b.id) + const map: Record = {} + let next = 0 + for (const integ of sorted) { + if (!(integ.type in map)) { + map[integ.type] = PALETTE[next % PALETTE.length] + next++ + } + } + return map +} + +export function getIntegrationColor(integrations: Integration[], type: string): string { + return getIntegrationTypeColors(integrations)[type] ?? '#7A7D85' +} diff --git a/src/pages/Help.tsx b/src/pages/Help.tsx index 9d72b0a..e82d00e 100644 --- a/src/pages/Help.tsx +++ b/src/pages/Help.tsx @@ -160,7 +160,7 @@ const quickStartSteps = [ export default function Help() { return ( -
+

How ArchNest works