import HelpOutlineIcon from '@mui/icons-material/HelpOutline'; import MailIcon from '@mui/icons-material/MailOutline'; import { Typography } from '@mui/material'; import { type FormikValues, useFormikContext } from 'formik'; import { equals, prop } from 'ramda'; import { array, boolean, mixed, number, object, string } from 'yup'; import type { Listing } from '../api/models'; import type { SelectEntry } from '../InputField/Select'; import { type Group, type InputProps, type InputPropsWithoutGroup, InputType } from './Inputs/models'; export interface BasicForm { active: boolean; activeSortableFieldsTable: boolean; animals: Array; anotherText: string; certificate: string; class: { id: number; name: string } | null; custom: string; email: string; group: { id: number; name: string } | null; inviteUsers: Array<{ role: SelectEntry; user: string; }>; inviteUsers2: Array; isForced: boolean; language: string; name: string; password: string; roleMapping: Array<{ role: SelectEntry; value: string; }>; scopes: Array; sports: Array; } const selectEntryValidationSchema = object().shape({ id: number().required('Required'), name: string().required('Required') }); export const basicFormValidationSchema = object().shape({ active: boolean().required('Active is required'), activeSortableFieldsTable: boolean().required( 'Active Sortable FieldsTable is required' ), animals: array().of(selectEntryValidationSchema.required('Required')), anotherText: string(), certificate: string(), class: selectEntryValidationSchema.nullable().required('Required'), custom: string().required('Custom is required'), email: string().email('Invalid email').required('Email is required'), file: mixed(), group: selectEntryValidationSchema.nullable().required('Required'), inviteUsers: array().of( object({ email: string().email('Invalid user email').required('Email is required'), role: selectEntryValidationSchema }) ), inviteUsers2: array().of(string().email('Invalid user email')), isForced: boolean().required('Is forced is required'), language: string().required('Language is required'), name: string().required('Name is required'), password: string().required('Password is required'), roleMapping: array().of( object({ role: selectEntryValidationSchema, value: string().required('Role value is required') }) ), scopes: array().of(string().min(3, '3 characters min').required('Required')), sports: array().of(selectEntryValidationSchema.required('Required')) }); const roleEntries: Array = [ { id: 1, name: 'Administrator' }, { id: 2, name: 'User' }, { id: 3, name: 'Editor' } ]; export const basicFormInitialValues = { active: false, activeSortableFieldsTable: false, animals: [], certificate: '', class: { id: 0, name: 'Class 0' }, custom: '', email: '', file: null, group: null, inviteUsers: [], inviteUsers2: [], isForced: false, language: 'French', name: '', notifications: { channels: { checked: true, Icon: MailIcon, label: 'mail' }, hostevents: ['ok', 'warning'], includeServices: { checked: true, label: 'Include services for this host' } }, password: '', roleMapping: [ { priority: 0, role: roleEntries[0], value: 'example' }, { priority: 1, role: roleEntries[1], value: 'example2' }, { priority: 2, role: roleEntries[2], value: 'example3' } ], scopes: [], sports: [] }; export const classOptions = [...Array(10).keys()].map((idx) => ({ id: idx, name: `Class ${idx}` })); export const sportOptions = [...Array(10).keys()].map((idx) => ({ id: idx, name: `Sport ${idx}` })); export const basicFormGroups: Array = [ { name: 'First group', order: 1 }, { EndIcon: () => , name: 'Third group', order: 3, TooltipContent: (): JSX.Element => Tooltip content }, { name: 'Second group', order: 2 }, { name: 'Fourth group', order: 4 } ]; export const basicFormInputs: Array = [ { fieldName: 'name', group: 'First group', label: 'Name', type: InputType.Text }, { fieldName: 'email', group: 'First group', label: 'Email', text: { endAdornment: , placeholder: 'Your email here' }, type: InputType.Text }, { fieldName: 'active', group: 'Second group', label: 'Active', type: InputType.Switch }, { additionalLabel: 'This a very special label', fieldName: 'password', group: 'First group', hideInput: (values) => values.active, label: 'Password', type: InputType.Password }, { fieldName: 'language', group: 'First group', label: 'Language', radio: { options: [ { label: 'French', value: 'French' }, { label: 'English', value: 'English' } ] }, type: InputType.Radio }, { fieldName: 'div', group: 'First group', label: 'divider', type: InputType.Divider }, { additionalLabel: 'Notifications', fieldName: '', grid: { alignItems: 'center', columns: [ { checkbox: { direction: 'horizontal' }, fieldName: 'notifications.channels', label: 'mail', type: InputType.Checkbox }, { fieldName: 'notifications.includeServices', label: 'Include services for this host', type: InputType.Checkbox }, { checkbox: { direction: 'horizontal', labelPlacement: 'top', options: ['ok', 'warning', 'critical', 'unknown'] }, fieldName: 'notifications.hostevents', label: 'host events', type: InputType.CheckboxGroup } ] }, group: 'Third group', label: 'Notifications', type: InputType.Grid }, { fieldName: 'anotherText', group: 'First group', hideInput: ({ language }) => equals(language, 'French'), label: 'Another Text input', type: InputType.Text }, { fieldName: 'isForced', group: 'First group', label: 'Is Forced?', radio: { options: [ { label: 'Is not forced', value: false }, { label: 'Is forced', value: true } ] }, type: InputType.Radio }, { fieldName: '', grid: { columns: [ { autocomplete: { options: classOptions }, fieldName: 'class', label: 'Class (Single autocomplete)', type: InputType.SingleAutocomplete }, { autocomplete: { options: sportOptions }, fieldName: 'sports', label: 'Sports (Multi autocomplete)', type: InputType.MultiAutocomplete } ] }, group: 'First group', label: 'autocompletes', type: InputType.Grid }, { autocomplete: { creatable: true, options: [] }, fieldName: 'scopes', group: 'First group', label: 'Scopes (Multi autocomplete that allows value creation)', type: InputType.MultiAutocomplete }, { fieldName: '', grid: { columns: [ { connectedAutocomplete: { additionalConditionParameters: [], customQueryParameters: [], endpoint: 'endpoint', helperText: 'Hello I am testing' } as InputProps['connectedAutocomplete'], fieldName: 'group', label: 'Group (Single connected autocomplete)', type: InputType.SingleConnectedAutocomplete }, { connectedAutocomplete: { additionalConditionParameters: [], customQueryParameters: [], endpoint: 'endpoint' } as InputProps['connectedAutocomplete'], fieldName: 'animals', label: 'Animals (Multi connected autocomplete)', type: InputType.MultiConnectedAutocomplete } ], gridTemplateColumns: '400px 1fr' }, group: 'First group', label: 'connected autocompletes', type: InputType.Grid }, { custom: { Component: ({ label }: InputPropsWithoutGroup): JSX.Element => ( This is a {label} component ) }, fieldName: 'custom', group: 'Second group', label: 'Custom', type: InputType.Custom }, { fieldName: 'inviteUsers', fieldsTable: { columns: [ { fieldName: 'email', label: 'Email', required: true, type: InputType.Text }, { autocomplete: { creatable: false, options: roleEntries }, fieldName: 'role', label: 'Role', type: InputType.SingleAutocomplete } ], defaultRowValue: { email: 'example@test.fr', role: null }, deleteLabel: 'Delete' }, group: 'First group', label: 'inviteUsers', type: InputType.FieldsTable }, { fieldName: 'inviteUsers2', fieldsTable: { columns: [ { fieldName: 'email', label: 'Email', required: true, type: InputType.Text } ], defaultRowValue: 'example', deleteLabel: 'Delete', hasSingleValue: true }, group: 'First group', label: 'inviteUsers2', type: InputType.FieldsTable }, { fieldName: 'activeSortableFieldsTable', group: 'First group', label: 'Active Sortable Fields Table', type: InputType.Switch }, { fieldName: 'roleMapping', fieldsTable: { columns: [ { fieldName: 'value', label: 'RoleValue', required: true, type: InputType.Text }, { autocomplete: { creatable: false, options: roleEntries }, fieldName: 'role', label: 'RoleAcl', type: InputType.SingleAutocomplete } ], defaultRowValue: { role: null, value: '' }, deleteLabel: 'Delete', getSortable: (values: FormikValues): boolean => prop('activeSortableFieldsTable', values) }, group: 'First group', label: 'roleMapping', type: InputType.FieldsTable }, { fieldName: 'certificate', group: 'First group', label: 'Certificate', text: { multilineRows: 4 }, type: InputType.Text }, { fieldName: 'file', file: { accept: 'image/*', CustomDropZoneContent: ({ files }) =>
{files?.length} files
, multiple: true }, group: 'First group', label: 'File', type: InputType.File } ]; export const CustomButton = (): JSX.Element => { const { dirty, isValid } = useFormikContext(); return (
Has form changed? {JSON.stringify(dirty)} Is valid? {JSON.stringify(isValid)}
); }; const buildEntities = (from: number): Array => { return Array(10) .fill(0) .map((_, index) => ({ id: from + index, name: `Entity ${from + index}` })); }; export const buildResult = (page: number): Listing => ({ meta: { limit: 10, page, total: 40 }, result: buildEntities((page - 1) * 10) });