<form class="js-select-appointment-form">
<select class="select" id="select-cc3d" name="select-cc3d">
<option class="select__hint" disabled="disabled" selected="selected" value="">Auswählen</option>
<option value="1-08:00/11:00">Mo, 8:00-11:00 Uhr</option>
<option value="1-11:00/14:00">Mo, 11:00-14:00 Uhr</option>
<option value="1-14:00/18:00">Mo, 14:00-18:00 Uhr</option>
<option value="2-08:00/11:00">Di 8:00-11:00 Uhr</option>
<option value="2-11:00/14:00">Di, 11:00-14:00 Uhr</option>
<option value="2-14:00/18:00">Di, 14:00-18:00 Uhr</option>
<option value="3-08:00/11:00">Mi, 8:00-11:00 Uhr</option>
<option value="3-11:00/14:00">Mi, 11:00-14:00 Uhr</option>
<option value="3-14:00/18:00">Mi, 14:00-18:00 Uhr</option>
<option value="4-08:00/11:00">Do, 8:00-11:00 Uhr</option>
<option value="4-11:00/14:00">Do, 11:00-14:00 Uhr</option>
<option value="4-14:00/18:00">Do, 14:00-18:00 Uhr</option>
<option value="5-14:00/16:00">Fr, 14:00-16:00 Uhr</option>
</select>
</form>
-
//- Prepare attr object
settings = settings || {};
settings.attr = settings.attr || {};
settings.attr.class = classList(settings.attr.class);
if (!formSelectorWorkaround) {
settings.attr.class.push('js-select-appointment');
}
//- Render atom
if formSelectorWorkaround
form.js-select-appointment-form
!= include('@select', settings)
else
!= include('@select', settings)
{
"settings": {
"hasPleaseSelectOption": true,
"options": [
{
"text": "Mo, 8:00-11:00 Uhr",
"value": "1-08:00/11:00"
},
{
"text": "Mo, 11:00-14:00 Uhr",
"value": "1-11:00/14:00"
},
{
"text": "Mo, 14:00-18:00 Uhr",
"value": "1-14:00/18:00"
},
{
"text": "Di 8:00-11:00 Uhr",
"value": "2-08:00/11:00"
},
{
"text": "Di, 11:00-14:00 Uhr",
"value": "2-11:00/14:00"
},
{
"text": "Di, 14:00-18:00 Uhr",
"value": "2-14:00/18:00"
},
{
"text": "Mi, 8:00-11:00 Uhr",
"value": "3-08:00/11:00"
},
{
"text": "Mi, 11:00-14:00 Uhr",
"value": "3-11:00/14:00"
},
{
"text": "Mi, 14:00-18:00 Uhr",
"value": "3-14:00/18:00"
},
{
"text": "Do, 8:00-11:00 Uhr",
"value": "4-08:00/11:00"
},
{
"text": "Do, 11:00-14:00 Uhr",
"value": "4-11:00/14:00"
},
{
"text": "Do, 14:00-18:00 Uhr",
"value": "4-14:00/18:00"
},
{
"text": "Fr, 14:00-16:00 Uhr",
"value": "5-14:00/16:00"
}
]
},
"formSelectorWorkaround": true
}
import setIsoDay from 'date-fns/set_iso_day';
import addWeeks from 'date-fns/add_weeks';
import setHours from 'date-fns/set_hours';
import addHours from 'date-fns/add_hours';
import setMinutes from 'date-fns/set_minutes';
import compareDesc from 'date-fns/compare_desc';
/**
* Time slot string
*
* example: '4-08:00/11:00'
* format: {weekDay}-{timeStart}/{timeEnd}
* format date-fns: E-HH:mm/HH:mm
* format PHP 5.1: N-H:i/H:i
* weekDay: 1=monday, 7=saturday
*/
export const TIME_SLOT_REGEX = /^([1-7])[-](0[0-9]|1[0-9]|2[0-3])[:]([0-5][0-9])[/](0[0-9]|1[0-9]|2[0-3])[:]([0-5][0-9])$/;
export function parseTimeSlot(timeSlotString) {
if (TIME_SLOT_REGEX.test(timeSlotString)) {
const [
,
day,
startHours,
startMinutes,
endHours,
endMinutes,
] = TIME_SLOT_REGEX.exec(timeSlotString);
return {
day: Number(day),
startHours: Number(startHours),
startMinutes: Number(startMinutes),
endHours: Number(endHours),
endMinutes: Number(endMinutes),
};
}
return null;
}
export function getAppointment({ timeSlot, weekOffset, bookDate }) {
const startDate = addWeeks(
setIsoDay(
setHours(
setMinutes(bookDate, timeSlot.startMinutes),
timeSlot.startHours,
),
timeSlot.day,
),
weekOffset,
);
const endDate = addWeeks(
setIsoDay(
setHours(
setMinutes(bookDate, timeSlot.endMinutes),
timeSlot.endHours,
),
timeSlot.day,
),
weekOffset,
);
return {
startDate,
endDate,
};
}
function getNextAppointments(params, weekOffset = 0, prevAppointments = []) {
const {
timeSlots,
count,
hoursAhead,
bookDate,
} = params;
const appointments = [...prevAppointments];
const timeSlotCount = timeSlots.length;
const aheadBookDate = addHours(bookDate, hoursAhead);
for (let i = 0; i < timeSlotCount; i += 1) {
const timeSlot = timeSlots[i];
const appointment = getAppointment({
timeSlot,
weekOffset,
bookDate,
});
const isAppointmentAvailable = compareDesc(aheadBookDate, appointment.startDate) >= 0;
if (isAppointmentAvailable) {
appointments.push(appointment);
}
if (appointments.length >= count) {
break;
}
}
/**
* Repeat search in the next week only if:
*
* (1) we have not found the required number of appointments
* AND
* (2) we have not reached the recursion limit (two weeks with empty results)
*/
if (appointments.length < count && weekOffset <= count) {
return getNextAppointments(params, weekOffset + 1, appointments);
}
return appointments;
}
export default function getAppointments(
{
timeSlotStrings,
count,
hoursAhead,
},
bookDate = new Date(),
) {
const timeSlots = timeSlotStrings.reduce(
(prevTimeSlots, timeSlotString) => {
const timeSlot = parseTimeSlot(timeSlotString);
if (!timeSlot) {
return prevTimeSlots;
}
return [
...prevTimeSlots,
timeSlot,
];
},
[],
);
if (!timeSlots.length) {
return null;
}
return getNextAppointments({
timeSlots,
count,
hoursAhead,
bookDate,
});
}
import h from 'hyperscript';
import format from 'date-fns/format';
import getIsoDay from 'date-fns/get_iso_day';
import getAppointments from './get-appointments';
const DAY_NAMES = [
'Mo',
'Di',
'Mi',
'Do',
'Fr',
'Sa',
'So',
];
function formatAppointment({ startDate, endDate }) {
const dayName = DAY_NAMES[getIsoDay(startDate) - 1];
return {
value: `${format(startDate, 'YYYY-MM-DD-HH:mm')}/${format(endDate, 'HH:mm')}`,
display: `${dayName}, ${format(startDate, 'D.M.YYYY, HH:mm')}-${format(endDate, 'HH:mm')} Uhr`,
};
}
function initField($el) {
const $options = $el.querySelectorAll('option:not([value=""]):not([disabled])');
const timeSlotStrings = $options.map($option => $option.value);
const appointments = getAppointments(
{
timeSlotStrings,
count: 2,
hoursAhead: 1,
},
new Date(),
);
if (appointments === null) {
return;
}
const $fragment = document.createDocumentFragment();
appointments.forEach((appointment) => {
const { value, display } = formatAppointment(appointment);
$fragment.appendChild(
h('option', { value }, display),
);
});
$el.appendChild($fragment);
$options.forEach($option => $option.remove());
}
// Intialize via class on the select element.
document.querySelectorAll('.js-select-appointment').forEach(initField);
// Intialize via class on the parent form element.
// This is a hacky workaround for cases where select attributes cannot be customized.
document.querySelectorAll('.js-select-appointment-form select').forEach(initField);
There are no notes for this item.