354 lines
14 KiB
TypeScript
354 lines
14 KiB
TypeScript
|
|
import React from "react";
|
|||
|
|
import {
|
|||
|
|
FaTimes,
|
|||
|
|
FaCalendar,
|
|||
|
|
FaClock,
|
|||
|
|
FaUser,
|
|||
|
|
FaCog,
|
|||
|
|
FaCheckCircle,
|
|||
|
|
} from "react-icons/fa";
|
|||
|
|
import { MrpWorkOrder } from "../../../types/mrp";
|
|||
|
|
import { QualityStatusEnum } from "../../../types/mm";
|
|||
|
|
import {
|
|||
|
|
getWorkOrderStatusColor,
|
|||
|
|
getWorkOrderStatusText,
|
|||
|
|
} from "../../../utils/erp";
|
|||
|
|
|
|||
|
|
interface ViewWorkOrderModalProps {
|
|||
|
|
isOpen: boolean;
|
|||
|
|
onClose: () => void;
|
|||
|
|
workOrder: MrpWorkOrder | null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const ViewWorkOrderModal: React.FC<ViewWorkOrderModalProps> = ({
|
|||
|
|
isOpen,
|
|||
|
|
onClose,
|
|||
|
|
workOrder,
|
|||
|
|
}) => {
|
|||
|
|
if (!isOpen || !workOrder) return null;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|||
|
|
<div className="bg-white rounded-lg shadow-xl max-w-4xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
|||
|
|
<div className="flex items-center justify-between p-4 border-b sticky top-0 bg-white z-10">
|
|||
|
|
<h2 className="text-lg font-semibold text-gray-900">
|
|||
|
|
İş Emri Detayları
|
|||
|
|
</h2>
|
|||
|
|
<button
|
|||
|
|
onClick={onClose}
|
|||
|
|
className="text-gray-400 hover:text-gray-600"
|
|||
|
|
>
|
|||
|
|
<FaTimes className="w-4 h-4" />
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="p-4 space-y-4">
|
|||
|
|
{/* Header Info */}
|
|||
|
|
<div className="bg-gray-50 rounded-lg p-3">
|
|||
|
|
<div className="flex items-center justify-between mb-3">
|
|||
|
|
<h3 className="text-lg font-medium text-gray-900">
|
|||
|
|
{workOrder.workOrderNumber}
|
|||
|
|
</h3>
|
|||
|
|
<span
|
|||
|
|
className={`px-2 py-0.5 text-xs font-medium rounded-full ${getWorkOrderStatusColor(
|
|||
|
|
workOrder.status
|
|||
|
|
)}`}
|
|||
|
|
>
|
|||
|
|
{getWorkOrderStatusText(workOrder.status)}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<FaCalendar className="w-3 h-3 text-gray-500" />
|
|||
|
|
<span className="text-gray-600">Oluşturulma:</span>
|
|||
|
|
<span className="font-medium">
|
|||
|
|
{new Date(workOrder.creationTime).toLocaleDateString("tr-TR")}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<FaClock className="w-3 h-3 text-gray-500" />
|
|||
|
|
<span className="text-gray-600">Son Güncelleme:</span>
|
|||
|
|
<span className="font-medium">
|
|||
|
|
{new Date(workOrder.lastModificationTime).toLocaleDateString(
|
|||
|
|
"tr-TR"
|
|||
|
|
)}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center gap-2">
|
|||
|
|
<FaUser className="w-3 h-3 text-gray-500" />
|
|||
|
|
<span className="text-gray-600">Sıra:</span>
|
|||
|
|
<span className="font-medium">{workOrder.sequence}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Production Order Info */}
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Üretim Emri Bilgileri
|
|||
|
|
</h4>
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|||
|
|
<div>
|
|||
|
|
<span className="text-sm text-gray-600">Üretim Emri:</span>
|
|||
|
|
<p className="font-medium">
|
|||
|
|
{workOrder.productionOrder?.orderNumber ||
|
|||
|
|
workOrder.productionOrderId}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<span className="text-sm text-gray-600">Öncelik:</span>
|
|||
|
|
<p className="font-medium">
|
|||
|
|
{workOrder.productionOrder?.priority || "N/A"}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Operation & Material Info */}
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Operasyon Bilgileri
|
|||
|
|
</h4>
|
|||
|
|
<div className="space-y-2">
|
|||
|
|
<div>
|
|||
|
|
<span className="text-sm text-gray-600">Operasyon:</span>
|
|||
|
|
<p className="font-medium">
|
|||
|
|
{workOrder.operation?.name || workOrder.operationId}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<span className="text-sm text-gray-600">İş Merkezi:</span>
|
|||
|
|
<p className="font-medium">
|
|||
|
|
{workOrder.workCenter?.name || workOrder.workCenterId}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<span className="text-sm text-gray-600">
|
|||
|
|
Atanan Operatörler:
|
|||
|
|
</span>
|
|||
|
|
<p className="font-medium">
|
|||
|
|
{workOrder.assignedOperators.length} operatör
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Malzeme Bilgileri
|
|||
|
|
</h4>
|
|||
|
|
<div className="space-y-2">
|
|||
|
|
<div>
|
|||
|
|
<span className="text-sm text-gray-600">Malzeme:</span>
|
|||
|
|
<p className="font-medium">
|
|||
|
|
{workOrder.material?.code} -{" "}
|
|||
|
|
{workOrder.material?.name || workOrder.materialId}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<span className="text-sm text-gray-600">Birim:</span>
|
|||
|
|
<p className="font-medium">
|
|||
|
|
{workOrder.material?.baseUnit?.name || "N/A"}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Quantities */}
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Miktar Bilgileri
|
|||
|
|
</h4>
|
|||
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|||
|
|
<div className="text-center p-2 bg-blue-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-blue-600">
|
|||
|
|
{workOrder.plannedQuantity}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">Planlanan</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-center p-2 bg-green-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-green-600">
|
|||
|
|
{workOrder.confirmedQuantity}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">Tamamlanan</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-center p-2 bg-red-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-red-600">
|
|||
|
|
{workOrder.scrapQuantity}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">Fire</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-center p-2 bg-gray-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-gray-600">
|
|||
|
|
{workOrder.plannedQuantity -
|
|||
|
|
workOrder.confirmedQuantity -
|
|||
|
|
workOrder.scrapQuantity}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">Kalan</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Schedule */}
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Zamanlama
|
|||
|
|
</h4>
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|||
|
|
<div className="flex items-center gap-3">
|
|||
|
|
<FaCalendar className="w-5 h-5 text-blue-500" />
|
|||
|
|
<div>
|
|||
|
|
<div className="text-sm text-gray-600">
|
|||
|
|
Planlanan Başlangıç
|
|||
|
|
</div>
|
|||
|
|
<div className="font-medium">
|
|||
|
|
{new Date(workOrder.plannedStartDate).toLocaleDateString(
|
|||
|
|
"tr-TR"
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex items-center gap-3">
|
|||
|
|
<FaCalendar className="w-5 h-5 text-green-500" />
|
|||
|
|
<div>
|
|||
|
|
<div className="text-sm text-gray-600">Planlanan Bitiş</div>
|
|||
|
|
<div className="font-medium">
|
|||
|
|
{new Date(workOrder.plannedEndDate).toLocaleDateString(
|
|||
|
|
"tr-TR"
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Time Information */}
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Zaman Bilgileri
|
|||
|
|
</h4>
|
|||
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|||
|
|
<div className="text-center p-2 bg-yellow-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-yellow-600">
|
|||
|
|
{workOrder.setupTime}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">Kurulum (dk)</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-center p-2 bg-blue-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-blue-600">
|
|||
|
|
{workOrder.processTime}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">İşlem (dk)</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-center p-2 bg-purple-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-purple-600">
|
|||
|
|
{workOrder.actualSetupTime || 0}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">Gerçek Kurulum (dk)</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-center p-2 bg-indigo-50 rounded-lg">
|
|||
|
|
<div className="text-xl font-bold text-indigo-600">
|
|||
|
|
{workOrder.actualProcessTime || 0}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">Gerçek İşlem (dk)</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Confirmations */}
|
|||
|
|
{workOrder.confirmations.length > 0 && (
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Onaylar
|
|||
|
|
</h4>
|
|||
|
|
<div className="space-y-2">
|
|||
|
|
{workOrder.confirmations.map((confirmation, index) => (
|
|||
|
|
<div
|
|||
|
|
key={index}
|
|||
|
|
className="flex items-center justify-between p-2 bg-gray-50 rounded-lg"
|
|||
|
|
>
|
|||
|
|
<div className="flex items-center gap-3">
|
|||
|
|
<FaCheckCircle className="w-4 h-4 text-green-500" />
|
|||
|
|
<div>
|
|||
|
|
<div className="font-medium">
|
|||
|
|
{confirmation.confirmedBy}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">
|
|||
|
|
{new Date(
|
|||
|
|
confirmation.confirmationDate
|
|||
|
|
).toLocaleDateString("tr-TR")}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-right">
|
|||
|
|
<div className="font-medium">
|
|||
|
|
{confirmation.confirmedQuantity}
|
|||
|
|
</div>
|
|||
|
|
<div className="text-sm text-gray-600">adet</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* Quality Checks */}
|
|||
|
|
{workOrder.qualityChecks.length > 0 && (
|
|||
|
|
<div className="bg-white border rounded-lg p-3">
|
|||
|
|
<h4 className="text-base font-medium text-gray-900 mb-2">
|
|||
|
|
Kalite Kontrolleri
|
|||
|
|
</h4>
|
|||
|
|
<div className="space-y-2">
|
|||
|
|
{workOrder.qualityChecks.map((check, index) => (
|
|||
|
|
<div
|
|||
|
|
key={index}
|
|||
|
|
className="flex items-center justify-between p-2 bg-gray-50 rounded-lg"
|
|||
|
|
>
|
|||
|
|
<div className="flex items-center gap-3">
|
|||
|
|
<FaCog className="w-4 h-4 text-blue-500" />
|
|||
|
|
<div>
|
|||
|
|
<div className="font-medium">{check.checkType}</div>
|
|||
|
|
<div className="text-sm text-gray-600">
|
|||
|
|
{new Date(check.checkDate).toLocaleDateString(
|
|||
|
|
"tr-TR"
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div className="text-right">
|
|||
|
|
<span
|
|||
|
|
className={`px-2 py-1 text-xs font-medium rounded-full ${
|
|||
|
|
check.status === QualityStatusEnum.Pending
|
|||
|
|
? "bg-green-100 text-green-800"
|
|||
|
|
: check.status === QualityStatusEnum.Rejected
|
|||
|
|
? "bg-red-100 text-red-800"
|
|||
|
|
: "bg-yellow-100 text-yellow-800"
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
{check.status}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="flex justify-end p-4 border-t sticky bottom-0 bg-white">
|
|||
|
|
<button
|
|||
|
|
onClick={onClose}
|
|||
|
|
className="px-3 py-1.5 bg-gray-600 text-white rounded-md hover:bg-gray-700 transition-colors text-sm"
|
|||
|
|
>
|
|||
|
|
Kapat
|
|||
|
|
</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default ViewWorkOrderModal;
|