mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 16:56:22 +02:00
80 lines
2.3 KiB
TypeScript
80 lines
2.3 KiB
TypeScript
import type { Announcement } from "@/contracts/types/announcement.types";
|
|
|
|
/**
|
|
* Returns true when the current time falls within the announcement's
|
|
* [startTime, endTime] window. Returns false for invalid windows
|
|
* (endTime before startTime) or when now is outside the range.
|
|
*/
|
|
export function isAnnouncementActive(announcement: Announcement, now = new Date()): boolean {
|
|
const start = new Date(announcement.startTime).getTime();
|
|
const end = new Date(announcement.endTime).getTime();
|
|
|
|
if (Number.isNaN(start) || Number.isNaN(end) || end < start) return false;
|
|
|
|
const nowMs = now.getTime();
|
|
return nowMs >= start && nowMs <= end;
|
|
}
|
|
|
|
/**
|
|
* Returns true when the announcement's audience matches the viewer context.
|
|
* - `"all"` — visible to everyone
|
|
* - `"users"` — visible only to authenticated users
|
|
* - `"web_visitors"` — visible only to unauthenticated visitors
|
|
*/
|
|
export function announcementMatchesAudience(
|
|
announcement: Announcement,
|
|
isAuthenticated: boolean
|
|
): boolean {
|
|
switch (announcement.audience) {
|
|
case "all":
|
|
return true;
|
|
case "users":
|
|
return isAuthenticated;
|
|
case "web_visitors":
|
|
return !isAuthenticated;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filter announcements to only those that are currently active and
|
|
* targeted at the given audience.
|
|
*/
|
|
export function getActiveAnnouncements(
|
|
announcements: Announcement[],
|
|
isAuthenticated: boolean,
|
|
now = new Date()
|
|
): Announcement[] {
|
|
return announcements.filter(
|
|
(a) => isAnnouncementActive(a, now) && announcementMatchesAudience(a, isAuthenticated)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns the number of milliseconds until the next announcement either
|
|
* starts or expires. Returns `null` when there are no upcoming transitions.
|
|
* Useful for scheduling re-renders so the UI updates automatically.
|
|
*/
|
|
export function msUntilNextTransition(
|
|
announcements: Announcement[],
|
|
now = new Date()
|
|
): number | null {
|
|
const nowMs = now.getTime();
|
|
let nearest: number | null = null;
|
|
|
|
for (const a of announcements) {
|
|
const start = new Date(a.startTime).getTime();
|
|
const end = new Date(a.endTime).getTime();
|
|
if (Number.isNaN(start) || Number.isNaN(end) || end < start) continue;
|
|
|
|
for (const edge of [start, end]) {
|
|
if (edge > nowMs) {
|
|
const diff = edge - nowMs;
|
|
if (nearest === null || diff < nearest) nearest = diff;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nearest;
|
|
}
|