UX: improvements to opening hours picker, fix some residual errors after refactoring
This commit is contained in:
parent
2569d0cb66
commit
b8264a3345
4 changed files with 102 additions and 23 deletions
|
@ -25,7 +25,7 @@
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const el = document.elementFromPoint(touch.clientX, touch.clientY)
|
const el = document.elementFromPoint(touch.clientX, touch.clientY)
|
||||||
if (!el) {
|
if (!el || !el.classList.contains("oh-timecell")) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
lastElement = <any>el
|
lastElement = <any>el
|
||||||
|
@ -46,12 +46,18 @@
|
||||||
if (el?.onmouseup) {
|
if (el?.onmouseup) {
|
||||||
el?.onmouseup(<any>ev)
|
el?.onmouseup(<any>ev)
|
||||||
}else{
|
}else{
|
||||||
|
// We dragged outside of the table
|
||||||
dispatch("clear")
|
dispatch("clear")
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
element.addEventListener("touchmove", ev => {
|
element.addEventListener("touchmove", ev => {
|
||||||
elementUnderTouch(ev)?.onmouseenter(<any>ev)
|
const underTouch = elementUnderTouch(ev)
|
||||||
|
if(typeof underTouch?.onmouseenter !== "function"){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
underTouch.onmouseenter(<any>ev)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
wd.sunday,
|
wd.sunday,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
let element: HTMLTableElement
|
||||||
|
|
||||||
function range(n: number) {
|
function range(n: number) {
|
||||||
return Utils.TimesT(n, n => n)
|
return Utils.TimesT(n, n => n)
|
||||||
}
|
}
|
||||||
|
@ -114,11 +116,29 @@
|
||||||
clearSelection()
|
clearSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let lasttouched: [number, number] = undefined
|
||||||
|
|
||||||
function moved(weekday: number, hour: number) {
|
function moved(weekday: number, hour: number) {
|
||||||
|
lasttouched = [weekday, hour]
|
||||||
if (selectionStart) {
|
if (selectionStart) {
|
||||||
clearSelection()
|
clearSelection()
|
||||||
setSelection(selectionStart[0], weekday, selectionStart[1], hour + 0.5)
|
setSelection(selectionStart[0], weekday, selectionStart[1], hour + 0.5)
|
||||||
}
|
}
|
||||||
|
const allRows = Array.from(element.getElementsByTagName("tr"))
|
||||||
|
for (const r of allRows) {
|
||||||
|
r.classList.remove("hover")
|
||||||
|
r.classList.remove("hovernext")
|
||||||
|
|
||||||
|
}
|
||||||
|
const selectedRow = allRows[hour * 2 + 2]
|
||||||
|
selectedRow?.classList?.add("hover")
|
||||||
|
const selectedNextRow = allRows[hour * 2 + 3]
|
||||||
|
selectedNextRow?.classList?.add("hovernext")
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseLeft() {
|
||||||
|
endSelection(...lasttouched)
|
||||||
}
|
}
|
||||||
|
|
||||||
let totalHeight = 0
|
let totalHeight = 0
|
||||||
|
@ -146,14 +166,20 @@
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<table class="oh-table no-weblate w-full" cellspacing="0" cellpadding="0">
|
<table
|
||||||
|
bind:this={element}
|
||||||
|
class="oh-table no-weblate w-full" cellspacing="0" cellpadding="0"
|
||||||
|
class:hasselection={selectionStart !== undefined} class:hasnoselection={selectionStart === undefined}
|
||||||
|
on:mouseleave={mouseLeft}>
|
||||||
<tr>
|
<tr>
|
||||||
|
<!-- Header row -->
|
||||||
<th style="width: 9%">
|
<th style="width: 9%">
|
||||||
<!-- Top-left cell -->
|
<!-- Top-left cell -->
|
||||||
|
<slot name="top-left">
|
||||||
<button class="absolute top-0 left-0 p-1 rounded-full" on:click={() => value.set([])} style="z-index: 10">
|
<button class="absolute top-0 left-0 p-1 rounded-full" on:click={() => value.set([])} style="z-index: 10">
|
||||||
<TrashIcon class="w-5 h-5" />
|
<TrashIcon class="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
|
</slot>
|
||||||
</th>
|
</th>
|
||||||
{#each days as wd}
|
{#each days as wd}
|
||||||
<th style="width: 13%">
|
<th style="width: 13%">
|
||||||
|
@ -162,14 +188,14 @@
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr class="h-0">
|
<tr class="h-0 nobold">
|
||||||
<!-- Virtual row to add the ranges to-->
|
<!-- Virtual row to add the ranges to-->
|
||||||
<td style="width: 9%" />
|
<td style="width: 9%" />
|
||||||
{#each range(7) as wd}
|
{#each range(7) as wd}
|
||||||
<td style="width: 13%; position: relative;">
|
<td style="width: 13%; position: relative;">
|
||||||
|
|
||||||
<div class="h-0 pointer-events-none" style="z-index: 10">
|
<div class="h-0 pointer-events-none" style="z-index: 10">
|
||||||
{#each $value.filter(oh => oh.weekday === wd) as range }
|
{#each $value.filter(oh => oh.weekday === wd).map(oh => OpeningHours.rangeAs24Hr(oh)) as range }
|
||||||
<div class="absolute pointer-events-none px-1 md:px-2 w-full "
|
<div class="absolute pointer-events-none px-1 md:px-2 w-full "
|
||||||
style={rangeStyle(range, totalHeight)}
|
style={rangeStyle(range, totalHeight)}
|
||||||
>
|
>
|
||||||
|
@ -180,7 +206,7 @@
|
||||||
<button class="w-fit rounded-full p-1 self-center pointer-events-auto"
|
<button class="w-fit rounded-full p-1 self-center pointer-events-auto"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
const cleaned = value.data.filter(v => !OpeningHours.isSame(v, range))
|
const cleaned = value.data.filter(v => !OpeningHours.isSame(v, range))
|
||||||
console.log("Cleaned", cleaned, value.data)
|
console.log("Cleaned", cleaned, OpeningHours.ToString(value.data))
|
||||||
value.set(cleaned)
|
value.set(cleaned)
|
||||||
}}>
|
}}>
|
||||||
<TrashIcon class="w-6 h-6" />
|
<TrashIcon class="w-6 h-6" />
|
||||||
|
@ -202,11 +228,13 @@
|
||||||
|
|
||||||
{#each range(24) as h}
|
{#each range(24) as h}
|
||||||
<tr style="height: 0.75rem; width: 9%"> <!-- even row, for the hour -->
|
<tr style="height: 0.75rem; width: 9%"> <!-- even row, for the hour -->
|
||||||
<td rowspan={ h < 23 ? 2: 1 }
|
<td rowspan={ h > 0 ? 2: 1 }
|
||||||
class="relative text-sm sm:text-base oh-left-col oh-timecell-full border-box interactive "
|
class="relative text-sm sm:text-base oh-left-col oh-timecell-full border-box interactive "
|
||||||
style={ h < 23 ? "top: 0.75rem" : "height:0; top: 0.75rem"}>
|
style={ h > 0 ? "top: -0.75rem" : "height:0; top: -0.75rem"}>
|
||||||
{#if h < 23}
|
{#if h > 0}
|
||||||
{h + 1}:00
|
<span class="hour-header w-full">
|
||||||
|
{h}:00
|
||||||
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
{#each range(7) as wd}
|
{#each range(7) as wd}
|
||||||
|
@ -215,12 +243,13 @@
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr style="height: 0.75rem"> <!-- odd row, for the half hour -->
|
<tr style="height: calc( 0.75rem - 1px) "> <!-- odd row, for the half hour -->
|
||||||
{#if h === 23}
|
{#if h === 0}
|
||||||
<td/>
|
<td/> <!-- extra cell to compensate for irregular header-->
|
||||||
{/if}
|
{/if}
|
||||||
{#each range(7) as wd}
|
{#each range(7) as wd}
|
||||||
<OHCell type="half" {h} {wd} on:start={() => startSelection(wd, h + 0.5)} on:end={() => endSelection(wd, h + 0.5)}
|
<OHCell type="half" {h} {wd} on:start={() => startSelection(wd, h + 0.5)}
|
||||||
|
on:end={() => endSelection(wd, h + 0.5)}
|
||||||
on:move={() => moved(wd, h + 0.5)} on:clear={() => clearSelection()} />
|
on:move={() => moved(wd, h + 0.5)} on:clear={() => clearSelection()} />
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -235,4 +264,25 @@
|
||||||
position: sticky;
|
position: sticky;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hasselection tr:hover .hour-header, .hasselection tr.hover .hour-header {
|
||||||
|
border-bottom: 2px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hasselection tr:hover + tr {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hasselection tr.hovernext {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hasnoselection tr:hover, .hasnoselection tr.hover {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
import OHTable from "./OpeningHours/OHTable.svelte"
|
import OHTable from "./OpeningHours/OHTable.svelte"
|
||||||
import OpeningHoursState from "../../OpeningHours/OpeningHoursState"
|
import OpeningHoursState from "../../OpeningHours/OpeningHoursState"
|
||||||
import Popup from "../../Base/Popup.svelte"
|
import Popup from "../../Base/Popup.svelte"
|
||||||
|
import CheckCircle from "@babeard/svelte-heroicons/mini/CheckCircle"
|
||||||
|
import Check from "@babeard/svelte-heroicons/mini/Check"
|
||||||
|
|
||||||
export let value: UIEventSource<string>
|
export let value: UIEventSource<string>
|
||||||
export let args: string
|
export let args: string
|
||||||
|
@ -34,9 +36,9 @@
|
||||||
</script>
|
</script>
|
||||||
<Popup bodyPadding="p-0" shown={expanded}>
|
<Popup bodyPadding="p-0" shown={expanded}>
|
||||||
<OHTable value={state.normalOhs} />
|
<OHTable value={state.normalOhs} />
|
||||||
<div class="absolute w-full pointer-events-none bottom-0 flex justify-end">
|
<button on:click={() => expanded.set(false)} class="absolute left-0 bottom-0 primary pointer-events-auto h-8 w-10 rounded-full">
|
||||||
<button on:click={() => expanded.set(false)} class="primary pointer-events-auto">Done</button>
|
<Check class="shrink-0 w-6 h-6 m-0 p-0" color="white"/>
|
||||||
</div>
|
</button>
|
||||||
</Popup>
|
</Popup>
|
||||||
<button on:click={() => expanded.set(true)}>Pick opening hours</button>
|
<button on:click={() => expanded.set(true)}>Pick opening hours</button>
|
||||||
<PublicHolidaySelector value={state.phSelectorValue} />
|
<PublicHolidaySelector value={state.phSelectorValue} />
|
||||||
|
|
|
@ -916,6 +916,27 @@ This list will be sorted
|
||||||
}
|
}
|
||||||
return ohs
|
return ohs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small utility function for the OH-table. if endHour is '0', rewrite this as '24'
|
||||||
|
*
|
||||||
|
* const oh = {
|
||||||
|
* weekday: 0,
|
||||||
|
* endMinutes: 0,
|
||||||
|
* endHour: 0,
|
||||||
|
* startHour: 10,
|
||||||
|
* startMinutes: 0
|
||||||
|
* }
|
||||||
|
* OH.rangeAs24Hr(oh).endHour // => 24
|
||||||
|
*/
|
||||||
|
static rangeAs24Hr(oh: OpeningHour) {
|
||||||
|
if(oh.endHour === 0){
|
||||||
|
return {
|
||||||
|
...oh, endHour : 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oh
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ToTextualDescription {
|
export class ToTextualDescription {
|
||||||
|
|
Loading…
Reference in a new issue