@scientist-softserv/webstore-component-library
Version:
A React component library intended for use with WebStore applications
123 lines (112 loc) • 4.34 kB
JSX
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