This commit is contained in:
@@ -65,6 +65,7 @@ interface ShotStatusClientProps {
|
||||
selectedProjectId: string | null;
|
||||
selectedProject: Project | null;
|
||||
shots: ShotRow[];
|
||||
episodeDueDates: { episode: string; dueDate: Date | string }[];
|
||||
canManage: boolean;
|
||||
}
|
||||
|
||||
@@ -388,11 +389,23 @@ export function ShotStatusClient({
|
||||
selectedProjectId,
|
||||
selectedProject,
|
||||
shots,
|
||||
episodeDueDates,
|
||||
canManage,
|
||||
}: ShotStatusClientProps) {
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
|
||||
// Restore last selected project if no project is currently selected
|
||||
useEffect(() => {
|
||||
if (!selectedProjectId) {
|
||||
const saved = localStorage.getItem("shotStatus:lastProjectId");
|
||||
if (saved && projects.some((p) => p.id === saved)) {
|
||||
router.replace(`/shot-status?projectId=${saved}`);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const [collapsedEpisodes, setCollapsedEpisodes] = useState<Set<string>>(new Set());
|
||||
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
|
||||
const [dueDateDialogOpen, setDueDateDialogOpen] = useState(false);
|
||||
@@ -405,6 +418,7 @@ export function ShotStatusClient({
|
||||
});
|
||||
|
||||
const handleProjectChange = (id: string) => {
|
||||
localStorage.setItem("shotStatus:lastProjectId", id);
|
||||
setSelectedIds(new Set());
|
||||
router.push(`/shot-status?projectId=${id}`);
|
||||
};
|
||||
@@ -454,6 +468,10 @@ export function ShotStatusClient({
|
||||
})()
|
||||
: [];
|
||||
|
||||
const episodeDueDateMap = new Map(
|
||||
episodeDueDates.map((e) => [e.episode, new Date(e.dueDate)])
|
||||
);
|
||||
|
||||
const statusCounts = shots.reduce(
|
||||
(acc, s) => {
|
||||
acc[s.status] = (acc[s.status] ?? 0) + 1;
|
||||
@@ -557,6 +575,8 @@ export function ShotStatusClient({
|
||||
const episodeIds = episodeShots.map((s) => s.id);
|
||||
const allEpSelected = episodeIds.every((id) => selectedIds.has(id));
|
||||
const someEpSelected = episodeIds.some((id) => selectedIds.has(id));
|
||||
const epDueDate = episodeDueDateMap.get(episode);
|
||||
const epIsOverdue = epDueDate && epDueDate < new Date();
|
||||
return (
|
||||
<div key={episode}>
|
||||
<div className="flex items-center gap-2 px-4 py-3 bg-zinc-800/60 hover:bg-zinc-800/90 transition-colors">
|
||||
@@ -581,6 +601,15 @@ export function ShotStatusClient({
|
||||
<span className="text-xs text-zinc-500 font-normal">
|
||||
{episodeShots.length} shot{episodeShots.length !== 1 ? "s" : ""}
|
||||
</span>
|
||||
{epDueDate && (
|
||||
<span className={cn(
|
||||
"flex items-center gap-1 text-xs",
|
||||
epIsOverdue ? "text-red-400" : "text-zinc-400"
|
||||
)}>
|
||||
<Calendar className="h-3 w-3" />
|
||||
{format(epDueDate, "d MMM yyyy")}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
{!collapsed && (
|
||||
|
||||
@@ -11,6 +11,14 @@ async function getProjects() {
|
||||
});
|
||||
}
|
||||
|
||||
async function getEpisodeDueDatesForProject(projectId: string) {
|
||||
return db.episodeDueDate.findMany({
|
||||
where: { projectId },
|
||||
select: { episode: true, dueDate: true },
|
||||
orderBy: { episode: "asc" },
|
||||
});
|
||||
}
|
||||
|
||||
async function getShotsForProject(projectId: string) {
|
||||
return db.shot.findMany({
|
||||
where: { projectId },
|
||||
@@ -47,9 +55,10 @@ export default async function ShotStatusPage({
|
||||
const { projectId } = await searchParams;
|
||||
const canManage = ["ADMIN", "PRODUCER", "SUPERVISOR"].includes(session.user.role);
|
||||
|
||||
const [projects, shots] = await Promise.all([
|
||||
const [projects, shots, episodeDueDates] = await Promise.all([
|
||||
getProjects(),
|
||||
projectId ? getShotsForProject(projectId) : Promise.resolve([]),
|
||||
projectId ? getEpisodeDueDatesForProject(projectId) : Promise.resolve([]),
|
||||
]);
|
||||
|
||||
const selectedProject = projects.find((p) => p.id === projectId) ?? null;
|
||||
@@ -60,6 +69,7 @@ export default async function ShotStatusPage({
|
||||
selectedProjectId={projectId ?? null}
|
||||
selectedProject={selectedProject}
|
||||
shots={shots as any}
|
||||
episodeDueDates={episodeDueDates}
|
||||
canManage={canManage}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user