* Extended functionalities

* Added different UIs
This commit is contained in:
2026-06-24 21:43:40 +02:00
parent 282f4864c4
commit f15bb7a916
348 changed files with 59057 additions and 498 deletions

View File

@@ -0,0 +1,57 @@
import { useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import { fetchDueReminders } from "@/api/diet.api";
import { isAuthenticated } from "@/store/authStore";
const POLL_MS = 60_000;
const notifiedKeys = new Set<string>();
function slotKey(id: number, date: string, hour: number, minute: number): string {
return `${date}:${hour}:${minute}:${id}`;
}
export function useReminderNotifications(): void {
const { t } = useTranslation();
const permissionRef = useRef<NotificationPermission | "unsupported">("default");
useEffect(() => {
if (typeof Notification === "undefined") {
permissionRef.current = "unsupported";
return;
}
permissionRef.current = Notification.permission;
if (Notification.permission === "default") {
void Notification.requestPermission().then((p) => {
permissionRef.current = p;
});
}
}, []);
useEffect(() => {
if (!isAuthenticated()) return;
const tick = async () => {
if (permissionRef.current !== "granted") return;
try {
const due = await fetchDueReminders();
const now = new Date();
const date = now.toISOString().slice(0, 10);
for (const r of due) {
const key = slotKey(r.id, date, now.getHours(), now.getMinutes());
if (notifiedKeys.has(key)) continue;
notifiedKeys.add(key);
new Notification(r.title, {
body: r.message ?? t("diet.reminderNotificationBody"),
tag: key,
});
}
} catch {
// ignore polling errors
}
};
void tick();
const id = window.setInterval(() => void tick(), POLL_MS);
return () => window.clearInterval(id);
}, [t]);
}