1- import React , { useState } from 'react' ;
2- import { Button , Menu } from 'antd' ;
1+ import React , { useEffect , useRef , useState } from 'react' ;
2+ import { Button , Menu , message } from 'antd' ;
33import { $t } from 'services/i18n' ;
44import { IWidgetCommonState , useWidget , WidgetModule , WidgetParams } from './common/useWidget' ;
55import { WidgetLayout } from './common/WidgetLayout' ;
@@ -9,6 +9,8 @@ import { metadata } from '../shared/inputs/metadata';
99import { WidgetType } from 'services/widgets' ;
1010import { authorizedHeaders , jfetch } from 'util/requests' ;
1111import { Services } from 'components-react/service-provider' ;
12+ import styles from './GenericGoal.m.less' ;
13+ import { assertIsDefined } from 'util/properties-type-guards' ;
1214
1315interface IGoalState extends IWidgetCommonState {
1416 data : {
@@ -53,6 +55,7 @@ export function GenericGoal() {
5355 setSelectedTab,
5456 selectedTab,
5557 saveGoal,
58+ resetGoal,
5659 type,
5760 } = useGenericGoal ( ) ;
5861
@@ -67,6 +70,10 @@ export function GenericGoal() {
6770 ends_at : '' ,
6871 } ) ;
6972
73+ useEffect ( ( ) => {
74+ message . config ( { top : 270 } ) ;
75+ } , [ ] ) ;
76+
7077 function updateGoalCreate ( key : string ) {
7178 return ( val : TInputValue ) => {
7279 setGoalCreateValues ( { ...goalCreateValues , [ key ] : val } ) ;
@@ -87,12 +94,18 @@ export function GenericGoal() {
8794 values = { goalCreateValues }
8895 onChange = { updateGoalCreate }
8996 />
90- < Button className = "button button--action" onClick = { ( ) => saveGoal ( goalCreateValues ) } >
91- { $t ( 'Save Goal' ) }
97+ < Button
98+ className = "button button--action"
99+ onClick = { ( ) => saveGoal ( goalCreateValues ) }
100+ style = { { marginBottom : 16 } }
101+ >
102+ { $t ( 'Start Goal' ) }
92103 </ Button >
93104 </ >
94105 ) }
95- { ! isLoading && selectedTab === 'goal' && hasGoal && < DisplayGoal goal = { goalSettings } /> }
106+ { ! isLoading && selectedTab === 'goal' && hasGoal && (
107+ < DisplayGoal goal = { goalSettings } resetGoal = { resetGoal } />
108+ ) }
96109 { ! isLoading && selectedTab === 'general' && (
97110 < FormFactory
98111 metadata = { visualMeta }
@@ -106,29 +119,31 @@ export function GenericGoal() {
106119 ) ;
107120}
108121
109- function DisplayGoal ( p : { goal : IGoalState [ 'data' ] [ 'goal' ] } ) {
110- const { resetGoal } = useGenericGoal ( ) ;
111-
122+ function DisplayGoal ( p : { goal : IGoalState [ 'data' ] [ 'goal' ] ; resetGoal : ( ) => void } ) {
112123 if ( ! p . goal ) return < > </ > ;
113124 return (
114125 < div className = "section__body" >
115- < div className = "goal-row" >
126+ < div className = { styles . goalRow } >
116127 < span > { $t ( 'Title' ) } </ span >
117128 < span > { p . goal . title } </ span >
118129 </ div >
119- < div className = "goal-row" >
130+ < div className = { styles . goalRow } >
120131 < span > { $t ( 'Goal Amount' ) } </ span >
121132 < span > { p . goal . goal_amount } </ span >
122133 </ div >
123- < div className = "goal-row" >
134+ < div className = { styles . goalRow } >
124135 < span > { $t ( 'Current Amount' ) } </ span >
125136 < span > { p . goal . current_amount } </ span >
126137 </ div >
127- < div className = "goal-row" >
138+ < div className = { styles . goalRow } >
128139 < span > { $t ( 'Days Remaining' ) } </ span >
129140 < span > { p . goal . to_go } </ span >
130141 </ div >
131- < Button className = "button button--soft-warning" onClick = { resetGoal } >
142+ < Button
143+ className = "button button--soft-warning"
144+ onClick = { p . resetGoal }
145+ style = { { marginBottom : 16 } }
146+ >
132147 { $t ( 'End Goal' ) }
133148 </ Button >
134149 </ div >
@@ -211,18 +226,31 @@ export class GenericGoalModule extends WidgetModule<IGoalState> {
211226 const url = this . config . goalUrl ;
212227 if ( ! url ) return ;
213228 jfetch ( new Request ( url , { method : 'DELETE' , headers : this . headers } ) ) ;
229+ this . setGoalData ( null ) ;
214230 }
215231
216- saveGoal ( options : Dictionary < TInputValue > ) {
232+ async saveGoal ( options : Dictionary < TInputValue > ) {
217233 const url = this . config . goalUrl ;
218234 if ( ! url ) return ;
219- jfetch (
220- new Request ( url , {
221- method : 'POST' ,
222- headers : this . headers ,
223- body : JSON . stringify ( options ) ,
224- } ) ,
225- ) ;
235+ try {
236+ const resp : IGoalState [ 'data' ] = await jfetch (
237+ new Request ( url , {
238+ method : 'POST' ,
239+ headers : this . headers ,
240+ body : JSON . stringify ( options ) ,
241+ } ) ,
242+ ) ;
243+ this . setGoalData ( resp . goal ) ;
244+ } catch ( e : unknown ) {
245+ message . error ( { content : ( e as any ) . result . message , duration : 2 } ) ;
246+ }
247+ }
248+
249+ private setGoalData ( goal : IGoalState [ 'data' ] [ 'goal' ] ) {
250+ assertIsDefined ( this . state . widgetData . data ) ;
251+ this . state . mutate ( state => {
252+ state . widgetData . data . goal = goal ;
253+ } ) ;
226254 }
227255
228256 patchAfterFetch ( data : IGoalState [ 'data' ] ) : IGoalState [ 'data' ] {
0 commit comments