5
5
FormControl ,
6
6
HelpBlock
7
7
} from '@freecodecamp/react-bootstrap' ;
8
- import { findIndex , find , isEqual , omit } from 'lodash-es' ;
8
+ import { findIndex , find , isEqual } from 'lodash-es' ;
9
9
import { nanoid } from 'nanoid' ;
10
- import React , { Component , FormEvent } from 'react' ;
10
+ import React , { Component } from 'react' ;
11
11
import { TFunction , withTranslation } from 'react-i18next' ;
12
12
import isURL from 'validator/lib/isURL' ;
13
13
@@ -16,10 +16,8 @@ import { hasProtocolRE } from '../../utils';
16
16
import { FullWidthRow , ButtonSpacer , Spacer } from '../helpers' ;
17
17
import BlockSaveButton from '../helpers/form/block-save-button' ;
18
18
import SectionHeader from './section-header' ;
19
- import PreventableButton from './PreventableButton' ;
20
19
21
- type PortfolioValues = {
22
- isSaved : boolean ;
20
+ type PortfolioItem = {
23
21
id : string ;
24
22
description : string ;
25
23
image : string ;
@@ -28,38 +26,32 @@ type PortfolioValues = {
28
26
} ;
29
27
30
28
type PortfolioProps = {
31
- isSaved : boolean ;
32
29
picture ?: string ;
33
- portfolio : PortfolioValues [ ] ;
30
+ portfolio : PortfolioItem [ ] ;
34
31
t : TFunction ;
35
- updatePortfolio : ( obj : { portfolio : PortfolioValues [ ] } ) => void ;
32
+ updatePortfolio : ( obj : { portfolio : PortfolioItem [ ] } ) => void ;
36
33
username ?: string ;
37
34
} ;
38
35
39
36
type PortfolioState = {
40
- portfolio : PortfolioValues [ ] ;
37
+ portfolio : PortfolioItem [ ] ;
38
+ unsavedItemId : string | null ;
41
39
} ;
42
40
43
- function createEmptyPortfolio ( ) {
41
+ function createEmptyPortfolioItem ( ) : PortfolioItem {
44
42
return {
45
43
id : nanoid ( ) ,
46
44
title : '' ,
47
45
description : '' ,
48
46
url : '' ,
49
- image : '' ,
50
- isSaved : false
47
+ image : ''
51
48
} ;
52
49
}
53
50
54
51
function createFindById ( id : string ) {
55
- return ( p : PortfolioValues ) => p . id === id ;
52
+ return ( p : PortfolioItem ) => p . id === id ;
56
53
}
57
54
58
- const mockEvent = {
59
- // eslint-disable-next-line @typescript-eslint/no-empty-function
60
- preventDefault ( ) { }
61
- } ;
62
-
63
55
class PortfolioSettings extends Component < PortfolioProps , PortfolioState > {
64
56
static displayName : string ;
65
57
constructor ( props : PortfolioProps ) {
@@ -68,7 +60,8 @@ class PortfolioSettings extends Component<PortfolioProps, PortfolioState> {
68
60
const { portfolio = [ ] } = props ;
69
61
70
62
this . state = {
71
- portfolio : [ ...portfolio ]
63
+ portfolio : [ ...portfolio ] ,
64
+ unsavedItemId : null
72
65
} ;
73
66
}
74
67
@@ -91,35 +84,33 @@ class PortfolioSettings extends Component<PortfolioProps, PortfolioState> {
91
84
} ) ;
92
85
} ;
93
86
94
- handleSubmit = ( e : React . FormEvent ) => {
87
+ handleSubmit = ( e : React . FormEvent < HTMLFormElement > , id : string ) => {
95
88
e . preventDefault ( ) ;
96
- const target = e . target as HTMLInputElement ;
97
- const id = target ?. id || undefined ;
98
- const { updatePortfolio } = this . props ;
99
- let { portfolio } = this . state ;
100
- if ( id ) {
101
- portfolio = portfolio . map ( item =>
102
- item . id === id ? { ...item , isSaved : true } : item
103
- ) ;
104
- this . setState ( {
105
- portfolio
106
- } ) ;
89
+ this . updateItem ( id ) ;
90
+ } ;
91
+
92
+ updateItem = ( id : string ) => {
93
+ const { portfolio, unsavedItemId } = this . state ;
94
+ if ( unsavedItemId === id ) {
95
+ this . setState ( { unsavedItemId : null } ) ;
107
96
}
108
- return updatePortfolio ( { portfolio } ) ;
97
+ this . props . updatePortfolio ( { portfolio } ) ;
109
98
} ;
110
99
111
100
handleAdd = ( ) => {
112
- return this . setState ( state => ( {
113
- portfolio : [ createEmptyPortfolio ( ) , ...state . portfolio ]
101
+ const item = createEmptyPortfolioItem ( ) ;
102
+ this . setState ( state => ( {
103
+ portfolio : [ item , ...state . portfolio ] ,
104
+ unsavedItemId : item . id
114
105
} ) ) ;
115
106
} ;
116
107
117
108
handleRemoveItem = ( id : string ) => {
118
- return this . setState (
109
+ this . setState (
119
110
state => ( {
120
111
portfolio : state . portfolio . filter ( p => p . id !== id )
121
112
} ) ,
122
- ( ) => this . handleSubmit ( mockEvent as FormEvent < Element > )
113
+ ( ) => this . updateItem ( id )
123
114
) ;
124
115
} ;
125
116
@@ -131,7 +122,7 @@ class PortfolioSettings extends Component<PortfolioProps, PortfolioState> {
131
122
return false ;
132
123
}
133
124
const edited = find ( portfolio , createFindById ( id ) ) ;
134
- return isEqual ( omit ( original , [ 'isSaved' ] ) , omit ( edited , [ 'isSaved' ] ) ) ;
125
+ return isEqual ( original , edited ) ;
135
126
} ;
136
127
137
128
// TODO: Check if this function is required or not
@@ -211,9 +202,9 @@ class PortfolioSettings extends Component<PortfolioProps, PortfolioState> {
211
202
}
212
203
213
204
renderPortfolio = (
214
- portfolio : PortfolioValues ,
205
+ portfolio : PortfolioItem ,
215
206
index : number ,
216
- arr : PortfolioValues [ ]
207
+ arr : PortfolioItem [ ]
217
208
) => {
218
209
const { t } = this . props ;
219
210
const { id, title, description, url, image } = portfolio ;
@@ -230,7 +221,7 @@ class PortfolioSettings extends Component<PortfolioProps, PortfolioState> {
230
221
return (
231
222
< div key = { id } >
232
223
< FullWidthRow >
233
- < form id = { id } onSubmit = { this . handleSubmit } >
224
+ < form onSubmit = { e => this . handleSubmit ( e , id ) } >
234
225
< FormGroup
235
226
controlId = { `${ id } -title` }
236
227
validationState = {
@@ -327,7 +318,7 @@ class PortfolioSettings extends Component<PortfolioProps, PortfolioState> {
327
318
328
319
render ( ) {
329
320
const { t } = this . props ;
330
- const { portfolio = [ ] } = this . state ;
321
+ const { portfolio = [ ] , unsavedItemId } = this . state ;
331
322
return (
332
323
< section id = 'portfolio-settings' >
333
324
< SectionHeader > { t ( 'settings.headings.portfolio' ) } </ SectionHeader >
@@ -338,11 +329,16 @@ class PortfolioSettings extends Component<PortfolioProps, PortfolioState> {
338
329
</ FullWidthRow >
339
330
< FullWidthRow >
340
331
< ButtonSpacer />
341
- < PreventableButton
342
- handleAdd = { this . handleAdd }
343
- t = { t }
344
- portfolio = { portfolio }
345
- />
332
+ < Button
333
+ block = { true }
334
+ bsSize = 'lg'
335
+ bsStyle = 'primary'
336
+ disabled = { unsavedItemId !== null }
337
+ onClick = { this . handleAdd }
338
+ type = 'button'
339
+ >
340
+ { t ( 'buttons.add-portfolio' ) }
341
+ </ Button >
346
342
</ FullWidthRow >
347
343
< Spacer size = { 2 } />
348
344
{ portfolio . length ? portfolio . map ( this . renderPortfolio ) : null }
0 commit comments