7a7088f2ad
A per-user ShotCommentRead marker records how far each person has read a shot's comments. Comments and replies from others after the marker put an orange "!" beside the shot code; its popover lists them and only "Mark read" clears it. A chip filters the board to flagged shots and marks all read. The migration marks existing comments as read so the board starts clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
"use server";
|
|
|
|
import { auth } from "@/auth";
|
|
import { revalidatePath } from "next/cache";
|
|
import { z } from "zod";
|
|
import {
|
|
getUnreadCommentsForShot,
|
|
getUnreadCommentSummaries,
|
|
markShotCommentsRead as markRead,
|
|
} from "@/lib/comment-reads";
|
|
|
|
export async function listUnreadShotComments(shotId: string) {
|
|
const session = await auth();
|
|
if (!session?.user) throw new Error("Unauthorized");
|
|
return getUnreadCommentsForShot(session.user.id, z.string().min(1).parse(shotId));
|
|
}
|
|
|
|
const markSchema = z.object({
|
|
shotId: z.string().min(1),
|
|
upTo: z.string().datetime(),
|
|
});
|
|
|
|
export async function markShotCommentsRead(shotId: string, upTo: string) {
|
|
const session = await auth();
|
|
if (!session?.user) throw new Error("Unauthorized");
|
|
const parsed = markSchema.parse({ shotId, upTo });
|
|
await markRead(session.user.id, parsed.shotId, new Date(parsed.upTo));
|
|
revalidatePath("/shot-status");
|
|
return { success: true };
|
|
}
|
|
|
|
/** Mark every flagged shot in a project read, up to what each one had when checked. */
|
|
export async function markProjectCommentsRead(projectId: string) {
|
|
const session = await auth();
|
|
if (!session?.user) throw new Error("Unauthorized");
|
|
const summaries = await getUnreadCommentSummaries(session.user.id, z.string().min(1).parse(projectId));
|
|
for (const [shotId, s] of Object.entries(summaries)) {
|
|
await markRead(session.user.id, shotId, new Date(s.latestAt));
|
|
}
|
|
revalidatePath("/shot-status");
|
|
return { success: true, count: Object.keys(summaries).length };
|
|
}
|