1
- import { useState } from 'react' ;
2
- import { useDispatch , useSelector } from 'react-redux' ;
3
- import { Container , Row , Form } from 'react-bootstrap' ;
4
- import { useNavigate } from 'react-router-dom' ;
5
- import { t } from '../utils' ;
6
- import { ArrayInput } from '../controls/form-controls/inputs/ArrayInput' ;
7
- import { deleteProject , saveProject } from '../../actions' ;
8
- import { StickyFooter } from '../controls/other/StickyFooter' ;
9
- import { BusyButton } from '../controls/form-controls/BusyButton' ;
10
- import { IProjectModel , ProjectClientInvoiceLine } from './models/IProjectModel' ;
11
- import { getNewProject , getNewProjectEndCustomer } from './models/getNewProject' ;
12
- import { ConfacState } from '../../reducers/app-state' ;
13
- import { getDefaultProjectMonthConfig } from './models/ProjectMonthModel' ;
14
- import { useDocumentTitle } from '../hooks/useDocumentTitle' ;
15
- import { getNewClient } from '../client/models/getNewClient' ;
16
- import { getNewConsultant } from '../consultant/models/getNewConsultant' ;
17
- import { Audit } from '../admin/audit/Audit' ;
18
- import { CopyProject } from './CopyProject' ;
19
- import { Claim } from '../users/models/UserModel' ;
20
- import { useParams } from 'react-router-dom' ;
21
- import { Col } from 'react-bootstrap' ;
1
+ import { useEffect , useState } from 'react' ;
2
+ import { useDispatch , useSelector } from 'react-redux' ;
3
+ import { Container , Row , Form , Col } from 'react-bootstrap' ;
4
+ import { useNavigate , useParams } from 'react-router-dom' ;
5
+ import { t } from '../utils' ;
6
+ import { ArrayInput } from '../controls/form-controls/inputs/ArrayInput' ;
7
+ import { deleteProject , saveProject } from '../../actions' ;
8
+ import { StickyFooter } from '../controls/other/StickyFooter' ;
9
+ import { BusyButton } from '../controls/form-controls/BusyButton' ;
10
+ import { IProjectModel , ProjectClientInvoiceLine } from './models/IProjectModel' ;
11
+ import { getNewProject , getNewProjectEndCustomer } from './models/getNewProject' ;
12
+ import { ConfacState } from '../../reducers/app-state' ;
13
+ import { getDefaultProjectMonthConfig } from './models/ProjectMonthModel' ;
14
+ import { useDocumentTitle } from '../hooks/useDocumentTitle' ;
15
+ import { Audit } from '../admin/audit/Audit' ;
16
+ import { CopyProject } from './CopyProject' ;
17
+ import { Claim } from '../users/models/UserModel' ;
22
18
import { SingleContractIcon } from "../client/contract/SingleContractIcon" ;
23
- import { EnhanceWithConfirmation } from '../enhancers/EnhanceWithConfirmation' ;
24
- import { Button } from '../controls/form-controls/Button' ;
25
- import { isDateIntervalValid } from '../controls/other/ProjectValidator' ;
19
+ import { EnhanceWithConfirmation } from '../enhancers/EnhanceWithConfirmation' ;
20
+ import { Button } from '../controls/form-controls/Button' ;
21
+ import { isDateIntervalValid } from '../controls/other/ProjectValidator' ;
26
22
import useEntityChangedToast from '../hooks/useEntityChangedToast' ;
27
- import { projectFormConfigClient , projectFormConfigEndCustomer } from './models/ProjectFormConfig' ;
23
+ import { getProjectFormConfig } from './models/ProjectFormConfig' ;
28
24
29
25
30
26
const ConfirmationButton = EnhanceWithConfirmation ( Button ) ;
31
27
32
28
33
- export const EditProject = ( ) => {
34
- const dispatch = useDispatch ( ) ;
35
- const navigate = useNavigate ( ) ;
29
+ const useProjectState = ( ) => {
36
30
const params = useParams ( ) ;
37
- const model = useSelector ( ( state : ConfacState ) => state . projects . find ( c => c . _id === params . id ) ) ;
31
+ const storeProject = useSelector ( ( state : ConfacState ) => state . projects . find ( c => c . _id === params . id ) ) ;
32
+
38
33
const consultants = useSelector ( ( state : ConfacState ) => state . consultants ) ;
39
- const [ project , setProject ] = useState < IProjectModel > ( model || getNewProject ( ) ) ;
40
- const consultant = useSelector ( ( state : ConfacState ) => state . consultants . find ( x => x . _id === project . consultantId ) || getNewConsultant ( ) ) ;
34
+ const [ project , setSimpleProject ] = useState < IProjectModel > ( storeProject || getNewProject ( ) ) ;
41
35
const clients = useSelector ( ( state : ConfacState ) => state . clients ) ;
42
- const client = useSelector ( ( state : ConfacState ) => state . clients . find ( x => x . _id === project . client . clientId ) || getNewClient ( ) ) ;
36
+
43
37
const hasProjectMonths = useSelector ( ( state : ConfacState ) => state . projectsMonth . some ( pm => pm . projectId === params . id ) ) ;
44
- const [ needsSync , setNeedsSync ] = useState < { consultant : boolean , client : boolean } > ( { consultant : false , client : false } ) ;
45
- const [ clientFormConfig , setClientFormConfig ] = useState ( project . forEndCustomer ? projectFormConfigClient : projectFormConfigEndCustomer )
46
38
47
- useEntityChangedToast ( project . _id ) ;
48
39
49
- const docTitle = consultant . _id ? 'projectEdit' : 'projectNew' ;
50
- useDocumentTitle ( docTitle , { consultant : consultant . firstName , client : client . name } ) ;
51
- if ( model && ( ! project . _id || project . _id !== params . id ) ) {
52
- setProject ( model ) ;
53
- }
54
-
55
- if ( needsSync . consultant || needsSync . client ) {
56
- let newProject = { ...project } ;
57
-
58
- if ( needsSync . consultant ) {
59
- // Set ProjectMonth invoicing config based on the Consultant.Type
60
- const selectedConsultant = consultants . find ( c => c . _id === project . consultantId ) ;
61
- newProject = {
62
- ...newProject ,
63
- projectMonthConfig : {
64
- ...newProject . projectMonthConfig ,
65
- ...getDefaultProjectMonthConfig ( selectedConsultant && selectedConsultant . type ) ,
66
- } ,
67
- } ;
40
+ useEffect ( ( ) => {
41
+ if ( storeProject ) {
42
+ setSimpleProject ( storeProject ) ;
43
+ } else {
44
+ setSimpleProject ( getNewProject ( ) ) ;
68
45
}
46
+ } , [ storeProject ] ) ; // eslint-disable-line
69
47
70
- if ( needsSync . client ) {
71
- // Set ProjectMonth invoicing config based on the Client.ChangingOrderNr
72
- const selectedClient = clients . find ( x => x . _id === project . client . clientId ) ;
48
+
49
+ const setProject = ( value : IProjectModel ) => {
50
+ const newProject = { ...project , ...value } ;
51
+
52
+ // Set ProjectMonth invoicing config based on the Client.ChangingOrderNr
53
+ if ( newProject . client . clientId !== project . client . clientId ) {
54
+ const selectedClient = clients . find ( x => x . _id === newProject . client . clientId ) ;
73
55
if ( selectedClient ) {
74
- newProject . projectMonthConfig . changingOrderNr = selectedClient . defaultChangingOrderNr ;
56
+ newProject . projectMonthConfig = {
57
+ ...newProject . projectMonthConfig ,
58
+ changingOrderNr : selectedClient . defaultChangingOrderNr ,
59
+ } ;
75
60
76
61
if ( selectedClient . defaultInvoiceLines ?. length > 1 ) {
77
62
newProject . client = {
@@ -83,45 +68,63 @@ export const EditProject = () => {
83
68
}
84
69
}
85
70
86
- setNeedsSync ( { consultant : false , client : false } ) ;
87
- setProject ( newProject ) ;
88
- }
89
-
90
- const setProjectInterceptor = ( value : IProjectModel ) => {
91
- const newProject = { ...project , ...value } ;
71
+ // Set ProjectMonth invoicing config based on the Consultant.Type
72
+ if ( newProject . consultantId !== project . consultantId ) {
73
+ const selectedConsultant = consultants . find ( c => c . _id === newProject . consultantId ) ;
74
+ if ( selectedConsultant ) {
75
+ newProject . projectMonthConfig = {
76
+ ...newProject . projectMonthConfig ,
77
+ ...getDefaultProjectMonthConfig ( selectedConsultant . type ) ,
78
+ } ;
79
+ }
80
+ }
92
81
82
+ // Enable/Disable "project is via client at end customer"
93
83
if ( ! newProject . forEndCustomer && newProject . endCustomer ) {
84
+ newProject . client = {
85
+ ...newProject . client ,
86
+ clientId : newProject . endCustomer . clientId ,
87
+ }
94
88
newProject . endCustomer = null ;
89
+ } else if ( newProject . forEndCustomer && ! newProject . endCustomer ) {
90
+ newProject . endCustomer = {
91
+ ...getNewProjectEndCustomer ( ) ,
92
+ clientId : newProject . client . clientId ,
93
+ } ;
94
+ newProject . client = {
95
+ ...newProject . client ,
96
+ clientId : '' ,
97
+ } ;
95
98
}
96
99
97
- if ( newProject . forEndCustomer && ! newProject . endCustomer ) {
98
- newProject . endCustomer = getNewProjectEndCustomer ( ) ;
99
- }
100
+ setSimpleProject ( newProject ) ;
101
+ } ;
100
102
101
- const clientTypeForClientField = ( newProject . forEndCustomer ? 'client' : 'endCustomer' )
102
- if ( project . client . clientId ) {
103
- const selectedClient = clients . find ( x => x . _id === project . client . clientId ) ;
104
- if ( selectedClient && ! selectedClient . types . includes ( clientTypeForClientField ) ) {
105
- newProject . client . clientId = '' ;
106
- }
107
- }
103
+ return {
104
+ project,
105
+ setProject,
106
+ canDelete : ! hasProjectMonths ,
107
+ } ;
108
+ }
108
109
109
- setProject ( newProject ) ;
110
+ const useEditProjectTitle = ( project : IProjectModel ) => {
111
+ const consultant = useSelector ( ( state : ConfacState ) => state . consultants . find ( x => x . _id === project . consultantId ) ) ;
112
+ const client = useSelector ( ( state : ConfacState ) => state . clients . find ( x => x . _id === project . client . clientId ) ) ;
113
+ const docTitle = consultant ?. _id ? 'projectEdit' : 'projectNew' ;
114
+ useDocumentTitle ( docTitle , { consultant : consultant ?. firstName ?? '' , client : client ?. name ?? '' } ) ;
115
+ }
110
116
111
- setClientFormConfig ( newProject . forEndCustomer ? projectFormConfigClient : projectFormConfigEndCustomer )
112
117
118
+ export const EditProject = ( ) => {
119
+ const dispatch = useDispatch ( ) ;
120
+ const navigate = useNavigate ( ) ;
121
+ const { project, setProject, canDelete} = useProjectState ( ) ;
122
+ const client = useSelector ( ( state : ConfacState ) => state . clients . find ( x => x . _id === project . client . clientId ) ) ;
113
123
124
+ useEntityChangedToast ( project . _id ) ;
125
+ useEditProjectTitle ( project ) ;
114
126
115
- // Set a flag to update fields that receive default values from the
116
- // selected Consultant/Client. Cannot update them at this point because
117
- // the selectors have not yet included the Consultant/Client when the
118
- // user created a new entity with the CreateModal button
119
- const consultantChanged = value . consultantId !== project . consultantId ;
120
- const clientChanged = value . client . clientId !== project . client . clientId ;
121
- if ( consultantChanged || clientChanged ) {
122
- setNeedsSync ( { consultant : consultantChanged , client : clientChanged } ) ;
123
- }
124
- } ;
127
+ const clientFormConfig = getProjectFormConfig ( project ) ;
125
128
126
129
const isButtonDisabled = ! project . consultantId
127
130
|| ! project . client || ! project . client . clientId
@@ -132,12 +135,15 @@ export const EditProject = () => {
132
135
< Container className = "edit-container" >
133
136
< Row className = "page-title-container" >
134
137
< h1 > { project . _id ? t ( 'project.project' ) : t ( 'project.createNew' ) } </ h1 >
135
- < Audit model = { model } modelType = "project" />
138
+ < Audit model = { project } modelType = "project" />
136
139
</ Row >
137
140
< Row >
138
141
< Col >
139
142
< h2 >
140
- < SingleContractIcon contracts = { [ project . contract , client ?. frameworkAgreement ] } style = { { fontSize : 28 } } />
143
+ < SingleContractIcon
144
+ contracts = { client ? [ project . contract , client ?. frameworkAgreement ] : [ project . contract ] }
145
+ style = { { fontSize : 28 } }
146
+ />
141
147
{ t ( 'project.contract.title' ) }
142
148
</ h2 >
143
149
</ Col >
@@ -147,7 +153,7 @@ export const EditProject = () => {
147
153
< ArrayInput
148
154
config = { clientFormConfig }
149
155
model = { project }
150
- onChange = { ( value : IProjectModel ) => setProjectInterceptor ( value ) }
156
+ onChange = { ( value : IProjectModel ) => setProject ( value ) }
151
157
tPrefix = "project."
152
158
/>
153
159
</ Row >
@@ -159,7 +165,7 @@ export const EditProject = () => {
159
165
variant = "danger"
160
166
title = { t ( 'project.deleteConfirm.title' ) }
161
167
componentChildren = { t ( 'delete' ) }
162
- claim = { claims => ! hasProjectMonths && ! ! project . _id && claims . includes ( Claim . DeleteProject ) }
168
+ claim = { claims => canDelete && ! ! project . _id && claims . includes ( Claim . DeleteProject ) }
163
169
>
164
170
{ t ( 'project.deleteConfirm.content' ) }
165
171
</ ConfirmationButton >
0 commit comments