First iteration of the timepicker
This commit is contained in:
parent
d1f286f466
commit
2a704a2b1d
7 changed files with 110 additions and 13 deletions
|
@ -1,3 +1,5 @@
|
|||
import {Utils} from "../Utils";
|
||||
|
||||
export interface OpeningHour {
|
||||
weekday: number, // 0 is monday, 1 is tuesday, ...
|
||||
startHour: number,
|
||||
|
@ -7,6 +9,35 @@ export interface OpeningHour {
|
|||
}
|
||||
|
||||
export class OpeningHourUtils {
|
||||
|
||||
|
||||
private static readonly days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]
|
||||
private static readonly daysIndexed = {
|
||||
mo: 0,
|
||||
tu: 1,
|
||||
we: 2,
|
||||
th: 3,
|
||||
fr: 4,
|
||||
sa: 5,
|
||||
su: 6
|
||||
}
|
||||
|
||||
public static ToString(ohs: OpeningHour[]) {
|
||||
const parts = [];
|
||||
|
||||
function hhmm(h, m) {
|
||||
return Utils.TwoDigits(h) + ":" + Utils.TwoDigits(m);
|
||||
}
|
||||
|
||||
for (const oh of ohs) {
|
||||
parts.push(
|
||||
OpeningHourUtils.days[oh.weekday] + " " + hhmm(oh.startHour, oh.startMinutes) + "-" + hhmm(oh.endHour, oh.endMinutes)
|
||||
)
|
||||
}
|
||||
|
||||
return parts.join("; ")+";"
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge duplicate opening-hour element in place.
|
||||
* Returns true if something changed
|
||||
|
@ -107,5 +138,47 @@ export class OpeningHourUtils {
|
|||
return OpeningHourUtils.startTime(mightLieIn) <= OpeningHourUtils.endTime(checked) &&
|
||||
OpeningHourUtils.endTime(checked) <= OpeningHourUtils.endTime(mightLieIn)
|
||||
}
|
||||
|
||||
static Parse(str: string) {
|
||||
if (str === undefined || str === "") {
|
||||
return []
|
||||
}
|
||||
|
||||
const parts = str.toLowerCase().split(";");
|
||||
const ohs = []
|
||||
|
||||
function parseTime(hhmm) {
|
||||
const spl = hhmm.trim().split(":");
|
||||
return [Number(spl[0].trim()), Number(spl[1].trim())]
|
||||
}
|
||||
|
||||
for (const part of parts) {
|
||||
if(part === ""){
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
||||
const partSplit = part.trim().split(" ");
|
||||
const weekday = OpeningHourUtils.daysIndexed[partSplit[0]]
|
||||
const timings = partSplit[1].split("-");
|
||||
const start = parseTime(timings[0])
|
||||
const end = parseTime(timings[1]);
|
||||
|
||||
const oh: OpeningHour = {
|
||||
weekday: weekday,
|
||||
startHour: start[0],
|
||||
startMinutes: start[1],
|
||||
endHour: end[0],
|
||||
endMinutes: end[1],
|
||||
}
|
||||
ohs.push(oh);
|
||||
|
||||
} catch (e) {
|
||||
console.error("Could not parse opening hours part", part, ", skipping it due to ", e)
|
||||
}
|
||||
}
|
||||
|
||||
return ohs;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
State.ts
2
State.ts
|
@ -23,7 +23,7 @@ export default class State {
|
|||
// The singleton of the global state
|
||||
public static state: State;
|
||||
|
||||
public static vNumber = "0.0.9b";
|
||||
public static vNumber = "0.1.0";
|
||||
|
||||
// The user journey states thresholds when a new feature gets unlocked
|
||||
public static userJourney = {
|
||||
|
|
|
@ -14,7 +14,7 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> {
|
|||
|
||||
private readonly _weekdays: UIEventSource<UIElement[]> = new UIEventSource<UIElement[]>([]);
|
||||
|
||||
constructor(ohs: UIEventSource<OpeningHour[]>) {
|
||||
constructor(ohs: UIEventSource<OpeningHour[]> = new UIEventSource<OpeningHour[]>([])) {
|
||||
super();
|
||||
this._ohs = ohs;
|
||||
this._backgroundTable = new OpeningHoursPickerTable(this._weekdays);
|
||||
|
|
|
@ -48,8 +48,8 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour> {
|
|||
Utils.Times(id => `<td id="${this.id}-timecell-${id}-${h}-30" class="oh-timecell oh-timecell-half"><div class="oh-timecell-inner"></div></td>`, 7) +
|
||||
'</tr>';
|
||||
}
|
||||
let days = OpeningHoursPickerTable.days.join("</th><th>");
|
||||
return `<table id="oh-table-${this.id}" class="oh-table"><tr><th></th><th>${days}</tr>${rows}</table>`;
|
||||
let days = OpeningHoursPickerTable.days.join("</th><th width='14%'>");
|
||||
return `<table id="oh-table-${this.id}" class="oh-table"><tr><th></th><th width='14%'>${days}</th></tr>${rows}</table>`;
|
||||
}
|
||||
|
||||
protected InnerUpdate() {
|
||||
|
|
|
@ -8,6 +8,8 @@ import {UIElement} from "../UIElement";
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import CombinedInputElement from "./CombinedInputElement";
|
||||
import SimpleDatePicker from "./SimpleDatePicker";
|
||||
import OpeningHoursPicker from "./OpeningHours/OpeningHoursPicker";
|
||||
import {OpeningHour, OpeningHourUtils} from "../../Logic/OpeningHours";
|
||||
|
||||
interface TextFieldDef {
|
||||
name: string,
|
||||
|
@ -141,6 +143,24 @@ export default class ValidatedTextField {
|
|||
return parsePhoneNumberFromString(str, country?.toUpperCase())?.isValid() ?? false
|
||||
},
|
||||
(str, country: any) => parsePhoneNumberFromString(str, country?.toUpperCase()).formatInternational()
|
||||
),
|
||||
ValidatedTextField.tp(
|
||||
"opening_hours",
|
||||
"Has extra elements to easily input when a POI is opened",
|
||||
(s, country) => true, // TODO
|
||||
str => str, // TODO reformat with opening_hours.js
|
||||
(value) => {
|
||||
const input = new InputElementMap<OpeningHour[], string>(new OpeningHoursPicker(),
|
||||
(a, b) => a === b,
|
||||
ohs => OpeningHourUtils.ToString(ohs),
|
||||
str => OpeningHourUtils.Parse(str)
|
||||
)
|
||||
input.GetValue().addCallback(latest => {
|
||||
console.log(latest);
|
||||
value.setData(latest);
|
||||
})
|
||||
return input;
|
||||
}
|
||||
)
|
||||
]
|
||||
|
||||
|
|
|
@ -214,6 +214,14 @@
|
|||
"type": "email"
|
||||
}
|
||||
},
|
||||
{
|
||||
"render": "Shop is open {opening_hours}",
|
||||
"question": "When is this shop opened?",
|
||||
"freeform": {
|
||||
"key": "opening_hours",
|
||||
"type": "opening_hours"
|
||||
}
|
||||
},
|
||||
{
|
||||
"question": {
|
||||
"en": "Does this shop sell bikes?",
|
||||
|
|
|
@ -92,10 +92,8 @@
|
|||
}
|
||||
|
||||
.oh-timerange-inner input {
|
||||
width: calc(100% - 2em);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin-left: 1em;
|
||||
margin-right:1em;
|
||||
}
|
||||
|
||||
.oh-timerange-inner-small {
|
||||
|
@ -109,8 +107,6 @@
|
|||
.oh-timerange-inner-small input {
|
||||
width: min-content;
|
||||
box-sizing: border-box;
|
||||
margin-left: 1em;
|
||||
margin-right:1em;
|
||||
}
|
||||
|
||||
.oh-delete-range{
|
||||
|
|
Loading…
Reference in a new issue