feat(dashboard): persist notification center state

This commit is contained in:
Felipe Coutinho
2026-03-25 00:29:24 +00:00
parent 50477fb1be
commit 5f70421f5a
20 changed files with 1620 additions and 407 deletions

View File

@@ -31,6 +31,7 @@ export const revalidateConfig = {
budgets: ["/budgets"],
payers: ["/payers"],
notes: ["/notes", "/notes/archived", "/dashboard"],
notifications: ["/dashboard"],
transactions: ["/transactions", "/accounts"],
inbox: ["/inbox", "/transactions", "/dashboard"],
} as const;
@@ -43,6 +44,7 @@ const DASHBOARD_ENTITIES: ReadonlySet<string> = new Set([
"budgets",
"payers",
"notes",
"notifications",
"inbox",
"recurring",
]);

View File

@@ -0,0 +1,16 @@
/**
* Detecta se um erro indica que a tabela `dashboard_notification_states`
* ainda nao existe no banco (migration pendente).
*/
export function isNotificationStatesTableMissing(error: unknown): boolean {
if (!(error instanceof Error)) {
return false;
}
const message = error.message.toLowerCase();
return (
message.includes("dashboard_notification_states") &&
(message.includes("does not exist") || message.includes("relation"))
);
}

View File

@@ -1,3 +1,4 @@
export * from "./actions";
export * from "./calendar";
export * from "./notifications";
export * from "./reports";

View File

@@ -0,0 +1,39 @@
export type NotificationType = "overdue" | "due_soon";
export type BudgetStatus = "exceeded" | "critical";
export type DashboardNotificationStateFields = {
notificationKey: string;
fingerprint: string;
href: string;
isRead: boolean;
isArchived: boolean;
readAt: Date | null;
archivedAt: Date | null;
};
export type DashboardNotification = {
type: "invoice" | "boleto";
name: string;
dueDate: string;
status: NotificationType;
amount: number;
period?: string;
showAmount: boolean;
cardLogo?: string | null;
} & DashboardNotificationStateFields;
export type BudgetNotification = {
categoryName: string;
budgetAmount: number;
spentAmount: number;
usedPercentage: number;
status: BudgetStatus;
} & DashboardNotificationStateFields;
export type DashboardNotificationsSnapshot = {
notifications: DashboardNotification[];
budgetNotifications: BudgetNotification[];
unreadCount: number;
visibleCount: number;
};