diff --git a/src/components/PersonalRecords.tsx b/src/components/PersonalRecords.tsx index 8a70e8d..f21e675 100644 --- a/src/components/PersonalRecords.tsx +++ b/src/components/PersonalRecords.tsx @@ -2,37 +2,31 @@ import { useCallback, useEffect, useState } from "react"; import { useAccount } from "@/components/AccountContext"; - interface StreakData { current: number; longest: number; lastCommitDate: string | null; totalActiveDays: number; } - interface ContributionData { days: number; total: number; data: Record; } - interface Repo { name: string; commits: number; url: string; } - function getBestDay(data: Record): { count: number; dateLabel: string | null } { let maxCount = 0; let bestDateStr: string | null = null; - for (const [dateStr, count] of Object.entries(data)) { if (count > maxCount) { maxCount = count; bestDateStr = dateStr; } } - let dateLabel: string | null = null; if (bestDateStr) { const parts = bestDateStr.split("-").map(Number); @@ -48,35 +42,29 @@ function getBestDay(data: Record): { count: number; dateLabel: s dateLabel = bestDateStr; } } - return { count: maxCount, dateLabel }; } - function getBestWeek(data: Record): { count: number; weekLabel: string | null } { const weeks: Record = {}; - for (const [dateStr, count] of Object.entries(data)) { const parts = dateStr.split("-").map(Number); if (parts.length === 3) { const d = new Date(Date.UTC(parts[0], parts[1] - 1, parts[2])); - const day = d.getUTCDay(); // 0 is Sunday, 1 is Monday - const diff = d.getUTCDate() - day + (day === 0 ? -6 : 1); // Monday week start + const day = d.getUTCDay(); + const diff = d.getUTCDate() - day + (day === 0 ? -6 : 1); const weekStart = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), diff)); const weekStr = weekStart.toISOString().slice(0, 10); weeks[weekStr] = (weeks[weekStr] ?? 0) + count; } } - let maxCount = 0; let bestWeekStr: string | null = null; - for (const [weekStr, count] of Object.entries(weeks)) { if (count > maxCount) { maxCount = count; bestWeekStr = weekStr; } } - let weekLabel: string | null = null; if (bestWeekStr) { const parts = bestWeekStr.split("-").map(Number); @@ -92,28 +80,22 @@ function getBestWeek(data: Record): { count: number; weekLabel: weekLabel = bestWeekStr; } } - return { count: maxCount, weekLabel }; } - function getBestMonth(data: Record): { count: number; monthLabel: string | null } { const months: Record = {}; - for (const [dateStr, count] of Object.entries(data)) { - const monthKey = dateStr.slice(0, 7); // YYYY-MM + const monthKey = dateStr.slice(0, 7); months[monthKey] = (months[monthKey] ?? 0) + count; } - let maxCount = 0; let bestMonthKey: string | null = null; - for (const [mKey, count] of Object.entries(months)) { if (count > maxCount) { maxCount = count; bestMonthKey = mKey; } } - let monthLabel: string | null = null; if (bestMonthKey) { const parts = bestMonthKey.split("-").map(Number); @@ -128,24 +110,19 @@ function getBestMonth(data: Record): { count: number; monthLabel monthLabel = bestMonthKey; } } - return { count: maxCount, monthLabel }; } - -function getBusiestRepo(repos: Repo[]): { count: number; repoLabel: string | null } { +function getBusiestRepo(repos: Repo[]): { count: number; repoLabel: string | null; repoUrl: string | null } { if (!repos || repos.length === 0) { - return { count: 0, repoLabel: null }; + return { count: 0, repoLabel: null, repoUrl: null }; } - const best = repos[0]; if (!best) { - return { count: 0, repoLabel: null }; + return { count: 0, repoLabel: null, repoUrl: null }; } - const shortName = best.name.split("/")[1] ?? best.name; - return { count: best.commits, repoLabel: shortName }; + return { count: best.commits, repoLabel: shortName, repoUrl: best.url ?? null }; } - export default function PersonalRecords() { const { selectedAccount } = useAccount(); const [streak, setStreak] = useState(null); @@ -153,36 +130,29 @@ export default function PersonalRecords() { const [repos, setRepos] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const fetchRecords = useCallback(async () => { setLoading(true); setError(null); - try { const paramStreak = selectedAccount !== null ? `?accountId=${encodeURIComponent(selectedAccount)}` : ""; - const paramContrib = selectedAccount !== null ? `&accountId=${encodeURIComponent(selectedAccount)}` : ""; - const [streakRes, contribRes, reposRes] = await Promise.all([ fetch(`/api/metrics/streak${paramStreak}`), fetch(`/api/metrics/contributions?days=365${paramContrib}`), fetch(`/api/metrics/repos?days=365${paramContrib}`), ]); - if (!streakRes.ok || !contribRes.ok || !reposRes.ok) { throw new Error("Failed to fetch personal records data"); } - const streakData = (await streakRes.json()) as StreakData; const contribData = (await contribRes.json()) as ContributionData; const reposData = (await reposRes.json()) as { repos: Repo[] }; - setStreak(streakData); setContributions(contribData); setRepos(reposData.repos ?? []); @@ -192,16 +162,13 @@ export default function PersonalRecords() { setLoading(false); } }, [selectedAccount]); - useEffect(() => { fetchRecords(); }, [fetchRecords, selectedAccount]); - const bestDay = getBestDay(contributions?.data ?? {}); const bestWeek = getBestWeek(contributions?.data ?? {}); const bestMonth = getBestMonth(contributions?.data ?? {}); const busiestRepo = getBusiestRepo(repos); - const records = [ { label: "Longest Streak", @@ -210,6 +177,7 @@ export default function PersonalRecords() { subtext: "All time", icon: "🏆", isRepo: false, + repoUrl: null, }, { label: "Best Day", @@ -218,6 +186,7 @@ export default function PersonalRecords() { subtext: bestDay.dateLabel ?? "—", icon: "⚡", isRepo: false, + repoUrl: null, }, { label: "Best Week", @@ -226,6 +195,7 @@ export default function PersonalRecords() { subtext: bestWeek.weekLabel ?? "—", icon: "🔥", isRepo: false, + repoUrl: null, }, { label: "Most Active Month", @@ -234,6 +204,7 @@ export default function PersonalRecords() { subtext: bestMonth.monthLabel ?? "—", icon: "📅", isRepo: false, + repoUrl: null, }, { label: "Busiest Repo", @@ -242,9 +213,9 @@ export default function PersonalRecords() { subtext: busiestRepo.repoLabel ?? "—", icon: "⭐", isRepo: true, + repoUrl: busiestRepo.repoUrl ?? null, }, ]; - return (

@@ -299,7 +270,34 @@ export default function PersonalRecords() { }`} title={rec.subtext} > - {rec.subtext} + {rec.isRepo && rec.repoUrl ? ( + + {rec.subtext} + + + + + + + ) : ( + rec.subtext + )}

))} @@ -307,4 +305,4 @@ export default function PersonalRecords() { )} ); -} +} \ No newline at end of file