brewlog/templates/base.html
Jon Seager 4fc81dd0c5
style(templates): modernize JS to arrow functions and const/let
Convert all remaining function declarations, var usage, and string
concatenation across base, add, checkin, and data templates.
2026-02-05 12:45:52 +00:00

99 lines
4.1 KiB
HTML

<!DOCTYPE html>
<html lang="en" data-star-root>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{% block title %}Brewlog{% endblock %}</title>
<link rel="stylesheet" href="/styles.css" />
<script src="https://cdn.tailwindcss.com"></script>
<script
type="module"
src="https://cdn.jsdelivr.net/gh/starfederation/datastar@1.0.0-RC.6/bundles/datastar.js"
></script>
{% block head %}{% endblock %}
<script>
document.addEventListener("DOMContentLoaded", () => {
const mobileQuery = window.matchMedia("(max-width: 767px)");
if (!mobileQuery.matches) return;
const setupInfiniteScroll = () => {
document.querySelectorAll("[data-infinite-scroll]").forEach((container) => {
const sentinel = container.querySelector(".infinite-scroll-sentinel");
if (!sentinel || sentinel.dataset.observed) return;
sentinel.dataset.observed = "true";
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const nextUrl = container.getAttribute("data-next-url");
const targetSelector = container.getAttribute("data-target");
if (!nextUrl || !targetSelector) {
observer.disconnect();
return;
}
observer.disconnect();
sentinel.remove();
fetch(nextUrl, {
headers: { "datastar-request": "true" },
})
.then((res) => res.text())
.then((html) => {
const doc = new DOMParser().parseFromString(html, "text/html");
const newTarget = doc.querySelector(targetSelector);
if (!newTarget) return;
// Append new rows to existing tbody
const existingTbody = container.querySelector("tbody");
const newTbody = newTarget.querySelector("tbody");
if (existingTbody && newTbody) {
Array.from(newTbody.children).forEach((row) => {
existingTbody.appendChild(document.adoptNode(row));
});
}
// Check if there are more pages
const newContainer = newTarget.querySelector("[data-infinite-scroll]");
const newNextUrl = newContainer && newContainer.getAttribute("data-next-url");
if (newNextUrl) {
container.setAttribute("data-next-url", newNextUrl);
const newSentinel = document.createElement("div");
newSentinel.className = "infinite-scroll-sentinel h-4 md:hidden";
newSentinel.setAttribute("aria-hidden", "true");
container.appendChild(newSentinel);
setupInfiniteScroll();
} else {
container.removeAttribute("data-next-url");
container.removeAttribute("data-infinite-scroll");
}
});
});
},
{ rootMargin: "200px" }
);
observer.observe(sentinel);
});
};
setupInfiniteScroll();
const bodyObserver = new MutationObserver(() => {
setupInfiniteScroll();
});
bodyObserver.observe(document.body, { childList: true, subtree: true });
});
</script>
</head>
<body class="min-h-screen bg-amber-50 text-stone-900">
<main class="mx-auto flex w-full max-w-5xl flex-col gap-8 px-6 py-10">
{% include "nav.html" %} {% block content %}{% endblock %}
<footer class="mt-8 text-xs text-stone-500">
<p>Built with Axum, Tailwind CSS, and Datastar.</p>
</footer>
</main>
</body>
</html>