All files / react-app/src/api useGetSystemNotifs.ts

70.14% Statements 47/67
45.16% Branches 14/31
77.77% Functions 14/18
72.13% Lines 44/61

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118                      105x 13x   13x 26x 13x     105x 118x   118x 118x     105x 18x 18x   18x     105x 41x 41x   41x     105x 15x   105x 15x                       105x 14x 14x 13x   1x 1x       105x 47x 47x 47x   47x 15x 15x         15x     47x   12x     47x 47x 47x 47x   47x                     47x             47x                
import { useQuery } from "@tanstack/react-query";
import { API } from "aws-amplify";
import { useEffect, useState } from "react";
import {
  BannerNotificationSchema,
  ReactQueryApiError,
  ValidBannerNotification,
} from "shared-types";
 
import { useGetUser } from "@/api";
 
const mapValidNotifications = (notifications: unknown[]): ValidBannerNotification[] => {
  Iif (!Array.isArray(notifications)) return [];
 
  return notifications
    .filter((notification) => BannerNotificationSchema.safeParse(notification).success)
    .map((notification) => BannerNotificationSchema.parse(notification));
};
 
const getTime = (value?: string) => {
  Iif (!value) return null;
 
  const time = new Date(value).getTime();
  return Number.isNaN(time) ? null : time;
};
 
const sortByPublishedDateDesc = (a: ValidBannerNotification, b: ValidBannerNotification) => {
  const aTime = getTime(a.pubDate) ?? Number.NEGATIVE_INFINITY;
  const bTime = getTime(b.pubDate) ?? Number.NEGATIVE_INFINITY;
 
  return bTime - aTime;
};
 
const isActiveNotification = (notification: ValidBannerNotification, now: number) => {
  const pubDate = getTime(notification.pubDate);
  const expDate = getTime(notification.expDate);
 
  return pubDate !== null && expDate !== null && pubDate <= now && expDate > now;
};
 
const getNotificationStorageKey = (username?: string) =>
  username ? `notifs.${username}` : undefined;
 
const parseDismissedNotifications = (value: string | null): string[] => {
  Eif (!value) return [];
 
  try {
    const parsed = JSON.parse(value);
    return Array.isArray(parsed)
      ? parsed.filter((item): item is string => typeof item === "string")
      : [];
  } catch {
    return [];
  }
};
 
export const getSystemNotifs = async (): Promise<ValidBannerNotification[]> => {
  try {
    const notifications = await API.get("os", "/systemNotifs", {});
    return mapValidNotifications(notifications);
  } catch (error) {
    console.error("Error fetching notifications:", error);
    return [];
  }
};
 
export const useGetSystemNotifs = () => {
  const userQuery = useGetUser();
  const [dismissed, setDismissed] = useState<string[]>([]);
  const username = userQuery?.data?.user?.username;
 
  useEffect(() => {
    const storageKey = getNotificationStorageKey(username);
    Iif (!storageKey) {
      setDismissed([]);
      return;
    }
 
    setDismissed(parseDismissedNotifications(localStorage.getItem(storageKey)));
  }, [username]);
 
  const result = useQuery<ValidBannerNotification[], ReactQueryApiError>(
    ["systemBannerNotifs"],
    () => getSystemNotifs(),
  );
 
  const now = Date.now();
  const allNotifications = [...(result.data ?? [])].sort(sortByPublishedDateDesc);
  const notDismissed = allNotifications.filter((i) => !dismissed.includes(i.notifId));
  const currentNotifs = notDismissed.filter((i) => isActiveNotification(i, now));
 
  const clearNotif = (id?: string) => {
    const toBeRemoved = id ?? currentNotifs?.[0]?.notifId ?? "";
    const cleared = [...dismissed, toBeRemoved].filter((v, i, a) => a.indexOf(v) === i);
 
    setDismissed(cleared);
    const storageKey = getNotificationStorageKey(username);
    if (storageKey) {
      localStorage.setItem(storageKey, JSON.stringify(cleared));
    }
  };
 
  const resetNotifs = () => {
    setDismissed([]);
    const storageKey = getNotificationStorageKey(username);
    if (storageKey) {
      localStorage.setItem(storageKey, JSON.stringify([]));
    }
  };
  return {
    notifications: currentNotifs,
    dismissed: dismissed,
    allNotifications,
    clearNotif: clearNotif,
    resetNotifs: resetNotifs,
  };
};