@@ -89,48 +89,70 @@ export function DonateWidget({
8989 const [ currentAmount , setCurrentAmount ] = useState (
9090 ( ) => defaultAmount ?? amounts [ frequency ] [ currency ] [ 0 ]
9191 )
92+ const [ amountDisplay , setAmountDisplay ] = useState ( ( ) =>
93+ ( ( defaultAmount ?? amounts [ frequency ] [ currency ] [ 0 ] ) / 100 ) . toFixed ( 2 )
94+ )
9295 const [ dirty , setDirty ] = useState ( false )
9396 const [ loadingCheckout , setLoadingCheckout ] = useState ( false )
9497 const [ error , setError ] = useState < string | null > ( null )
9598
9699 const intl = useIntl ( )
97100
101+ const updateAmount = useCallback ( ( amount : number ) => {
102+ const intAmount = Math . round ( amount )
103+ if ( isNaN ( intAmount ) || intAmount < 100 ) {
104+ return
105+ }
106+ setCurrentAmount ( intAmount )
107+ setAmountDisplay ( ( intAmount / 100 ) . toFixed ( 2 ) )
108+ } , [ ] )
109+
98110 const handleChangeFrequency = useCallback (
99111 ( toFrequency : DonationFrequency ) => ( ) => {
100112 setFrequency ( toFrequency )
101- setCurrentAmount ( amounts [ toFrequency ] [ currency ] [ 0 ] )
113+ updateAmount ( amounts [ toFrequency ] [ currency ] [ 0 ] )
102114 setDirty ( false )
103115 setError ( null )
104116 } ,
105- [ amounts , currency ]
117+ [ amounts , currency , updateAmount ]
106118 )
107119 const handleChangeCurrency = useCallback (
108120 ( toCurrency : Currency ) => {
109121 setCurrency ( toCurrency )
110- setCurrentAmount ( amounts [ frequency ] [ toCurrency ] [ 0 ] )
122+ updateAmount ( amounts [ frequency ] [ toCurrency ] [ 0 ] )
111123 setDirty ( false )
112124 setError ( null )
113125 } ,
114- [ amounts , frequency ]
126+ [ amounts , frequency , updateAmount ]
115127 )
116128 const handleChangeAmount : React . ChangeEventHandler < HTMLInputElement > =
117129 useCallback (
118130 ( event ) => {
119- setCurrentAmount ( event . currentTarget . valueAsNumber * 100 )
120131 setDirty ( true )
121- if ( event . currentTarget . valueAsNumber < 1 ) {
122- setError ( intl . formatMessage ( messages . amountError ) )
123- } else {
124- setError ( null )
132+ const { value, valueAsNumber } = event . currentTarget
133+ setAmountDisplay (
134+ value . replaceAll ( / [ ^ 0 - 9 \. ] + / g, "" ) ||
135+ valueAsNumber . toFixed ( 2 ) ||
136+ ( currentAmount / 100 ) . toFixed ( 2 )
137+ )
138+ if ( isNaN ( valueAsNumber ) || valueAsNumber < 1 ) {
139+ return
125140 }
141+ setCurrentAmount ( valueAsNumber * 100 )
126142 } ,
127- [ intl ]
143+ [ currentAmount ]
128144 )
129- const handleClickAmount = useCallback ( ( amount : number ) => {
130- setCurrentAmount ( amount )
131- setDirty ( false )
132- setError ( null )
133- } , [ ] )
145+ const handleClickAmount = useCallback (
146+ ( amount : number ) => {
147+ updateAmount ( amount )
148+ setDirty ( false )
149+ setError ( null )
150+ } ,
151+ [ updateAmount ]
152+ )
153+ const handleBlurAmount = useCallback ( ( ) => {
154+ setAmountDisplay ( ( currentAmount / 100 ) . toFixed ( 2 ) )
155+ } , [ currentAmount ] )
134156
135157 const handleDonate = useCallback ( ( ) => {
136158 setLoadingCheckout ( true )
@@ -191,10 +213,11 @@ export function DonateWidget({
191213 < Input
192214 className = "rounded-l-none focus:shadow-none"
193215 type = "number"
194- value = { currentAmount / 100 }
216+ value = { amountDisplay }
195217 onChange = { handleChangeAmount }
218+ onBlur = { handleBlurAmount }
196219 min = { 1 }
197- step = { 1 }
220+ step = { 0.01 }
198221 aria-label = { intl . formatMessage ( messages . amountSelect ) }
199222 disabled = { loadingCheckout }
200223 fullWidth
0 commit comments