UNPKG

@scientist-softserv/webstore-component-library

Version:

A React component library intended for use with WebStore applications

123 lines (112 loc) 4.34 kB
import React, { useState, useRef } from 'react' import PropTypes from 'prop-types' import { Card, CloseButton, Form, ListGroup, } from 'react-bootstrap' import { addDays, apiV2CompatibleStrings, convertToBase64 } from '../../resources/utilityFunctions' const AdditionalInfo = ({ backgroundColor, defaultRequiredDate, disabled, updateRequestForm, }) => { const [showProposalDate, setShowProposalDate] = useState(true) const [files, setFiles] = useState([]) const fileRef = useRef(null) const oneDayFromNow = addDays((new Date()), 1).toISOString().slice(0, 10) const handleChange = (value) => { updateRequestForm(value, 'proposedDeadline') } const handleAddFile = async (event) => { event.preventDefault() try { // "event.target.files" returns a FileList, which looks like an array but does not respond to array methods // except "length". we are using the spread syntax to set "files" to be an iterable array const fileArray = [...event.target.files] const newBase64Files = await Promise.all(convertToBase64(fileArray)) const newFiles = fileArray.map((file, index) => ({ [file.name]: newBase64Files[index] })) setFiles([...files, ...newFiles]) updateRequestForm(apiV2CompatibleStrings([...files, ...newFiles]), 'attachments') fileRef.current.value = '' } catch (error) { throw new Error(error) } } const handleDeleteFile = (file) => { const remainingFiles = files.filter((obj) => obj !== file) setFiles(remainingFiles) updateRequestForm(apiV2CompatibleStrings(remainingFiles), 'attachments') } return ( <Card className='mb-4'> <Card.Header className={`h3 bg-${backgroundColor}`}>Additional Information</Card.Header> <Card.Body> {showProposalDate && ( <Form.Group className='mb-3' controlId='required-by' > <Form.Label>Proposals Required By:</Form.Label> <Form.Control className='prevent-validation-styles' type='date' min={oneDayFromNow} defaultValue={defaultRequiredDate} placeholder='Proposals Required By' disabled={(showProposalDate === false) || disabled} onChange={showProposalDate && ((e) => handleChange(e.target.value))} required /> <Form.Control.Feedback type='invalid'> Please select a date when you will need your proposal, or check the box below. </Form.Control.Feedback> </Form.Group> )} <Form.Group className='mb-3' controlId='open-proposal-due-date' > <Form.Check className='prevent-validation-styles' disabled={disabled} type='checkbox' label='Proposals can be submitted at any time.' onChange={() => { setShowProposalDate(!showProposalDate) if (showProposalDate) handleChange('') }} /> </Form.Group> {/* TODO(summercook): figure out how these attachments will be saved. Currently we have an open question in slack */} <Form.Group controlId='attachments' className='mb-3'> <Form.Label>Attachments:</Form.Label> <Form.Control className='prevent-validation-styles' disabled={disabled} multiple type='file' onChange={handleAddFile} ref={fileRef} /> </Form.Group> <ListGroup variant='flush'> {files.map((file) => { const fileName = Object.keys(file)[0] return ( <ListGroup.Item key={fileName} className='d-flex align-items-center'> <span>{fileName}</span> <CloseButton onClick={() => handleDeleteFile(file)} className='ms-auto' /> </ListGroup.Item> ) })} </ListGroup> </Card.Body> </Card> ) } AdditionalInfo.propTypes = { backgroundColor: PropTypes.string, updateRequestForm: PropTypes.func.isRequired, disabled: PropTypes.bool.isRequired, } AdditionalInfo.defaultProps = { backgroundColor: 'light', } export default AdditionalInfo