isere-cd38: add calendar booking template (#50311)

This commit is contained in:
Thomas Jund 2021-02-04 13:42:39 +01:00
parent 14cdda56ec
commit 0f3453af9b
2 changed files with 407 additions and 0 deletions

View File

@ -575,6 +575,97 @@ div#rub_service {
}
}
// ENS CALENDAR WIDGET
.ens-calendar {
$max-btn-size: 4rem;
display: flex;
max-width: $max-btn-size * 7;
position: relative;
&, &--month {
.is-hidden {
display: none !important;
}
}
table, thead, tbody {
display: block;
}
&--month {
flex: 0 0 100%;
}
&--head {
min-height: 3rem;
padding-left: 3rem;
padding-right: 3rem;
text-transform: uppercase;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
}
&--weekday {
text-transform: uppercase;
font-weight: 500;
}
&--weekdays,
&--week {
display: flex;
}
&--weekday,
&--day {
flex: 1 1 0;
padding: 0.15rem;
}
div.gru-content &--day-btn {
margin: 0;
display: block;
width: 100%;
padding-left: 0;
padding-right: 0;
background-color: white;
border: 1px solid;
&[data-status=open] {
color: green;
&:hover, &.on {
background-color: green;
color: white;
}
}
&[data-status=partially-open] {
color: #D66909;
&:hover, &.on {
background-color: #D66909;
color: white;
}
}
&[data-status=close] {
color: red;
background-color: white;
border: 1px solid;
&:hover, &.on {
background-color: red;
color: white;
}
}
}
div.gru-content &--next, div.gru-content &--prev {
position: absolute;
top: 0;
margin: 0;
}
&--next {
right: 0;
}
&--prev {
left: 0;
}
}
//

View File

@ -0,0 +1,316 @@
{% extends "qommon/forms/widget.html" %}
{% load qommon i18n %}
{% block widget-control %}
<select
id="form_{{widget.name}}"
name="{{widget.name}}"
{% for attr in widget.attrs.items %}{{attr.0}}="{{attr.1}}"{% endfor %}
style="display: none"
>
<option value="">---</option>
{% for option in widget.get_options %}
{% with datetime=option.options.date|parse_datetime %}
<option
{% for attr in option.attrs.items %} {{attr.0}}="{{attr.1}}"{% endfor %}
data-weeknumber="{{ option.options.date_weeknumber }}"
data-daynumber="{{ option.options.date_number }}"
data-weekdayindex="{{ option.options.date_weekdayindex }}"
data-month="{{ option.options.date_month }}"
data-status="{{ option.options.status }}"
>
{{ option.description }}
</option>
{% endwith %}
{% endfor %}
</select>
<div id="form_{{widget.name}}_calendar" class="ens-calendar is-hidden">
</div>
<script>
$(function() {
const prefix = "ens-calendar--";
const WEEKDAYS = ["{% trans "Monday" %}", "{% trans "Tuesday" %}",
"{% trans "Wednesday" %}", "{% trans "Thursday" %}",
"{% trans "Friday" %}", "{% trans "Saturday" %}",
"{% trans "Sunday" %}", ];
const $select = $('#form_{{widget.name}}');
let $options = $select.find('option');
const $calendar = $('#form_{{widget.name}}_calendar');
const $prev_btn = $('<button class="' + prefix + 'prev" role="button"></button>');
const $next_btn = $('<button class="' + prefix + 'next" role="button"></button>');
const activated_day_class = "on";
let calendar_days;
let $month_calendars;
let $day_btns;
let active_index = 0;
// map available data
// if static, data = $options
// if live, data = json
const define_calendar_days = function(data) {
const is$ = data instanceof $;
let days = data;
if (is$) {
days = $.makeArray($options);
}
const json_datas = days.map(function(day, idx){
const date = {};
date.value = (is$) ? day.value : day.id;
date.label = (is$) ? day.text : day.details;
date.number = (is$) ? day.dataset.daynumber : day.date_number ;
date.weekdayindex = (is$) ? day.dataset.weekdayindex : day.date_weekdayindex;
date.weeknumber = (is$) ? day.dataset.weeknumber : day.date_weeknumber;
date.month = (is$) ? day.dataset.month : day.date_month;
date.idx = (is$) ? idx : idx + 1;
date.status = (is$) ? day.dataset.status : day.status;
return date;
}).filter(function(date){
return date.value;
});
return json_datas;
};
// render Calendar
const calendar_layout = function() {
// Return array of uniq key
const list_of = function (arr, key) {
return arr
.map(function(day){
return day[key];
})
.filter(function(day, idx, days) {
return days.indexOf(day) === idx;
});
}
const months = list_of(calendar_days, 'month');
// Generate thead markup of month table
const days_headers_tpl = function() {
let days = '';
const day = WEEKDAYS.forEach(function(el) {
days += ('<th class="' + prefix + 'weekday">' + el.slice(0, 3) + '</th>');
});
return '<thead>'+
'<tr class="' + prefix + 'weekdays">' + days + '</tr>' +
'</thead>';
};
// Generate tbody markup of month table
const days_body_tpl = function(month) {
const day_tpl = function(day) {
let day_markup = "";
if (day) {
const disabled = (day.status === "close") ? 'disabled' : "";
let selectedClass = "";
if ($options[day.idx].selected) {
selectedClass = activated_day_class;
// Change active_index to display correct month
active_index = months.indexOf(month);
}
day_markup += '<td class="' + prefix + 'day">' +
'<button ' +
'role="button"'+
'title="' + day.label + '"' +
'class="' + prefix + 'day-btn ' + selectedClass +'"' +
'data-option-idx="' + day.idx + '"' +
'data-status="' + day.status + '"' +
disabled + '>' +
day.number +
'</button>' +
'</td>';
} else {
day_markup += '<td class="' + prefix +'day is-empty"></td>'
}
return day_markup;
};
const days_of_month = calendar_days.filter(function(day) {
return day.month === month;
});
const weeks_of_month = list_of(days_of_month, "weeknumber");
let weeks_markup = '';
weeks_of_month.forEach(function(weeknumber) {
let days_markup = "";
const days_of_week = days_of_month.filter(function(day) {
return day.weeknumber === weeknumber;
});
// empty days before
const first_position = parseInt(days_of_week[0].weekdayindex);
for (let i = 1; i < first_position; i++) {
days_markup += day_tpl();
}
// days of week
days_of_week.forEach(function(day) {
days_markup += day_tpl(day);
});
// empty days after
const last_position = parseInt(days_of_week[days_of_week.length - 1].weekdayindex);
if (last_position) {
for (let i = last_position; i < 7; i++) {
days_markup += day_tpl();
}
}
// week raw
weeks_markup += '<tr class="' + prefix + 'week">' + days_markup + '</tr>';
});
return '<tbody>' + weeks_markup +'</tbody>';
};
// render month
const $month_tpl = function (month) {
const $month_calendar = $('<div class="ens-calendar--month is-hidden">' +
'<strong class="ens-calendar--head">' + month + '</strong>' +
'<table>' +
days_headers_tpl() +
days_body_tpl(month) +
'</table>' +
'</div>');
$month_calendars = $month_calendars.add($month_calendar);
$month_day_btns = $month_calendar.find('.' + prefix + 'day-btn');
$day_btns = $day_btns.add($month_day_btns);
return $month_calendar;
};
// render calendar
const render_calendar = function() {
$calendar.empty();
months.forEach(function(month){
$month_tpl(month).appendTo($calendar);
$prev_btn.add($next_btn).appendTo($calendar);
});
};
return render_calendar();
};
// Go to
const goto = function(index) {
$month_calendars.addClass('is-hidden');
$prev_btn.add($next_btn).prop('disabled', null);
max = $month_calendars.length - 1;
switch (index) {
case 0:
$prev_btn.prop('disabled', true); break;
case max :
$next_btn.prop('disabled', true); break;
}
$month_calendars.eq(index).removeClass('is-hidden');
active_index = index;
};
const init = function() {
$calendar.addClass('is-hidden');
$month_calendars = $();
$day_btns = $();
calendar_layout();
goto(active_index);
$calendar.removeClass('is-hidden');
// events
$prev_btn.click(function(e){
e.preventDefault();
goto(active_index - 1);
});
$next_btn.click(function(e){
e.preventDefault();
goto(active_index + 1);
});
$day_btns.click(function(e){
e.preventDefault();
$day_btns.removeClass(activated_day_class);
$options.eq(this.dataset.optionIdx).prop('selected', true);
$(this).addClass(activated_day_class);
});
};
// if Static
if ($options.length > 1) {
calendar_days = define_calendar_days($options);
init();
}
// if $select is filled live
$select.on('wcs:options-change', function(ev, data) {
if (!data) return;
calendar_days = define_calendar_days(data.items);
$('<option value=""></option>').prependTo($select);
$options = $select.find('option');
init();
});
});
</script>
{% if request.quixote_request.is_in_backoffice %}
<style>
.ens-calendar.is-hidden,
.ens-calendar--month.is-hidden {
display: none !important;
}
.ens-calendar {
position: relative;
width: 350px;
}
.ens-calendar--head {
text-align: center;
display: block;
height: 3em;
padding-left: 3em;
padding-right: 3em;
}
.ens-calendar--day-btn[data-status=open] {
color: green;
}
.ens-calendar--day-btn[data-status=open]:hover,
.ens-calendar--day-btn[data-status=open].on {
background-color: green;
color: white;
}
.ens-calendar--day-btn[data-status=partially-open] {
color: orange;
}
.ens-calendar--day-btn[data-status=partially-open]:hover,
.ens-calendar--day-btn[data-status=partially-open].on {
background-color: orange;
color: white;
}
.ens-calendar--day-btn[data-status=close] {
color: red;
}
.ens-calendar--day-btn[data-status=close]:hover,
.ens-calendar--day-btn[data-status=close].on {
background-color: red;
color: white;
}
.ens-calendar--next, .ens-calendar--prev {
position: absolute;
top: 0;
margin: 0;
}
.ens-calendar--next {
right: 0;
}
.ens-calendar--prev {
left: 0;
}
</style>
{% endif %}
{% endblock %}
{% block widget-hint %}
{% if widget.hint %}<div class="hint">{{widget.hint}}</div>{% endif %}
{% endblock %}