muller-reporting-sys/app/shift-manager/reports/[id]/page.tsx
2025-11-12 22:21:35 +03:00

208 lines
7.0 KiB
TypeScript

import DashboardLayout from "@/components/DashboardLayout"
import { auth } from "@/lib/auth"
import { prisma } from "@/lib/prisma"
import Link from "next/link"
import { notFound } from "next/navigation"
export default async function ReportViewPage({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const session = await auth()
const manager = await prisma.shiftManager.findFirst({
where: { email: session?.user?.email || "" }
})
if (!manager) return <div>Manager not found</div>
const report = await prisma.machineShiftReport.findFirst({
where: {
id,
shift: {
shiftManagerId: manager.id
}
},
include: {
worker: true,
machine: true,
shift: {
include: {
shiftTeamMembers: {
include: {
team: true
}
}
}
}
}
})
if (!report) notFound()
const { worker, machine, shift } = report
const team = shift.shiftTeamMembers[0]?.team
return (
<DashboardLayout requiredRole="shift_manager">
<div>
<div className="mb-6">
<Link
href={`/shift-manager/shifts/${shift.id}`}
className="text-blue-600 hover:underline mb-4 inline-block"
>
Back to Shift Details
</Link>
<h1 className="text-3xl font-bold text-gray-800">Operator Report</h1>
</div>
{/* Report Header */}
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div>
<p className="text-sm text-gray-500">Operator</p>
<p className="text-lg font-medium text-gray-900">
{worker.firstName} {worker.surname}
</p>
<p className="text-xs text-gray-500">{worker.email || 'N/A'}</p>
</div>
<div>
<p className="text-sm text-gray-500">Machine</p>
<p className="text-lg font-medium text-gray-900">{machine.name}</p>
<p className="text-xs text-gray-500">{machine.machineType}</p>
</div>
<div>
<p className="text-sm text-gray-500">Shift</p>
<p className="text-lg font-medium text-gray-900">{shift.name}</p>
<p className="text-xs text-gray-500">
{new Date(shift.shiftDate).toLocaleDateString()}
</p>
</div>
<div>
<p className="text-sm text-gray-500">Team</p>
<p className="text-lg font-medium text-gray-900">{team?.name || 'N/A'}</p>
</div>
<div>
<p className="text-sm text-gray-500">Submitted At</p>
<p className="text-lg font-medium text-gray-900">
{new Date(report.createdAt).toLocaleString()}
</p>
</div>
<div>
<p className="text-sm text-gray-500">Last Updated</p>
<p className="text-lg font-medium text-gray-900">
{new Date(report.updatedAt).toLocaleString()}
</p>
</div>
</div>
</div>
{/* Report Sections */}
<div className="space-y-6">
{/* Safety Checklist */}
{report.safetyChecklist && (
<ReportSection title="Safety Checklist" data={report.safetyChecklist} />
)}
{/* Production Parameters */}
{report.productionParameters && (
<ReportSection title="Production Parameters" data={report.productionParameters} />
)}
{/* Bottle Weight Tracking */}
{report.bottleWeightTracking && (
<ReportSection title="Bottle Weight Tracking" data={report.bottleWeightTracking} />
)}
{/* Hourly Quality Checks */}
{report.hourlyQualityChecks && (
<ReportSection title="Hourly Quality Checks" data={report.hourlyQualityChecks} />
)}
{/* Production Tracking */}
{report.productionTracking && (
<ReportSection title="Production Tracking" data={report.productionTracking} />
)}
{/* Seam Leak Test */}
{report.seamLeakTest && (
<ReportSection title="Seam Leak Test" data={report.seamLeakTest} />
)}
{/* Film Details */}
{report.filmDetails && (
<ReportSection title="Film Details" data={report.filmDetails} />
)}
{/* Wall Thickness */}
{report.wallThickness && (
<ReportSection title="Wall Thickness" data={report.wallThickness} />
)}
{/* Section Weights */}
{report.sectionWeights && (
<ReportSection title="Section Weights" data={report.sectionWeights} />
)}
{/* Station 1 Weights */}
{report.station1Weights && (
<ReportSection title="Station 1 Weights" data={report.station1Weights} />
)}
{/* Quality Metrics */}
{report.qualityMetrics && (
<ReportSection title="Quality Metrics" data={report.qualityMetrics} />
)}
{/* Output Metrics */}
{report.outputMetrics && (
<ReportSection title="Output Metrics" data={report.outputMetrics} />
)}
{/* Summary Data */}
{(report.averageWeight || report.totalBagsMade) && (
<div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
<h2 className="text-lg font-semibold text-gray-800">Summary</h2>
</div>
<div className="p-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{report.averageWeight && (
<div>
<p className="text-sm text-gray-500">Average Weight</p>
<p className="text-2xl font-bold text-gray-900">{report.averageWeight} g</p>
</div>
)}
{report.totalBagsMade && (
<div>
<p className="text-sm text-gray-500">Total Bags Made</p>
<p className="text-2xl font-bold text-gray-900">{report.totalBagsMade}</p>
</div>
)}
</div>
</div>
</div>
)}
</div>
</div>
</DashboardLayout>
)
}
function ReportSection({ title, data }: { title: string; data: any }) {
return (
<div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
<h2 className="text-lg font-semibold text-gray-800">{title}</h2>
</div>
<div className="p-6">
<pre className="bg-gray-50 p-4 rounded-lg overflow-x-auto text-sm">
{JSON.stringify(data, null, 2)}
</pre>
</div>
</div>
)
}