forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			125 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
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(t: string): boolean {
 | 
						|
        return true
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *
 | 
						|
     * // should construct an element
 | 
						|
     * const html = new PublicHolidayInput().InnerConstructElement()
 | 
						|
     * html !== undefined // => true
 | 
						|
     *
 | 
						|
     * // should construct an element despite having an invalid input
 | 
						|
     * const html = new PublicHolidayInput(new UIEventSource("invalid")).InnerConstructElement()
 | 
						|
     * html !== undefined // => true
 | 
						|
     *
 | 
						|
     * // should construct an element despite having null as input
 | 
						|
     * const html = new PublicHolidayInput(new UIEventSource(null)).InnerConstructElement()
 | 
						|
     * html !== undefined // => 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")
 | 
						|
        /*
 | 
						|
         * 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]).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]
 | 
						|
        )
 | 
						|
    }
 | 
						|
}
 |