|
1 | 1 |
|
| 2 | + |
| 3 | + |
| 4 | +// app.js |
| 5 | +// Expose refresh functions globally so other scripts can call them |
| 6 | + |
| 7 | +// Hackatime refresh |
| 8 | +window.refreshHackatime = async function(username, apiKey) { |
| 9 | + const BASE_V1 = 'https://hackatime.hackclub.com/api/v1'; |
| 10 | + const BASE_HACKATIME_V1 = 'https://hackatime.hackclub.com/api/hackatime/v1'; |
| 11 | + |
| 12 | + const summaryEl = document.getElementById('hackatimeSummary'); |
| 13 | + const table = document.getElementById('hackatimeTable'); |
| 14 | + const tbody = table ? table.querySelector('tbody') : null; |
| 15 | + const projectsWrap = document.getElementById('hackatimeProjects'); |
| 16 | + const projectsList = document.getElementById('hackatimeProjectsList'); |
| 17 | + |
| 18 | + if (!summaryEl) return; |
| 19 | + |
| 20 | + summaryEl.textContent = 'Loading Hackatime…'; |
| 21 | + if (tbody) tbody.innerHTML = ''; |
| 22 | + if (table) table.style.display = 'none'; |
| 23 | + if (projectsList) projectsList.innerHTML = ''; |
| 24 | + if (projectsWrap) projectsWrap.style.display = 'none'; |
| 25 | + |
| 26 | + try { |
| 27 | + // Today’s status |
| 28 | + const todayRes = await fetch(`${BASE_HACKATIME_V1}/users/current/statusbar/today?api_key=${encodeURIComponent(apiKey)}`); |
| 29 | + const todayJson = await todayRes.json(); |
| 30 | + const todayText = todayJson?.data?.grand_total?.text || ''; |
| 31 | + summaryEl.textContent = todayText ? `Today: ${todayText}` : 'No coding today'; |
| 32 | + |
| 33 | + // Stats |
| 34 | + const statsRes = await fetch(`${BASE_V1}/users/${encodeURIComponent(username)}/stats?api_key=${encodeURIComponent(apiKey)}`); |
| 35 | + const statsJson = await statsRes.json(); |
| 36 | + const totalSeconds = statsJson?.total_seconds || 0; |
| 37 | + const totalHours = (totalSeconds / 3600).toFixed(2); |
| 38 | + summaryEl.textContent += ` • Total: ${totalHours} hrs`; |
| 39 | + |
| 40 | + // Languages |
| 41 | + if (Array.isArray(statsJson?.languages) && tbody) { |
| 42 | + tbody.innerHTML = ''; |
| 43 | + statsJson.languages.slice(0, 10).forEach(lang => { |
| 44 | + const tr = document.createElement('tr'); |
| 45 | + tr.innerHTML = `<td>${lang.name}</td><td>${lang.text}</td>`; |
| 46 | + tbody.appendChild(tr); |
| 47 | + }); |
| 48 | + table.style.display = 'table'; |
| 49 | + } |
| 50 | + |
| 51 | + // Projects |
| 52 | + if (Array.isArray(statsJson?.projects) && projectsList) { |
| 53 | + projectsList.innerHTML = ''; |
| 54 | + statsJson.projects.slice(0, 10).forEach(p => { |
| 55 | + const li = document.createElement('li'); |
| 56 | + li.textContent = `${p.name} — ${p.text}`; |
| 57 | + projectsList.appendChild(li); |
| 58 | + }); |
| 59 | + projectsWrap.style.display = 'block'; |
| 60 | + } |
| 61 | + } catch (err) { |
| 62 | + console.error('Hackatime fetch error', err); |
| 63 | + summaryEl.textContent = 'Error loading Hackatime'; |
| 64 | + } |
| 65 | +}; |
| 66 | + |
| 67 | +// GitHub refresh |
| 68 | +window.refreshGithub = async function(username) { |
| 69 | + const githubSummary = document.getElementById('githubSummary'); |
| 70 | + const githubRepos = document.getElementById('githubRepos'); |
| 71 | + |
| 72 | + if (!githubSummary || !githubRepos) return; |
| 73 | + |
| 74 | + githubSummary.textContent = 'Loading GitHub…'; |
| 75 | + githubRepos.innerHTML = ''; |
| 76 | + |
| 77 | + try { |
| 78 | + const profileRes = await fetch(`https://api.github.com/users/${encodeURIComponent(username)}`); |
| 79 | + const profile = await profileRes.json(); |
| 80 | + githubSummary.textContent = `${profile.login} • ${profile.public_repos} repos • ${profile.followers} followers`; |
| 81 | + |
| 82 | + const reposRes = await fetch(`https://api.github.com/users/${encodeURIComponent(username)}/repos?per_page=100`); |
| 83 | + const repos = await reposRes.json(); |
| 84 | + repos.sort((a, b) => b.stargazers_count - a.stargazers_count); |
| 85 | + |
| 86 | + repos.slice(0, 8).forEach(r => { |
| 87 | + const li = document.createElement('li'); |
| 88 | + li.innerHTML = `<a href="${r.html_url}" target="_blank">${r.name} (${r.stargazers_count}★)</a>`; |
| 89 | + githubRepos.appendChild(li); |
| 90 | + }); |
| 91 | + } catch (err) { |
| 92 | + console.error('GitHub fetch error', err); |
| 93 | + githubSummary.textContent = 'Error loading GitHub'; |
| 94 | + } |
| 95 | +}; |
| 96 | + |
| 97 | +// Startup: load saved settings once DOM is ready |
| 98 | +document.addEventListener('DOMContentLoaded', () => { |
| 99 | + const settings = JSON.parse(localStorage.getItem('settings')) || {}; |
| 100 | + if (settings.hackatimeUsername && settings.hackatimeKey) { |
| 101 | + window.refreshHackatime(settings.hackatimeUsername, settings.hackatimeKey); |
| 102 | + } |
| 103 | + if (settings.githubUsername) { |
| 104 | + window.refreshGithub(settings.githubUsername); |
| 105 | + } |
| 106 | +}); |
| 107 | + |
| 108 | + |
2 | 109 | document.addEventListener('DOMContentLoaded', () => { |
3 | 110 |
|
4 | 111 |
|
|
0 commit comments