feat(dashboard): novos widgets de anexos, inbox e tendências de categoria

- Widget Anexos: resumo de arquivos do período (total, imagens, PDFs, recentes)
- Widget Inbox: snapshot de pré-lançamentos pendentes do Companion
- Widget Tendências de Categoria: redireciona para relatório de tendências
- fetch-dashboard-data: busca attachmentsSnapshot e inboxSnapshot em paralelo
- widgets-config: tipo DashboardWidgetQuickActionOptions centralizado; props
  adminPayerSlug e quickActionOptions adicionadas ao contrato do widget
- dashboard-grid-editable: usa o novo tipo unificado de quickActionOptions
- proxy.ts: frame-src adicionado à CSP para preview de PDFs via S3
- rota /attachments criada com layout próprio

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-04-11 17:51:09 +00:00
parent dfb4126b12
commit 7a3bff52ac
9 changed files with 766 additions and 94 deletions

View File

@@ -1,7 +1,9 @@
import { cacheLife, cacheTag } from "next/cache";
import { fetchAttachmentsForPeriod } from "@/features/attachments/queries";
import { fetchDashboardAccounts } from "./accounts-queries";
import { fetchDashboardCategoryOverview } from "./category-overview-queries";
import { fetchDashboardCurrentPeriodOverview } from "./current-period-overview-queries";
import { fetchDashboardInboxSnapshot } from "./inbox-snapshot-queries";
import { fetchDashboardInvoices } from "./invoices-queries";
import { fetchDashboardNotes } from "./notes-queries";
import { fetchDashboardPayers } from "./payers-queries";
@@ -16,6 +18,8 @@ async function fetchDashboardDataInternal(userId: string, period: string) {
categoryOverview,
pagadoresSnapshot,
notesData,
allAttachments,
inboxSnapshot,
] = await Promise.all([
fetchDashboardPeriodOverview(userId, period),
fetchDashboardAccounts(userId),
@@ -24,8 +28,27 @@ async function fetchDashboardDataInternal(userId: string, period: string) {
fetchDashboardCategoryOverview(userId, period),
fetchDashboardPayers(userId, period),
fetchDashboardNotes(userId),
fetchAttachmentsForPeriod(userId, period),
fetchDashboardInboxSnapshot(userId),
]);
const attachmentsSnapshot = allAttachments.reduce(
(acc, attachment, index) => {
acc.totalBytes += attachment.fileSize;
if (attachment.mimeType.startsWith("image/")) acc.imageCount++;
if (attachment.mimeType === "application/pdf") acc.pdfCount++;
if (index < 5) acc.recentAttachments.push(attachment);
return acc;
},
{
totalCount: allAttachments.length,
totalBytes: 0,
imageCount: 0,
pdfCount: 0,
recentAttachments: [] as typeof allAttachments,
},
);
return {
metrics: periodOverview.metrics,
accountsSnapshot,
@@ -46,6 +69,8 @@ async function fetchDashboardDataInternal(userId: string, period: string) {
purchasesByCategoryData: currentPeriodOverview.purchasesByCategoryData,
incomeByCategoryData: categoryOverview.incomeByCategoryData,
expensesByCategoryData: categoryOverview.expensesByCategoryData,
attachmentsSnapshot,
inboxSnapshot,
};
}