Refactor invoice data table and templates page for improved readability and functionality

- Cleaned up imports and formatted code for better readability in invoices-data-table.tsx.
- Enhanced invoice interface definitions for clarity.
- Improved toast messages for bulk delete and update actions.
- Refactored date formatting and status type retrieval for better readability.
- Simplified template management in templates page, extracting TemplateList component.
- Added registration toggle based on environment variable DISABLE_SIGNUPS.
- Updated navbar to conditionally render registration link based on allowRegistration prop.
- Enhanced error handling and validation in expenses and settings routers.
- Improved PDF export footer handling.
- Updated TRPC react integration for cleaner type imports.
This commit is contained in:
2026-04-29 22:49:07 -04:00
parent dbb739b060
commit ddc2b42672
20 changed files with 916 additions and 483 deletions
+10 -10
View File
@@ -58,11 +58,11 @@ export const expensesRouter = createTRPCRouter({
.mutation(async ({ ctx, input }) => {
const clean = {
...input,
clientId: input.clientId?.trim() || null,
businessId: input.businessId?.trim() || null,
invoiceId: input.invoiceId?.trim() || null,
category: input.category?.trim() || null,
notes: input.notes?.trim() || null,
clientId: input.clientId?.trim() ?? null,
businessId: input.businessId?.trim() ?? null,
invoiceId: input.invoiceId?.trim() ?? null,
category: input.category?.trim() ?? null,
notes: input.notes?.trim() ?? null,
};
if (clean.clientId) {
@@ -121,11 +121,11 @@ export const expensesRouter = createTRPCRouter({
const clean = {
...data,
clientId: data.clientId?.trim() || null,
businessId: data.businessId?.trim() || null,
invoiceId: data.invoiceId?.trim() || null,
category: data.category?.trim() || null,
notes: data.notes?.trim() || null,
clientId: data.clientId?.trim() ?? null,
businessId: data.businessId?.trim() ?? null,
invoiceId: data.invoiceId?.trim() ?? null,
category: data.category?.trim() ?? null,
notes: data.notes?.trim() ?? null,
updatedAt: new Date(),
};
+36 -9
View File
@@ -1,5 +1,5 @@
import { z } from "zod";
import { eq } from "drizzle-orm";
import { and, eq } from "drizzle-orm";
import { TRPCError } from "@trpc/server";
import bcrypt from "bcryptjs";
import {
@@ -8,6 +8,7 @@ import {
publicProcedure,
} from "~/server/api/trpc";
import {
accounts,
users,
clients,
businesses,
@@ -29,9 +30,10 @@ import {
type RadiusPreference,
type SidebarStyle,
} from "~/lib/branding";
import type { db as database } from "~/server/db";
async function requireAdmin(ctx: {
db: typeof import("~/server/db").db;
db: typeof database;
session: { user: { id: string } };
}) {
const user = await ctx.db.query.users.findFirst({
@@ -425,13 +427,38 @@ export const settingsRouter = createTRPCRouter({
saltRounds,
);
// Update the password
await ctx.db
.update(users)
.set({
password: hashedNewPassword,
})
.where(eq(users.id, userId));
await ctx.db.transaction(async (tx) => {
await tx
.update(users)
.set({
password: hashedNewPassword,
})
.where(eq(users.id, userId));
const credentialAccount = await tx.query.accounts.findFirst({
where: and(
eq(accounts.userId, userId),
eq(accounts.providerId, "credential"),
),
});
if (credentialAccount) {
await tx
.update(accounts)
.set({
password: hashedNewPassword,
updatedAt: new Date(),
})
.where(eq(accounts.id, credentialAccount.id));
} else {
await tx.insert(accounts).values({
userId,
accountId: userId,
providerId: "credential",
password: hashedNewPassword,
});
}
});
return { success: true };
}),