Files
Checkmate/client/src/Pages/Notifications/index.tsx
T
gorkem-bwl 031a6fdf3c feat(client): unified EmptyState across all pages and table empties
- New EmptyState + EmptyStateIllustration components: stacked-cards SVG
  with grid background, theme-aware light/dark palette.
- Variants: default (centered with title + description), compact
  (horizontal, in-section), fullscreen (vertically centers in viewport).
- Wired into Checks, Incidents, Logs (Logs+Queue tabs), Notifications,
  Maintenance, Status pages, and Team tab — each with i18n title +
  description and a fullscreen layout when truly empty.
- Table.EmptyView now wraps the EmptyState in a divider-bordered card
  so short messages no longer look orphaned.
- Incidents Option-A short-circuit: when summary.total === 0, replace
  the whole page chrome with EmptyState; otherwise keep filters + cards.
- Fallback.tsx (BaseFallback / EmptyFallback / EmptyMonitorFallback /
  ErrorFallback) refactored to delegate to EmptyState.
2026-04-25 23:26:34 -04:00

73 lines
2.0 KiB
TypeScript

import { BasePageWithStates } from "@/Components/design-elements";
import { NotificationsTable } from "@/Pages/Notifications/components/NotificationsTable";
import { Dialog } from "@/Components/inputs";
import { HeaderCreate } from "@/Components/common";
import { useState } from "react";
import { useGet, useDelete } from "@/Hooks/UseApi";
import { useTranslation } from "react-i18next";
import type { Notification } from "@/Types/Notification";
import { useIsAdmin } from "@/Hooks/useIsAdmin";
const NotificationsPage = () => {
const { t } = useTranslation();
const isAdmin = useIsAdmin();
const [selectedChannel, setSelectedChannel] = useState<Notification | null>(null);
const isDialogOpen = Boolean(selectedChannel);
const {
data: notifications,
isLoading,
isValidating,
error,
refetch,
} = useGet<Notification[]>("/notifications/team", {}, { keepPreviousData: true });
const { deleteFn, loading: isDeleting } = useDelete();
const handleConfirm = async () => {
if (!selectedChannel) return;
await deleteFn(`/notifications/${selectedChannel.id}`);
setSelectedChannel(null);
refetch();
};
const handleCancel = () => {
setSelectedChannel(null);
};
return (
<BasePageWithStates
headerKey="notifications"
page={t("pages.notifications.fallback.title")}
description={t("pages.notifications.fallback.description")}
loading={isLoading || isValidating}
error={!!error}
totalCount={notifications?.length ?? 0}
actionButtonText={t("pages.notifications.fallback.actionButton")}
actionLink="/notifications/create"
>
<HeaderCreate
path="/notifications/create"
isLoading={isLoading || isValidating}
isAdmin={isAdmin}
/>
<NotificationsTable
notifications={notifications ?? []}
setSelectedChannel={setSelectedChannel}
/>
<Dialog
open={isDialogOpen}
title={t("common.dialogs.delete.title")}
content={t("common.dialogs.delete.description")}
onConfirm={handleConfirm}
onCancel={handleCancel}
loading={isDeleting}
/>
</BasePageWithStates>
);
};
export default NotificationsPage;