Skip to content

Commit

Permalink
[MWPW-159556] Time picker update (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
qiyundai authored Nov 5, 2024
1 parent ef4e6b3 commit 503eb9c
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 45 deletions.
23 changes: 16 additions & 7 deletions ecc/blocks/event-info-component/event-info-component.css
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,9 @@
flex: 1 1 0;
}

.event-info-component .time-pickers .time-picker-wrapper label {
display: block;
font-size: var(--type-body-xs-size);
}

.event-info-component .time-zone-picker {
.event-info-component .time-pickers .time-picker-wrapper .select-wrapper {
display: flex;
justify-content: flex-end;
gap: 8px;
}

.event-info-component .time-zone-picker sp-picker,
Expand All @@ -123,6 +118,20 @@
box-sizing: border-box;
}

.event-info-component .time-pickers .time-picker-wrapper .select-wrapper sp-picker:last-of-type {
width: max-content;
}

.event-info-component .time-pickers .time-picker-wrapper label {
display: block;
font-size: var(--type-body-xs-size);
}

.event-info-component .time-zone-picker {
display: flex;
justify-content: flex-end;
}

.event-info-component .date-input {
height: 40px;
}
Expand Down
21 changes: 16 additions & 5 deletions ecc/blocks/event-info-component/event-info-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
generateToolTip,
decorateTextfield,
decorateTextarea,
convertTo24HourFormat,
miloReplaceKey,
} from '../../scripts/utils.js';

Expand Down Expand Up @@ -42,13 +41,25 @@ function buildTimePicker(column, wrapper) {

if (j === 1) {
const timeSlots = c.querySelectorAll('li');
const select = createTag('sp-picker', { id: `time-picker-${pickerHandle}`, class: 'select-input', required: true, label: '-' });
const selectWrapper = createTag('div', { class: 'select-wrapper' });
const submitValueHolder = createTag('input', { type: 'hidden', name: `time-picker-${pickerHandle}`, id: `time-picker-${pickerHandle}-value`, value: '' });
const timeSelect = createTag('sp-picker', { id: `time-picker-${pickerHandle}`, class: 'select-input', required: true, label: '-' });
const ampmSelect = createTag('sp-picker', { id: `ampm-picker-${pickerHandle}`, class: 'select-input', required: true, label: '-' });

timeSlots.forEach((t) => {
const text = t.textContent.trim();
const opt = createTag('sp-menu-item', { value: convertTo24HourFormat(text) }, text);
select.append(opt);
const opt = createTag('sp-menu-item', { value: text }, text);
timeSelect.append(opt);
});

['AM', 'PM'].forEach((t, ti) => {
const opt = createTag('sp-menu-item', { value: t }, t);
if (ti === 0) opt.selected = true;
ampmSelect.append(opt);
});
timePickerWrapper.append(select);

selectWrapper.append(timeSelect, ampmSelect, submitValueHolder);
timePickerWrapper.append(selectWrapper);
}
});

Expand Down
117 changes: 89 additions & 28 deletions ecc/blocks/form-handler/controllers/event-info-component-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { getEvents } from '../../../scripts/esp-controller.js';
import BlockMediator from '../../../scripts/deps/block-mediator.min.js';
import { LIBS } from '../../../scripts/scripts.js';
import { changeInputValue } from '../../../scripts/utils.js';
import { changeInputValue, parse24HourFormat, convertTo24HourFormat } from '../../../scripts/utils.js';

const { createTag, getConfig } = await import(`${LIBS}/utils/utils.js`);

Expand Down Expand Up @@ -320,8 +320,8 @@ export function onSubmit(component, props) {
const localStartDate = datePicker.dataset.startDate;
const localEndDate = datePicker.dataset.endDate;

const localStartTime = component.querySelector('#time-picker-start-time').value;
const localEndTime = component.querySelector('#time-picker-end-time').value;
const localStartTime = component.querySelector('#time-picker-start-time-value').value;
const localEndTime = component.querySelector('#time-picker-end-time-value').value;

const timezone = component.querySelector('#time-zone-select-input').value;

Expand Down Expand Up @@ -372,7 +372,11 @@ export default async function init(component, props) {

const eventTitleInput = component.querySelector('#info-field-event-title');
const startTimeInput = component.querySelector('#time-picker-start-time');
const startAmpmInput = component.querySelector('#ampm-picker-start-time');
const endTimeInput = component.querySelector('#time-picker-end-time');
const endAmpmInput = component.querySelector('#ampm-picker-end-time');
const startTime = component.querySelector('#time-picker-start-time-value');
const endTime = component.querySelector('#time-picker-end-time-value');
const datePicker = component.querySelector('#event-info-date-picker');

initCalendar(component);
Expand All @@ -381,46 +385,100 @@ export default async function init(component, props) {
BlockMediator.set('eventDupMetrics', { ...BlockMediator.get('eventDupMetrics'), title: eventTitleInput.value });
});

const updateEndTimeOptions = () => {
const onEndTimeUpdate = () => {
if (endAmpmInput.value && endTimeInput.value) {
endTime.value = convertTo24HourFormat(`${endTimeInput.value} ${endAmpmInput.value}`);
} else {
return;
}

if (datePicker.dataset.startDate !== datePicker.dataset.endDate) return;
const allOptions = startTimeInput.querySelectorAll('sp-menu-item');
allOptions.forEach((option) => {
if (option.value >= endTimeInput.value && endTimeInput.value) {
option.disabled = true;
} else {
option.disabled = false;

if (startAmpmInput.value) {
let toReset = false;
const allOptions = startTimeInput.querySelectorAll('sp-menu-item');
allOptions.forEach((option) => {
const optionTime = convertTo24HourFormat(`${option.value} ${startAmpmInput.value}`);
if (optionTime >= endTime.value) {
option.disabled = true;
if (option.selected) {
toReset = true;
}
} else {
option.disabled = false;
}
});

if (toReset) {
startTimeInput.value = '';
startAmpmInput.value = '';
startTime.value = null;
allOptions.forEach((option) => {
option.disabled = false;
});
}
});
}
};

const updateStartTimeOptions = () => {
const onStartTimeUpdate = () => {
if (startAmpmInput.value && startTimeInput.value) {
startTime.value = convertTo24HourFormat(`${startTimeInput.value} ${startAmpmInput.value}`);
} else {
return;
}

if (datePicker.dataset.startDate !== datePicker.dataset.endDate) return;
const allOptions = endTimeInput.querySelectorAll('sp-menu-item');
allOptions.forEach((option) => {
if (option.value <= startTimeInput.value && startTimeInput.value) {
option.disabled = true;
} else {
option.disabled = false;

if (endAmpmInput.value) {
let toReset = false;
const allOptions = endTimeInput.querySelectorAll('sp-menu-item');
allOptions.forEach((option) => {
const optionTime = convertTo24HourFormat(`${option.value} ${endAmpmInput.value}`);
if (optionTime <= startTime.value) {
option.disabled = true;
if (option.selected) {
toReset = true;
}
} else {
option.disabled = false;
}
});

if (toReset) {
endTimeInput.value = '';
endAmpmInput.value = '';
endTime.value = null;
allOptions.forEach((option) => {
option.disabled = false;
});
}
});
}
};

const updateTimeOptionsBasedOnDate = () => {
const updateTimeOptionsBasedOnDate = (e) => {
if (datePicker.dataset.startDate !== datePicker.dataset.endDate) {
startTimeInput?.querySelectorAll('sp-menu-item')?.forEach((option) => {
option.disabled = false;
});
endTimeInput?.querySelectorAll('sp-menu-item')?.forEach((option) => {
option.disabled = false;
});
} else if (e?.target === endAmpmInput) {
onEndTimeUpdate();
onStartTimeUpdate();
} else {
onStartTimeUpdate();
onEndTimeUpdate();
}
};

endTimeInput.addEventListener('change', updateEndTimeOptions);
startTimeInput.addEventListener('change', updateStartTimeOptions);
startTimeInput.addEventListener('change', onStartTimeUpdate);
endTimeInput.addEventListener('change', onEndTimeUpdate);
startAmpmInput.addEventListener('change', updateTimeOptionsBasedOnDate);
endAmpmInput.addEventListener('change', updateTimeOptionsBasedOnDate);

datePicker.addEventListener('change', () => {
updateTimeOptionsBasedOnDate();
datePicker.addEventListener('change', (e) => {
updateTimeOptionsBasedOnDate(e);
BlockMediator.set('eventDupMetrics', { ...BlockMediator.get('eventDupMetrics'), startDate: datePicker.dataset.startDate });
});

Expand Down Expand Up @@ -461,10 +519,15 @@ export default async function init(component, props) {
&& localStartTime
&& localEndTime
&& timezone) {
const startTimePieces = parse24HourFormat(localStartTime);
const endTimePieces = parse24HourFormat(localEndTime);

component.querySelector('#info-field-event-title').value = title || '';
component.querySelector('#info-field-event-description').value = description || '';
changeInputValue(startTimeInput, 'value', localStartTime || '');
changeInputValue(endTimeInput, 'value', localEndTime || '');
changeInputValue(startTimeInput, 'value', `${startTimePieces.hours}:${startTimePieces.minutes}` || '');
changeInputValue(startAmpmInput, 'value', startTimePieces.period || '');
changeInputValue(endTimeInput, 'value', `${endTimePieces.hours}:${endTimePieces.minutes}` || '');
changeInputValue(endAmpmInput, 'value', endTimePieces.period || '');
changeInputValue(component.querySelector('#time-zone-select-input'), 'value', `${timezone}` || '');

BlockMediator.set('eventDupMetrics', {
Expand All @@ -485,8 +548,6 @@ export default async function init(component, props) {
component.classList.add('prefilled');
}

updateEndTimeOptions();
updateStartTimeOptions();
updateTimeOptionsBasedOnDate();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ export default class AgendaFieldsetGroup extends LitElement {
}

getCompleteAgenda() {
return this.agendaItems.filter((o) => (o.startTime && o.description));
return this.agendaItems.filter((agenda) => agenda.startTime && agenda.description).map((agenda) => ({
startTime: agenda.startTime,
description: agenda.description,
}));
}

hasOnlyEmptyAgendaLeft() {
Expand Down
6 changes: 6 additions & 0 deletions ecc/components/agenda-fieldset/agenda-fieldset.css.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export const style = css`
.time-picker .time-picker-wrapper {
flex: 1;
min-width: 150px;
display: flex;
gap: 8px;
}
.time-picker .time-picker-wrapper sp-picker.period-picker-input {
width: max-content;
}
.text-field-wrapper {
Expand Down
32 changes: 28 additions & 4 deletions ecc/components/agenda-fieldset/agenda-fieldset.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LIBS } from '../../scripts/scripts.js';
import { parse24HourFormat, convertTo24HourFormat } from '../../scripts/utils.js';
import { style } from './agenda-fieldset.css.js';
import { convertTo24HourFormat } from '../../scripts/utils.js';

const { LitElement, html, repeat } = await import(`${LIBS}/deps/lit-all.min.js`);

Expand All @@ -16,23 +16,47 @@ export default class AgendaFieldset extends LitElement {

updateValue(key, value) {
this.agenda = { ...this.agenda, [key]: value };

if (this.agenda.startTimeValue && this.agenda.startTimePeriod) {
this.agenda.startTime = convertTo24HourFormat(`${this.agenda.startTimeValue} ${this.agenda.startTimePeriod}`);
}

this.dispatchEvent(new CustomEvent('update-agenda', {
detail: { agenda: this.agenda },
bubbles: true,
composed: true,
}));
}

parseAgendaTime() {
if (!this.agenda.startTime) return '';

const { hours, minutes } = parse24HourFormat(this.agenda.startTime);
return `${hours}:${minutes}`;
}

parseAgendaPeriod() {
if (!this.agenda.startTime) return '';

const { period } = parse24HourFormat(this.agenda.startTime);
return period;
}

render() {
return html`
<div class="field-container">
<div class="time-picker">
<p>Time</p>
<div class="time-picker-wrapper">
<sp-picker class="time-picker-input select-input" label="Pick agenda time" value=${this.agenda.startTime} @change=${(event) => {
this.updateValue('startTime', event.target.value);
<sp-picker class="time-picker-input select-input" label="Pick agenda time" value=${this.parseAgendaTime()} @change=${(event) => {
this.updateValue('startTimeValue', event.target.value);
}}>
${repeat(this.timeslots, (timeslot) => html`<sp-menu-item value=${timeslot}>${timeslot}</sp-menu-item>`)}
</sp-picker>
<sp-picker class="period-picker-input select-input" label="AM/PM" value=${this.parseAgendaPeriod()} @change=${(event) => {
this.updateValue('startTimePeriod', event.target.value);
}}>
${repeat(this.timeslots, (timeslot) => html`<sp-menu-item value=${convertTo24HourFormat(timeslot)}>${timeslot}</sp-menu-item>`)}
${repeat(['AM', 'PM'], (p) => html`<sp-menu-item value=${p}>${p}</sp-menu-item>`)}
</sp-picker>
</div>
</div>
Expand Down
21 changes: 21 additions & 0 deletions ecc/scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ export function convertTo24HourFormat(timeStr) {
return `${formattedHours}:${formattedMinutes}:00`;
}

export function parse24HourFormat(timeStr) {
if (!timeStr) return null;

const timeFormat = /^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;

if (!timeStr.match(timeFormat)) {
throw new Error("Invalid time format. Expected format: 'HH:mm:ss'");
}

const [hours, minutes] = timeStr.split(':').map(Number);
const period = hours < 12 ? 'AM' : 'PM';
const formattedHours = hours % 12 || 12;
const formattedMinutes = minutes.toString().padStart(2, '0');

return {
hours: formattedHours,
minutes: formattedMinutes,
period,
};
}

export function getEventPageHost() {
if (window.location.href.includes('.hlx.')) {
return window.location.origin.replace(window.location.hostname, `${getEventServiceEnv()}--events-milo--adobecom.hlx.page`);
Expand Down

0 comments on commit 503eb9c

Please sign in to comment.