Refactoring: port small part of OHInput into svelte
This commit is contained in:
parent
013c2e4b61
commit
5f355aa3e2
3 changed files with 101 additions and 116 deletions
|
@ -10,9 +10,10 @@ import Combine from "../Base/Combine"
|
||||||
import { FixedUiElement } from "../Base/FixedUiElement"
|
import { FixedUiElement } from "../Base/FixedUiElement"
|
||||||
import { OH, OpeningHour } from "./OpeningHours"
|
import { OH, OpeningHour } from "./OpeningHours"
|
||||||
import { InputElement } from "../Input/InputElement"
|
import { InputElement } from "../Input/InputElement"
|
||||||
import PublicHolidayInput from "./PublicHolidayInput"
|
|
||||||
import Translations from "../i18n/Translations"
|
import Translations from "../i18n/Translations"
|
||||||
import BaseUIElement from "../BaseUIElement"
|
import BaseUIElement from "../BaseUIElement"
|
||||||
|
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||||
|
import PublicHolidaySelector from "./PublicHolidaySelector.svelte"
|
||||||
|
|
||||||
export default class OpeningHoursInput extends InputElement<string> {
|
export default class OpeningHoursInput extends InputElement<string> {
|
||||||
private readonly _value: UIEventSource<string>
|
private readonly _value: UIEventSource<string>
|
||||||
|
@ -87,19 +88,19 @@ export default class OpeningHoursInput extends InputElement<string> {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const phSelector = new PublicHolidayInput(new UIEventSource<string>(ph))
|
const phSelectorValue = new UIEventSource<string>(ph ?? "")
|
||||||
|
|
||||||
// Note: MUST be bound AFTER the leftover rules!
|
// Note: MUST be bound AFTER the leftover rules!
|
||||||
const rulesFromOhPicker: UIEventSource<OpeningHour[]> = valueWithoutPrefix.sync(
|
const rulesFromOhPicker: UIEventSource<OpeningHour[]> = valueWithoutPrefix.sync(
|
||||||
(str) => {
|
(str) => {
|
||||||
return OH.Parse(str)
|
return OH.Parse(str)
|
||||||
},
|
},
|
||||||
[leftoverRules, phSelector.GetValue()],
|
[leftoverRules, phSelectorValue],
|
||||||
(rules, oldString) => {
|
(rules, oldString) => {
|
||||||
// We always add a ';', to easily add new rules. We remove the ';' again at the end of the function
|
// We always add a ';', to easily add new rules. We remove the ';' again at the end of the function
|
||||||
// Important: spaces are _not_ allowed after a ';' as it'll destabilize the parsing!
|
// Important: spaces are _not_ allowed after a ';' as it'll destabilize the parsing!
|
||||||
let str = OH.ToString(rules) + ";"
|
let str = OH.ToString(rules) + ";"
|
||||||
const ph = phSelector.GetValue().data
|
const ph = phSelectorValue.data
|
||||||
if (ph) {
|
if (ph) {
|
||||||
str += ph + ";"
|
str += ph + ";"
|
||||||
}
|
}
|
||||||
|
@ -138,7 +139,7 @@ export default class OpeningHoursInput extends InputElement<string> {
|
||||||
|
|
||||||
const ohPicker = new OpeningHoursPicker(rulesFromOhPicker)
|
const ohPicker = new OpeningHoursPicker(rulesFromOhPicker)
|
||||||
|
|
||||||
this._element = new Combine([leftoverWarning, ohPicker, phSelector])
|
this._element = new Combine([leftoverWarning, ohPicker, new SvelteUIElement(PublicHolidaySelector, {value: phSelectorValue})])
|
||||||
}
|
}
|
||||||
|
|
||||||
GetValue(): UIEventSource<string> {
|
GetValue(): UIEventSource<string> {
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
import { OH } from "./OpeningHours"
|
|
||||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
|
||||||
import Combine from "../Base/Combine"
|
|
||||||
import { TextField } from "../Input/TextField"
|
|
||||||
import { DropDown } from "../Input/DropDown"
|
|
||||||
import { InputElement } from "../Input/InputElement"
|
|
||||||
import Translations from "../i18n/Translations"
|
|
||||||
import Toggle from "../Input/Toggle"
|
|
||||||
|
|
||||||
export default class PublicHolidayInput extends InputElement<string> {
|
|
||||||
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false)
|
|
||||||
|
|
||||||
private readonly _value: UIEventSource<string>
|
|
||||||
|
|
||||||
constructor(value: UIEventSource<string> = new UIEventSource<string>("")) {
|
|
||||||
super()
|
|
||||||
this._value = value
|
|
||||||
}
|
|
||||||
|
|
||||||
GetValue(): UIEventSource<string> {
|
|
||||||
return this._value
|
|
||||||
}
|
|
||||||
|
|
||||||
IsValid(_: string): boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InnerConstructElement(): HTMLElement {
|
|
||||||
const dropdown = new DropDown(Translations.t.general.opening_hours.open_during_ph.Clone(), [
|
|
||||||
{ shown: Translations.t.general.opening_hours.ph_not_known.Clone(), value: "" },
|
|
||||||
{ shown: Translations.t.general.opening_hours.ph_closed.Clone(), value: "off" },
|
|
||||||
{ shown: Translations.t.general.opening_hours.ph_open_as_usual.Clone(), value: "open" },
|
|
||||||
{ shown: Translations.t.general.opening_hours.ph_open.Clone(), value: " " },
|
|
||||||
]).SetClass("inline-block w-full")
|
|
||||||
/*
|
|
||||||
* Either "" (unknown), " " (opened) or "off" (closed)
|
|
||||||
* */
|
|
||||||
const mode = dropdown.GetValue()
|
|
||||||
|
|
||||||
const start = new TextField({
|
|
||||||
placeholder: "starthour",
|
|
||||||
htmlType: "time",
|
|
||||||
}).SetClass("inline-block")
|
|
||||||
const end = new TextField({
|
|
||||||
placeholder: "starthour",
|
|
||||||
htmlType: "time",
|
|
||||||
}).SetClass("inline-block")
|
|
||||||
|
|
||||||
const askHours = new Toggle(
|
|
||||||
new Combine([
|
|
||||||
Translations.t.general.opening_hours.opensAt.Clone(),
|
|
||||||
start,
|
|
||||||
Translations.t.general.opening_hours.openTill.Clone(),
|
|
||||||
end,
|
|
||||||
]),
|
|
||||||
undefined,
|
|
||||||
mode.map((mode) => mode === " ")
|
|
||||||
)
|
|
||||||
|
|
||||||
this.SetupDataSync(mode, start.GetValue(), end.GetValue())
|
|
||||||
|
|
||||||
return new Combine([dropdown, askHours]).SetClass("w-full flex").ConstructElement()
|
|
||||||
}
|
|
||||||
|
|
||||||
private SetupDataSync(
|
|
||||||
mode: UIEventSource<string>,
|
|
||||||
startTime: UIEventSource<string>,
|
|
||||||
endTime: UIEventSource<string>
|
|
||||||
) {
|
|
||||||
const value = this._value
|
|
||||||
value
|
|
||||||
.map((ph) => OH.ParsePHRule(ph))
|
|
||||||
.addCallbackAndRunD((parsed) => {
|
|
||||||
if (parsed === null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mode.setData(parsed.mode)
|
|
||||||
startTime.setData(parsed.start)
|
|
||||||
endTime.setData(parsed.end)
|
|
||||||
})
|
|
||||||
|
|
||||||
// We use this as a 'addCallbackAndRun'
|
|
||||||
mode.map(
|
|
||||||
(mode) => {
|
|
||||||
if (mode === undefined || mode === "") {
|
|
||||||
// not known
|
|
||||||
value.setData(undefined)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (mode === "off") {
|
|
||||||
value.setData("PH off")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (mode === "open") {
|
|
||||||
value.setData("PH open")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open during PH with special hours
|
|
||||||
if (startTime.data === undefined || endTime.data === undefined) {
|
|
||||||
// hours not filled in - not saveable
|
|
||||||
value.setData(undefined)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const oh = `PH ${startTime.data}-${endTime.data}`
|
|
||||||
value.setData(oh)
|
|
||||||
},
|
|
||||||
[startTime, endTime]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
95
src/UI/OpeningHours/PublicHolidaySelector.svelte
Normal file
95
src/UI/OpeningHours/PublicHolidaySelector.svelte
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<script lang="ts">
|
||||||
|
|
||||||
|
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||||
|
import Dropdown from "../Base/Dropdown.svelte"
|
||||||
|
import Tr from "../Base/Tr.svelte"
|
||||||
|
import Translations from "../i18n/Translations"
|
||||||
|
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||||
|
import { TextField } from "../Input/TextField"
|
||||||
|
import { OH } from "./OpeningHours"
|
||||||
|
|
||||||
|
export let value: UIEventSource<string>
|
||||||
|
let startValue: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||||
|
let endValue: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||||
|
|
||||||
|
const t = Translations.t.general.opening_hours
|
||||||
|
let mode = new UIEventSource("")
|
||||||
|
|
||||||
|
|
||||||
|
value
|
||||||
|
.map((ph) => OH.ParsePHRule(ph))
|
||||||
|
.addCallbackAndRunD((parsed) => {
|
||||||
|
if (parsed === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mode.setData(parsed.mode)
|
||||||
|
startValue.setData(parsed.start)
|
||||||
|
endValue.setData(parsed.end)
|
||||||
|
})
|
||||||
|
|
||||||
|
function updateValue() {
|
||||||
|
if (mode.data === undefined || mode.data === "") {
|
||||||
|
// not known
|
||||||
|
value.setData("")
|
||||||
|
} else if (mode.data === "off") {
|
||||||
|
value.setData("PH off")
|
||||||
|
} else if (mode.data === "open") {
|
||||||
|
value.setData("PH open")
|
||||||
|
} else if (startValue.data === undefined || endValue.data === undefined) {
|
||||||
|
// Open during PH with special hours
|
||||||
|
// hours not filled in - not saveable
|
||||||
|
value.setData(undefined)
|
||||||
|
} else {
|
||||||
|
value.setData(`PH ${startValue.data}-${endValue.data}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startValue.addCallbackAndRunD(() => updateValue())
|
||||||
|
endValue.addCallbackAndRunD(() => updateValue())
|
||||||
|
mode.addCallbackAndRunD(() => updateValue())
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
|
||||||
|
<Tr t={t.open_during_ph} />
|
||||||
|
|
||||||
|
<Dropdown value={mode}>
|
||||||
|
<option value={""}>
|
||||||
|
<Tr t={t.ph_not_known} />
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value={"off"}>
|
||||||
|
<Tr t={t.ph_closed} />
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value={"open"}>
|
||||||
|
<Tr t={t.ph_open_as_usual} />
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value={" "}> <!-- Yes, the value is a single space-->
|
||||||
|
<Tr t={t.ph_open} />
|
||||||
|
</option>
|
||||||
|
</Dropdown>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{#if $mode === " "}
|
||||||
|
<div class="flex">
|
||||||
|
<Tr t={t.opensAt} />
|
||||||
|
<ToSvelte construct={
|
||||||
|
|
||||||
|
new TextField({
|
||||||
|
value: startValue,
|
||||||
|
placeholder: "starthour",
|
||||||
|
htmlType: "time",
|
||||||
|
}).SetClass("inline-block")
|
||||||
|
} />
|
||||||
|
<Tr t={t.openTill} />
|
||||||
|
<ToSvelte construct={ new TextField({
|
||||||
|
value: endValue,
|
||||||
|
placeholder: "endhour",
|
||||||
|
htmlType: "time",
|
||||||
|
}).SetClass("inline-block")
|
||||||
|
} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
Loading…
Reference in a new issue