diff --git a/components/missions/missions-admin-panel.tsx b/components/missions/missions-admin-panel.tsx index b4faac91..8287a3ee 100644 --- a/components/missions/missions-admin-panel.tsx +++ b/components/missions/missions-admin-panel.tsx @@ -17,7 +17,7 @@ import { CardContent } from "../ui/card"; import { Badge } from "../ui/badge"; -import { X, Search, UserPlus, Users, PlusCircle, AlertCircle, Check } from "lucide-react"; +import { X, Search, UserPlus, Users, PlusCircle, AlertCircle, Check, Loader2 } from "lucide-react"; import { toast } from "../ui/use-toast"; import { DropdownMenu, @@ -73,11 +73,25 @@ export function MissionsAdminPanel() { participation?: string; profils?: string[]; }>({}); + + // Form progression state + const [activeSection, setActiveSection] = useState("general"); + const [completedSections, setCompletedSections] = useState>(new Set()); + const [formValues, setFormValues] = useState({ + name: "", + oddScope: "", + niveau: "", + intention: "", + missionType: "", + donneurDOrdre: "", + projection: "", + }); // State for storing fetched data const [users, setUsers] = useState([]); const [groups, setGroups] = useState([]); const [loading, setLoading] = useState(true); + const [isSubmitting, setIsSubmitting] = useState(false); // Check if mission is valid (has all required guardiens) const isMissionValid = gardienDuTemps !== null && gardienDeLaParole !== null && gardienDeLaMemoire !== null; @@ -242,7 +256,7 @@ export function MissionsAdminPanel() { } }; - // Check if all guardian roles are filled + // Check if all necessary guardiens roles are filled const areAllGuardiensFilled = (): boolean => { return gardienDuTemps !== null && gardienDeLaParole !== null && gardienDeLaMemoire !== null; }; @@ -285,24 +299,270 @@ export function MissionsAdminPanel() { } }; + // Handle form input changes + const handleInputChange = (field: string, value: string) => { + setFormValues({ + ...formValues, + [field]: value + }); + + // Update mission data + setMissionData(prev => ({ + ...prev, + [field]: value + })); + }; + + // Validate General section + const validateGeneralSection = (): boolean => { + const requiredFields = ['name', 'oddScope', 'niveau', 'intention']; + const missingFields = requiredFields.filter(field => !formValues[field as keyof typeof formValues]); + + if (missingFields.length > 0) { + toast({ + title: "Champs obligatoires manquants", + description: "Veuillez remplir tous les champs obligatoires avant de continuer.", + variant: "destructive", + }); + return false; + } + + return true; + }; + + // Validate Details section + const validateDetailsSection = (): boolean => { + const requiredFields = ['missionType', 'donneurDOrdre', 'projection']; + const missingFields = requiredFields.filter(field => !formValues[field as keyof typeof formValues]); + + if (missingFields.length > 0) { + toast({ + title: "Champs obligatoires manquants", + description: "Veuillez remplir tous les champs obligatoires avant de continuer.", + variant: "destructive", + }); + return false; + } + + return true; + }; + + // Validate Skills section + const validateSkillsSection = (): boolean => { + if (selectedProfils.length === 0) { + toast({ + title: "Sélection requise", + description: "Veuillez sélectionner au moins un profil de compétence.", + variant: "destructive", + }); + return false; + } + + return true; + }; + + // Validate Membres section + const validateMembresSection = (): boolean => { + if (!areAllGuardiensFilled()) { + toast({ + title: "Gardiens manquants", + description: "Vous devez assigner les trois gardiens avant de finaliser la mission.", + variant: "destructive", + }); + return false; + } + + return true; + }; + + // Proceed to next section + const goToNextSection = (currentSection: string) => { + let isValid = false; + let nextSection = ""; + + switch (currentSection) { + case "general": + isValid = validateGeneralSection(); + nextSection = "details"; + break; + case "details": + isValid = validateDetailsSection(); + nextSection = "attachments"; + break; + case "attachments": + // Attachments are optional + isValid = true; + nextSection = "skills"; + break; + case "skills": + isValid = validateSkillsSection(); + nextSection = "membres"; + break; + case "membres": + isValid = validateMembresSection(); + if (isValid) { + // Ready to submit the form + createMission(); + } + return; + default: + return; + } + + if (isValid) { + setCompletedSections(prev => new Set([...prev, currentSection])); + setActiveSection(nextSection); + } + }; + + // Skip optional section + const skipSection = (currentSection: string) => { + if (currentSection === "attachments") { + setCompletedSections(prev => new Set([...prev, currentSection])); + setActiveSection("skills"); + } + }; + + // Add createMission function to handle form submission + const createMission = async () => { + if (!isMissionValid) { + toast({ + title: "Mission incomplète", + description: "Vous devez assigner les trois gardiens avant de pouvoir enregistrer.", + variant: "destructive", + }); + return; + } + + try { + setIsSubmitting(true); + + // Prepare mission data + const missionPayload = { + ...missionData, + name: formValues.name, + oddScope: formValues.oddScope, + niveau: formValues.niveau, + intention: formValues.intention, + missionType: formValues.missionType, + donneurDOrdre: formValues.donneurDOrdre, + projection: formValues.projection, + services: selectedServices, + profils: selectedProfils, + users: [ + { userId: gardienDuTemps as string, role: 'temps' }, + { userId: gardienDeLaParole as string, role: 'parole' }, + { userId: gardienDeLaMemoire as string, role: 'memoire' }, + ...volontaires.map(userId => ({ userId, role: 'volontaire' })) + ] + }; + + // Create the mission + const response = await fetch('/api/missions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(missionPayload), + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to create mission'); + } + + const result = await response.json(); + + toast({ + title: "Mission créée avec succès", + description: "La mission a été enregistrée.", + }); + + // Redirect to the mission page + window.location.href = `/missions/${result.id}`; + + } catch (error) { + console.error('Error creating mission:', error); + toast({ + title: "Erreur", + description: error instanceof Error ? error.message : "Une erreur s'est produite lors de la création de la mission", + variant: "destructive", + }); + } finally { + setIsSubmitting(false); + } + }; + return (
- + { + // Only allow navigation to completed sections or current section + if (completedSections.has(value) || value === activeSection) { + setActiveSection(value); + } else { + toast({ + title: "Section verrouillée", + description: "Veuillez compléter la section actuelle d'abord.", + variant: "destructive", + }); + } + }} className="w-full"> - General - Details - Attachments - Skills - Membres + + General + + + Details + + + Attachments + + + Skills + + + Membres +
- + handleInputChange('name', e.target.value)} + required + />
@@ -325,7 +585,10 @@ export function MissionsAdminPanel() {
- handleInputChange('oddScope', value)} + > @@ -353,7 +616,10 @@ export function MissionsAdminPanel() {
- handleInputChange('niveau', value)} + > @@ -380,10 +646,27 @@ export function MissionsAdminPanel() {
-