diff --git a/apps/web/src/lib/components/AIEngagementInsights.svelte b/apps/web/src/lib/components/AIEngagementInsights.svelte new file mode 100644 index 00000000..0f41e1f6 --- /dev/null +++ b/apps/web/src/lib/components/AIEngagementInsights.svelte @@ -0,0 +1,15 @@ + + + diff --git a/apps/web/src/lib/components/AISkillMatcher.svelte b/apps/web/src/lib/components/AISkillMatcher.svelte new file mode 100644 index 00000000..3c1a7984 --- /dev/null +++ b/apps/web/src/lib/components/AISkillMatcher.svelte @@ -0,0 +1,20 @@ + + + diff --git a/apps/web/src/lib/components/AchievementBadges.svelte b/apps/web/src/lib/components/AchievementBadges.svelte new file mode 100644 index 00000000..5072ed77 --- /dev/null +++ b/apps/web/src/lib/components/AchievementBadges.svelte @@ -0,0 +1,111 @@ + + +
+
+

Achievements

+
+ +
+ {#each badges as badge} +
+
+ + + +
+ {badge.title} + {#if badge.locked} +
+ + + + +
+ {/if} +
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/ActivityHeatmap.svelte b/apps/web/src/lib/components/ActivityHeatmap.svelte new file mode 100644 index 00000000..acb0577a --- /dev/null +++ b/apps/web/src/lib/components/ActivityHeatmap.svelte @@ -0,0 +1,189 @@ + + +
+
+

Realtime Contributor Activity

+ + Live + +
+ +
+
+ {#each heatmapData as week, wIndex} +
+ {#each week as day, dIndex} +
+ {/each} +
+ {/each} +
+
+ +
+ Less +
+
+
+
+
+ More +
+
+ + diff --git a/apps/web/src/lib/components/AnalyticsWidget.svelte b/apps/web/src/lib/components/AnalyticsWidget.svelte new file mode 100644 index 00000000..17d25bfe --- /dev/null +++ b/apps/web/src/lib/components/AnalyticsWidget.svelte @@ -0,0 +1,126 @@ + + +
+
+
+ {icon} +
+ + {isPositive ? '↑' : '↓'} {trend} + +
+ +
+

{title}

+
{value}
+
+
+ + diff --git a/apps/web/src/lib/components/BountyBoard.svelte b/apps/web/src/lib/components/BountyBoard.svelte new file mode 100644 index 00000000..d2c82fb2 --- /dev/null +++ b/apps/web/src/lib/components/BountyBoard.svelte @@ -0,0 +1,196 @@ + + +
+
+

Active Bounties

+ Matched to Your Skills +
+ +
+ {#each bounties as bounty} +
+
+
+ + + + {bounty.repo} +
+

{bounty.issue}

+
+ {#each bounty.tags as tag} + {tag} + {/each} +
+
+ +
+
+ {bounty.amount} + {bounty.match}% Match +
+ +
+
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/BountyEarningsChart.svelte b/apps/web/src/lib/components/BountyEarningsChart.svelte new file mode 100644 index 00000000..d635fa77 --- /dev/null +++ b/apps/web/src/lib/components/BountyEarningsChart.svelte @@ -0,0 +1,170 @@ + + +
+
+

Cumulative Earnings

+ ${values[values.length - 1].toLocaleString()} +
+ +
+ + + + + + + + + + {#each gridLines as line} + {@const y = padding.top + chartHeight - ((line / maxValue) * chartHeight)} + + + ${line >= 1000 ? (line/1000) + 'k' : line} + + {/each} + + + {#each points as point, i} + + {data[i].label} + + {/each} + + + + + + + + + {#each points as point, i} + + {data[i].label}: ${data[i].value} + + {/each} + +
+
+ + diff --git a/apps/web/src/lib/components/BountyRadar.svelte b/apps/web/src/lib/components/BountyRadar.svelte new file mode 100644 index 00000000..0d9c4646 --- /dev/null +++ b/apps/web/src/lib/components/BountyRadar.svelte @@ -0,0 +1,138 @@ + + +
+
+

Bounty Success by Sector

+
+ +
+ + + {#each gridLevels as level} + + {/each} + + + {#each data as _, i} + {@const { x, y } = getRadarCoordinates(100, i, sides, center, radius)} + + {/each} + + + + + + {#each data as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + + {d.label}: {d.value}% success rate + + {/each} + + + {#each labels as label} + + {label.text} + + {/each} + +
+
+ + diff --git a/apps/web/src/lib/components/CodeReviewInsights.svelte b/apps/web/src/lib/components/CodeReviewInsights.svelte new file mode 100644 index 00000000..8bb3ebde --- /dev/null +++ b/apps/web/src/lib/components/CodeReviewInsights.svelte @@ -0,0 +1,147 @@ + + +
+
+

AI Code Review Trends

+ +
+ +
+ {#each insights as insight} +
+
+ {#if insight.type === 'positive'} + + + + {:else if insight.type === 'improvement'} + + + + {:else} + + + + + + {/if} +
+
+

{insight.message}

+ {insight.file} +
+
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/CompatibilityRadar.svelte b/apps/web/src/lib/components/CompatibilityRadar.svelte new file mode 100644 index 00000000..6205aede --- /dev/null +++ b/apps/web/src/lib/components/CompatibilityRadar.svelte @@ -0,0 +1,209 @@ + + +
+
+

Skill Overlap Radar

+
+ You + Match +
+
+ +
+ + + {#each gridLevels as level} + + {/each} + + + {#each userData as _, i} + {@const { x, y } = getRadarCoordinates(100, i, sides, center, radius)} + + {/each} + + + + + + + + + {#each matchData as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + + Match {d.label}: {d.value}% + + {/each} + + {#each userData as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + + Your {d.label}: {d.value}% + + {/each} + + + {#each labels as label} + + {label.text} + + {/each} + +
+
+ + diff --git a/apps/web/src/lib/components/ContributionForecastChart.svelte b/apps/web/src/lib/components/ContributionForecastChart.svelte new file mode 100644 index 00000000..11a66058 --- /dev/null +++ b/apps/web/src/lib/components/ContributionForecastChart.svelte @@ -0,0 +1,193 @@ + + +
+
+

{title}

+
+ Historical + Predicted +
+
+ + +
+ + diff --git a/apps/web/src/lib/components/ContributionRadar.svelte b/apps/web/src/lib/components/ContributionRadar.svelte new file mode 100644 index 00000000..06f4d5fc --- /dev/null +++ b/apps/web/src/lib/components/ContributionRadar.svelte @@ -0,0 +1,164 @@ + + +
+

Contribution Radar

+ +
+ + + {#each gridLevels as level} + + {/each} + + + {#each data as _, i} + {@const { x, y } = getRadarCoordinates(100, i, sides, center, radius)} + + {/each} + + + + + + {#each data as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + + {d.label}: {d.value}% + + {/each} + + + {#each labels as label} + + {label.text} + + {/each} + +
+
+ + diff --git a/apps/web/src/lib/components/DeveloperMatchCard.svelte b/apps/web/src/lib/components/DeveloperMatchCard.svelte new file mode 100644 index 00000000..f3ac53c8 --- /dev/null +++ b/apps/web/src/lib/components/DeveloperMatchCard.svelte @@ -0,0 +1,219 @@ + + +
+
+

Top Hackathon Match

+ Highly Compatible +
+ +
+
+ + + + + {matchProfile.name} +
{matchProfile.matchScore}%
+
+ +
+

{matchProfile.name}

+ {matchProfile.handle} +

{matchProfile.role}

+
+
+ +
+ Shared Stack: +
+ {#each commonSkills as skill} + {skill} + {/each} +
+
+ + +
+ + diff --git a/apps/web/src/lib/components/EmbedCodeGenerator.svelte b/apps/web/src/lib/components/EmbedCodeGenerator.svelte new file mode 100644 index 00000000..2b03c0ff --- /dev/null +++ b/apps/web/src/lib/components/EmbedCodeGenerator.svelte @@ -0,0 +1,150 @@ + + +
+
+

Embed Code

+ +
+ +
+
+
+
+
+
+
+ HTML +
+
{embedCode}
+
+
+ + diff --git a/apps/web/src/lib/components/EventInteractionHeatmap.svelte b/apps/web/src/lib/components/EventInteractionHeatmap.svelte new file mode 100644 index 00000000..9a322895 --- /dev/null +++ b/apps/web/src/lib/components/EventInteractionHeatmap.svelte @@ -0,0 +1,124 @@ + + +
+
+

Event Interaction Heatmap

+
+ +
+ {#each heatmapData as intensity, i} +
+ {/each} +
+ +
+ Quiet +
+
+
+
+
+
+
+ Peak +
+
+ + diff --git a/apps/web/src/lib/components/EventRadar.svelte b/apps/web/src/lib/components/EventRadar.svelte new file mode 100644 index 00000000..873f82e1 --- /dev/null +++ b/apps/web/src/lib/components/EventRadar.svelte @@ -0,0 +1,139 @@ + + +
+
+

Event Dominance

+
+ +
+ + + {#each gridLevels as level} + + {/each} + + + {#each data as _, i} + {@const { x, y } = getRadarCoordinates(100, i, sides, center, radius)} + + {/each} + + + + + + {#each data as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + + {d.label}: {d.value}% + + {/each} + + + {#each labels as label} + + {label.text} + + {/each} + +
+
+ + diff --git a/apps/web/src/lib/components/EventTimeline.svelte b/apps/web/src/lib/components/EventTimeline.svelte new file mode 100644 index 00000000..47dc14ad --- /dev/null +++ b/apps/web/src/lib/components/EventTimeline.svelte @@ -0,0 +1,145 @@ + + +
+
+

Event Timeline

+
+ +
+ {#each events as event, i} +
+
+
+ {#if i < events.length - 1} +
+ {/if} +
+
+
+ {event.date} + {event.type} +
+

{event.title}

+
+
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/GlobalLeaderboard.svelte b/apps/web/src/lib/components/GlobalLeaderboard.svelte new file mode 100644 index 00000000..c2c7e87e --- /dev/null +++ b/apps/web/src/lib/components/GlobalLeaderboard.svelte @@ -0,0 +1,214 @@ + + +
+
+

Global Rankings

+ +
+ +
+ + + + + + + + + + + {#each leaderboard as user} + + + + + + + {/each} + +
RankDeveloperScoreTrend
+ {user.rank} + +
+ {user.name} +
+ {user.name} + {user.handle} +
+
+
{user.score.toLocaleString()} + {#if user.trend === 'up'} + + + + {:else if user.trend === 'down'} + + + + {:else} + + + + {/if} +
+
+
+ + diff --git a/apps/web/src/lib/components/GrowthRadar.svelte b/apps/web/src/lib/components/GrowthRadar.svelte new file mode 100644 index 00000000..0e63f24c --- /dev/null +++ b/apps/web/src/lib/components/GrowthRadar.svelte @@ -0,0 +1,146 @@ + + +
+

Growth Analytics Radar

+ +
+ + + {#each gridLevels as level} + + {/each} + + + {#each data as _, i} + {@const { x, y } = getRadarCoordinates(100, i, sides, center, radius)} + + {/each} + + + + + + {#each data as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + + {d.label}: {d.value}% + + {/each} + + + {#each labels as label} + + {label.text} + + {/each} + +
+
+ + diff --git a/apps/web/src/lib/components/InsightFeed.svelte b/apps/web/src/lib/components/InsightFeed.svelte new file mode 100644 index 00000000..513c5a5c --- /dev/null +++ b/apps/web/src/lib/components/InsightFeed.svelte @@ -0,0 +1,93 @@ + + +
+
+

+ {#if variant === 'ai'}🤖 {/if} + {title} +

+
+ +
    + {#each items as item} +
  • + + +

    {item.text}

    +
  • + {/each} +
+
+ + diff --git a/apps/web/src/lib/components/LearningPathTimeline.svelte b/apps/web/src/lib/components/LearningPathTimeline.svelte new file mode 100644 index 00000000..48efb144 --- /dev/null +++ b/apps/web/src/lib/components/LearningPathTimeline.svelte @@ -0,0 +1,160 @@ + + +
+
+

Learning Roadmap

+ AI Generated +
+ +
+ {#each paths as path, i} +
+
+
+ {#if path.status === 'completed'} + + + + {:else if path.status === 'in-progress'} +
+ {/if} +
+ {#if i < paths.length - 1} +
+ {/if} +
+ +
+

{path.title}

+ {path.duration} +
+
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/LiveActivityFeed.svelte b/apps/web/src/lib/components/LiveActivityFeed.svelte new file mode 100644 index 00000000..03809898 --- /dev/null +++ b/apps/web/src/lib/components/LiveActivityFeed.svelte @@ -0,0 +1,19 @@ + + + diff --git a/apps/web/src/lib/components/LivePreviewPane.svelte b/apps/web/src/lib/components/LivePreviewPane.svelte new file mode 100644 index 00000000..b99fcbb4 --- /dev/null +++ b/apps/web/src/lib/components/LivePreviewPane.svelte @@ -0,0 +1,170 @@ + + +
+
+

Live Preview

+
+ +
+
+
+
+
+
Sarah Chen
+
Full Stack Developer
+
+
+
+
+
A+
+
Reputation
+
+
+
14.5k
+
Global Rank
+
+
+
+ + + + +
+
+
+
+ + diff --git a/apps/web/src/lib/components/MentorshipMatch.svelte b/apps/web/src/lib/components/MentorshipMatch.svelte new file mode 100644 index 00000000..5ce7415b --- /dev/null +++ b/apps/web/src/lib/components/MentorshipMatch.svelte @@ -0,0 +1,139 @@ + + +
+
+

Recommended Mentors

+
+ +
+ {#each mentors as mentor} +
+
+ {mentor.name} +
+ + + + {mentor.match}% +
+
+ +
+

{mentor.name}

+ {mentor.role} @ {mentor.company} +
+ + +
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/MomentumInsights.svelte b/apps/web/src/lib/components/MomentumInsights.svelte new file mode 100644 index 00000000..4e603a3a --- /dev/null +++ b/apps/web/src/lib/components/MomentumInsights.svelte @@ -0,0 +1,15 @@ + + + diff --git a/apps/web/src/lib/components/NetworkingGrowthForecast.svelte b/apps/web/src/lib/components/NetworkingGrowthForecast.svelte new file mode 100644 index 00000000..04991966 --- /dev/null +++ b/apps/web/src/lib/components/NetworkingGrowthForecast.svelte @@ -0,0 +1,129 @@ + + +
+
+

{title}

+
+ + +
+ + diff --git a/apps/web/src/lib/components/NetworkingPulseCard.svelte b/apps/web/src/lib/components/NetworkingPulseCard.svelte new file mode 100644 index 00000000..864676a5 --- /dev/null +++ b/apps/web/src/lib/components/NetworkingPulseCard.svelte @@ -0,0 +1,198 @@ + + +
+
+
+

Networking Pulse

+ + Live + +
+
+ {status} +
+
+ +
+
+
+ {scansPerHour} + /hr +
+ QR Scan Velocity +
+ +
+ +
+
+ {totalConnections} +
+ Total Connections +
+
+ + +
+ + diff --git a/apps/web/src/lib/components/NetworkingRecommendationPanel.svelte b/apps/web/src/lib/components/NetworkingRecommendationPanel.svelte new file mode 100644 index 00000000..02c74209 --- /dev/null +++ b/apps/web/src/lib/components/NetworkingRecommendationPanel.svelte @@ -0,0 +1,146 @@ + + +
+
+

Recommended Events

+ +
+ +
+ {#each events as event (event.id)} +
+
+

{event.name}

+
+ {event.type} + + {event.date} +
+
+
+ + + + {event.matchScore}% Match +
+
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/OSSImpactGraph.svelte b/apps/web/src/lib/components/OSSImpactGraph.svelte new file mode 100644 index 00000000..3fe7518b --- /dev/null +++ b/apps/web/src/lib/components/OSSImpactGraph.svelte @@ -0,0 +1,149 @@ + + +
+
+

{title}

+
+ +
+
+ {maxVal} + {Math.round(maxVal / 2)} + 0 +
+ +
+ {#each data as item} +
+
+
+
+ {item.label} +
+ {/each} +
+
+
+ + diff --git a/apps/web/src/lib/components/PortfolioThemeSelector.svelte b/apps/web/src/lib/components/PortfolioThemeSelector.svelte new file mode 100644 index 00000000..b26c89ee --- /dev/null +++ b/apps/web/src/lib/components/PortfolioThemeSelector.svelte @@ -0,0 +1,129 @@ + + +
+
+

Portfolio Theme

+
+ +
+ {#each themes as theme} + + {/each} +
+
+ + diff --git a/apps/web/src/lib/components/RSVPTracker.svelte b/apps/web/src/lib/components/RSVPTracker.svelte new file mode 100644 index 00000000..c9adf8df --- /dev/null +++ b/apps/web/src/lib/components/RSVPTracker.svelte @@ -0,0 +1,177 @@ + + +
+
+
+

{event.name}

+ {event.date} +
+ {event.status} +
+ +
+
+ Preparation Progress + {event.progress}% +
+
+
+
+
+ +
    + {#each event.checklist as item} +
  • +
    + {#if item.done} + + + + {/if} +
    + {item.label} +
  • + {/each} +
+
+ + diff --git a/apps/web/src/lib/components/RankingTierCard.svelte b/apps/web/src/lib/components/RankingTierCard.svelte new file mode 100644 index 00000000..4ea51271 --- /dev/null +++ b/apps/web/src/lib/components/RankingTierCard.svelte @@ -0,0 +1,201 @@ + + +
+
+

Current Tier

+ Top {percentile}% +
+ +
+
+ + + + +
+ {tier} + #{rank} +
+
+
+ +
+
+ Total Points + {points.toLocaleString()} +
+
+ Next Tier + {nextTierPoints.toLocaleString()} +
+
+ +
+ {nextTierPoints - points} points to reach Master Tier +
+
+ + diff --git a/apps/web/src/lib/components/RealtimeConnectionStream.svelte b/apps/web/src/lib/components/RealtimeConnectionStream.svelte new file mode 100644 index 00000000..d2874d42 --- /dev/null +++ b/apps/web/src/lib/components/RealtimeConnectionStream.svelte @@ -0,0 +1,129 @@ + + +
+
+

Live Activity Stream

+
+ +
+ {#each stream as item (item.id)} +
+
+ {#if item.type === 'scan'} + + + + {:else if item.type === 'view'} + + + + + {:else} + + + + + + + {/if} +
+
+

{item.user} {item.action}

+ {item.time} +
+
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/ReputationScoreCard.svelte b/apps/web/src/lib/components/ReputationScoreCard.svelte new file mode 100644 index 00000000..f59f4133 --- /dev/null +++ b/apps/web/src/lib/components/ReputationScoreCard.svelte @@ -0,0 +1,204 @@ + + +
+
+
+

AI Reputation Score

+ {tier} Tier +
+
+ ↑ {trend} pts +
+
+ +
+ + + + +
+ {score} + / 1000 +
+
+ + +
+ + diff --git a/apps/web/src/lib/components/SkillGapAnalyzer.svelte b/apps/web/src/lib/components/SkillGapAnalyzer.svelte new file mode 100644 index 00000000..fa3981fe --- /dev/null +++ b/apps/web/src/lib/components/SkillGapAnalyzer.svelte @@ -0,0 +1,184 @@ + + +
+
+

Skill Gap Analysis

+ Target: Senior Full Stack +
+ +
+ + + {#each gridLevels as level} + + {/each} + + + {#each skills as _, i} + {@const { x, y } = getRadarCoordinates(100, i, sides, center, radius)} + + {/each} + + + + + + + + + {#each skills as skill, i} + + {skill.name} + + {/each} + +
+ +
+
+
+ Current Level +
+
+
+ Industry Standard +
+
+
+ + diff --git a/apps/web/src/lib/components/SponsorshipGraph.svelte b/apps/web/src/lib/components/SponsorshipGraph.svelte new file mode 100644 index 00000000..af036896 --- /dev/null +++ b/apps/web/src/lib/components/SponsorshipGraph.svelte @@ -0,0 +1,193 @@ + + +
+
+

Sponsorships

+ ${mrr.toLocaleString()}/mo +
+ +
+
+ {sponsors} + Active Sponsors +
+
+ + + + +3 this month +
+
+ +
+

Funding Distribution

+
+ {#each distribution as tier} +
+
+ {tier.tier} + {tier.count} sponsors +
+
+
+
+ ${tier.amount} +
+ {/each} +
+
+
+ + diff --git a/apps/web/src/lib/components/TopContributorsFeed.svelte b/apps/web/src/lib/components/TopContributorsFeed.svelte new file mode 100644 index 00000000..799ad7ae --- /dev/null +++ b/apps/web/src/lib/components/TopContributorsFeed.svelte @@ -0,0 +1,19 @@ + + + diff --git a/apps/web/src/lib/components/VelocityScoreCard.svelte b/apps/web/src/lib/components/VelocityScoreCard.svelte new file mode 100644 index 00000000..cc8971cd --- /dev/null +++ b/apps/web/src/lib/components/VelocityScoreCard.svelte @@ -0,0 +1,173 @@ + + +
+
+
+

Contribution Velocity

+ {status} +
+
+ {growthPercentage} +
+
+ +
+
+ {velocityScore} + Current Momentum +
+ +
+ +
+ {predictedScore} + Predicted (30d) +
+
+ + +
+ + diff --git a/apps/web/src/lib/components/WidgetCustomizer.svelte b/apps/web/src/lib/components/WidgetCustomizer.svelte new file mode 100644 index 00000000..f773e4c6 --- /dev/null +++ b/apps/web/src/lib/components/WidgetCustomizer.svelte @@ -0,0 +1,117 @@ + + +
+
+

Include Widgets

+
+ +
+ {#each widgets as widget} + + {/each} +
+
+ + diff --git a/apps/web/src/lib/utils/chartMath.ts b/apps/web/src/lib/utils/chartMath.ts new file mode 100644 index 00000000..270eadab --- /dev/null +++ b/apps/web/src/lib/utils/chartMath.ts @@ -0,0 +1,84 @@ +export interface Coordinate { + x: number; + y: number; +} + +/** + * Calculates X/Y coordinates for a point on a radar chart + */ +export function getRadarCoordinates( + value: number, + index: number, + sides: number, + center: number, + radius: number +): Coordinate { + // Handle edge case of 0 sides + if (sides === 0) return { x: center, y: center }; + + const angle = (Math.PI * 2) / sides; + const r = (value / 100) * radius; + // -Math.PI/2 to start drawing from the top + const theta = index * angle - Math.PI / 2; + + return { + x: center + r * Math.cos(theta), + y: center + r * Math.sin(theta) + }; +} + +/** + * Generates an SVG polygon points string for a data series + */ +export function generateRadarPoints( + dataValues: number[], + center: number, + radius: number +): string { + const sides = dataValues.length; + if (sides === 0) return ''; + + return dataValues + .map((val, i) => { + const { x, y } = getRadarCoordinates(val, i, sides, center, radius); + return `${x},${y}`; + }) + .join(' '); +} + +/** + * Generates an SVG polygon points string for a background grid level + */ +export function getGridPolygon( + level: number, + sides: number, + center: number, + radius: number +): string { + if (sides === 0) return ''; + + return Array.from({ length: sides }) + .map((_, i) => { + const { x, y } = getRadarCoordinates(level, i, sides, center, radius); + return `${x},${y}`; + }) + .join(' '); +} + +/** + * Generates label coordinates pushed further out from the radar edges + */ +export function generateLabelCoordinates( + data: { label: string; value: number }[], + center: number, + radius: number, + pushFactor: number = 120 +): (Coordinate & { text: string })[] { + const sides = data.length; + if (sides === 0) return []; + + return data.map((d, i) => { + const { x, y } = getRadarCoordinates(pushFactor, i, sides, center, radius); + return { x, y, text: d.label }; + }); +} diff --git a/apps/web/src/lib/utils/visualizationEngine.ts b/apps/web/src/lib/utils/visualizationEngine.ts new file mode 100644 index 00000000..f491a531 --- /dev/null +++ b/apps/web/src/lib/utils/visualizationEngine.ts @@ -0,0 +1,70 @@ +/** + * Generates an SVG line path string for sequential data + */ +export function getPathData( + data: number[], + maxVal: number, + width: number, + height: number +): string { + if (!data || data.length === 0) return ''; + // Avoid division by zero + if (data.length === 1) return `M 0 ${height - (data[0] / maxVal) * height}`; + + const stepX = width / (data.length - 1); + const safeMax = maxVal > 0 ? maxVal : 1; // Prevent division by zero + + return data.map((val, i) => { + const x = i * stepX; + const y = height - (val / safeMax) * height; + return `${i === 0 ? 'M' : 'L'} ${x} ${y}`; + }).join(' '); +} + +/** + * Generates an SVG area path string (filled down to baseline) for sequential data + */ +export function getAreaPathData( + data: number[], + maxVal: number, + width: number, + height: number +): string { + if (!data || data.length === 0) return ''; + const linePath = getPathData(data, maxVal, width, height); + // Complete the path by drawing to bottom right, then bottom left, then close + return `${linePath} L ${width} ${height} L 0 ${height} Z`; +} + +/** + * Generates an array of coordinates for interactive points + */ +export function generatePointCoordinates( + data: number[], + maxVal: number, + width: number, + height: number +): { cx: number; cy: number }[] { + if (!data || data.length === 0) return []; + if (data.length === 1) return [{ cx: 0, cy: height - (data[0] / maxVal) * height }]; + + const stepX = width / (data.length - 1); + const safeMax = maxVal > 0 ? maxVal : 1; + + return data.map((val, i) => ({ + cx: i * stepX, + cy: height - (val / safeMax) * height + })); +} + +/** + * Calculates Y-axis grid values + */ +export function calculateYAxisGrid( + data: number[], + numLines: number +): number[] { + const maxVal = Math.max(...data, 1); + const step = maxVal / numLines; + return Array.from({ length: numLines + 1 }, (_, i) => Math.round(i * step)); +} diff --git a/apps/web/src/routes/dashboard/+page.svelte b/apps/web/src/routes/dashboard/+page.svelte new file mode 100644 index 00000000..cf0dc9b7 --- /dev/null +++ b/apps/web/src/routes/dashboard/+page.svelte @@ -0,0 +1,649 @@ + + + + Analytics Command Center | DevCard + + +
+
+
+

GitHub Analytics Command Center

+

Realtime insights into contributor intelligence and repository health.

+
+
+ + +
+
+ +
+
+ {#each stats as stat} + + {/each} +
+ +
+
+ +
+ +
+
+

🤖 AI Contribution Insights

+
+
    +
  • + +

    High merge probability detected for your recent frontend PRs based on historical maintainer behavior.

    +
  • +
  • + +

    Your PR review time is slightly above average today. Consider smaller, isolated commits.

    +
  • +
  • + +

    Found 3 open issues matching your React/Next.js skillset with "critical" priority.

    +
  • +
+ +
+
+ +
+

AI Reputation & Impact

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+

Contribution Velocity Predictor

+
+ +
+
+ + +
+
+ +
+
+ +
+
+ +
+

Networking & Event Intelligence

+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ +
+

AI Smart Developer Match Engine

+
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+

Event Intelligence Command Center

+
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+

Global Rankings & Achievements

+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+

Monetization & Bounties

+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+

AI Mentor & Career Growth

+
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+ +
+

Export & Portfolio

+
+ +
+
+ portfolioTheme = t} + /> + +
+
+ +
+
+ +
+
+
+
+ +