1
- import React
2
- from 'react'
1
+ import React , { useState , useRef } from 'react'
3
2
import PropTypes from 'prop-types'
3
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
4
4
import {
5
+ Alert ,
6
+ Button ,
7
+ CloseButton ,
8
+ Form ,
9
+ InputGroup ,
10
+ ListGroup ,
5
11
Offcanvas ,
6
12
Tab ,
7
13
Tabs ,
8
14
} from 'react-bootstrap'
9
15
import FilesTable from '../../../components/FilesTable/FilesTable'
10
- import { allowNull } from '../../../resources/utilityFunctions'
16
+ import { allowNull , apiV2CompatibleStrings , convertToBase64 } from '../../../resources/utilityFunctions'
11
17
12
- const ViewFiles = ( { backgroundColor, initialFiles, handleClose } ) => {
18
+ const ViewFiles = ( { backgroundColor, files, handleClose, onSubmit } ) => {
19
+ const fileRef = useRef ( null )
20
+ const [ tempFiles , setTempFiles ] = useState ( [ ] )
21
+ const [ showSuccessAlert , setShowSuccessAlert ] = useState ( false )
13
22
const documentTabs = [
14
23
{
15
24
eventKey : 'files' ,
@@ -23,16 +32,83 @@ const ViewFiles = ({ backgroundColor, initialFiles, handleClose }) => {
23
32
} ,
24
33
]
25
34
35
+ const handleAddFile = async ( event ) => {
36
+ event . preventDefault ( )
37
+ try {
38
+ // "event.target.files" returns a FileList, which looks like an array but does not respond to array methods
39
+ // except "length". we are using the spread syntax to set "files" to be an iterable array
40
+ const fileArray = [ ...event . target . files ]
41
+ const newBase64Files = await Promise . all ( convertToBase64 ( fileArray ) )
42
+ const newFiles = fileArray . map ( ( file , index ) => ( { [ file . name ] : newBase64Files [ index ] } ) )
43
+ setTempFiles ( [ ...tempFiles , ...newFiles ] )
44
+ if ( showSuccessAlert ) {
45
+ setShowSuccessAlert ( false )
46
+ }
47
+ fileRef . current . value = ''
48
+ } catch ( error ) {
49
+ throw new Error ( error )
50
+ }
51
+ }
52
+
53
+ const handleSubmit = async ( event ) => {
54
+ event . preventDefault ( )
55
+ await onSubmit ( { files : apiV2CompatibleStrings ( [ ...tempFiles ] ) } )
56
+ if ( tempFiles . length > 0 ) {
57
+ setShowSuccessAlert ( true )
58
+ setTempFiles ( [ ] )
59
+ }
60
+ }
61
+
62
+ const handleDeleteTempFile = ( file ) => {
63
+ const remainingFiles = tempFiles . filter ( ( obj ) => obj !== file )
64
+ setTempFiles ( remainingFiles )
65
+ }
66
+
26
67
return (
27
68
< Offcanvas show onHide = { handleClose } placement = 'end' scroll = 'true' >
28
69
< Offcanvas . Header className = { `d-flex border-bottom px-3 py-2 bg-${ backgroundColor } -8` } closeButton >
29
70
< Offcanvas . Title > Documents</ Offcanvas . Title >
30
71
</ Offcanvas . Header >
31
72
< Offcanvas . Body className = 'border rounded p-2 m-3' >
73
+ < Form >
74
+ < h6 className = 'mt-3' > Upload Additional Documents</ h6 >
75
+ < InputGroup controlId = 'attachments' className = 'mb-3' >
76
+ < Form . Control
77
+ multiple
78
+ type = 'file'
79
+ onChange = { handleAddFile }
80
+ ref = { fileRef }
81
+ />
82
+ < Button
83
+ variant = 'outline-primary'
84
+ onClick = { handleSubmit }
85
+ type = 'submit'
86
+ >
87
+ < FontAwesomeIcon icon = 'fa-upload' />
88
+ </ Button >
89
+ </ InputGroup >
90
+ </ Form >
91
+ < ListGroup variant = 'flush' >
92
+ { tempFiles . map ( ( file ) => {
93
+ const fileName = Object . keys ( file ) [ 0 ]
94
+ return (
95
+ < ListGroup . Item key = { fileName } className = 'd-flex align-items-center' >
96
+ < span > { fileName } </ span >
97
+ < CloseButton onClick = { ( ) => handleDeleteTempFile ( file ) } className = 'ms-auto' />
98
+ </ ListGroup . Item >
99
+ )
100
+ } ) }
101
+ { showSuccessAlert
102
+ && (
103
+ < Alert variant = 'success' onClose = { ( ) => setShowSuccessAlert ( false ) } dismissible >
104
+ Your files have been uploaded successfully. It may take some time for them to appear below.
105
+ </ Alert >
106
+ ) }
107
+ </ ListGroup >
32
108
< Tabs defaultActiveKey = 'files' id = 'document-tabs' justify fill >
33
109
{ documentTabs && documentTabs . map ( ( tab ) => {
34
110
const { eventKey, title, status } = tab
35
- const filteredFiles = initialFiles . filter ( ( f ) => ( status === f . status ) || ( status === 'Other File' && f . status === null ) )
111
+ const filteredFiles = files . filter ( ( f ) => ( status === f . status ) || ( status === 'Other File' && f . status === null ) )
36
112
return (
37
113
< Tab
38
114
eventKey = { eventKey }
@@ -43,6 +119,7 @@ const ViewFiles = ({ backgroundColor, initialFiles, handleClose }) => {
43
119
< FilesTable
44
120
files = { filteredFiles }
45
121
status = { status }
122
+ handleDeleteFile = { handleDeleteTempFile }
46
123
/>
47
124
</ Tab >
48
125
)
@@ -55,7 +132,7 @@ const ViewFiles = ({ backgroundColor, initialFiles, handleClose }) => {
55
132
56
133
ViewFiles . propTypes = {
57
134
backgroundColor : PropTypes . string ,
58
- initialFiles : PropTypes . arrayOf (
135
+ files : PropTypes . arrayOf (
59
136
PropTypes . shape ( {
60
137
contentLength : PropTypes . string . isRequired ,
61
138
contentType : PropTypes . string . isRequired ,
@@ -69,10 +146,11 @@ ViewFiles.propTypes = {
69
146
} ) ,
70
147
) . isRequired ,
71
148
handleClose : PropTypes . func . isRequired ,
149
+ onSubmit : PropTypes . func . isRequired ,
72
150
}
73
151
74
152
ViewFiles . defaultProps = {
75
- backgroundColor : 'secondary'
153
+ backgroundColor : 'secondary' ,
76
154
}
77
155
78
156
export default ViewFiles
0 commit comments