Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
import { z } from 'zod';
|
|
|
|
|
|
|
|
|
|
const CUSTOM_FIELD_TYPES = ['text', 'number', 'date', 'boolean', 'select'] as const;
|
|
|
|
|
const CUSTOM_FIELD_ENTITIES = ['client', 'interest', 'berth'] as const;
|
|
|
|
|
|
|
|
|
|
export const createFieldSchema = z
|
|
|
|
|
.object({
|
|
|
|
|
entityType: z.enum(CUSTOM_FIELD_ENTITIES),
|
|
|
|
|
fieldName: z
|
|
|
|
|
.string()
|
|
|
|
|
.min(1)
|
|
|
|
|
.max(50)
|
|
|
|
|
.regex(/^[a-z_][a-z0-9_]*$/, 'Must be snake_case'),
|
|
|
|
|
fieldLabel: z.string().min(1).max(100),
|
|
|
|
|
fieldType: z.enum(CUSTOM_FIELD_TYPES),
|
2026-05-04 22:57:01 +02:00
|
|
|
selectOptions: z.array(z.string().min(1).max(100)).min(1).max(50).optional(),
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
isRequired: z.boolean().default(false),
|
|
|
|
|
sortOrder: z.number().int().min(0).default(0),
|
|
|
|
|
})
|
|
|
|
|
.refine(
|
2026-05-04 22:57:01 +02:00
|
|
|
(data) => data.fieldType !== 'select' || (data.selectOptions && data.selectOptions.length > 0),
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
{
|
|
|
|
|
message: 'Select fields must have at least one option',
|
|
|
|
|
path: ['selectOptions'],
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const updateFieldSchema = z.object({
|
|
|
|
|
fieldLabel: z.string().min(1).max(100).optional(),
|
|
|
|
|
selectOptions: z.array(z.string().min(1).max(100)).optional(),
|
|
|
|
|
isRequired: z.boolean().optional(),
|
|
|
|
|
sortOrder: z.number().int().min(0).optional(),
|
2026-05-04 22:57:01 +02:00
|
|
|
// fieldType intentionally omitted - cannot be changed after creation
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const setValuesSchema = z.object({
|
|
|
|
|
values: z.array(
|
|
|
|
|
z.object({
|
|
|
|
|
fieldId: z.string().uuid(),
|
|
|
|
|
value: z.unknown(),
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export type CreateFieldInput = z.infer<typeof createFieldSchema>;
|
|
|
|
|
export type UpdateFieldInput = z.infer<typeof updateFieldSchema>;
|
|
|
|
|
export type SetValuesInput = z.infer<typeof setValuesSchema>;
|