221 lines
8.1 KiB
TypeScript
221 lines
8.1 KiB
TypeScript
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
|