Files
wtr/lib/notification-api.ts
zv 91acdb39b8
Some checks failed
CI / Lint, test, typecheck and build (push) Has been cancelled
feat: add weather unit preferences
2026-07-04 20:16:11 +02:00

90 lines
3.2 KiB
TypeScript

import type { Language } from "@/lib/i18n";
import type { Province } from "@/types/province";
import type { DistanceUnit, PrecipitationUnit, PressureUnit, TemperatureUnit, WindSpeedUnit } from "@/types/units";
import type { WeatherRegion } from "@/types/weather-region";
interface VapidKeyResponse {
configured: boolean;
publicKey: string | null;
}
export async function fetchVapidPublicKey(signal?: AbortSignal) {
const response = await fetch("/api/notifications/vapid-key", { signal });
if (!response.ok) throw new Error("Unable to load Web Push configuration.");
return response.json() as Promise<VapidKeyResponse>;
}
interface SavePushSubscriptionOptions {
region?: WeatherRegion;
officialWarningsEnabled?: boolean;
morningBriefEnabled?: boolean;
tomorrowBriefEnabled?: boolean;
latitude?: number | null;
longitude?: number | null;
locationName?: string | null;
timezone?: string | null;
countyTeryt?: string | null;
temperatureUnit?: TemperatureUnit;
windSpeedUnit?: WindSpeedUnit;
precipitationUnit?: PrecipitationUnit;
pressureUnit?: PressureUnit;
distanceUnit?: DistanceUnit;
}
export async function savePushSubscription(
subscription: PushSubscription,
province: Province | null,
language: Language,
options: SavePushSubscriptionOptions = {},
) {
const response = await fetch("/api/notifications/subscriptions", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
subscription: subscription.toJSON(),
province,
language,
region: options.region ?? "PL",
enabled: options.officialWarningsEnabled ?? true,
morningBriefEnabled: options.morningBriefEnabled === true,
tomorrowBriefEnabled: options.tomorrowBriefEnabled === true,
latitude: options.latitude ?? null,
longitude: options.longitude ?? null,
locationName: options.locationName ?? null,
timezone: options.timezone ?? null,
countyTeryt: options.countyTeryt ?? null,
temperatureUnit: options.temperatureUnit,
windSpeedUnit: options.windSpeedUnit,
precipitationUnit: options.precipitationUnit,
pressureUnit: options.pressureUnit,
distanceUnit: options.distanceUnit,
}),
});
if (!response.ok) throw new Error("Unable to save push subscription.");
}
export async function deletePushSubscription(endpoint: string) {
const response = await fetch("/api/notifications/subscriptions", {
method: "DELETE",
headers: { "content-type": "application/json" },
body: JSON.stringify({ endpoint }),
});
if (!response.ok) throw new Error("Unable to delete push subscription.");
}
export async function sendTestPushNotification(endpoint: string) {
const response = await fetch("/api/notifications/test", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ endpoint }),
});
if (!response.ok) throw new Error("Unable to send test notification.");
}
export function decodeBase64UrlKey(value: string) {
const padding = "=".repeat((4 - (value.length % 4)) % 4);
const base64 = `${value}${padding}`.replace(/-/g, "+").replace(/_/g, "/");
const raw = window.atob(base64);
return Uint8Array.from(raw, (character) => character.charCodeAt(0));
}