Untitled

mail@pastecode.io avatar
unknown
typescript
a year ago
34 kB
4
Indexable
Never
import { useCallback, useEffect, useRef, useState } from "react";
import useResponsive from "src/hooks/useResponsive";
import {LocalizationProvider, DatePicker, TimePicker} from '@mui/x-date-pickers'
import {FormControlLabel, Checkbox, RadioGroup, Radio} from '@mui/material'
import { useSetRecoilState } from "recoil";
import { captchaAtom } from "src/atoms/captcha";
import { GoogleReCaptchaProvider, GoogleReCaptcha } from 'react-google-recaptcha-v3';
import { useClickAway } from "use-click-away";
import PhoneInput from 'react-phone-input-2'
import globalSettings from "src/constants/globalSettings_backup";
import PlacesAutocomplete, {geocodeByAddress} from 'react-places-autocomplete';  
import { AddListItemButton, AddressContainer, AddressOption, AddressOptions, CheckBoxesContainer, CheckBoxesWrapper, ChipStyle, ChipText, ChipX, ConsetContainer, Container, FileInput, HTMLBlockStyle, InputStyle, ListContainer, ListInput, ListInputContainer, ListItem, ListItemText, ListItemsContainer, MultiSelectedOption, Option, PageNavigation, PageNavigationContainer, PhoneContainer, RemoveListItemButton, Required, RoundedInputContainer, RoundedInputStyle, RoundedOption, RoundedSelectOptionsStyle, RoundedSelectStyle, RoundedSelectStyleProps, RoundedSelectedOption, SectionLine, SelectArrow, SelectContainer, SelectStyle, SelectedOption, TextareaStyle, Title, UploadButton, UploadIcon, UploadText } from "./styles";
import { ReactComponent as SearchIcon } from "../../assets/icons/search.svg";
import { InputProps } from "../../types/input";
import 'react-phone-input-2/lib/style.css'

type TextFieldProps = {
    title: string;
    placeholder: string;
    required?: boolean;
    type?: 'text' | 'number' | 'hidden';
    defaultValue?: string;
    size?: string;
    onChange?: (data : any) => void;
    errorMessage?: string;
    layoutGridColumnSpan?: string;
}

export function TextField({title, placeholder, required, type = 'text', defaultValue, size, onChange, errorMessage, layoutGridColumnSpan} : TextFieldProps){
    return (
        <Container sx={layoutGridColumnSpan ? {gridColumn: `span ${layoutGridColumnSpan}`} : {}}>
            <InputStyle value={defaultValue} type={type} placeholder={errorMessage || placeholder} placeholderOpacity={errorMessage ? 1 : 0.5} placeholderColor={errorMessage ? 'red' : globalSettings.Colors.bodyBlack} required={required} onChange={onChange} />
        </Container>
    )
}

type RoundedTextFieldProps = {
    placeholder: string;
    icon?: React.ReactNode;
    size?: string;
    onChange: (e:any) => void;
    width?: string;
};

export function RoundedTextField({placeholder, icon, size, onChange, width} : RoundedTextFieldProps){
    return (
        <RoundedInputContainer minWidth={width} width={width} >
            {icon || <SearchIcon />}
            <RoundedInputStyle placeholder={placeholder} onChange={(e)=>onChange(e)} />
        </RoundedInputContainer>
    )
}

type SelectProps = {
    title: string;
    options: {
        text: string;
        value: string;
    }[];
    required?: boolean;
    size?: string;
    onSelect?: (item:string) => void;
    onChange?: (data : any) => void;
    errorMessage?: string;
    layoutGridColumnSpan?: string;
}

export function SelectDropDown ({title, options, required, size, onSelect, onChange, errorMessage, layoutGridColumnSpan} : SelectProps) {
    const [selectedOption, setSelectedOption] = useState<string | null>(null)
    const [showSelect, setShowSelect] = useState<boolean>(false)
    const showSelectDropDown = () => {
        setShowSelect(true)
    }
    const selectOption = (item : string) => {
        setSelectedOption(item)
        setShowSelect(false)
        if(onSelect){
            onSelect(item)
        }
        if(onChange){
            onChange({target: {value: item}})
        }
    }
    const dropDownRef = useRef(null)
    useClickAway(dropDownRef, () => {
        setShowSelect(false)
    })
    return (
        <Container sx={layoutGridColumnSpan ? {gridColumn: `span ${layoutGridColumnSpan}`} : {}}>
            <Title>{title}{required?<Required>*</Required>:null}</Title>
            <SelectContainer onMouseDown={showSelectDropDown} ref={dropDownRef}>
                <SelectArrow selected={showSelect} />
                <SelectedOption>{selectedOption || <div style={errorMessage ? {opacity: 1, color: 'red'} : {opacity: 0.5}}>{errorMessage || 'Please Select'}</div>}</SelectedOption>
                {showSelect?
                    <SelectStyle defaultValue="">
                        {options.map((item, key) => (
                            <Option key={key} onClick={()=>selectOption(item.text)} selected={item.text===selectedOption}>{item.text}</Option>
                        ))}
                    </SelectStyle>
                :null}
            </SelectContainer>
        </Container>
    )
}

type RoundedSelectProps = RoundedSelectStyleProps & {
    firstItem?: {
        title: string;
        onClick: () => void;
    };
    placeholder?: string;
    options: {
        title: string;
        id: any;
    }[];
    optionBackgroundColor?: string;
    optionTextColor?: string;
    size?: string;
    onSelect?: (item:any) => void;
    selectwidth?: string;
    width?: string;
}

export function RoundedSelect ({selectwidth, firstItem, options, placeholder, activetextcolor, bordercolor, arrowcolor, optionBackgroundColor, optionTextColor, size, onSelect, width} : RoundedSelectProps) {
    const [selectedOption, setSelectedOption] = useState<{title: string, id: any} | null>(null)
    const [showSelect, setShowSelect] = useState<boolean>(false)
    const showSelectDropDown = () => {
        setShowSelect(true)
    }
    const selectOption = (item : {title: string; id: any}) => {
        setSelectedOption(item)
        if(onSelect){
            onSelect(item.id)
        }
        setShowSelect(false)
    }
    const dropDownRef = useRef(null)
    useClickAway(dropDownRef, () => {
        setShowSelect(false)
    })
    const firstItemClick = () => {
        if(firstItem){
            firstItem.onClick()
        }
        setSelectedOption(null)
        setShowSelect(false)
    }
    return (
        <RoundedSelectStyle selected={showSelect} width={width} minWidth={width} ref={dropDownRef} onMouseDown={showSelectDropDown} activetextcolor={activetextcolor} bordercolor={bordercolor} arrowcolor={arrowcolor}>
            <SelectArrow selected={showSelect} />
            <RoundedSelectedOption>{selectedOption?.title || placeholder}</RoundedSelectedOption>
            {showSelect?
                <RoundedSelectOptionsStyle defaultValue="">
                    {firstItem ? <RoundedOption backgroundColor={optionBackgroundColor} textcolor={optionTextColor} onClick={firstItemClick}>{firstItem.title}</RoundedOption> : null}
                    {options.map((item, key) => (
                        <RoundedOption backgroundColor={optionBackgroundColor} textcolor={optionTextColor} key={key} onClick={()=>selectOption(item)} selected={item.id===selectedOption?.id}>{item.title}</RoundedOption>
                    ))}
                </RoundedSelectOptionsStyle>
            :null}
        </RoundedSelectStyle>
    )
}

type TextAreaProps = {
    title: string;
    placeholder: string;
    required?: boolean;
    size?: string;
    onChange?: (data : any) => void;
    layoutGridColumnSpan?: string;
}

export function Textarea ({title, placeholder, required, size, onChange, layoutGridColumnSpan} : TextAreaProps) {
    return (
        <Container sx={layoutGridColumnSpan ? {gridColumn: `span ${layoutGridColumnSpan}`} : {}}>
            <TextareaStyle placeholder={placeholder} onChange={onChange} />
        </Container>
    )
}

type RadioProps = {
    options: {
        text: string;
        value: string;
    }[],
    name: string;
    size?: string;
    onChange?: (data : any) => void;
    layoutGridColumnSpan?: string;
}


export function RadioButtons ({options, name, size, onChange, layoutGridColumnSpan} : RadioProps) {    
    
    useEffect(() => {
        if(onChange){
            onChange({target: options[0]})
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [])

    let radio_styles = {
        gap: '3.3vw',
        padding: '0.2vw',
        margin: '0.1vw 0.6vw 0.1vw 1vw',
        height: '1.5vw',
        width: '1.5vw',
        fontSize: '0.9vw !important',
        margin2: '0 0 0 -1.5vw',
        marginTop: '0'
    }

    const isMobile = useResponsive('down', 768)

    if(isMobile){
        radio_styles = {
            gap: '7.5vw',
            padding: '0',
            margin: '0vw 3vw 0vw 0vw',
            height: '7vw',
            width: '7vw',
            fontSize: '3.8vw !important',
            margin2: '0 0 0 -1vw',
            marginTop: '5.5vw'
        }
    }else{
        radio_styles = {
            gap: '3.3vw',
            padding: '0.2vw',
            margin: '0.1vw 0.6vw 0.1vw 1vw',
            height: '1.5vw',
            width: '1.5vw',
            fontSize: '0.9vw !important',
            margin2: '0 0 0 -1.5vw',
            marginTop: '0'
        }
    }

    return (
        <RadioGroup
            aria-labelledby={name}
            defaultValue={options[0].value}
            name={name}
            row
            sx={{marginTop: radio_styles.marginTop, gap: radio_styles.gap, columnSpan: layoutGridColumnSpan || null}}
        >
        {options.map((item, index) => <FormControlLabel sx={{'& > span:first-of-type': {'&:hover': {backgroundColor: globalSettings.Colors.primaryLight1}, padding: radio_styles.padding, margin: radio_styles.margin, '& > svg': {height: radio_styles.height, width: radio_styles.width}}, '& > span:last-of-type': { fontSize: radio_styles.fontSize }, margin: radio_styles.margin2}} onChange={onChange} key={index} value={item.value} control={<Radio sx={{'&.Mui-checked':{color:"#66A4F9"}}} />} label={item.text} />)}
      </RadioGroup>
    )
}

type CheckBoxesProps = {
    label: string;
    options: {
        text: string;
        value: string;
    }[],
    required?: boolean;
    size?: string;
}

export function CheckBoxes ({label, options, required, size} : CheckBoxesProps) {
    return (
        <CheckBoxesContainer>
            <Title>{label}{required && <Required>*</Required>}</Title>
            <CheckBoxesWrapper>
                {options.map((item, index)=><FormControlLabel control={<Checkbox />} label={item.text} key={index} />)}
            </CheckBoxesWrapper>
        </CheckBoxesContainer>
    )
}

type HTMLBlockProps = {
    content: string;
    size?: string;
}

export function HTMLBlock ({content, size} : HTMLBlockProps) { 
    return (
        <HTMLBlockStyle dangerouslySetInnerHTML={{__html: content}} />
    )
}

export function Section ({size}:{size?: string}) {
    return <SectionLine />
}

type DateProps = {
    label: string;
    size?: string;
};

export function MultiSelect ({title, options, required, size, onSelect, onChange, errorMessage, layoutGridColumnSpan} : SelectProps) {
    const [showSelect, setShowSelect] = useState<boolean>(false)
    const showSelectDropDown = (e : React.MouseEvent) => {
        const target = e.target as HTMLElement;
        if(target){
            if(target.classList.contains('chip')){
                return
            }
        }
        setShowSelect(true)
    }
    const [selectedOptions, setSelectedOptions] = useState<string[]>([])
    const selectOption = (item : string) => {
        if(selectedOptions.includes(item)){
            const newSelectedOptions = selectedOptions.filter(option=>option!==item)
            setSelectedOptions(newSelectedOptions)
            if(onChange){
                onChange({target: {value: newSelectedOptions}})
            }
        }else{
            setSelectedOptions([...selectedOptions, item])
            if(onChange){
                onChange({target: {value: [...selectedOptions, item]}})
            }
        }
        setShowSelect(false)
    }
    const removeChip = (text : string) => {
        if(onChange){
            setSelectedOptions(selectedOptions.filter(item=>item!==text))
            onChange({target: {value: selectedOptions.filter(item=>item!==text).length === 0 ? null : selectedOptions.filter(item=>item!==text)}})
        }
    }
    const Chip = ({text} : {text: string}) => <ChipStyle className="chip" onClick={()=>removeChip(text)}><ChipText>{text}</ChipText><ChipX /></ChipStyle>
    const dropDownRef = useRef(null)
    useClickAway(dropDownRef, () => {
        setShowSelect(false)
    })
    return (
        <Container sx={layoutGridColumnSpan ? {gridColumn: `span ${layoutGridColumnSpan}`} : {}}>
            <Title>{title}{required?<Required>*</Required>:null}</Title>
            <SelectContainer onMouseDown={showSelectDropDown} ref={dropDownRef}>
                <SelectArrow selected={showSelect} />
                <MultiSelectedOption>{selectedOptions.length > 0 ? selectedOptions.map((item, index)=> (
                    <Chip text={item} key={index} />
                )) : <div style={{opacity: 0.5}}>Please Select</div>}</MultiSelectedOption>
                {showSelect?
                    <SelectStyle defaultValue="">
                        {options.map((item, key) => (
                            <Option key={key} onClick={()=>selectOption(item.text)} selected={selectedOptions.includes(item.text)}>{item.text}</Option>
                        ))}
                    </SelectStyle>
                :null}
            </SelectContainer>
        </Container>
    )
}

export function Date({ label, size }: DateProps) {
    return (
        <div>
            <LocalizationProvider>
                <DatePicker label={label} />
            </LocalizationProvider>
        </div>
    );
}  

export function Time({label, size} : DateProps) {
    return (
        <div> 
            <LocalizationProvider>
                <TimePicker label={label} />
                <style>
                    {`
                        .MuiButtonBase-root {
                            line-height: 1.5;
                        }
                    `}
                </style>
            </LocalizationProvider>
        </div>
    )
}

type AddressProps = {
    required?: boolean;
    inputs: {
        id: number;
        label: string;
        placeholder: string;
        name: string;
        autocompleteAttribute?: string;
    }[];
    onChange?: (data:any) => void;
}

type Suggestion = {
    description: string;
    place_id: string;
}  

type PlacesAutocompleteProps = {
    getInputProps: any;
    suggestions: Suggestion[];
    getSuggestionItemProps: any;
    loading: boolean;
}

export function Address({required, inputs, onChange} : AddressProps) {
    const [address, setAddress] = useState<string>('');
  
    const handleChange = (newAddress: string) => {
      setAddress(newAddress);
      onGlobalChange();
    };

    const inputMap = {
        address: 1,
        city: 2,
        state: 3,
        postcode: 4,
        country: 5
    }
  
    const handleSelect = (selectedAddress: string) => {
      geocodeByAddress(selectedAddress)
        .then((results: google.maps.GeocoderResult[]) => {
            const addressComponents = results[0].address_components;
            let addressLineOne = ''
            for (let i = 0; i < addressComponents.length; i+=1) {
                const component = addressComponents[i];
                const componentType = component.types[0];
                switch (componentType) {
                    case "street_number":
                        addressLineOne = `${addressLineOne} ${component.long_name}`
                    break;
                    case "route":
                        addressLineOne = `${addressLineOne} ${component.long_name}`
                    break;
                    case "establishment":
                        addressLineOne = `${addressLineOne} ${component.long_name}`
                    break;
                    case "locality":
                        addressLineOne = `${addressLineOne}, ${component.long_name}`
                    break;
                    case "administrative_area_level_1": {
                        const stateInputElem = document.getElementsByClassName('addressForm')[inputMap.state] as HTMLInputElement
                        if(stateInputElem){
                            stateInputElem.value = component.long_name
                        }
                    }
                    break;
                    case "country": {
                        const countryInputElem = document.getElementsByClassName('addressForm')[inputMap.country] as HTMLInputElement
                        if(countryInputElem){
                            countryInputElem.value = component.long_name
                        }
                    }
                    break;
                    case 'administrative_area_level_2': {
                      const cityInputElem = document.getElementsByClassName('addressForm')[inputMap.city] as HTMLInputElement;
                      if (cityInputElem) {
                        cityInputElem.value = component.short_name;
                      }
                      break;
                    }
                    case 'postal_code': {
                      const postalCodeInputElem = document.getElementsByClassName('addressForm')[inputMap.postcode] as HTMLInputElement;
                      if (postalCodeInputElem) {
                        postalCodeInputElem.value = component.long_name;
                      }
                      break;
                    }
                    default:
                    break;
                }
                const addressInputElem = document.getElementsByClassName('addressForm')[inputMap.address] as HTMLInputElement
                if(addressInputElem){
                    setAddress(addressLineOne)
                }
                onGlobalChange();
            }

        })
        .catch((error: any) => console.error('Error', error));
    };

    const onGlobalChange = () => {
        const elem = document.getElementsByClassName('addressForm') as HTMLCollectionOf<HTMLInputElement>
        if(onChange){
            setTimeout(() => {
                const addressMap = {
                    1: elem[inputMap.address].value,
                    3: elem[inputMap.city].value,
                    4: elem[inputMap.state].value,
                    5: elem[inputMap.postcode].value,
                    6: elem[inputMap.country].value
                }
                onChange({target: {value: addressMap}})
            }, 300)
        }
    }
  
    return (
        <>
        {inputs.map(({id, label, placeholder, name}, index) => {
            if(index === 0){
                return (
                    <PlacesAutocomplete
                        key={index}
                        value={address}
                        onChange={handleChange}
                        onSelect={handleSelect}
                    >
                    {({ getInputProps, suggestions, getSuggestionItemProps }:PlacesAutocompleteProps) => (
                        <AddressContainer sx={{gridColumn: 'span 6'}}>
                            <Container>
                                <Title>{label}{required && <Required>*</Required>}</Title>
                                <InputStyle className="addressForm" {...getInputProps()} type='text' placeholder={placeholder} required={required} />
                            </Container>
                            <AddressOptions>
                                {suggestions?.map((suggestion: Suggestion, key:number) => {
                                const style = { cursor: 'pointer' };
                                return (
                                    <AddressOption
                                        {...getSuggestionItemProps(suggestion, {
                                            style,
                                        })}
                                        key={key}
                                    >
                                        {suggestion.description}
                                    </AddressOption>
                                );
                                })}
                            </AddressOptions>
                        </AddressContainer>
                    )}
                    </PlacesAutocomplete>
                )
            }
            return (
                <Container key={index} sx={{gridColumn: 'span 6'}}>
                    <Title>{label}{required && <Required>*</Required>}</Title>
                    <InputStyle onChange={onGlobalChange} className="addressForm" type='text' placeholder={placeholder} required={required} />
                </Container>
            )
        })}
        </>
    );
}
  
type PhoneProps = {
    label: string;
    required?: boolean;
    placeholder?: string;
    size?: string;
    onChange?: (data : any) => void;
}

export function Phone({label, required, placeholder, size, onChange} : PhoneProps) {
    const [value, setValue] = useState('')
    const setPhone = (data : any) => {
        setValue(data)
        if(onChange){
            onChange(data)
        }
    }
    return (
        <PhoneContainer>
            {label!==''?<Title>{label}{required && <Required>*</Required>}</Title>:null}
            <PhoneInput country='au' value={value} onChange={setPhone} placeholder={placeholder} />
        </PhoneContainer>
    )
}

type EmailProps = {
    title: string;
    placeholder: string;
    required?: boolean;
    size?: string;
    onChange?: (data : any) => void;
    errorMessage?: string;
    layoutGridColumnSpan?: string;
} 

export function Email({title, placeholder, required, size, onChange, errorMessage, layoutGridColumnSpan} : EmailProps) {
    return (
        <Container sx={layoutGridColumnSpan ? {gridColumn: `span ${layoutGridColumnSpan}`} : {}}>
            <InputStyle id='email' onChange={onChange} type='email' placeholder={errorMessage || placeholder} placeholderOpacity={errorMessage ? 1 : 0.5} placeholderColor={errorMessage ? 'red' : globalSettings.Colors.bodyBlack} required={required} />
        </Container>
    )
}

export function FileUpload({size} : {size?: string}) {

    const onFileUpload = (file: File | null) => {
        console.log(`uploaded ${file?.name}`)
    }

    const [selectedFile, setSelectedFile] = useState<File | null>(null);
  
    const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
      const file = event.target?.files ? event.target.files[0] : null;
      setSelectedFile(file);
      onFileUpload(file);
    };

    const fileInputRef = useRef<HTMLInputElement | null>(null);

    const onUploadButtonClick = () => {
        if(fileInputRef.current){
            fileInputRef.current.click()
        }
    }
  
    return (
        <UploadButton onClick={onUploadButtonClick}>
          <UploadIcon />
          <UploadText>{selectedFile ? selectedFile.name : 'Upload File'}</UploadText>
          <FileInput ref={fileInputRef} type="file" onChange={handleFileChange} />
        </UploadButton>
    );
}

export function CaptchaComponent () {
    const setCaptcha = useSetRecoilState(captchaAtom)
    const onCaptchaChange = useCallback(async (e : any) => {

        const url = 'https://automation.orangedigital.au/api/v1.0/pilot-partners-development/recaptcha';
      
        try {
          const response = await fetch(url, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: new URLSearchParams({
                response: e, 
              })
          });
      
          const data = await response.json();
          const { success, score } = data;
      
          if (success && score >= 0.5) {
            setCaptcha(true)
          } else {
            setCaptcha(false)
          }

        } catch (error) {
          setCaptcha(false)
        }
          
          // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [])
    return (
        <>
            <div id='captcha' style={{gridColumn: 'span 12'}} />
            <GoogleReCaptchaProvider 
                reCaptchaKey="6LeJa1UnAAAAAI3kR1QWAcsaSV4ugwjvrZFMiuzP"
                container={{
                    element: "captcha",
                    parameters: {
                        theme: 'light',
                    }
                }}
            >
                <GoogleReCaptcha
                    onVerify={onCaptchaChange}
                />
            </GoogleReCaptchaProvider>
        </>
    )
}


type WebsiteProps = {
    title: string;
    placeholder: string;
    required?: boolean;
    size?: string;
} 

export function Website({title, placeholder, required, size} : WebsiteProps) {
    return (
        <Container>
            <Title>{title}{required && <Required>*</Required>}</Title>
            <InputStyle type='text' placeholder={placeholder} required={required} />
        </Container>
    )
}


type NameProps = {
    required?: boolean;
    inputs: {
        id: number;
        label: string;
        placeholder: string;
        name: string;
        autocompleteAttribute?: string;
        choices?: {text: string, value: string}[]
    }[];
}

export function Name({required, inputs} : NameProps) {
    return (
        <>
            {inputs.map(({id, label, placeholder, name, choices}, index) => (
                    <Container key={index}>
                        {!choices?<Title>{label}{required && <Required>*</Required>}</Title>:null}
                        {choices?<SelectDropDown title={label} options={choices} />:<InputStyle id={name} type='text' placeholder={placeholder} required={required} />}
                    </Container>
                )
            )}
        </>
    );
}

type ListProps = {
    label: string;
    placeholder?: string;
    id: number;
    formId: number;
    size?: string;
}

export function List({label, placeholder, id, formId, size} : ListProps) {
    const [listItems, setListItems] = useState<string[]>([])
    const listInputRef = useRef<HTMLInputElement>(null)
    const addListItem = () => {
        if(listInputRef.current && listInputRef.current.value.length > 0){
            setListItems([...listItems, listInputRef.current.value])
        }
    }
    const onKeyDown = (e : React.KeyboardEvent) => {
        if(e.key === 'Enter'){
            addListItem()
        }
    }
    const removeListItem = (item: string) => {
        const newListItems = listItems.filter(e=>e!==item)
        setListItems(newListItems)
    }
    return (
        <ListContainer>
            <Title>{label}</Title>
            <ListInputContainer>
                <ListInput onKeyDown={onKeyDown} placeholder={placeholder} ref={listInputRef} />
                <AddListItemButton onMouseDown={addListItem} />
            </ListInputContainer>
            <ListItemsContainer>
                {listItems.map((item, index) => (
                    <ListItem key={index}>
                        <ListItemText>{item}</ListItemText>
                        <RemoveListItemButton onClick={()=>removeListItem(item)} />
                    </ListItem>
                ))}
            </ListItemsContainer>
        </ListContainer>
    )
}

type ConsetProps = {
    id: number;
    formId: number;
    label: string;
    inputs?: {
        id: string;
        label: string;
        name?: string;
        isHidden?: boolean;
    }[];
    checkboxLabel: string;
    isRequired?: boolean;
    size?: string;
}

export function Consent ({label, id, formId, inputs, checkboxLabel, isRequired = true, size} : ConsetProps) {
    return (
        <ConsetContainer>
            <Title>{label}{isRequired && <Required>*</Required>}</Title>
            <FormControlLabel control={<Checkbox />} label={checkboxLabel} />
        </ConsetContainer>
    )
}

type PageProps = {
    nextButton: {
        text: string;
    };
    previousButton: {
        text: string;
    };
    goToNextPage?: () => void;
    goToPreviousPage?: () => void;
    isFirstPage?: boolean;
    isLastPage?: boolean;
}

export function Page ({nextButton, previousButton, goToNextPage, goToPreviousPage, isFirstPage, isLastPage} : PageProps) {
    return (
        <PageNavigationContainer>
            {!isFirstPage?<PageNavigation onClick={goToPreviousPage}>{previousButton.text}</PageNavigation>:null}
            {!isLastPage?<PageNavigation onClick={goToNextPage}>{nextButton.text}</PageNavigation>:null}
        </PageNavigationContainer>
    )
}
  
export default function Input ({type, label, placeholder, isRequired, choices, defaultValue, content, inputs, id, formId, checkboxLabel, size, nextButton, previousButton, goToNextPage, goToPreviousPage, isFirstPage, isLastPage, onChange, errorMessage, layoutGridColumnSpan} : InputProps) {
    switch (type) {
        case 'text':
            if(placeholder){
                return <TextField title={label} placeholder={placeholder} required={isRequired} layoutGridColumnSpan={layoutGridColumnSpan} onChange={onChange} errorMessage={errorMessage} />
            }
            throw new Error('placeholder is invalid for text');
        case 'textarea':
            if(placeholder){
                return <Textarea title={label} placeholder={placeholder} required={isRequired} layoutGridColumnSpan={layoutGridColumnSpan} onChange={onChange} />
            }
            throw new Error('placeholder is invalid for textarea');
        case 'select':
            if(choices){
                return <SelectDropDown title={label} required={isRequired} options={choices} layoutGridColumnSpan={layoutGridColumnSpan} onChange={onChange} errorMessage={errorMessage} />
            }
            throw new Error('choices is invalid for select');
        case 'multiselect':
            if(choices){
                return <MultiSelect title={label} required={isRequired} options={choices} layoutGridColumnSpan={layoutGridColumnSpan} onChange={onChange} errorMessage={errorMessage} />
            }
            throw new Error('choices is invalid for multiselect');
        case 'number':
            if(placeholder){
                return <TextField title={label} placeholder={placeholder} required={isRequired} type="number" layoutGridColumnSpan={layoutGridColumnSpan} />
            }
            throw new Error('placeholder is invalid for number');
        case 'checkbox':
            if(choices){
                return null
            }
            throw new Error('choices is invalid for checkbox');
        case 'radio':
            if(choices){
                return <RadioButtons name={label} options={choices} onChange={onChange} />
            }
            throw new Error('choices is invalid for radio');
        case 'hidden':
            return <TextField title={label} placeholder='' type="hidden" defaultValue={defaultValue} />
        case 'html':
            if(content){
                return <HTMLBlock content={content} />
            }
            throw new Error('content is invalid for html');
        case 'section':
            return <Section />
        case 'date':
            return <Date label={label} />
        case 'time':
            return <Time label={label} />
        case 'address':
            if(inputs){
                return <Address inputs={inputs} onChange={onChange} />
            }
            throw new Error('inputs is invalid for address');
        case 'phone':
            return <Phone label={label} onChange={onChange} />
        case 'email':
            if(placeholder){
                return <Email title={label} placeholder={placeholder} required={isRequired} onChange={onChange} errorMessage={errorMessage} layoutGridColumnSpan={layoutGridColumnSpan} />
            }
            throw new Error('placeholder is invalid for email');
        case 'fileupload':
            return <FileUpload />
        case 'captcha':
            return <CaptchaComponent />
        case 'website':
            if(placeholder){
                return <Website title={label} placeholder={placeholder} required={isRequired} />
            }
            throw new Error('placeholder is invalid for website');
        case 'name':
            if(inputs){
                return <Name inputs={inputs} />
            }
            throw new Error('inputs is invalid for name');
        case 'list':
            if(placeholder){
                return <List label={label} placeholder={placeholder} id={id} formId={formId} />
            }
            throw new Error('placeholder is invalid for list');
        case 'consent':
            if(checkboxLabel){
                return <Consent label={label} id={id} formId={formId} checkboxLabel={checkboxLabel} isRequired={isRequired} />
            }
            throw new Error('checkboxLabel is invalid for consent');
        case 'page':
            if(nextButton && previousButton && goToNextPage && goToPreviousPage && isFirstPage!==undefined && isLastPage!==undefined){
                return <Page nextButton={nextButton} previousButton={previousButton} goToNextPage={goToNextPage} goToPreviousPage={goToPreviousPage} isFirstPage={isFirstPage} isLastPage={isLastPage} />
            }
            throw new Error('nextButton or previousButton or goToNextPage or goToPreviousPage or isFirstPage or isLastPage is invalid for page');
        default:
            throw new Error('type is invalid for input');
    }
}