isere-cd38: add calendar booking template (#50311)
This commit is contained in:
parent
14cdda56ec
commit
0f3453af9b
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -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 %}
|
Loading…
Reference in New Issue