blob: b91e3b08eb782c87ccc047e12dfb320c2e22bfd7 [file] [log] [blame]
Pranav Nachanekarafe52e82019-10-03 16:35:08 +05301frappe.ready(async () => {
Pranav Nachanekarafe52e82019-10-03 16:35:08 +05302 initialise_select_date();
pranav nachnekar27910542019-09-03 12:04:52 +05303})
Pranav Nachanekarafe52e82019-10-03 16:35:08 +05304
Pranav Nachanekar10711dd2019-09-09 15:41:20 +05305window.holiday_list = [];
pranav nachnekar27910542019-09-03 12:04:52 +05306
Pranav Nachanekar10711dd2019-09-09 15:41:20 +05307async function initialise_select_date() {
Pranav Nachanekara2dbd392019-09-12 10:48:26 +05308 navigate_to_page(1);
Pranav Nachanekar10711dd2019-09-09 15:41:20 +05309 await get_global_variables();
10 setup_date_picker();
11 setup_timezone_selector();
12 hide_next_button();
pranav nachnekar27910542019-09-03 12:04:52 +053013}
14
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053015async function get_global_variables() {
0Pranav793ba8f2019-11-14 11:25:49 +053016 // Using await through this file instead of then.
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053017 window.appointment_settings = (await frappe.call({
pranav nachnekar27910542019-09-03 12:04:52 +053018 method: 'erpnext.www.book-appointment.index.get_appointment_settings'
Pranav Nachanekarafe52e82019-10-03 16:35:08 +053019 })).message;
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053020 window.timezones = (await frappe.call({
0Pranav793ba8f2019-11-14 11:25:49 +053021 method:'erpnext.www.book-appointment.index.get_timezones'
pranav nachnekar27910542019-09-03 12:04:52 +053022 })).message;
0Pranavd1c530c2019-10-31 15:36:33 +053023 window.holiday_list = window.appointment_settings.holiday_list;
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053024}
25
26function setup_timezone_selector() {
0Pranav793ba8f2019-11-14 11:25:49 +053027 /**
28 * window.timezones is a dictionary with the following structure
29 * { IANA name: Pretty name}
30 * For example : { Asia/Kolkata : "India Time - Asia/Kolkata"}
31 */
pranav nachnekar27910542019-09-03 12:04:52 +053032 let timezones_element = document.getElementById('appointment-timezone');
Pranav Nachanekar91a56492019-09-17 16:58:41 +053033 let offset = new Date().getTimezoneOffset();
0Pranav793ba8f2019-11-14 11:25:49 +053034 Object.keys(window.timezones).forEach((timezone) => {
Pranav Nachanekar91a56492019-09-17 16:58:41 +053035 let opt = document.createElement('option');
Pranav Nachanekarc6da5fb2019-10-03 11:56:23 +053036 opt.value = timezone;
Pranav Nachanekar25148d02019-10-04 11:32:39 +053037 if (timezone == moment.tz.guess()) {
Pranav Nachanekarc6da5fb2019-10-03 11:56:23 +053038 opt.selected = true;
39 }
0Pranav793ba8f2019-11-14 11:25:49 +053040 opt.innerHTML = window.timezones[timezone]
pranav nachnekar27910542019-09-03 12:04:52 +053041 timezones_element.appendChild(opt)
42 });
43}
44
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053045function setup_date_picker() {
pranav nachnekar27910542019-09-03 12:04:52 +053046 let date_picker = document.getElementById('appointment-date');
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053047 let today = new Date();
48 date_picker.min = today.toISOString().substr(0, 10);
Pranav Nachanekar469247b2019-09-12 11:15:42 +053049 today.setDate(today.getDate() + window.appointment_settings.advance_booking_days);
Pranav Nachanekar91a56492019-09-17 16:58:41 +053050 date_picker.max = today.toISOString().substr(0, 10);
pranav nachnekar27910542019-09-03 12:04:52 +053051}
52
Pranav Nachanekar91a56492019-09-17 16:58:41 +053053function hide_next_button() {
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053054 let next_button = document.getElementById('next-button');
55 next_button.disabled = true;
Pranav Nachanekar91a56492019-09-17 16:58:41 +053056 next_button.onclick = () => frappe.msgprint("Please select a date and time");
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053057}
58
Pranav Nachanekar91a56492019-09-17 16:58:41 +053059function show_next_button() {
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053060 let next_button = document.getElementById('next-button');
61 next_button.disabled = false;
62 next_button.onclick = setup_details_page;
63}
64
65function on_date_or_timezone_select() {
66 let date_picker = document.getElementById('appointment-date');
67 let timezone = document.getElementById('appointment-timezone');
68 if (date_picker.value === '') {
69 clear_time_slots();
70 hide_next_button();
71 frappe.throw('Please select a date');
72 }
73 window.selected_date = date_picker.value;
74 window.selected_timezone = timezone.value;
75 update_time_slots(date_picker.value, timezone.value);
Pranav Nachanekara322b152019-09-11 14:25:26 +053076 let lead_text = document.getElementById('lead-text');
77 lead_text.innerHTML = "Select Time"
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053078}
79
80async function get_time_slots(date, timezone) {
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053081 let slots = (await frappe.call({
pranav nachnekar27910542019-09-03 12:04:52 +053082 method: 'erpnext.www.book-appointment.index.get_appointment_slots',
83 args: {
84 date: date,
85 timezone: timezone
86 }
87 })).message;
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053088 return slots;
89}
pranav nachnekarc5b2a582019-09-03 14:16:47 +053090
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053091async function update_time_slots(selected_date, selected_timezone) {
92 let timeslot_container = document.getElementById('timeslot-container');
93 window.slots = await get_time_slots(selected_date, selected_timezone);
94 clear_time_slots();
95 if (window.slots.length <= 0) {
96 let message_div = document.createElement('p');
pranav nachnekar27910542019-09-03 12:04:52 +053097 message_div.innerHTML = "There are no slots available on this date";
98 timeslot_container.appendChild(message_div);
Pranav Nachanekar10711dd2019-09-09 15:41:20 +053099 return
pranav nachnekar27910542019-09-03 12:04:52 +0530100 }
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530101 window.slots.forEach((slot, index) => {
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530102 // Get and append timeslot div
103 let timeslot_div = get_timeslot_div_layout(slot)
pranav nachnekar27910542019-09-03 12:04:52 +0530104 timeslot_container.appendChild(timeslot_div);
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530105 });
106 set_default_timeslot();
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530107}
108
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530109function get_timeslot_div_layout(timeslot) {
110 let start_time = new Date(timeslot.time)
111 let timeslot_div = document.createElement('div');
112 timeslot_div.classList.add('time-slot');
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530113 if (!timeslot.availability) {
114 timeslot_div.classList.add('unavailable')
115 }
116 timeslot_div.innerHTML = get_slot_layout(start_time);
117 timeslot_div.id = timeslot.time.substr(11, 20);
118 timeslot_div.addEventListener('click', select_time);
119 return timeslot_div
120}
121
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530122function clear_time_slots() {
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530123 // Clear any existing divs in timeslot container
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530124 let timeslot_container = document.getElementById('timeslot-container');
125 while (timeslot_container.firstChild) {
Pranav Nachanekar7323bfd2019-09-18 14:33:10 +0530126 timeslot_container.removeChild(timeslot_container.firstChild);
pranav nachnekar27910542019-09-03 12:04:52 +0530127 }
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530128}
129
130function get_slot_layout(time) {
0Pranav6e6954c2019-11-13 16:00:59 +0530131 let timezone = document.getElementById("appointment-timezone").value;
Pranav Nachanekar7323bfd2019-09-18 14:33:10 +0530132 time = new Date(time);
0Pranav6e6954c2019-11-13 16:00:59 +0530133 let start_time_string = moment(time).tz(timezone).format("LT");
134 let end_time = moment(time).tz(timezone).add(window.appointment_settings.appointment_duration, 'minutes');
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530135 let end_time_string = end_time.format("LT");
136 return `<span style="font-size: 1.2em;">${start_time_string}</span><br><span class="text-muted small">to ${end_time_string}</span>`;
pranav nachnekar27910542019-09-03 12:04:52 +0530137}
138
139function select_time() {
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530140 if (this.classList.contains('unavailable')) {
Pranav Nachanekar7323bfd2019-09-18 14:33:10 +0530141 return;
pranav nachnekar27910542019-09-03 12:04:52 +0530142 }
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530143 let selected_element = document.getElementsByClassName('selected');
Pranav Nachanekar25148d02019-10-04 11:32:39 +0530144 if (!(selected_element.length > 0)) {
Pranav Nachanekar7323bfd2019-09-18 14:33:10 +0530145 this.classList.add('selected');
146 show_next_button();
147 return;
pranav nachnekar27910542019-09-03 12:04:52 +0530148 }
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530149 selected_element = selected_element[0]
Pranav Nachanekar7323bfd2019-09-18 14:33:10 +0530150 window.selected_time = this.id;
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530151 selected_element.classList.remove('selected');
152 this.classList.add('selected');
Pranav Nachanekara2dbd392019-09-12 10:48:26 +0530153 show_next_button();
pranav nachnekar27910542019-09-03 12:04:52 +0530154}
155
156function set_default_timeslot() {
157 let timeslots = document.getElementsByClassName('time-slot')
Pranav Nachanekar7323bfd2019-09-18 14:33:10 +0530158 // Can't use a forEach here since, we need to break the loop after a timeslot is selected
pranav nachnekar27910542019-09-03 12:04:52 +0530159 for (let i = 0; i < timeslots.length; i++) {
160 const timeslot = timeslots[i];
161 if (!timeslot.classList.contains('unavailable')) {
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530162 timeslot.classList.add('selected');
pranav nachnekar27910542019-09-03 12:04:52 +0530163 break;
164 }
165 }
166}
167
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530168function navigate_to_page(page_number) {
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530169 let page1 = document.getElementById('select-date-time');
170 let page2 = document.getElementById('enter-details');
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530171 switch (page_number) {
172 case 1:
Pranav Nachanekara2dbd392019-09-12 10:48:26 +0530173 page1.style.display = 'block';
174 page2.style.display = 'none';
175 break;
176 case 2:
177 page1.style.display = 'none';
178 page2.style.display = 'block';
179 break;
180 default:
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530181 break;
Pranav Nachanekara2dbd392019-09-12 10:48:26 +0530182 }
183}
184
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530185function setup_details_page() {
Pranav Nachanekara2dbd392019-09-12 10:48:26 +0530186 navigate_to_page(2)
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530187 let date_container = document.getElementsByClassName('date-span')[0];
188 let time_container = document.getElementsByClassName('time-span')[0];
Pranav Nachanekar5c008ef2019-09-10 13:12:07 +0530189 date_container.innerHTML = moment(window.selected_date).format("MMM Do YYYY");
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530190 time_container.innerHTML = moment(window.selected_time, "HH:mm:ss").format("LT");
pranav nachnekar27910542019-09-03 12:04:52 +0530191}
192
pranav nachnekarc5b2a582019-09-03 14:16:47 +0530193async function submit() {
0Pranava92f0602019-11-13 12:13:42 +0530194 let button = document.getElementById('submit-button');
195 button.disabled = true;
Pranav Nachanekarc9cf5ae2019-09-24 12:08:37 +0530196 let form = document.querySelector('#customer-form');
Pranav Nachanekar25148d02019-10-04 11:32:39 +0530197 if (!form.checkValidity()) {
Pranav Nachanekarc9cf5ae2019-09-24 12:08:37 +0530198 form.reportValidity();
0Pranava92f0602019-11-13 12:13:42 +0530199 button.disabled = false;
Pranav Nachanekarc9cf5ae2019-09-24 12:08:37 +0530200 return;
201 }
0Pranava92f0602019-11-13 12:13:42 +0530202 let contact = get_form_data();
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530203 let appointment = (await frappe.call({
pranav nachnekarc5b2a582019-09-03 14:16:47 +0530204 method: 'erpnext.www.book-appointment.index.create_appointment',
205 args: {
Pranav Nachanekardb21f862019-09-09 17:01:40 +0530206 'date': window.selected_date,
207 'time': window.selected_time,
0Pranava92f0602019-11-13 12:13:42 +0530208 'contact': contact,
0Pranavd1c530c2019-10-31 15:36:33 +0530209 'tz':window.selected_timezone
pranav nachnekarc5b2a582019-09-03 14:16:47 +0530210 }
211 })).message;
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530212 frappe.msgprint(__('Appointment Created Successfully'));
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530213}
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530214
Pranav Nachanekar91a56492019-09-17 16:58:41 +0530215function get_form_data() {
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530216 contact = {};
0Pranav6de68c82019-11-01 09:51:32 +0530217 let inputs = ['name', 'skype', 'number', 'notes', 'email'];
218 inputs.forEach((id) => contact[id] = document.getElementById(`customer_${id}`).value)
0Pranava92f0602019-11-13 12:13:42 +0530219 return contact
Pranav Nachanekar10711dd2019-09-09 15:41:20 +0530220}