mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-12 10:53:51 +00:00
100 lines
3.0 KiB
TypeScript
100 lines
3.0 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { useForm } from 'react-hook-form';
|
|
import { Button, Input } from '@chakra-ui/react';
|
|
import { CustomField } from 'ontime-types';
|
|
import { isAlphanumeric } from 'ontime-utils';
|
|
|
|
import { maybeAxiosError } from '../../../../common/api/utils';
|
|
import SwatchSelect from '../../../../common/components/input/colour-input/SwatchSelect';
|
|
import * as Panel from '../PanelUtils';
|
|
|
|
import style from './ProjectSettingsPanel.module.scss';
|
|
|
|
interface CustomFieldsFormProps {
|
|
onSubmit: (field: CustomField) => Promise<void>;
|
|
onCancel: () => void;
|
|
initialColour?: string;
|
|
initialLabel?: string;
|
|
}
|
|
|
|
export default function CustomFieldForm(props: CustomFieldsFormProps) {
|
|
const { onSubmit, onCancel, initialColour, initialLabel } = props;
|
|
|
|
const {
|
|
handleSubmit,
|
|
register,
|
|
setFocus,
|
|
setError,
|
|
setValue,
|
|
getValues,
|
|
formState: { errors, isSubmitting, isValid, isDirty },
|
|
} = useForm({
|
|
defaultValues: { label: initialLabel || '', colour: initialColour || '' },
|
|
resetOptions: {
|
|
keepDirtyValues: true,
|
|
},
|
|
});
|
|
|
|
const setupSubmit = async (values: { label: string; colour: string }) => {
|
|
const { label, colour } = values;
|
|
const newField: CustomField = {
|
|
type: 'string', // type is not user definable yet
|
|
colour,
|
|
label,
|
|
};
|
|
try {
|
|
await onSubmit(newField);
|
|
} catch (error) {
|
|
setError('root', { type: 'custom', message: maybeAxiosError(error) });
|
|
}
|
|
};
|
|
|
|
// give initial focus to the label
|
|
useEffect(() => {
|
|
setFocus('label');
|
|
}, [setFocus]);
|
|
|
|
const handleSelectColour = (colour: string) => {
|
|
setValue('colour', colour, { shouldDirty: true });
|
|
};
|
|
|
|
const colour = getValues('colour');
|
|
const canSubmit = isDirty && isValid;
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit(setupSubmit)} className={style.fieldForm}>
|
|
<div className={style.column}>
|
|
<Panel.Description>Label</Panel.Description>
|
|
{errors.label && <Panel.Error>{errors.label.message}</Panel.Error>}
|
|
<Input
|
|
{...register('label', {
|
|
required: { value: true, message: 'Required field' },
|
|
validate: (value) => {
|
|
if (value.trim().length === 0) return 'Required field';
|
|
if (!isAlphanumeric(value)) return 'Only alphanumeric characters are allowed';
|
|
return true;
|
|
},
|
|
})}
|
|
size='sm'
|
|
variant='ontime-filled'
|
|
autoComplete='off'
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Panel.Description>Colour</Panel.Description>
|
|
<SwatchSelect name='colour' value={colour} handleChange={(_field, value) => handleSelectColour(value)} />
|
|
</div>
|
|
{errors.root && <Panel.Error>{errors.root.message}</Panel.Error>}
|
|
<div className={style.buttonRow}>
|
|
<Button size='sm' variant='ontime-ghosted' onClick={onCancel}>
|
|
Cancel
|
|
</Button>
|
|
<Button size='sm' type='submit' variant='ontime-filled' isDisabled={!canSubmit} isLoading={isSubmitting}>
|
|
Save
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
);
|
|
}
|