Improve MineGeo interface and functionality
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
"use client";
|
||||
import { useI18n } from "@/components/I18nProvider";
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
@@ -38,6 +40,7 @@ export type SessionView = {
|
||||
}[];
|
||||
};
|
||||
export function Game({ id }: { id: string }) {
|
||||
const { t, formatNumber } = useI18n();
|
||||
const router = useRouter(),
|
||||
[session, setSession] = useState<SessionView | null>(null),
|
||||
[pin, setPin] = useState<Pin | null>(null),
|
||||
@@ -207,28 +210,28 @@ export function Game({ id }: { id: string }) {
|
||||
)}
|
||||
<div className="game-info">
|
||||
<div>
|
||||
<small>ROUND</small>
|
||||
<small>{t("ROUND")}</small>
|
||||
<strong>{session ? session.round + 1 : "—"} / 5</strong>
|
||||
</div>
|
||||
<div>
|
||||
<small>TIME LEFT</small>
|
||||
<small>{t("TIME LEFT")}</small>
|
||||
<strong className={remaining <= 10 ? "urgent" : ""}>
|
||||
{Math.floor(remaining / 60)}:
|
||||
{String(remaining % 60).padStart(2, "0")}
|
||||
</strong>
|
||||
</div>
|
||||
<div>
|
||||
<small>POINTS</small>
|
||||
<strong>{total.toLocaleString()}</strong>
|
||||
<small>{t("POINTS")}</small>
|
||||
<strong>{formatNumber(total)}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{session && (
|
||||
<div className={"game-map " + (expanded ? "expanded" : "")}>
|
||||
<div className="map-topline">
|
||||
<span>↑ N · PLACE YOUR GUESS</span>
|
||||
<span>{t("↑ N · PLACE YOUR GUESS")}</span>
|
||||
<button
|
||||
aria-label={expanded ? "Collapse map" : "Expand map"}
|
||||
aria-label={expanded ? t("Collapse map") : t("Expand map")}
|
||||
onClick={() => setExpanded((v) => !v)}
|
||||
>
|
||||
{expanded ? <Minimize2 size={15} /> : <Maximize2 size={15} />}
|
||||
@@ -249,7 +252,7 @@ export function Game({ id }: { id: string }) {
|
||||
<small>
|
||||
{pin
|
||||
? `X ${Math.round(pin.x)} · Z ${Math.round(pin.z)}`
|
||||
: "Click the map to drop a pin"}
|
||||
: t("Click the map to drop a pin")}
|
||||
</small>
|
||||
<button
|
||||
className="button primary full"
|
||||
@@ -257,64 +260,69 @@ export function Game({ id }: { id: string }) {
|
||||
onClick={() => guess()}
|
||||
>
|
||||
<MapPin size={15} />
|
||||
{busy ? "Checking your guess…" : "Submit guess"}
|
||||
{busy ? t("Checking your guess…") : t("Submit guess")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="look-help">
|
||||
<span>
|
||||
<Move size={12} /> DRAG TO LOOK AROUND
|
||||
<Move size={12} /> {t("DRAG TO LOOK AROUND")}
|
||||
</span>
|
||||
<span>
|
||||
<MousePointer2 size={12} />{" "}
|
||||
{session?.difficulty === "hard" ? "NO ZOOM" : "SCROLL TO ZOOM"}
|
||||
{session?.difficulty === "hard" ? t("NO ZOOM") : t("SCROLL TO ZOOM")}
|
||||
</span>
|
||||
</div>
|
||||
{(!session || !loaded.panorama || !loaded.map) && !error && (
|
||||
<div className="game-loading">
|
||||
<div className="loading-cube" />
|
||||
<h2>Preparing your expedition.</h2>
|
||||
<p>Loading panorama and surface map…</p>
|
||||
<h2>{t("Preparing your expedition.")}</h2>
|
||||
<p>{t("Loading panorama and surface map…")}</p>
|
||||
</div>
|
||||
)}
|
||||
{error && (
|
||||
<div className="round-result" role="alert">
|
||||
<h2>Connection interrupted.</h2>
|
||||
<p>{error}</p>
|
||||
<h2>{t("Connection interrupted.")}</h2>
|
||||
<p>{t(error)}</p>
|
||||
<button
|
||||
className="button primary"
|
||||
onClick={() => window.location.reload()}
|
||||
>
|
||||
Reconnect
|
||||
{t("Reconnect")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{result && !error && (
|
||||
<div className="round-result">
|
||||
<span className="eyebrow">
|
||||
ROUND {(session?.round || 0) + 1} COMPLETE
|
||||
{t("ROUND")} {(session?.round || 0) + 1} {t("COMPLETE")}
|
||||
</span>
|
||||
<h2>
|
||||
{result.timedOut
|
||||
? "Time slipped away."
|
||||
? t("Time slipped away.")
|
||||
: result.score === 5000
|
||||
? "Right on the block!"
|
||||
? t("Right on the block!")
|
||||
: result.score > 3000
|
||||
? "You know your way around."
|
||||
: "A little off the beaten block."}
|
||||
? t("You know your way around.")
|
||||
: t("A little off the beaten block.")}
|
||||
</h2>
|
||||
<div className="score">
|
||||
{result.score.toLocaleString()}
|
||||
{formatNumber(result.score)}
|
||||
<small> / 5,000</small>
|
||||
</div>
|
||||
<p>
|
||||
{result.timedOut
|
||||
? "The clock ran out. This round scores zero."
|
||||
: `${Math.round(result.distance || 0).toLocaleString()} blocks from the actual location.`}
|
||||
? t("The clock ran out. This round scores zero.")
|
||||
: t("{count} blocks from the actual location.", {
|
||||
count: formatNumber(Math.round(result.distance || 0)),
|
||||
})}
|
||||
</p>
|
||||
<button className="button primary full" onClick={next}>
|
||||
{session?.round === 4 ? "See expedition results" : "Next round"} →
|
||||
{session?.round === 4
|
||||
? t("See expedition results")
|
||||
: t("Next round")}{" "}
|
||||
→
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user