diff --git a/components/missions/missions-admin-panel.bak.tsx b/components/missions/missions-admin-panel.bak.tsx new file mode 100644 index 00000000..3ead1381 --- /dev/null +++ b/components/missions/missions-admin-panel.bak.tsx @@ -0,0 +1,1338 @@ +"use client"; + +import React, { useState, useEffect } from "react"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger +} from "../ui/tabs"; +import { Input } from "../ui/input"; +import { Button } from "../ui/button"; +import { Textarea } from "../ui/textarea"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"; +import { Checkbox } from "../ui/checkbox"; +import { + Card, + CardContent +} from "../ui/card"; +import { Badge } from "../ui/badge"; +import { X, Search, UserPlus, Users, PlusCircle, AlertCircle, Check } from "lucide-react"; +import { toast } from "../ui/use-toast"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger +} 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 { + id: string; + username: string; + firstName: string; + lastName: string; + email: string; + roles?: string[]; + enabled?: boolean; +} + +interface Group { + id: string; + name: string; + path: string; + membersCount: number; +} + +// User role types in mission +type GuardienRole = 'temps' | 'parole' | 'memoire'; +type UserRole = GuardienRole | 'volontaire'; + +export function MissionsAdminPanel() { + const router = useRouter(); + const [selectedServices, setSelectedServices] = useState([]); + const [selectedProfils, setSelectedProfils] = useState([]); + const [searchTerm, setSearchTerm] = useState(""); + const [selectedTab, setSelectedTab] = useState<'users' | 'groups'>('users'); + const [gardienDuTemps, setGardienDuTemps] = useState(null); + const [gardienDeLaParole, setGardienDeLaParole] = useState(null); + const [gardienDeLaMemoire, setGardienDeLaMemoire] = useState(null); + const [volontaires, setVolontaires] = useState([]); + const [missionId, setMissionId] = useState(""); + const [activeTab, setActiveTab] = useState("general"); + const [isSubmitting, setIsSubmitting] = useState(false); + const [missionData, setMissionData] = useState<{ + name?: string; + logo?: string; + oddScope?: string[]; + niveau?: string; + intention?: string; + missionType?: string; + donneurDOrdre?: string; + projection?: string; + services?: string[]; + participation?: string; + profils?: string[]; + }>({}); + + // State for storing fetched data + const [users, setUsers] = useState([]); + const [groups, setGroups] = useState([]); + const [loading, setLoading] = useState(true); + + // Check if mission is valid (has all required guardiens) + const isMissionValid = gardienDuTemps !== null && gardienDeLaParole !== null && gardienDeLaMemoire !== null; + + // Fetch users and groups on component mount + useEffect(() => { + const fetchData = async () => { + setLoading(true); + try { + await Promise.all([fetchUsers(), fetchGroups()]); + } catch (error) { + console.error("Error fetching data:", error); + } finally { + setLoading(false); + } + }; + + fetchData(); + }, []); + + // Function to fetch users from API + const fetchUsers = async () => { + try { + const response = await fetch("/api/users"); + if (!response.ok) { + throw new Error("Failed to fetch users"); + } + const data = await response.json(); + setUsers(data); + } catch (error) { + console.error("Error fetching users:", error); + toast({ + title: "Erreur", + description: "Erreur lors de la récupération des utilisateurs", + variant: "destructive", + }); + } + }; + + // Function to fetch groups from API + const fetchGroups = async () => { + try { + const response = await fetch("/api/groups"); + if (!response.ok) { + throw new Error("Failed to fetch groups"); + } + const data = await response.json(); + + // Fetch member counts for groups + const groupsWithCounts = await Promise.all( + (Array.isArray(data) ? data : []).map(async (group) => { + try { + const membersResponse = await fetch(`/api/groups/${group.id}/members`); + if (membersResponse.ok) { + const members = await membersResponse.json(); + return { + ...group, + membersCount: Array.isArray(members) ? members.length : 0 + }; + } + return {...group, membersCount: 0}; + } catch (error) { + console.error(`Error fetching members for group ${group.id}:`, error); + return {...group, membersCount: 0}; + } + }) + ); + + setGroups(groupsWithCounts); + } catch (error) { + console.error("Error fetching groups:", error); + toast({ + title: "Erreur", + description: "Erreur lors de la récupération des groupes", + variant: "destructive", + }); + } + }; + + // Filtered users based on search term + const filteredUsers = users.filter(user => + (user.username?.toLowerCase() || "").includes(searchTerm.toLowerCase()) || + (user.email?.toLowerCase() || "").includes(searchTerm.toLowerCase()) || + (user.firstName?.toLowerCase() || "").includes(searchTerm.toLowerCase()) || + (user.lastName?.toLowerCase() || "").includes(searchTerm.toLowerCase()) + ); + + // Filtered groups based on search term + const filteredGroups = groups.filter(group => + (group.name?.toLowerCase() || "").includes(searchTerm.toLowerCase()) + ); + + // Function to check if a user is already assigned to any role + const isUserAssigned = (userId: string) => { + return gardienDuTemps === userId || + gardienDeLaParole === userId || + gardienDeLaMemoire === userId || + volontaires.includes(userId); + }; + + // Function to get user's roles (can now have multiple) + const getUserRoles = (userId: string): UserRole[] => { + const roles: UserRole[] = []; + if (gardienDuTemps === userId) roles.push('temps'); + if (gardienDeLaParole === userId) roles.push('parole'); + if (gardienDeLaMemoire === userId) roles.push('memoire'); + if (volontaires.includes(userId)) roles.push('volontaire'); + return roles; + }; + + // For backwards compatibility with existing code + const getUserRole = (userId: string): UserRole | null => { + const roles = getUserRoles(userId); + return roles.length > 0 ? roles[0] : null; + }; + + // Function to get role display name + const getRoleDisplayName = (role: UserRole | null): string => { + switch(role) { + case 'temps': return "Gardien du Temps"; + case 'parole': return "Gardien de la Parole"; + case 'memoire': return "Gardien de la Mémoire"; + case 'volontaire': return "Volontaire"; + default: return ""; + } + }; + + // Function to assign a user to a specific guardian role + const assignGuardienRole = (userId: string, role: GuardienRole) => { + // No longer removing user from existing roles to allow multiple roles + // Only remove from volunteers if they're currently a volunteer + if (volontaires.includes(userId)) { + setVolontaires(prev => prev.filter(id => id !== userId)); + } + + // Assign to new role + if (role === 'temps') { + setGardienDuTemps(userId); + } else if (role === 'parole') { + setGardienDeLaParole(userId); + } else if (role === 'memoire') { + setGardienDeLaMemoire(userId); + } + + toast({ + title: "Rôle assigné", + description: `L'utilisateur a été assigné comme ${getRoleDisplayName(role)}`, + }); + }; + + // Function to assign a user as volunteer + const assignVolontaire = (userId: string) => { + // Remove from any existing role first + removeUserFromAllRoles(userId); + + // Add to volunteers + setVolontaires(prev => [...prev, userId]); + + toast({ + title: "Rôle assigné", + description: "L'utilisateur a été assigné comme Volontaire", + }); + }; + + // Function to remove a user from all roles + const removeUserFromAllRoles = (userId: string) => { + if (gardienDuTemps === userId) setGardienDuTemps(null); + if (gardienDeLaParole === userId) setGardienDeLaParole(null); + if (gardienDeLaMemoire === userId) setGardienDeLaMemoire(null); + if (volontaires.includes(userId)) { + setVolontaires(prev => prev.filter(id => id !== userId)); + } + }; + + // Check if all guardian roles are filled + const areAllGuardiensFilled = (): boolean => { + return gardienDuTemps !== null && gardienDeLaParole !== null && gardienDeLaMemoire !== null; + }; + + // Function to fetch group members + const fetchGroupMembers = async (groupId: string) => { + try { + const response = await fetch(`/api/groups/${groupId}/members`); + if (!response.ok) { + throw new Error("Failed to fetch group members"); + } + const data = await response.json(); + return data; + } catch (error) { + console.error(`Error fetching members for group ${groupId}:`, error); + toast({ + title: "Erreur", + description: "Erreur lors de la récupération des membres du groupe", + variant: "destructive", + }); + return []; + } + }; + + // Handler for viewing group members + const handleViewGroupMembers = async (groupId: string, groupName: string) => { + try { + setLoading(true); + const members = await fetchGroupMembers(groupId); + // Here you would typically open a dialog to show members + // For this implementation, we'll just show a toast with the count + toast({ + title: `Membres de ${groupName}`, + description: `${members.length} membres trouvés dans ce groupe`, + }); + } catch (error) { + console.error("Error handling group members:", error); + } finally { + setLoading(false); + } + }; + + // Function to navigate to the next tab + const goToNextTab = () => { + const tabOrder = ["general", "details", "attachments", "skills", "membres"]; + const currentIndex = tabOrder.indexOf(activeTab); + if (currentIndex < tabOrder.length - 1) { + const nextTab = tabOrder[currentIndex + 1]; + setActiveTab(nextTab); + } + }; + + // Function to navigate to the previous tab + const goToPreviousTab = () => { + const tabOrder = ["general", "details", "attachments", "skills", "membres"]; + const currentIndex = tabOrder.indexOf(activeTab); + if (currentIndex > 0) { + const prevTab = tabOrder[currentIndex - 1]; + setActiveTab(prevTab); + } + }; + + // Check if we're on the last tab + const isLastTab = () => { + return activeTab === "membres"; + }; + + // Check if we're on the first tab + const isFirstTab = () => { + 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 ( +
+ + + + + General + Details + Attachments + Skills + Membres + + + +
+
+ + handleInputChange('name', e.target.value)} + /> +
+ +
+ + { + // Handle logo upload complete + if (data?.filePath) { + setMissionData(prev => ({ + ...prev, + logo: data.filePath + })); + } + }} + /> +
+ +
+
+ + +
+ +
+ + +
+
+ +
+ +
+
+ Paragraphe +
+ + + + + +
+
+