Add sign up draft facility (avoids having to re-enter data if you refresh page)
authorNick Downing <nick@ndcode.org>
Fri, 14 Jan 2022 12:31:47 +0000 (23:31 +1100)
committerNick Downing <nick@ndcode.org>
Fri, 14 Jan 2022 12:31:47 +0000 (23:31 +1100)
_lib/post_request.jst
api/sign_up/get_draft.json.jst [new file with mode: 0644]
api/sign_up/set_draft.json.jst [new file with mode: 0644]
my_account/sign_up/index.html.jst

index a20e797..7d7f2ba 100644 (file)
@@ -24,12 +24,12 @@ return async (env, api, func) => {
     )
     env.request.pipe(write_stream)
     let arguments = JSON.parse((await data).toString())
-    console.log('api', api, 'arguments', arguments)
+    console.log('api', api, 'arguments', JSON.stringify(arguments))
 
     result = await func(...arguments)
     if (result === undefined)
       result = null
-    console.log('api', api, 'result', result)
+    console.log('api', api, 'result', JSON.stringify(result))
   }
   catch (error) {
     let problem =
diff --git a/api/sign_up/get_draft.json.jst b/api/sign_up/get_draft.json.jst
new file mode 100644 (file)
index 0000000..1f80c00
--- /dev/null
@@ -0,0 +1,30 @@
+let logjson = (await import('@ndcode/logjson')).default
+let XDate = require('xdate')
+
+return async env => {
+  let post_request = await _require('/_lib/post_request.jst')
+  let session_cookie = await _require('/_lib/session_cookie.jst')
+  let Problem = await _require('/_lib/Problem.jst')
+
+  post_request(
+    // env
+    env,
+    // api
+    '/api/sign_up/get_draft',
+    // func
+    async () => {
+      let transaction = await env.site.database.Transaction()
+      try {
+        // initialize env.session_key, set cookie in env.response
+        let session = await session_cookie(env, transaction)
+
+        return await logjson.logjson_to_json(
+          await session.get('sign_up_draft', {})
+        )
+      }
+      finally {
+        transaction.rollback()
+      }
+    }
+  )
+}
diff --git a/api/sign_up/set_draft.json.jst b/api/sign_up/set_draft.json.jst
new file mode 100644 (file)
index 0000000..79c4de3
--- /dev/null
@@ -0,0 +1,38 @@
+let XDate = require('xdate')
+
+return async env => {
+  let post_request = await _require('/_lib/post_request.jst')
+  let session_cookie = await _require('/_lib/session_cookie.jst')
+  let Problem = await _require('/_lib/Problem.jst')
+
+  post_request(
+    // env
+    env,
+    // api
+    '/api/sign_up/set_draft',
+    // func
+    async details => {
+      // coerce and/or validate
+      details = {
+        email: details.email.slice(0, 256).toLowerCase(),
+        given_names: details.given_names.slice(0, 256),
+        family_name: details.family_name.slice(0, 256),
+        password: details.password.slice(0, 256),
+        contact_me: details.contact_me ? true : false
+      }
+
+      let transaction = await env.site.database.Transaction()
+      try {
+        // initialize env.session_key, set cookie in env.response
+        let session = await session_cookie(env, transaction)
+
+        session.set('sign_up_draft', transaction.json_to_logjson(details))
+        await transaction.commit()
+      }
+      catch (error) {
+        transaction.rollback()
+        throw error
+      }
+    }
+  )
+}
index 8eaff34..0bbf5b8 100644 (file)
@@ -1,8 +1,26 @@
+let logjson = (await import('@ndcode/logjson')).default
+
 return async env => {
   let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
   let icon_cross = await env.site.get_min_svg('/_svg/icon_cross.svg')
   let icon_tick = await env.site.get_min_svg('/_svg/icon_tick.svg')
   let navbar = await _require('/_lib/navbar.jst')
+  let session_cookie = await _require('/_lib/session_cookie.jst')
+
+  // preload draft details if any
+  let transaction = await env.site.database.Transaction(), details
+  try {
+    // initialize env.session_key, set cookie in env.response
+    let session = await session_cookie(env, transaction)
+
+    details = await logjson.logjson_to_json(
+      await session.get('sign_up_draft', {})
+    )
+  }
+  finally {
+    transaction.rollback()
+  }
+  console.log('details', JSON.stringify(details))
 
   await navbar(
     env,
@@ -40,13 +58,13 @@ return async env => {
                 div.col-md-6 {
                   div.form-group {
                     label.form-label(for="given-names") {'Given names *'}
-                    input.form-control#given-names(type="text" placeholder="Your given names" required="required" maxlength=256) {}
+                    input.form-control#given-names(type="text" value=details.given_names || '' placeholder="Your given names" required="required" maxlength=256) {}
                   }
                 }
                 div.col-md-6 {
                   div.form-group {
                     label.form-label(for="family-name") {'Family name'}
-                    input.form-control#family-name(type="text" placeholder="Your family name" maxlength=256) {}
+                    input.form-control#family-name(type="text" value=details.family_name || '' placeholder="Your family name" maxlength=256) {}
                   }
                 }
               }
@@ -54,20 +72,23 @@ return async env => {
                 div.col-md-6 {
                   div.form-group {
                     label.form-label(for="email") {'Email *'}
-                    input.form-control#email(type="email" placeholder="Your email address" required="required" maxlength=256) {}
+                    input.form-control#email(type="email" value=details.email || '' placeholder="Your email address" required="required" maxlength=256) {}
                   }
                 }
                 div.col-md-6 {
                   div.form-group {
                     label.form-label(for="password") {'Password *'}
-                    input.form-control#password(type="password" placeholder="New password" required="required" minlength=8 maxlength=256) {}
+                    input.form-control#password(type="password" value=details.password || '' placeholder="New password" required="required" minlength=8 maxlength=256) {}
                   }
                 }
               }
               div.row {
                 div.col-md-12 {
                   div.custom-control.custom-checkbox {
-                    input.custom-control-input#contact-me(type="checkbox" checked="checked") {}
+                    if (details.contact_me === undefined || details.contact_me)
+                      input.custom-control-input#contact-me(type="checkbox" checked="checked") {}
+                    else
+                      input.custom-control-input#contact-me(type="checkbox") {}
                     ' '
                     label.custom-control-label(for="contact-me") {
                       'Contact me by email with updates and special offers'
@@ -162,10 +183,64 @@ return async env => {
           '/api/sign_up/create_account.json',
           ...arguments
         )
+        //let sign_up_get_draft = async (...arguments) => api_call(
+        //  '/api/sign_up/get_draft.json',
+        //  ...arguments
+        //)
+        let sign_up_set_draft = async (...arguments) => api_call(
+          '/api/sign_up/set_draft.json',
+          ...arguments
+        )
 
-        $(document).ready(
+        let details = () => {
+          return {
+            email: document.getElementById('email').value.slice(0, 256).toLowerCase(),
+            given_names: document.getElementById('given-names').value.slice(0, 256),
+            family_name: document.getElementById('family-name').value.slice(0, 256),
+            password: document.getElementById('password').value.slice(0, 256),
+            contact_me: document.getElementById('contact-me').checked ? true : false
+          }
+        }
+
+        let draft_timeout_running = false
+        let draft_timeout_handler = async () => {
+          draft_timeout_running = false
+          await sign_up_set_draft(details())
+          //console.log('draft', await sign_up_get_draft())
+        }
+        let draft_change_handler = () => {
+          if (!draft_timeout_running) {
+            draft_timeout_running = true
+            setTimeout(draft_timeout_handler, 5000)
+          }
+        }
+
+        document.addEventListener(
+          'DOMContentLoaded', 
           () => {
-            $('#step-1-continue').click(
+            document.getElementById('given-names').addEventListener(
+              'change',
+              draft_change_handler
+            )
+            document.getElementById('family-name').addEventListener(
+              'change',
+              draft_change_handler
+            )
+            document.getElementById('email').addEventListener(
+              'change',
+              draft_change_handler
+            )
+            document.getElementById('password').addEventListener(
+              'change',
+              draft_change_handler
+            )
+            document.getElementById('contact-me').addEventListener(
+              'change',
+              draft_change_handler
+            )
+
+            document.getElementById('step-1-continue').addEventListener(
+              'click',
               async () => {
                 if (
                   !document.getElementById('given-names').reportValidity() ||
@@ -189,15 +264,9 @@ return async env => {
                 try {
                   await sign_up_create_account(
                     // verification_code
-                    document.getElementById('verification-code').value,
+                    document.getElementById('verification-code').value.slice(0, 6).toLowerCase(),
                     // details
-                    {
-                      email: document.getElementById('email').value,
-                      given_names: document.getElementById('given-names').value,
-                      family_name: document.getElementById('family-name').value,
-                      password: document.getElementById('password').value,
-                      contact_me: document.getElementById('contact-me').value
-                    }
+                    details()
                   )
                 }
                 catch (e) {
@@ -205,7 +274,7 @@ return async env => {
                   $('#step-2-cross').show()
                   $('#step-2-spinner').hide()
 
-                  $('#step-2-message').text(e.message)
+                  document.getElementById('step-2-message').textContent = e.message
                   $('#step-2-collapse').collapse('show')
                   return
                 }
@@ -213,7 +282,7 @@ return async env => {
                 $('#step-2-cross').hide()
                 $('#step-2-spinner').hide()
 
-                $('#step-2-message').text(`Your account with email "${document.getElementById('email').value}" has been created.`)
+                document.getElementById('step-2-message').textContent = `Your account with email "${document.getElementById('email').value}" has been created.`
                 $('#step-2-collapse').collapse('show')
               }
             )