diff --git a/actions/shots.ts b/actions/shots.ts index 8da85b1..a71bc13 100644 --- a/actions/shots.ts +++ b/actions/shots.ts @@ -197,6 +197,7 @@ export async function duplicateShot(sourceShotId: string) { const updateShotSchema = z.object({ shotId: z.string().cuid(), + shotCode: z.string().min(1).max(120).regex(/^[A-Z0-9_]+$/i, "Alphanumeric and underscores only").optional(), description: z.string().optional(), status: z.nativeEnum(ShotStatus).optional(), priority: z.nativeEnum(ShotPriority).optional(), @@ -218,12 +219,22 @@ export async function updateShot(data: z.infer) { } const parsed = updateShotSchema.parse(data); - const { shotId, dueDate, artistId, ...rest } = parsed; + const { shotId, dueDate, artistId, shotCode, ...rest } = parsed; + + // Check uniqueness if shotCode is being changed + if (shotCode) { + const existing = await db.shot.findFirst({ + where: { projectId: (await db.shot.findUnique({ where: { id: shotId }, select: { projectId: true } }))!.projectId, shotCode, id: { not: shotId } }, + select: { id: true }, + }); + if (existing) throw new Error(`Shot code "${shotCode}" is already used in this project.`); + } const shot = await db.shot.update({ where: { id: shotId }, data: { ...rest, + ...(shotCode ? { shotCode: shotCode.toUpperCase() } : {}), dueDate: dueDate ? new Date(dueDate) : dueDate === null ? null : undefined, artistId: artistId === "" ? null : artistId, }, diff --git a/components/shots/ShotSettingsTab.tsx b/components/shots/ShotSettingsTab.tsx index e388e9d..a8920ac 100644 --- a/components/shots/ShotSettingsTab.tsx +++ b/components/shots/ShotSettingsTab.tsx @@ -22,6 +22,7 @@ import { useToast } from "@/components/ui/use-toast"; import { Upload, X, Film, ImageIcon, Video } from "lucide-react"; const settingsSchema = z.object({ + shotCode: z.string().min(1, "Required").max(120).regex(/^[A-Z0-9_]+$/i, "Alphanumeric and underscores only"), description: z.string().optional(), status: z.enum(["WAITING", "IN_PROGRESS", "IN_REVIEW", "REVISIONS", "COMPLETE"]), priority: z.enum(["LOW", "NORMAL", "HIGH", "URGENT"]), @@ -128,6 +129,7 @@ export function ShotSettingsTab({ shot, artists, onSaved }: ShotSettingsTabProps } = useForm({ resolver: zodResolver(settingsSchema), defaultValues: { + shotCode: shot.shotCode, description: shot.description ?? "", status: shot.status as SettingsFormValues["status"], priority: shot.priority as SettingsFormValues["priority"], @@ -209,6 +211,7 @@ export function ShotSettingsTab({ shot, artists, onSaved }: ShotSettingsTabProps await updateShot({ shotId: shot.id, + shotCode: values.shotCode, description: values.description || undefined, status: values.status, priority: values.priority, @@ -240,6 +243,16 @@ export function ShotSettingsTab({ shot, artists, onSaved }: ShotSettingsTabProps +
+ + + {errors.shotCode &&

{errors.shotCode.message}

} +
+