erp-platform/ui/src/views/hr/components/BadgeAssignmentModal.tsx
2025-09-16 00:02:48 +03:00

336 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from "react";
import {
FaUsers,
FaAward,
FaSave,
FaTimesCircle,
FaCalendarAlt,
} from "react-icons/fa";
import { mockEmployees } from "../../../mocks/mockEmployees";
import { mockBadges } from "../../../mocks/mockBadges";
export interface BadgeAssignmentFormData {
employeeId: string;
badgeId: string;
reason?: string;
earnedDate: string;
expiryDate?: string;
notes?: string;
}
interface BadgeAssignmentModalProps {
isOpen: boolean;
onClose: () => void;
onSubmit: (assignmentData: BadgeAssignmentFormData) => void;
preSelectedEmployeeId?: string;
preSelectedBadgeId?: string;
}
const BadgeAssignmentModal: React.FC<BadgeAssignmentModalProps> = ({
isOpen,
onClose,
onSubmit,
preSelectedEmployeeId,
preSelectedBadgeId,
}) => {
const [formData, setFormData] = useState<BadgeAssignmentFormData>({
employeeId: "",
badgeId: "",
reason: "",
earnedDate: new Date().toISOString().split("T")[0],
expiryDate: "",
notes: "",
});
const [searchEmployee, setSearchEmployee] = useState("");
const [searchBadge, setSearchBadge] = useState("");
useEffect(() => {
if (isOpen) {
setFormData({
employeeId: preSelectedEmployeeId || "",
badgeId: preSelectedBadgeId || "",
reason: "",
earnedDate: new Date().toISOString().split("T")[0],
expiryDate: "",
notes: "",
});
setSearchEmployee("");
setSearchBadge("");
}
}, [isOpen, preSelectedEmployeeId, preSelectedBadgeId]);
const handleInputChange = (
e: React.ChangeEvent<
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
>
) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSubmit(formData);
onClose();
};
const filteredEmployees = mockEmployees.filter(
(employee) =>
employee.fullName.toLowerCase().includes(searchEmployee.toLowerCase()) ||
employee.code.toLowerCase().includes(searchEmployee.toLowerCase())
);
const filteredBadges = mockBadges.filter(
(badge) =>
badge.isActive &&
(badge.name.toLowerCase().includes(searchBadge.toLowerCase()) ||
badge.description.toLowerCase().includes(searchBadge.toLowerCase()))
);
const selectedEmployee = mockEmployees.find(
(emp) => emp.id === formData.employeeId
);
const selectedBadge = mockBadges.find(
(badge) => badge.id === formData.badgeId
);
return (
isOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-xl shadow-2xl 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 bg-gradient-to-r from-green-50 to-emerald-50 rounded-t-xl">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-green-600 rounded-lg flex items-center justify-center">
<FaAward className="w-5 h-5 text-white" />
</div>
<div>
<h3 className="text-xl font-bold text-gray-900">Rozet Ata</h3>
<p className="text-gray-600">
Personele başarı rozeti atayın
</p>
</div>
</div>
<button
onClick={onClose}
className="text-gray-400 hover:text-gray-600 p-1 hover:bg-gray-100 rounded-lg transition-colors"
>
<FaTimesCircle className="w-6 h-6" />
</button>
</div>
{/* Form */}
<form onSubmit={handleSubmit} className="p-3">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{/* Sol Kolon - Personel Seçimi */}
<div className="space-y-4">
<div className="bg-gray-50 p-2 rounded-lg">
<h4 className="text-sm font-semibold text-gray-800 mb-2 flex items-center gap-2">
<FaUsers className="w-5 h-5 text-blue-600" />
Personel Seçimi
</h4>
<div className="space-y-4">
<div>
<select
name="employeeId"
value={formData.employeeId}
onChange={handleInputChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
required
>
<option value="">Personel seçin...</option>
{filteredEmployees.map((employee) => (
<option key={employee.id} value={employee.id}>
{employee.fullName} - {employee.code}
</option>
))}
</select>
</div>
{selectedEmployee && (
<div className="bg-blue-50 p-2 rounded-lg border border-blue-200 text-xs">
<div className="flex items-start justify-between">
<div className="flex-1">
<h4 className="font-medium text-blue-900 mb-1">
{selectedEmployee.fullName}
</h4>
<p className="text-xs text-blue-700 mb-1">
{selectedEmployee.code} {" "}
{selectedEmployee.department?.name}
</p>
<div className="text-xs text-blue-600">
<span className="font-medium">Email:</span>{" "}
{selectedEmployee.email}
</div>
</div>
</div>
</div>
)}
</div>
</div>
</div>
{/* Sağ Kolon - Rozet Seçimi */}
<div className="space-y-4">
<div className="bg-gray-50 p-2 rounded-lg">
<h4 className="text-sm font-semibold text-gray-800 mb-2 flex items-center gap-2">
<FaAward className="w-5 h-5 text-purple-600" />
Rozet Seçimi
</h4>
<div className="space-y-4">
<div>
<select
name="badgeId"
value={formData.badgeId}
onChange={handleInputChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
required
>
<option value="">Rozet seçin...</option>
{filteredBadges.map((badge) => (
<option key={badge.id} value={badge.id}>
{badge.icon} {badge.name} ({badge.points} puan)
</option>
))}
</select>
</div>
{selectedBadge && (
<div className="bg-purple-50 p-2 rounded-lg border border-purple-200 text-xs">
<div className="flex items-start gap-3">
<div
className="w-10 h-10 rounded-full flex items-center justify-center text-lg flex-shrink-0"
style={{
backgroundColor: selectedBadge.backgroundColor,
border: `2px solid ${selectedBadge.color}`,
}}
>
{selectedBadge.icon}
</div>
<div className="flex-1">
<h4 className="font-medium text-purple-900 mb-1">
{selectedBadge.name}
</h4>
<p className="text-xs text-purple-700 mb-1">
{selectedBadge.description}
</p>
<div className="grid grid-cols-2 gap-2 text-xs text-purple-600">
<div>
<span className="font-medium">Puan:</span>{" "}
{selectedBadge.points}
</div>
<div>
<span className="font-medium">Kategori:</span>{" "}
{selectedBadge.category}
</div>
</div>
<div className="mt-2 text-xs text-purple-600">
<span className="font-medium">Kriter:</span>{" "}
{selectedBadge.criteria}
</div>
</div>
</div>
</div>
)}
</div>
</div>
</div>
</div>
{/* Atama Detayları */}
<div className="mt-3 bg-gray-50 p-2 rounded-lg">
<h4 className="text-sm font-semibold text-gray-800 mb-2 flex items-center gap-2">
<FaCalendarAlt className="w-5 h-5 text-green-600" />
Atama Detayları
</h4>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-3">
<div>
<label className="block text-xs font-medium text-gray-700 mb-1">
Kazanılma Tarihi <span className="text-red-500">*</span>
</label>
<input
type="date"
name="earnedDate"
value={formData.earnedDate}
onChange={handleInputChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
required
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-700 mb-1">
Geçerlilik Süresi (Opsiyonel)
</label>
<input
type="date"
name="expiryDate"
value={formData.expiryDate}
onChange={handleInputChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-700 mb-1">
Kazanma Nedeni
</label>
<input
type="text"
name="reason"
value={formData.reason}
onChange={handleInputChange}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder="Örn: Q3 hedeflerini %120 başarıyla tamamladı"
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-700 mb-1">
Notlar
</label>
<textarea
name="notes"
value={formData.notes}
onChange={handleInputChange}
rows={2}
className="w-full px-2 py-1 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder="Ek notlar..."
/>
</div>
</div>
</div>
{/* Footer */}
<div className="flex items-center justify-end gap-2 mt-3 pt-3 border-t border-gray-200">
<button
type="button"
onClick={onClose}
className="px-3 py-1 text-sm text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors flex items-center gap-2"
>
<FaTimesCircle className="w-4 h-4" />
İptal
</button>
<button
type="submit"
className="px-3 py-1 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors flex items-center gap-2 shadow-md hover:shadow-lg"
>
<FaSave className="w-4 h-4" />
Rozet Ata
</button>
</div>
</form>
</div>
</div>
)
);
};
export default BadgeAssignmentModal;