Skip to content

Commit f9cc750

Browse files
committed
upgrade progress bar
1 parent 5a525ab commit f9cc750

7 files changed

Lines changed: 109 additions & 44 deletions

File tree

client/src/components/ui/progress.tsx

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,49 @@
11
import Image from "next/image";
2-
import * as React from "react";
2+
import { useEffect, useRef, useState } from "react";
3+
4+
import { getPageConfigByName } from "../../config/pages";
35

46
export default function ProgressBar({ pageName }: { pageName: string }) {
5-
const [progressWidth, setProgressWidth] = React.useState(0);
6-
let progress = 0;
7-
let titleName = "";
7+
const [progressWidth, setProgressWidth] = useState(0);
8+
const [isAnimating, setIsAnimating] = useState(false);
9+
const previousPageRef = useRef<string>("");
10+
const previousProgressRef = useRef<number>(0);
11+
const isFirstRenderRef = useRef<boolean>(true);
812

9-
switch (pageName) {
10-
case "schedule":
11-
progress = 0;
12-
titleName = "Drone Competition Schedule";
13-
break;
14-
case "format-rules":
15-
progress = 30;
16-
titleName = "Format & Rules";
17-
break;
18-
case "guests-sponsors":
19-
titleName = "Guests & Sponsors";
20-
progress = 60;
21-
break;
22-
case "leaderboard":
23-
titleName = "Leaderboard";
24-
progress = 80;
25-
break;
26-
}
13+
const pageConfig = getPageConfigByName(pageName);
14+
const progress = pageConfig?.progress || 0;
15+
const titleName = pageConfig?.title || "";
2716

28-
React.useEffect(() => {
17+
useEffect(() => {
2918
const updateProgress = () => {
19+
let targetProgress = progress;
20+
3021
if (pageName === "leaderboard") {
31-
setProgressWidth(window.innerWidth >= 768 ? 90 : 80);
22+
targetProgress = window.innerWidth >= 768 ? 90 : 80;
23+
}
24+
25+
if (isFirstRenderRef.current) {
26+
setProgressWidth(0);
27+
setIsAnimating(true);
28+
setTimeout(() => {
29+
setProgressWidth(targetProgress);
30+
previousProgressRef.current = targetProgress;
31+
previousPageRef.current = pageName;
32+
isFirstRenderRef.current = false;
33+
}, 10);
34+
} else if (previousPageRef.current !== pageName) {
35+
setIsAnimating(false);
36+
setProgressWidth(previousProgressRef.current);
37+
38+
setTimeout(() => {
39+
setIsAnimating(true);
40+
setProgressWidth(targetProgress);
41+
previousProgressRef.current = targetProgress;
42+
previousPageRef.current = pageName;
43+
}, 10);
3244
} else {
33-
setProgressWidth(progress);
45+
setProgressWidth(targetProgress);
46+
previousProgressRef.current = targetProgress;
3447
}
3548
};
3649

@@ -39,20 +52,30 @@ export default function ProgressBar({ pageName }: { pageName: string }) {
3952
return () => window.removeEventListener("resize", updateProgress);
4053
}, [pageName, progress]);
4154

55+
useEffect(() => {
56+
if (isAnimating) {
57+
const timer = setTimeout(() => {
58+
setIsAnimating(false);
59+
}, 3000);
60+
61+
return () => clearTimeout(timer);
62+
}
63+
}, [isAnimating]);
64+
4265
return (
4366
<div>
4467
<div className="w-full flex-col justify-center">
4568
<div className="mb-4 flex items-center justify-center">
46-
<a className="title-large text-center text-[30px] text-dark md:text-[50px] lg:text-[60px]">
69+
<h1 className="title-large text-center text-[30px] text-dark md:text-[50px] lg:text-[60px]">
4770
{titleName}
48-
</a>
71+
</h1>
4972
</div>
5073
<div className="flex flex-1 items-center">
5174
<div
5275
className="flex-shrink-0"
5376
style={{
5477
width: `${progressWidth}%`,
55-
transition: "width 3s ease-in-out",
78+
transition: isAnimating ? "width 3s ease-in-out" : "none",
5679
}}
5780
/>
5881
<div className="flex-shrink-0">

client/src/config/pages.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
export interface PageConfig {
2+
path: string;
3+
name: string;
4+
title: string;
5+
progress: number;
6+
}
7+
8+
export const PAGES_CONFIG: PageConfig[] = [
9+
{
10+
path: "/schedule",
11+
name: "schedule",
12+
title: "Drone Competition Schedule",
13+
progress: 0,
14+
},
15+
{
16+
path: "/format-rules",
17+
name: "format-rules",
18+
title: "Format & Rules",
19+
progress: 30,
20+
},
21+
{
22+
path: "/guests-sponsors",
23+
name: "guests-sponsors",
24+
title: "Guests & Sponsors",
25+
progress: 60,
26+
},
27+
{
28+
path: "/leaderboard",
29+
name: "leaderboard",
30+
title: "Leaderboard",
31+
progress: 80,
32+
},
33+
];
34+
35+
export const getPageConfigByPath = (path: string): PageConfig | null => {
36+
return PAGES_CONFIG.find((page) => page.path === path) || null;
37+
};
38+
39+
export const getPageConfigByName = (name: string): PageConfig | null => {
40+
return PAGES_CONFIG.find((page) => page.name === name) || null;
41+
};
42+
43+
export const getPageName = (path: string): string | null => {
44+
const config = getPageConfigByPath(path);
45+
return config ? config.name : null;
46+
};

client/src/pages/_app.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
44
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
55
import type { AppProps } from "next/app";
66
import { Montserrat, Plus_Jakarta_Sans, Work_Sans } from "next/font/google";
7+
import { useRouter } from "next/router";
78

89
import Footer from "../components/ui/footer";
910
import Navbar from "../components/ui/navbar";
11+
import ProgressBar from "../components/ui/progress";
12+
import { getPageName } from "../config/pages";
1013

1114
const fontMontserrat = Montserrat({
1215
subsets: ["latin"],
@@ -26,6 +29,10 @@ const fontWorkSans = Work_Sans({
2629
const queryClient = new QueryClient();
2730

2831
export default function App({ Component, pageProps }: AppProps) {
32+
const router = useRouter();
33+
34+
const currentPageName = getPageName(router.pathname);
35+
2936
return (
3037
<div
3138
className={`${fontMontserrat.variable} ${fontPlusJakartaSans.variable} ${fontWorkSans.variable}`}
@@ -35,6 +42,11 @@ export default function App({ Component, pageProps }: AppProps) {
3542
<Navbar />
3643
<div className="w-full">
3744
<main className="mx-auto flex min-h-screen max-w-7xl flex-col items-center gap-4 p-24">
45+
{currentPageName && (
46+
<div className="mt-4 w-full justify-center">
47+
<ProgressBar pageName={currentPageName} />
48+
</div>
49+
)}
3850
<Component {...pageProps} />
3951
</main>
4052
</div>

client/src/pages/format-rules.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useState } from "react";
33
import { usePings } from "@/hooks/pings";
44

55
import { Button } from "../components/ui/button";
6-
import ProgressBar from "../components/ui/progress";
76

87
export default function Home() {
98
const [clicked, setClicked] = useState(false);
@@ -13,9 +12,6 @@ export default function Home() {
1312

1413
return (
1514
<>
16-
<div className="mt-4 w-full justify-center">
17-
<ProgressBar pageName="format-rules" />
18-
</div>
1915
<Button onClick={() => setClicked(true)}>
2016
{isLoading ? "Loading" : "Ping"}
2117
</Button>

client/src/pages/guests-sponsors.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useState } from "react";
33
import { usePings } from "@/hooks/pings";
44

55
import { Button } from "../components/ui/button";
6-
import ProgressBar from "../components/ui/progress";
76

87
export default function Home() {
98
const [clicked, setClicked] = useState(false);
@@ -13,9 +12,6 @@ export default function Home() {
1312

1413
return (
1514
<>
16-
<div className="mt-4 w-full justify-center">
17-
<ProgressBar pageName="guests-sponsors" />
18-
</div>
1915
<Button onClick={() => setClicked(true)}>
2016
{isLoading ? "Loading" : "Ping"}
2117
</Button>

client/src/pages/leaderboard.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useState } from "react";
33
import { usePings } from "@/hooks/pings";
44

55
import { Button } from "../components/ui/button";
6-
import ProgressBar from "../components/ui/progress";
76

87
export default function Home() {
98
const [clicked, setClicked] = useState(false);
@@ -13,9 +12,6 @@ export default function Home() {
1312

1413
return (
1514
<>
16-
<div className="mt-4 w-full justify-center">
17-
<ProgressBar pageName="leaderboard" />
18-
</div>
1915
<Button onClick={() => setClicked(true)}>
2016
{isLoading ? "Loading" : "Ping"}
2117
</Button>

client/src/pages/schedule.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useState } from "react";
33
import { usePings } from "@/hooks/pings";
44

55
import { Button } from "../components/ui/button";
6-
import ProgressBar from "../components/ui/progress";
76

87
export default function Home() {
98
const [clicked, setClicked] = useState(false);
@@ -13,9 +12,6 @@ export default function Home() {
1312

1413
return (
1514
<>
16-
<div className="mt-4 w-full justify-center">
17-
<ProgressBar pageName="schedule" />
18-
</div>
1915
<Button onClick={() => setClicked(true)}>
2016
{isLoading ? "Loading" : "Ping"}
2117
</Button>

0 commit comments

Comments
 (0)