From fbfadba49a1b449a2bf6640d994909a5180a09c9 Mon Sep 17 00:00:00 2001 From: Bhuvanesh S Date: Fri, 29 May 2026 22:00:49 +0530 Subject: [PATCH 1/4] feat: add Web3 & Decentralized Identity Integration --- .../components/AIEngagementInsights.svelte | 15 + .../src/lib/components/AISkillMatcher.svelte | 20 + .../lib/components/AchievementBadges.svelte | 111 +++ .../src/lib/components/ActivityHeatmap.svelte | 189 +++++ .../src/lib/components/AnalyticsWidget.svelte | 126 ++++ .../web/src/lib/components/BountyBoard.svelte | 196 +++++ .../lib/components/BountyEarningsChart.svelte | 170 +++++ .../web/src/lib/components/BountyRadar.svelte | 138 ++++ .../lib/components/CodeReviewInsights.svelte | 147 ++++ .../lib/components/CompatibilityRadar.svelte | 209 ++++++ .../ContributionForecastChart.svelte | 193 +++++ .../lib/components/ContributionRadar.svelte | 164 ++++ .../components/DecentralizedReputation.svelte | 306 ++++++++ .../lib/components/DeveloperMatchCard.svelte | 219 ++++++ .../lib/components/EmbedCodeGenerator.svelte | 150 ++++ .../components/EventInteractionHeatmap.svelte | 124 ++++ apps/web/src/lib/components/EventRadar.svelte | 139 ++++ .../src/lib/components/EventTimeline.svelte | 145 ++++ .../lib/components/GlobalLeaderboard.svelte | 214 ++++++ .../web/src/lib/components/GrowthRadar.svelte | 146 ++++ .../web/src/lib/components/InsightFeed.svelte | 93 +++ .../components/LearningPathTimeline.svelte | 160 ++++ .../lib/components/LiveActivityFeed.svelte | 19 + .../src/lib/components/LivePreviewPane.svelte | 170 +++++ .../src/lib/components/MentorshipMatch.svelte | 139 ++++ .../lib/components/MomentumInsights.svelte | 15 + .../lib/components/NFTBadgeShowcase.svelte | 401 ++++++++++ .../NetworkingGrowthForecast.svelte | 129 ++++ .../lib/components/NetworkingPulseCard.svelte | 198 +++++ .../NetworkingRecommendationPanel.svelte | 146 ++++ .../src/lib/components/OSSImpactGraph.svelte | 149 ++++ .../components/PortfolioThemeSelector.svelte | 129 ++++ .../web/src/lib/components/RSVPTracker.svelte | 177 +++++ .../src/lib/components/RankingTierCard.svelte | 201 +++++ .../RealtimeConnectionStream.svelte | 129 ++++ .../lib/components/ReputationScoreCard.svelte | 204 +++++ .../lib/components/SkillGapAnalyzer.svelte | 184 +++++ .../lib/components/SponsorshipGraph.svelte | 193 +++++ .../lib/components/TopContributorsFeed.svelte | 19 + .../lib/components/VelocityScoreCard.svelte | 173 +++++ .../components/VerifiableCredentials.svelte | 418 +++++++++++ .../lib/components/Web3WalletConnect.svelte | 490 ++++++++++++ .../lib/components/WidgetCustomizer.svelte | 117 +++ apps/web/src/lib/utils/chartMath.ts | 84 +++ apps/web/src/lib/utils/visualizationEngine.ts | 70 ++ apps/web/src/routes/dashboard/+page.svelte | 698 ++++++++++++++++++ apps/web/src/routes/u/[username]/+page.svelte | 6 +- 47 files changed, 8028 insertions(+), 4 deletions(-) create mode 100644 apps/web/src/lib/components/AIEngagementInsights.svelte create mode 100644 apps/web/src/lib/components/AISkillMatcher.svelte create mode 100644 apps/web/src/lib/components/AchievementBadges.svelte create mode 100644 apps/web/src/lib/components/ActivityHeatmap.svelte create mode 100644 apps/web/src/lib/components/AnalyticsWidget.svelte create mode 100644 apps/web/src/lib/components/BountyBoard.svelte create mode 100644 apps/web/src/lib/components/BountyEarningsChart.svelte create mode 100644 apps/web/src/lib/components/BountyRadar.svelte create mode 100644 apps/web/src/lib/components/CodeReviewInsights.svelte create mode 100644 apps/web/src/lib/components/CompatibilityRadar.svelte create mode 100644 apps/web/src/lib/components/ContributionForecastChart.svelte create mode 100644 apps/web/src/lib/components/ContributionRadar.svelte create mode 100644 apps/web/src/lib/components/DecentralizedReputation.svelte create mode 100644 apps/web/src/lib/components/DeveloperMatchCard.svelte create mode 100644 apps/web/src/lib/components/EmbedCodeGenerator.svelte create mode 100644 apps/web/src/lib/components/EventInteractionHeatmap.svelte create mode 100644 apps/web/src/lib/components/EventRadar.svelte create mode 100644 apps/web/src/lib/components/EventTimeline.svelte create mode 100644 apps/web/src/lib/components/GlobalLeaderboard.svelte create mode 100644 apps/web/src/lib/components/GrowthRadar.svelte create mode 100644 apps/web/src/lib/components/InsightFeed.svelte create mode 100644 apps/web/src/lib/components/LearningPathTimeline.svelte create mode 100644 apps/web/src/lib/components/LiveActivityFeed.svelte create mode 100644 apps/web/src/lib/components/LivePreviewPane.svelte create mode 100644 apps/web/src/lib/components/MentorshipMatch.svelte create mode 100644 apps/web/src/lib/components/MomentumInsights.svelte create mode 100644 apps/web/src/lib/components/NFTBadgeShowcase.svelte create mode 100644 apps/web/src/lib/components/NetworkingGrowthForecast.svelte create mode 100644 apps/web/src/lib/components/NetworkingPulseCard.svelte create mode 100644 apps/web/src/lib/components/NetworkingRecommendationPanel.svelte create mode 100644 apps/web/src/lib/components/OSSImpactGraph.svelte create mode 100644 apps/web/src/lib/components/PortfolioThemeSelector.svelte create mode 100644 apps/web/src/lib/components/RSVPTracker.svelte create mode 100644 apps/web/src/lib/components/RankingTierCard.svelte create mode 100644 apps/web/src/lib/components/RealtimeConnectionStream.svelte create mode 100644 apps/web/src/lib/components/ReputationScoreCard.svelte create mode 100644 apps/web/src/lib/components/SkillGapAnalyzer.svelte create mode 100644 apps/web/src/lib/components/SponsorshipGraph.svelte create mode 100644 apps/web/src/lib/components/TopContributorsFeed.svelte create mode 100644 apps/web/src/lib/components/VelocityScoreCard.svelte create mode 100644 apps/web/src/lib/components/VerifiableCredentials.svelte create mode 100644 apps/web/src/lib/components/Web3WalletConnect.svelte create mode 100644 apps/web/src/lib/components/WidgetCustomizer.svelte create mode 100644 apps/web/src/lib/utils/chartMath.ts create mode 100644 apps/web/src/lib/utils/visualizationEngine.ts create mode 100644 apps/web/src/routes/dashboard/+page.svelte 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/DecentralizedReputation.svelte b/apps/web/src/lib/components/DecentralizedReputation.svelte new file mode 100644 index 00000000..3c5c50aa --- /dev/null +++ b/apps/web/src/lib/components/DecentralizedReputation.svelte @@ -0,0 +1,306 @@ + + +
+
+ 🧬 +
+

Web3 Reputation Score

+ On-Chain Activity & Trust Metrics +
+
+ +
+
+ + + + +
+ {totalScore} + / {maxScore} +
+
+ +
+ {reputationTier} + Percentile: {percentile} +
+
+ +
+
+ Trust Factor Breakdown + +
+ +
+ {#each reputationMetrics as metric} +
+
+ {metric.icon} +
+ {metric.name} + {#if showBreakdown} +

{metric.desc}

+ {:else} + {metric.count} verified events + {/if} +
+
+ +{metric.pts} XP +
+ {/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/NFTBadgeShowcase.svelte b/apps/web/src/lib/components/NFTBadgeShowcase.svelte new file mode 100644 index 00000000..cacc32a6 --- /dev/null +++ b/apps/web/src/lib/components/NFTBadgeShowcase.svelte @@ -0,0 +1,401 @@ + + +
+
+ 🏆 +
+

NFT Achievement Gallery

+ Verified On-Chain Developer Badges +
+
+ +
+ {#each badges as badge} + + {/each} +
+ + {#if selectedBadge} + + {/if} +
+ + 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/VerifiableCredentials.svelte b/apps/web/src/lib/components/VerifiableCredentials.svelte new file mode 100644 index 00000000..aca3d2f0 --- /dev/null +++ b/apps/web/src/lib/components/VerifiableCredentials.svelte @@ -0,0 +1,418 @@ + + +
+
+ 🛡️ +
+

ZK Skill Credentials

+ W3C Decentralized Identifiers (DIDs) +
+
+ +
+ {#each credentials as cred} +
+
+
+

{cred.title}

+ {cred.issuer} • {cred.type} +
+ + 🛡️ + Verified + +
+ + +
+ {/each} +
+ + {#if showProofModal && selectedCredential} + + {/if} +
+ + diff --git a/apps/web/src/lib/components/Web3WalletConnect.svelte b/apps/web/src/lib/components/Web3WalletConnect.svelte new file mode 100644 index 00000000..0601f2a1 --- /dev/null +++ b/apps/web/src/lib/components/Web3WalletConnect.svelte @@ -0,0 +1,490 @@ + + +
+
+
+ 🔌 +

Web3 Identity Portal

+
+ {#if isConnected} + Connected + {:else if isConnecting} + Connecting... + {:else} + Disconnected + {/if} +
+ +
+ {#if !isConnected && !isConnecting} +

Link your crypto wallet to anchor your developer identity and showcase ZK skills & NFTs.

+ +
+ {#each wallets as wallet} + + {/each} +
+ {:else if isConnecting} +
+
+

Connecting to {selectedWallet}...

+ Awaiting signature approval in your wallet extension. +
+ {:else} + +
+
+
+ 🧬 +
+
+

{ensName || 'No ENS Domain'}

+
+ {walletAddress.slice(0, 6)}...{walletAddress.slice(-4)} + +
+
+
+ +
+ Active Network +
+ + {#if showDropdown} +
+ {#each networks as net} + + {/each} +
+ {/if} +
+
+ +
+ Account Balance +

{balance}

+
+ + +
+ {/if} +
+
+ + 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..f483a3db --- /dev/null +++ b/apps/web/src/routes/dashboard/+page.svelte @@ -0,0 +1,698 @@ + + + + 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

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

Web3 & Decentralized Identity

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

Export & Portfolio

+
+ +
+
+ portfolioTheme = t} + /> + +
+
+ +
+
+ +
+
+
+
+ + diff --git a/apps/web/src/routes/u/[username]/+page.svelte b/apps/web/src/routes/u/[username]/+page.svelte index 50cb4226..90837b8a 100644 --- a/apps/web/src/routes/u/[username]/+page.svelte +++ b/apps/web/src/routes/u/[username]/+page.svelte @@ -17,7 +17,7 @@ let mounted = $state(false); let copyMessage = $state(''); let copyStatus = $state<'success' | 'error'>('success'); - let copyMessageTimeout: ReturnType; + let copyMessageTimeout: ReturnType | undefined = undefined; onMount(() => { mounted = true; @@ -37,9 +37,7 @@ clearTimeout(copyMessageTimeout); } - clearTimeout(copyTimeout); - - copyTimeout = setTimeout(() => { + copyMessageTimeout = setTimeout(() => { copyMessage = ''; }, 3000); } From 00797f784ef423aeb929c262676d027843b9c862 Mon Sep 17 00:00:00 2001 From: Bhuvanesh S Date: Fri, 29 May 2026 22:07:15 +0530 Subject: [PATCH 2/4] feat: add Team & Organization Dynamics Simulator --- .../ActiveWorkloadDistribution.svelte | 223 ++++++++++ .../lib/components/OrgHierarchyTree.svelte | 284 +++++++++++++ .../lib/components/PeerReviewFeedback.svelte | 382 ++++++++++++++++++ .../components/TeamCompatibilityMatrix.svelte | 273 +++++++++++++ apps/web/src/routes/dashboard/+page.svelte | 49 +++ 5 files changed, 1211 insertions(+) create mode 100644 apps/web/src/lib/components/ActiveWorkloadDistribution.svelte create mode 100644 apps/web/src/lib/components/OrgHierarchyTree.svelte create mode 100644 apps/web/src/lib/components/PeerReviewFeedback.svelte create mode 100644 apps/web/src/lib/components/TeamCompatibilityMatrix.svelte diff --git a/apps/web/src/lib/components/ActiveWorkloadDistribution.svelte b/apps/web/src/lib/components/ActiveWorkloadDistribution.svelte new file mode 100644 index 00000000..e53dd6d0 --- /dev/null +++ b/apps/web/src/lib/components/ActiveWorkloadDistribution.svelte @@ -0,0 +1,223 @@ + + +
+
+ 📊 +
+

Active Workload Distribution

+ Weekly Allocation & Project Health +
+
+ +
+
+ Total Allocation + {capacityUsed}% Capacity +
+ +
+ {#each projects as project} +
hoveredProject = project.id} + onmouseleave={() => hoveredProject = null} + >
+ {/each} +
+
+ +
+ {#each projects as project} +
hoveredProject = project.id} + onmouseleave={() => hoveredProject = null} + > +
+ +
+ {project.name} + {project.count} +
+
+ +
+ {project.allocation}% + + {project.status} + +
+
+ {/each} +
+
+ + diff --git a/apps/web/src/lib/components/OrgHierarchyTree.svelte b/apps/web/src/lib/components/OrgHierarchyTree.svelte new file mode 100644 index 00000000..e222ce7d --- /dev/null +++ b/apps/web/src/lib/components/OrgHierarchyTree.svelte @@ -0,0 +1,284 @@ + + +
+
+ 🌳 +
+

Organization Hierarchy

+ Reporting Lines & Org Architecture +
+
+ +
+
+ {#each hierarchyNodes as node, index} +
+ {#if index > 0} +
+ {/if} + + +
+ {/each} +
+
+ +
+ {#if selectedNode} +
+
+ {selectedNode.avatar} +
+

{selectedNode.name}

+ {selectedNode.role} +
+
+
+
+ Department: + {selectedNode.department} +
+
+ Level: + L{selectedNode.level} (Org tier) +
+
+
+ {:else} +

Select a node in the org tree to inspect staff profile details.

+ {/if} +
+
+ + diff --git a/apps/web/src/lib/components/PeerReviewFeedback.svelte b/apps/web/src/lib/components/PeerReviewFeedback.svelte new file mode 100644 index 00000000..0819288a --- /dev/null +++ b/apps/web/src/lib/components/PeerReviewFeedback.svelte @@ -0,0 +1,382 @@ + + +
+
+ 💬 +
+

Peer Review Ecosystem

+ Teammate Sentiment & Feedback Stream +
+
+ +
+
+ {avgRating} +
+ ⭐⭐⭐⭐⭐ + Avg rating ({reviews.length} reviews) +
+
+
+
+ 92% Positive + Sentiment Sync +
+
+
+
+
+
+ +
+ {#each reviews as review} +
+
+ {review.reviewer} + {review.date} +
+
+ {'★'.repeat(review.rating)}{'☆'.repeat(5 - review.rating)} +
+

"{review.comment}"

+
+ {/each} +
+ + +
+ + diff --git a/apps/web/src/lib/components/TeamCompatibilityMatrix.svelte b/apps/web/src/lib/components/TeamCompatibilityMatrix.svelte new file mode 100644 index 00000000..54162eb5 --- /dev/null +++ b/apps/web/src/lib/components/TeamCompatibilityMatrix.svelte @@ -0,0 +1,273 @@ + + +
+
+ 🤝 +
+

Team Compatibility Matrix

+ AI-Powered Synergy & Trait Alignment +
+
+ +
+ {#each teamMembers as member} + + {/each} +
+ +
+ {#if selectedMember} +
+

Trait Breakdown: {selectedMember.name}

+ +
+
+ Technical + {selectedMember.traits.technical}% +
+
+ Communication + {selectedMember.traits.communication}% +
+
+ Culture + {selectedMember.traits.culture}% +
+
+ Execution Speed + {selectedMember.traits.speed}% +
+
+ +

💡 {selectedMember.notes}

+
+ {:else} +
+

Select a team member above to analyze granular alignment metrics.

+
+ {/if} +
+
+ + diff --git a/apps/web/src/routes/dashboard/+page.svelte b/apps/web/src/routes/dashboard/+page.svelte index f483a3db..0258e5fb 100644 --- a/apps/web/src/routes/dashboard/+page.svelte +++ b/apps/web/src/routes/dashboard/+page.svelte @@ -41,6 +41,10 @@ import VerifiableCredentials from '$lib/components/VerifiableCredentials.svelte'; import NFTBadgeShowcase from '$lib/components/NFTBadgeShowcase.svelte'; import DecentralizedReputation from '$lib/components/DecentralizedReputation.svelte'; + import TeamCompatibilityMatrix from '$lib/components/TeamCompatibilityMatrix.svelte'; + import ActiveWorkloadDistribution from '$lib/components/ActiveWorkloadDistribution.svelte'; + import OrgHierarchyTree from '$lib/components/OrgHierarchyTree.svelte'; + import PeerReviewFeedback from '$lib/components/PeerReviewFeedback.svelte'; let portfolioTheme = $state('glassmorphism'); @@ -246,6 +250,25 @@ +
+

Team & Organization Dynamics

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

Web3 & Decentralized Identity

@@ -695,4 +718,30 @@ grid-template-columns: 1fr; } } + + .team-widgets { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1.5rem; + } + + .team-matrix-wrapper, + .team-workload-wrapper, + .team-hierarchy-wrapper, + .peer-feedback-wrapper { + display: flex; + flex-direction: column; + } + + @media (max-width: 1200px) { + .team-widgets { + grid-template-columns: repeat(2, 1fr); + } + } + + @media (max-width: 768px) { + .team-widgets { + grid-template-columns: 1fr; + } + } From 6ffc2c15af312070270c466d043382a675ab9814 Mon Sep 17 00:00:00 2001 From: Bhuvanesh S Date: Fri, 29 May 2026 22:16:09 +0530 Subject: [PATCH 3/4] feat: implement Master Animation Pass & Final Polish --- apps/web/src/app.css | 39 ++++++++++++++++++ apps/web/src/routes/dashboard/+page.svelte | 48 +++++++++++----------- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/apps/web/src/app.css b/apps/web/src/app.css index 0f9e8bb0..c9df8aec 100644 --- a/apps/web/src/app.css +++ b/apps/web/src/app.css @@ -203,4 +203,43 @@ html { :root:not(.dark) .btn-secondary { border-color: var(--border); background: rgba(0, 0, 0, 0.04); +} + +/* ---------- Premium Animation & Interaction Pass ---------- */ + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(22px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeInUp 0.75s cubic-bezier(0.16, 1, 0.3, 1) both; + will-change: transform, opacity; +} + +.glass { + transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.3s cubic-bezier(0.16, 1, 0.3, 1); +} + +.glass:hover { + transform: translateY(-4px); + box-shadow: 0 20px 40px -15px rgba(99, 102, 241, 0.15), var(--shadow-nav); + border-color: rgba(99, 102, 241, 0.35); +} + +/* Specific section scale-ups on hover */ +.kpi-grid > *, .reputation-widgets > *, .velocity-widgets > *, .networking-widgets > *, .match-widgets > *, .event-widgets > *, .ranking-widgets > *, .monetization-widgets > *, .mentor-widgets > *, .team-widgets > *, .web3-widgets > *, .export-widgets > * { + transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.3s cubic-bezier(0.16, 1, 0.3, 1); +} + +.kpi-grid > *:hover, .reputation-widgets > *:hover, .velocity-widgets > *:hover, .networking-widgets > *:hover, .match-widgets > *:hover, .event-widgets > *:hover, .ranking-widgets > *:hover, .monetization-widgets > *:hover, .mentor-widgets > *:hover, .team-widgets > *:hover, .web3-widgets > *:hover, .export-widgets > *:hover { + transform: translateY(-3px) scale(1.01); + box-shadow: 0 15px 30px -10px rgba(99, 102, 241, 0.12), var(--shadow-nav); + border-color: rgba(99, 102, 241, 0.3); } \ No newline at end of file diff --git a/apps/web/src/routes/dashboard/+page.svelte b/apps/web/src/routes/dashboard/+page.svelte index 0258e5fb..2df4cdc5 100644 --- a/apps/web/src/routes/dashboard/+page.svelte +++ b/apps/web/src/routes/dashboard/+page.svelte @@ -74,7 +74,7 @@
-
+
{#each stats as stat} -
+
@@ -113,11 +113,11 @@
-
+

AI Reputation & Impact

-
+
@@ -129,11 +129,11 @@
-
+

Contribution Velocity Predictor

-
+
@@ -146,11 +146,11 @@
-
+

Networking & Event Intelligence

-
+
@@ -164,11 +164,11 @@
-
+

AI Smart Developer Match Engine

-
+
@@ -181,11 +181,11 @@
-
+

Event Intelligence Command Center

-
+
@@ -198,11 +198,11 @@
-
+

Global Rankings & Achievements

-
+
@@ -215,11 +215,11 @@
-
+

Monetization & Bounties

-
+
@@ -232,11 +232,11 @@
-
+

AI Mentor & Career Growth

-
+
@@ -250,11 +250,11 @@
-
+

Team & Organization Dynamics

-
+
@@ -269,11 +269,11 @@
-
+

Web3 & Decentralized Identity

-
+
@@ -288,11 +288,11 @@
-
+

Export & Portfolio

-
+
Date: Fri, 29 May 2026 22:33:06 +0530 Subject: [PATCH 4/4] refactor: harden analytics infrastructure and improve dashboard maintainability Signed-off-by: Bhuvanesh S --- .../src/lib/components/ActivityHeatmap.svelte | 8 + .../lib/components/BaseForecastChart.svelte | 270 ++++++++++++++++++ .../src/lib/components/BaseRadarChart.svelte | 260 +++++++++++++++++ .../lib/components/BountyEarningsChart.svelte | 136 ++------- .../web/src/lib/components/BountyRadar.svelte | 130 +-------- .../lib/components/CompatibilityRadar.svelte | 198 +------------ .../ContributionForecastChart.svelte | 193 +------------ .../lib/components/ContributionRadar.svelte | 158 +--------- .../components/EventInteractionHeatmap.svelte | 8 + apps/web/src/lib/components/EventRadar.svelte | 131 +-------- .../web/src/lib/components/GrowthRadar.svelte | 140 +-------- .../NetworkingGrowthForecast.svelte | 128 +-------- .../src/lib/components/OSSImpactGraph.svelte | 2 +- .../lib/components/SkillGapAnalyzer.svelte | 12 +- .../lib/components/SponsorshipGraph.svelte | 4 +- apps/web/src/lib/utils/analyticsHelpers.ts | 86 ++++++ apps/web/src/routes/dashboard/+page.svelte | 26 +- .../src/routes/devcard/[id]/+page.server.ts | 6 +- 18 files changed, 767 insertions(+), 1129 deletions(-) create mode 100644 apps/web/src/lib/components/BaseForecastChart.svelte create mode 100644 apps/web/src/lib/components/BaseRadarChart.svelte create mode 100644 apps/web/src/lib/utils/analyticsHelpers.ts diff --git a/apps/web/src/lib/components/ActivityHeatmap.svelte b/apps/web/src/lib/components/ActivityHeatmap.svelte index acb0577a..f4b4ffb1 100644 --- a/apps/web/src/lib/components/ActivityHeatmap.svelte +++ b/apps/web/src/lib/components/ActivityHeatmap.svelte @@ -39,6 +39,13 @@ default: return 'var(--color-level-0)'; } } + + function handleKeydown(event: KeyboardEvent, day: { intensity: number, date: Date }) { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + alert(`${day.date.toDateString()}: ${day.intensity * 3} contributions`); + } + }
@@ -61,6 +68,7 @@ tabindex="0" style="background-color: {getIntensityColor(day.intensity)};" title="{day.date.toDateString()}: {day.intensity * 3} contributions" + onkeydown={(e) => handleKeydown(e, day)} >
{/each}
diff --git a/apps/web/src/lib/components/BaseForecastChart.svelte b/apps/web/src/lib/components/BaseForecastChart.svelte new file mode 100644 index 00000000..00ebae6c --- /dev/null +++ b/apps/web/src/lib/components/BaseForecastChart.svelte @@ -0,0 +1,270 @@ + + +
+
+

{title}

+ {#if predictedData && predictedData.length > 0} +
+ + + Historical + + + + Predicted + +
+ {/if} +
+ + +
+ + diff --git a/apps/web/src/lib/components/BaseRadarChart.svelte b/apps/web/src/lib/components/BaseRadarChart.svelte new file mode 100644 index 00000000..03a0dd15 --- /dev/null +++ b/apps/web/src/lib/components/BaseRadarChart.svelte @@ -0,0 +1,260 @@ + + +
+
+

{title}

+ {#if showLegend || compareData.length > 0} +
+ + + {legendLabel1} + + {#if compareData.length > 0} + + + {legendLabel2} + + {/if} +
+ {/if} +
+ +
+ + + {#each gridLevels as level} + + {/each} + + + {#each data as _, i} + {@const { x, y } = getRadarCoordinates(100, i, sides, center, radius)} + + {/each} + + + {#if comparePoints} + + {/if} + + + + + + {#if compareData.length > 0} + {#each compareData as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + handleKeydown(e, d, true)} + > + {legendLabel2} {d.label}: {d.value}% + + {/each} + {/if} + + + {#each data as d, i} + {@const { x, y } = getRadarCoordinates(d.value, i, sides, center, radius)} + handleKeydown(e, d, false)} + > + {legendLabel1} {d.label}: {d.value}% + + {/each} + + + {#each labels as label} + + {label.text} + + {/each} + +
+
+ + diff --git a/apps/web/src/lib/components/BountyEarningsChart.svelte b/apps/web/src/lib/components/BountyEarningsChart.svelte index d635fa77..dd1ed44e 100644 --- a/apps/web/src/lib/components/BountyEarningsChart.svelte +++ b/apps/web/src/lib/components/BountyEarningsChart.svelte @@ -1,5 +1,5 @@

Cumulative Earnings

- ${values[values.length - 1].toLocaleString()} + ${total.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} - +
+
@@ -100,7 +44,7 @@ border-radius: var(--radius-lg); display: flex; flex-direction: column; - gap: 1.5rem; + gap: 1rem; height: 100%; } @@ -122,49 +66,15 @@ color: #10b981; } - .chart-container { + .chart-wrapper { flex: 1; - display: flex; - align-items: center; - justify-content: center; width: 100%; } - svg { - width: 100%; - height: 100%; - overflow: visible; - } - - .grid-line { - stroke: rgba(255, 255, 255, 0.05); - stroke-width: 1; - } - - .axis-label { - fill: var(--text-muted); - font-size: 0.7rem; - font-family: inherit; - } - - .line-path { - fill: none; - stroke: #10b981; - stroke-width: 3; - stroke-linecap: round; - stroke-linejoin: round; - } - - .data-point { - fill: var(--bg-primary); - stroke: #10b981; - stroke-width: 2; - transition: transform 0.2s, r 0.2s; - } - - .data-point:hover { - r: 6; - fill: #10b981; - cursor: pointer; + :global(.bounty-earnings .forecast-chart) { + padding: 0 !important; + background: transparent !important; + border: none !important; + box-shadow: none !important; } diff --git a/apps/web/src/lib/components/BountyRadar.svelte b/apps/web/src/lib/components/BountyRadar.svelte index 0d9c4646..ecbb17fc 100644 --- a/apps/web/src/lib/components/BountyRadar.svelte +++ b/apps/web/src/lib/components/BountyRadar.svelte @@ -1,10 +1,5 @@ -
-
-

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/CompatibilityRadar.svelte b/apps/web/src/lib/components/CompatibilityRadar.svelte index 6205aede..b0af5866 100644 --- a/apps/web/src/lib/components/CompatibilityRadar.svelte +++ b/apps/web/src/lib/components/CompatibilityRadar.svelte @@ -1,10 +1,5 @@ -
-
-

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 index 11a66058..48c921cd 100644 --- a/apps/web/src/lib/components/ContributionForecastChart.svelte +++ b/apps/web/src/lib/components/ContributionForecastChart.svelte @@ -1,4 +1,6 @@ -
-
-

{title}

-
- Historical - Predicted -
-
- - -
- - + diff --git a/apps/web/src/lib/components/ContributionRadar.svelte b/apps/web/src/lib/components/ContributionRadar.svelte index 06f4d5fc..f2cec9a8 100644 --- a/apps/web/src/lib/components/ContributionRadar.svelte +++ b/apps/web/src/lib/components/ContributionRadar.svelte @@ -1,4 +1,6 @@ -
-

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/EventInteractionHeatmap.svelte b/apps/web/src/lib/components/EventInteractionHeatmap.svelte index 9a322895..73f895d8 100644 --- a/apps/web/src/lib/components/EventInteractionHeatmap.svelte +++ b/apps/web/src/lib/components/EventInteractionHeatmap.svelte @@ -22,6 +22,13 @@ if (intensity === 3) return 'high'; return 'peak'; } + + function handleKeydown(event: KeyboardEvent, intensity: number, idx: number) { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + alert(`Hour ${idx % hoursPerDay + 1}, Day ${Math.floor(idx / hoursPerDay) + 1}: Interaction level ${intensity}`); + } + }
@@ -37,6 +44,7 @@ tabindex="0" title="Hour {i % hoursPerDay + 1}, Day {Math.floor(i / hoursPerDay) + 1}: Intensity {intensity}" aria-label="Event interaction intensity {intensity}" + onkeydown={(e) => handleKeydown(e, intensity, i)} >
{/each}
diff --git a/apps/web/src/lib/components/EventRadar.svelte b/apps/web/src/lib/components/EventRadar.svelte index 873f82e1..3bb515d5 100644 --- a/apps/web/src/lib/components/EventRadar.svelte +++ b/apps/web/src/lib/components/EventRadar.svelte @@ -1,10 +1,5 @@ -
-
-

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/GrowthRadar.svelte b/apps/web/src/lib/components/GrowthRadar.svelte index 0e63f24c..21e729e8 100644 --- a/apps/web/src/lib/components/GrowthRadar.svelte +++ b/apps/web/src/lib/components/GrowthRadar.svelte @@ -1,4 +1,6 @@ -
-

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/NetworkingGrowthForecast.svelte b/apps/web/src/lib/components/NetworkingGrowthForecast.svelte index 04991966..97a6e137 100644 --- a/apps/web/src/lib/components/NetworkingGrowthForecast.svelte +++ b/apps/web/src/lib/components/NetworkingGrowthForecast.svelte @@ -1,4 +1,6 @@ -
-
-

{title}

-
- - -
- - + diff --git a/apps/web/src/lib/components/OSSImpactGraph.svelte b/apps/web/src/lib/components/OSSImpactGraph.svelte index 3fe7518b..3a068bc9 100644 --- a/apps/web/src/lib/components/OSSImpactGraph.svelte +++ b/apps/web/src/lib/components/OSSImpactGraph.svelte @@ -16,7 +16,7 @@ maxExpected?: number; }>(); - let maxVal = $derived(Math.max(...data.map(d => d.value), maxExpected)); + let maxVal = $derived(Math.max(...data.map((d: { value: number }) => d.value), maxExpected));
diff --git a/apps/web/src/lib/components/SkillGapAnalyzer.svelte b/apps/web/src/lib/components/SkillGapAnalyzer.svelte index fa3981fe..0a3d9526 100644 --- a/apps/web/src/lib/components/SkillGapAnalyzer.svelte +++ b/apps/web/src/lib/components/SkillGapAnalyzer.svelte @@ -21,7 +21,7 @@ // Helper to generate polygon string function getPolygon(dataKey: 'current' | 'target') { - return skills.map((s, i) => { + return skills.map((s: { name: string, current: number, target: number }, i: number) => { const { x, y } = getRadarCoordinates(s[dataKey], i, sides, center, radius); return `${x},${y}`; }).join(' '); @@ -33,7 +33,7 @@ let gridLevels = [25, 50, 75, 100]; // Custom label generation - let labels = $derived(skills.map((s, i) => { + let labels = $derived(skills.map((s: { name: string, current: number, target: number }, i: number) => { return getRadarCoordinates(125, i, sides, center, radius); })); @@ -45,7 +45,13 @@
- + {#each gridLevels as level} diff --git a/apps/web/src/lib/components/SponsorshipGraph.svelte b/apps/web/src/lib/components/SponsorshipGraph.svelte index af036896..73e8ac43 100644 --- a/apps/web/src/lib/components/SponsorshipGraph.svelte +++ b/apps/web/src/lib/components/SponsorshipGraph.svelte @@ -13,7 +13,7 @@ distribution?: { tier: string, amount: number, count: number, color: string }[]; }>(); - let maxAmount = $derived(Math.max(...distribution.map(d => d.amount))); + let maxAmount = $derived(Math.max(...distribution.map((d: { amount: number }) => d.amount)));
@@ -28,7 +28,7 @@ Active Sponsors
- + +3 this month diff --git a/apps/web/src/lib/utils/analyticsHelpers.ts b/apps/web/src/lib/utils/analyticsHelpers.ts new file mode 100644 index 00000000..5e7c5a25 --- /dev/null +++ b/apps/web/src/lib/utils/analyticsHelpers.ts @@ -0,0 +1,86 @@ +/** + * Utility functions for metrics, trends, and analytical calculations + */ + +/** + * Calculates percentage change between two values + */ +export function calculateTrend(current: number, previous: number): { + percentage: string; + isPositive: boolean; + formatted: string; +} { + if (previous === 0) { + return { + percentage: '0%', + isPositive: true, + formatted: '0%' + }; + } + + const diff = current - previous; + const pct = (diff / previous) * 100; + const isPositive = pct >= 0; + const absPct = Math.abs(pct).toFixed(1); + + return { + percentage: `${absPct}%`, + isPositive, + formatted: `${isPositive ? '↑' : '↓'} ${absPct}%` + }; +} + +/** + * Formats values to localized currency or compact formats + */ +export function formatMetric(value: number, type: 'currency' | 'number' | 'percent' | 'compact' = 'number'): string { + if (type === 'currency') { + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: 'USD', + maximumFractionDigits: 0 + }).format(value); + } + + if (type === 'percent') { + return `${value.toFixed(1)}%`; + } + + if (type === 'compact') { + return new Intl.NumberFormat('en-US', { + notation: 'compact', + compactDisplay: 'short' + }).format(value); + } + + return new Intl.NumberFormat('en-US').format(value); +} + +/** + * Generates standard tooltip content based on axis label, value, and unit + */ +export function generateTooltipText(label: string, value: number | string, unit: string = ''): string { + const formattedVal = typeof value === 'number' ? formatMetric(value) : value; + return `${label}: ${formattedVal}${unit ? ' ' + unit : ''}`; +} + +/** + * Determines ranking tier based on score + */ +export function calculateRankTier(score: number): { + tier: string; + color: string; +} { + if (score >= 900) return { tier: 'Diamond', color: '#818cf8' }; + if (score >= 750) return { tier: 'Gold', color: '#facc15' }; + if (score >= 500) return { tier: 'Silver', color: '#94a3b8' }; + return { tier: 'Bronze', color: '#b45309' }; +} + +/** + * Computes average of an array of numbers safely + */ +export function calculateAverage(data: number[]): number { + if (!data || data.length === 0) return 0; + return data.reduce((sum, val) => sum + val, 0) / data.length; +} diff --git a/apps/web/src/routes/dashboard/+page.svelte b/apps/web/src/routes/dashboard/+page.svelte index 2df4cdc5..0a906b8b 100644 --- a/apps/web/src/routes/dashboard/+page.svelte +++ b/apps/web/src/routes/dashboard/+page.svelte @@ -6,20 +6,18 @@ import ContributionRadar from '$lib/components/ContributionRadar.svelte'; import VelocityScoreCard from '$lib/components/VelocityScoreCard.svelte'; import ContributionForecastChart from '$lib/components/ContributionForecastChart.svelte'; - import MomentumInsights from '$lib/components/MomentumInsights.svelte'; + import InsightFeed from '$lib/components/InsightFeed.svelte'; import GrowthRadar from '$lib/components/GrowthRadar.svelte'; import NetworkingPulseCard from '$lib/components/NetworkingPulseCard.svelte'; import RealtimeConnectionStream from '$lib/components/RealtimeConnectionStream.svelte'; import NetworkingGrowthForecast from '$lib/components/NetworkingGrowthForecast.svelte'; import EventInteractionHeatmap from '$lib/components/EventInteractionHeatmap.svelte'; - import AIEngagementInsights from '$lib/components/AIEngagementInsights.svelte'; import DeveloperMatchCard from '$lib/components/DeveloperMatchCard.svelte'; import CompatibilityRadar from '$lib/components/CompatibilityRadar.svelte'; import AISkillMatcher from '$lib/components/AISkillMatcher.svelte'; import NetworkingRecommendationPanel from '$lib/components/NetworkingRecommendationPanel.svelte'; import EventTimeline from '$lib/components/EventTimeline.svelte'; import EventRadar from '$lib/components/EventRadar.svelte'; - import LiveActivityFeed from '$lib/components/LiveActivityFeed.svelte'; import RSVPTracker from '$lib/components/RSVPTracker.svelte'; import GlobalLeaderboard from '$lib/components/GlobalLeaderboard.svelte'; import RankingTierCard from '$lib/components/RankingTierCard.svelte'; @@ -136,7 +134,11 @@
- +
@@ -160,7 +162,11 @@
- +
@@ -194,7 +200,15 @@
- +
diff --git a/apps/web/src/routes/devcard/[id]/+page.server.ts b/apps/web/src/routes/devcard/[id]/+page.server.ts index a93fbc75..952fd31f 100644 --- a/apps/web/src/routes/devcard/[id]/+page.server.ts +++ b/apps/web/src/routes/devcard/[id]/+page.server.ts @@ -19,9 +19,9 @@ export const load: PageServerLoad = async ({ params, fetch }) => { const card = await res.json(); return { card }; - } catch (error) { - if (error && typeof error === 'object' && 'status' in error) { - throw error; + } catch (err) { + if (err && typeof err === 'object' && 'status' in err) { + throw err; } throw error(500, 'Failed to connect to backend'); }