chore(style): codebase em-dash sweep + minor layout polish
Replaces every em-dash and en-dash with regular ASCII hyphens across comments, JSX strings, and dev-facing logs. Mostly cosmetic but stops the inconsistent mix that crept in over the last few months (some files used em-dashes in comments, others didn't, some used both). Bundles two small dashboard-layout tweaks that touch a couple of already-modified files: - (dashboard)/layout.tsx main padding goes from p-6 to pt-3 px-6 pb-6 so page content sits closer to the topbar. - Sidebar now receives the ports list it needs for the footer port switcher. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* soft warnings and hard caps.
|
||||
*
|
||||
* Token-denominated rather than dollar-denominated so the cap survives
|
||||
* model price changes — and it's the unit both OpenAI and Anthropic
|
||||
* model price changes - and it's the unit both OpenAI and Anthropic
|
||||
* SDKs return in `response.usage`.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ export const aiUsageLedger = pgTable(
|
||||
portId: text('port_id')
|
||||
.notNull()
|
||||
.references(() => ports.id, { onDelete: 'cascade' }),
|
||||
/** Optional — system-initiated calls (e.g. scheduled summarizers) won't have a user. */
|
||||
/** Optional - system-initiated calls (e.g. scheduled summarizers) won't have a user. */
|
||||
userId: text('user_id').references(() => user.id, { onDelete: 'set null' }),
|
||||
/** Stable feature key: 'ocr', 'summary', 'embedding', 'reply_draft', etc. */
|
||||
feature: text('feature').notNull(),
|
||||
|
||||
@@ -127,7 +127,7 @@ export const clientTags = pgTable(
|
||||
clientId: text('client_id')
|
||||
.notNull()
|
||||
.references(() => clients.id, { onDelete: 'cascade' }),
|
||||
tagId: text('tag_id').notNull(), // references tags.id — defined later in system.ts
|
||||
tagId: text('tag_id').notNull(), // references tags.id - defined later in system.ts
|
||||
},
|
||||
(table) => [primaryKey({ columns: [table.clientId, table.tagId] })],
|
||||
);
|
||||
@@ -194,7 +194,7 @@ export const clientMergeCandidates = pgTable(
|
||||
},
|
||||
(table) => [
|
||||
index('idx_cmc_port_status').on(table.portId, table.status),
|
||||
// Same pair shouldn't surface twice — enforce uniqueness on the
|
||||
// Same pair shouldn't surface twice - enforce uniqueness on the
|
||||
// canonical (a < b) ordering.
|
||||
uniqueIndex('idx_cmc_pair').on(table.portId, table.clientAId, table.clientBId),
|
||||
],
|
||||
|
||||
@@ -5,7 +5,7 @@ import { pgTable, text, boolean, timestamp, index, uniqueIndex } from 'drizzle-o
|
||||
*
|
||||
* `tokenHash` is a SHA-256 hash of the raw token sent in the email. Lookups
|
||||
* happen by hash so a DB compromise never leaks active tokens. The invite
|
||||
* is consumed at /set-password — the route creates the better-auth `user`
|
||||
* is consumed at /set-password - the route creates the better-auth `user`
|
||||
* row + `account` credential and the matching `user_profiles` extension.
|
||||
*/
|
||||
export const crmUserInvites = pgTable(
|
||||
|
||||
@@ -31,7 +31,7 @@ export const gdprExports = pgTable(
|
||||
.references(() => user.id, { onDelete: 'restrict' }),
|
||||
/** 'pending' | 'building' | 'ready' | 'sent' | 'failed' */
|
||||
status: text('status').notNull().default('pending'),
|
||||
/** MinIO path under the configured bucket — null until the worker uploads. */
|
||||
/** MinIO path under the configured bucket - null until the worker uploads. */
|
||||
storageKey: text('storage_key'),
|
||||
sizeBytes: integer('size_bytes'),
|
||||
/** When status='failed', the truncated error message. */
|
||||
@@ -41,7 +41,7 @@ export const gdprExports = pgTable(
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
readyAt: timestamp('ready_at', { withTimezone: true }),
|
||||
sentAt: timestamp('sent_at', { withTimezone: true }),
|
||||
/** Cleanup target — bundles are removed from MinIO after this. */
|
||||
/** Cleanup target - bundles are removed from MinIO after this. */
|
||||
expiresAt: timestamp('expires_at', { withTimezone: true }),
|
||||
},
|
||||
(table) => [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Phase B — operational insight surfaces.
|
||||
* Phase B - operational insight surfaces.
|
||||
*
|
||||
* - `alerts`: rule-engine-fired actionable cards. The fingerprint column
|
||||
* dedupes re-evaluations of the same condition; the partial unique
|
||||
@@ -35,12 +35,12 @@ export const alerts = pgTable(
|
||||
/** Optional FK target: 'interest', 'reservation', 'document', 'expense', ... */
|
||||
entityType: text('entity_type'),
|
||||
entityId: text('entity_id'),
|
||||
/** Hash of (rule_id + entity_type + entity_id) — dedupes re-evaluations. */
|
||||
/** Hash of (rule_id + entity_type + entity_id) - dedupes re-evaluations. */
|
||||
fingerprint: text('fingerprint').notNull(),
|
||||
firedAt: timestamp('fired_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
dismissedAt: timestamp('dismissed_at', { withTimezone: true }),
|
||||
dismissedBy: text('dismissed_by').references(() => user.id),
|
||||
/** "Someone is on it" — alert stays visible but stops nagging. */
|
||||
/** "Someone is on it" - alert stays visible but stops nagging. */
|
||||
acknowledgedAt: timestamp('acknowledged_at', { withTimezone: true }),
|
||||
acknowledgedBy: text('acknowledged_by').references(() => user.id),
|
||||
/** Set by the engine when the underlying condition no longer fires. */
|
||||
@@ -49,7 +49,7 @@ export const alerts = pgTable(
|
||||
metadata: jsonb('metadata').default({}),
|
||||
},
|
||||
(table) => [
|
||||
// Only one open alert per (port, fingerprint) — re-evaluation upserts.
|
||||
// Only one open alert per (port, fingerprint) - re-evaluation upserts.
|
||||
uniqueIndex('idx_alerts_fingerprint_open')
|
||||
.on(table.portId, table.fingerprint)
|
||||
.where(sql`resolved_at IS NULL`),
|
||||
@@ -85,7 +85,7 @@ export type NewAnalyticsSnapshot = typeof analyticsSnapshots.$inferInsert;
|
||||
export type AlertSeverity = 'info' | 'warning' | 'critical';
|
||||
|
||||
/**
|
||||
* Rule IDs in the v1 catalog — keep in sync with `alert-rules.ts`.
|
||||
* Rule IDs in the v1 catalog - keep in sync with `alert-rules.ts`.
|
||||
*
|
||||
* Two rules from the original spec (`document.expiring_soon`,
|
||||
* `audit.suspicious_login`) are deferred until their data sources land:
|
||||
|
||||
@@ -16,7 +16,7 @@ export const interests = pgTable(
|
||||
clientId: text('client_id')
|
||||
.notNull()
|
||||
.references(() => clients.id),
|
||||
berthId: text('berth_id'), // nullable — FK to berths defined in berths.ts, added via relation
|
||||
berthId: text('berth_id'), // nullable - FK to berths defined in berths.ts, added via relation
|
||||
yachtId: text('yacht_id'), // FK added via relation; nullable until pipeline leaves 'open'
|
||||
pipelineStage: text('pipeline_stage').notNull().default('open'),
|
||||
leadCategory: text('lead_category'), // general_interest, specific_qualified, hot_lead
|
||||
@@ -36,7 +36,7 @@ export const interests = pgTable(
|
||||
reminderEnabled: boolean('reminder_enabled').notNull().default(false),
|
||||
reminderDays: integer('reminder_days'),
|
||||
reminderLastFired: timestamp('reminder_last_fired', { withTimezone: true }),
|
||||
/** Terminal outcome. Independent of pipelineStage — `outcome` is set
|
||||
/** Terminal outcome. Independent of pipelineStage - `outcome` is set
|
||||
* alongside the stage transition to `completed` to distinguish won
|
||||
* deals from the various lost variants. NULL while the interest is
|
||||
* still active. */
|
||||
|
||||
@@ -28,7 +28,7 @@ export const migrationSourceLinks = pgTable(
|
||||
targetEntityType: text('target_entity_type').notNull(),
|
||||
/** UUID of the new-system entity (clients.id, interests.id, etc.). */
|
||||
targetEntityId: text('target_entity_id').notNull(),
|
||||
/** Apply-id from the migration run that created this link — pairs with
|
||||
/** Apply-id from the migration run that created this link - pairs with
|
||||
* the on-disk apply manifest so `--rollback --apply-id <id>` knows
|
||||
* exactly which links to remove. */
|
||||
appliedId: text('applied_id').notNull(),
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ports } from './ports';
|
||||
import { clients } from './clients';
|
||||
|
||||
/**
|
||||
* Portal users — one per client account that's been invited to the client
|
||||
* Portal users - one per client account that's been invited to the client
|
||||
* portal. Separate from the CRM `users` table (managed by better-auth) so the
|
||||
* authentication realms stay isolated.
|
||||
*
|
||||
|
||||
@@ -3,7 +3,7 @@ import { pgTable, text, timestamp, index } from 'drizzle-orm/pg-core';
|
||||
import { ports } from './ports';
|
||||
|
||||
/**
|
||||
* Residential clients — physically separated from `clients` because the
|
||||
* Residential clients - physically separated from `clients` because the
|
||||
* residential side is handled by an external team that should never see
|
||||
* marina-side data, and vice versa. The two domains share a port but no
|
||||
* tables, so the access boundary is enforced at the schema level.
|
||||
@@ -24,7 +24,7 @@ export const residentialClients = pgTable(
|
||||
* PhoneInput component lands. The free-text `phone` column stays
|
||||
* for one release as a fallback for unparseable rows. */
|
||||
phoneE164: text('phone_e164'),
|
||||
/** ISO-3166-1 alpha-2 — country the phone was parsed against. */
|
||||
/** ISO-3166-1 alpha-2 - country the phone was parsed against. */
|
||||
phoneCountry: text('phone_country'),
|
||||
/** ISO-3166-1 alpha-2 nationality. */
|
||||
nationalityIso: text('nationality_iso'),
|
||||
@@ -55,7 +55,7 @@ export const residentialClients = pgTable(
|
||||
);
|
||||
|
||||
/**
|
||||
* Residential interests — one per inquiry/lead. A residential_client can
|
||||
* Residential interests - one per inquiry/lead. A residential_client can
|
||||
* have multiple interests over time (e.g. inquired about a unit in 2025,
|
||||
* came back about a different unit in 2026).
|
||||
*
|
||||
@@ -78,7 +78,7 @@ export const residentialInterests = pgTable(
|
||||
source: text('source'), // website | manual | referral | broker
|
||||
notes: text('notes'),
|
||||
/**
|
||||
* Free-text capture of unit-type / size / floor / budget preferences —
|
||||
* Free-text capture of unit-type / size / floor / budget preferences -
|
||||
* residential leads are exploratory and the external team uses notes
|
||||
* heavily. Schema can grow into structured columns later if needed.
|
||||
*/
|
||||
|
||||
@@ -144,7 +144,7 @@ export type UserPreferences = {
|
||||
|
||||
/**
|
||||
* Core user table managed by Better Auth.
|
||||
* Do NOT modify directly — Better Auth handles CRUD via its adapter.
|
||||
* Do NOT modify directly - Better Auth handles CRUD via its adapter.
|
||||
*/
|
||||
export const user = pgTable('user', {
|
||||
id: text('id').primaryKey(),
|
||||
@@ -282,7 +282,7 @@ export const userPortRoles = pgTable(
|
||||
);
|
||||
|
||||
/**
|
||||
* Sessions table — Better Auth compatibility.
|
||||
* Sessions table - Better Auth compatibility.
|
||||
* Better Auth manages session creation/validation.
|
||||
*/
|
||||
export const session = pgTable(
|
||||
|
||||
Reference in New Issue
Block a user