Skip to content

Commit

Permalink
add dagsen info page
Browse files Browse the repository at this point in the history
  • Loading branch information
marnym committed Apr 25, 2024
1 parent fbc2bbb commit 3826c62
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 23 deletions.
22 changes: 19 additions & 3 deletions dagsen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ export type Menu = {
extra?: string;
};

export async function fetchMenu(
day: 0 | 1 = dayNumber(helsinkiDate()),
): Promise<Menu | null> {
export const LANGUAGES = ["sv", "fi", "en"] as const;
export type Language = typeof LANGUAGES[number];

export async function fetchMenuJSON(day: 0 | 1 = dayNumber(helsinkiDate())): Promise<Menu | null> {
try {
const res = await fetch(`http://api.teknolog.fi/taffa/sv/json/${day}`);
return res.json();
Expand All @@ -22,6 +23,16 @@ export async function fetchMenu(
}
}

export async function fetchMenuText(lang: Language): Promise<string | null> {
try {
const res = await fetch(`http://api.teknolog.fi/taffa/${lang}/today`);
return res.text();
} catch (e) {
console.error("Failed to fetch menu from lunch API:", e);
return null;
}
}

function dayNumber(now: Date): 0 | 1 {
const weekday = now.getDay();
return 0 < weekday && weekday < 6 && now.getHours() >= 15 ? 1 : 0;
Expand All @@ -39,3 +50,8 @@ export async function fetchAlaCarte(): Promise<string | null> {
return null;
}
}

export function openTime(now: Date): string {
const weekday = now.getDay();
return 0 < weekday && weekday < 6 ? "10:30 - 15:00" : "";
}
12 changes: 9 additions & 3 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
{
"deno.enable": true,
"deno.lint": true,
"deno.unstable": true,
"deno.enable": true,
"deno.lint": true,
"deno.unstable": true,
"fmt": {
"lineWidth": 120
},
"tasks": {
"dev": "deno run --watch --allow-read --allow-env --allow-net main.ts"
}
}
83 changes: 66 additions & 17 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import "https://deno.land/[email protected]/dotenv/load.ts";
import { serveDir } from "https://deno.land/[email protected]/http/file_server.ts";
import { Eta } from "https://deno.land/x/[email protected]/src/index.ts";
import { fetchAlaCarte, fetchMenu, Menu } from "./dagsen.ts";
import { Page } from "./page.ts";
import { createPage } from "./page.ts";
import { fetchAlaCarte, fetchMenuJSON, fetchMenuText, Language, LANGUAGES, Menu, openTime } from "./dagsen.ts";
import { createPage, Page } from "./page.ts";
import { helsinkiDate } from "./date.ts";

const {
Expand Down Expand Up @@ -37,7 +36,8 @@ const PAGES: readonly Page[] = [
] as const;

async function handler(req: Request): Promise<Response> {
const pathname = new URL(req.url).pathname;
const url = new URL(req.url);
const pathname = url.pathname;

if (pathname.startsWith("/static")) {
return serveDir(req, {
Expand All @@ -46,6 +46,8 @@ async function handler(req: Request): Promise<Response> {
});
}

if (pathname.startsWith("/dagsen")) return dagsenHandler(url.searchParams);

const pages = PAGES
.filter((p) => p.condition())
.map((p) => p.id);
Expand Down Expand Up @@ -77,10 +79,7 @@ async function handler(req: Request): Promise<Response> {

Deno.serve(handler);

async function pageHandler(
pages: readonly string[],
match: URLPatternResult,
): Promise<Response> {
async function pageHandler(pages: readonly string[], match: URLPatternResult): Promise<Response> {
const pageId = match.pathname.groups.id ?? "";
if (!pages.includes(pageId)) {
return new Response("Page not found", { status: 404 });
Expand All @@ -93,6 +92,29 @@ async function pageHandler(
});
}

async function dagsenHandler(params: URLSearchParams): Promise<Response> {
let lang = params.get("lang") as Language | null;

if (lang !== null) {
const renderData = await fetchDagsenRenderData(lang);
const html = await eta.renderAsync("dagsen/menu", renderData);
return new Response(html, {
headers: new Headers({ "Content-Type": "text/html" }),
});
}

lang = lang ?? "sv";
if (!LANGUAGES.includes(lang)) {
lang = "sv";
}

const renderData = await fetchDagsenRenderData(lang);
const html = await eta.renderAsync("dagsen/index", renderData);
return new Response(html, {
headers: new Headers({ "Content-Type": "text/html" }),
});
}

async function fetchPiTemp(): Promise<number | null> {
try {
const res = await fetch("https://mask.tf.fi/data/pi/temperature");
Expand All @@ -115,13 +137,10 @@ type RenderData = {
votes: typeof VOTES_URL;
};

async function fetchRenderData(
pages: readonly string[],
pageId: string,
): Promise<RenderData> {
async function fetchRenderData(pages: readonly string[], pageId: string): Promise<RenderData> {
const res = await Promise.all([
fetchPiTemp(),
fetchMenu(),
fetchMenuJSON(),
fetchAlaCarte(),
]);

Expand All @@ -141,6 +160,33 @@ async function fetchRenderData(
};
}

type DagsenRenderData = {
date: string;
menuItems: string[];
openTime: string;
nextPage: string;
pageTimeout: string;
};

async function fetchDagsenRenderData(language: Language): Promise<DagsenRenderData> {
const now = new Date();

const date = now.toLocaleDateString("en-GB", { year: "2-digit", month: "2-digit", "day": "2-digit" })
.split("/")
.slice(0, 2)
.join("/");

const menuItems = (await fetchMenuText(language))?.split("\r\n") ?? [];

return {
date,
menuItems: menuItems,
openTime: openTime(now),
nextPage: nextDagsenPage(LANGUAGES, language),
pageTimeout: "5s",
};
}

/**
* @param refreshTime time in format of HH:MM
*/
Expand All @@ -158,11 +204,14 @@ function calculateSecondsUntilRefresh(now: Date, refreshTime: string): number {
return (refreshDate.getTime() - now.getTime()) / 1000;
}

function nextPage(
pages: readonly string[],
currentPage: PageResponse["id"],
): PageResponse["id"] {
function nextPage(pages: readonly string[], currentPage: PageResponse["id"]): PageResponse["id"] {
const pagesLength = pages.length;
const nextIndex = pages.indexOf(currentPage) + 1;
return `/pages/${pages[nextIndex % pagesLength]}`;
}

function nextDagsenPage(languages: readonly Language[], currentLanguage: Language): string {
const languagesLength = languages.length;
const nextIndex = languages.indexOf(currentLanguage) + 1;
return `/dagsen?lang=${languages[nextIndex % languagesLength]}`;
}
Binary file added public/dagsen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions templates/dagsen/index.eta
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="sv">

<head>
<title>Dagsen - Meny</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/static/scripts/htmx.min.js"></script>
<style>
body {
text-align: center;
font-family: "Montserrat", sans-serif;
}

h1 {
font-size: 4em;
}

#menu {
font-size: 2em;
}

#open-time {
font-size: 1.5em;
font-weight: bold;
}
</style>
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet">
</head>

<body>
<!-- Beautiful -->
<br />
<br />
<br />

<img src="/static/dagsen.png" width="400px" />
<%~ include("./menu.eta", it) %>
</body>

</html>
20 changes: 20 additions & 0 deletions templates/dagsen/menu.eta
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div hx-get="<%~ it.nextPage %>" hx-trigger="every <%= it.pageTimeout %>" hx-swap="outerHTML">
<h1>
<%= it.date %>
</h1>

<div id="menu">
<% it.menuItems.forEach((menuItem) => { %>
<p>
<strong>
<%= menuItem %>
</strong>
</p>
<% }) %>
</div>

<br />
<p id="open-time">
<%= it.openTime %>
</p>
</div>

0 comments on commit 3826c62

Please sign in to comment.