missions button

This commit is contained in:
alma 2025-05-06 08:48:19 +02:00
parent 36160df93c
commit 5f84229fb0

View File

@ -27,6 +27,7 @@ import {
} from "../ui/dropdown-menu";
import { FileUpload } from "./file-upload";
import { AttachmentsList } from "./attachments-list";
import { useRouter } from "next/navigation";
// Define interfaces for user and group data
interface User {
@ -51,6 +52,7 @@ type GuardienRole = 'temps' | 'parole' | 'memoire';
type UserRole = GuardienRole | 'volontaire';
export function MissionsAdminPanel() {
const router = useRouter();
const [selectedServices, setSelectedServices] = useState<string[]>([]);
const [selectedProfils, setSelectedProfils] = useState<string[]>([]);
const [searchTerm, setSearchTerm] = useState("");
@ -61,6 +63,7 @@ export function MissionsAdminPanel() {
const [volontaires, setVolontaires] = useState<string[]>([]);
const [missionId, setMissionId] = useState<string>("");
const [activeTab, setActiveTab] = useState<string>("general");
const [isSubmitting, setIsSubmitting] = useState(false);
const [missionData, setMissionData] = useState<{
name?: string;
logo?: string;
@ -316,6 +319,105 @@ export function MissionsAdminPanel() {
return activeTab === "general";
};
// Validate all required fields
const validateMission = () => {
const requiredFields = {
name: !!missionData.name,
oddScope: Array.isArray(missionData.oddScope) && missionData.oddScope.length > 0,
niveau: !!missionData.niveau,
intention: !!missionData.intention,
missionType: !!missionData.missionType,
donneurDOrdre: !!missionData.donneurDOrdre,
projection: !!missionData.projection,
participation: !!missionData.participation,
gardiens: gardienDuTemps !== null && gardienDeLaParole !== null && gardienDeLaMemoire !== null
};
const isValid = Object.values(requiredFields).every(field => field === true);
if (!isValid) {
const missingFields = Object.entries(requiredFields)
.filter(([_, value]) => value === false)
.map(([key, _]) => key);
toast({
title: "Champs obligatoires manquants",
description: `Veuillez remplir tous les champs obligatoires: ${missingFields.join(", ")}`,
variant: "destructive",
});
}
return isValid;
};
// Handle mission submission
const handleSubmitMission = async () => {
if (!validateMission()) {
return;
}
setIsSubmitting(true);
try {
// Prepare the mission data
const guardians = {
"gardien-temps": gardienDuTemps,
"gardien-parole": gardienDeLaParole,
"gardien-memoire": gardienDeLaMemoire
};
const missionSubmitData = {
...missionData,
services: selectedServices,
profils: selectedProfils,
guardians,
volunteers: volontaires
};
// Send to API
const response = await fetch('/api/missions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(missionSubmitData),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Failed to create mission');
}
const data = await response.json();
toast({
title: "Mission créée avec succès",
description: "Tous les gardiens ont été assignés et la mission a été enregistrée.",
});
// Redirect to missions list
router.push('/missions');
} catch (error) {
console.error('Error creating mission:', error);
toast({
title: "Erreur",
description: error instanceof Error ? error.message : "Une erreur est survenue lors de la création de la mission",
variant: "destructive",
});
} finally {
setIsSubmitting(false);
}
};
// Function to handle input changes
const handleInputChange = (field: string, value: any) => {
setMissionData(prev => ({
...prev,
[field]: value
}));
};
return (
<div className="w-full">
<Card className="border shadow-sm bg-white">
@ -332,8 +434,13 @@ export function MissionsAdminPanel() {
<TabsContent value="general" className="space-y-6">
<div className="space-y-4">
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">Nom de la Mission</label>
<Input placeholder="Nom de la mission" className="bg-white border-gray-300" />
<label className="block text-sm font-medium mb-1 text-gray-700">Nom de la Mission<span className="text-red-500">*</span></label>
<Input
placeholder="Nom de la mission"
className="bg-white border-gray-300"
value={missionData.name || ''}
onChange={(e) => handleInputChange('name', e.target.value)}
/>
</div>
<div>
@ -355,8 +462,8 @@ export function MissionsAdminPanel() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">ODD scope</label>
<Select>
<label className="block text-sm font-medium mb-1 text-gray-700">ODD scope<span className="text-red-500">*</span></label>
<Select onValueChange={(value) => handleInputChange('oddScope', [value])}>
<SelectTrigger className="bg-white border-gray-300">
<SelectValue placeholder="Choisir le scope" />
</SelectTrigger>
@ -383,8 +490,8 @@ export function MissionsAdminPanel() {
</div>
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">Niveau</label>
<Select>
<label className="block text-sm font-medium mb-1 text-gray-700">Niveau<span className="text-red-500">*</span></label>
<Select onValueChange={(value) => handleInputChange('niveau', value)}>
<SelectTrigger className="bg-white border-gray-300">
<SelectValue placeholder="Choisir un niveau" />
</SelectTrigger>
@ -399,7 +506,7 @@ export function MissionsAdminPanel() {
</div>
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">Intention</label>
<label className="block text-sm font-medium mb-1 text-gray-700">Intention<span className="text-red-500">*</span></label>
<div className="border rounded-md border-gray-300">
<div className="bg-gray-50 p-2 border-b flex items-center space-x-2">
<span className="text-gray-700">Paragraphe</span>
@ -411,7 +518,11 @@ export function MissionsAdminPanel() {
<Button variant="ghost" size="icon" className="h-8 w-8 text-gray-700">"</Button>
</div>
</div>
<Textarea className="min-h-[200px] border-0 bg-white" />
<Textarea
className="min-h-[200px] border-0 bg-white"
value={missionData.intention || ''}
onChange={(e) => handleInputChange('intention', e.target.value)}
/>
</div>
</div>
</div>
@ -421,8 +532,8 @@ export function MissionsAdminPanel() {
<div className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">Type de mission</label>
<Select>
<label className="block text-sm font-medium mb-1 text-gray-700">Type de mission<span className="text-red-500">*</span></label>
<Select onValueChange={(value) => handleInputChange('missionType', value)}>
<SelectTrigger className="bg-white border-gray-300">
<SelectValue placeholder="Type de location" />
</SelectTrigger>
@ -435,8 +546,8 @@ export function MissionsAdminPanel() {
</div>
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">Donneur d'ordre</label>
<Select>
<label className="block text-sm font-medium mb-1 text-gray-700">Donneur d'ordre<span className="text-red-500">*</span></label>
<Select onValueChange={(value) => handleInputChange('donneurDOrdre', value)}>
<SelectTrigger className="bg-white border-gray-300">
<SelectValue placeholder="Sélectionner" />
</SelectTrigger>
@ -451,8 +562,8 @@ export function MissionsAdminPanel() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">Projection</label>
<Select>
<label className="block text-sm font-medium mb-1 text-gray-700">Projection<span className="text-red-500">*</span></label>
<Select onValueChange={(value) => handleInputChange('projection', value)}>
<SelectTrigger className="bg-white border-gray-300">
<SelectValue placeholder="Select duration" />
</SelectTrigger>
@ -532,8 +643,8 @@ export function MissionsAdminPanel() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1 text-gray-700">Participation</label>
<Select>
<label className="block text-sm font-medium mb-1 text-gray-700">Participation<span className="text-red-500">*</span></label>
<Select onValueChange={(value) => handleInputChange('participation', value)}>
<SelectTrigger className="bg-white border-gray-300">
<SelectValue placeholder="Select participation" />
</SelectTrigger>
@ -1165,6 +1276,7 @@ export function MissionsAdminPanel() {
variant="outline"
className="text-gray-700 bg-white hover:bg-gray-50 border border-gray-300"
onClick={goToPreviousTab}
disabled={isSubmitting}
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-2">
<polyline points="19 12 5 12"></polyline>
@ -1177,30 +1289,28 @@ export function MissionsAdminPanel() {
<Button
className="bg-blue-600 hover:bg-blue-700 text-white"
onClick={() => {
if (isLastTab() && isMissionValid) {
// Submit the form on the last tab if valid
toast({
title: "Mission enregistrée",
description: "Tous les gardiens ont été assignés avec succès.",
});
} else if (isLastTab() && !isMissionValid) {
// Show validation error on last tab
toast({
title: "Mission incomplète",
description: "Vous devez assigner les trois gardiens avant de pouvoir enregistrer.",
variant: "destructive",
});
if (isLastTab()) {
handleSubmitMission();
} else {
// Go to next tab
goToNextTab();
}
}}
disabled={isSubmitting}
>
{isLastTab() ? "Enregistrer" : "Suivant"}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="ml-2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
{isSubmitting ? (
<>
<span className="animate-spin mr-2"></span>
{isLastTab() ? "Enregistrement..." : "Chargement..."}
</>
) : (
<>
{isLastTab() ? "Enregistrer" : "Suivant"}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="ml-2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</>
)}
</Button>
</div>
</CardContent>