erp-platform/ui/src/views/maintenance/components/AssignNotificationModal.tsx

251 lines
8.6 KiB
TypeScript
Raw Normal View History

2025-09-15 09:31:47 +00:00
import React, { useState } from "react";
import { FaTimes, FaSave, FaUser, FaUsers } from "react-icons/fa";
import { PmFaultNotification } from "../../../types/pm";
import { mockEmployees } from "../../../mocks/mockEmployees";
import { mockMaintenanceTeams } from "../../../mocks/mockMaintenanceTeams";
interface AssignNotificationModalProps {
isOpen: boolean;
onClose: () => void;
onSave: (assignments: {
notificationIds: string[];
assignedTo?: string;
teamId?: string;
}) => void;
notifications: PmFaultNotification[];
}
const AssignNotificationModal: React.FC<AssignNotificationModalProps> = ({
isOpen,
onClose,
onSave,
notifications,
}) => {
const [assignmentType, setAssignmentType] = useState<"person" | "team">(
"person"
);
const [assignedTo, setAssignedTo] = useState("");
const [teamId, setTeamId] = useState("");
const [errors, setErrors] = useState<Record<string, string>>({});
if (!isOpen || notifications.length === 0) return null;
const validateForm = () => {
const newErrors: Record<string, string> = {};
if (assignmentType === "person" && !assignedTo) {
newErrors.assignedTo = "Kişi seçimi gerekli";
}
if (assignmentType === "team" && !teamId) {
newErrors.teamId = "Ekip seçimi gerekli";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSave = () => {
if (validateForm()) {
const assignmentData = {
notificationIds: notifications.map((n) => n.id),
...(assignmentType === "person" ? { assignedTo } : { teamId }),
};
onSave(assignmentData);
onClose();
// Reset form
setAssignmentType("person");
setAssignedTo("");
setTeamId("");
setErrors({});
}
};
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto">
{/* Header */}
<div className="flex items-center justify-between p-3 border-b border-gray-200">
<h2 className="text-xl font-bold text-gray-900">Atama Yap</h2>
<button
onClick={onClose}
className="text-gray-400 hover:text-gray-600 transition-colors"
>
<FaTimes className="w-5 h-5" />
</button>
</div>
{/* Content */}
<div className="p-3 space-y-3">
{/* Notification Summary */}
<div className="bg-blue-50 border border-blue-200 rounded-lg p-2">
<h4 className="text-xs font-medium text-blue-800 mb-1.5">
Seçili Arıza Bildirimleri ({notifications.length})
</h4>
<div className="space-y-1">
{notifications.map((notification) => (
<div key={notification.id} className="text-sm text-blue-700">
<span className="font-medium">
{notification.notificationCode}
</span>
{" - "}
<span>{notification.title}</span>
{" ("}
<span>{notification.workCenter.code}</span>
{")"}
</div>
))}
</div>
</div>
{/* Assignment Type */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Atama Türü
</label>
<div className="flex space-x-3">
<label className="flex items-center">
<input
type="radio"
value="person"
checked={assignmentType === "person"}
onChange={(e) =>
setAssignmentType(e.target.value as "person" | "team")
}
className="mr-2"
/>
<FaUser className="w-4 h-4 mr-2 text-gray-500" />
<span>Kişiye Ata</span>
</label>
<label className="flex items-center">
<input
type="radio"
value="team"
checked={assignmentType === "team"}
onChange={(e) =>
setAssignmentType(e.target.value as "person" | "team")
}
className="mr-2"
/>
<FaUsers className="w-4 h-4 mr-2 text-gray-500" />
<span>Ekibe Ata</span>
</label>
</div>
</div>
{/* Person Assignment */}
{assignmentType === "person" && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Atanacak Kişi *
</label>
<select
value={assignedTo}
onChange={(e) => setAssignedTo(e.target.value)}
className={`w-full px-2.5 py-1.5 text-sm border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${
errors.assignedTo ? "border-red-500" : "border-gray-300"
}`}
>
<option value="">Kişi seçin</option>
{mockEmployees.map((employee) => (
<option key={employee.id} value={employee.fullName}>
{employee.fullName} - {employee.jobPosition?.name}
</option>
))}
</select>
{errors.assignedTo && (
<p className="text-red-500 text-xs mt-1">{errors.assignedTo}</p>
)}
</div>
)}
{/* Team Assignment */}
{assignmentType === "team" && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Atanacak Ekip *
</label>
<select
value={teamId}
onChange={(e) => setTeamId(e.target.value)}
className={`w-full px-2.5 py-1.5 text-sm border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${
errors.teamId ? "border-red-500" : "border-gray-300"
}`}
>
<option value="">Ekip seçin</option>
{mockMaintenanceTeams
.filter((team) => team.isActive)
.map((team) => (
<option key={team.id} value={team.id}>
{team.name} ({team.code})
</option>
))}
</select>
{errors.teamId && (
<p className="text-red-500 text-xs mt-1">{errors.teamId}</p>
)}
</div>
)}
{/* Assignment Preview */}
{(assignedTo || teamId) && (
<div className="bg-green-50 border border-green-200 rounded-lg p-2">
<h4 className="text-sm font-medium text-green-800 mb-1">
Atama Özeti
</h4>
<div className="text-sm text-green-700">
<p>
<strong>{notifications.length}</strong> arıza bildirimi{" "}
{assignmentType === "person" ? (
<>
<strong>
{
mockEmployees.find(
(emp) => emp.fullName === assignedTo
)?.fullName
}
</strong>
kişisine atanacak
</>
) : (
<>
<strong>
{
mockMaintenanceTeams.find(
(team) => team.id === teamId
)?.name
}
</strong>
ekibine atanacak
</>
)}
</p>
</div>
</div>
)}
</div>
{/* Footer */}
<div className="flex items-center justify-end space-x-2 p-3 border-t border-gray-200">
<button
onClick={onClose}
className="px-3 py-1 text-sm text-gray-600 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
>
İptal
</button>
<button
onClick={handleSave}
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center space-x-2"
>
<FaSave className="w-4 h-4" />
<span>Ata</span>
</button>
</div>
</div>
</div>
);
};
export default AssignNotificationModal;