form ready for submitting sr records

This commit is contained in:
Kalle (Sendou) 2020-12-19 13:32:55 +02:00
parent 6341361e3f
commit 2cb22fb5d8
3 changed files with 117 additions and 62 deletions

View File

@ -1,2 +1,7 @@
export const ADMIN_DISCORD_ID = "79237403620945920"; export const ADMIN_DISCORD_ID = "79237403620945920";
export const GANBA_DISCORD_ID = "312082701865713665"; export const GANBA_DISCORD_ID = "312082701865713665";
export const SALMON_RUN_ADMIN_DISCORD_IDS = [
"81154649993785344", // Brian
"116999083796725761", // Marty
"78546869373906944", // Minaraii
];

View File

@ -0,0 +1,31 @@
import * as z from "zod";
// https://stackoverflow.com/a/3809435
const urlRegex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/;
export const salmonRunRecordSchema = z.object({
rotationId: z.number(), // check on db level
goldenEggCount: z.number().min(0).max(300),
category: z.string(), // check on db level
userIds: z.array(z.number()),
links: z
.string()
.refine((val) => {
const lines = linesFromTextareaValue(val);
if (lines.length === 0 || lines.length > 4) {
return false;
}
return true;
}, "Include 1-4 links")
.refine((val) => {
return linesFromTextareaValue(val).every((link) => urlRegex.test(link));
}, "One of the links is invalid"),
});
function linesFromTextareaValue(value: string) {
return value
.trim()
.split("\n")
.filter((val) => val !== "");
}

View File

@ -2,6 +2,7 @@ import {
Button, Button,
Flex, Flex,
FormControl, FormControl,
FormErrorMessage,
FormHelperText, FormHelperText,
FormLabel, FormLabel,
NumberDecrementStepper, NumberDecrementStepper,
@ -12,23 +13,18 @@ import {
Select, Select,
Textarea, Textarea,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { zodResolver } from "@hookform/resolvers/zod";
import { t, Trans } from "@lingui/macro"; import { t, Trans } from "@lingui/macro";
import { useLingui } from "@lingui/react"; import { useLingui } from "@lingui/react";
import { SalmonRunRecordCategory } from "@prisma/client";
import Breadcrumbs from "components/common/Breadcrumbs"; import Breadcrumbs from "components/common/Breadcrumbs";
import MyContainer from "components/common/MyContainer"; import MyContainer from "components/common/MyContainer";
import UserSelector from "components/common/UserSelector"; import UserSelector from "components/common/UserSelector";
import RotationSelector from "components/sr/RotationSelector"; import RotationSelector from "components/sr/RotationSelector";
import { salmonRunRecordSchema } from "lib/validators/salmonRunRecord";
import Image from "next/image"; import Image from "next/image";
import { useState } from "react"; import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
interface RecordFormData { import * as z from "zod";
rotationId: number;
userIds: number[];
category: SalmonRunRecordCategory;
goldenEggCount: number;
links: string;
}
const salmonRunCategoryToNatural = { const salmonRunCategoryToNatural = {
TOTAL: t`All waves`, TOTAL: t`All waves`,
@ -52,10 +48,20 @@ const salmonRunCategoryToNatural = {
LT_COHOCK: t`Cohock Charge`, LT_COHOCK: t`Cohock Charge`,
} as const; } as const;
type FormData = z.infer<typeof salmonRunRecordSchema>;
const AddRecordModal = () => { const AddRecordModal = () => {
const { i18n } = useLingui(); const { i18n } = useLingui();
const [sending, setSending] = useState(false); const [sending, setSending] = useState(false);
const [form, setForm] = useState<Partial<RecordFormData>>({ rotationId: 1 }); const { handleSubmit, errors, register, control, watch } = useForm<FormData>({
resolver: zodResolver(salmonRunRecordSchema),
});
const watchRotationId = watch("rotationId", undefined);
const onSubmit = async (data: FormData) => {
console.log("data", data);
};
return ( return (
<MyContainer> <MyContainer>
@ -66,36 +72,22 @@ const AddRecordModal = () => {
{ name: t`New record` }, { name: t`New record` },
]} ]}
/> />
<form /*onSubmit={handleSubmit(onSubmit)}*/> <form onSubmit={handleSubmit(onSubmit)}>
<RotationSelector <Controller
rotationId={form.rotationId} name="rotationId"
setRotationId={(rotationId) => { control={control}
if (!rotationId) { defaultValue={undefined}
const newForm = { ...form }; render={({ value, onChange }) => (
delete newForm.rotationId; <RotationSelector rotationId={value} setRotationId={onChange} />
setForm(newForm); )}
return;
}
setForm({ ...form, rotationId });
}}
/> />
{form.rotationId && ( {watchRotationId && (
<> <>
<FormLabel htmlFor="category" mt={4}> <FormLabel htmlFor="category" mt={4}>
<Trans>Category</Trans> <Trans>Category</Trans>
</FormLabel> </FormLabel>
<Select <Select name="category" ref={register}>
name="category"
value={form.category}
onChange={(e) =>
setForm({
...form,
category: e.target.value as SalmonRunRecordCategory,
})
}
>
{Object.entries(salmonRunCategoryToNatural).map( {Object.entries(salmonRunCategoryToNatural).map(
([key, value]) => ( ([key, value]) => (
<option key={key} value={key}> <option key={key} value={key}>
@ -105,46 +97,70 @@ const AddRecordModal = () => {
)} )}
</Select> </Select>
<FormLabel htmlFor="goldenEggCount" mt={4}> <FormControl isInvalid={!!errors.goldenEggCount}>
<Flex alignItems="center"> <FormLabel htmlFor="goldenEggCount" mt={4}>
<Flex align="center" mr={1}> <Flex alignItems="center">
<Image <Flex align="center" mr={1}>
src="/images/salmonRunIcons/Golden%20Egg.png" <Image
width={32} src="/images/salmonRunIcons/Golden%20Egg.png"
height={32} width={32}
/> height={32}
/>
</Flex>
<Trans>Golden Egg Count</Trans>
</Flex> </Flex>
<Trans>Golden Egg Count</Trans> </FormLabel>
</Flex> <Controller
</FormLabel> name="goldenEggCount"
<NumberInput name="goldenEggCount" maxW={48}> control={control}
<NumberInputField /> defaultValue={0}
<NumberInputStepper> render={({ value, onChange }) => (
<NumberIncrementStepper /> <NumberInput
<NumberDecrementStepper /> name="goldenEggCount"
</NumberInputStepper> maxW={48}
</NumberInput> value={value}
onChange={(_, value) => onChange(value)}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
)}
/>
<FormErrorMessage>
{errors.goldenEggCount?.message}
</FormErrorMessage>
</FormControl>
<FormControl> <FormControl>
<FormLabel mt={4}> <FormLabel mt={4}>
<Trans>Players</Trans> <Trans>Players</Trans>
</FormLabel> </FormLabel>
<UserSelector <Controller
value={form.userIds ?? []} name="userIds"
setValue={(userIds: number[]) => setForm({ ...form, userIds })} control={control}
isMulti={true} defaultValue={[]}
maxMultiCount={3} render={({ value, onChange }) => (
<UserSelector
value={value}
setValue={onChange}
isMulti={true}
maxMultiCount={3}
/>
)}
/> />
<FormHelperText> <FormHelperText>
Add up to three people you played with when you got the result. Add up to three people you played with when you got the result.
</FormHelperText> </FormHelperText>
</FormControl> </FormControl>
<FormControl> <FormControl isInvalid={!!errors.links}>
<FormLabel mt={4}> <FormLabel mt={4}>
<Trans>Links</Trans> <Trans>Links</Trans>
</FormLabel> </FormLabel>
<FormHelperText mb={4} mt="-10px"> <FormHelperText mb={3} mt="-7px">
<Trans> <Trans>
Add one to four links to provide context behind the record Add one to four links to provide context behind the record
(e.g. VoDs on YouTube, screenshots on Twitter). One link per (e.g. VoDs on YouTube, screenshots on Twitter). One link per
@ -152,17 +168,20 @@ const AddRecordModal = () => {
</Trans> </Trans>
</FormHelperText> </FormHelperText>
<Textarea <Textarea
value={form.links} name="links"
onChange={(e) => setForm({ ...form, links: e.target.value })} ref={register}
rows={4} rows={4}
resize="none" resize="none"
placeholder={ placeholder={
"https://twitter.com/BrianTheDrumer/status/1338469066797953024\nhttps://www.youtube.com/watch?v=6evFXzxrTfU" "https://twitter.com/BrianTheDrumer/status/1338469066797953024\nhttps://www.youtube.com/watch?v=6evFXzxrTfU"
} }
/> />
<FormErrorMessage mt="-1px">
{errors.links?.message}
</FormErrorMessage>
</FormControl> </FormControl>
<Button mt={6} /*type="submit"*/ isLoading={sending}> <Button mt={6} type="submit" isLoading={sending}>
<Trans>Submit</Trans> <Trans>Submit</Trans>
</Button> </Button>
</> </>