Unify the dashboard experience and retire the multi-theme engine so onboarding and day-to-day invoicing feel consistent and easier to maintain.
Shared layout, tabs, and sidebar timer; user onboarding and registration polish; settings danger zone and data export; chart and tRPC perf fixes; migrations for onboarding and dropped appearance columns. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import { db } from "~/server/db";
|
||||
import { users } from "~/server/db/schema";
|
||||
import { Resend } from "resend";
|
||||
import { env } from "~/env";
|
||||
import { APP_EMAIL_DOMAIN } from "~/lib/app-email";
|
||||
import { getAppUrl } from "~/lib/app-url";
|
||||
import { generatePasswordResetEmailTemplate } from "~/lib/email-templates";
|
||||
import crypto from "crypto";
|
||||
|
||||
@@ -72,7 +74,7 @@ export async function POST(request: NextRequest) {
|
||||
// Send password reset email using Resend
|
||||
try {
|
||||
const resend = new Resend(env.RESEND_API_KEY);
|
||||
const resetUrl = `${process.env.BETTER_AUTH_URL ?? "http://localhost:3000"}/auth/reset-password?token=${resetToken}`;
|
||||
const resetUrl = `${getAppUrl()}/auth/reset-password?token=${resetToken}`;
|
||||
|
||||
const emailTemplate = generatePasswordResetEmailTemplate({
|
||||
userEmail: email,
|
||||
@@ -82,8 +84,10 @@ export async function POST(request: NextRequest) {
|
||||
expiryHours: 24,
|
||||
});
|
||||
|
||||
const fromDomain = env.RESEND_DOMAIN ?? APP_EMAIL_DOMAIN;
|
||||
|
||||
await resend.emails.send({
|
||||
from: "beenvoice <noreply@beenvoice.com>",
|
||||
from: `beenvoice <noreply@${fromDomain}>`,
|
||||
to: email,
|
||||
subject: emailTemplate.subject,
|
||||
html: emailTemplate.html,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { eq } from "drizzle-orm";
|
||||
import { type NextRequest, NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { auth } from "~/lib/auth";
|
||||
import { getDatabaseSetupErrorMessage } from "~/lib/db-errors";
|
||||
import { env } from "~/env";
|
||||
import { db } from "~/server/db";
|
||||
import { accounts, users } from "~/server/db/schema";
|
||||
@@ -161,6 +162,12 @@ export async function POST(request: NextRequest) {
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Registration error:", error);
|
||||
|
||||
const databaseSetupError = getDatabaseSetupErrorMessage(error);
|
||||
if (databaseSetupError) {
|
||||
return NextResponse.json({ error: databaseSetupError }, { status: 503 });
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Internal server error" },
|
||||
{ status: 500 },
|
||||
|
||||
@@ -3,6 +3,7 @@ import { z, type ZodType } from "zod";
|
||||
|
||||
import { createCaller } from "~/server/api/root";
|
||||
import { createTRPCContext } from "~/server/api/trpc";
|
||||
import { getAppUrl } from "~/lib/app-url";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
@@ -856,7 +857,7 @@ const tools = {
|
||||
schema: z.object({ id: z.string(), ttlHours: z.number().positive().optional() }),
|
||||
handler: async (input, caller) => {
|
||||
const result = await caller.invoices.generatePublicToken(input);
|
||||
const base = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000";
|
||||
const base = getAppUrl();
|
||||
return {
|
||||
...result,
|
||||
webUrl: `${base}/i/${result.token}`,
|
||||
|
||||
Reference in New Issue
Block a user