Improve MineGeo interface and functionality

This commit is contained in:
2026-10-06 19:24:41 +05:00
parent 7404f1dc1c
commit 233e4d57f0
67 changed files with 3053 additions and 643 deletions

View File

@@ -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>
)}