| {invoice.client.name} |
diff --git a/app/timer/page.tsx b/app/timer/page.tsx
index 0d14f37..ce5f944 100644
--- a/app/timer/page.tsx
+++ b/app/timer/page.tsx
@@ -110,7 +110,7 @@ export default function TimerPage() {
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
};
- const selectedClient = clientsData?.find((c: Client) => c.id === selectedClientId);
+ const selectedClient = clientsData?.clients?.find((c: Client) => c.id === selectedClientId);
const currentEarnings = selectedClient ? (seconds / 3600) * selectedClient.hourlyRate : 0;
if (clientsLoading) {
@@ -144,7 +144,7 @@ export default function TimerPage() {
className="w-full px-4 py-3 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-slate-900 disabled:bg-slate-100"
>
- {clientsData?.map((client: Client) => (
+ {clientsData?.clients?.map((client: Client) => (
diff --git a/prisma/migrations/20260330120000_add_invoice_hourly_rate/migration.sql b/prisma/migrations/20260330120000_add_invoice_hourly_rate/migration.sql
new file mode 100644
index 0000000..92ef432
--- /dev/null
+++ b/prisma/migrations/20260330120000_add_invoice_hourly_rate/migration.sql
@@ -0,0 +1,2 @@
+-- Add hourlyRate column to Invoice
+ALTER TABLE "Invoice" ADD COLUMN "hourlyRate" NUMERIC(10,2) NOT NULL DEFAULT 0;
diff --git a/prisma/migrations/20260330140000_update_client_hourlyrate_and_updatedAt/migration.sql b/prisma/migrations/20260330140000_update_client_hourlyrate_and_updatedAt/migration.sql
new file mode 100644
index 0000000..3dcd635
--- /dev/null
+++ b/prisma/migrations/20260330140000_update_client_hourlyrate_and_updatedAt/migration.sql
@@ -0,0 +1,20 @@
+-- Convert Client.hourlyRate from DOUBLE PRECISION to NUMERIC(10,2), set default and not-null
+-- Add updatedAt TIMESTAMP(3) NOT NULL with DEFAULT CURRENT_TIMESTAMP
+
+-- 1) Ensure no NULLs remain in hourlyRate
+UPDATE "Client" SET "hourlyRate" = 0 WHERE "hourlyRate" IS NULL;
+
+-- 2) Alter column type to NUMERIC(10,2) with rounding to 2 decimal places
+ALTER TABLE "Client" ALTER COLUMN "hourlyRate" TYPE NUMERIC(10,2) USING ROUND("hourlyRate"::numeric, 2);
+
+-- 3) Set default to 0
+ALTER TABLE "Client" ALTER COLUMN "hourlyRate" SET DEFAULT 0;
+
+-- 4) Enforce NOT NULL (Prisma model requires non-nullable Decimal)
+ALTER TABLE "Client" ALTER COLUMN "hourlyRate" SET NOT NULL;
+
+-- 5) Add updatedAt column with millisecond precision and default current timestamp
+ALTER TABLE "Client" ADD COLUMN IF NOT EXISTS "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
+
+-- Optional: backfill updatedAt for existing rows (set to createdAt if present)
+UPDATE "Client" SET "updatedAt" = COALESCE("updatedAt", "createdAt") WHERE "updatedAt" IS NULL;
diff --git a/prisma/migrations/20260330173921_update_client_hourlyrate_and_updated_at/migration.sql b/prisma/migrations/20260330173921_update_client_hourlyrate_and_updated_at/migration.sql
new file mode 100644
index 0000000..3572b49
--- /dev/null
+++ b/prisma/migrations/20260330173921_update_client_hourlyrate_and_updated_at/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "Client" ALTER COLUMN "updatedAt" DROP DEFAULT;
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index e808ba9..c1cb153 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -25,8 +25,10 @@ model Client {
id String @id @default(cuid())
name String
email String
- hourlyRate Float
+
+ hourlyRate Decimal @db.Decimal(10, 2) @default(0)
createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@ -52,6 +54,8 @@ model Invoice {
id String @id @default(cuid())
totalHours Float
totalAmount Float
+ // Hourly rate used when the invoice was generated (persisted for historical accuracy)
+ hourlyRate Decimal @db.Decimal(10, 2) @default(0)
periodStart DateTime?
periodEnd DateTime?
createdAt DateTime @default(now())
|