import Link from "next/link"; import { requireOperator } from "@/lib/auth"; import { prisma } from "@/lib/prisma"; /** * Operator dashboard. Because phones often have the browser open between scans, * we want this page to answer one question fast: "what am I currently working * on?" Active claims are the headline list; below that we show a generic * "scan a card to start" hint so a fresh operator knows what to do. */ const OP_INCLUDE = { machine: { select: { name: true } }, part: { select: { code: true, name: true, qty: true, assembly: { select: { code: true, qty: true, project: { select: { code: true, name: true } }, }, }, }, }, } as const; export default async function OperatorHomePage() { const user = await requireOperator(); const [claims, resumable] = await Promise.all([ prisma.operation.findMany({ where: { claimedByUserId: user.id, status: "in_progress" }, orderBy: { claimedAt: "desc" }, include: OP_INCLUDE, }), // B1: partial ops are unclaimed after a release and only re-surface when // someone physically re-scans the card. List them here so any operator // can pick up where the last shift left off. prisma.operation.findMany({ where: { status: "partial", claimedByUserId: null }, orderBy: { updatedAt: "desc" }, take: 50, include: OP_INCLUDE, }), ]); return (

Hi, {user.name}

Scan a QR card with your phone camera to start a step, or continue an active one below.

{claims.length === 0 && resumable.length === 0 ? (
You have no active steps. Scan a traveler QR to begin.
) : null} {claims.length > 0 ? (

Active ({claims.length})

{claims.map((c) => (
{c.part.assembly.project.code} · {c.part.assembly.code}
{c.part.name}
Step {c.sequence}: {c.name}
{c.part.code} {c.machine ? {c.machine.name} : null} {c.claimedAt ? since {new Date(c.claimedAt).toLocaleTimeString()} : null}
))}
) : null} {resumable.length > 0 ? (

Resumable ({resumable.length})

Previously started and released with units still to run. Tap to pick up where the last shift left off.

{resumable.map((c) => { const total = c.part.qty * c.part.assembly.qty; const remaining = Math.max(total - c.unitsCompleted, 0); return (
{c.part.assembly.project.code} · {c.part.assembly.code}
{c.part.name}
Step {c.sequence}: {c.name}
{c.part.code} {c.machine ? {c.machine.name} : null} {c.unitsCompleted} of {total} done · {remaining} remaining
); })}
) : null}
); }