mirror of
https://github.com/soconnor0919/beenvoice.git
synced 2026-05-08 09:38:55 -04:00
refactor: migrate authentication system and update Drizzle schema.
This commit is contained in:
@@ -136,9 +136,9 @@ export default function SendEmailPage() {
|
||||
action:
|
||||
canRetry && retryCount < 2
|
||||
? {
|
||||
label: "Retry",
|
||||
onClick: () => handleRetry(),
|
||||
}
|
||||
label: "Retry",
|
||||
onClick: () => handleRetry(),
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
@@ -150,31 +150,31 @@ export default function SendEmailPage() {
|
||||
const invoice = useMemo(() => {
|
||||
return invoiceData
|
||||
? {
|
||||
id: invoiceData.id,
|
||||
invoiceNumber: invoiceData.invoiceNumber,
|
||||
issueDate: invoiceData.issueDate,
|
||||
dueDate: invoiceData.dueDate,
|
||||
status: invoiceData.status,
|
||||
taxRate: invoiceData.taxRate,
|
||||
client: invoiceData.client
|
||||
? {
|
||||
name: invoiceData.client.name,
|
||||
email: invoiceData.client.email,
|
||||
}
|
||||
: undefined,
|
||||
business: invoiceData.business
|
||||
? {
|
||||
name: invoiceData.business.name,
|
||||
nickname: invoiceData.business.nickname,
|
||||
email: invoiceData.business.email,
|
||||
}
|
||||
: undefined,
|
||||
items: invoiceData.items?.map((item) => ({
|
||||
id: item.id,
|
||||
hours: item.hours,
|
||||
rate: item.rate,
|
||||
})),
|
||||
}
|
||||
id: invoiceData.id,
|
||||
invoiceNumber: invoiceData.invoiceNumber,
|
||||
issueDate: invoiceData.issueDate,
|
||||
dueDate: invoiceData.dueDate,
|
||||
status: invoiceData.status,
|
||||
taxRate: invoiceData.taxRate,
|
||||
client: invoiceData.client
|
||||
? {
|
||||
name: invoiceData.client.name,
|
||||
email: invoiceData.client.email,
|
||||
}
|
||||
: undefined,
|
||||
business: invoiceData.business
|
||||
? {
|
||||
name: invoiceData.business.name,
|
||||
nickname: invoiceData.business.nickname,
|
||||
email: invoiceData.business.email,
|
||||
}
|
||||
: undefined,
|
||||
items: invoiceData.items?.map((item) => ({
|
||||
id: item.id,
|
||||
hours: item.hours,
|
||||
rate: item.rate,
|
||||
})),
|
||||
}
|
||||
: undefined;
|
||||
}, [invoiceData]);
|
||||
|
||||
@@ -184,6 +184,7 @@ export default function SendEmailPage() {
|
||||
|
||||
// Set default subject
|
||||
const defaultSubject = `Invoice ${invoice.invoiceNumber} from ${invoice.business?.name ?? "Your Business"}`;
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setSubject(defaultSubject);
|
||||
|
||||
// Set default content (empty since template handles everything)
|
||||
|
||||
+18
-16
@@ -16,7 +16,8 @@ import { Button } from "~/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
||||
import { Skeleton } from "~/components/ui/skeleton";
|
||||
import { getEffectiveInvoiceStatus } from "~/lib/invoice-status";
|
||||
import { auth } from "~/server/auth";
|
||||
import { auth } from "~/lib/auth";
|
||||
import { headers } from "next/headers";
|
||||
import { HydrateClient, api } from "~/trpc/server";
|
||||
import type { StoredInvoiceStatus } from "~/types/invoice";
|
||||
import { RevenueChart } from "~/app/dashboard/_components/revenue-chart";
|
||||
@@ -126,15 +127,15 @@ async function DashboardStats() {
|
||||
const pendingChange =
|
||||
lastMonthInvoices.length > 0
|
||||
? ((pendingInvoices.length -
|
||||
lastMonthInvoices.filter((invoice) => {
|
||||
const status = getEffectiveInvoiceStatus(
|
||||
invoice.status as StoredInvoiceStatus,
|
||||
invoice.dueDate,
|
||||
);
|
||||
return status === "sent" || status === "overdue";
|
||||
}).length) /
|
||||
lastMonthInvoices.length) *
|
||||
100
|
||||
lastMonthInvoices.filter((invoice) => {
|
||||
const status = getEffectiveInvoiceStatus(
|
||||
invoice.status as StoredInvoiceStatus,
|
||||
invoice.dueDate,
|
||||
);
|
||||
return status === "sent" || status === "overdue";
|
||||
}).length) /
|
||||
lastMonthInvoices.length) *
|
||||
100
|
||||
: pendingInvoices.length > 0
|
||||
? 100
|
||||
: 0;
|
||||
@@ -323,11 +324,10 @@ function QuickActions() {
|
||||
<Link
|
||||
key={action.title}
|
||||
href={action.href}
|
||||
className={`hover-lift flex w-full items-start space-x-3 rounded-lg border p-4 transition-colors ${
|
||||
action.featured
|
||||
? "border-foreground/20 bg-muted/50 hover:bg-muted"
|
||||
: "border-border bg-background hover:bg-muted/50"
|
||||
}`}
|
||||
className={`hover-lift flex w-full items-start space-x-3 rounded-lg border p-4 transition-colors ${action.featured
|
||||
? "border-foreground/20 bg-muted/50 hover:bg-muted"
|
||||
: "border-border bg-background hover:bg-muted/50"
|
||||
}`}
|
||||
>
|
||||
<Icon className="h-5 w-5 flex-shrink-0" />
|
||||
<div className="min-w-0 flex-1">
|
||||
@@ -624,7 +624,9 @@ function CardSkeleton() {
|
||||
}
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const session = await auth();
|
||||
const session = await auth.api.getSession({
|
||||
headers: await headers(),
|
||||
});
|
||||
const firstName = session?.user?.name?.split(" ")[0] ?? "User";
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
User,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { authClient } from "~/lib/auth-client";
|
||||
import * as React from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
@@ -66,7 +66,7 @@ import { AppearanceSettings } from "./appearance-settings";
|
||||
import { useAnimationPreferences } from "~/components/providers/animation-preferences-provider";
|
||||
|
||||
export function SettingsContent() {
|
||||
const { data: session } = useSession();
|
||||
const { data: session } = authClient.useSession();
|
||||
const [name, setName] = useState("");
|
||||
const [deleteConfirmText, setDeleteConfirmText] = useState("");
|
||||
const [importData, setImportData] = useState("");
|
||||
|
||||
@@ -41,6 +41,7 @@ export function ThemeSelector() {
|
||||
"h-8 w-8 rounded-full border-2",
|
||||
colorTheme === t.name && "border-primary",
|
||||
)}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
||||
onClick={() => setColorTheme(t.name as any)}
|
||||
style={{ backgroundColor: t.hex }}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user