erp-platform/ui/src/views/hr/components/BadgeEditModal.tsx
2025-09-15 12:31:47 +03:00

426 lines
17 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 {
FaPlus,
FaEdit,
FaSave,
FaTimesCircle,
FaAward,
FaPalette,
FaInfoCircle,
} from "react-icons/fa";
import { HrBadge, BadgeCategoryEnum, BadgeRarityEnum } from "../../../types/hr";
import { iconOptions } from "../../../utils/erp";
interface BadgeEditModalProps {
isOpen: boolean;
onClose: () => void;
badge?: HrBadge | null;
onSubmit: (badgeData: HrBadge) => void;
mode: "create" | "edit";
}
const BadgeEditModal: React.FC<BadgeEditModalProps> = ({
isOpen,
onClose,
badge,
onSubmit,
mode,
}) => {
const [formData, setFormData] = useState<HrBadge>({
id: "",
code: "",
name: "",
description: "",
icon: "⭐",
color: "#FFD700",
backgroundColor: "#FFF8DC",
category: BadgeCategoryEnum.Performance,
criteria: "",
points: 10,
rarity: BadgeRarityEnum.Common,
isActive: true,
creationTime: new Date(),
lastModificationTime: new Date(),
});
const generateBadgeCode = () => {
const timestamp = Date.now().toString().slice(-6);
return `BADGE-${timestamp}`;
};
useEffect(() => {
if (mode === "edit" && badge) {
setFormData({
id: badge.id,
code: badge.code,
name: badge.name,
description: badge.description,
icon: badge.icon,
color: badge.color,
backgroundColor: badge.backgroundColor,
category: badge.category,
criteria: badge.criteria,
points: badge.points,
rarity: badge.rarity,
isActive: badge.isActive,
creationTime: badge.creationTime,
lastModificationTime: badge.lastModificationTime,
});
} else {
// Reset form for create mode
setFormData({
id: "",
code: generateBadgeCode(),
name: "",
description: "",
icon: "⭐",
color: "#FFD700",
backgroundColor: "#FFF8DC",
category: BadgeCategoryEnum.Performance,
criteria: "",
points: 10,
rarity: BadgeRarityEnum.Common,
isActive: true,
creationTime: new Date(),
lastModificationTime: new Date(),
});
}
}, [mode, badge, isOpen]);
const handleInputChange = (
e: React.ChangeEvent<
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
>
) => {
const { name, value, type } = e.target;
if (type === "checkbox") {
const checked = (e.target as HTMLInputElement).checked;
setFormData((prev) => ({
...prev,
[name]: checked,
}));
} else if (name === "points") {
setFormData((prev) => ({
...prev,
[name]: parseInt(value) || 0,
}));
} else {
setFormData((prev) => ({
...prev,
[name]: value,
}));
}
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSubmit(formData);
onClose();
};
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-4 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-t-xl">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-blue-600 rounded-lg flex items-center justify-center">
{mode === "edit" ? (
<FaEdit className="w-5 h-5 text-white" />
) : (
<FaPlus className="w-5 h-5 text-white" />
)}
</div>
<div className="text-sm">
<h3 className="text-xl font-bold text-gray-900">
{mode === "edit" ? "Rozet Düzenle" : "Yeni Rozet Oluştur"}
</h3>
<p className="text-sm text-gray-600">
{mode === "edit"
? "Mevcut rozet bilgilerini güncelleyin"
: "Yeni bir başarı rozeti tanımlayı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-4">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{/* Sol Kolon */}
<div className="space-y-4">
<div className="bg-gray-50 p-3 rounded-lg">
<h4 className="text-base font-semibold text-gray-800 mb-3 flex items-center gap-2">
<FaAward className="w-5 h-5 text-blue-600" />
Temel Bilgiler
</h4>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Rozet Kodu <span className="text-red-500">*</span>
</label>
<input
type="text"
name="code"
value={formData.code}
onChange={handleInputChange}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder="Rozet kodunu girin..."
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Rozet Adı <span className="text-red-500">*</span>
</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleInputChange}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder="Rozet adını girin..."
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
ıklama
</label>
<textarea
name="description"
value={formData.description}
onChange={handleInputChange}
rows={1}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder="Rozet açıklaması..."
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Kazanma Kriteri <span className="text-red-500">*</span>
</label>
<textarea
name="criteria"
value={formData.criteria}
onChange={handleInputChange}
rows={2}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder="Bu rozeti kazanmak için gerekli şartlar..."
required
/>
</div>
</div>
</div>
</div>
{/* Sağ Kolon */}
<div className="space-y-4">
<div className="bg-gray-50 p-3 rounded-lg">
<h4 className="text-base font-semibold text-gray-800 mb-3 flex items-center gap-2">
<FaPalette className="w-5 h-5 text-purple-600" />
Görsel ve Özellikler
</h4>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
İkon
</label>
<select
name="icon"
value={formData.icon}
onChange={handleInputChange}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
>
{iconOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.value} {option.label}
</option>
))}
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Renk
</label>
<input
type="color"
name="color"
value={formData.color}
onChange={handleInputChange}
className="w-full h-9 border border-gray-300 rounded-lg cursor-pointer"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Arka Plan Rengi
</label>
<input
type="color"
name="backgroundColor"
value={formData.backgroundColor}
onChange={handleInputChange}
className="w-full h-9 border border-gray-300 rounded-lg cursor-pointer"
/>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Kategori
</label>
<select
name="category"
value={formData.category}
onChange={handleInputChange}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
>
{Object.values(BadgeCategoryEnum).map((category) => (
<option key={category} value={category}>
{category === BadgeCategoryEnum.Performance &&
"Performans"}
{category === BadgeCategoryEnum.Leadership &&
"Liderlik"}
{category === BadgeCategoryEnum.Innovation &&
"İnovasyon"}
{category === BadgeCategoryEnum.Teamwork &&
"Takım Çalışması"}
{category === BadgeCategoryEnum.Customer &&
"Müşteri"}
{category === BadgeCategoryEnum.Safety &&
"Güvenlik"}
{category === BadgeCategoryEnum.Attendance &&
"Devam"}
{category === BadgeCategoryEnum.Training &&
"Eğitim"}
{category === BadgeCategoryEnum.Project && "Proje"}
{category === BadgeCategoryEnum.Special && "Özel"}
</option>
))}
</select>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Puan
</label>
<input
type="number"
name="points"
value={formData.points}
onChange={handleInputChange}
min="1"
max="1000"
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder="10"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Nadirlık
</label>
<select
name="rarity"
value={formData.rarity}
onChange={handleInputChange}
className="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
>
{Object.values(BadgeRarityEnum).map((rarity) => (
<option key={rarity} value={rarity}>
{rarity === BadgeRarityEnum.Common && "Yaygın"}
{rarity === BadgeRarityEnum.Uncommon && "Nadir"}
{rarity === BadgeRarityEnum.Rare && "Çok Nadir"}
{rarity === BadgeRarityEnum.Epic && "Efsanevi"}
{rarity === BadgeRarityEnum.Legendary && "Efsane"}
</option>
))}
</select>
</div>
</div>
<div className="flex items-center">
<input
type="checkbox"
name="isActive"
checked={formData.isActive}
onChange={handleInputChange}
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<label className="ml-2 block text-sm text-gray-900">
Aktif
</label>
</div>
</div>
</div>
{/* Preview */}
<div className="bg-gray-50 p-3 rounded-lg">
<h4 className="text-base font-semibold text-gray-800 mb-3 flex items-center gap-2">
<FaInfoCircle className="w-5 h-5 text-green-600" />
Önizleme
</h4>
<div className="flex items-center gap-3 p-3 bg-white rounded-lg border">
<div
className="w-12 h-12 rounded-full flex items-center justify-center text-xl"
style={{
backgroundColor: formData.backgroundColor,
border: `2px solid ${formData.color}`,
}}
>
{formData.icon}
</div>
<div>
<div className="font-medium text-gray-900">
{formData.name || "Rozet Adı"}
</div>
<div className="text-sm text-gray-500">
{formData.points} puan {formData.category}
</div>
</div>
</div>
</div>
</div>
</div>
{/* Footer */}
<div className="flex items-center justify-end gap-3 mt-4 pt-4 border-t border-gray-200">
<button
type="button"
onClick={onClose}
className="px-3 py-1.5 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.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2 shadow-md hover:shadow-lg"
>
<FaSave className="w-4 h-4" />
{mode === "edit" ? "Güncelle" : "Oluştur"}
</button>
</div>
</form>
</div>
</div>
)
);
};
export default BadgeEditModal;