espace-paie-odentas/components/MaintenanceButton.tsx
2025-10-22 11:00:44 +02:00

249 lines
No EOL
7.3 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { AlertTriangle, Power, PowerOff } from "lucide-react";
interface MaintenanceStatus {
is_maintenance_mode: boolean;
maintenance_message: string | null;
scheduled_end_date: string | null;
}
interface MaintenanceButtonProps {
isStaff: boolean;
}
export function MaintenanceButton({ isStaff }: MaintenanceButtonProps) {
const [status, setStatus] = useState<MaintenanceStatus | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [message, setMessage] = useState("");
const [endDate, setEndDate] = useState("");
const [endTime, setEndTime] = useState("");
const [isLoading, setIsLoading] = useState(false);
// Charger le statut au montage
useEffect(() => {
if (isStaff) {
fetchMaintenanceStatus();
}
}, [isStaff]);
const fetchMaintenanceStatus = async () => {
try {
const response = await fetch("/api/maintenance");
if (response.ok) {
const data = await response.json();
setStatus(data);
} else {
// Fallback par défaut si l'API n'existe pas encore
setStatus({
is_maintenance_mode: false,
maintenance_message: null,
scheduled_end_date: null
});
}
} catch (error) {
console.error("Failed to fetch maintenance status:", error);
// Fallback par défaut en cas d'erreur
setStatus({
is_maintenance_mode: false,
maintenance_message: null,
scheduled_end_date: null
});
}
};
const handleActivateMaintenance = () => {
// Réinitialiser les valeurs du modal
setMessage("L'Espace Paie est temporairement indisponible pour maintenance.");
// Date par défaut : dans 2 heures
const defaultEnd = new Date();
defaultEnd.setHours(defaultEnd.getHours() + 2);
setEndDate(defaultEnd.toISOString().split('T')[0]);
setEndTime(defaultEnd.toTimeString().slice(0, 5));
setIsModalOpen(true);
};
const handleDeactivateMaintenance = async () => {
setIsLoading(true);
try {
const response = await fetch("/api/maintenance", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
is_maintenance_mode: false,
maintenance_message: null,
scheduled_end_date: null
})
});
if (response.ok) {
const newStatus = await response.json();
setStatus(newStatus);
} else {
alert("Erreur lors de la désactivation de la maintenance");
}
} catch (error) {
console.error("Error deactivating maintenance:", error);
alert("Erreur lors de la désactivation de la maintenance");
} finally {
setIsLoading(false);
}
};
const handleConfirmMaintenance = async () => {
if (!message.trim()) {
alert("Veuillez saisir un message de maintenance");
return;
}
if (!endDate || !endTime) {
alert("Veuillez sélectionner une date et heure de fin");
return;
}
setIsLoading(true);
try {
const scheduledEndDate = new Date(`${endDate}T${endTime}:00`).toISOString();
const response = await fetch("/api/maintenance", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
is_maintenance_mode: true,
maintenance_message: message,
scheduled_end_date: scheduledEndDate
})
});
if (response.ok) {
const newStatus = await response.json();
setStatus(newStatus);
setIsModalOpen(false);
} else {
alert("Erreur lors de l'activation de la maintenance");
}
} catch (error) {
console.error("Error activating maintenance:", error);
alert("Erreur lors de l'activation de la maintenance");
} finally {
setIsLoading(false);
}
};
// Ne pas afficher le composant si ce n'est pas un staff
if (!isStaff) {
return null;
}
// Afficher un placeholder pendant le chargement
if (!status) {
return (
<Button
disabled
variant="outline"
size="sm"
className="flex items-center gap-2 text-gray-400 border-gray-200"
>
<PowerOff size={16} />
Chargement...
</Button>
);
}
return (
<>
{status.is_maintenance_mode ? (
<Button
onClick={handleDeactivateMaintenance}
disabled={isLoading}
variant="outline"
size="sm"
className="flex items-center gap-2 text-green-600 border-green-200 hover:bg-green-50"
>
<Power size={16} />
Réactiver l'Espace Paie
</Button>
) : (
<Button
onClick={handleActivateMaintenance}
disabled={isLoading}
variant="outline"
size="sm"
className="flex items-center gap-2 text-orange-600 border-orange-200 hover:bg-orange-50"
>
<PowerOff size={16} />
Fermer l'Espace Paie
</Button>
)}
<Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<AlertTriangle className="text-orange-500" size={20} />
Fermer l'Espace Paie
</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div>
<Label htmlFor="message">Message de maintenance</Label>
<Textarea
id="message"
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Message affiché aux utilisateurs..."
rows={3}
className="mt-1"
/>
</div>
<div className="grid grid-cols-2 gap-3">
<div>
<Label htmlFor="endDate">Date de fin prévue</Label>
<Input
id="endDate"
type="date"
value={endDate}
onChange={(e) => setEndDate(e.target.value)}
className="mt-1"
/>
</div>
<div>
<Label htmlFor="endTime">Heure de fin</Label>
<Input
id="endTime"
type="time"
value={endTime}
onChange={(e) => setEndTime(e.target.value)}
className="mt-1"
/>
</div>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => setIsModalOpen(false)}>
Annuler
</Button>
<Button
onClick={handleConfirmMaintenance}
disabled={isLoading}
className="bg-orange-600 hover:bg-orange-700"
>
{isLoading ? "Activation..." : "Activer la maintenance"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
}