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; } 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)); }