Initial commit
This commit is contained in:
239
src/app/page.tsx
Normal file
239
src/app/page.tsx
Normal file
@@ -0,0 +1,239 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import { DashboardShell } from "@/components/dashboard/dashboard-shell";
|
||||
import { getCurrentAccountingPeriod } from "@/lib/accounting-periods";
|
||||
import { getRollbackMetadata } from "@/lib/audit-log";
|
||||
import type {
|
||||
DashboardAccountingPeriod,
|
||||
DashboardAuditLog,
|
||||
DashboardManagedUser,
|
||||
DashboardViewer,
|
||||
DashboardWorkingGroup
|
||||
} from "@/lib/dashboard-types";
|
||||
import { canManageUsers } from "@/lib/domain";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { getCurrentViewer } from "@/lib/session";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const viewer = await getCurrentViewer();
|
||||
|
||||
if (!viewer) {
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const currentPeriod = await getCurrentAccountingPeriod();
|
||||
|
||||
if (!currentPeriod) {
|
||||
throw new Error("Kein Abrechnungszeitraum gefunden.");
|
||||
}
|
||||
|
||||
const accountingPeriods = await prisma.accountingPeriod.findMany({
|
||||
orderBy: {
|
||||
startsAt: "desc"
|
||||
}
|
||||
});
|
||||
|
||||
const workingGroups = await prisma.workingGroup.findMany({
|
||||
include: {
|
||||
members: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
username: true,
|
||||
role: true
|
||||
}
|
||||
},
|
||||
budgets: {
|
||||
where: {
|
||||
periodId: currentPeriod.id
|
||||
},
|
||||
orderBy: {
|
||||
name: "asc"
|
||||
},
|
||||
include: {
|
||||
expenses: {
|
||||
orderBy: {
|
||||
createdAt: "desc"
|
||||
},
|
||||
include: {
|
||||
creator: {
|
||||
select: {
|
||||
id: true,
|
||||
username: true
|
||||
}
|
||||
},
|
||||
approvals: {
|
||||
orderBy: {
|
||||
timestamp: "asc"
|
||||
},
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
username: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: {
|
||||
name: "asc"
|
||||
}
|
||||
});
|
||||
|
||||
const managedUsers = canManageUsers(viewer.role)
|
||||
? await prisma.user.findMany({
|
||||
include: {
|
||||
workingGroup: {
|
||||
select: {
|
||||
name: true
|
||||
}
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
approvals: true,
|
||||
createdExpenses: true
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: [
|
||||
{
|
||||
role: "asc"
|
||||
},
|
||||
{
|
||||
username: "asc"
|
||||
}
|
||||
]
|
||||
})
|
||||
: [];
|
||||
|
||||
const auditLogs = canManageUsers(viewer.role)
|
||||
? await prisma.auditLog.findMany({
|
||||
orderBy: {
|
||||
createdAt: "desc"
|
||||
},
|
||||
take: 120,
|
||||
include: {
|
||||
actor: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
username: true,
|
||||
role: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
: [];
|
||||
|
||||
const serializedViewer: DashboardViewer = {
|
||||
id: viewer.id,
|
||||
name: viewer.username,
|
||||
username: viewer.username,
|
||||
role: viewer.role,
|
||||
workingGroupId: viewer.workingGroupId,
|
||||
approvalPreference: viewer.approvalPreference
|
||||
};
|
||||
|
||||
const serializedGroups: DashboardWorkingGroup[] = workingGroups.map((workingGroup) => ({
|
||||
id: workingGroup.id,
|
||||
name: workingGroup.name,
|
||||
totalBudget: workingGroup.budgets.reduce((sum, budget) => sum + Number(budget.totalBudget), 0),
|
||||
members: workingGroup.members.map((member) => ({
|
||||
id: member.id,
|
||||
name: member.username,
|
||||
username: member.username,
|
||||
role: member.role
|
||||
})),
|
||||
budgets: workingGroup.budgets.map((budget) => ({
|
||||
id: budget.id,
|
||||
name: budget.name,
|
||||
totalBudget: Number(budget.totalBudget),
|
||||
colorCode: budget.colorCode,
|
||||
periodId: budget.periodId,
|
||||
expenses: budget.expenses.map((expense) => ({
|
||||
id: expense.id,
|
||||
title: expense.title,
|
||||
description: expense.description,
|
||||
amount: Number(expense.amount),
|
||||
budgetId: expense.budgetId,
|
||||
periodId: expense.periodId,
|
||||
approvalStatus: expense.approvalStatus,
|
||||
recurrence: expense.recurrence,
|
||||
paidAt: expense.paidAt?.toISOString() ?? null,
|
||||
documentedAt: expense.documentedAt?.toISOString() ?? null,
|
||||
proofUrl: expense.proofUrl,
|
||||
createdAt: expense.createdAt.toISOString(),
|
||||
creator: {
|
||||
id: expense.creator.id,
|
||||
name: expense.creator.username
|
||||
},
|
||||
approvals: expense.approvals.map((approval) => ({
|
||||
id: approval.id,
|
||||
approvalType: approval.approvalType,
|
||||
timestamp: approval.timestamp.toISOString(),
|
||||
user: {
|
||||
id: approval.user.id,
|
||||
name: approval.user.username
|
||||
}
|
||||
}))
|
||||
}))
|
||||
}))
|
||||
}));
|
||||
|
||||
const serializedUsers: DashboardManagedUser[] = managedUsers.map((user) => ({
|
||||
id: user.id,
|
||||
name: user.username,
|
||||
username: user.username,
|
||||
role: user.role,
|
||||
workingGroupId: user.workingGroupId,
|
||||
workingGroupName: user.workingGroup?.name ?? null,
|
||||
approvalPreference: user.approvalPreference,
|
||||
createdExpensesCount: user._count.createdExpenses,
|
||||
approvalsCount: user._count.approvals
|
||||
}));
|
||||
|
||||
const serializedPeriods: DashboardAccountingPeriod[] = accountingPeriods.map((period) => ({
|
||||
id: period.id,
|
||||
name: period.name,
|
||||
startsAt: period.startsAt.toISOString(),
|
||||
endsAt: period.endsAt.toISOString(),
|
||||
isCurrent: period.isCurrent
|
||||
}));
|
||||
|
||||
const serializedAuditLogs: DashboardAuditLog[] = auditLogs.map((entry) => ({
|
||||
id: entry.id,
|
||||
action: entry.action,
|
||||
entityType: entry.entityType,
|
||||
entityId: entry.entityId,
|
||||
entityLabel: entry.entityLabel,
|
||||
summary: entry.summary,
|
||||
canRestore: Boolean(getRollbackMetadata(entry.metadata)),
|
||||
createdAt: entry.createdAt.toISOString(),
|
||||
actor: entry.actor
|
||||
? {
|
||||
id: entry.actor.id,
|
||||
name: entry.actor.username,
|
||||
username: entry.actor.username,
|
||||
role: entry.actor.role
|
||||
}
|
||||
: null
|
||||
}));
|
||||
|
||||
return (
|
||||
<DashboardShell
|
||||
viewer={serializedViewer}
|
||||
workingGroups={serializedGroups}
|
||||
managedUsers={serializedUsers}
|
||||
auditLogs={serializedAuditLogs}
|
||||
accountingPeriods={serializedPeriods}
|
||||
currentPeriodId={currentPeriod.id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user