Files
twotalesanimation 0aedc4b1fa
Deploy / deploy (push) Successful in 3m26s
feat(shots): previous/next shot navigation on the shot page
Prev/next buttons beside the breadcrumb walk the project's shot list in
the same order as the Shots tab. The ordering now lives in
lib/shot-order.ts, shared by the project page and the shot API.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 07:45:24 +02:00

37 lines
1.4 KiB
TypeScript

// The order shots appear in on the project page's Shots tab. Shared with the
// shot detail page so its previous/next navigation walks the same list.
type OrderableShot = {
episode?: string | null;
scene: string;
shotNumber: number;
shotGroup?: { name: string } | null;
};
export function sortShotsForList<T extends OrderableShot>(shots: T[], projectType: string): T[] {
// Episodic: episode → scene → shotNumber
if (projectType === "EPISODIC") {
return [...shots].sort((a, b) => {
const ea = a.episode ?? "";
const eb = b.episode ?? "";
if (ea !== eb) return ea.localeCompare(eb, undefined, { numeric: true });
if (a.scene !== b.scene) return a.scene.localeCompare(b.scene, undefined, { numeric: true });
return a.shotNumber - b.shotNumber;
});
}
// Standard with custom groups: group → scene → shotNumber, ungrouped last
if (projectType === "STANDARD" && shots.some((s) => s.shotGroup)) {
return [...shots].sort((a, b) => {
const ga = a.shotGroup?.name ?? "￿";
const gb = b.shotGroup?.name ?? "￿";
if (ga !== gb) return ga.localeCompare(gb, undefined, { numeric: true });
if (a.scene !== b.scene) return a.scene.localeCompare(b.scene, undefined, { numeric: true });
return a.shotNumber - b.shotNumber;
});
}
// Otherwise the list keeps the query's createdAt order
return shots;
}