I am working on some website modifications on the appointment module to change some behaviors. What I am trying to do is make it able to choose more than one appointment in (/calendar/<appointment_type>) before sending the user to the confirmation form. The original functionality is works by sending the user to confirm his appointment by clicking on any hour button he choose, First I have tried to inherit and replace the XML snippet (calendar_appointment_slots.xml) which is concerned with giving an href for each hour button by ones that don't have an href. This is the original XML code
<?xml version="1.0" encoding="UTF-8"?>
<template>
<t t-name="appointment.slots_list">
<h5 class="text-center" t-out="slotDate"/>
<div class="o_slots_list row">
<t t-foreach="slots" t-as="slot">
<div class="col-md-6 col-12 mt-2 px-1">
<a class="btn btn-block btn-outline-primary text-black col-12"
t-attf-href="/calendar/#{appointment_type_id}/info?employee_id=#{slot['employee_id']}&date_time=#{slot['datetime']}&duration=#{slot['duration']}#{filter_appointment_type_ids ? '&filter_appointment_type_ids=' + filter_appointment_type_ids : ''}"
t-out="slot['hours']"/>
</div>
</t>
</div>
</t>
</template>
and this is what I want to replace with
<?xml version="1.0" encoding="utf-8"?>
<template>
<t t-name="my_module.inherit_slots_list" t-inherit="appointment.slots_list" t-inherit-mode="extension">
<xpath expr="//div[@class='o_slots_list row'][1]/t[1]" position="replace">
<t t-foreach="slots" t-as="slot">
<div class="col-md-6 col-12 mt-2 px-1">
<a class="btn btn-block btn-outline-primary text-black col-12 o_time"
t-out="slot['hours']"/>
</div>
</t>
</xpath>
</t>
</template>
then I have tried to inherit a JS file (appointment_select_appointment_slot.js) and add a function to append more than one appointment based on a number that user can choose to a list of appointments before sending the result to some backend route. This is the original appointment_select_appointment_slot.js
odoo.define('appointment.select_appointment_slot', function (require) {
'use strict';
var core = require('web.core');
var publicWidget = require('web.public.widget');
var qweb = core.qweb;
publicWidget.registry.appointmentSlotSelect = publicWidget.Widget.extend({
selector: '.o_appointment',
xmlDependencies: ['/appointment/static/src/xml/calendar_appointment_slots.xml'],
events: {
'change select[name="timezone"]': '_onRefresh',
'change select[id="selectEmployee"]': '_onRefresh',
'click .o_js_calendar_navigate': '_onCalendarNavigate',
'click .o_day': '_onClickDaySlot',
},
/**
* Navigate between the months available in the calendar displayed
*/
_onCalendarNavigate: function (ev) {
var parent = this.$('.o_appointment_month:not(.d-none)');
let monthID = parseInt(parent.attr('id').split('-')[1]);
monthID += ((this.$(ev.currentTarget).attr('id') === 'nextCal') ? 1 : -1);
parent.addClass('d-none');
this.$(`div#month-${monthID}`).removeClass('d-none');
},
/**
* Display the list of slots available for the date selected
*/
_onClickDaySlot: function (ev) {
this.$('.o_slot_selected').removeClass('o_slot_selected');
this.$(ev.currentTarget).addClass('o_slot_selected');
const appointmentTypeID = this.$("input[name='appointment_type_id']").val();
const appointmentTypeIDs = this.$("input[name='filter_appointment_type_ids']").val();
const slotDate = this.$(ev.currentTarget.firstElementChild).attr('id');
const slots = JSON.parse(this.$(ev.currentTarget).find('div')[0].dataset['availableSlots']);
let $slotsList = this.$('#slotsList').empty();
$(qweb.render('appointment.slots_list', {
slotDate: moment(slotDate).format("dddd D MMMM"),
slots: slots,
appointment_type_id: appointmentTypeID,
filter_appointment_type_ids: appointmentTypeIDs,
})).appendTo($slotsList);
},
/**
* Refresh the slots info when the user modify the timezone or the employee
*/
_onRefresh: function (ev) {
if (this.$("#slots_availabilities")[0]) {
var self = this;
const appointmentTypeID = this.$("input[name='appointment_type_id']").val();
const employeeID = this.$("#slots_form select[name='employee_id']").val();
const timezone = this.$("select[name='timezone']").val();
this._rpc({
route: `/calendar/${appointmentTypeID}/update_available_slots`,
params: {
employee_id: employeeID,
timezone: timezone,
},
}).then(function (data) {
if (data) {
self.$("#slots_availabilities").replaceWith(data);
}
});
}
},
});
});
and this is my code
odoo.define('my_module.appointments_num', function (require) {
'use strict';
var select_appointment_slot = require('appointment.select_appointment_slot');
var clicks = 0;
var appointments = []
var numberOfAppointments = 1
select_appointment_slot.include({
events: _.extend({}, select_appointment_slot.prototype.events, {
'click .o_time': '_onTimeClick',
'click .dropdown-item-number': '_onNumberClick'
}),
_onTimeClick: function (ev) {
if (this.$("#slots_availabilities")[0]) {
clicks++;
var self = this;
const appointmentsNumber = this.$("select[name='number_of_appointments']").val();
const timeSelected = this.$(ev.currentTarget).text();
const appointmentTypeID = this.$("input[name='appointment_type_id']").val();
const employeeID = this.$("#slots_form select[name='employee_id']").val();
const timezone = this.$("select[name='timezone']").val();
const slots = JSON.parse(this.$('.o_slot_selected').find('div')[0].dataset['availableSlots']);
$.each(slots , function(index, value) {
if (value['hours'] === timeSelected){
appointments.push(value);
return false;
}
});
if (clicks === numberOfAppointments){
this._rpc({
route: `/calendar/${appointmentTypeID}/list_of_appointments`,
params: {
appointments
},
})
}
}
},
_onNumberClick: function(ev){
numberOfAppointments = parseInt(this.$(ev.currentTarget).text());
alert(numberOfAppointments);
}
});
});
My problem is neither the JS inheritance works nor the XML. I would really appreciate if someone can help me to make this work. Thanks!