@@ -35,6 +35,8 @@ const prplInteractiveTaskFormListener = {
3535 formElement . addEventListener ( 'submit' , ( event ) => {
3636 event . preventDefault ( ) ;
3737
38+ prplInteractiveTaskFormListener . showLoading ( formElement ) ;
39+
3840 // Get the form data.
3941 const formData = new FormData ( formElement ) ;
4042 const settingsToPass = { } ;
@@ -56,6 +58,8 @@ const prplInteractiveTaskFormListener = {
5658 return response ;
5759 }
5860
61+ prplInteractiveTaskFormListener . hideLoading ( formElement ) ;
62+
5963 // This will trigger the celebration event (confetti) as well.
6064 prplSuggestedTask . maybeComplete ( postId ) . then ( ( ) => {
6165 // Close popover.
@@ -76,6 +80,8 @@ const prplInteractiveTaskFormListener = {
7680 const formSubmitHandler = ( event ) => {
7781 event . preventDefault ( ) ;
7882
83+ prplInteractiveTaskFormListener . showLoading ( formElement ) ;
84+
7985 callback ( )
8086 . then ( ( response ) => {
8187 if ( true !== response . success ) {
@@ -110,6 +116,9 @@ const prplInteractiveTaskFormListener = {
110116 ) ;
111117 } )
112118 . finally ( ( ) => {
119+ // Hide loading state.
120+ prplInteractiveTaskFormListener . hideLoading ( formElement ) ;
121+
113122 // Remove the form listener once the callback is executed.
114123 formElement . removeEventListener (
115124 'submit' ,
@@ -139,6 +148,8 @@ const prplInteractiveTaskFormListener = {
139148 formElement . addEventListener ( 'submit' , ( event ) => {
140149 event . preventDefault ( ) ;
141150
151+ prplInteractiveTaskFormListener . showLoading ( formElement ) ;
152+
142153 const formData = new FormData ( formElement ) ;
143154 const settingsToPass = { } ;
144155 settingsToPass [ setting ] = settingCallbackValue (
@@ -157,7 +168,6 @@ const prplInteractiveTaskFormListener = {
157168 } ,
158169 } )
159170 . then ( ( response ) => {
160- console . log ( response ) ;
161171 if ( true !== response . success ) {
162172 // Show error to the user.
163173 prplInteractiveTaskFormListener . showError (
@@ -193,6 +203,10 @@ const prplInteractiveTaskFormListener = {
193203 error ,
194204 popoverId
195205 ) ;
206+ } )
207+ . finally ( ( ) => {
208+ // Hide loading state.
209+ prplInteractiveTaskFormListener . hideLoading ( formElement ) ;
196210 } ) ;
197211 } ) ;
198212 } ,
@@ -214,17 +228,12 @@ const prplInteractiveTaskFormListener = {
214228
215229 console . error ( 'Error in interactive task callback:' , error ) ;
216230
217- // Add error message.
218- const submitButton = formElement . querySelector (
219- 'button[type="submit"] '
231+ // Check if there's already an error message <p> element right after the form
232+ const existingErrorElement = formElement . parentNode . querySelector (
233+ 'p.prpl-interactive-task-error-message '
220234 ) ;
221235
222- if (
223- submitButton &&
224- ! formElement . querySelector (
225- '.prpl-interactive-task-error-message'
226- )
227- ) {
236+ if ( ! existingErrorElement ) {
228237 // Add paragraph with error message.
229238 const errorParagraph = document . createElement ( 'p' ) ;
230239 errorParagraph . classList . add (
@@ -234,11 +243,57 @@ const prplInteractiveTaskFormListener = {
234243 ) ;
235244 errorParagraph . textContent = prplL10n ( 'somethingWentWrong' ) ;
236245
237- // Append before submit button.
238- submitButton . parentNode . insertBefore (
239- errorParagraph ,
240- submitButton
246+ // Append after the form element.
247+ formElement . insertAdjacentElement ( 'afterend' , errorParagraph ) ;
248+ }
249+ } ,
250+
251+ /**
252+ * Show loading state.
253+ *
254+ * @param {HTMLFormElement } formElement - The form element.
255+ * @return {void }
256+ */
257+ showLoading : ( formElement ) => {
258+ let submitButton = formElement . querySelector ( 'button[type="submit"]' ) ;
259+
260+ if ( ! submitButton ) {
261+ submitButton = formElement . querySelector (
262+ 'button[data-action="completeTask"]'
241263 ) ;
242264 }
265+
266+ submitButton . disabled = true ;
267+
268+ // Add spinner.
269+ const spinner = document . createElement ( 'span' ) ;
270+ spinner . classList . add ( 'prpl-spinner' ) ;
271+ spinner . innerHTML =
272+ '<span class="spinner" style="visibility: visible;"></span>' ; // WP spinner.
273+
274+ // Append spinner after submit button.
275+ submitButton . after ( spinner ) ;
276+ } ,
277+
278+ /**
279+ * Hide loading state.
280+ *
281+ * @param {HTMLFormElement } formElement - The form element.
282+ * @return {void }
283+ */
284+ hideLoading : ( formElement ) => {
285+ let submitButton = formElement . querySelector ( 'button[type="submit"]' ) ;
286+
287+ if ( ! submitButton ) {
288+ submitButton = formElement . querySelector (
289+ 'button[data-action="completeTask"]'
290+ ) ;
291+ }
292+
293+ submitButton . disabled = false ;
294+ const spinner = formElement . querySelector ( 'span.prpl-spinner' ) ;
295+ if ( spinner ) {
296+ spinner . remove ( ) ;
297+ }
243298 } ,
244299} ;
0 commit comments