feat: add administration page and account role management

- Implemented `AdministrationContent` component for managing account roles.
- Created `AdministrationPage` to serve as the main entry point for administration tasks.
- Added PDF preview functionality with `PdfPreviewFrame` component for invoice generation.
- Introduced `InputColor` component for advanced color selection with various formats.
- Established color conversion utilities in `color-converter.ts` for handling color formats.
- Defined appearance-related schemas and types in `appearance.ts` for consistent theme management.
This commit is contained in:
2026-04-30 10:50:50 -04:00
parent ddc2b42672
commit 0e46fdafb2
87 changed files with 4562 additions and 2421 deletions
+27 -6
View File
@@ -47,7 +47,10 @@ export const expensesRouter = createTRPCRouter({
});
if (!expense) {
throw new TRPCError({ code: "NOT_FOUND", message: "Expense not found" });
throw new TRPCError({
code: "NOT_FOUND",
message: "Expense not found",
});
}
return expense;
@@ -72,7 +75,11 @@ export const expensesRouter = createTRPCRouter({
eq(clients.createdById, ctx.session.user.id),
),
});
if (!client) throw new TRPCError({ code: "FORBIDDEN", message: "Client not found" });
if (!client)
throw new TRPCError({
code: "FORBIDDEN",
message: "Client not found",
});
}
if (clean.businessId) {
@@ -82,7 +89,11 @@ export const expensesRouter = createTRPCRouter({
eq(businesses.createdById, ctx.session.user.id),
),
});
if (!business) throw new TRPCError({ code: "FORBIDDEN", message: "Business not found" });
if (!business)
throw new TRPCError({
code: "FORBIDDEN",
message: "Business not found",
});
}
if (clean.invoiceId) {
@@ -92,7 +103,11 @@ export const expensesRouter = createTRPCRouter({
eq(invoices.createdById, ctx.session.user.id),
),
});
if (!invoice) throw new TRPCError({ code: "FORBIDDEN", message: "Invoice not found" });
if (!invoice)
throw new TRPCError({
code: "FORBIDDEN",
message: "Invoice not found",
});
}
const [expense] = await ctx.db
@@ -116,7 +131,10 @@ export const expensesRouter = createTRPCRouter({
});
if (!existing) {
throw new TRPCError({ code: "NOT_FOUND", message: "Expense not found" });
throw new TRPCError({
code: "NOT_FOUND",
message: "Expense not found",
});
}
const clean = {
@@ -145,7 +163,10 @@ export const expensesRouter = createTRPCRouter({
});
if (!existing) {
throw new TRPCError({ code: "NOT_FOUND", message: "Expense not found" });
throw new TRPCError({
code: "NOT_FOUND",
message: "Expense not found",
});
}
await ctx.db.delete(expenses).where(eq(expenses.id, input.id));