'use client' import React, { useMemo } from 'react' import { Card, CardContent } from './card' import { ProgressCircle } from './progress-circle' export type ConnectProgressProps = { providers: Array<{ id: string; name: string }> connectedIds: Set className?: string layout?: 'fixed-desktop' | 'inline' // Preview what the score would be if a connect/disconnect action occurred previewProviderId?: string | null previewAction?: 'connect' | 'disconnect' | null // When a provider is selected (in the connect screen), show a pulsing gain segment selectedProviderId?: string | null } export function ConnectProgress(props: ConnectProgressProps) { const { providers, connectedIds, className, layout = 'fixed-desktop', previewProviderId, previewAction, selectedProviderId } = props const normalizeId = (s: string) => s.toLowerCase().replace(/[^a-z]/g, '') const computeNormalizedSet = (ids: Set) => { const norm = new Set() ids.forEach(id => norm.add(normalizeId(id))) return norm } const normalizedIds = useMemo(() => computeNormalizedSet(connectedIds), [connectedIds]) const hasGithub = normalizedIds.has('github') const hasLinkedIn = normalizedIds.has('linkedin') const otherConnectedCount = useMemo(() => { let count = 0 normalizedIds.forEach(id => { if (id !== 'github' && id !== 'githubapp' && id !== 'linkedin') count += 1 }) return count }, [normalizedIds]) const computePercent = (ids: Set) => { const norm = computeNormalizedSet(ids) const gh = norm.has('github') const gha = norm.has('githubapp') const li = norm.has('linkedin') let others = 0 norm.forEach(id => { if (id !== 'github' && id !== 'githubapp' && id !== 'linkedin') others += 1 }) const githubWeight = gh ? 60 : 0 const githubAppWeight = gha ? 20 : 0 const linkedinWeight = li ? 0 : 0 // LinkedIn is not included in the score const othersWeight = others * 10 return Math.max(0, Math.min(100, githubWeight + githubAppWeight + linkedinWeight + othersWeight)) } const progressPercent = useMemo(() => computePercent(connectedIds), [connectedIds]) const previewPercent = useMemo(() => { const pid = normalizeId(previewProviderId || '') if (!pid || !previewAction) return null as number | null const next = new Set(Array.from(normalizedIds)) const has = next.has(pid) if (previewAction === 'connect' && !has) next.add(pid) if (previewAction === 'disconnect' && has) next.delete(pid) const val = computePercent(next) return val === progressPercent ? null : val }, [previewProviderId, previewAction, normalizedIds, progressPercent]) const progressCopy = useMemo(() => { const score = previewPercent ?? progressPercent if (score < 20) { return { headline: 'Insufficient', body: 'No meaningful data connections', } } else if (score < 40) { return { headline: 'Sparse', body: 'Limited verified sources', } } else if (score < 60) { return { headline: 'Adequate', body: 'Adequate → Minimum viable data coverage', } } else if (score < 80) { return { headline: 'Robust', body: 'Strong, multi-source data foundation', } } else { return { headline: 'Optimal', body: 'Comprehensive, high-confidence dataset', } } }, [previewPercent, progressPercent]); const selectedPulse = useMemo(() => { const sid = normalizeId(selectedProviderId || '') if (!sid || sid === 'githubapp') return { from: undefined as number | undefined, to: undefined as number | undefined } // Do not show if already connected if (normalizedIds.has(sid)) return { from: undefined as number | undefined, to: undefined as number | undefined } // Potential gain if they proceed with this provider let gain = 0 if (sid === 'github') gain = 65 else if (sid === 'linkedin') gain = 15 else { // Others always contribute +10 each (no cap) const othersAlready = otherConnectedCount gain = 10 } const to = Math.max(0, Math.min(100, progressPercent + gain)) return { from: progressPercent, to } }, [selectedProviderId, normalizedIds, progressPercent, otherConnectedCount]) const isPreviewing = previewPercent !== null && previewPercent !== undefined const valueToShow = previewPercent ?? progressPercent const centerIndicator = useMemo(() => { if (previewPercent == null) return null as 'up' | 'down' | null return previewPercent > progressPercent ? 'up' : previewPercent < progressPercent ? 'down' : null }, [previewPercent, progressPercent]) const content = (
Profile Depth: {progressCopy.headline}
{progressCopy.body}
) if (layout === 'inline') return content return (
{content}
) } export default ConnectProgress