1
0
Fork 0

feat(eod): update difficulty selection in EOD components and bump version to 0.2.0

This commit is contained in:
Jason Fraley 2026-08-26 23:55:03 -04:00
parent 7a34c3901e
commit d740d43800
4 changed files with 16 additions and 5 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "polaris-task-force", "name": "polaris-task-force",
"version": "0.1.6", "version": "0.2.0",
"description": "Web app for the Arma 3 unit Polaris Task Force. Uses Next.js for client- and server-side rendering, with a Postgres database and some other neat libraries.", "description": "Web app for the Arma 3 unit Polaris Task Force. Uses Next.js for client- and server-side rendering, with a Postgres database and some other neat libraries.",
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",

View file

@ -1,7 +1,7 @@
"use client"; "use client";
import { useCallback, useState } from "react"; import { useCallback, useState } from "react";
import type { EodStats } from "@/app/(frontend)/eod/actions"; import type { EodDifficulty, EodStats } from "@/app/(frontend)/eod/actions";
import { useRealtimePresence } from "@/hooks/useRealtimePresence"; import { useRealtimePresence } from "@/hooks/useRealtimePresence";
import { EodLeaderboard } from "./EodLeaderboard"; import { EodLeaderboard } from "./EodLeaderboard";
import { MinesweeperBoard } from "./MinesweeperBoard"; import { MinesweeperBoard } from "./MinesweeperBoard";
@ -15,6 +15,7 @@ export function EodArena({
}) { }) {
const [refreshKey, setRefreshKey] = useState(0); const [refreshKey, setRefreshKey] = useState(0);
const [playing, setPlaying] = useState(false); const [playing, setPlaying] = useState(false);
const [selectedDifficulty, setSelectedDifficulty] = useState<EodDifficulty>("training");
const activeTeams = useRealtimePresence("eod", playing, true); const activeTeams = useRealtimePresence("eod", playing, true);
const onPhaseChange = useCallback((phase: "ready" | "playing" | "over") => { const onPhaseChange = useCallback((phase: "ready" | "playing" | "over") => {
setPlaying(phase === "playing"); setPlaying(phase === "playing");
@ -26,11 +27,14 @@ export function EodArena({
initialStats={initialStats} initialStats={initialStats}
onGameRecorded={() => setRefreshKey((key) => key + 1)} onGameRecorded={() => setRefreshKey((key) => key + 1)}
onPhaseChange={onPhaseChange} onPhaseChange={onPhaseChange}
onDifficultyChange={setSelectedDifficulty}
/> />
<EodLeaderboard <EodLeaderboard
refreshKey={refreshKey} refreshKey={refreshKey}
currentUserId={currentUserId} currentUserId={currentUserId}
activeTeams={activeTeams} activeTeams={activeTeams}
difficulty={selectedDifficulty}
onDifficultyChange={setSelectedDifficulty}
/> />
</div> </div>
); );

View file

@ -10,6 +10,7 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import type { EodDifficulty } from "@/app/(frontend)/eod/actions";
import type { PresenceParticipant } from "@/hooks/useRealtimePresence"; import type { PresenceParticipant } from "@/hooks/useRealtimePresence";
interface ApiUser { interface ApiUser {
@ -58,6 +59,8 @@ interface EodLeaderboardProps {
refreshKey?: number; refreshKey?: number;
currentUserId?: number | string; currentUserId?: number | string;
activeTeams?: PresenceParticipant[]; activeTeams?: PresenceParticipant[];
difficulty: EodDifficulty;
onDifficultyChange: (difficulty: EodDifficulty) => void;
} }
function rankClass(index: number) { function rankClass(index: number) {
@ -71,8 +74,9 @@ export function EodLeaderboard({
refreshKey = 0, refreshKey = 0,
currentUserId, currentUserId,
activeTeams = [], activeTeams = [],
difficulty,
onDifficultyChange,
}: EodLeaderboardProps) { }: EodLeaderboardProps) {
const [difficulty, setDifficulty] = useState<"training" | "perimeter" | "supplyRoad">("training");
const [rows, setRows] = useState<LeaderboardRow[] | null>(null); const [rows, setRows] = useState<LeaderboardRow[] | null>(null);
const [failed, setFailed] = useState(false); const [failed, setFailed] = useState(false);
@ -146,7 +150,7 @@ export function EodLeaderboard({
<div className="ml-auto flex items-center gap-2 text-xs text-muted-foreground"> <div className="ml-auto flex items-center gap-2 text-xs text-muted-foreground">
<Select <Select
value={difficulty} value={difficulty}
onValueChange={(value) => setDifficulty(value as typeof difficulty)} onValueChange={(value) => onDifficultyChange(value as EodDifficulty)}
> >
<SelectTrigger aria-label="Leaderboard sector" className="h-8 w-[150px] text-xs"> <SelectTrigger aria-label="Leaderboard sector" className="h-8 w-[150px] text-xs">
<SelectValue /> <SelectValue />

View file

@ -174,10 +174,12 @@ export function MinesweeperBoard({
initialStats: serverStats, initialStats: serverStats,
onGameRecorded, onGameRecorded,
onPhaseChange, onPhaseChange,
onDifficultyChange,
}: { }: {
initialStats: EodStats; initialStats: EodStats;
onGameRecorded: () => void; onGameRecorded: () => void;
onPhaseChange: (phase: Phase) => void; onPhaseChange: (phase: Phase) => void;
onDifficultyChange: (difficulty: EodDifficulty) => void;
}) { }) {
const router = useRouter(); const router = useRouter();
const [difficulty, setDifficulty] = useState<GameMode>("training"); const [difficulty, setDifficulty] = useState<GameMode>("training");
@ -240,13 +242,14 @@ export function MinesweeperBoard({
if (submittingRef.current) return; if (submittingRef.current) return;
const nextConfig = nextDifficulty === "custom" ? customConfig : DIFFICULTIES[nextDifficulty]; const nextConfig = nextDifficulty === "custom" ? customConfig : DIFFICULTIES[nextDifficulty];
setDifficulty(nextDifficulty); setDifficulty(nextDifficulty);
if (nextDifficulty !== "custom") onDifficultyChange(nextDifficulty);
setBoard(emptyBoard(nextConfig.rows * nextConfig.cols)); setBoard(emptyBoard(nextConfig.rows * nextConfig.cols));
generatedRef.current = false; generatedRef.current = false;
setSeconds(0); setSeconds(0);
setLastRun(null); setLastRun(null);
setPhaseSafe("ready"); setPhaseSafe("ready");
}, },
[customConfig, difficulty, setPhaseSafe], [customConfig, difficulty, onDifficultyChange, setPhaseSafe],
); );
useEffect(() => { useEffect(() => {