Add multiplayer rooms and Vercel analytics
This commit is contained in:
@@ -3,13 +3,16 @@ import { useI18n } from "@/components/I18nProvider";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ArrowRight, Timer, ZoomIn } from "lucide-react";
|
||||
import { ArrowRight, Timer, ZoomIn, Users } from "lucide-react";
|
||||
import { difficulties, type Difficulty } from "@/shared/protocol";
|
||||
import { api } from "@/lib/client-api";
|
||||
export { api } from "@/lib/client-api";
|
||||
export function StartGame({ datasetId }: { datasetId: string }) {
|
||||
const { t } = useI18n();
|
||||
const [difficulty, setDifficulty] = useState<Difficulty>("normal"),
|
||||
[mode, setMode] = useState<"solo" | "multiplayer">("solo"),
|
||||
[displayName, setDisplayName] = useState(""),
|
||||
[playerLimit, setPlayerLimit] = useState(4),
|
||||
[loading, setLoading] = useState(false),
|
||||
[error, setError] = useState("");
|
||||
const router = useRouter();
|
||||
@@ -17,11 +20,15 @@ export function StartGame({ datasetId }: { datasetId: string }) {
|
||||
setLoading(true);
|
||||
setError("");
|
||||
try {
|
||||
const session = await api<{ id: string }>("sessions", {
|
||||
datasetId,
|
||||
difficulty,
|
||||
});
|
||||
router.push("/play/" + session.id);
|
||||
const session = await api<{ id: string }>(
|
||||
mode === "solo" ? "sessions" : "rooms",
|
||||
{
|
||||
datasetId,
|
||||
difficulty,
|
||||
...(mode === "multiplayer" ? { displayName, playerLimit } : {}),
|
||||
},
|
||||
);
|
||||
router.push((mode === "solo" ? "/play/" : "/multiplayer/") + session.id);
|
||||
} catch (e) {
|
||||
setError((e as Error).message);
|
||||
setLoading(false);
|
||||
@@ -31,6 +38,24 @@ export function StartGame({ datasetId }: { datasetId: string }) {
|
||||
<div className="start-panel">
|
||||
<span className="eyebrow">{t("YOUR EXPEDITION")}</span>
|
||||
<h2>{t("Choose your challenge.")}</h2>
|
||||
<div className="tabs" aria-label={t("Game mode")}>
|
||||
<button
|
||||
aria-pressed={mode === "solo"}
|
||||
className={mode === "solo" ? "active" : ""}
|
||||
disabled={loading}
|
||||
onClick={() => setMode("solo")}
|
||||
>
|
||||
{t("Solo")}
|
||||
</button>
|
||||
<button
|
||||
aria-pressed={mode === "multiplayer"}
|
||||
className={mode === "multiplayer" ? "active" : ""}
|
||||
disabled={loading}
|
||||
onClick={() => setMode("multiplayer")}
|
||||
>
|
||||
<Users size={15} /> {t("Multiplayer")}
|
||||
</button>
|
||||
</div>
|
||||
<div className="difficulty-options">
|
||||
{Object.entries(difficulties).map(([key, value]) => (
|
||||
<button
|
||||
@@ -55,12 +80,53 @@ export function StartGame({ datasetId }: { datasetId: string }) {
|
||||
<p className="muted">
|
||||
{t("5 rounds · 25,000 possible points · No movement")}
|
||||
</p>
|
||||
{mode === "multiplayer" && (
|
||||
<div className="multiplayer-settings">
|
||||
<label htmlFor="room-display-name">{t("Your player name")}</label>
|
||||
<input
|
||||
id="room-display-name"
|
||||
value={displayName}
|
||||
onChange={(event) => setDisplayName(event.target.value)}
|
||||
minLength={2}
|
||||
maxLength={32}
|
||||
placeholder={t("Enter a player name")}
|
||||
autoComplete="nickname"
|
||||
disabled={loading}
|
||||
/>
|
||||
<label htmlFor="room-player-limit">
|
||||
{t("Player limit (including you)")}
|
||||
</label>
|
||||
<select
|
||||
id="room-player-limit"
|
||||
value={playerLimit}
|
||||
onChange={(event) => setPlayerLimit(Number(event.target.value))}
|
||||
disabled={loading}
|
||||
>
|
||||
{Array.from({ length: 15 }, (_, i) => i + 2).map((count) => (
|
||||
<option key={count} value={count}>
|
||||
{count}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<p className="muted">
|
||||
{t(
|
||||
"Create a room, share the invite link, and start when your friends arrive.",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
className="button primary full"
|
||||
onClick={start}
|
||||
disabled={loading}
|
||||
disabled={
|
||||
loading || (mode === "multiplayer" && displayName.trim().length < 2)
|
||||
}
|
||||
>
|
||||
{loading ? t("Preparing your world…") : t("Start exploring")}
|
||||
{loading
|
||||
? t("Preparing your world…")
|
||||
: mode === "multiplayer"
|
||||
? t("Create multiplayer room")
|
||||
: t("Start exploring")}
|
||||
<ArrowRight size={17} />
|
||||
</button>
|
||||
{error && (
|
||||
|
||||
Reference in New Issue
Block a user