From ac9d3e1516f35201553a57fbaefe3a05c983b72b Mon Sep 17 00:00:00 2001 From: Martin <2026226+martin-mfg@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:49:02 +0100 Subject: [PATCH] various frontend fixes (#101) - fix going to step 2 after logging in We need to re-evaluate the `useEffect` function when `isAuthorized` changes. - fix Skeleton not showing in step 2 - change wakatime example user to [alan](https://wakatime.com/@alan). The data for ffflabs has only 2 categories now, mainly "other", which isn't a great example. Alan is the founder of WakaTime, so he should be a good example user. Wakatime only returns his data for the last 7 days, probably because he's not a premium wakatime user. - fix duplicate CSS class - fix spell-checker complaint --- README.md | 2 +- apps/frontend/src/axios-override.ts | 32 +- .../src/components/Card/CardImage.tsx | 2 +- .../src/components/Card/SvgInline.tsx | 6 +- apps/frontend/src/constants.ts | 2 +- .../frontend/src/mockData/wakatime_proxy.json | 540 +++++++----------- apps/frontend/src/pages/App/AppTrends.tsx | 13 +- apps/frontend/src/pages/Home/Home.tsx | 4 +- docs/advanced_documentation.md | 10 +- 9 files changed, 258 insertions(+), 353 deletions(-) diff --git a/README.md b/README.md index 1598ea93..13f33c0f 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ As more comfortable alternative, use the [GitHub-Stats-Extended Wizard](https:// - ...and development time: - [![Harlok's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=ffflabs&langs_count=6)](https://wakatime.com/@ffflabs) + [![Alan's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=alan&langs_count=6)](https://wakatime.com/@alan) - Pin more than 6 repos in your GitHub profile: diff --git a/apps/frontend/src/axios-override.ts b/apps/frontend/src/axios-override.ts index d3c904d3..96267c61 100644 --- a/apps/frontend/src/axios-override.ts +++ b/apps/frontend/src/axios-override.ts @@ -1,7 +1,13 @@ import axios, { getAdapter } from "axios"; import { setupCache } from "axios-cache-interceptor"; -import { HOST } from "./constants"; +import { + DEMO_GIST, + DEMO_REPO, + DEMO_USER, + DEMO_WAKATIME_USER, + HOST, +} from "./constants"; import additionalUserStars from "./mockData/additional_user_stars.json" with { type: "json" }; import commentedIssues from "./mockData/commented_issues.json" with { type: "json" }; import commentedPrs from "./mockData/commented_prs.json" with { type: "json" }; @@ -85,7 +91,7 @@ axios.defaults.adapter = async (config) => { params.query?.includes( "query userInfo($login: String!, $after: String, $includeMergedPullRequests:", ) && - params.variables?.login === "anuraghazra" + params.variables?.login === DEMO_USER ) { return createMockResponse(userStats, config); } @@ -95,7 +101,7 @@ axios.defaults.adapter = async (config) => { params.query?.includes( "query userInfo($login: String!, $after: String, $ownerAffiliations:", ) && - params.variables?.login === "anuraghazra" + params.variables?.login === DEMO_USER ) { return createMockResponse(additionalUserStars, config); } @@ -105,7 +111,7 @@ axios.defaults.adapter = async (config) => { params.query?.includes( "query userInfo($login: String!, $ownerAffiliations:", ) && - params.variables?.login === "anuraghazra" + params.variables?.login === DEMO_USER ) { return createMockResponse(topLanguages, config); } @@ -114,8 +120,8 @@ axios.defaults.adapter = async (config) => { config.url === "https://api.github.com/graphql" && params.query?.includes("fragment RepoInfo on Repository {") && params.variables && - params.variables.login === "anuraghazra" && - params.variables.repo === "github-readme-stats" + params.variables.login === DEMO_REPO.split("/")[0] && + params.variables.repo === DEMO_REPO.split("/")[1] ) { return createMockResponse(repository, config); } @@ -123,23 +129,23 @@ axios.defaults.adapter = async (config) => { if ( config.url === "https://api.github.com/graphql" && params.query?.includes("query gistInfo(") && - params.variables?.gistName === "bbfce31e0217a3689c8d961a356cb10d" + params.variables?.gistName === DEMO_GIST ) { return createMockResponse(gist_graphql, config); } switch (config.url) { - case "https://api.github.com/gists/bbfce31e0217a3689c8d961a356cb10d": + case `https://api.github.com/gists/${DEMO_GIST}`: return createMockResponse(gist_rest, config); - case "https://api.github.com/search/commits?per_page=1&q=author:anuraghazra": + case `https://api.github.com/search/commits?per_page=1&q=author:${DEMO_USER}`: return createMockResponse(commits, config); - case "https://api.github.com/search/issues?per_page=1&q=commenter:anuraghazra+-author:anuraghazra+type:pr": + case `https://api.github.com/search/issues?per_page=1&q=commenter:${DEMO_USER}+-author:${DEMO_USER}+type:pr`: return createMockResponse(commentedPrs, config); - case "https://api.github.com/search/issues?per_page=1&q=reviewed-by:anuraghazra+-author:anuraghazra+type:pr": + case `https://api.github.com/search/issues?per_page=1&q=reviewed-by:${DEMO_USER}+-author:${DEMO_USER}+type:pr`: return createMockResponse(reviewedPrs, config); - case "https://api.github.com/search/issues?per_page=1&q=commenter:anuraghazra+-author:anuraghazra+type:issue": + case `https://api.github.com/search/issues?per_page=1&q=commenter:${DEMO_USER}+-author:${DEMO_USER}+type:issue`: return createMockResponse(commentedIssues, config); - case `https://${HOST}/api/wakatime-proxy?username=ffflabs`: + case `https://${HOST}/api/wakatime-proxy?username=${DEMO_WAKATIME_USER}`: return createMockResponse(wakatimeProxy, config); default: return defaultAdapter(config); diff --git a/apps/frontend/src/components/Card/CardImage.tsx b/apps/frontend/src/components/Card/CardImage.tsx index ce6fca69..6a20d0ca 100644 --- a/apps/frontend/src/components/Card/CardImage.tsx +++ b/apps/frontend/src/components/Card/CardImage.tsx @@ -20,7 +20,7 @@ export const CardImage = ({ const fullImageSrc = `https://${HOST}/api${imageSrc}&client=wizard`; return ( -
+
; } // maximum dimensions of cards in SelectCard stage - return ; + return ( +
+ +
+ ); } // Render a container div for the shadow DOM diff --git a/apps/frontend/src/constants.ts b/apps/frontend/src/constants.ts index 985fefa4..67e64f86 100644 --- a/apps/frontend/src/constants.ts +++ b/apps/frontend/src/constants.ts @@ -16,7 +16,7 @@ export const GITHUB_PUBLIC_AUTH_URL = `https://github.com/login/oauth/authorize? export const DEMO_USER = "anuraghazra"; export const DEMO_REPO = "anuraghazra/github-readme-stats"; export const DEMO_GIST = "bbfce31e0217a3689c8d961a356cb10d"; -export const DEMO_WAKATIME_USER = "ffflabs"; +export const DEMO_WAKATIME_USER = "alan"; window.process = { env: { diff --git a/apps/frontend/src/mockData/wakatime_proxy.json b/apps/frontend/src/mockData/wakatime_proxy.json index 54b00be7..ad79a30e 100644 --- a/apps/frontend/src/mockData/wakatime_proxy.json +++ b/apps/frontend/src/mockData/wakatime_proxy.json @@ -1,346 +1,175 @@ { - "id": "10d3dbf0-217c-451a-b39d-7125faca6776", - "user_id": "2dd5e7c6-e792-422f-9f0e-e76985af66e2", - "range": "last_year", + "id": "6c0b00b7-f277-4454-b889-6c58c9f488c9", + "user_id": "66b6796d-eb84-4bb9-b9d2-8dc882f4c6ac", + "range": "last_7_days", "timeout": 15, "writes_only": false, - "holidays": 231, + "ai_additions": 16, + "ai_deletions": 0, + "human_additions": 0, + "human_deletions": 0, + "holidays": 2, "status": "ok", - "is_stuck": false, - "days_minus_holidays": 134, - "percent_calculated": 100, - "is_already_updating": false, - "is_up_to_date": true, - "total_seconds": 263996.570273, - "days_including_holidays": 365, - "total_seconds_including_other_language": 770251.949874, - "daily_average_including_other_language": 5748, - "daily_average": 1970, - "human_readable_total_including_other_language": "213 hrs 57 mins", - "operating_systems": [ - { - "total_seconds": 496480.13012, - "name": "Unknown OS", - "percent": 64.46, - "digital": "137:54", - "decimal": "137.90", - "text": "137 hrs 54 mins", - "hours": 137, - "minutes": 54 - }, - { - "total_seconds": 272853.07107, - "name": "Linux", - "percent": 35.42, - "digital": "75:47", - "decimal": "75.78", - "text": "75 hrs 47 mins", - "hours": 75, - "minutes": 47 - }, - { - "total_seconds": 918.748684, - "name": "Windows", - "percent": 0.12, - "digital": "0:15", - "decimal": "0.25", - "text": "15 mins", - "hours": 0, - "minutes": 15 - } - ], "categories": [ - { - "name": "Meeting", - "total_seconds": 496480.13012, - "percent": 64.46, - "digital": "137:54", - "decimal": "137.90", - "text": "137 hrs 54 mins", - "hours": 137, - "minutes": 54 - }, { "name": "Coding", - "total_seconds": 273771.819754, - "percent": 35.54, - "digital": "76:02", - "decimal": "76.03", - "text": "76 hrs 2 mins", - "hours": 76, - "minutes": 2 - } - ], - "editors": [ - { - "total_seconds": 496480.13012, - "name": "Google Calendar", - "percent": 64.46, - "digital": "137:54", - "decimal": "137.90", - "text": "137 hrs 54 mins", - "hours": 137, - "minutes": 54 + "total_seconds": 8673.080165, + "percent": 81.4, + "digital": "2:24", + "decimal": "2.40", + "text": "2 hrs 24 mins", + "hours": 2, + "minutes": 24 }, { - "total_seconds": 250778.595434, - "name": "VS Code", - "percent": 32.56, - "digital": "69:39", - "decimal": "69.65", - "text": "69 hrs 39 mins", - "hours": 69, - "minutes": 39 - }, - { - "total_seconds": 22993.22432, - "name": "DataGrip", - "percent": 2.99, - "digital": "6:23", - "decimal": "6.38", - "text": "6 hrs 23 mins", - "hours": 6, - "minutes": 23 - } - ], - "human_readable_daily_average_including_other_language": "1 hr 35 mins", - "is_up_to_date_pending_future": false, - "human_readable_total": "73 hrs 19 mins", - "languages": [ - { - "name": "Other", - "total_seconds": 506255.379601, - "percent": 65.73, - "digital": "140:37", - "decimal": "140.62", - "text": "140 hrs 37 mins", - "hours": 140, - "minutes": 37 - }, - { - "name": "TypeScript", - "total_seconds": 74336.229167, - "percent": 9.65, - "digital": "20:38", - "decimal": "20.63", - "text": "20 hrs 38 mins", - "hours": 20, - "minutes": 38 - }, - { - "name": "PHP", - "total_seconds": 41144.797498, - "percent": 5.34, - "digital": "11:25", - "decimal": "11.42", - "text": "11 hrs 25 mins", - "hours": 11, + "name": "Meeting", + "total_seconds": 1500, + "percent": 14.08, + "digital": "0:25", + "decimal": "0.42", + "text": "25 mins", + "hours": 0, "minutes": 25 }, { - "name": "Vue.js", - "total_seconds": 27060.047966, - "percent": 3.51, - "digital": "7:31", - "decimal": "7.52", - "text": "7 hrs 31 mins", - "hours": 7, - "minutes": 31 + "name": "AI Coding", + "total_seconds": 390.931491, + "percent": 3.67, + "digital": "0:06", + "decimal": "0.10", + "text": "6 mins", + "hours": 0, + "minutes": 6 }, { - "name": "JavaScript", - "total_seconds": 26924.099536, - "percent": 3.5, - "digital": "7:28", - "decimal": "7.47", - "text": "7 hrs 28 mins", - "hours": 7, - "minutes": 28 - }, - { - "name": "JSON", - "total_seconds": 26366.784244, - "percent": 3.42, - "digital": "7:19", - "decimal": "7.32", - "text": "7 hrs 19 mins", - "hours": 7, - "minutes": 19 - }, - { - "name": "SQL", - "total_seconds": 23022.426581, - "percent": 2.99, - "digital": "6:23", - "decimal": "6.38", - "text": "6 hrs 23 mins", - "hours": 6, - "minutes": 23 - }, - { - "name": "Blade Template", - "total_seconds": 15362.231057, - "percent": 1.99, - "digital": "4:16", - "decimal": "4.27", - "text": "4 hrs 16 mins", - "hours": 4, - "minutes": 16 - }, - { - "name": "Bash", - "total_seconds": 8844.393415, - "percent": 1.15, - "digital": "2:27", - "decimal": "2.45", - "text": "2 hrs 27 mins", - "hours": 2, - "minutes": 27 - }, + "name": "Writing Docs", + "total_seconds": 91, + "percent": 0.85, + "digital": "0:01", + "decimal": "0.02", + "text": "1 min", + "hours": 0, + "minutes": 1 + } + ], + "percent_calculated": 100, + "human_readable_total_including_other_language": "2 hrs 57 mins", + "human_readable_daily_average": "29 mins", + "languages": [ { "name": "HTML", - "total_seconds": 8555.093038, - "percent": 1.11, - "digital": "2:22", - "decimal": "2.37", - "text": "2 hrs 22 mins", - "hours": 2, - "minutes": 22 - }, - { - "name": "Markdown", - "total_seconds": 3799.950136, - "percent": 0.49, - "digital": "1:03", - "decimal": "1.05", - "text": "1 hr 3 mins", - "hours": 1, - "minutes": 3 - }, - { - "name": "Python", - "total_seconds": 3182.262429, - "percent": 0.41, - "digital": "0:53", - "decimal": "0.88", - "text": "53 mins", + "total_seconds": 2771, + "percent": 26.01, + "digital": "0:46", + "decimal": "0.77", + "text": "46 mins", "hours": 0, - "minutes": 53 - }, - { - "name": "SCSS", - "total_seconds": 1421.7404, - "percent": 0.18, - "digital": "0:23", - "decimal": "0.38", - "text": "23 mins", - "hours": 0, - "minutes": 23 - }, - { - "name": "TSConfig", - "total_seconds": 1184.367779, - "percent": 0.15, - "digital": "0:19", - "decimal": "0.32", - "text": "19 mins", - "hours": 0, - "minutes": 19 - }, - { - "name": "TOML", - "total_seconds": 1073.305056, - "percent": 0.14, - "digital": "0:17", - "decimal": "0.28", - "text": "17 mins", - "hours": 0, - "minutes": 17 - }, - { - "name": "Image (svg)", - "total_seconds": 1065.634724, - "percent": 0.14, - "digital": "0:17", - "decimal": "0.28", - "text": "17 mins", - "hours": 0, - "minutes": 17 - }, - { - "name": "Text", - "total_seconds": 220.856383, - "percent": 0.03, - "digital": "0:03", - "decimal": "0.05", - "text": "3 mins", - "hours": 0, - "minutes": 3 - }, - { - "name": "CSS", - "total_seconds": 205.648265, - "percent": 0.03, - "digital": "0:03", - "decimal": "0.05", - "text": "3 mins", - "hours": 0, - "minutes": 3 - }, - { - "name": "Git Config", - "total_seconds": 89.248561, - "percent": 0.01, - "digital": "0:01", - "decimal": "0.02", - "text": "1 min", - "hours": 0, - "minutes": 1 - }, - { - "name": "Makefile", - "total_seconds": 77.397983, - "percent": 0.01, - "digital": "0:01", - "decimal": "0.02", - "text": "1 min", - "hours": 0, - "minutes": 1 - }, - { - "name": "Diff", - "total_seconds": 36.762629, - "percent": 0, - "digital": "0:00", - "decimal": "0.00", - "text": "0 secs", - "hours": 0, - "minutes": 0 - }, - { - "name": "GitIgnore file", - "total_seconds": 8.992, - "percent": 0, - "digital": "0:00", - "decimal": "0.00", - "text": "0 secs", - "hours": 0, - "minutes": 0 + "minutes": 46 }, { "name": "YAML", - "total_seconds": 8.961989, - "percent": 0, - "digital": "0:00", - "decimal": "0.00", - "text": "0 secs", + "total_seconds": 2465, + "percent": 23.13, + "digital": "0:41", + "decimal": "0.68", + "text": "41 mins", "hours": 0, - "minutes": 0 + "minutes": 41 }, { - "name": "Docker", - "total_seconds": 5.339437, - "percent": 0, + "name": "Other", + "total_seconds": 1710.011656, + "percent": 16.05, + "digital": "0:28", + "decimal": "0.47", + "text": "28 mins", + "hours": 0, + "minutes": 28 + }, + { + "name": "Python", + "total_seconds": 1449, + "percent": 13.6, + "digital": "0:24", + "decimal": "0.40", + "text": "24 mins", + "hours": 0, + "minutes": 24 + }, + { + "name": "Text", + "total_seconds": 797, + "percent": 7.48, + "digital": "0:13", + "decimal": "0.22", + "text": "13 mins", + "hours": 0, + "minutes": 13 + }, + { + "name": "XML", + "total_seconds": 554, + "percent": 5.2, + "digital": "0:09", + "decimal": "0.15", + "text": "9 mins", + "hours": 0, + "minutes": 9 + }, + { + "name": "JSON", + "total_seconds": 263, + "percent": 2.47, + "digital": "0:04", + "decimal": "0.07", + "text": "4 mins", + "hours": 0, + "minutes": 4 + }, + { + "name": "Go", + "total_seconds": 232, + "percent": 2.18, + "digital": "0:03", + "decimal": "0.05", + "text": "3 mins", + "hours": 0, + "minutes": 3 + }, + { + "name": "solution", + "total_seconds": 170, + "percent": 1.6, + "digital": "0:02", + "decimal": "0.03", + "text": "2 mins", + "hours": 0, + "minutes": 2 + }, + { + "name": "Less", + "total_seconds": 95, + "percent": 0.89, + "digital": "0:01", + "decimal": "0.02", + "text": "1 min", + "hours": 0, + "minutes": 1 + }, + { + "name": "Markdown", + "total_seconds": 91, + "percent": 0.85, + "digital": "0:01", + "decimal": "0.02", + "text": "1 min", + "hours": 0, + "minutes": 1 + }, + { + "name": "C#", + "total_seconds": 58, + "percent": 0.54, "digital": "0:00", "decimal": "0.00", "text": "0 secs", @@ -348,11 +177,76 @@ "minutes": 0 } ], - "human_readable_daily_average": "32 mins", + "total_seconds_including_other_language": 10655.011656, + "human_readable_total": "2 hrs 29 mins", + "is_already_updating": false, + "human_readable_daily_average_including_other_language": "35 mins", + "is_up_to_date": true, + "operating_systems": [ + { + "total_seconds": 9155.011656, + "name": "Mac", + "percent": 85.92, + "digital": "2:32", + "decimal": "2.53", + "text": "2 hrs 32 mins", + "hours": 2, + "minutes": 32 + }, + { + "total_seconds": 1500, + "name": "Unknown OS", + "percent": 14.08, + "digital": "0:25", + "decimal": "0.42", + "text": "25 mins", + "hours": 0, + "minutes": 25 + } + ], + "is_stuck": false, + "daily_average_including_other_language": 2131, + "days_minus_holidays": 5, + "days_including_holidays": 7, + "daily_average": 1789, + "is_up_to_date_pending_future": false, + "editors": [ + { + "total_seconds": 8764.080165, + "name": "Vim", + "percent": 82.25, + "digital": "2:26", + "decimal": "2.43", + "text": "2 hrs 26 mins", + "hours": 2, + "minutes": 26 + }, + { + "total_seconds": 1500, + "name": "Google Calendar", + "percent": 14.08, + "digital": "0:25", + "decimal": "0.42", + "text": "25 mins", + "hours": 0, + "minutes": 25 + }, + { + "total_seconds": 390.931491, + "name": "Claude Code", + "percent": 3.67, + "digital": "0:06", + "decimal": "0.10", + "text": "6 mins", + "hours": 0, + "minutes": 6 + } + ], + "total_seconds": 8945, "is_cached": true, - "username": "ffflabs", + "username": "alan", "is_including_today": false, - "human_readable_range": "last year", + "human_readable_range": "last week", "is_coding_activity_visible": true, "is_language_usage_visible": true, "is_editor_usage_visible": true, diff --git a/apps/frontend/src/pages/App/AppTrends.tsx b/apps/frontend/src/pages/App/AppTrends.tsx index 51442e40..25a483b9 100644 --- a/apps/frontend/src/pages/App/AppTrends.tsx +++ b/apps/frontend/src/pages/App/AppTrends.tsx @@ -80,17 +80,18 @@ export function AppTrends() { }, [userToken]); { - /** - * This effect mus be executed only on page load, - * otherwise logged in user are unable to go back on first step + /* + * This effect must only be executed when `isAuthenticated` changes, + * otherwise logged-in user are unable to go back to step 1. */ - const hasCheckedUserAuthStatusOnLoad = useRef(false); + const prevIsAuthenticated = useRef(isAuthenticated); + useEffect(() => { - if (hasCheckedUserAuthStatusOnLoad.current) { + if (prevIsAuthenticated.current === isAuthenticated) { return; } - hasCheckedUserAuthStatusOnLoad.current = true; + prevIsAuthenticated.current = isAuthenticated; if (isAuthenticated && stage === 0) { setStage(1); diff --git a/apps/frontend/src/pages/Home/Home.tsx b/apps/frontend/src/pages/Home/Home.tsx index a471c34e..f6fcc25b 100644 --- a/apps/frontend/src/pages/Home/Home.tsx +++ b/apps/frontend/src/pages/Home/Home.tsx @@ -193,10 +193,10 @@ export function HomeScreen({ stage, setStage }: HomeScreenProps): JSX.Element { useEffect(() => { async function redirectCode() { - // After requesting Github access, Github redirects back to your app with a code parameter + // After requesting GitHub access, GitHub redirects back to your app with a code parameter const url = window.location.href; - // If Github API returns the code parameter + // If GitHub API returns the code parameter if (url.includes("code=")) { const tempPrivateAccess = url.includes("private"); const newUrl = url.split("?code=", 2) as [string, string]; diff --git a/docs/advanced_documentation.md b/docs/advanced_documentation.md index b3d1c104..325fd057 100644 --- a/docs/advanced_documentation.md +++ b/docs/advanced_documentation.md @@ -553,7 +553,7 @@ You can use the `&stats_format=bytes` option to display the stats in bytes inste Change the `?username=` value to your [WakaTime](https://wakatime.com) username. ```md -[![Harlok's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=ffflabs)](https://wakatime.com/@ffflabs) +[![Alan's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=alan)](https://wakatime.com/@alan) ``` ### Options @@ -579,13 +579,13 @@ You can customize the appearance and behavior of the WakaTime stats card using t ### Demo -![Harlok's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=ffflabs) +![Alan's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=alan) -![Harlok's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=ffflabs\&card_width=315\&hide_progress=true) +![Alan's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=alan\&card_width=315\&hide_progress=true) * Compact layout -![Harlok's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=ffflabs\&layout=compact) +![Alan's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=alan\&layout=compact) *** @@ -667,7 +667,7 @@ Choose from any of the [default themes](#themes) * WakaTime card -![Harlok's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=ffflabs) +![Alan's WakaTime stats](https://github-stats-extended.vercel.app/api/wakatime?username=alan) ***