mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-02-11 06:24:56 -05:00
* upgraded storybook dependencies * upgraded web dependencies * updated timezone selector * upgrade chakra in metamaps * upgraded react-dnd in metamaps * upgraded framer-motion * fixed types in metamaps * upgraded eslint * upgraded lerna, husky and graphql * upgraded node version * removed metamaps package * fixed all eslint issues * ran yarn format to prettier format all files * updated lint-staged & husky scripts * add executable perms to pre-push scripts * updated yarn.lock * fixed eslint and moved chakra icons to ds * fixed emotion errors * removed extra useContext * update yarn.lock * upgraded more packages * removed unnecessary .huskyrc.json * lint fix
319 lines
8.3 KiB
TypeScript
319 lines
8.3 KiB
TypeScript
import {
|
|
Box,
|
|
ConfirmModal,
|
|
Flex,
|
|
HStack,
|
|
Input,
|
|
MetaButton,
|
|
MetaTag,
|
|
Select,
|
|
Text,
|
|
Textarea,
|
|
VStack,
|
|
} from '@metafam/ds';
|
|
import {
|
|
GuildFragmentFragment,
|
|
QuestFragmentFragment,
|
|
QuestRepetition_Enum,
|
|
QuestStatus_Enum,
|
|
} from 'graphql/autogen/types';
|
|
import { useRouter } from 'next/router';
|
|
import React, { useMemo, useState } from 'react';
|
|
import { Controller, FieldError, useForm } from 'react-hook-form';
|
|
|
|
import { QuestRepetitionHint, UriRegexp } from '../../utils/questHelpers';
|
|
import { CategoryOption, SkillOption } from '../../utils/skillHelpers';
|
|
import { FlexContainer } from '../Container';
|
|
import { SkillsSelect } from '../Skills';
|
|
import { RepetitionColors } from './QuestTags';
|
|
|
|
const validations = {
|
|
title: {
|
|
required: true,
|
|
minLength: 4,
|
|
maxLength: 50,
|
|
},
|
|
description: {
|
|
required: true,
|
|
minLength: 4,
|
|
},
|
|
repetition: {
|
|
required: true,
|
|
},
|
|
guild_id: {
|
|
required: true,
|
|
},
|
|
external_link: {
|
|
pattern: UriRegexp,
|
|
},
|
|
cooldown: {
|
|
valueAsNumber: true,
|
|
min: 1,
|
|
},
|
|
};
|
|
|
|
export interface CreateQuestFormInputs {
|
|
title: string;
|
|
description: string | undefined | null;
|
|
repetition: QuestRepetition_Enum;
|
|
status: QuestStatus_Enum;
|
|
guild_id: string | null;
|
|
external_link: string | undefined | null;
|
|
cooldown: number | undefined | null;
|
|
skills: SkillOption[];
|
|
}
|
|
|
|
const MetaFamGuildId = 'f94b7cd4-cf29-4251-baa5-eaacab98a719';
|
|
|
|
const getDefaultFormValues = (
|
|
editQuest: QuestFragmentFragment | undefined,
|
|
guilds: GuildFragmentFragment[],
|
|
): CreateQuestFormInputs => ({
|
|
title: editQuest?.title || '',
|
|
repetition: editQuest?.repetition || QuestRepetition_Enum.Unique,
|
|
description: editQuest?.description || '',
|
|
external_link: editQuest?.external_link || '',
|
|
guild_id:
|
|
editQuest?.guild_id ||
|
|
guilds.find((g) => g.id === MetaFamGuildId)?.id ||
|
|
guilds[0].id,
|
|
status: editQuest?.status || QuestStatus_Enum.Open,
|
|
cooldown: editQuest?.cooldown || null,
|
|
skills: editQuest
|
|
? editQuest.quest_skills
|
|
.map((s) => s.skill)
|
|
.map((s) => ({
|
|
value: s.id,
|
|
label: s.name,
|
|
...s,
|
|
}))
|
|
: [],
|
|
});
|
|
|
|
type FieldProps = {
|
|
children: React.ReactNode;
|
|
label: string;
|
|
error?: FieldError;
|
|
};
|
|
|
|
const Field: React.FC<FieldProps> = ({ children, error, label }) => (
|
|
<Flex mb={2} w="100%" align="center" direction="column">
|
|
<Flex justify="space-between" w="100%" mb={2}>
|
|
<Text textStyle="caption" textAlign="left" ml={4}>
|
|
{label}
|
|
</Text>
|
|
|
|
<Text textStyle="caption" textAlign="left" color="red.400" mr={4}>
|
|
{error?.type === 'required' && 'Required'}
|
|
{error?.type === 'pattern' && 'Invalid URL'}
|
|
{error?.type === 'minLength' && 'Too short'}
|
|
{error?.type === 'maxLength' && 'Too long'}
|
|
{error?.type === 'min' && 'Too small'}
|
|
</Text>
|
|
</Flex>
|
|
|
|
{children}
|
|
</Flex>
|
|
);
|
|
|
|
type Props = {
|
|
guilds: GuildFragmentFragment[];
|
|
editQuest?: QuestFragmentFragment;
|
|
skillChoices: Array<CategoryOption>;
|
|
onSubmit: (data: CreateQuestFormInputs) => void;
|
|
success?: boolean;
|
|
fetching?: boolean;
|
|
submitLabel: string;
|
|
loadingLabel: string;
|
|
};
|
|
|
|
export const QuestForm: React.FC<Props> = ({
|
|
guilds,
|
|
skillChoices,
|
|
onSubmit,
|
|
success,
|
|
fetching,
|
|
submitLabel,
|
|
loadingLabel,
|
|
editQuest,
|
|
}) => {
|
|
const defaultValues = useMemo<CreateQuestFormInputs>(
|
|
() => getDefaultFormValues(editQuest, guilds),
|
|
[editQuest, guilds],
|
|
);
|
|
const {
|
|
register,
|
|
control,
|
|
errors,
|
|
watch,
|
|
handleSubmit,
|
|
} = useForm<CreateQuestFormInputs>({
|
|
defaultValues,
|
|
});
|
|
const router = useRouter();
|
|
const [exitAlert, setExitAlert] = useState<boolean>(false);
|
|
const createQuestInput = watch();
|
|
|
|
return (
|
|
<Box w="100%" maxW="30rem">
|
|
<VStack>
|
|
<Field label="Title" error={errors.title}>
|
|
<Input
|
|
background="dark"
|
|
placeholder="Buidl stuff"
|
|
isRequired
|
|
name="title"
|
|
ref={register(validations.title)}
|
|
isInvalid={!!errors.title}
|
|
minLength={validations.title.minLength}
|
|
maxLength={validations.title.maxLength}
|
|
/>
|
|
</Field>
|
|
|
|
<Field label="Description" error={errors.description}>
|
|
<Textarea
|
|
background="dark"
|
|
placeholder="Please describe in details what needs to be done"
|
|
isRequired
|
|
name="description"
|
|
ref={register(validations.description)}
|
|
isInvalid={!!errors.description}
|
|
/>
|
|
</Field>
|
|
|
|
<Field label="Link" error={errors.external_link}>
|
|
<Input
|
|
background="dark"
|
|
placeholder="External link"
|
|
name="external_link"
|
|
ref={register(validations.external_link)}
|
|
isInvalid={!!errors.external_link}
|
|
/>
|
|
</Field>
|
|
|
|
<Field label="Repetition">
|
|
<Select
|
|
isRequired
|
|
name="repetition"
|
|
ref={register(validations.repetition)}
|
|
isInvalid={!!errors.repetition}
|
|
bg="dark"
|
|
color="white"
|
|
>
|
|
{Object.entries(QuestRepetition_Enum).map(([key, value]) => (
|
|
<option key={value} value={value}>
|
|
{key}
|
|
</option>
|
|
))}
|
|
</Select>
|
|
<MetaTag
|
|
size="md"
|
|
fontWeight="normal"
|
|
p={2}
|
|
mt={2}
|
|
backgroundColor={RepetitionColors[createQuestInput.repetition]}
|
|
>
|
|
{QuestRepetitionHint[createQuestInput.repetition]}
|
|
</MetaTag>
|
|
</Field>
|
|
{createQuestInput.repetition === QuestRepetition_Enum.Recurring && (
|
|
<Field label="Cooldown (hours)" error={errors.cooldown}>
|
|
<Input
|
|
isRequired
|
|
background="dark"
|
|
placeholder="3600"
|
|
name="cooldown"
|
|
type="number"
|
|
ref={register(validations.cooldown)}
|
|
isInvalid={!!errors.cooldown}
|
|
/>
|
|
</Field>
|
|
)}
|
|
|
|
<Field label="Guild">
|
|
<Select
|
|
isRequired
|
|
name="guild_id"
|
|
ref={register(validations.guild_id)}
|
|
isInvalid={!!errors.guild_id}
|
|
bg="dark"
|
|
color="white"
|
|
>
|
|
{guilds.map((guild) => (
|
|
<option key={guild.id} value={guild.id}>
|
|
{guild.name}
|
|
</option>
|
|
))}
|
|
</Select>
|
|
</Field>
|
|
|
|
{editQuest && (
|
|
<Field label="Status">
|
|
<Select
|
|
isRequired
|
|
name="status"
|
|
bg="dark"
|
|
color="white"
|
|
ref={register}
|
|
isInvalid={!!errors.status}
|
|
>
|
|
{Object.entries(QuestStatus_Enum).map(([key, value]) => (
|
|
<option key={value} value={value}>
|
|
{key}
|
|
</option>
|
|
))}
|
|
</Select>
|
|
</Field>
|
|
)}
|
|
|
|
<Field label="Skills">
|
|
<FlexContainer w="100%" align="stretch" maxW="50rem">
|
|
<Controller
|
|
name="skills"
|
|
control={control}
|
|
defaultValue={[]}
|
|
render={({ onChange, value }) => (
|
|
<SkillsSelect
|
|
skillChoices={skillChoices}
|
|
skills={value}
|
|
setSkills={onChange}
|
|
placeHolder="Select required skills"
|
|
/>
|
|
)}
|
|
/>
|
|
</FlexContainer>
|
|
</Field>
|
|
|
|
<HStack justify="space-between" mt={4} w="100%">
|
|
<MetaButton
|
|
variant="outline"
|
|
colorScheme="pink"
|
|
onClick={() => setExitAlert(true)}
|
|
isDisabled={fetching || success}
|
|
>
|
|
Cancel
|
|
</MetaButton>
|
|
<MetaButton
|
|
mt={10}
|
|
isLoading={fetching}
|
|
loadingText={loadingLabel}
|
|
onClick={handleSubmit(onSubmit)}
|
|
isDisabled={success}
|
|
>
|
|
{submitLabel}
|
|
</MetaButton>
|
|
</HStack>
|
|
</VStack>
|
|
|
|
<ConfirmModal
|
|
isOpen={exitAlert}
|
|
onNope={() => setExitAlert(false)}
|
|
onYep={() =>
|
|
router.push(editQuest ? `/quest/${editQuest.id}` : '/quests')
|
|
}
|
|
header="Are you sure you want to leave ?"
|
|
/>
|
|
</Box>
|
|
);
|
|
};
|