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

296 lines
11 KiB
TypeScript
Raw Normal View History

2025-09-15 09:31:47 +00:00
import React, { useState, useEffect } from "react";
import {
FaTimes,
FaSave,
FaExclamationTriangle,
FaCheckCircle,
FaTimesCircle,
} from "react-icons/fa";
import { Team } from "../../../types/common";
interface TeamStatusChangeModalProps {
isOpen: boolean;
onClose: () => void;
onSave: (teamIds: string[], newStatus: boolean, reason?: string) => void;
selectedTeams: Team[];
}
const TeamStatusChangeModal: React.FC<TeamStatusChangeModalProps> = ({
isOpen,
onClose,
onSave,
selectedTeams,
}) => {
const [newStatus, setNewStatus] = useState<boolean>(true);
const [reason, setReason] = useState("");
const [errors, setErrors] = useState<Record<string, string>>({});
const activeTeams = selectedTeams.filter((team) => team.isActive);
const inactiveTeams = selectedTeams.filter((team) => !team.isActive);
useEffect(() => {
if (isOpen) {
// Reset form when modal opens
setNewStatus(true);
setReason("");
setErrors({});
}
}, [isOpen]);
const validateForm = () => {
const newErrors: Record<string, string> = {};
if (!newStatus && !reason.trim()) {
newErrors.reason = "Ekipleri pasif yaparken sebep belirtmeniz gerekli";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSave = () => {
if (validateForm()) {
const teamIds = selectedTeams.map((team) => team.id);
onSave(teamIds, newStatus, reason.trim() || undefined);
onClose();
}
};
const getImpactAnalysis = () => {
const teamsToActivate = newStatus ? inactiveTeams : [];
const teamsToDeactivate = newStatus ? [] : activeTeams;
return {
teamsToActivate,
teamsToDeactivate,
totalMembers: selectedTeams.reduce(
(total, team) => total + team.members.filter((m) => m.isActive).length,
0
),
activeMembers: activeTeams.reduce(
(total, team) => total + team.members.filter((m) => m.isActive).length,
0
),
};
};
const impact = getImpactAnalysis();
return (
isOpen && (
<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-lg mx-4 max-h-[90vh] overflow-y-auto">
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-gray-200">
<div>
<h2 className="text-xl font-bold text-gray-900">
Ekip Durumu Değiştir
</h2>
<p className="text-sm text-gray-600">
{selectedTeams.length} ekibin durumunu değiştirin
</p>
</div>
<button
onClick={onClose}
className="p-2 text-gray-400 hover:text-gray-600 transition-colors"
>
<FaTimes className="w-4 h-4" />
</button>
</div>
{/* Content */}
<div className="p-3 space-y-3">
{/* Status Selection */}
<div>
<h3 className="text-sm font-medium text-gray-900 mb-2">
Yeni Durum
</h3>
<div className="space-y-3">
<label className="flex items-center p-2 border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer">
<input
type="radio"
checked={newStatus === true}
onChange={() => setNewStatus(true)}
className="text-green-600 focus:ring-green-500"
/>
<FaCheckCircle className="w-5 h-5 text-green-600 ml-3 mr-2" />
<div>
<span className="font-medium text-gray-900">Aktif</span>
<p className="text-xs text-gray-600">
Ekipler aktif hale gelir ve emirleri alabilir
</p>
</div>
</label>
<label className="flex items-center p-2 border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer">
<input
type="radio"
checked={newStatus === false}
onChange={() => setNewStatus(false)}
className="text-red-600 focus:ring-red-500"
/>
<FaTimesCircle className="w-5 h-5 text-red-600 ml-3 mr-2" />
<div>
<span className="font-medium text-gray-900">Pasif</span>
<p className="text-xs text-gray-600">
Ekipler pasif hale gelir ve yeni emirleri alamaz
</p>
</div>
</label>
</div>
</div>
{/* Reason (required for deactivation) */}
{!newStatus && (
<div>
<label className="block text-xs font-medium text-gray-700 mb-1">
Pasif Yapma Sebebi *
</label>
<textarea
value={reason}
onChange={(e) => {
setReason(e.target.value);
if (errors.reason) {
setErrors((prev) => ({ ...prev, reason: "" }));
}
}}
rows={2}
className={`w-full px-3 py-1.5 text-sm border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${
errors.reason ? "border-red-500" : "border-gray-300"
}`}
placeholder="Ekiplerin neden pasif yapıldığınııklayın..."
/>
{errors.reason && (
<p className="text-red-500 text-xs mt-1">{errors.reason}</p>
)}
</div>
)}
{/* Impact Analysis */}
<div className="bg-gray-50 rounded-lg p-3">
<h3 className="text-sm font-medium text-gray-900 mb-3">
Etki Analizi
</h3>
<div className="grid grid-cols-2 gap-3 mb-3">
<div className="text-center">
<div className="text-base font-bold text-blue-600">
{selectedTeams.length}
</div>
<div className="text-sm text-gray-600">
Toplam Seçili Ekip
</div>
</div>
<div className="text-center">
<div className="text-base font-bold text-green-600">
{impact.totalMembers}
</div>
<div className="text-sm text-gray-600">Toplam Üye Sayısı</div>
</div>
</div>
{!newStatus && impact.teamsToDeactivate.length > 0 && (
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-2">
<div className="flex items-start space-x-3">
<FaExclamationTriangle className="w-5 h-5 text-yellow-600 mt-0.5" />
<div>
<h4 className="text-sm font-medium text-yellow-800">
Uyarı
</h4>
<p className="text-sm text-yellow-700 mt-1">
{impact.teamsToDeactivate.length} aktif ekip pasif
yapılacak. Bu ekipler artık yeni emirleri alamayacak.
</p>
</div>
</div>
</div>
)}
{newStatus && impact.teamsToActivate.length > 0 && (
<div className="bg-green-50 border border-green-200 rounded-lg p-2">
<div className="flex items-start space-x-3">
<FaCheckCircle className="w-5 h-5 text-green-600 mt-0.5" />
<div>
<h4 className="text-sm font-medium text-green-800">
Bilgi
</h4>
<p className="text-sm text-green-700 mt-1">
{impact.teamsToActivate.length} pasif ekip aktif hale
gelecek. Bu ekipler tekrar emirleri alabilecek.
</p>
</div>
</div>
</div>
)}
</div>
{/* Selected Teams List */}
<div>
<h3 className="text-sm font-medium text-gray-900 mb-2">
Etkilenecek Ekipler
</h3>
<div className="max-h-32 overflow-y-auto border border-gray-200 rounded-lg">
{selectedTeams.map((team) => (
<div
key={team.id}
className="flex items-center justify-between p-2 border-b border-gray-100 last:border-b-0"
>
<div>
<h4 className="font-medium text-sm text-gray-900">
{team.name}
</h4>
<p className="text-sm text-gray-600">{team.code}</p>
</div>
<div className="flex items-center space-x-2">
<span
className={`px-2 py-1 text-xs font-semibold rounded-full ${
team.isActive
? "bg-green-100 text-green-800"
: "bg-gray-100 text-gray-800"
}`}
>
{team.isActive ? "Aktif" : "Pasif"}
</span>
<span className="text-sm text-gray-500"></span>
<span
className={`px-2 py-1 text-xs font-semibold rounded-full ${
newStatus
? "bg-green-100 text-green-800"
: "bg-gray-100 text-gray-800"
}`}
>
{newStatus ? "Aktif" : "Pasif"}
</span>
</div>
</div>
))}
</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.5 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.5 text-sm text-white rounded-lg transition-colors flex items-center space-x-2 ${
newStatus
? "bg-green-600 hover:bg-green-700"
: "bg-red-600 hover:bg-red-700"
}`}
>
<FaSave className="w-4 h-4" />
<span>Durumu Değiştir</span>
</button>
</div>
</div>
</div>
)
);
};
export default TeamStatusChangeModal;