advent22/ui/src/components/Calendar.vue
Jörn-Michael Miehe fd1a66ba25 🔧 ui: overall typescript compliance
- reduce use of `as` in favor of Vue's `UnwrapRef`
- add `wait_for` helper function

⚠️ known bug: PreviewDoor (DoorChooser) onClick not working
2025-12-25 19:56:25 +00:00

110 lines
2.8 KiB
Vue

<!-- eslint-disable vue/multi-word-component-names -->
<template>
<MultiModal @handle="on_modal_handle" />
<BulmaToast @handle="on_toast_handle" class="content">
<p>
Du hast noch keine Türchen geöffnet, vielleicht gibt es ein Anzeigeproblem
in Deinem Webbrowser?
</p>
<div class="level">
<div class="level-item">
<BulmaButton
class="is-success"
text="Türchen anzeigen"
@click.left="
store.is_touch_device = true;
toast?.hide();
"
/>
</div>
<div class="level-item">
<BulmaButton
class="is-danger"
text="Ich möchte selbst suchen"
@click.left="toast?.hide()"
/>
</div>
</div>
</BulmaToast>
<figure>
<div class="image is-unselectable">
<img :src="ensure_loaded(store.background_image).data_url" />
<ThouCanvas>
<CalendarDoor
v-for="(door, index) in doors"
:key="`door-${index}`"
:door="door"
:visible="store.is_touch_device"
:title="name_door(door.day)"
@click="door_click(door.day)"
style="cursor: pointer"
/>
</ThouCanvas>
</div>
</figure>
</template>
<script setup lang="ts">
import { API } from "@/lib/api";
import { APIError } from "@/lib/api_error";
import { ensure_loaded, Like, name_door } from "@/lib/helpers";
import { ImageData } from "@/lib/model";
import { Door } from "@/lib/rects/door";
import { advent22Store } from "@/lib/store";
import { onBeforeUnmount } from "vue";
import MultiModal, { HMultiModal } from "./MultiModal.vue";
import BulmaButton from "./bulma/Button.vue";
import BulmaToast, { HBulmaToast } from "./bulma/Toast.vue";
import CalendarDoor from "./calendar/CalendarDoor.vue";
import ThouCanvas from "./calendar/ThouCanvas.vue";
defineProps<{
doors: Like<Door>[];
}>();
const store = advent22Store();
let modal: HMultiModal | undefined;
let toast: HBulmaToast | undefined;
let toast_timeout: number | undefined;
function on_modal_handle(handle: HMultiModal) {
modal = handle;
}
function on_toast_handle(handle: HBulmaToast) {
toast = handle;
if (store.is_touch_device) return;
store.when_initialized(() => {
toast_timeout = window.setTimeout(() => {
if (store.user_doors.length === 0) return;
if (store.is_touch_device) return;
toast!.show({ duration: 600000, type: "is-warning" });
}, 10e3);
});
}
async function door_click(day: number) {
window.clearTimeout(toast_timeout);
toast?.hide();
if (modal === undefined) return;
modal.show_loading();
try {
const day_image = await API.request<ImageData>(`user/image_${day}`);
modal.show_image(day_image.data_url, name_door(day));
} catch (error) {
APIError.alert(error);
modal.hide();
}
}
onBeforeUnmount(() => toast?.hide());
</script>