rotation selector

This commit is contained in:
Kalle (Sendou)
2020-12-16 11:24:52 +02:00
parent f05e4542b2
commit e10a8a425a
9 changed files with 287 additions and 12 deletions

View File

@@ -1,17 +1,27 @@
import { Select, Tag, TagCloseButton, TagLabel } from "@chakra-ui/react";
import { t } from "@lingui/macro";
import { useLingui } from "@lingui/react";
import { weaponsWithHero } from "lib/lists/weaponsWithHero";
import { salmonRunWeapons, weaponsWithHero } from "lib/lists/weaponsWithHero";
import WeaponImage from "./WeaponImage";
interface Props {
name: string;
name?: string;
value: string[];
onChange: (value: string[]) => void;
isSalmonRun?: boolean;
}
const MultiWeaponSelector: React.FC<Props> = ({ name, value, onChange }) => {
const MultiWeaponSelector: React.FC<Props> = ({
name,
value,
onChange,
isSalmonRun,
}) => {
const { i18n } = useLingui();
const weaponsArray: readonly string[] = isSalmonRun
? salmonRunWeapons
: weaponsWithHero;
return (
<>
<Select
@@ -26,7 +36,13 @@ const MultiWeaponSelector: React.FC<Props> = ({ name, value, onChange }) => {
<option hidden value="">
{t`Select weapon`}
</option>
{weaponsWithHero.map((wpn) => (
{isSalmonRun && (
<>
<option value="RANDOM">{t`Random`}</option>
<option value="RANDOM_GRIZZCO">{t`Random (Grizzco)`}</option>
</>
)}
{weaponsArray.map((wpn) => (
<option key={wpn} value={wpn}>
{i18n._(wpn)}
</option>

View File

@@ -0,0 +1,48 @@
import {
Button,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
} from "@chakra-ui/react";
import { Trans } from "@lingui/macro";
import { useState } from "react";
import RotationSelector from "./RotationSelector";
interface Props {
onClose: () => void;
}
const AddRecordModal: React.FC<Props> = ({ onClose }) => {
const [sending, setSending] = useState(false);
return (
<Modal isOpen onClose={onClose} size="xl" closeOnOverlayClick={false}>
<ModalOverlay>
<ModalContent>
<ModalHeader>
<Trans>Adding a new Salmon Run result</Trans>
</ModalHeader>
<ModalCloseButton borderRadius="50%" />
<form /*onSubmit={handleSubmit(onSubmit)}*/>
<ModalBody pb={6}>
<RotationSelector />
</ModalBody>
<ModalFooter>
<Button mr={3} /*type="submit"*/ isLoading={sending}>
<Trans>Save</Trans>
</Button>
<Button onClick={onClose} variant="outline">
<Trans>Cancel</Trans>
</Button>
</ModalFooter>
</form>
</ModalContent>
</ModalOverlay>
</Modal>
);
};
export default AddRecordModal;

View File

@@ -0,0 +1,128 @@
import { Box, Button, FormLabel, Select } from "@chakra-ui/react";
import { t, Trans } from "@lingui/macro";
import { useLingui } from "@lingui/react";
import MultiWeaponSelector from "components/common/MultiWeaponSelector";
import SubText from "components/common/SubText";
import WeaponImage from "components/common/WeaponImage";
import { salmonRunStages } from "lib/lists/stages";
import { useMyTheme } from "lib/useMyTheme";
import { GetAllSalmonRunRotationsData } from "prisma/queries/getAllSalmonRunRotations";
import { useState } from "react";
import useSWR from "swr";
const randomToNaturalName = {
RANDOM: t`Random`,
RANDOM_GRIZZCO: t`Random (Grizzco)`,
} as const;
interface Props {}
const RotationSelector: React.FC<Props> = ({}) => {
const { gray } = useMyTheme();
const { i18n } = useLingui();
const { data } = useSWR<GetAllSalmonRunRotationsData>("/api/sr/rotations");
const [stage, setStage] = useState("Spawning Grounds");
const [weapons, setWeapons] = useState<string[]>([]);
const [idSelected, setIdSelected] = useState<number | null>(null);
const filteredRotations = getFilteredRotations();
if (idSelected && data) {
const rotation = data.find((rotation) => rotation.id === idSelected)!;
return (
<Box>
<SubText>
<Trans>Selected rotation</Trans>
</SubText>
<Box my={2} fontWeight="bold">
#{rotation.id}
</Box>
<Box my={2} color={gray}>
{new Date(rotation.startTime).toLocaleDateString()}
</Box>
{rotation.weapons.map((wpn, i) => (
<Box as="span" mx={1} key={i}>
<WeaponImage name={wpn} size={32} />
</Box>
))}
<Box my={2}>
<Button
size="sm"
variant="outline"
onClick={() => setIdSelected(null)}
>
<Trans>Change selection</Trans>
</Button>
</Box>
</Box>
);
}
return (
<>
<FormLabel htmlFor="stage">
<Trans>Stage</Trans>
</FormLabel>
<Select
name="stage"
value={stage}
onChange={(e) => setStage(e.target.value)}
>
{salmonRunStages.map((stage) => (
<option key={stage} value={stage}>
{i18n._(stage)}
</option>
))}
</Select>
<Box mt={4}>
<FormLabel htmlFor="weapons">
<Trans>Weapons</Trans>
</FormLabel>
<MultiWeaponSelector
name="weapons"
value={weapons}
onChange={setWeapons}
isSalmonRun
/>
</Box>
{filteredRotations && (
<Box mt={4}>
<FormLabel htmlFor="rotation">
<Trans>Rotation</Trans>
</FormLabel>
<Select
name="rotation"
onChange={(e) => setIdSelected(parseInt(e.target.value))}
>
{filteredRotations.map((rotation) => (
<option key={rotation.id} value={rotation.id}>
{new Date(rotation.startTime).toLocaleDateString()} -{" "}
{rotation.weapons
.map((wpn) =>
wpn === "RANDOM" || wpn === "RANDOM_GRIZZCO"
? randomToNaturalName[wpn]
: wpn
)
.join(", ")}
</option>
))}
</Select>
</Box>
)}
</>
);
function getFilteredRotations() {
if (!data) return null;
if (!stage || weapons.length < 1) return null;
return data.filter((rotation) => {
return (
rotation.stage === stage &&
weapons.every((wpn) => rotation.weapons.includes(wpn))
);
});
}
};
export default RotationSelector;

View File

@@ -142,6 +142,59 @@ export const weaponsWithHero = [
"Kensa Undercover Brella",
] as const;
export const salmonRunWeapons = [
"Sploosh-o-matic",
"Splattershot Jr.",
"Splash-o-matic",
"Aerospray MG",
"Splattershot",
".52 Gal",
"N-ZAP '85",
"Splattershot Pro",
".96 Gal",
"Jet Squelcher",
"L-3 Nozzlenose",
"H-3 Nozzlenose",
"Squeezer",
"Luna Blaster",
"Blaster",
"Range Blaster",
"Rapid Blaster",
"Rapid Blaster Pro",
"Clash Blaster",
"Carbon Roller",
"Splat Roller",
"Dynamo Roller",
"Flingza Roller",
"Inkbrush",
"Octobrush",
"Classic Squiffer",
"Splat Charger",
"Splatterscope",
"E-liter 4K",
"E-liter 4K Scope",
"Bamboozler 14 Mk I",
"Goo Tuber",
"Slosher",
"Tri-Slosher",
"Sloshing Machine",
"Bloblobber",
"Explosher",
"Mini Splatling",
"Heavy Splatling",
"Hydra Splatling",
"Ballpoint Splatling",
"Nautilus 47",
"Dapple Dualies",
"Splat Dualies",
"Glooga Dualies",
"Dualie Squelchers",
"Dark Tetra Dualies",
"Splat Brella",
"Tenta Brella",
"Undercover Brella",
] as const;
export const weaponsWithHeroCategorized: readonly {
name: string;
weapons: readonly string[];

View File

@@ -1,18 +1,12 @@
import { NextApiRequest, NextApiResponse } from "next";
import prisma from "prisma/client";
import { getAllSalmonRunRotations } from "prisma/queries/getAllSalmonRunRotations";
const rotationsHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method !== "GET") {
return res.status(405).end();
}
const rotations = await prisma.salmonRunRotation.findMany({
where: { startTime: { lt: new Date() } },
orderBy: { id: "desc" },
select: { id: true, startTime: true, weapons: true, stage: true },
});
res.status(200).json(rotations);
res.status(200).json(await getAllSalmonRunRotations());
};
export default rotationsHandler;

23
pages/sr/leaderboards.tsx Normal file
View File

@@ -0,0 +1,23 @@
import { Button } from "@chakra-ui/react";
import { t, Trans } from "@lingui/macro";
import Breadcrumbs from "components/common/Breadcrumbs";
import AddRecordModal from "components/sr/AddRecordModal";
import { useState } from "react";
const SalmonRunLeaderboardsPage = ({}) => {
const [showModal, setShowModal] = useState(true);
return (
<>
{showModal && <AddRecordModal onClose={() => setShowModal(false)} />}
<Breadcrumbs
pages={[{ name: t`Salmon Run` }, { name: t`Leaderboards` }]}
/>
<Button variant="outline" onClick={() => setShowModal(true)}>
<Trans>Submit result</Trans>
</Button>
</>
);
};
export default SalmonRunLeaderboardsPage;

View File

@@ -0,0 +1,13 @@
import { Prisma } from "@prisma/client";
import prisma from "prisma/client";
export type GetAllSalmonRunRotationsData = Prisma.PromiseReturnType<
typeof getAllSalmonRunRotations
>;
export const getAllSalmonRunRotations = async () =>
prisma.salmonRunRotation.findMany({
where: { startTime: { lt: new Date() } },
orderBy: { id: "desc" },
select: { id: true, startTime: true, weapons: true, stage: true },
});

BIN
public/weapons/RANDOM.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB