+12
-1
@@ -197,6 +197,7 @@ export async function duplicateShot(sourceShotId: string) {
|
|||||||
|
|
||||||
const updateShotSchema = z.object({
|
const updateShotSchema = z.object({
|
||||||
shotId: z.string().cuid(),
|
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(),
|
description: z.string().optional(),
|
||||||
status: z.nativeEnum(ShotStatus).optional(),
|
status: z.nativeEnum(ShotStatus).optional(),
|
||||||
priority: z.nativeEnum(ShotPriority).optional(),
|
priority: z.nativeEnum(ShotPriority).optional(),
|
||||||
@@ -218,12 +219,22 @@ export async function updateShot(data: z.infer<typeof updateShotSchema>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parsed = updateShotSchema.parse(data);
|
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({
|
const shot = await db.shot.update({
|
||||||
where: { id: shotId },
|
where: { id: shotId },
|
||||||
data: {
|
data: {
|
||||||
...rest,
|
...rest,
|
||||||
|
...(shotCode ? { shotCode: shotCode.toUpperCase() } : {}),
|
||||||
dueDate: dueDate ? new Date(dueDate) : dueDate === null ? null : undefined,
|
dueDate: dueDate ? new Date(dueDate) : dueDate === null ? null : undefined,
|
||||||
artistId: artistId === "" ? null : artistId,
|
artistId: artistId === "" ? null : artistId,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { useToast } from "@/components/ui/use-toast";
|
|||||||
import { Upload, X, Film, ImageIcon, Video } from "lucide-react";
|
import { Upload, X, Film, ImageIcon, Video } from "lucide-react";
|
||||||
|
|
||||||
const settingsSchema = z.object({
|
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(),
|
description: z.string().optional(),
|
||||||
status: z.enum(["WAITING", "IN_PROGRESS", "IN_REVIEW", "REVISIONS", "COMPLETE"]),
|
status: z.enum(["WAITING", "IN_PROGRESS", "IN_REVIEW", "REVISIONS", "COMPLETE"]),
|
||||||
priority: z.enum(["LOW", "NORMAL", "HIGH", "URGENT"]),
|
priority: z.enum(["LOW", "NORMAL", "HIGH", "URGENT"]),
|
||||||
@@ -128,6 +129,7 @@ export function ShotSettingsTab({ shot, artists, onSaved }: ShotSettingsTabProps
|
|||||||
} = useForm<SettingsFormValues>({
|
} = useForm<SettingsFormValues>({
|
||||||
resolver: zodResolver(settingsSchema),
|
resolver: zodResolver(settingsSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
shotCode: shot.shotCode,
|
||||||
description: shot.description ?? "",
|
description: shot.description ?? "",
|
||||||
status: shot.status as SettingsFormValues["status"],
|
status: shot.status as SettingsFormValues["status"],
|
||||||
priority: shot.priority as SettingsFormValues["priority"],
|
priority: shot.priority as SettingsFormValues["priority"],
|
||||||
@@ -209,6 +211,7 @@ export function ShotSettingsTab({ shot, artists, onSaved }: ShotSettingsTabProps
|
|||||||
|
|
||||||
await updateShot({
|
await updateShot({
|
||||||
shotId: shot.id,
|
shotId: shot.id,
|
||||||
|
shotCode: values.shotCode,
|
||||||
description: values.description || undefined,
|
description: values.description || undefined,
|
||||||
status: values.status,
|
status: values.status,
|
||||||
priority: values.priority,
|
priority: values.priority,
|
||||||
@@ -240,6 +243,16 @@ export function ShotSettingsTab({ shot, artists, onSaved }: ShotSettingsTabProps
|
|||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
<Label>Shot Code</Label>
|
||||||
|
<Input
|
||||||
|
{...register("shotCode")}
|
||||||
|
className="font-mono uppercase"
|
||||||
|
placeholder="SHOW_SC010_0010"
|
||||||
|
/>
|
||||||
|
{errors.shotCode && <p className="text-xs text-destructive">{errors.shotCode.message}</p>}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<Label>Description</Label>
|
<Label>Description</Label>
|
||||||
<Textarea {...register("description")} rows={3} placeholder="Shot description…" />
|
<Textarea {...register("description")} rows={3} placeholder="Shot description…" />
|
||||||
|
|||||||
Reference in New Issue
Block a user