Fix linting issues

This commit is contained in:
Ategon 2025-01-22 20:12:54 -05:00
parent 0807ce5a67
commit a2307ec34e
9 changed files with 209 additions and 181 deletions
src
app
theme-slaughter
theme-suggestions
theme-voting
components

View file

@ -1,6 +1,5 @@
import Timers from "@/components/timers"; import Timers from "@/components/timers";
import Streams from "@/components/streams"; import Streams from "@/components/streams";
import JamHeader from "@/components/jam-header";
import ThemeSlaughter from "@/components/themes/theme-slaughter"; import ThemeSlaughter from "@/components/themes/theme-slaughter";
export default async function Home() { export default async function Home() {

View file

@ -1,6 +1,5 @@
import Timers from "@/components/timers"; import Timers from "@/components/timers";
import Streams from "@/components/streams"; import Streams from "@/components/streams";
import JamHeader from "@/components/jam-header";
import ThemeSuggestions from "@/components/themes/theme-suggest"; import ThemeSuggestions from "@/components/themes/theme-suggest";
export default async function Home() { export default async function Home() {

View file

@ -1,6 +1,5 @@
import Timers from "@/components/timers"; import Timers from "@/components/timers";
import Streams from "@/components/streams"; import Streams from "@/components/streams";
import JamHeader from "@/components/jam-header";
import ThemeVoting from "@/components/themes/theme-vote"; import ThemeVoting from "@/components/themes/theme-vote";
export default async function Home() { export default async function Home() {

View file

@ -5,7 +5,8 @@ import { useEffect, useState } from "react";
import { getCurrentJam, ActiveJamResponse } from "../../helpers/jam"; import { getCurrentJam, ActiveJamResponse } from "../../helpers/jam";
export default function JamHeader() { export default function JamHeader() {
const [activeJamResponse, setActiveJamResponse] = useState<ActiveJamResponse | null>(null); const [activeJamResponse, setActiveJamResponse] =
useState<ActiveJamResponse | null>(null);
const [topTheme, setTopTheme] = useState<string | null>(null); const [topTheme, setTopTheme] = useState<string | null>(null);
// Fetch active jam details // Fetch active jam details
@ -40,15 +41,18 @@ export default function JamHeader() {
fetchData(); fetchData();
}, []); }, []);
// Helper function to get ordinal suffix // Helper function to get ordinal suffix
const getOrdinalSuffix = (day: number): string => { const getOrdinalSuffix = (day: number): string => {
if (day > 3 && day < 21) return "th"; if (day > 3 && day < 21) return "th";
switch (day % 10) { switch (day % 10) {
case 1: return "st"; case 1:
case 2: return "nd"; return "st";
case 3: return "rd"; case 2:
default: return "th"; return "nd";
case 3:
return "rd";
default:
return "th";
} }
}; };
@ -72,18 +76,33 @@ export default function JamHeader() {
<p> <p>
{activeJamResponse?.jam ? ( {activeJamResponse?.jam ? (
<> <>
{new Date(activeJamResponse.jam.startTime).toLocaleDateString('en-US', { {new Date(activeJamResponse.jam.startTime).toLocaleDateString(
month: 'long', "en-US",
})} {new Date(activeJamResponse.jam.startTime).getDate()} {
{getOrdinalSuffix(new Date(activeJamResponse.jam.startTime).getDate())} month: "long",
}
)}{" "}
{new Date(activeJamResponse.jam.startTime).getDate()}
{getOrdinalSuffix(
new Date(activeJamResponse.jam.startTime).getDate()
)}
{" - "} {" - "}
{new Date(new Date(activeJamResponse.jam.startTime).getTime() + {new Date(
(activeJamResponse.jam.jammingHours * 60 * 60 * 1000)).toLocaleDateString('en-US', { new Date(activeJamResponse.jam.startTime).getTime() +
month: 'long', activeJamResponse.jam.jammingHours * 60 * 60 * 1000
})} {new Date(new Date(activeJamResponse.jam.startTime).getTime() + ).toLocaleDateString("en-US", {
(activeJamResponse.jam.jammingHours * 60 * 60 * 1000)).getDate()} month: "long",
{getOrdinalSuffix(new Date(new Date(activeJamResponse.jam.startTime).getTime() + })}{" "}
(activeJamResponse.jam.jammingHours * 60 * 60 * 1000)).getDate())} {new Date(
new Date(activeJamResponse.jam.startTime).getTime() +
activeJamResponse.jam.jammingHours * 60 * 60 * 1000
).getDate()}
{getOrdinalSuffix(
new Date(
new Date(activeJamResponse.jam.startTime).getTime() +
activeJamResponse.jam.jammingHours * 60 * 60 * 1000
).getDate()
)}
</> </>
) : ( ) : (
"Dates TBA" "Dates TBA"
@ -96,7 +115,7 @@ export default function JamHeader() {
{activeJamResponse?.phase === "Suggestion" && ( {activeJamResponse?.phase === "Suggestion" && (
<div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x"> <div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x">
<a <a
href="/theme-suggestions" // href="/theme-suggestions"
className="text-blue-300 dark:text-blue-500 hover:underline font-semibold" className="text-blue-300 dark:text-blue-500 hover:underline font-semibold"
> >
Go to Theme Suggestion Go to Theme Suggestion
@ -107,7 +126,7 @@ export default function JamHeader() {
{activeJamResponse?.phase === "Survival" && ( {activeJamResponse?.phase === "Survival" && (
<div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x"> <div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x">
<a <a
href="/theme-slaughter" // href="/theme-slaughter"
className="text-blue-300 dark:text-blue-500 hover:underline font-semibold" className="text-blue-300 dark:text-blue-500 hover:underline font-semibold"
> >
Go to Theme Survival Go to Theme Survival
@ -118,7 +137,7 @@ export default function JamHeader() {
{activeJamResponse?.phase === "Voting" && ( {activeJamResponse?.phase === "Voting" && (
<div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x"> <div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x">
<a <a
href="/theme-voting" // href="/theme-voting"
className="text-blue-300 dark:text-blue-500 hover:underline font-semibold" className="text-blue-300 dark:text-blue-500 hover:underline font-semibold"
> >
Go to Theme Voting Go to Theme Voting
@ -139,7 +158,9 @@ export default function JamHeader() {
{activeJamResponse?.phase === "Rating" && ( {activeJamResponse?.phase === "Rating" && (
<div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x"> <div className="bg-gray-100 dark:bg-gray-800 p-4 text-center rounded-b-2x">
{topTheme ? ( {topTheme ? (
<p className="text-xl font-bold text-blue-500">THEME: {topTheme} RESULTS</p> <p className="text-xl font-bold text-blue-500">
THEME: {topTheme} RESULTS
</p>
) : ( ) : (
<p>No top-scoring theme available.</p> <p>No top-scoring theme available.</p>
)} )}

View file

@ -24,7 +24,7 @@ import NextImage from "next/image";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { getCookie, hasCookie } from "@/helpers/cookie"; import { getCookie, hasCookie } from "@/helpers/cookie";
import { getCurrentJam, joinJam, ActiveJamResponse } from "@/helpers/jam"; import { getCurrentJam, joinJam } from "@/helpers/jam";
import { JamType } from "@/types/JamType"; import { JamType } from "@/types/JamType";
import { UserType } from "@/types/UserType"; import { UserType } from "@/types/UserType";
import NavbarUser from "./PCNavbarUser"; import NavbarUser from "./PCNavbarUser";

View file

@ -1,17 +1,22 @@
"use client"; "use client";
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useCallback } from "react";
import { getCookie } from "@/helpers/cookie"; import { getCookie } from "@/helpers/cookie";
import { getCurrentJam, hasJoinedCurrentJam, ActiveJamResponse } from "@/helpers/jam"; import {
getCurrentJam,
hasJoinedCurrentJam,
ActiveJamResponse,
} from "@/helpers/jam";
export default function ThemeSlaughter() { export default function ThemeSlaughter() {
const [randomTheme, setRandomTheme] = useState(null); const [randomTheme, setRandomTheme] = useState(null);
const [votedThemes, setVotedThemes] = useState([]); const [votedThemes, setVotedThemes] = useState([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [token, setToken] = useState(null); const [token, setToken] = useState(null);
const [hasJoined, setHasJoined] = useState<boolean>(false); const [hasJoined, setHasJoined] = useState<boolean>(false);
const [activeJamResponse, setActiveJam] = useState<ActiveJamResponse | null>(null); const [activeJamResponse, setActiveJam] = useState<ActiveJamResponse | null>(
null
);
const [phaseLoading, setPhaseLoading] = useState(true); const [phaseLoading, setPhaseLoading] = useState(true);
// Fetch token on the client side // Fetch token on the client side
@ -36,16 +41,18 @@ export default function ThemeSlaughter() {
fetchCurrentJamPhase(); fetchCurrentJamPhase();
}, []); }, []);
// Fetch a random theme // Fetch a random theme
const fetchRandomTheme = async () => { const fetchRandomTheme = useCallback(async () => {
if (!token) return; // Wait until token is available if (!token) return; // Wait until token is available
if( !activeJamResponse) return; if (!activeJamResponse) return;
if(activeJamResponse && activeJamResponse.jam && activeJamResponse.phase != "Survival") if (
{ activeJamResponse &&
activeJamResponse.jam &&
activeJamResponse.phase != "Survival"
) {
return ( return (
<div> <div>
<h1>It's not Theme Survival phase.</h1> <h1>It&apos;s not Theme Survival phase.</h1>
</div> </div>
); );
} }
@ -69,10 +76,10 @@ export default function ThemeSlaughter() {
} catch (error) { } catch (error) {
console.error("Error fetching random theme:", error); console.error("Error fetching random theme:", error);
} }
}; }, [activeJamResponse, token]);
// Fetch voted themes // Fetch voted themes
const fetchVotedThemes = async () => { const fetchVotedThemes = useCallback(async () => {
if (!token) return; // Wait until token is available if (!token) return; // Wait until token is available
try { try {
@ -94,7 +101,7 @@ export default function ThemeSlaughter() {
} catch (error) { } catch (error) {
console.error("Error fetching voted themes:", error); console.error("Error fetching voted themes:", error);
} }
}; }, [token]);
// Handle voting // Handle voting
const handleVote = async (voteType) => { const handleVote = async (voteType) => {
@ -148,14 +155,12 @@ export default function ThemeSlaughter() {
} }
}; };
useEffect(() => { useEffect(() => {
if (token && activeJamResponse?.phase === "Survival") { if (token && activeJamResponse?.phase === "Survival") {
fetchRandomTheme(); fetchRandomTheme();
fetchVotedThemes(); fetchVotedThemes();
} }
}, [token, activeJamResponse]); }, [token, activeJamResponse, fetchRandomTheme, fetchVotedThemes]);
useEffect(() => { useEffect(() => {
const init = async () => { const init = async () => {
@ -198,7 +203,9 @@ export default function ThemeSlaughter() {
Not in Theme Slaughter Phase Not in Theme Slaughter Phase
</h1> </h1>
<p className="text-gray-600 dark:text-gray-400"> <p className="text-gray-600 dark:text-gray-400">
The current phase is <strong>{activeJamResponse?.phase || "Unknown"}</strong>. Please come back during the Theme Slaughter phase. The current phase is{" "}
<strong>{activeJamResponse?.phase || "Unknown"}</strong>. Please come
back during the Theme Slaughter phase.
</p> </p>
</div> </div>
); );
@ -207,12 +214,9 @@ export default function ThemeSlaughter() {
const loggedIn = getCookie("token"); const loggedIn = getCookie("token");
if (!loggedIn) { if (!loggedIn) {
return ( return <div>Sign in to be able to join the Theme Survival</div>;
<div>Sign in to be able to join the Theme Survival</div>
);
} }
return ( return (
<div className="flex h-screen"> <div className="flex h-screen">
{/* Left Side */} {/* Left Side */}
@ -247,7 +251,9 @@ export default function ThemeSlaughter() {
</div> </div>
</> </>
) : ( ) : (
<p className="text-gray-600 dark:text-gray-400">No themes available.</p> <p className="text-gray-600 dark:text-gray-400">
No themes available.
</p>
)} )}
</div> </div>

View file

@ -2,7 +2,11 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { getCookie } from "@/helpers/cookie"; import { getCookie } from "@/helpers/cookie";
import { getCurrentJam, hasJoinedCurrentJam , ActiveJamResponse } from "@/helpers/jam"; import {
getCurrentJam,
hasJoinedCurrentJam,
ActiveJamResponse,
} from "@/helpers/jam";
export default function ThemeSuggestions() { export default function ThemeSuggestions() {
const [suggestion, setSuggestion] = useState(""); const [suggestion, setSuggestion] = useState("");
@ -12,7 +16,8 @@ export default function ThemeSuggestions() {
const [userSuggestions, setUserSuggestions] = useState([]); const [userSuggestions, setUserSuggestions] = useState([]);
const [themeLimit, setThemeLimit] = useState(0); const [themeLimit, setThemeLimit] = useState(0);
const [hasJoined, setHasJoined] = useState<boolean>(false); const [hasJoined, setHasJoined] = useState<boolean>(false);
const [activeJamResponse, setActiveJamResponse] = useState<ActiveJamResponse | null>(null); const [activeJamResponse, setActiveJamResponse] =
useState<ActiveJamResponse | null>(null);
const [phaseLoading, setPhaseLoading] = useState(true); // Loading state for fetching phase const [phaseLoading, setPhaseLoading] = useState(true); // Loading state for fetching phase
// Fetch the current jam phase using helpers/jam // Fetch the current jam phase using helpers/jam
@ -105,9 +110,14 @@ export default function ThemeSuggestions() {
setSuccessMessage("Suggestion added successfully!"); setSuccessMessage("Suggestion added successfully!");
setSuggestion(""); // Clear input field setSuggestion(""); // Clear input field
fetchSuggestions(); // Refresh suggestions list fetchSuggestions(); // Refresh suggestions list
} catch (error: any) { } catch (error) {
if (error instanceof Error) {
console.error("Error submitting suggestion:", error.message); console.error("Error submitting suggestion:", error.message);
setErrorMessage(error.message || "An unexpected error occurred."); setErrorMessage(error.message || "An unexpected error occurred.");
} else {
console.error("Unknown error:", error);
setErrorMessage("An unexpected error occurred.");
}
} finally { } finally {
setLoading(false); setLoading(false);
} }
@ -176,9 +186,7 @@ export default function ThemeSuggestions() {
const token = getCookie("token"); const token = getCookie("token");
if (!token) { if (!token) {
return ( return <div>Sign in to be able to suggest themes</div>;
<div>Sign in to be able to suggest themes</div>
);
} }
// Render message if not in Suggestion phase // Render message if not in Suggestion phase
@ -189,7 +197,9 @@ export default function ThemeSuggestions() {
Not in Suggestion Phase Not in Suggestion Phase
</h1> </h1>
<p className="text-gray-600 dark:text-gray-400"> <p className="text-gray-600 dark:text-gray-400">
The current phase is <strong>{activeJamResponse?.phase || "Unknown"}</strong>. Please come back during the Suggestion phase. The current phase is{" "}
<strong>{activeJamResponse?.phase || "Unknown"}</strong>. Please come
back during the Suggestion phase.
</p> </p>
</div> </div>
); );
@ -234,7 +244,7 @@ export default function ThemeSuggestions() {
</form> </form>
) : ( ) : (
<p className="text-yellow-500 text-sm"> <p className="text-yellow-500 text-sm">
You've reached your theme suggestion limit for this jam! You&apos;ve reached your theme suggestion limit for this jam!
</p> </p>
)} )}
@ -262,7 +272,7 @@ export default function ThemeSuggestions() {
</ul> </ul>
) : ( ) : (
<p className="text-gray-600 dark:text-gray-400"> <p className="text-gray-600 dark:text-gray-400">
You haven't submitted any suggestions yet. You haven&apos;t submitted any suggestions yet.
</p> </p>
)} )}
</div> </div>

View file

@ -2,12 +2,17 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { getCookie } from "@/helpers/cookie"; import { getCookie } from "@/helpers/cookie";
import { getCurrentJam, hasJoinedCurrentJam , ActiveJamResponse } from "@/helpers/jam"; import {
getCurrentJam,
hasJoinedCurrentJam,
ActiveJamResponse,
} from "@/helpers/jam";
export default function VotingPage() { export default function VotingPage() {
const [themes, setThemes] = useState([]); const [themes, setThemes] = useState([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [activeJamResponse, setActiveJamResponse] = useState<ActiveJamResponse | null>(null); const [activeJamResponse, setActiveJamResponse] =
useState<ActiveJamResponse | null>(null);
const [hasJoined, setHasJoined] = useState<boolean>(false); const [hasJoined, setHasJoined] = useState<boolean>(false);
const [phaseLoading, setPhaseLoading] = useState(true); // Loading state for fetching phase const [phaseLoading, setPhaseLoading] = useState(true); // Loading state for fetching phase
const token = getCookie("token"); const token = getCookie("token");
@ -28,8 +33,10 @@ export default function VotingPage() {
fetchCurrentJamPhase(); fetchCurrentJamPhase();
}, []); }, []);
// Fetch themes only when phase is "Voting"
useEffect(() => {
// Fetch top N themes with voting scores // Fetch top N themes with voting scores
const fetchThemes = async () => { async function fetchThemes() {
if (!token || !activeJamResponse) return; if (!token || !activeJamResponse) return;
try { try {
@ -62,12 +69,12 @@ export default function VotingPage() {
console.log("Fetched votes:", votes); // Debug log console.log("Fetched votes:", votes); // Debug log
// Merge themes with user's votes // Merge themes with user's votes
const themesWithVotes = themes.map(theme => { const themesWithVotes = themes.map((theme) => {
const vote = votes.find(v => v.themeSuggestionId === theme.id); const vote = votes.find((v) => v.themeSuggestionId === theme.id);
console.log(`Theme ${theme.id} vote:`, vote); // Debug log console.log(`Theme ${theme.id} vote:`, vote); // Debug log
return { return {
...theme, ...theme,
votingScore: vote ? vote.votingScore : null votingScore: vote ? vote.votingScore : null,
}; };
}); });
@ -80,15 +87,12 @@ export default function VotingPage() {
} catch (error) { } catch (error) {
console.error("Error fetching themes:", error); console.error("Error fetching themes:", error);
} }
}; }
// Fetch themes only when phase is "Voting"
useEffect(() => {
if (activeJamResponse?.phase === "Voting") { if (activeJamResponse?.phase === "Voting") {
fetchThemes(); fetchThemes();
} }
}, [activeJamResponse]); }, [activeJamResponse, token]);
// Handle voting // Handle voting
const handleVote = async (themeId, votingScore) => { const handleVote = async (themeId, votingScore) => {
@ -113,9 +117,7 @@ export default function VotingPage() {
// Just update the local state instead of re-fetching all themes // Just update the local state instead of re-fetching all themes
setThemes((prevThemes) => setThemes((prevThemes) =>
prevThemes.map((theme) => prevThemes.map((theme) =>
theme.id === themeId theme.id === themeId ? { ...theme, votingScore } : theme
? { ...theme, votingScore }
: theme
) )
); );
} else { } else {
@ -138,7 +140,6 @@ export default function VotingPage() {
init(); init();
}, []); }, []);
if (phaseLoading || loading) { if (phaseLoading || loading) {
return <div>Loading...</div>; return <div>Loading...</div>;
} }
@ -162,7 +163,6 @@ export default function VotingPage() {
); );
} }
if (activeJamResponse?.phase !== "Voting") { if (activeJamResponse?.phase !== "Voting") {
return ( return (
<div className="p-4 bg-gray-100 dark:bg-gray-800 min-h-screen"> <div className="p-4 bg-gray-100 dark:bg-gray-800 min-h-screen">
@ -170,7 +170,9 @@ export default function VotingPage() {
Not in Voting Phase Not in Voting Phase
</h1> </h1>
<p className="text-gray-600 dark:text-gray-400"> <p className="text-gray-600 dark:text-gray-400">
The current phase is <strong>{activeJamResponse?.phase || "Unknown"}</strong>. Please come back during the Voting phase. The current phase is{" "}
<strong>{activeJamResponse?.phase || "Unknown"}</strong>. Please come
back during the Voting phase.
</p> </p>
</div> </div>
); );
@ -179,9 +181,7 @@ export default function VotingPage() {
const loggedIn = getCookie("token"); const loggedIn = getCookie("token");
if (!loggedIn) { if (!loggedIn) {
return ( return <div>Sign in to be able to vote</div>;
<div>Sign in to be able to vote</div>
);
} }
return ( return (
@ -233,7 +233,9 @@ export default function VotingPage() {
</div> </div>
{/* Theme Suggestion */} {/* Theme Suggestion */}
<div className="text-gray-800 dark:text-white">{theme.suggestion}</div> <div className="text-gray-800 dark:text-white">
{theme.suggestion}
</div>
</div> </div>
))} ))}
</div> </div>

View file

@ -1,15 +1,12 @@
"use client" "use client";
import { Spacer } from "@nextui-org/react"; import { Spacer } from "@nextui-org/react";
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import Timer from "./Timer"; import Timer from "./Timer";
import { getCurrentJam, ActiveJamResponse } from "@/helpers/jam"; import { getCurrentJam, ActiveJamResponse } from "@/helpers/jam";
export default function Timers() { export default function Timers() {
const [activeJamResponse, setActiveJamResponse] =
const [activeJamResponse, setActiveJamResponse] = useState<ActiveJamResponse | null>(null); useState<ActiveJamResponse | null>(null);
const [phaseLoading, setPhaseLoading] = useState(true); // Loading state for fetching phase
// Fetch the current jam phase using helpers/jam // Fetch the current jam phase using helpers/jam
useEffect(() => { useEffect(() => {
@ -20,15 +17,13 @@ export default function Timers() {
} catch (error) { } catch (error) {
console.error("Error fetching current jam:", error); console.error("Error fetching current jam:", error);
} finally { } finally {
setPhaseLoading(false); // Stop loading when phase is fetched
} }
}; };
fetchCurrentJamPhase(); fetchCurrentJamPhase();
}, []); }, []);
if(activeJamResponse && activeJamResponse.jam) if (activeJamResponse && activeJamResponse.jam) {
{
return ( return (
<div className="text-[#333] dark:text-white transition-color duration-250"> <div className="text-[#333] dark:text-white transition-color duration-250">
<Timer <Timer
@ -39,16 +34,13 @@ export default function Timers() {
<p>Site under construction</p> <p>Site under construction</p>
</div> </div>
); );
} } else {
else
{
return ( return (
<div className="text-[#333] dark:text-white transition-color duration-250"> <div className="text-[#333] dark:text-white transition-color duration-250">
No upcoming jams No upcoming jams
<Spacer y={8} /> <Spacer y={8} />
<p>Site under construction</p> <p>Site under construction</p>
</div> </div>
) );
} }
} }