aboutsummaryrefslogtreecommitdiffstats
path: root/VegaData/wwwroot/index.js
diff options
context:
space:
mode:
authorivar <i@oiee.no>2025-10-26 11:33:38 +0100
committerivar <i@oiee.no>2025-10-26 11:33:38 +0100
commit2e8ad7dc6d49361c6ee00dc628e119c0c06e2779 (patch)
treebecc4cde99eff6ed1d168f9e9c454c0f2bbbee9d /VegaData/wwwroot/index.js
parent8de1187b627625b94ef8088de3e9255ccd17baf4 (diff)
downloadvegadata-2e8ad7dc6d49361c6ee00dc628e119c0c06e2779.tar.xz
vegadata-2e8ad7dc6d49361c6ee00dc628e119c0c06e2779.zip
.
Diffstat (limited to 'VegaData/wwwroot/index.js')
-rw-r--r--VegaData/wwwroot/index.js152
1 files changed, 152 insertions, 0 deletions
diff --git a/VegaData/wwwroot/index.js b/VegaData/wwwroot/index.js
new file mode 100644
index 0000000..45af7f2
--- /dev/null
+++ b/VegaData/wwwroot/index.js
@@ -0,0 +1,152 @@
+import { Temporal } from "temporal-polyfill";
+import { gqp, sqp, t } from "./framework.js";
+
+let _;
+
+async function getShows() {
+ if (_) return _;
+ const response = await fetch("/shows");
+ _ = await response.json();
+ return _;
+}
+
+const ulShows = document.getElementById("ulShows");
+const search = document.getElementById("search");
+const renderShowsBtn = document.getElementById("renderShowsBtn");
+
+renderShowsBtn.addEventListener("click", () => {
+ renderShows("");
+ search.value = "";
+});
+
+function dateString(date, small = false) {
+ const instant = Temporal.Instant.from(`${date}Z`)
+ const stringOptions = {
+ weekday: "long",
+ hour: "2-digit",
+ timeZone: "UTC",
+ minute: "2-digit",
+ month: "long",
+ calendar: "gregory",
+ day: "numeric"
+ }
+
+ if (small) {
+ return instant.toLocaleString("nb-NO", stringOptions);
+ }
+
+ return instant.toLocaleString("nb-NO", {
+ year: "numeric",
+ era: "long",
+ ...stringOptions
+ });
+}
+
+function copyLink(t, e) {
+ const initialInnerText = t.target.innerText;
+ if ("clipboard" in navigator) {
+ navigator.clipboard.writeText(`${location.origin}/index.html#${urlId(e)}`)
+ t.target.innerText = `${initialInnerText} ✓`
+ setTimeout(() => {
+ t.target.innerText = initialInnerText
+ }, 1000)
+ }
+}
+
+function vegascene(showing) {
+ if (showing.movieMainVersion.startsWith("KUL")) return `https://www.vegascene.no/teater/${showing.movieMainVersion}`
+ return `https://www.vegascene.no/film/${showing.movieMainVersion}`
+}
+
+function urlId(e) {
+ return `${e.movieVersion}${e.startDateTime}`.replaceAll("-", "").replaceAll(" ", "").replaceAll(":", "")
+}
+
+async function renderShows(query, rendered) {
+ query = query?.trim();
+ sqp({ q: query ?? "" })
+
+ const shows = (await getShows()).reduce((acc, curr) => {
+ const key = curr.title;
+ if (!acc[key]) {
+ acc[key] = [];
+ }
+ acc[key].push(curr);
+ return acc;
+ }, {});
+
+ async function share(show) {
+ const shareData = {
+ title: `${show.title} ${dateString(show.startDateTime, true)} på vega`,
+ url: `${location.origin}/index.html#${urlId(show)}`,
+ }
+ await navigator.share(shareData);
+ }
+
+ const lis = [];
+
+ for (const showKey of Object.keys(shows).sort((a, b) => a.localeCompare(b))) {
+ const times = shows[showKey].sort((a, b) => Temporal.PlainDate.compare(Temporal.PlainDate.from(a.startDateTime), Temporal.PlainDate.from(b.startDateTime)))
+ if (query) {
+ const words = [showKey.toLowerCase()]
+ for (const time of times) {
+ words.push(dateString(time.startDateTime))
+ words.push(time.scene)
+ words.push(time.tags.join(" "))
+ }
+ if (!words.some((word) => word.match(query.toLowerCase()))) continue;
+ }
+
+ lis.push(
+ t("li", { class: "show", id: showKey }, [
+ t("div", { class: "title" }, [
+ t("h2", { class: "italic" }, showKey),
+ t("a", { href: vegascene(shows[showKey][0]) }, "(Åpne på vegascene.no)")
+ ]),
+ t("ul", { id: "times" }, [
+ t("li", undefined,
+ times.filter(e => e.ticketUrl !== "").map(e => {
+ let tagLine = `${e.scene} - ${[e.type, ...e.tags].join(", ")}`
+ tagLine = tagLine[0].toUpperCase() + tagLine.slice(1)
+ let dateLine = dateString(e.startDateTime)
+ dateLine = dateLine[0].toUpperCase() + dateLine.slice(1)
+ return t("li", { class: `time time-${e.id}`, id: urlId(e) }, [
+ t("div", undefined, [
+ t("span", { title: e.startDateTime, class: "date" }, dateLine),
+ t("span", undefined, tagLine),
+ t("div", { class: "actions" }, [
+ t("a", { href: e.ticketUrl }, "Billetter"),
+ "share" in navigator ? t("button", { onclick: () => share(e) }, "Del tid") : null,
+ t("button", { onclick: (t) => copyLink(t, e) }, "Kopier lenke")
+ ])
+ ])
+ ])
+ }))
+ ])
+ ])
+ )
+ }
+
+ if (!lis.length) ulShows.replaceChildren(...[t("i", undefined, "Dessverre")])
+ else ulShows.replaceChildren(...lis);
+
+ const interval = setInterval(() => {
+ const element = document.querySelector("#ulShows");
+ if (element.childNodes.length > 0) {
+ clearInterval(interval);
+ rendered();
+ }
+ }, 50);
+}
+
+renderShows(search.value, () => {
+ if (gqp("q")) search.value = gqp("q")
+ search.addEventListener("input", e => renderShows(e.currentTarget.value));
+ const id = location.href.indexOf("#") !== -1 ? location.href.substring(location.href.indexOf("#")) : ""
+ if (id !== "") {
+ const target = document.querySelector(id)
+ target.scrollIntoView({ behavior: "smooth", block: "center" })
+ target.classList.add("activeShow")
+ document.querySelectorAll(".time").forEach(el => el.id !== id.slice(1) && el.classList.remove("activeShow"))
+ }
+}); \ No newline at end of file