forked from MapComplete/MapComplete
123 lines
3.9 KiB
Svelte
123 lines
3.9 KiB
Svelte
|
<script lang="ts">
|
||
|
|
||
|
import PlusCircle from "@rgossiaux/svelte-heroicons/solid/PlusCircle"
|
||
|
import TimeInput from "../TimeInput.svelte"
|
||
|
import { TrashIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||
|
import Checkbox from "../../../Base/Checkbox.svelte"
|
||
|
import Tr from "../../../Base/Tr.svelte"
|
||
|
import { Stores, UIEventSource } from "../../../../Logic/UIEventSource"
|
||
|
import Translations from "../../../i18n/Translations"
|
||
|
import { OH } from "../../../OpeningHours/OpeningHours"
|
||
|
import { Utils } from "../../../../Utils"
|
||
|
|
||
|
export let value: UIEventSource<string>
|
||
|
|
||
|
const wt = Translations.t.general.weekdays.abbreviations
|
||
|
/*
|
||
|
Single rule for collection times, e.g. "Mo-Fr 10:00, 17:00"
|
||
|
*/
|
||
|
let weekdays: Translation[] = [wt.monday, wt.tuesday, wt.wednesday, wt.thursday, wt.friday, wt.saturday, wt.sunday, Translations.t.general.opening_hours.ph]
|
||
|
|
||
|
let initialTimes= Utils.NoEmpty(value.data?.split(" ")?.[1]?.split(",")?.map(s => s.trim())??[])
|
||
|
let values = new UIEventSource(initialTimes.map(t => new UIEventSource(t)))
|
||
|
if(values.data.length === 0){
|
||
|
values.data.push(new UIEventSource(""))
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
let daysOfTheWeek = [...OH.days, "PH"]
|
||
|
let selectedDays = daysOfTheWeek.map(() => new UIEventSource(false))
|
||
|
|
||
|
let initialDays = Utils.NoEmpty(value.data?.split(" ")?.[0]?.split(",") ?? [])
|
||
|
for (const initialDay of initialDays) {
|
||
|
if (initialDay.indexOf("-") > 0) {
|
||
|
let [start, end] = initialDay.split("-")
|
||
|
let startindex = daysOfTheWeek.indexOf(start)
|
||
|
let stopindex = daysOfTheWeek.indexOf(end)
|
||
|
for (let i = startindex; i <= stopindex; i++) {
|
||
|
selectedDays[i]?.set(true)
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
let index = daysOfTheWeek.indexOf(initialDay)
|
||
|
if (index >= 0) {
|
||
|
selectedDays[index]?.set(true)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let selectedDaysBound = Stores.concat(selectedDays)
|
||
|
.mapD(days => Utils.NoNull(days.map((selected, i) => selected ? daysOfTheWeek[i] : undefined)))
|
||
|
let valuesConcat: Store<string[]> = values.bindD(values => Stores.concat(values))
|
||
|
.mapD(values => Utils.NoEmpty(values))
|
||
|
valuesConcat.mapD(times => {
|
||
|
console.log(times)
|
||
|
times = Utils.NoNull(times)
|
||
|
if (!times || times?.length === 0) {
|
||
|
return undefined
|
||
|
}
|
||
|
times?.sort(/*concatted, new array*/)
|
||
|
return (Utils.NoEmpty(selectedDaysBound.data).join(",") + " " + times).trim()
|
||
|
}, [selectedDaysBound]).addCallbackAndRunD(v => value.set(v))
|
||
|
|
||
|
function selectWeekdays() {
|
||
|
for (let i = 0; i < 5; i++) {
|
||
|
selectedDays[i].set(true)
|
||
|
}
|
||
|
for (let i = 5; i < selectedDays.length; i++) {
|
||
|
selectedDays[i].set(false)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function clearDays() {
|
||
|
for (let i = 0; i < selectedDays.length; i++) {
|
||
|
selectedDays[i].set(false)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
</script>
|
||
|
|
||
|
<div class="rounded-xl my-2 p-2 low-interaction flex w-full justify-between flex-wrap">
|
||
|
|
||
|
<div class="flex flex-col">
|
||
|
|
||
|
<div class="flex flex-wrap">
|
||
|
{#each $values as value, i}
|
||
|
<div class="flex mx-4 gap-x-1 items-center">
|
||
|
<TimeInput {value} />
|
||
|
{#if $values.length > 1}
|
||
|
<button class="as-link">
|
||
|
<TrashIcon class="w-6 h-6" />
|
||
|
</button>
|
||
|
{/if}
|
||
|
</div>
|
||
|
{/each}
|
||
|
<button on:click={() => {values.data.push(new UIEventSource(undefined)); values.ping()}}>
|
||
|
<PlusCircle class="w-6 h-6" />
|
||
|
Add time
|
||
|
</button>
|
||
|
</div>
|
||
|
<div class="flex w-fit flex-wrap">
|
||
|
{#each daysOfTheWeek as day, i}
|
||
|
<div class="w-fit">
|
||
|
<Checkbox selected={selectedDays[i]}>
|
||
|
<Tr t={weekdays[i]} />
|
||
|
</Checkbox>
|
||
|
</div>
|
||
|
{/each}
|
||
|
</div>
|
||
|
|
||
|
</div>
|
||
|
<div class="flex flex-wrap justify-between w-full">
|
||
|
|
||
|
<div class="flex flex-wrap gap-x-4">
|
||
|
<button class="as-link text-sm" on:click={() => selectWeekdays()}>Select weekdays</button>
|
||
|
<button class="as-link text-sm" on:click={() => clearDays()}>Clear days</button>
|
||
|
|
||
|
</div>
|
||
|
<slot name="right" />
|
||
|
</div>
|
||
|
</div>
|