From 1780d378d4dc88dafc7f98455b583288ee8bc556 Mon Sep 17 00:00:00 2001 From: sajeetharan Date: Sun, 16 Aug 2026 23:36:51 +0530 Subject: [PATCH] fix: preserve developer state across navigation --- app/page.jsx | 19 ++++++++++++++----- components/DetailPanel.jsx | 3 ++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/page.jsx b/app/page.jsx index 2a3075b..372e582 100644 --- a/app/page.jsx +++ b/app/page.jsx @@ -20,13 +20,14 @@ import dynamic from 'next/dynamic'; const Globe = dynamic(() => import('../components/Globe.jsx'), { ssr: false }); const PENDING_CLAIM_KEY = 'devglobe-pending-claim'; +let cachedDeveloperDataset = null; export default function Home() { - const [developers, setDevelopers] = useState([]); + const [developers, setDevelopers] = useState(() => cachedDeveloperDataset?.developers || []); const [datasetCount, setDatasetCount] = useState(null); - const [filtered, setFiltered] = useState([]); + const [filtered, setFiltered] = useState(() => cachedDeveloperDataset?.developers || []); const [selectedDev, setSelectedDev] = useState(null); - const [loading, setLoading] = useState(true); + const [loading, setLoading] = useState(() => !cachedDeveloperDataset); const [error, setError] = useState(null); const [flyTarget, setFlyTarget] = useState(null); const [selectedCountry, setSelectedCountry] = useState(''); @@ -34,7 +35,7 @@ export default function Home() { const [theme, setTheme] = useState('dark'); const [user, setUser] = useState(null); const [claimStatus, setClaimStatus] = useState('unclaimed'); // 'unclaimed' | 'pending' | 'claimed' | 'no_match' - const [claimedLogins, setClaimedLogins] = useState(new Set()); + const [claimedLogins, setClaimedLogins] = useState(() => new Set(cachedDeveloperDataset?.claimedLogins || [])); const [sidebarOpen, setSidebarOpen] = useState(false); const [sidebarView, setSidebarView] = useState('leaderboard'); const [cardRequest, setCardRequest] = useState(0); @@ -135,12 +136,17 @@ export default function Home() { setFiltered(scored); const claimed = new Set(raw.filter(d => d.claimed).map(d => d.login)); setClaimedLogins(claimed); + cachedDeveloperDataset = { developers: scored, claimedLogins: claimed }; claimedDeveloper = scored.find(developer => developer.login === user.login); } } else if (claimedDeveloper) { claimedDeveloper = { ...claimedDeveloper, claimed: true }; - setDevelopers(current => current.map(developer => developer.login === user.login ? claimedDeveloper : developer)); + const updatedDevelopers = developers.map(developer => developer.login === user.login ? claimedDeveloper : developer); + const updatedClaimedLogins = new Set(cachedDeveloperDataset?.claimedLogins || []); + updatedClaimedLogins.add(user.login); + setDevelopers(updatedDevelopers); setFiltered(current => current.map(developer => developer.login === user.login ? claimedDeveloper : developer)); + cachedDeveloperDataset = { developers: updatedDevelopers, claimedLogins: updatedClaimedLogins }; } claimedDeveloper ||= { @@ -200,6 +206,8 @@ export default function Home() { }, []); useEffect(() => { + if (cachedDeveloperDataset) return; + async function loadData() { try { fetch('/api/developers/count', { signal: AbortSignal.timeout(10000) }) @@ -218,6 +226,7 @@ export default function Home() { // Build set of all claimed logins from data const claimed = new Set(raw.filter(d => d.claimed).map(d => d.login)); setClaimedLogins(claimed); + cachedDeveloperDataset = { developers: scored, claimedLogins: claimed }; setLoading(false); } catch (err) { setError(err.message); diff --git a/components/DetailPanel.jsx b/components/DetailPanel.jsx index f936fec..66556f2 100644 --- a/components/DetailPanel.jsx +++ b/components/DetailPanel.jsx @@ -1,6 +1,7 @@ 'use client'; import React, { useEffect, useRef, useState } from 'react'; +import Link from 'next/link'; import { track } from '@vercel/analytics'; import * as d3 from 'd3'; import { formatNum, formatRelativeTime, isStaleData } from '../lib/format.js'; @@ -192,7 +193,7 @@ export default function DetailPanel({ dev, onClose, onCardGenerated, claimedLogi {merged.soUserId && ( StackOverflow ↗ )} - Impact History + Impact History Get Badge ↗