576 lines
24 KiB
JavaScript
576 lines
24 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
(function setTzCookie() {
|
|
try {
|
|
var tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
if (tz && document.cookie.indexOf('tz=' + tz) === -1) {
|
|
document.cookie = 'tz=' + tz + ';path=/;max-age=31536000;SameSite=Lax';
|
|
}
|
|
} catch (e) {}
|
|
})();
|
|
|
|
var dateInput = document.getElementById('bookingDate');
|
|
var slotsContainer = document.getElementById('slotsContainer');
|
|
var slotsGrid = document.getElementById('slotsGrid');
|
|
var slotsLoading = document.getElementById('slotsLoading');
|
|
var noSlots = document.getElementById('noSlots');
|
|
var slotDatetimeInput = document.getElementById('slotDatetime');
|
|
var slotDurationInput = document.getElementById('slotDuration');
|
|
var submitBtn = document.getElementById('btnSubmitBooking');
|
|
var typeSelect = document.getElementById('appointmentTypeSelect');
|
|
var selectedSlotBtn = null;
|
|
|
|
var weekContainer = document.getElementById('weekCalendarContainer');
|
|
var weekLoading = document.getElementById('weekCalendarLoading');
|
|
var weekGrid = document.getElementById('weekCalendarGrid');
|
|
var weekHeader = document.getElementById('weekCalendarHeader');
|
|
var weekBody = document.getElementById('weekCalendarBody');
|
|
var weekEmpty = document.getElementById('weekCalendarEmpty');
|
|
var weekNav = document.getElementById('weekCalendarNav');
|
|
|
|
var currentWeekDays = [];
|
|
var currentWeekEvents = [];
|
|
|
|
function getAppointmentTypeId() {
|
|
if (typeSelect) return typeSelect.value;
|
|
var hidden = document.querySelector('input[name="appointment_type_id"]');
|
|
return hidden ? hidden.value : null;
|
|
}
|
|
|
|
function truncate(str, max) {
|
|
if (!str) return '';
|
|
return str.length > max ? str.substring(0, max) + '...' : str;
|
|
}
|
|
|
|
function formatDateStr(d) {
|
|
var y = d.getFullYear();
|
|
var m = ('0' + (d.getMonth() + 1)).slice(-2);
|
|
var day = ('0' + d.getDate()).slice(-2);
|
|
return y + '-' + m + '-' + day;
|
|
}
|
|
|
|
function addDays(dateStr, n) {
|
|
var d = new Date(dateStr + 'T12:00:00');
|
|
d.setDate(d.getDate() + n);
|
|
return formatDateStr(d);
|
|
}
|
|
|
|
function getMonday(dateStr) {
|
|
var d = new Date(dateStr + 'T12:00:00');
|
|
var dow = d.getDay();
|
|
var diff = dow === 0 ? -6 : 1 - dow;
|
|
d.setDate(d.getDate() + diff);
|
|
return formatDateStr(d);
|
|
}
|
|
|
|
function selectDay(dateStr) {
|
|
if (dateInput) {
|
|
dateInput.value = dateStr;
|
|
}
|
|
fetchSlots(dateStr);
|
|
if (currentWeekDays.length) {
|
|
renderWeekCalendar(currentWeekDays, currentWeekEvents, dateStr);
|
|
}
|
|
}
|
|
|
|
function fetchWeekEvents(date, selectDate) {
|
|
if (!weekContainer || !date) return;
|
|
|
|
weekContainer.style.display = 'block';
|
|
weekLoading.style.display = 'block';
|
|
weekGrid.style.display = 'none';
|
|
weekEmpty.style.display = 'none';
|
|
if (weekNav) weekNav.style.display = 'none';
|
|
|
|
fetch('/my/schedule/week-events', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
jsonrpc: '2.0',
|
|
method: 'call',
|
|
params: { selected_date: date },
|
|
}),
|
|
})
|
|
.then(function (resp) { return resp.json(); })
|
|
.then(function (data) {
|
|
weekLoading.style.display = 'none';
|
|
var result = data.result || {};
|
|
var events = result.events || [];
|
|
var weekDays = result.week_days || [];
|
|
|
|
if (result.error || !weekDays.length) {
|
|
weekEmpty.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
currentWeekDays = weekDays;
|
|
currentWeekEvents = events;
|
|
|
|
var sel = selectDate || date;
|
|
renderWeekCalendar(weekDays, events, sel);
|
|
})
|
|
.catch(function () {
|
|
weekLoading.style.display = 'none';
|
|
weekEmpty.textContent = 'Failed to load calendar. Please try again.';
|
|
weekEmpty.style.display = 'block';
|
|
});
|
|
}
|
|
|
|
function navigateWeek(direction) {
|
|
var workDays = currentWeekDays.filter(function (d) {
|
|
return d.label !== 'Sat' && d.label !== 'Sun';
|
|
});
|
|
if (!workDays.length) return;
|
|
|
|
var refDate = direction > 0 ? workDays[workDays.length - 1].date : workDays[0].date;
|
|
var newDate = addDays(refDate, direction > 0 ? 7 : -7);
|
|
var monday = getMonday(newDate);
|
|
|
|
var today = formatDateStr(new Date());
|
|
var targetSelect = monday;
|
|
if (today >= monday && today <= addDays(monday, 4)) {
|
|
targetSelect = today;
|
|
}
|
|
|
|
fetchWeekEvents(monday, targetSelect);
|
|
selectDay(targetSelect);
|
|
}
|
|
|
|
function renderWeekCalendar(weekDays, events, selectedDate) {
|
|
weekHeader.innerHTML = '';
|
|
weekBody.innerHTML = '';
|
|
|
|
var eventsByDate = {};
|
|
events.forEach(function (ev) {
|
|
if (!eventsByDate[ev.date]) eventsByDate[ev.date] = [];
|
|
eventsByDate[ev.date].push(ev);
|
|
});
|
|
|
|
var workDays = weekDays.filter(function (d) {
|
|
return d.label !== 'Sat' && d.label !== 'Sun';
|
|
});
|
|
|
|
if (!workDays.length) {
|
|
weekGrid.style.display = 'none';
|
|
weekEmpty.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
var monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
var firstD = new Date(workDays[0].date + 'T12:00:00');
|
|
var lastD = new Date(workDays[workDays.length - 1].date + 'T12:00:00');
|
|
var rangeLabel = monthNames[firstD.getMonth()] + ' ' + firstD.getDate();
|
|
if (firstD.getMonth() !== lastD.getMonth()) {
|
|
rangeLabel += ' - ' + monthNames[lastD.getMonth()] + ' ' + lastD.getDate();
|
|
} else {
|
|
rangeLabel += ' - ' + lastD.getDate();
|
|
}
|
|
rangeLabel += ', ' + firstD.getFullYear();
|
|
|
|
if (weekNav) {
|
|
weekNav.style.display = 'flex';
|
|
var rangeEl = weekNav.querySelector('#weekRangeLabel');
|
|
if (rangeEl) rangeEl.textContent = rangeLabel;
|
|
}
|
|
|
|
weekGrid.style.cssText = 'display: grid; grid-template-columns: repeat(' + workDays.length + ', 1fr); border-radius: 10px; overflow: hidden; border: 1px solid #e5e7eb;';
|
|
weekHeader.style.cssText = 'display: contents;';
|
|
weekBody.style.cssText = 'display: contents;';
|
|
|
|
workDays.forEach(function (day) {
|
|
var isSelected = day.date === selectedDate;
|
|
var isToday = day.date === formatDateStr(new Date());
|
|
var dayEvents = eventsByDate[day.date] || [];
|
|
|
|
var col = document.createElement('div');
|
|
col.style.cssText = 'cursor: pointer; user-select: none;';
|
|
col.dataset.date = day.date;
|
|
col.addEventListener('click', function () {
|
|
selectDay(day.date);
|
|
});
|
|
|
|
var headerCell = document.createElement('div');
|
|
headerCell.style.cssText = 'text-align: center; padding: 10px 4px 8px; border-right: 1px solid #f0f0f0; border-bottom: 1px solid #e5e7eb; transition: background 0.15s;';
|
|
if (isSelected) {
|
|
headerCell.style.background = 'linear-gradient(180deg, #eff6ff 0%, #dbeafe 100%)';
|
|
} else {
|
|
headerCell.style.background = '#fafbfc';
|
|
}
|
|
|
|
var labelEl = document.createElement('div');
|
|
labelEl.style.cssText = 'font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: ' + (isSelected ? '#2563eb' : '#9ca3af') + ';';
|
|
labelEl.textContent = day.label;
|
|
|
|
var numEl = document.createElement('div');
|
|
if (isSelected) {
|
|
numEl.innerHTML = '<span style="display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background: #2563eb; color: #fff; font-size: 16px; font-weight: 700;">' + day.day_num + '</span>';
|
|
} else if (isToday) {
|
|
numEl.innerHTML = '<span style="display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background: #059669; color: #fff; font-size: 16px; font-weight: 700;">' + day.day_num + '</span>';
|
|
} else {
|
|
numEl.style.cssText = 'font-size: 18px; font-weight: 700; line-height: 1.2; color: #374151;';
|
|
numEl.textContent = day.day_num;
|
|
}
|
|
|
|
headerCell.appendChild(labelEl);
|
|
headerCell.appendChild(numEl);
|
|
weekHeader.appendChild(col);
|
|
col.appendChild(headerCell);
|
|
|
|
var bodyCell = document.createElement('div');
|
|
bodyCell.style.cssText = 'padding: 6px; min-height: 90px; border-right: 1px solid #f0f0f0; overflow-y: auto; transition: background 0.15s;';
|
|
bodyCell.style.background = isSelected ? '#f0f7ff' : '#fff';
|
|
|
|
if (dayEvents.length) {
|
|
dayEvents.forEach(function (ev) {
|
|
var card = document.createElement('div');
|
|
card.style.cssText = 'margin-bottom: 4px; padding: 5px 7px; border-radius: 6px; background: linear-gradient(135deg, #eff6ff 0%, #f0f7ff 100%); border-left: 3px solid #3b82f6; cursor: pointer; transition: box-shadow 0.15s;';
|
|
card.title = ev.start_time + ' - ' + ev.end_time + '\n' + ev.name + (ev.location ? '\n' + ev.location : '');
|
|
card.onmouseenter = function () { card.style.boxShadow = '0 2px 8px rgba(59,130,246,0.15)'; };
|
|
card.onmouseleave = function () { card.style.boxShadow = 'none'; };
|
|
|
|
var timeEl = document.createElement('div');
|
|
timeEl.style.cssText = 'font-size: 10px; font-weight: 600; color: #3b82f6;';
|
|
timeEl.textContent = ev.start_time;
|
|
|
|
var nameEl = document.createElement('div');
|
|
nameEl.style.cssText = 'font-size: 11px; color: #374151; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;';
|
|
nameEl.textContent = truncate(ev.name, 20);
|
|
|
|
card.appendChild(timeEl);
|
|
card.appendChild(nameEl);
|
|
bodyCell.appendChild(card);
|
|
});
|
|
}
|
|
|
|
var bodyCol = document.createElement('div');
|
|
bodyCol.style.cssText = 'cursor: pointer;';
|
|
bodyCol.dataset.date = day.date;
|
|
bodyCol.addEventListener('click', function () {
|
|
selectDay(day.date);
|
|
});
|
|
bodyCol.appendChild(bodyCell);
|
|
weekBody.appendChild(bodyCol);
|
|
});
|
|
|
|
weekGrid.style.display = 'grid';
|
|
weekEmpty.style.display = 'none';
|
|
}
|
|
|
|
function fetchSlots(date) {
|
|
var typeId = getAppointmentTypeId();
|
|
if (!typeId || !date) return;
|
|
|
|
slotsContainer.style.display = 'block';
|
|
slotsLoading.style.display = 'block';
|
|
slotsGrid.innerHTML = '';
|
|
noSlots.style.display = 'none';
|
|
slotDatetimeInput.value = '';
|
|
if (submitBtn) submitBtn.disabled = true;
|
|
selectedSlotBtn = null;
|
|
|
|
fetch('/my/schedule/available-slots', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
jsonrpc: '2.0',
|
|
method: 'call',
|
|
params: {
|
|
appointment_type_id: parseInt(typeId),
|
|
selected_date: date,
|
|
},
|
|
}),
|
|
})
|
|
.then(function (resp) { return resp.json(); })
|
|
.then(function (data) {
|
|
slotsLoading.style.display = 'none';
|
|
slotsGrid.innerHTML = '';
|
|
var result = data.result || {};
|
|
var slots = result.slots || [];
|
|
|
|
if (result.error) {
|
|
noSlots.textContent = result.error;
|
|
noSlots.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
if (!slots.length) {
|
|
noSlots.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
var morningSlots = [];
|
|
var afternoonSlots = [];
|
|
slots.forEach(function (slot) {
|
|
var text = slot.start_hour.toLowerCase();
|
|
var match = text.match(/(\d+)/);
|
|
var hour = match ? parseInt(match[1]) : 0;
|
|
if (text.indexOf('pm') > -1 && hour !== 12) hour += 12;
|
|
if (text.indexOf('am') > -1 && hour === 12) hour = 0;
|
|
if (hour < 12) {
|
|
morningSlots.push(slot);
|
|
} else {
|
|
afternoonSlots.push(slot);
|
|
}
|
|
});
|
|
|
|
function renderGroup(label, icon, groupSlots) {
|
|
if (!groupSlots.length) return;
|
|
var header = document.createElement('div');
|
|
header.className = 'w-100 mt-2 mb-1';
|
|
header.innerHTML = '<small class="text-muted fw-semibold"><i class="fa ' + icon + ' me-1"></i>' + label + '</small>';
|
|
slotsGrid.appendChild(header);
|
|
|
|
groupSlots.forEach(function (slot) {
|
|
var btn = document.createElement('button');
|
|
btn.type = 'button';
|
|
btn.className = 'btn btn-outline-primary btn-sm slot-btn';
|
|
btn.style.cssText = 'min-width: 100px; border-radius: 8px; padding: 8px 14px;';
|
|
btn.textContent = slot.start_hour;
|
|
btn.dataset.datetime = slot.datetime;
|
|
btn.dataset.duration = slot.duration;
|
|
btn.addEventListener('click', function () {
|
|
if (selectedSlotBtn) {
|
|
selectedSlotBtn.classList.remove('btn-primary');
|
|
selectedSlotBtn.classList.add('btn-outline-primary');
|
|
}
|
|
btn.classList.remove('btn-outline-primary');
|
|
btn.classList.add('btn-primary');
|
|
selectedSlotBtn = btn;
|
|
slotDatetimeInput.value = slot.datetime;
|
|
slotDurationInput.value = slot.duration;
|
|
if (submitBtn) submitBtn.disabled = false;
|
|
});
|
|
slotsGrid.appendChild(btn);
|
|
});
|
|
}
|
|
|
|
renderGroup('Morning', 'fa-sun-o', morningSlots);
|
|
renderGroup('Afternoon', 'fa-cloud', afternoonSlots);
|
|
|
|
fetchAiSuggestions(date);
|
|
})
|
|
.catch(function (err) {
|
|
slotsLoading.style.display = 'none';
|
|
noSlots.textContent = 'Failed to load slots. Please try again.';
|
|
noSlots.style.display = 'block';
|
|
});
|
|
}
|
|
|
|
var aiRequestCounter = 0;
|
|
|
|
function fetchAiSuggestions(date) {
|
|
var section = document.getElementById('aiSuggestSection');
|
|
var loading = document.getElementById('aiSuggestLoading');
|
|
var grid = document.getElementById('aiSuggestGrid');
|
|
if (!section || !grid) return;
|
|
|
|
var myRequestId = ++aiRequestCounter;
|
|
|
|
section.style.display = 'block';
|
|
loading.style.display = 'block';
|
|
grid.innerHTML = '';
|
|
|
|
var streetInput = document.getElementById('clientStreet');
|
|
var latInput = document.getElementById('clientLat');
|
|
var lngInput = document.getElementById('clientLng');
|
|
var durationInput = document.getElementById('slotDuration');
|
|
|
|
var params = {
|
|
selected_date: date,
|
|
appointment_type_id: getAppointmentTypeId() || 0,
|
|
location: streetInput ? streetInput.value : '',
|
|
lat: latInput ? parseFloat(latInput.value) || 0 : 0,
|
|
lng: lngInput ? parseFloat(lngInput.value) || 0 : 0,
|
|
duration: durationInput ? parseFloat(durationInput.value) || 1.0 : 1.0,
|
|
};
|
|
|
|
fetch('/my/schedule/ai/suggest', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ jsonrpc: '2.0', method: 'call', params: params }),
|
|
})
|
|
.then(function (r) { return r.json(); })
|
|
.then(function (data) {
|
|
if (myRequestId !== aiRequestCounter) return;
|
|
loading.style.display = 'none';
|
|
grid.innerHTML = '';
|
|
var result = data.result || {};
|
|
var suggestions = result.suggestions || [];
|
|
if (!suggestions.length) {
|
|
section.style.display = 'none';
|
|
return;
|
|
}
|
|
suggestions.forEach(function (s) {
|
|
var card = document.createElement('div');
|
|
card.className = 'border rounded-3 p-2 mb-2 d-flex justify-content-between align-items-center';
|
|
card.style.cssText = 'background: linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%); cursor: pointer; transition: all 0.15s;';
|
|
card.innerHTML =
|
|
'<div><strong class="text-primary">' + (s.time || '') + '</strong>' +
|
|
'<br/><small class="text-muted">' + (s.reason || '') + '</small></div>' +
|
|
'<i class="fa fa-magic text-info"></i>';
|
|
card.addEventListener('click', function () {
|
|
grid.querySelectorAll('.ai-card-selected').forEach(function (el) {
|
|
el.classList.remove('ai-card-selected');
|
|
el.style.border = '';
|
|
el.style.boxShadow = '';
|
|
});
|
|
card.classList.add('ai-card-selected');
|
|
card.style.border = '2px solid #2563eb';
|
|
card.style.boxShadow = '0 2px 8px rgba(37,99,235,0.2)';
|
|
|
|
if (s.datetime && slotDatetimeInput) {
|
|
if (selectedSlotBtn) {
|
|
selectedSlotBtn.classList.remove('btn-primary');
|
|
selectedSlotBtn.classList.add('btn-outline-primary');
|
|
}
|
|
slotDatetimeInput.value = s.datetime;
|
|
if (slotDurationInput) slotDurationInput.value = s.duration || '1.0';
|
|
if (submitBtn) submitBtn.disabled = false;
|
|
|
|
var btns = slotsGrid ? slotsGrid.querySelectorAll('.slot-btn') : [];
|
|
btns.forEach(function (btn) {
|
|
if (btn.dataset.datetime === s.datetime) {
|
|
btn.classList.remove('btn-outline-primary');
|
|
btn.classList.add('btn-primary');
|
|
selectedSlotBtn = btn;
|
|
btn.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
}
|
|
});
|
|
}
|
|
});
|
|
grid.appendChild(card);
|
|
});
|
|
})
|
|
.catch(function () {
|
|
if (myRequestId !== aiRequestCounter) return;
|
|
loading.style.display = 'none';
|
|
section.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
var aiSuggestBtn = document.getElementById('btnAiSuggest');
|
|
if (aiSuggestBtn) {
|
|
aiSuggestBtn.addEventListener('click', function () {
|
|
if (dateInput && dateInput.value) fetchAiSuggestions(dateInput.value);
|
|
});
|
|
}
|
|
|
|
if (dateInput) {
|
|
dateInput.addEventListener('change', function () {
|
|
var val = this.value;
|
|
fetchWeekEvents(val, val);
|
|
fetchSlots(val);
|
|
});
|
|
}
|
|
|
|
if (typeSelect) {
|
|
typeSelect.addEventListener('change', function () {
|
|
if (dateInput && dateInput.value) {
|
|
fetchSlots(dateInput.value);
|
|
}
|
|
});
|
|
}
|
|
|
|
var btnPrevWeek = document.getElementById('btnPrevWeek');
|
|
var btnNextWeek = document.getElementById('btnNextWeek');
|
|
if (btnPrevWeek) {
|
|
btnPrevWeek.addEventListener('click', function () { navigateWeek(-1); });
|
|
}
|
|
if (btnNextWeek) {
|
|
btnNextWeek.addEventListener('click', function () { navigateWeek(1); });
|
|
}
|
|
|
|
if (dateInput && weekContainer) {
|
|
var today = formatDateStr(new Date());
|
|
dateInput.value = today;
|
|
fetchWeekEvents(today, today);
|
|
fetchSlots(today);
|
|
}
|
|
|
|
var bookingForm = document.getElementById('bookingForm');
|
|
if (bookingForm) {
|
|
bookingForm.addEventListener('submit', function (e) {
|
|
if (!slotDatetimeInput || !slotDatetimeInput.value) {
|
|
e.preventDefault();
|
|
if (typeof fusionToast === 'function') { fusionToast('Please select a time slot before booking.', 'danger'); }
|
|
else { window.alert('Please select a time slot before booking.'); }
|
|
return false;
|
|
}
|
|
var clientName = bookingForm.querySelector('input[name="client_name"]');
|
|
if (!clientName || !clientName.value.trim()) {
|
|
e.preventDefault();
|
|
if (typeof fusionToast === 'function') { fusionToast('Please enter the client name.', 'danger'); }
|
|
else { window.alert('Please enter the client name.'); }
|
|
return false;
|
|
}
|
|
if (submitBtn) {
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<i class="fa fa-spinner fa-spin me-1"></i> Booking...';
|
|
}
|
|
});
|
|
}
|
|
|
|
function setupAddressAutocomplete() {
|
|
var streetInput = document.getElementById('clientStreet');
|
|
if (!streetInput || typeof google === 'undefined') return;
|
|
|
|
var autocomplete = new google.maps.places.Autocomplete(streetInput, {
|
|
componentRestrictions: { country: 'ca' },
|
|
types: ['address'],
|
|
});
|
|
|
|
autocomplete.addListener('place_changed', function () {
|
|
var place = autocomplete.getPlace();
|
|
if (!place.address_components) return;
|
|
|
|
var streetNumber = '';
|
|
var streetName = '';
|
|
var city = '';
|
|
var province = '';
|
|
var postalCode = '';
|
|
|
|
for (var i = 0; i < place.address_components.length; i++) {
|
|
var component = place.address_components[i];
|
|
var types = component.types;
|
|
|
|
if (types.indexOf('street_number') > -1) {
|
|
streetNumber = component.long_name;
|
|
} else if (types.indexOf('route') > -1) {
|
|
streetName = component.long_name;
|
|
} else if (types.indexOf('locality') > -1) {
|
|
city = component.long_name;
|
|
} else if (types.indexOf('administrative_area_level_1') > -1) {
|
|
province = component.long_name;
|
|
} else if (types.indexOf('postal_code') > -1) {
|
|
postalCode = component.long_name;
|
|
}
|
|
}
|
|
|
|
streetInput.value = (streetNumber + ' ' + streetName).trim();
|
|
var cityInput = document.getElementById('clientCity');
|
|
if (cityInput) cityInput.value = city;
|
|
var provInput = document.getElementById('clientProvince');
|
|
if (provInput) provInput.value = province;
|
|
var postalInput = document.getElementById('clientPostal');
|
|
if (postalInput) postalInput.value = postalCode;
|
|
|
|
if (place.geometry && place.geometry.location) {
|
|
var latInput = document.getElementById('clientLat');
|
|
var lngInput = document.getElementById('clientLng');
|
|
if (latInput) latInput.value = place.geometry.location.lat();
|
|
if (lngInput) lngInput.value = place.geometry.location.lng();
|
|
}
|
|
});
|
|
}
|
|
|
|
if (window._googleMapsReady) {
|
|
setupAddressAutocomplete();
|
|
} else {
|
|
window._scheduleAutocompleteInit = setupAddressAutocomplete;
|
|
}
|
|
|
|
})();
|