From ba14526fc5a9f06c2273935e2870f2fab96ddad2 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 5 Apr 2026 01:59:08 +0000 Subject: [PATCH] Set up proper DB migrations and fix remaining mobile responsive issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrations: - drizzle.config.ts: add out: './drizzle' so drizzle-kit generate writes SQL migration files instead of only supporting push - drizzle/0000_glossy_magneto.sql: initial migration capturing all 9 current tables (users, accounts, sessions, verification_tokens, sso_providers, clients, businesses, invoices, invoice_items) - src/server/db/migrate.ts: programmatic runner using drizzle-orm's migrate() — tracks applied migrations in __drizzle_migrations, safe to run on every deploy - package.json: db:migrate now runs the programmatic runner instead of drizzle-kit migrate (CLI requires devDeps at runtime) - start.sh: replace drizzle-kit push with bun src/server/db/migrate.ts - Dockerfile: copy drizzle/ folder into the runner image so migrations are available at container startup Mobile fixes: - data-table.tsx: pagination buttons grow from 32px to 40px on mobile (h-10 w-10 md:h-8 md:w-8) to meet 44px touch-target guidelines - floating-action-bar.tsx: stack left-content + action buttons to column layout on narrow screens (flex-col sm:flex-row), reduce padding on mobile (p-3 sm:p-4) - revenue-chart.tsx: responsive chart height (h-48 md:h-64) so the chart doesn't consume too much vertical space on small screens https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi --- Dockerfile | 1 + drizzle.config.ts | 1 + drizzle/0000_glossy_magneto.sql | 166 +++ drizzle/meta/0000_snapshot.json | 1259 +++++++++++++++++ drizzle/meta/_journal.json | 13 + package.json | 2 +- .../dashboard/_components/revenue-chart.tsx | 2 +- src/components/data/data-table.tsx | 8 +- src/components/layout/floating-action-bar.tsx | 2 +- src/server/db/migrate.ts | 49 + start.sh | 5 +- 11 files changed, 1498 insertions(+), 10 deletions(-) create mode 100644 drizzle/0000_glossy_magneto.sql create mode 100644 drizzle/meta/0000_snapshot.json create mode 100644 drizzle/meta/_journal.json create mode 100644 src/server/db/migrate.ts diff --git a/Dockerfile b/Dockerfile index e6d48f0..79de32a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,6 +44,7 @@ RUN bun install --frozen-lockfile --production --verbose COPY --from=builder /app/start.sh ./start.sh COPY --from=builder /app/next.config.js ./next.config.js COPY --from=builder /app/src ./src +COPY --from=builder /app/drizzle ./drizzle COPY --from=builder /app/drizzle.config.ts ./drizzle.config.ts COPY --from=builder /app/.env.example ./.env.example diff --git a/drizzle.config.ts b/drizzle.config.ts index 4ef0d89..a286a87 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -14,6 +14,7 @@ if (!process.env.DATABASE_URL) { export default { schema: "./src/server/db/schema.ts", + out: "./drizzle", dialect: "postgresql", dbCredentials: { url: process.env.DATABASE_URL, diff --git a/drizzle/0000_glossy_magneto.sql b/drizzle/0000_glossy_magneto.sql new file mode 100644 index 0000000..9921a06 --- /dev/null +++ b/drizzle/0000_glossy_magneto.sql @@ -0,0 +1,166 @@ +CREATE TABLE "beenvoice_account" ( + "id" text PRIMARY KEY NOT NULL, + "userId" varchar(255) NOT NULL, + "accountId" varchar(255) NOT NULL, + "providerId" varchar(255) NOT NULL, + "accessToken" text, + "refreshToken" text, + "accessTokenExpiresAt" timestamp, + "refreshTokenExpiresAt" timestamp, + "scope" varchar(255), + "idToken" text, + "password" text, + "createdAt" timestamp DEFAULT now() NOT NULL, + "updatedAt" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +CREATE TABLE "beenvoice_business" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "name" varchar(255) NOT NULL, + "nickname" varchar(255), + "email" varchar(255), + "phone" varchar(50), + "addressLine1" varchar(255), + "addressLine2" varchar(255), + "city" varchar(100), + "state" varchar(50), + "postalCode" varchar(20), + "country" varchar(100), + "website" varchar(255), + "taxId" varchar(100), + "logoUrl" varchar(500), + "isDefault" boolean DEFAULT false, + "resendApiKey" varchar(255), + "resendDomain" varchar(255), + "emailFromName" varchar(255), + "createdById" varchar(255) NOT NULL, + "createdAt" timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updatedAt" timestamp +); +--> statement-breakpoint +CREATE TABLE "beenvoice_client" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "name" varchar(255) NOT NULL, + "email" varchar(255), + "phone" varchar(50), + "addressLine1" varchar(255), + "addressLine2" varchar(255), + "city" varchar(100), + "state" varchar(50), + "postalCode" varchar(20), + "country" varchar(100), + "defaultHourlyRate" real, + "createdById" varchar(255) NOT NULL, + "createdAt" timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updatedAt" timestamp +); +--> statement-breakpoint +CREATE TABLE "beenvoice_invoice_item" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "invoiceId" varchar(255) NOT NULL, + "date" timestamp NOT NULL, + "description" varchar(500) NOT NULL, + "hours" real NOT NULL, + "rate" real NOT NULL, + "amount" real NOT NULL, + "position" integer DEFAULT 0 NOT NULL, + "createdAt" timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL +); +--> statement-breakpoint +CREATE TABLE "beenvoice_invoice" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "invoiceNumber" varchar(100) NOT NULL, + "businessId" varchar(255), + "clientId" varchar(255) NOT NULL, + "issueDate" timestamp NOT NULL, + "dueDate" timestamp NOT NULL, + "status" varchar(50) DEFAULT 'draft' NOT NULL, + "totalAmount" real DEFAULT 0 NOT NULL, + "taxRate" real DEFAULT 0 NOT NULL, + "notes" varchar(1000), + "createdById" varchar(255) NOT NULL, + "createdAt" timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updatedAt" timestamp +); +--> statement-breakpoint +CREATE TABLE "beenvoice_session" ( + "id" text PRIMARY KEY NOT NULL, + "userId" varchar(255) NOT NULL, + "token" varchar(255) NOT NULL, + "expiresAt" timestamp NOT NULL, + "ipAddress" text, + "userAgent" text, + "createdAt" timestamp DEFAULT now() NOT NULL, + "updatedAt" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "beenvoice_session_token_unique" UNIQUE("token") +); +--> statement-breakpoint +CREATE TABLE "beenvoice_sso_provider" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "providerId" varchar(255) NOT NULL, + "userId" varchar(255) NOT NULL, + "redirectURI" varchar(255) DEFAULT '' NOT NULL, + "oidcConfig" text, + "samlConfig" text, + "createdAt" timestamp DEFAULT now() NOT NULL, + "updatedAt" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "beenvoice_sso_provider_providerId_unique" UNIQUE("providerId") +); +--> statement-breakpoint +CREATE TABLE "beenvoice_user" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "name" varchar(255) NOT NULL, + "email" varchar(255) NOT NULL, + "emailVerified" boolean DEFAULT false NOT NULL, + "image" varchar(255), + "createdAt" timestamp DEFAULT now() NOT NULL, + "updatedAt" timestamp DEFAULT now() NOT NULL, + "password" varchar(255), + "resetToken" varchar(255), + "resetTokenExpiry" timestamp, + "prefersReducedMotion" boolean DEFAULT false NOT NULL, + "animationSpeedMultiplier" real DEFAULT 1 NOT NULL, + "colorTheme" varchar(50) DEFAULT 'slate' NOT NULL, + "customColor" varchar(50), + "theme" varchar(20) DEFAULT 'system' NOT NULL, + CONSTRAINT "beenvoice_user_email_unique" UNIQUE("email") +); +--> statement-breakpoint +CREATE TABLE "beenvoice_verification_token" ( + "id" text PRIMARY KEY NOT NULL, + "identifier" varchar(255) NOT NULL, + "value" varchar(255) NOT NULL, + "expiresAt" timestamp NOT NULL, + "createdAt" timestamp DEFAULT now() NOT NULL, + "updatedAt" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "beenvoice_account" ADD CONSTRAINT "beenvoice_account_userId_beenvoice_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."beenvoice_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_business" ADD CONSTRAINT "beenvoice_business_createdById_beenvoice_user_id_fk" FOREIGN KEY ("createdById") REFERENCES "public"."beenvoice_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_client" ADD CONSTRAINT "beenvoice_client_createdById_beenvoice_user_id_fk" FOREIGN KEY ("createdById") REFERENCES "public"."beenvoice_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_invoice_item" ADD CONSTRAINT "beenvoice_invoice_item_invoiceId_beenvoice_invoice_id_fk" FOREIGN KEY ("invoiceId") REFERENCES "public"."beenvoice_invoice"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_invoice" ADD CONSTRAINT "beenvoice_invoice_businessId_beenvoice_business_id_fk" FOREIGN KEY ("businessId") REFERENCES "public"."beenvoice_business"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_invoice" ADD CONSTRAINT "beenvoice_invoice_clientId_beenvoice_client_id_fk" FOREIGN KEY ("clientId") REFERENCES "public"."beenvoice_client"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_invoice" ADD CONSTRAINT "beenvoice_invoice_createdById_beenvoice_user_id_fk" FOREIGN KEY ("createdById") REFERENCES "public"."beenvoice_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_session" ADD CONSTRAINT "beenvoice_session_userId_beenvoice_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."beenvoice_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "beenvoice_sso_provider" ADD CONSTRAINT "beenvoice_sso_provider_userId_beenvoice_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."beenvoice_user"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "account_userId_idx" ON "beenvoice_account" USING btree ("userId");--> statement-breakpoint +CREATE INDEX "business_created_by_idx" ON "beenvoice_business" USING btree ("createdById");--> statement-breakpoint +CREATE INDEX "business_name_idx" ON "beenvoice_business" USING btree ("name");--> statement-breakpoint +CREATE INDEX "business_nickname_idx" ON "beenvoice_business" USING btree ("nickname");--> statement-breakpoint +CREATE INDEX "business_email_idx" ON "beenvoice_business" USING btree ("email");--> statement-breakpoint +CREATE INDEX "business_is_default_idx" ON "beenvoice_business" USING btree ("isDefault");--> statement-breakpoint +CREATE INDEX "client_created_by_idx" ON "beenvoice_client" USING btree ("createdById");--> statement-breakpoint +CREATE INDEX "client_name_idx" ON "beenvoice_client" USING btree ("name");--> statement-breakpoint +CREATE INDEX "client_email_idx" ON "beenvoice_client" USING btree ("email");--> statement-breakpoint +CREATE INDEX "invoice_item_invoice_id_idx" ON "beenvoice_invoice_item" USING btree ("invoiceId");--> statement-breakpoint +CREATE INDEX "invoice_item_date_idx" ON "beenvoice_invoice_item" USING btree ("date");--> statement-breakpoint +CREATE INDEX "invoice_item_position_idx" ON "beenvoice_invoice_item" USING btree ("position");--> statement-breakpoint +CREATE INDEX "invoice_business_id_idx" ON "beenvoice_invoice" USING btree ("businessId");--> statement-breakpoint +CREATE INDEX "invoice_client_id_idx" ON "beenvoice_invoice" USING btree ("clientId");--> statement-breakpoint +CREATE INDEX "invoice_created_by_idx" ON "beenvoice_invoice" USING btree ("createdById");--> statement-breakpoint +CREATE INDEX "invoice_number_idx" ON "beenvoice_invoice" USING btree ("invoiceNumber");--> statement-breakpoint +CREATE INDEX "invoice_status_idx" ON "beenvoice_invoice" USING btree ("status");--> statement-breakpoint +CREATE INDEX "session_userId_idx" ON "beenvoice_session" USING btree ("userId");--> statement-breakpoint +CREATE INDEX "sso_provider_user_id_idx" ON "beenvoice_sso_provider" USING btree ("userId");--> statement-breakpoint +CREATE INDEX "verification_token_identifier_idx" ON "beenvoice_verification_token" USING btree ("identifier"); \ No newline at end of file diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json new file mode 100644 index 0000000..54ec008 --- /dev/null +++ b/drizzle/meta/0000_snapshot.json @@ -0,0 +1,1259 @@ +{ + "id": "f6c70548-143c-48a3-a0c5-85873eaaa326", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.beenvoice_account": { + "name": "beenvoice_account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "accountId": { + "name": "accountId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "providerId": { + "name": "providerId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "accessToken": { + "name": "accessToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessTokenExpiresAt": { + "name": "accessTokenExpiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refreshTokenExpiresAt": { + "name": "refreshTokenExpiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "idToken": { + "name": "idToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "beenvoice_account_userId_beenvoice_user_id_fk": { + "name": "beenvoice_account_userId_beenvoice_user_id_fk", + "tableFrom": "beenvoice_account", + "tableTo": "beenvoice_user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_business": { + "name": "beenvoice_business", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "nickname": { + "name": "nickname", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "addressLine1": { + "name": "addressLine1", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "addressLine2": { + "name": "addressLine2", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "city": { + "name": "city", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "postalCode": { + "name": "postalCode", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "country": { + "name": "country", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "website": { + "name": "website", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "taxId": { + "name": "taxId", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "logoUrl": { + "name": "logoUrl", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "isDefault": { + "name": "isDefault", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "resendApiKey": { + "name": "resendApiKey", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "resendDomain": { + "name": "resendDomain", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "emailFromName": { + "name": "emailFromName", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "createdById": { + "name": "createdById", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "business_created_by_idx": { + "name": "business_created_by_idx", + "columns": [ + { + "expression": "createdById", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "business_name_idx": { + "name": "business_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "business_nickname_idx": { + "name": "business_nickname_idx", + "columns": [ + { + "expression": "nickname", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "business_email_idx": { + "name": "business_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "business_is_default_idx": { + "name": "business_is_default_idx", + "columns": [ + { + "expression": "isDefault", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "beenvoice_business_createdById_beenvoice_user_id_fk": { + "name": "beenvoice_business_createdById_beenvoice_user_id_fk", + "tableFrom": "beenvoice_business", + "tableTo": "beenvoice_user", + "columnsFrom": [ + "createdById" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_client": { + "name": "beenvoice_client", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "addressLine1": { + "name": "addressLine1", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "addressLine2": { + "name": "addressLine2", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "city": { + "name": "city", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "postalCode": { + "name": "postalCode", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "country": { + "name": "country", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "defaultHourlyRate": { + "name": "defaultHourlyRate", + "type": "real", + "primaryKey": false, + "notNull": false + }, + "createdById": { + "name": "createdById", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "client_created_by_idx": { + "name": "client_created_by_idx", + "columns": [ + { + "expression": "createdById", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "client_name_idx": { + "name": "client_name_idx", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "client_email_idx": { + "name": "client_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "beenvoice_client_createdById_beenvoice_user_id_fk": { + "name": "beenvoice_client_createdById_beenvoice_user_id_fk", + "tableFrom": "beenvoice_client", + "tableTo": "beenvoice_user", + "columnsFrom": [ + "createdById" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_invoice_item": { + "name": "beenvoice_invoice_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "invoiceId": { + "name": "invoiceId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "date": { + "name": "date", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar(500)", + "primaryKey": false, + "notNull": true + }, + "hours": { + "name": "hours", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "rate": { + "name": "rate", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "amount": { + "name": "amount", + "type": "real", + "primaryKey": false, + "notNull": true + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "invoice_item_invoice_id_idx": { + "name": "invoice_item_invoice_id_idx", + "columns": [ + { + "expression": "invoiceId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invoice_item_date_idx": { + "name": "invoice_item_date_idx", + "columns": [ + { + "expression": "date", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invoice_item_position_idx": { + "name": "invoice_item_position_idx", + "columns": [ + { + "expression": "position", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "beenvoice_invoice_item_invoiceId_beenvoice_invoice_id_fk": { + "name": "beenvoice_invoice_item_invoiceId_beenvoice_invoice_id_fk", + "tableFrom": "beenvoice_invoice_item", + "tableTo": "beenvoice_invoice", + "columnsFrom": [ + "invoiceId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_invoice": { + "name": "beenvoice_invoice", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "invoiceNumber": { + "name": "invoiceNumber", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + }, + "businessId": { + "name": "businessId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "clientId": { + "name": "clientId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "issueDate": { + "name": "issueDate", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "dueDate": { + "name": "dueDate", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "totalAmount": { + "name": "totalAmount", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "taxRate": { + "name": "taxRate", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "notes": { + "name": "notes", + "type": "varchar(1000)", + "primaryKey": false, + "notNull": false + }, + "createdById": { + "name": "createdById", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "invoice_business_id_idx": { + "name": "invoice_business_id_idx", + "columns": [ + { + "expression": "businessId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invoice_client_id_idx": { + "name": "invoice_client_id_idx", + "columns": [ + { + "expression": "clientId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invoice_created_by_idx": { + "name": "invoice_created_by_idx", + "columns": [ + { + "expression": "createdById", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invoice_number_idx": { + "name": "invoice_number_idx", + "columns": [ + { + "expression": "invoiceNumber", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "invoice_status_idx": { + "name": "invoice_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "beenvoice_invoice_businessId_beenvoice_business_id_fk": { + "name": "beenvoice_invoice_businessId_beenvoice_business_id_fk", + "tableFrom": "beenvoice_invoice", + "tableTo": "beenvoice_business", + "columnsFrom": [ + "businessId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "beenvoice_invoice_clientId_beenvoice_client_id_fk": { + "name": "beenvoice_invoice_clientId_beenvoice_client_id_fk", + "tableFrom": "beenvoice_invoice", + "tableTo": "beenvoice_client", + "columnsFrom": [ + "clientId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "beenvoice_invoice_createdById_beenvoice_user_id_fk": { + "name": "beenvoice_invoice_createdById_beenvoice_user_id_fk", + "tableFrom": "beenvoice_invoice", + "tableTo": "beenvoice_user", + "columnsFrom": [ + "createdById" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_session": { + "name": "beenvoice_session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ipAddress": { + "name": "ipAddress", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userAgent": { + "name": "userAgent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "beenvoice_session_userId_beenvoice_user_id_fk": { + "name": "beenvoice_session_userId_beenvoice_user_id_fk", + "tableFrom": "beenvoice_session", + "tableTo": "beenvoice_user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "beenvoice_session_token_unique": { + "name": "beenvoice_session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_sso_provider": { + "name": "beenvoice_sso_provider", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "providerId": { + "name": "providerId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "redirectURI": { + "name": "redirectURI", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "oidcConfig": { + "name": "oidcConfig", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "samlConfig": { + "name": "samlConfig", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "sso_provider_user_id_idx": { + "name": "sso_provider_user_id_idx", + "columns": [ + { + "expression": "userId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "beenvoice_sso_provider_userId_beenvoice_user_id_fk": { + "name": "beenvoice_sso_provider_userId_beenvoice_user_id_fk", + "tableFrom": "beenvoice_sso_provider", + "tableTo": "beenvoice_user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "beenvoice_sso_provider_providerId_unique": { + "name": "beenvoice_sso_provider_providerId_unique", + "nullsNotDistinct": false, + "columns": [ + "providerId" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_user": { + "name": "beenvoice_user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "password": { + "name": "password", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "resetToken": { + "name": "resetToken", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "resetTokenExpiry": { + "name": "resetTokenExpiry", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "prefersReducedMotion": { + "name": "prefersReducedMotion", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "animationSpeedMultiplier": { + "name": "animationSpeedMultiplier", + "type": "real", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "colorTheme": { + "name": "colorTheme", + "type": "varchar(50)", + "primaryKey": false, + "notNull": true, + "default": "'slate'" + }, + "customColor": { + "name": "customColor", + "type": "varchar(50)", + "primaryKey": false, + "notNull": false + }, + "theme": { + "name": "theme", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true, + "default": "'system'" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "beenvoice_user_email_unique": { + "name": "beenvoice_user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.beenvoice_verification_token": { + "name": "beenvoice_verification_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_token_identifier_idx": { + "name": "verification_token_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json new file mode 100644 index 0000000..2c528ff --- /dev/null +++ b/drizzle/meta/_journal.json @@ -0,0 +1,13 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1775354242672, + "tag": "0000_glossy_magneto", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index e08c243..9c17890 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "build": "next build", "check": "eslint . && tsc --noEmit", "db:generate": "drizzle-kit generate", - "db:migrate": "drizzle-kit migrate", + "db:migrate": "bun src/server/db/migrate.ts", "db:push": "drizzle-kit push", "db:studio": "drizzle-kit studio", "db:clone": "./scripts/clone-local.sh", diff --git a/src/app/dashboard/_components/revenue-chart.tsx b/src/app/dashboard/_components/revenue-chart.tsx index 1497ebc..87aafa0 100644 --- a/src/app/dashboard/_components/revenue-chart.tsx +++ b/src/app/dashboard/_components/revenue-chart.tsx @@ -86,7 +86,7 @@ export function RevenueChart({ data }: RevenueChartProps) { } return ( -
+
diff --git a/src/components/data/data-table.tsx b/src/components/data/data-table.tsx index fea0c49..34b0600 100644 --- a/src/components/data/data-table.tsx +++ b/src/components/data/data-table.tsx @@ -471,7 +471,7 @@ export function DataTable({