import React from 'react'; import { TextField, TextFieldProps, TextFieldHTMLProps } from '@rmwc/textfield'; import { Select, SelectProps, SelectHTMLProps } from '@rmwc/select'; import { Card, CardProps } from '@rmwc/card'; import Button from '@tutorbook/button'; import SubjectSelect, { SubjectSelectProps } from '@tutorbook/subject-select'; import ScheduleInput, { ScheduleInputProps } from '@tutorbook/schedule-input'; import CheckmarkOverlay from '@tutorbook/checkmark-overlay'; import { Availability } from '@tutorbook/model'; import styles from './form.module.scss'; export type InputElAlias = | 'textfield' | 'textarea' | 'select' | 'subjectselect' | 'scheduleinput'; interface UniqueInputProps { readonly el: InputElAlias; readonly label: string; readonly key?: string; } type InputProps = UniqueInputProps & ( | SubjectSelectProps | ScheduleInputProps | (TextFieldProps & TextFieldHTMLProps) | (SelectProps & SelectHTMLProps) ); interface CustomInputProps { readonly el: JSX.Element; } type Input = InputProps | CustomInputProps; interface FormProps extends React.HTMLProps { readonly inputs: ReadonlyArray; readonly submitLabel: string; readonly cardProps?: CardProps & React.HTMLProps; readonly onFormSubmit: (formValues: { readonly [formInputLabel: string]: any; }) => Promise; readonly loadingLabel?: boolean; readonly loadingCheckmark?: boolean; } interface FormState { readonly submitting: boolean; readonly submitted: boolean; } export default class Form extends React.Component { public readonly state: FormState = { submitting: false, submitted: false, }; private readonly values: { [formInputLabel: string]: any; } = {}; public constructor(props: FormProps) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } /** * Renders the input React components from the given array of `InputProps`. * @todo Perhaps revert back to rendering once (in the constructor) and using * a `this.inputs` field to improve performance. */ private renderInputs(): JSX.Element[] { return this.props.inputs.map((input: Input, index: number) => { const { el, ...props } = input; switch (el) { case 'textfield': return ( this.handleInputChange(input as InputProps, event) } key={index} outlined className={styles.formField} {...(props as TextFieldProps)} /> ); case 'textarea': return ( this.handleInputChange(input as InputProps, event) } key={index} outlined textarea rows={4} className={styles.formField} {...(props as TextFieldProps)} /> ); case 'select': return (