1111 * limitations under the License.
1212 * */
1313
14- import React , { useCallback , useEffect , useState } from "react" ;
14+ import React from "react" ;
1515import T from "i18n-react/dist/i18n-react" ;
16- import TextField from "@mui/material/TextField" ;
16+ import { useFormik , FormikProvider } from "formik" ;
17+ import * as yup from "yup" ;
1718import Button from "@mui/material/Button" ;
1819import Grid2 from "@mui/material/Grid2" ;
1920import Box from "@mui/material/Box" ;
2021import Stack from "@mui/material/Stack" ;
22+ import MuiFormikTextField from "openstack-uicore-foundation/lib/components/mui/formik-inputs/textfield" ;
2123import SimpleLinkList from "openstack-uicore-foundation/lib/components/simple-link-list" ;
2224import { queryTicketTypes } from "openstack-uicore-foundation/lib/utils/query-actions" ;
23- import { scrollToError , shallowEqual } from "../../utils/methods" ;
25+ import useScrollToError from "../../hooks/useScrollToError" ;
26+
27+ const validationSchema = yup . object ( {
28+ name : yup . string ( ) . required ( T . translate ( "validation.required" ) ) ,
29+ rate : yup
30+ . number ( )
31+ . typeError ( T . translate ( "validation.number" ) )
32+ . min ( 0 , T . translate ( "validation.min" , { min : 0 } ) )
33+ . required ( T . translate ( "validation.required" ) ) ,
34+ tax_id : yup . string ( ) . required ( T . translate ( "validation.required" ) )
35+ } ) ;
2436
2537const TaxTypeForm = ( {
2638 entity : entityProp ,
27- errors : errorsProp ,
2839 currentSummit,
2940 onTicketLink,
3041 onTicketUnLink,
3142 onSubmit
3243} ) => {
33- const [ entity , setEntity ] = useState ( { ...entityProp } ) ;
34- const [ errors , setErrors ] = useState ( errorsProp ) ;
35-
36- useEffect ( ( ) => {
37- setEntity ( { ...entityProp } ) ;
38- setErrors ( { } ) ;
39- } , [ entityProp . id ] ) ;
40-
41- useEffect ( ( ) => {
42- const nextTicketTypes = entityProp . ticket_types ?? [ ] ;
43-
44- setEntity ( ( prev ) => {
45- if ( prev . id !== entityProp . id ) return prev ;
46- if ( shallowEqual ( prev . ticket_types ?? [ ] , nextTicketTypes ) ) return prev ;
47-
48- return {
49- ...prev ,
50- ticket_types : [ ...nextTicketTypes ]
51- } ;
52- } ) ;
53- } , [ entityProp . id , entityProp . ticket_types ] ) ;
54-
55- useEffect ( ( ) => {
56- scrollToError ( errorsProp ) ;
57- if ( ! shallowEqual ( errors , errorsProp ) ) {
58- setErrors ( { ...errorsProp } ) ;
59- }
60- } , [ errorsProp ] ) ;
61-
62- const handleChange = useCallback (
63- ( ev ) => {
64- const { value, id } = ev . target ;
65- const newEntity = { ...entity , [ id ] : value } ;
66- const newErrors = { ...errors , [ id ] : "" } ;
67- setEntity ( newEntity ) ;
68- setErrors ( newErrors ) ;
69- } ,
70- [ entity , errors ]
71- ) ;
44+ const initialValues = {
45+ id : entityProp . id ,
46+ name : entityProp . name || "" ,
47+ rate : entityProp . rate ?? "" ,
48+ tax_id : entityProp . tax_id || "" ,
49+ ticket_types : entityProp . ticket_types ?? [ ]
50+ } ;
7251
73- const handleSubmit = useCallback (
74- ( ev ) => {
75- ev . preventDefault ( ) ;
76- onSubmit ( { ...entity } ) ;
52+ const formik = useFormik ( {
53+ initialValues,
54+ validationSchema,
55+ enableReinitialize : true ,
56+ onSubmit : ( values ) => {
57+ onSubmit ( { ...entityProp , ...values } ) ;
7758 } ,
78- [ entity , onSubmit ]
79- ) ;
59+ validateOnChange : false
60+ } ) ;
8061
81- const hasErrors = useCallback (
82- ( field ) => {
83- if ( field in errors ) {
84- return errors [ field ] ;
85- }
86-
87- return "" ;
88- } ,
89- [ errors ]
90- ) ;
62+ useScrollToError ( formik ) ;
9163
92- const handleTicketLink = useCallback (
93- ( value ) => {
94- onTicketLink ( entity . id , value ) ;
95- } ,
96- [ entity . id , onTicketLink ]
97- ) ;
98-
99- const handleTicketUnLink = useCallback (
100- ( valueId ) => {
101- onTicketUnLink ( entity . id , valueId ) ;
102- } ,
103- [ entity . id , onTicketUnLink ]
104- ) ;
64+ const handleTicketLink = ( value ) => {
65+ onTicketLink ( formik . values . id , value ) ;
66+ } ;
67+ const handleTicketUnLink = ( valueId ) => {
68+ onTicketUnLink ( formik . values . id , valueId ) ;
69+ } ;
10570
10671 const ticketColumns = [
10772 { columnKey : "name" , value : T . translate ( "edit_tax_type.name" ) } ,
@@ -110,7 +75,6 @@ const TaxTypeForm = ({
11075 value : T . translate ( "edit_tax_type.description" )
11176 }
11277 ] ;
113-
11478 const ticketOptions = {
11579 title : T . translate ( "edit_tax_type.ticket_types" ) ,
11680 valueKey : "name" ,
@@ -125,66 +89,57 @@ const TaxTypeForm = ({
12589 } ;
12690
12791 return (
128- < Box component = "form" onSubmit = { handleSubmit } >
129- < input type = "hidden" id = "id" value = { entity . id } />
130-
131- < Grid2 container spacing = { 2 } sx = { { mb : 2 } } >
132- < Grid2 size = { { xs : 12 , sm : 6 , md : 4 } } >
133- < TextField
134- id = "name"
135- label = { T . translate ( "edit_tax_type.name" ) }
136- value = { entity . name }
137- onChange = { handleChange }
138- error = { ! ! hasErrors ( "name" ) }
139- helperText = { hasErrors ( "name" ) }
140- fullWidth
141- required
142- />
143- </ Grid2 >
144- </ Grid2 >
145-
146- < Grid2 container spacing = { 2 } sx = { { mb : 3 } } >
147- < Grid2 size = { { xs : 12 , sm : 6 , md : 4 } } >
148- < TextField
149- id = "rate"
150- label = { T . translate ( "edit_tax_type.rate" ) }
151- type = "number"
152- value = { entity . rate }
153- onChange = { handleChange }
154- error = { ! ! hasErrors ( "rate" ) }
155- helperText = { hasErrors ( "rate" ) }
156- fullWidth
157- />
92+ < FormikProvider value = { formik } >
93+ < Box
94+ component = "form"
95+ onSubmit = { formik . handleSubmit }
96+ noValidate
97+ autoComplete = "off"
98+ >
99+ < input type = "hidden" name = "id" value = { formik . values . id } />
100+ < Grid2 container spacing = { 2 } sx = { { mb : 2 } } >
101+ < Grid2 size = { { xs : 12 , sm : 6 , md : 4 } } >
102+ < MuiFormikTextField
103+ name = "name"
104+ label = { T . translate ( "edit_tax_type.name" ) }
105+ required
106+ fullWidth
107+ />
108+ </ Grid2 >
158109 </ Grid2 >
159- < Grid2 size = { { xs : 12 , sm : 6 , md : 4 } } >
160- < TextField
161- id = "tax_id"
162- label = { T . translate ( "edit_tax_type.tax_id" ) }
163- value = { entity . tax_id }
164- onChange = { handleChange }
165- error = { ! ! hasErrors ( "tax_id" ) }
166- helperText = { hasErrors ( "tax_id" ) }
167- fullWidth
168- />
110+ < Grid2 container spacing = { 2 } sx = { { mb : 3 } } >
111+ < Grid2 size = { { xs : 12 , sm : 6 , md : 4 } } >
112+ < MuiFormikTextField
113+ name = "rate"
114+ label = { T . translate ( "edit_tax_type.rate" ) }
115+ type = "number"
116+ fullWidth
117+ />
118+ </ Grid2 >
119+ < Grid2 size = { { xs : 12 , sm : 6 , md : 4 } } >
120+ < MuiFormikTextField
121+ name = "tax_id"
122+ label = { T . translate ( "edit_tax_type.tax_id" ) }
123+ fullWidth
124+ />
125+ </ Grid2 >
169126 </ Grid2 >
170- </ Grid2 >
171-
172- { entity . id !== 0 && (
173- < Box sx = { { mb : 3 } } >
174- < SimpleLinkList
175- values = { entity . ticket_types }
176- columns = { ticketColumns }
177- options = { ticketOptions }
178- />
179- </ Box >
180- ) }
181-
182- < Stack direction = "row" justifyContent = "flex-end" >
183- < Button variant = "contained" type = "submit" >
184- { T . translate ( "general.save" ) }
185- </ Button >
186- </ Stack >
187- </ Box >
127+ { formik . values . id !== 0 && (
128+ < Box sx = { { mb : 3 } } >
129+ < SimpleLinkList
130+ values = { formik . values . ticket_types }
131+ columns = { ticketColumns }
132+ options = { ticketOptions }
133+ />
134+ </ Box >
135+ ) }
136+ < Stack direction = "row" justifyContent = "flex-end" >
137+ < Button variant = "contained" type = "submit" >
138+ { T . translate ( "general.save" ) }
139+ </ Button >
140+ </ Stack >
141+ </ Box >
142+ </ FormikProvider >
188143 ) ;
189144} ;
190145
0 commit comments