import { Box, Button, Checkbox, CheckboxGroup, FormControl, FormErrorMessage, FormHelperText, FormLabel, Input, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Stack, Textarea, useToast, } from "@chakra-ui/react"; import { zodResolver } from "@hookform/resolvers/zod"; import { t, Trans } from "@lingui/macro"; import { Ability } from "@prisma/client"; import ViewSlots from "components/builds/ViewSlots"; import GearSelector from "components/common/GearSelector"; import WeaponSelector from "components/common/WeaponSelector"; import { useUser } from "hooks/common"; import { GetBuildsByUserData } from "prisma/queries/getBuildsByUser"; import { useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { FiTrash } from "react-icons/fi"; import { mutate } from "swr"; import { getToastOptions } from "utils/getToastOptions"; import { weapons } from "utils/lists/weapons"; import { sendData } from "utils/postData"; import { Unpacked } from "utils/types"; import { buildSchema, DESCRIPTION_CHARACTER_LIMIT, TITLE_CHARACTER_LIMIT, } from "utils/validators/build"; import * as z from "zod"; import AbilitiesSelector from "./AbilitiesSelector"; interface Props { onClose: () => void; build?: Unpacked>; weaponFromQuery?: string; } type FormData = z.infer; const BuildModal: React.FC = ({ onClose, build, weaponFromQuery }) => { const [sending, setSending] = useState(false); const [deleting, setDeleting] = useState(false); const [loggedInUser] = useUser(); const { handleSubmit, errors, register, watch, control } = useForm({ resolver: zodResolver(buildSchema), defaultValues: { headAbilities: ([ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", ] as unknown) as Ability[], clothingAbilities: ([ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", ] as unknown) as Ability[], shoesAbilities: ([ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", ] as unknown) as Ability[], weapon: weapons.includes(weaponFromQuery as any) ? weaponFromQuery : undefined, ...build, }, }); const watchTitle = watch("title", build?.title); const watchDescription = watch("description", build?.description); const toast = useToast(); const onSubmit = async (formData: FormData) => { if (!loggedInUser) { console.error("Unexpected no logged in user"); return; } setSending(true); const mutationData = { ...formData }; for (const [key, value] of Object.entries(mutationData)) { if (value === "" || value === undefined) { // @ts-ignore mutationData[key] = null; } } const success = await sendData( build ? "PUT" : "POST", "/api/builds", build ? { ...mutationData, id: build.id } : mutationData ); setSending(false); if (!success) return; mutate(`/api/users/${loggedInUser.id}/builds`); toast( getToastOptions(build ? t`Build updated` : t`New build added`, "success") ); onClose(); }; const onDelete = async () => { if (!loggedInUser) { console.error("Unexpected no logged in user"); return; } if (!build) { console.error("Unexpected no build"); return; } setDeleting(true); const success = await sendData("DELETE", "/api/builds", { id: build.id }); setDeleting(false); if (!success) return; mutate(`/api/users/${loggedInUser.id}/builds`); toast(getToastOptions(t`Build deleted`, "success")); onClose(); }; return ( {build ? ( Editing build ) : ( Adding a new build )}
{build && ( )} Weapon ( )} /> {t`Choose a weapon for your build`} {/* yeah....... didn't find an easier way to do this with the library so here we are */} ( ( ( { const abilityArrays = { headAbilities, clothingAbilities, shoesAbilities, }; const onChange = { headAbilities: onHeadChange, clothingAbilities: onClothingChange, shoesAbilities: onShoesChange, }; const newAbilityArray = [ ...abilityArrays[gear], ]; newAbilityArray[index] = "UNKNOWN"; onChange[gear](newAbilityArray); }} /> { onHeadChange(newAbilities.headAbilities); onClothingChange( newAbilities.clothingAbilities ); onShoesChange(newAbilities.shoesAbilities); }} /> )} /> )} /> )} /> {t`Your build is missing some abilities`} Title {(watchTitle ?? "").length}/{TITLE_CHARACTER_LIMIT} {errors.title?.message} Description