profileShare

rasmusjy / tasteprint

Read-only snapshot

No repository description.

main default branch 169 files Expires Sep 13, 2026, 9:06 AM
JoinChallengePage.tsx 1,067 bytes
1 import { useEffect, useRef, useState } from "react";
2 import { useNavigate, useParams } from "react-router-dom";
3 import { api, ApiError, jsonBody } from "../lib/api";
4 import type { Challenge } from "../types";
5 import { ErrorState, LoadingScreen } from "../components/Ui";
6
7 export function JoinChallengePage() {
8 const { code } = useParams();
9 const navigate = useNavigate();
10 const started = useRef(false);
11 const [error, setError] = useState("");
12
13 useEffect(() => {
14 if (!code || started.current) return;
15 started.current = true;
16 api<Challenge>("/api/v1/challenges/join", { method: "POST", ...jsonBody({ joinCode: code }) })
17 .then(challenge => navigate(`/app/challenges/${challenge.id}`, { replace: true }))
18 .catch(caught => setError(caught instanceof ApiError ? caught.message : "The invitation could not be opened."));
19 }, [code, navigate]);
20
21 if (error) return <div className="standalone-state"><ErrorState message={error} /></div>;
22 return <div className="standalone-state"><LoadingScreen label="Joining the shared map" /></div>;
23 }
24