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>
This commit is contained in:
97
src/lib/validators/berths.ts
Normal file
97
src/lib/validators/berths.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { z } from 'zod';
|
||||
import { BERTH_STATUSES } from '@/lib/constants';
|
||||
import { baseListQuerySchema } from '@/lib/api/route-helpers';
|
||||
|
||||
// ─── Update Berth ─────────────────────────────────────────────────────────────
|
||||
|
||||
export const updateBerthSchema = z.object({
|
||||
area: z.string().optional(),
|
||||
lengthFt: z.coerce.number().optional(),
|
||||
lengthM: z.coerce.number().optional(),
|
||||
widthFt: z.coerce.number().optional(),
|
||||
widthM: z.coerce.number().optional(),
|
||||
draftFt: z.coerce.number().optional(),
|
||||
draftM: z.coerce.number().optional(),
|
||||
widthIsMinimum: z.boolean().optional(),
|
||||
nominalBoatSize: z.string().optional(),
|
||||
nominalBoatSizeM: z.string().optional(),
|
||||
waterDepth: z.coerce.number().optional(),
|
||||
waterDepthM: z.coerce.number().optional(),
|
||||
waterDepthIsMinimum: z.boolean().optional(),
|
||||
sidePontoon: z.string().optional(),
|
||||
powerCapacity: z.string().optional(),
|
||||
voltage: z.string().optional(),
|
||||
mooringType: z.string().optional(),
|
||||
cleatType: z.string().optional(),
|
||||
cleatCapacity: z.string().optional(),
|
||||
bollardType: z.string().optional(),
|
||||
bollardCapacity: z.string().optional(),
|
||||
access: z.string().optional(),
|
||||
price: z.coerce.number().optional(),
|
||||
priceCurrency: z.string().optional(),
|
||||
bowFacing: z.string().optional(),
|
||||
berthApproved: z.boolean().optional(),
|
||||
tenureType: z.enum(['permanent', 'fixed_term']).optional(),
|
||||
tenureYears: z.coerce.number().int().optional(),
|
||||
tenureStartDate: z.string().optional(),
|
||||
tenureEndDate: z.string().optional(),
|
||||
});
|
||||
|
||||
export type UpdateBerthInput = z.infer<typeof updateBerthSchema>;
|
||||
|
||||
// ─── Update Berth Status ──────────────────────────────────────────────────────
|
||||
|
||||
export const updateBerthStatusSchema = z.object({
|
||||
status: z.enum(BERTH_STATUSES),
|
||||
reason: z.string().min(1, 'Reason is required'),
|
||||
});
|
||||
|
||||
export type UpdateBerthStatusInput = z.infer<typeof updateBerthStatusSchema>;
|
||||
|
||||
// ─── List Berths ──────────────────────────────────────────────────────────────
|
||||
|
||||
export const listBerthsSchema = baseListQuerySchema.extend({
|
||||
status: z.enum(BERTH_STATUSES).optional(),
|
||||
area: z.string().optional(),
|
||||
minLength: z.coerce.number().optional(),
|
||||
maxLength: z.coerce.number().optional(),
|
||||
minPrice: z.coerce.number().optional(),
|
||||
maxPrice: z.coerce.number().optional(),
|
||||
tenureType: z.enum(['permanent', 'fixed_term']).optional(),
|
||||
tagIds: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((v) => (v ? v.split(',') : undefined)),
|
||||
});
|
||||
|
||||
export type ListBerthsQuery = z.infer<typeof listBerthsSchema>;
|
||||
|
||||
// ─── Add Maintenance Log ──────────────────────────────────────────────────────
|
||||
|
||||
export const addMaintenanceLogSchema = z.object({
|
||||
category: z.enum(['routine', 'repair', 'inspection', 'upgrade']),
|
||||
description: z.string().min(1),
|
||||
cost: z.coerce.number().optional(),
|
||||
costCurrency: z.string().optional(),
|
||||
responsibleParty: z.string().optional(),
|
||||
performedDate: z.string().min(1, 'Performed date is required'),
|
||||
photoFileIds: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
export type AddMaintenanceLogInput = z.infer<typeof addMaintenanceLogSchema>;
|
||||
|
||||
// ─── Update Waiting List ──────────────────────────────────────────────────────
|
||||
|
||||
export const updateWaitingListSchema = z.object({
|
||||
entries: z.array(
|
||||
z.object({
|
||||
clientId: z.string(),
|
||||
position: z.number().int().min(1),
|
||||
priority: z.enum(['normal', 'high']).optional(),
|
||||
notifyPref: z.enum(['email', 'in_app', 'both']).optional(),
|
||||
notes: z.string().optional(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
export type UpdateWaitingListInput = z.infer<typeof updateWaitingListSchema>;
|
||||
Reference in New Issue
Block a user