123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- import ms from "pretty-ms";
- import { useCallback, useState } from "react";
- import { createGame } from "../../../domain/apiMethods";
- import {
- COUNTRY_RACE,
- DISTANCE,
- HARD,
- FROZEN,
- NORMAL,
- RACE,
- RANDOM_STREET_VIEW,
- TIME_BANK,
- URBAN,
- NIGHTMARE,
- RAMP,
- RAMP_HARD,
- } from "../../../domain/constants";
- import useCountryLookup from "../../../hooks/useCountryLookup";
- import Loading from "../Loading";
- import { CountryDropdown, Dropdown, DropdownGroup, Item } from "./Dropdown";
- import ErrorModal from "./ErrorModal";
- import styles from "./GameCreationForm.module.css";
- const DEFAULTS = {
- timer: 300,
- rounds: 5,
- countryLock: null,
- generationMethod: RANDOM_STREET_VIEW,
- gameMode: NORMAL,
- clockMode: NORMAL,
- scoreMethod: DISTANCE,
- roundPointCap: null,
- };
- const PRESETS = {
- URBAN_AMERICA: {
- ...DEFAULTS,
- generationMethod: URBAN,
- countryLock: "us",
- },
- URBAN_GLOBAL: {
- ...DEFAULTS,
- generationMethod: URBAN,
- },
- FAST_FROZEN: {
- ...DEFAULTS,
- timer: 30,
- rounds: 3,
- generationMethod: RANDOM_STREET_VIEW,
- gameMode: FROZEN,
- },
- COUNTRY_RACE: {
- ...DEFAULTS,
- scoreMethod: COUNTRY_RACE,
- },
- FROZEN_COUNTRY_RACE: {
- ...DEFAULTS,
- timer: 30,
- gameMode: FROZEN,
- scoreMethod: COUNTRY_RACE,
- },
- BOOTLEG_GG_DUEL: {
- ...DEFAULTS,
- clockMode: RACE,
- scoreMethod: RAMP,
- },
- };
- export const LastSettingsButton = ({ onClick }) => (
- <div
- className={styles.reusebutton}
- role="button"
- tabIndex="0"
- onClick={onClick}
- onKeyDown={({ key }) => {
- if (key === "Enter") {
- onClick();
- }
- }}
- title="Reuse Previous Game Settings"
- >
- <span aria-label="recycle" role="img">
- ♻️
- </span>
- </div>
- );
- const GameCreationForm = ({ afterCreate, lastSettings = null }) => {
- const [loading, setLoading] = useState(false);
- const [creationError, setCreationError] = useState(false);
- const [timer, setTimer] = useState(DEFAULTS.timer);
- const [rounds, setRounds] = useState(DEFAULTS.rounds);
- const [countryLock, setCountryLock] = useState(DEFAULTS.countryLock);
- const [generationMethod, setGenMethod] = useState(DEFAULTS.generationMethod);
- const [gameMode, setGameMode] = useState(DEFAULTS.gameMode);
- const [clockMode, setClockMode] = useState(DEFAULTS.clockMode);
- const [scoreMethod, setScoreMethod] = useState(DEFAULTS.scoreMethod);
- const [roundPointCap, setRoundPointCap] = useState(DEFAULTS.roundPointCap);
- const countryLookup = useCountryLookup(generationMethod);
- const [presetOpen, setPresetOpen] = useState(false);
- const setPreset = useCallback(
- ({
- timer: newTimer,
- rounds: newRounds,
- countryLock: newCountryLock,
- generationMethod: newGenMethod,
- gameMode: newGameMode,
- clockMode: newClockMode,
- scoreMethod: newScoreMethod,
- roundPointCap: newRoundPointCap,
- }) => {
- setTimer(newTimer);
- setRounds(newRounds);
- setCountryLock(newCountryLock);
- setGenMethod(newGenMethod);
- setGameMode(newGameMode);
- setClockMode(newClockMode);
- setScoreMethod(newScoreMethod);
- setRoundPointCap(newRoundPointCap);
- },
- []
- );
- if (loading || countryLookup === null) {
- return <Loading />;
- }
- const onCreateGame = async () => {
- setLoading(true);
- let gameId;
- try {
- gameId = await createGame(
- timer,
- rounds,
- countryLock,
- generationMethod,
- gameMode,
- clockMode,
- scoreMethod,
- roundPointCap
- );
- } catch (e) {
- setCreationError(true);
- setLoading(false);
- return;
- }
- if (afterCreate) {
- afterCreate(gameId);
- }
- };
- return (
- <div className={styles.form}>
- <ErrorModal
- open={creationError}
- onClose={() => setCreationError(false)}
- />
- <div className={styles.buttoncontainer}>
- <Dropdown
- buttonClass={styles.favbutton}
- selected={DEFAULTS}
- onClick={() => setPresetOpen(o => !o)}
- onSelect={v => {
- setPresetOpen(false);
- setPreset(v);
- }}
- open={presetOpen}
- >
- <Item value={DEFAULTS} display="⭐">
- Default
- </Item>
- <Item value={PRESETS.URBAN_AMERICA} display="⭐">
- Urban America
- </Item>
- <Item value={PRESETS.URBAN_GLOBAL} display="⭐">
- Urban Global
- </Item>
- <Item value={PRESETS.FAST_FROZEN} display="⭐">
- Fast Frozen
- </Item>
- <Item value={PRESETS.COUNTRY_RACE} display="⭐">
- Country Race
- </Item>
- <Item value={PRESETS.FROZEN_COUNTRY_RACE} display="⭐">
- Frozen Country Race
- </Item>
- <Item value={PRESETS.BOOTLEG_GG_DUEL} display="⭐">
- Legally Distinct from Geoguessr Duels
- </Item>
- </Dropdown>
- {lastSettings && (
- <LastSettingsButton onClick={() => setPreset(lastSettings)} />
- )}
- <button className={styles.start} onClick={onCreateGame} type="button">
- New Game
- </button>
- </div>
- <div className={styles.dropdowns}>
- <DropdownGroup>
- <Dropdown selected={timer} onSelect={setTimer} open="timer">
- <Item value={30} display={ms(30 * 1000)}>
- 30 Seconds
- </Item>
- <Item value={120} display={ms(2 * 60 * 1000)}>
- 2 Minutes
- </Item>
- <Item value={300} display={ms(5 * 60 * 1000)}>
- 5 Minutes
- </Item>
- <Item value={3600} display={ms(60 * 60 * 1000)}>
- 1 Hour
- </Item>
- </Dropdown>
- <Dropdown selected={rounds} onSelect={setRounds} open="rounds">
- <Item value={1}>1 Round</Item>
- <Item value={3}>3 Rounds</Item>
- <Item value={5}>5 Rounds</Item>
- <Item value={10}>10 Rounds</Item>
- </Dropdown>
- <Dropdown
- selected={generationMethod}
- onSelect={setGenMethod}
- open="gen"
- >
- <Item value={RANDOM_STREET_VIEW} display="🎲">
- Random Street View
- </Item>
- <Item value={URBAN} display="🏙️">
- Urban Centers
- </Item>
- </Dropdown>
- <CountryDropdown
- countryLookup={countryLookup}
- selected={countryLock}
- onSelect={setCountryLock}
- open="country"
- />
- <Dropdown selected={gameMode} onSelect={setGameMode} open="gameMode">
- <Item value={NORMAL} display="📍">
- Normal
- </Item>
- <Item value={FROZEN} display="❄️">
- Frozen
- </Item>
- </Dropdown>
- <Dropdown
- selected={clockMode}
- onSelect={setClockMode}
- open="clockMode"
- >
- <Item value={NORMAL} display="⏰">
- Standard
- </Item>
- <Item value={TIME_BANK} display="🏦">
- Time Bank
- </Item>
- <Item value={RACE} display="⚔️">
- Duel
- </Item>
- </Dropdown>
- <Dropdown
- selected={scoreMethod}
- onSelect={setScoreMethod}
- open="scoreMethod"
- >
- <Item value={DISTANCE} display="📏">
- Distance
- </Item>
- <Item value={RAMP} display="📈">
- Ramping
- </Item>
- <Item value={COUNTRY_RACE} display="🗾">
- Country Race
- </Item>
- <Item value={HARD} display="😬">
- Hard Mode
- </Item>
- <Item value={RAMP_HARD} display="🧀">
- Ramping Hard Mode
- </Item>
- <Item value={NIGHTMARE} display="💀">
- Nightmare Mode
- </Item>
- </Dropdown>
- <Dropdown
- selected={roundPointCap}
- onSelect={setRoundPointCap}
- open="roundPointCap"
- >
- <Item value={null} display="♾️">
- No Limit
- </Item>
- <Item value={10000} display="10k">
- 10k Total Points per Round
- </Item>
- <Item value={20000} display="20k">
- 20k Total Points per Round
- </Item>
- </Dropdown>
- </DropdownGroup>
- </div>
- </div>
- );
- };
- export default GameCreationForm;
|