portfolio-analyser / index.html
blackrajeev's picture
undefined - Initial Deployment
15ed379 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GitHub Portfolio Analyzer</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.gradient-bg {
background: linear-gradient(135deg, #6e8efb, #a777e3);
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
}
.language-bar {
height: 10px;
border-radius: 5px;
display: inline-block;
vertical-align: middle;
margin-right: 5px;
}
.radar-chart {
width: 100%;
height: 300px;
}
.heatmap {
display: grid;
grid-template-columns: repeat(52, 1fr);
gap: 2px;
}
.heatmap-cell {
width: 10px;
height: 10px;
border-radius: 2px;
}
.repo-card:hover .repo-stats {
opacity: 1;
transform: translateY(0);
}
.repo-stats {
opacity: 0;
transform: translateY(10px);
transition: all 0.3s ease;
}
.animate-pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
</style>
</head>
<body class="bg-gray-50 font-sans">
<!-- Navigation -->
<nav class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<div class="flex-shrink-0 flex items-center">
<i class="fab fa-github text-2xl text-gray-800 mr-2"></i>
<span class="text-xl font-bold text-gray-800">Portfolio Analyzer</span>
</div>
</div>
<div class="hidden sm:ml-6 sm:flex sm:items-center">
<button id="loginBtn" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<i class="fab fa-github mr-2"></i> Login with GitHub
</button>
</div>
</div>
</div>
</nav>
<!-- Hero Section -->
<div class="gradient-bg text-white">
<div class="max-w-7xl mx-auto py-12 px-4 sm:px-6 lg:px-8 text-center">
<h1 class="text-4xl font-extrabold tracking-tight sm:text-5xl lg:text-6xl mb-6">
Analyze Your GitHub Portfolio
</h1>
<p class="text-xl max-w-3xl mx-auto">
Get detailed insights about your coding skills, project quality, and areas for improvement based on your GitHub repositories.
</p>
<div class="mt-8">
<button id="heroLoginBtn" class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-indigo-600 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-white">
<i class="fab fa-github mr-2"></i> Connect Your GitHub Account
</button>
</div>
</div>
</div>
<!-- Features Section -->
<div class="py-12 bg-white">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="lg:text-center">
<h2 class="text-base text-indigo-600 font-semibold tracking-wide uppercase">Features</h2>
<p class="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">
Comprehensive Code Analysis
</p>
</div>
<div class="mt-10">
<div class="grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-3">
<div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<i class="fas fa-code text-xl"></i>
</div>
<div class="mt-5">
<h3 class="text-lg font-medium text-gray-900">Language Analysis</h3>
<p class="mt-2 text-base text-gray-500">
Detailed breakdown of programming languages used across all your repositories with proficiency metrics.
</p>
</div>
</div>
<div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<i class="fas fa-check-circle text-xl"></i>
</div>
<div class="mt-5">
<h3 class="text-lg font-medium text-gray-900">Code Quality</h3>
<p class="mt-2 text-base text-gray-500">
Automated assessment of code quality including complexity, maintainability, and best practices.
</p>
</div>
</div>
<div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<i class="fas fa-vial text-xl"></i>
</div>
<div class="mt-5">
<h3 class="text-lg font-medium text-gray-900">Test Coverage</h3>
<p class="mt-2 text-base text-gray-500">
Evaluation of test coverage and testing practices across your projects.
</p>
</div>
</div>
<div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<i class="fas fa-project-diagram text-xl"></i>
</div>
<div class="mt-5">
<h3 class="text-lg font-medium text-gray-900">Project Structure</h3>
<p class="mt-2 text-base text-gray-500">
Analysis of project architecture and organization patterns.
</p>
</div>
</div>
<div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<i class="fas fa-chart-line text-xl"></i>
</div>
<div class="mt-5">
<h3 class="text-lg font-medium text-gray-900">Activity Metrics</h3>
<p class="mt-2 text-base text-gray-500">
Tracking of your coding activity, commit frequency, and contribution patterns.
</p>
</div>
</div>
<div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<i class="fas fa-bullseye text-xl"></i>
</div>
<div class="mt-5">
<h3 class="text-lg font-medium text-gray-900">Milestone Planning</h3>
<p class="mt-2 text-base text-gray-500">
Personalized recommendations for skill development and project milestones.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Dashboard Section (Visible after login) -->
<div id="dashboard" class="hidden py-12 bg-gray-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center mb-8">
<div>
<h2 class="text-2xl font-bold text-gray-900">Your GitHub Portfolio Analysis</h2>
<p class="text-gray-600">Based on your public repositories</p>
</div>
<div class="flex items-center">
<img id="userAvatar" class="h-10 w-10 rounded-full mr-3" src="" alt="">
<span id="username" class="font-medium text-gray-900"></span>
</div>
</div>
<!-- Summary Cards -->
<div class="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4 mb-8">
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-indigo-500 rounded-md p-3">
<i class="fas fa-code text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Total Repositories</dt>
<dd id="totalRepos" class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">0</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-green-500 rounded-md p-3">
<i class="fas fa-star text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Total Stars</dt>
<dd id="totalStars" class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">0</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-blue-500 rounded-md p-3">
<i class="fas fa-code-branch text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Primary Language</dt>
<dd id="primaryLanguage" class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">-</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="bg-white overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<div class="flex items-center">
<div class="flex-shrink-0 bg-purple-500 rounded-md p-3">
<i class="fas fa-chart-pie text-white"></i>
</div>
<div class="ml-5 w-0 flex-1">
<dl>
<dt class="text-sm font-medium text-gray-500 truncate">Code Quality Score</dt>
<dd id="qualityScore" class="flex items-baseline">
<div class="text-2xl font-semibold text-gray-900">0/100</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
</div>
<!-- Language Distribution -->
<div class="mb-8">
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Language Distribution</h3>
<div id="languageChart" class="h-64"></div>
<div id="languageList" class="mt-4 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"></div>
</div>
</div>
<!-- Repository List -->
<div class="mb-8">
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Your Repositories</h3>
<div id="repoList" class="space-y-4"></div>
</div>
</div>
<!-- Code Quality Metrics -->
<div class="mb-8">
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Code Quality Metrics</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h4 class="font-medium text-gray-700 mb-2">Maintainability</h4>
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="maintainabilityBar" class="bg-green-500 h-4 rounded-full" style="width: 0%"></div>
</div>
<p class="text-sm text-gray-500 mt-1" id="maintainabilityText">Calculating...</p>
</div>
<div>
<h4 class="font-medium text-gray-700 mb-2">Test Coverage</h4>
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="coverageBar" class="bg-blue-500 h-4 rounded-full" style="width: 0%"></div>
</div>
<p class="text-sm text-gray-500 mt-1" id="coverageText">Calculating...</p>
</div>
<div>
<h4 class="font-medium text-gray-700 mb-2">Documentation</h4>
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="docsBar" class="bg-purple-500 h-4 rounded-full" style="width: 0%"></div>
</div>
<p class="text-sm text-gray-500 mt-1" id="docsText">Calculating...</p>
</div>
<div>
<h4 class="font-medium text-gray-700 mb-2">Code Complexity</h4>
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="complexityBar" class="bg-yellow-500 h-4 rounded-full" style="width: 0%"></div>
</div>
<p class="text-sm text-gray-500 mt-1" id="complexityText">Calculating...</p>
</div>
</div>
</div>
</div>
<!-- Activity Heatmap -->
<div class="mb-8">
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Coding Activity</h3>
<div class="overflow-x-auto">
<div id="heatmap" class="heatmap mb-2"></div>
</div>
<div class="flex justify-between text-xs text-gray-500 mt-2">
<span>Less</span>
<span>More</span>
</div>
</div>
</div>
<!-- Tech Stack Analysis -->
<div class="mb-8">
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Your Tech Stack</h3>
<div id="techStack" class="flex flex-wrap gap-2">
<!-- Tech stack items will be added here -->
</div>
</div>
</div>
<!-- Milestones -->
<div class="mb-8">
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">Recommended Milestones</h3>
<div id="milestones" class="space-y-4">
<div class="border-l-4 border-indigo-500 pl-4 py-2">
<h4 class="font-medium">Improve Test Coverage</h4>
<p class="text-sm text-gray-600">Aim for at least 80% test coverage in your main projects</p>
<div class="mt-2 flex items-center text-sm">
<span class="text-indigo-600">0/3 projects improved</span>
<span class="mx-2">·</span>
<span class="text-gray-500">Due in 2 months</span>
</div>
</div>
<div class="border-l-4 border-green-500 pl-4 py-2">
<h4 class="font-medium">Learn a New Language</h4>
<p class="text-sm text-gray-600">Expand your skills by learning Rust or Go</p>
<div class="mt-2 flex items-center text-sm">
<span class="text-green-600">Not started</span>
<span class="mx-2">·</span>
<span class="text-gray-500">Due in 3 months</span>
</div>
</div>
<div class="border-l-4 border-yellow-500 pl-4 py-2">
<h4 class="font-medium">Improve Documentation</h4>
<p class="text-sm text-gray-600">Add comprehensive READMEs to all your main projects</p>
<div class="mt-2 flex items-center text-sm">
<span class="text-yellow-600">1/5 projects documented</span>
<span class="mx-2">·</span>
<span class="text-gray-500">Due in 1 month</span>
</div>
</div>
</div>
<button class="mt-4 inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Add Custom Milestone
</button>
</div>
</div>
</div>
</div>
<!-- Loading State -->
<div id="loading" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div class="bg-white rounded-lg p-8 max-w-md w-full text-center">
<div class="animate-spin rounded-full h-16 w-16 border-b-2 border-indigo-600 mx-auto mb-4"></div>
<h3 class="text-lg font-medium text-gray-900 mb-2">Analyzing Your GitHub Portfolio</h3>
<p class="text-gray-600">This may take a few moments while we analyze your repositories...</p>
</div>
</div>
<script>
// GitHub OAuth configuration
const clientId = 'YOUR_GITHUB_CLIENT_ID'; // Replace with your GitHub OAuth app client ID
const clientSecret = 'YOUR_GITHUB_CLIENT_SECRET'; // Replace with your GitHub OAuth app client secret
const redirectUri = window.location.href.split('?')[0]; // Current page URL
// DOM elements
const loginBtn = document.getElementById('loginBtn');
const heroLoginBtn = document.getElementById('heroLoginBtn');
const dashboard = document.getElementById('dashboard');
const loading = document.getElementById('loading');
// Check for OAuth callback
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
if (code) {
// We have an OAuth code, exchange it for an access token
exchangeCodeForToken(code);
}
// Set up login buttons
loginBtn.addEventListener('click', initiateGitHubLogin);
heroLoginBtn.addEventListener('click', initiateGitHubLogin);
function initiateGitHubLogin() {
// Redirect to GitHub OAuth
const githubOAuthUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=user,repo`;
window.location.href = githubOAuthUrl;
}
async function exchangeCodeForToken(code) {
showLoading();
try {
// In a real app, you would do this server-side for security
// This is just for demonstration
const response = await fetch('https://github.com/login/oauth/access_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
client_id: clientId,
client_secret: clientSecret,
code: code,
redirect_uri: redirectUri
})
});
const data = await response.json();
const accessToken = data.access_token;
if (accessToken) {
// Store token (in a real app, use secure storage)
localStorage.setItem('github_token', accessToken);
// Remove code from URL
window.history.replaceState({}, document.title, window.location.pathname);
// Load user data
await loadUserData(accessToken);
} else {
hideLoading();
alert('Failed to authenticate with GitHub');
}
} catch (error) {
hideLoading();
console.error('Error exchanging code for token:', error);
alert('An error occurred during authentication');
}
}
async function loadUserData(token) {
try {
// Get user info
const userResponse = await fetch('https://api.github.com/user', {
headers: {
'Authorization': `token ${token}`
}
});
const user = await userResponse.json();
// Get user repos
const reposResponse = await fetch('https://api.github.com/user/repos?per_page=100', {
headers: {
'Authorization': `token ${token}`
}
});
const repos = await reposResponse.json();
// Process and display data
displayUserData(user, repos);
analyzeRepositories(repos);
hideLoading();
dashboard.classList.remove('hidden');
} catch (error) {
hideLoading();
console.error('Error loading user data:', error);
alert('Failed to load GitHub data');
}
}
function displayUserData(user, repos) {
// Display basic user info
document.getElementById('username').textContent = user.login;
document.getElementById('userAvatar').src = user.avatar_url;
// Display repo count
document.getElementById('totalRepos').textContent = repos.length;
// Calculate total stars
const totalStars = repos.reduce((sum, repo) => sum + repo.stargazers_count, 0);
document.getElementById('totalStars').textContent = totalStars;
}
function analyzeRepositories(repos) {
// Analyze languages
const languageStats = analyzeLanguages(repos);
displayLanguageStats(languageStats);
// Display repositories
displayRepositories(repos);
// Generate mock quality metrics (in a real app, this would be more sophisticated)
generateQualityMetrics();
// Generate mock activity heatmap
generateActivityHeatmap();
// Generate mock tech stack
generateTechStack(languageStats);
}
function analyzeLanguages(repos) {
const languageStats = {};
let totalBytes = 0;
// Filter out repos without language data
const reposWithLanguages = repos.filter(repo => repo.language);
// Count language occurrences
reposWithLanguages.forEach(repo => {
if (!languageStats[repo.language]) {
languageStats[repo.language] = {
count: 0,
bytes: 0,
color: getLanguageColor(repo.language),
stars: 0
};
}
languageStats[repo.language].count++;
languageStats[repo.language].stars += repo.stargazers_count;
});
// Set primary language
let primaryLanguage = '';
let maxCount = 0;
for (const lang in languageStats) {
if (languageStats[lang].count > maxCount) {
maxCount = languageStats[lang].count;
primaryLanguage = lang;
}
}
document.getElementById('primaryLanguage').textContent = primaryLanguage;
return languageStats;
}
function displayLanguageStats(languageStats) {
const languageList = document.getElementById('languageList');
languageList.innerHTML = '';
// Sort languages by count
const sortedLanguages = Object.keys(languageStats).sort((a, b) => {
return languageStats[b].count - languageStats[a].count;
});
// Display top languages
sortedLanguages.slice(0, 6).forEach(lang => {
const stat = languageStats[lang];
const percentage = Math.round((stat.count / Object.keys(languageStats).length) * 100);
const langElement = document.createElement('div');
langElement.className = 'bg-gray-50 p-4 rounded-lg';
langElement.innerHTML = `
<div class="flex items-center justify-between">
<div class="flex items-center">
<span class="language-bar" style="width: 10px; height: 10px; background-color: ${stat.color || '#3182ce'};"></span>
<span class="font-medium">${lang}</span>
</div>
<span class="text-gray-600">${stat.count} repos</span>
</div>
<div class="mt-2">
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-blue-500 h-2 rounded-full" style="width: ${percentage}%"></div>
</div>
</div>
<div class="mt-2 flex justify-between text-sm text-gray-500">
<span>${percentage}% of repos</span>
<span>${stat.stars} <i class="fas fa-star text-yellow-400"></i></span>
</div>
`;
languageList.appendChild(langElement);
});
// Simple chart visualization
const chartContainer = document.getElementById('languageChart');
chartContainer.innerHTML = `
<div class="flex items-end h-48 mt-6 space-x-1">
${sortedLanguages.slice(0, 5).map(lang => {
const stat = languageStats[lang];
const height = Math.round((stat.count / languageStats[sortedLanguages[0]].count) * 100);
return `
<div class="flex flex-col items-center flex-1">
<div class="w-full bg-blue-500 rounded-t hover:bg-blue-600 transition-all" style="height: ${height}%"></div>
<div class="text-xs text-gray-500 mt-1">${lang}</div>
</div>
`;
}).join('')}
</div>
`;
}
function displayRepositories(repos) {
const repoList = document.getElementById('repoList');
repoList.innerHTML = '';
// Sort by stars
const sortedRepos = [...repos].sort((a, b) => b.stargazers_count - a.stargazers_count);
// Display top 10 repos
sortedRepos.slice(0, 10).forEach(repo => {
const repoElement = document.createElement('div');
repoElement.className = 'repo-card border border-gray-200 rounded-lg p-4 hover:shadow-md transition-all';
repoElement.innerHTML = `
<div class="flex justify-between items-start">
<div>
<h4 class="font-medium text-lg">
<a href="${repo.html_url}" target="_blank" class="text-indigo-600 hover:text-indigo-800">${repo.name}</a>
</h4>
<p class="text-gray-600 text-sm mt-1">${repo.description || 'No description provided'}</p>
</div>
<div class="flex items-center">
<span class="text-gray-500 mr-2">${repo.stargazers_count}</span>
<i class="fas fa-star text-yellow-400"></i>
</div>
</div>
<div class="repo-stats mt-3 pt-3 border-t border-gray-100">
<div class="flex flex-wrap gap-4 text-sm">
<div class="flex items-center">
<span class="language-bar" style="width: 10px; height: 10px; background-color: ${getLanguageColor(repo.language) || '#3182ce'};"></span>
<span class="ml-1 text-gray-600">${repo.language || 'Unknown'}</span>
</div>
<div class="flex items-center">
<i class="fas fa-code-branch text-gray-400 mr-1"></i>
<span class="text-gray-600">${repo.forks_count} forks</span>
</div>
<div class="flex items-center">
<i class="fas fa-eye text-gray-400 mr-1"></i>
<span class="text-gray-600">${repo.watchers_count} watchers</span>
</div>
<div class="flex items-center">
<i class="fas fa-calendar-alt text-gray-400 mr-1"></i>
<span class="text-gray-600">Updated ${formatDate(repo.updated_at)}</span>
</div>
</div>
</div>
`;
repoList.appendChild(repoElement);
});
}
function generateQualityMetrics() {
// Mock quality metrics (in a real app, this would come from analysis)
const maintainability = Math.floor(Math.random() * 40) + 60; // 60-100
const coverage = Math.floor(Math.random() * 50) + 30; // 30-80
const docs = Math.floor(Math.random() * 60) + 20; // 20-80
const complexity = Math.floor(Math.random() * 40) + 40; // 40-80
document.getElementById('maintainabilityBar').style.width = `${maintainability}%`;
document.getElementById('coverageBar').style.width = `${coverage}%`;
document.getElementById('docsBar').style.width = `${docs}%`;
document.getElementById('complexityBar').style.width = `${100 - complexity}%`;
document.getElementById('maintainabilityText').textContent =
maintainability >= 80 ? 'Excellent maintainability' :
maintainability >= 60 ? 'Good maintainability' : 'Needs improvement';
document.getElementById('coverageText').textContent =
coverage >= 70 ? 'Great test coverage' :
coverage >= 50 ? 'Moderate test coverage' : 'Low test coverage';
document.getElementById('docsText').textContent =
docs >= 70 ? 'Well documented' :
docs >= 50 ? 'Moderate documentation' : 'Needs more documentation';
document.getElementById('complexityText').textContent =
complexity <= 40 ? 'Simple and clean' :
complexity <= 60 ? 'Moderate complexity' : 'High complexity - consider refactoring';
document.getElementById('qualityScore').textContent = `${Math.round((maintainability + coverage + (100 - complexity) + docs) / 4)}/100`;
}
function generateActivityHeatmap() {
const heatmap = document.getElementById('heatmap');
heatmap.innerHTML = '';
// Generate mock activity data (52 weeks)
for (let i = 0; i < 52 * 7; i++) {
const cell = document.createElement('div');
cell.className = 'heatmap-cell';
// Random activity level (0-4)
const activity = Math.floor(Math.random() * 5);
// Set color based on activity level
const colors = ['#ebedf0', '#9be9a8', '#40c463', '#30a14e', '#216e39'];
cell.style.backgroundColor = colors[activity];
heatmap.appendChild(cell);
}
}
function generateTechStack(languageStats) {
const techStack = document.getElementById('techStack');
techStack.innerHTML = '';
// Sort languages by count
const sortedLanguages = Object.keys(languageStats).sort((a, b) => {
return languageStats[b].count - languageStats[a].count;
});
// Display top 8 languages as tech stack
sortedLanguages.slice(0, 8).forEach(lang => {
const stat = languageStats[lang];
const techItem = document.createElement('div');
techItem.className = 'flex items-center px-3 py-1 rounded-full text-sm font-medium bg-indigo-100 text-indigo-800';
techItem.innerHTML = `
<span class="language-bar" style="width: 8px; height: 8px; background-color: ${stat.color || '#3182ce'};"></span>
<span class="ml-2">${lang}</span>
`;
techStack.appendChild(techItem);
});
// Add some common technologies (mock data)
const commonTechs = ['React', 'Node.js', 'Express', 'MongoDB', 'Docker', 'Git'];
commonTechs.forEach(tech => {
const techItem = document.createElement('div');
techItem.className = 'flex items-center px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800';
techItem.innerHTML = `
<i class="fas fa-check-circle mr-2"></i>
<span>${tech}</span>
`;
techStack.appendChild(techItem);
});
}
function getLanguageColor(language) {
// Simple color mapping for common languages
const colors = {
'JavaScript': '#f1e05a',
'TypeScript': '#3178c6',
'Python': '#3572A5',
'Java': '#b07219',
'C++': '#f34b7d',
'C': '#555555',
'C#': '#178600',
'Ruby': '#701516',
'PHP': '#4F5D95',
'Go': '#00ADD8',
'Rust': '#dea584',
'Swift': '#ffac45',
'Kotlin': '#A97BFF',
'HTML': '#e34c26',
'CSS': '#563d7c',
'Shell': '#89e051',
'Dart': '#00B4AB',
'Scala': '#c22d40',
'R': '#198CE7'
};
return colors[language] || '#3182ce'; // Default to blue if unknown
}
function formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' });
}
function showLoading() {
loading.classList.remove('hidden');
}
function hideLoading() {
loading.classList.add('hidden');
}
// Check for existing token on page load
document.addEventListener('DOMContentLoaded', () => {
const token = localStorage.getItem('github_token');
if (token) {
showLoading();
loadUserData(token);
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=blackrajeev/portfolio-analyser" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>