8a39212d5e21ff80442c5c140a7fb3f89a0b0189
[ndcode_site.git] / contact / index.html.jst
1 let XDate = require('xdate')
2
3 return async env => {
4   let breadcrumbs = await _require('/_lib/breadcrumbs.jst')
5   let icon_cross = await env.site.get_min_svg('/_svg/icon_cross.svg')
6   let icon_tick = await env.site.get_min_svg('/_svg/icon_tick.svg')
7   let navbar = await _require('/_lib/navbar.jst')
8   let session_cookie = await _require('/_lib/session_cookie.jst')
9
10   // preload draft details if any
11   let transaction = await env.site.database.Transaction(), draft_details
12   try {
13     // initialize env.session_key, set cookie in env.response
14     let session = await session_cookie(env, transaction)
15
16     let contact_draft = await session.get('contact_draft')
17     draft_details =
18       contact_draft !== undefined &&
19         XDate.now() < await contact_draft.get_json('expires') ?
20         {
21           email: await contact_draft.get_json('email'),
22           given_names: await contact_draft.get_json('given_names'),
23           family_name: await contact_draft.get_json('family_name'),
24           company: await contact_draft.get_json('company'),
25           email: await contact_draft.get_json('email'),
26           message: await contact_draft.get_json('message')
27         } :
28         null
29
30     await transaction.commit()
31   }
32   catch (error) {
33     transaction.rollback()
34     throw error
35   }
36   console.log('draft_details', JSON.stringify(draft_details))
37
38   await navbar(
39     env,
40     // head
41     async _out => {},
42     // body
43     async _out => {
44       await breadcrumbs(env, _out)
45
46       p {'Do you require more information, or assistance with integrating the projects on this site? We’d love to hear from you.'}
47
48       div.accordion#accordion.mb-5(role="tablist" aria-multiselectable="true") {
49         div.card#step-1 {
50           div.card-header#step-1-heading(role="tab") {
51             span#step-1-tick(style="display: none;") {
52               span.icon-color.pr-3 {_out.push(icon_tick)}
53             }
54             span#step-1-cross(style="display: none;") {
55               span.icon-color.pr-3 {_out.push(icon_cross)}
56             }
57             //span#step-1-spinner(style="display: none;") {
58             //  span.icon-color.pr-3 {
59             //    div.spinner-border(role="status") {
60             //      span.sr-only {'Loading...'}
61             //    }
62             //  }
63             //}
64             a.h5(data-toggle="collapse" data-parent="#accordion" href="#step-1-collapse" aria-expanded="true" aria-controls="step-1-collapse") {
65               'Enquiry details'
66             }
67           }
68           div#step-1-collapse.collapse.show(role="tabpanel" aria-labelledby="step-1-heading" data-parent="#accordion") {
69             div.card-body {
70               div.row {
71                 div.col-md-6 {
72                   div.form-group {
73                     label.form-label(for="given-names") {'Given names *'}
74                     input.form-control#given-names(type="text" value=draft_details ? draft_details.given_names : '' placeholder="Your given names" required="required" maxlength=256) {}
75                   }
76                 }
77                 div.col-md-6 {
78                   div.form-group {
79                     label.form-label(for="family-name") {'Family name'}
80                     input.form-control#family-name(type="text" value=draft_details ? draft_details.family_name : '' placeholder="Your family name" maxlength=256) {}
81                   }
82                 }
83               }
84               div.row {
85                 div.col-md-6 {
86                   div.form-group {
87                    label.form-label(for="company") {'Company'}
88                     input.form-control#company(type="company" value=draft_details ? draft_details.company : '' placeholder="Your company" maxlength=256) {}
89                   }
90                 }
91                 div.col-md-6 {
92                   div.form-group {
93                    label.form-label(for="email") {'Email *'}
94                     input.form-control#email(type="email" value=draft_details ? draft_details.email : '' placeholder="Your email address" required="required" maxlength=256) {}
95                   }
96                 }
97               }
98               div.row {
99                 div.col-md-12 {
100                   div.form-group {
101                     label.form-label(for="message") {'Message *'}
102                     textarea.form-control#message(placeholder="Your message" required="required" rows=6 maxlength=65536) {
103                       if (draft_details)
104                         `${draft_details.message}`
105                     }
106                   }
107                 }
108               }
109
110               button.btn.btn-success#step-1-continue(type="button") {'Continue'}
111               p.'mt-3'.mb-0 {'* These fields are required.'}
112             }
113           }
114         }
115         div.card#step-2 {
116           div.card-header#step-2-heading(role="tab") {
117             span#step-2-tick(style="display: none;") {
118               span.icon-color.pr-3 {_out.push(icon_tick)}
119             }
120             span#step-2-cross(style="display: none;") {
121               span.icon-color.pr-3 {_out.push(icon_cross)}
122             }
123             span#step-2-spinner(style="display: none;") {
124               span.icon-color.pr-3 {
125                 div.spinner-border(role="status") {
126                   span.sr-only {'Loading...'}
127                 }
128               }
129             }
130             a.h5.collapsed(data-toggle="collapse" data-parent="#accordion" href="#step-2-collapse" aria-expanded="false" aria-controls="step-2-collapse") {
131               'Send enquiry'
132             }
133           }
134           div#step-2-collapse.collapse(role="tabpanel" aria-labelledby="step-2-heading" data-parent="#accordion") {
135             div.card-body {
136               p#step-2-message {'Please enter enquiry details first.'}
137
138               button.btn.btn-outline-secondary#step-2-back(type="button") {'Back'}
139               button.btn.btn-outline-secondary.ml-3#step-2-resend-enquiry(type="button") {'Re-send enquiry'}
140             }
141           }
142         }
143       }
144     },
145     // scripts
146     async _out => {
147       //script(src="/js/api_call.js") {}
148
149       script {
150         //let api_contact_get_draft = async (...args) => api_call(
151         //  '/api/contact/get_draft.json',
152         //  ...args
153         //)
154         let api_contact_set_draft = async (...args) => api_call(
155           '/api/contact/set_draft.json',
156           ...args
157         )
158         let api_contact_send_enquiry = async (...args) => api_call(
159           '/api/contact/send_enquiry.json',
160           ...args
161         )
162
163         let draft_timeout_running = false
164         let draft_timeout_handler = async () => {
165           draft_timeout_running = false
166           await api_contact_set_draft(
167             {
168               given_names: document.getElementById('given-names').value.slice(0, 256),
169               family_name: document.getElementById('family-name').value.slice(0, 256),
170               company: document.getElementById('company').value.slice(0, 256),
171               email: document.getElementById('email').value.slice(0, 256).toLowerCase(),
172               message: document.getElementById('message').value.slice(0, 65536)
173             }
174           )
175           //console.log('draft', await api_contact_get_draft())
176         }
177         let draft_change_handler = () => {
178           if (!draft_timeout_running) {
179             draft_timeout_running = true
180             setTimeout(draft_timeout_handler, 5000)
181           }
182         }
183
184         let details
185         let step_1 = async () => {
186           if (
187             !document.getElementById('given-names').reportValidity() ||
188               !document.getElementById('family-name').reportValidity() ||
189               !document.getElementById('company').reportValidity() ||
190               !document.getElementById('email').reportValidity() ||
191               !document.getElementById('message').reportValidity()
192           ) {
193             $('#step-1-tick').hide()
194             $('#step-1-cross').show()
195             //$('#step-1-spinner').hide()
196             return false
197           }
198           $('#step-1-tick').show()
199           $('#step-1-cross').hide()
200           //$('#step-1-spinner').hide()
201
202           details = {
203             given_names: document.getElementById('given-names').value.slice(0, 256),
204             family_name: document.getElementById('family-name').value.slice(0, 256),
205             company: document.getElementById('company').value.slice(0, 256),
206             email: document.getElementById('email').value.slice(0, 256).toLowerCase(),
207             message: document.getElementById('message').value.slice(0, 65536)
208           }
209           return true
210         }
211
212         let step_2 = async () => {
213           $('#step-2-tick').hide()
214           $('#step-2-cross').hide()
215           $('#step-2-spinner').show()
216           document.getElementById('step-2').scrollIntoView()
217
218           try {
219             await api_contact_send_enquiry(details)
220           }
221           catch (error) {
222             let problem =
223               error instanceof Problem ?
224                 error :
225                 new Problem(
226                   // title
227                   'Bad request',
228                   // detail
229                   (error.stack || error.message).toString()
230                   // status
231                   400
232                 )
233
234             $('#step-2-tick').hide()
235             $('#step-2-cross').show()
236             $('#step-2-spinner').hide()
237
238             document.getElementById('step-2-message').textContent = problem.detail
239             $('#step-2-collapse').collapse('show')
240             return false
241           }
242           $('#step-2-tick').show()
243           $('#step-2-cross').hide()
244           $('#step-2-spinner').hide()
245
246           document.getElementById('step-2-message').textContent = 'We have received your enquiry. We will be in touch as soon as possible.'
247           return true
248         }
249
250         document.addEventListener(
251           'DOMContentLoaded',
252           () => {
253             document.getElementById('given-names').addEventListener(
254               'change',
255               draft_change_handler
256             )
257             document.getElementById('family-name').addEventListener(
258               'change',
259               draft_change_handler
260             )
261             document.getElementById('company').addEventListener(
262               'change',
263               draft_change_handler
264             )
265             document.getElementById('email').addEventListener(
266               'change',
267               draft_change_handler
268             )
269             document.getElementById('message').addEventListener(
270               'change',
271               draft_change_handler
272             )
273
274             document.getElementById('step-1-continue').addEventListener(
275               'click',
276               async () => {
277                 if (await step_1() && await step_2())
278                   $('#step-2-collapse').collapse('show')
279               }
280             )
281
282             document.getElementById('step-2-back').addEventListener(
283               'click',
284               () => {$('#step-1-collapse').collapse('show')}
285             )
286
287             document.getElementById('step-2-resend-enquiry').addEventListener(
288               'click',
289               async () => {
290                 if (await step_2())
291                   $('#step-2-collapse').collapse('show')
292               }
293             )
294           }
295         )
296       }
297     }
298   )
299 }