feat(reports): add reports page and export notification downloads

This commit is contained in:
2026-04-27 16:15:41 +03:30
parent 4befb50eb7
commit 61a1dc238d
13 changed files with 1978 additions and 9 deletions

View File

@@ -11,8 +11,10 @@ import {
import { toast } from "sonner"
import {
buildNotificationStreamUrl,
downloadNotificationFile,
deleteNotification,
getNotifications,
isReportExportDownloadUrl,
issueNotificationStreamToken,
markAllNotificationsRead,
markNotificationSeen,
@@ -120,11 +122,22 @@ export function NotificationsProvider({ children }: { children: ReactNode }) {
setNotifications((current) => current.filter((notification) => notification.id !== notificationId))
}, [])
const openNotificationTarget = useCallback((notification: NotificationItem) => {
const openNotificationTarget = useCallback(async (notification: NotificationItem) => {
const downloadUrl =
typeof notification.meta?.download_url === "string"
? notification.meta.download_url
: notification.action_url
if (downloadUrl && isReportExportDownloadUrl(downloadUrl)) {
await downloadNotificationFile(downloadUrl, typeof notification.meta?.file_name === "string" ? notification.meta.file_name : null)
return
}
if (!notification.action_url) {
return
}
window.location.assign(notification.action_url)
window.open(notification.action_url, "_blank", "noopener,noreferrer")
}, [])
const showIncomingToast = useCallback(
@@ -145,7 +158,9 @@ export function NotificationsProvider({ children }: { children: ReactNode }) {
action: notification.action_url
? {
label: t.notifications?.openAction || "Open",
onClick: () => openNotificationTarget(notification),
onClick: () => {
void openNotificationTarget(notification)
},
}
: undefined,
})
@@ -254,8 +269,12 @@ export function NotificationsProvider({ children }: { children: ReactNode }) {
const handleNotificationClick = useCallback(async (notification: NotificationItem) => {
await markAsSeen(notification)
openNotificationTarget(notification)
}, [markAsSeen, openNotificationTarget])
try {
await openNotificationTarget(notification)
} catch {
toast.error(t.notifications?.openError || "Failed to open notification")
}
}, [markAsSeen, openNotificationTarget, t.notifications])
const connectToStream = useCallback(async () => {
if (!getAccessToken()) {