sendou.ink/components/plus/SuggestionModal.tsx
Kalle 1589b84c4b
New layout (#427) closes #405
* side layout initial

* add elements to side nav

* side buttons links

* remove clog

* calendar page initial

* position sticky working

* x trends page initial

* new table

* same mode selector

* mobile friendly table

* no underline for nav links

* xsearch

* x trends page outlined

* sr initial

* relocate calendar components

* calendar fix flex

* topnav fancier look

* layout looking good edition

* relocate xtrends

* xtrends remove linecharts

* x trends new

* calender page new

* delete headbanner, new login

* remove calendar stuff from api

* rename stuff in utils

* fix user item margin

* new home page initial

* remove page concept

* no pointer xtrends

* remove xrank from app

* xtrends service

* move fa from app

* move plus

* maps tweaks

* new table for plus history

* navigational sidebar flex tweaks

* builds page

* analyzer

* user page

* free agents

* plans

* remove mx

* tweaks

* change layout to grid

* home page finalized

* mobile nav

* restrict main content width

* tweaks style

* language switcher

* container in css

* sticky nav

* use duplicate icons for now

* change mapsketch width to old

* chara tour vid

* borzoic icons
2021-04-21 17:26:50 +03:00

176 lines
5.6 KiB
TypeScript

import {
Button,
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Select,
Textarea,
useToast,
} from "@chakra-ui/react";
import { zodResolver } from "@hookform/resolvers/zod";
import UserSelector from "components/common/UserSelector";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { getToastOptions } from "utils/objects";
import { trpc } from "utils/trpc";
import {
suggestionFullSchema,
SUGGESTION_DESCRIPTION_LIMIT,
} from "utils/validators/suggestion";
import * as z from "zod";
interface Props {
userPlusMembershipTier: number;
}
type FormData = z.infer<typeof suggestionFullSchema>;
const SuggestionModal: React.FC<Props> = ({ userPlusMembershipTier }) => {
const toast = useToast();
const [isOpen, setIsOpen] = useState(false);
const { handleSubmit, errors, register, watch, control } = useForm<FormData>({
resolver: zodResolver(suggestionFullSchema),
});
const utils = trpc.useQueryUtils();
const { mutate, status } = trpc.useMutation("plus.suggestion", {
onSuccess() {
toast(getToastOptions("New suggestion submitted", "success"));
utils.invalidateQuery(["plus.suggestions"]);
setIsOpen(false);
},
onError(error) {
toast(getToastOptions(error.message, "error"));
},
});
const watchDescription = watch("description", "");
return (
<>
<Button
size="sm"
mb={4}
onClick={() => setIsOpen(true)}
data-cy="suggestion-button"
>
Add new suggestion
</Button>
{isOpen && (
<Modal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
size="xl"
closeOnOverlayClick={false}
>
<ModalOverlay>
<ModalContent>
<ModalHeader>Adding a new suggestion</ModalHeader>
<ModalCloseButton borderRadius="50%" />
<form onSubmit={handleSubmit((data) => mutate(data))}>
<ModalBody pb={2}>
<FormLabel>Tier</FormLabel>
<Controller
name="tier"
control={control}
defaultValue={userPlusMembershipTier}
render={({ value, onChange }) => (
<Select
value={value}
onChange={(e) => onChange(Number(e.target.value))}
>
{userPlusMembershipTier === 1 && (
<option value="1">+1</option>
)}
{userPlusMembershipTier <= 2 && (
<option value="2">+2</option>
)}
<option value="3">+3</option>
</Select>
)}
/>
<FormControl isInvalid={!!errors.suggestedId}>
<FormLabel mt={4}>User</FormLabel>
<Controller
name="suggestedId"
control={control}
render={({ value, onChange }) => (
<UserSelector
value={value}
setValue={onChange}
isMulti={false}
maxMultiCount={undefined}
/>
)}
/>
<FormErrorMessage>
{errors.suggestedId?.message}
</FormErrorMessage>
</FormControl>
<FormControl>
<FormLabel mt={4}>Region</FormLabel>
<Select
name="region"
ref={register}
data-cy="region-select"
>
<option value="NA">NA</option>
<option value="EU">EU</option>
</Select>
<FormHelperText>
If the player isn't from either region then choose the one
they play most commonly with.
</FormHelperText>
</FormControl>
<FormControl isInvalid={!!errors.description}>
<FormLabel htmlFor="description" mt={4}>
Description
</FormLabel>
<Textarea
name="description"
ref={register}
data-cy="description-textarea"
/>
<FormHelperText>
{(watchDescription ?? "").length}/
{SUGGESTION_DESCRIPTION_LIMIT}
</FormHelperText>
<FormErrorMessage>
{errors.description?.message}
</FormErrorMessage>
</FormControl>
</ModalBody>
<ModalFooter>
<Button
mr={3}
type="submit"
isLoading={status === "loading"}
data-cy="submit-button"
>
Save
</Button>
<Button onClick={() => setIsOpen(false)} variant="outline">
Cancel
</Button>
</ModalFooter>
</form>
</ModalContent>
</ModalOverlay>
</Modal>
)}
</>
);
};
export default SuggestionModal;