286 lines
7.3 KiB
TypeScript
286 lines
7.3 KiB
TypeScript
import { Role, ApprovalStatus, ReviewStatus, ShotStatus, ShotPriority, ProjectStatus, TaskStatus, TaskType } from "@prisma/client";
|
|
|
|
// Re-export Prisma enums for convenience
|
|
export { Role, ApprovalStatus, ReviewStatus, ShotStatus, ShotPriority, ProjectStatus, TaskStatus, TaskType };
|
|
|
|
// ── Annotation Types ─────────────────────────────────────────────────────────
|
|
|
|
export type AnnotationTool = "freehand" | "arrow" | "rectangle" | "circle";
|
|
|
|
export interface AnnotationPoint {
|
|
x: number; // normalized 0-1 relative to canvas width
|
|
y: number; // normalized 0-1 relative to canvas height
|
|
}
|
|
|
|
export interface AnnotationShape {
|
|
id: string;
|
|
tool: AnnotationTool;
|
|
/** For freehand: all path points. For others: [startPoint, endPoint] */
|
|
points: AnnotationPoint[];
|
|
color: string;
|
|
strokeWidth: number;
|
|
frameNumber: number;
|
|
}
|
|
|
|
export interface AnnotationDrawingData {
|
|
shapes: AnnotationShape[];
|
|
canvasWidth: number;
|
|
canvasHeight: number;
|
|
version: "1.0";
|
|
}
|
|
|
|
// ── Review Player State ──────────────────────────────────────────────────────
|
|
|
|
export interface ReviewPlayerState {
|
|
isPlaying: boolean;
|
|
currentFrame: number;
|
|
currentTime: number;
|
|
duration: number;
|
|
playbackRate: number;
|
|
volume: number;
|
|
isMuted: boolean;
|
|
isFullscreen: boolean;
|
|
isAnnotating: boolean;
|
|
selectedTool: AnnotationTool;
|
|
selectedColor: string;
|
|
strokeWidth: number;
|
|
showAnnotations: boolean;
|
|
fps: number;
|
|
totalFrames: number;
|
|
}
|
|
|
|
// ── Comment Types ────────────────────────────────────────────────────────────
|
|
|
|
export interface CommentWithReplies {
|
|
id: string;
|
|
versionId: string;
|
|
authorId: string;
|
|
frameNumber: number;
|
|
timestamp: number;
|
|
text: string;
|
|
isResolved: boolean;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
author: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
image: string | null;
|
|
role: Role;
|
|
} | null;
|
|
replies: CommentReplyWithAuthor[];
|
|
annotations: AnnotationSummary[];
|
|
}
|
|
|
|
export interface CommentReplyWithAuthor {
|
|
id: string;
|
|
commentId: string;
|
|
authorId: string;
|
|
text: string;
|
|
createdAt: Date;
|
|
author: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
image: string | null;
|
|
role: Role;
|
|
} | null;
|
|
}
|
|
|
|
export interface AnnotationSummary {
|
|
id: string;
|
|
frameNumber: number;
|
|
drawingData: unknown;
|
|
color: string;
|
|
isVisible: boolean;
|
|
authorId: string;
|
|
}
|
|
|
|
// ── Version Types ────────────────────────────────────────────────────────────
|
|
|
|
export interface VersionWithDetails {
|
|
id: string;
|
|
versionNumber: number;
|
|
shotId: string | null;
|
|
taskId: string | null;
|
|
artistId: string | null;
|
|
isClientVisible: boolean;
|
|
sharedAt: Date | null;
|
|
sharedById: string | null;
|
|
fileUrl: string;
|
|
fileName: string;
|
|
fileSize: bigint | null;
|
|
mimeType: string | null;
|
|
thumbnailUrl: string | null;
|
|
posterUrl: string | null;
|
|
proxyUrl: string | null;
|
|
fps: number;
|
|
duration: number | null;
|
|
frameCount: number | null;
|
|
width: number | null;
|
|
height: number | null;
|
|
notes: string | null;
|
|
approvalStatus: ApprovalStatus;
|
|
reviewStatus: ReviewStatus;
|
|
isLatest: boolean;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
artist: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
image: string | null;
|
|
} | null;
|
|
_count?: {
|
|
comments: number;
|
|
};
|
|
approvals?: {
|
|
id: string;
|
|
status: string;
|
|
notes: string | null;
|
|
createdAt: Date;
|
|
user: { id: string; name: string | null; image: string | null };
|
|
}[];
|
|
}
|
|
|
|
// ── Shot Types ───────────────────────────────────────────────────────────────
|
|
|
|
export interface ShotWithDetails {
|
|
id: string;
|
|
shotCode: string;
|
|
scene: string;
|
|
episode: string | null;
|
|
shotNumber: number;
|
|
sequence: string | null;
|
|
description: string | null;
|
|
status: ShotStatus;
|
|
priority: ShotPriority;
|
|
artistId: string | null;
|
|
projectId: string;
|
|
fps: number;
|
|
frameStart: number | null;
|
|
frameEnd: number | null;
|
|
dueDate: Date | null;
|
|
thumbnailUrl: string | null;
|
|
originalFootageUrl: string | null;
|
|
originalFootageKey: string | null;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
artist: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
image: string | null;
|
|
} | null;
|
|
versions: VersionWithDetails[];
|
|
_count?: {
|
|
versions: number;
|
|
};
|
|
}
|
|
|
|
// ── Task Types ───────────────────────────────────────────────────────────────
|
|
|
|
export interface TaskWithDetails {
|
|
id: string;
|
|
title: string;
|
|
description: string | null;
|
|
type: TaskType;
|
|
status: TaskStatus;
|
|
priority: ShotPriority;
|
|
dueDate: Date | null;
|
|
estimatedHours: number | null;
|
|
sortOrder: number;
|
|
shotId: string | null;
|
|
assetId: string | null;
|
|
assignedArtistId: string | null;
|
|
createdById: string;
|
|
projectId: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
assignedArtist: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
image: string | null;
|
|
} | null;
|
|
createdBy: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
};
|
|
_count?: {
|
|
versions: number;
|
|
};
|
|
}
|
|
|
|
export interface AssetWithDetails {
|
|
id: string;
|
|
projectId: string;
|
|
assetCode: string;
|
|
name: string;
|
|
description: string | null;
|
|
status: ShotStatus;
|
|
priority: ShotPriority;
|
|
leadId: string | null;
|
|
dueDate: Date | null;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
lead: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
image: string | null;
|
|
} | null;
|
|
tasks: TaskWithDetails[];
|
|
_count?: {
|
|
tasks: number;
|
|
};
|
|
}
|
|
|
|
// ── Dashboard Types ──────────────────────────────────────────────────────────
|
|
|
|
export interface DashboardStats {
|
|
awaitingReview: number;
|
|
needsRevisions: number;
|
|
approved: number;
|
|
overdue: number;
|
|
activeProjects: number;
|
|
// Task widgets
|
|
tasksDueToday: number;
|
|
tasksInReview: number;
|
|
tasksOverdue: number;
|
|
myTasksCount: number;
|
|
}
|
|
|
|
// ── Notification Badge ────────────────────────────────────────────────────────
|
|
|
|
export interface NotificationItem {
|
|
id: string;
|
|
type: string;
|
|
title: string;
|
|
message: string;
|
|
data: Record<string, unknown> | null;
|
|
isRead: boolean;
|
|
createdAt: Date;
|
|
}
|
|
|
|
// ── Next-Auth session extension ──────────────────────────────────────────────
|
|
|
|
declare module "next-auth" {
|
|
interface Session {
|
|
user: {
|
|
id: string;
|
|
role: Role;
|
|
mustChangePassword: boolean;
|
|
name?: string | null;
|
|
email?: string | null;
|
|
image?: string | null;
|
|
};
|
|
}
|
|
|
|
interface User {
|
|
role: Role;
|
|
mustChangePassword?: boolean;
|
|
}
|
|
}
|