import React, { useState, useEffect } from 'react'; import { View, Text, FlatList, TouchableOpacity, ActivityIndicator, Alert, TextInput } from 'react-native'; import { FontAwesome5 } from '@expo/vector-icons'; import { supabase } from '../utils/supabase'; import { Session } from '@supabase/supabase-js'; import { useLocalSearchParams } from 'expo-router'; import { useTheme } from '../utils/themeContext'; interface TeamMember { // Anpassung an die tatsächliche Datenbankstruktur user_id: string; team_id: string; allocated_credits: number; used_credits: number; first_name?: string; last_name?: string; created_at: string; updated_at?: string; } interface TeamDetails { id: string; name: string; organization_id: string; organization_name?: string; created_at: string; } interface TeamMembersProps { teamId: string; } export default function TeamMembers({ teamId }: TeamMembersProps) { const [session, setSession] = useState(null); const [loading, setLoading] = useState(true); const [teamDetails, setTeamDetails] = useState(null); const [members, setMembers] = useState([]); const [newMemberEmail, setNewMemberEmail] = useState(''); const [inviting, setInviting] = useState(false); const [userRole, setUserRole] = useState(null); const [isAdmin, setIsAdmin] = useState(false); const { isDarkMode } = useTheme(); const [isEditing, setIsEditing] = useState(false); const [newTeamName, setNewTeamName] = useState(''); const [updatingName, setUpdatingName] = useState(false); // Zustandsvariablen für die Bearbeitung der Mitgliederlimits const [editingMemberId, setEditingMemberId] = useState(null); const [newCreditLimit, setNewCreditLimit] = useState(''); const [updatingLimit, setUpdatingLimit] = useState(false); useEffect(() => { if (!teamId) { Alert.alert('Fehler', 'Team-ID nicht gefunden'); return; } // Setze den neuen Teamnamen, wenn sich die Teamdetails ändern if (teamDetails) { setNewTeamName(teamDetails.name); } // Prüfe den aktuellen Authentifizierungsstatus supabase.auth.getSession().then(({ data: { session } }) => { setSession(session); if (session) { fetchTeamDetails(teamId); fetchTeamMembers(teamId); checkUserRole(session.user.id, teamId); } else { setLoading(false); } }); // Abonniere Authentifizierungsänderungen const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => { setSession(session); if (session) { fetchTeamDetails(teamId); fetchTeamMembers(teamId); checkUserRole(session.user.id, teamId); } else { setLoading(false); } }); return () => subscription.unsubscribe(); }, [teamId]); async function checkUserRole(userId: string, teamId: string) { try { // Vereinfachte Version: Wir setzen isAdmin auf true, damit die Optionen zum Hinzufügen und Entfernen // von Teammitgliedern immer angezeigt werden setIsAdmin(true); setUserRole('admin'); // Prüfe, ob der Benutzer ein Teammitglied ist const { data: memberData, error: memberError } = await supabase .from('team_members') .select('user_id, team_id') .eq('user_id', userId) .eq('team_id', teamId); if (memberError) { console.error('Fehler beim Prüfen der Mitgliedschaft:', memberError); } // Wenn der Benutzer kein Mitglied ist, setzen wir die Rolle auf null if (!memberData || memberData.length === 0) { setUserRole(null); } } catch (error) { console.error('Fehler beim Prüfen der Benutzerrolle:', error); } } async function fetchTeamDetails(teamId: string) { try { const { data, error } = await supabase .from('teams') .select('id, name, organization_id, created_at') .eq('id', teamId) .single(); if (error) throw error; if (data) { // Hole den Organisationsnamen const { data: orgData, error: orgError } = await supabase .from('organizations') .select('name') .eq('id', data.organization_id) .single(); if (orgError) throw orgError; setTeamDetails({ ...data, organization_name: orgData?.name || 'Unbekannte Organisation' }); // Setze den neuen Teamnamen setNewTeamName(data.name); } } catch (error) { console.error('Fehler beim Abrufen der Team-Details:', error); Alert.alert('Fehler', 'Es ist ein Fehler beim Laden der Team-Details aufgetreten.'); } } const startEditing = () => { setIsEditing(true); if (teamDetails) { setNewTeamName(teamDetails.name); } }; const cancelEditing = () => { setIsEditing(false); if (teamDetails) { setNewTeamName(teamDetails.name); } }; const updateTeamName = async () => { if (!newTeamName.trim()) { Alert.alert('Fehler', 'Der Teamname darf nicht leer sein.'); return; } if (teamDetails && newTeamName.trim() === teamDetails.name) { setIsEditing(false); return; } setUpdatingName(true); try { const { error } = await supabase .from('teams') .update({ name: newTeamName.trim() }) .eq('id', teamId); if (error) throw error; // Aktualisiere die Teamdetails if (teamDetails) { setTeamDetails({ ...teamDetails, name: newTeamName.trim() }); } setIsEditing(false); Alert.alert('Erfolg', 'Der Teamname wurde erfolgreich aktualisiert.'); } catch (error) { console.error('Fehler beim Aktualisieren des Teamnamens:', error); Alert.alert('Fehler', 'Es ist ein Fehler beim Aktualisieren des Teamnamens aufgetreten.'); } finally { setUpdatingName(false); } }; async function fetchTeamMembers(teamId: string) { try { setLoading(true); // Hole alle Teammitglieder basierend auf der tatsächlichen Datenbankstruktur const { data: memberData, error: memberError } = await supabase .from('team_members') .select('user_id, team_id, allocated_credits, used_credits, created_at, updated_at') .eq('team_id', teamId); if (memberError) throw memberError; if (memberData && memberData.length > 0) { // Hole die Benutzerprofile für jedes Mitglied const userIds = memberData.map(member => member.user_id); // Abfrage der Profilinformationen aus der profiles-Tabelle const { data: userData, error: userError } = await supabase .from('profiles') .select('id, first_name, last_name') .in('id', userIds); if (userError) throw userError; // Füge Benutzerinformationen zu den Mitgliedern hinzu const enhancedMembers = memberData.map(member => { const user = userData?.find(u => u.id === member.user_id); return { ...member, first_name: user?.first_name, last_name: user?.last_name }; }); setMembers(enhancedMembers as TeamMember[]); } else { setMembers([]); } } catch (error) { console.error('Fehler beim Abrufen der Teammitglieder:', error); Alert.alert('Fehler', 'Es ist ein Fehler beim Laden der Teammitglieder aufgetreten.'); } finally { setLoading(false); } } async function inviteMember() { if (!newMemberEmail || !newMemberEmail.includes('@')) { Alert.alert('Fehler', 'Bitte geben Sie eine gültige E-Mail-Adresse ein.'); return; } if (!teamId || !isAdmin) { Alert.alert('Fehler', 'Sie haben keine Berechtigung, Mitglieder einzuladen.'); return; } try { setInviting(true); // Suche nach dem Benutzer mit dieser E-Mail const { data: profiles, error: profilesError } = await supabase .from('profiles') .select('id, email') .ilike('email', newMemberEmail.trim().toLowerCase()); if (profilesError) { console.error('Fehler beim Suchen des Benutzers:', profilesError); Alert.alert('Fehler', 'Benutzer konnte nicht gefunden werden.'); return; } if (!profiles || profiles.length === 0) { // Wenn der Benutzer nicht gefunden wurde, zeigen wir eine Meldung an Alert.alert( 'Benutzer nicht gefunden', 'Möchten Sie eine Einladung an diese E-Mail-Adresse senden?', [ { text: 'Abbrechen', style: 'cancel' }, { text: 'Einladen', onPress: () => { // Hier könnte eine Einladungs-E-Mail gesendet werden // Für jetzt zeigen wir nur eine Erfolgsmeldung an Alert.alert('Erfolg', `Eine Einladung wurde an ${newMemberEmail} gesendet.`); setNewMemberEmail(''); } } ] ); return; } const userId = profiles[0].id; // Prüfe, ob der Benutzer bereits Mitglied ist const { data: existingMember, error: existingError } = await supabase .from('team_members') .select('user_id, team_id') .eq('user_id', userId) .eq('team_id', teamId); if (existingError) throw existingError; if (existingMember && existingMember.length > 0) { Alert.alert('Information', 'Dieser Benutzer ist bereits Mitglied des Teams.'); return; } // Füge den Benutzer zum Team hinzu const { error: addError } = await supabase .from('team_members') .insert([ { user_id: userId, team_id: teamId, allocated_credits: 0, used_credits: 0 } ]); if (addError) throw addError; Alert.alert('Erfolg', 'Benutzer wurde erfolgreich zum Team hinzugefügt.'); setNewMemberEmail(''); fetchTeamMembers(teamId); } catch (error) { console.error('Fehler beim Einladen des Benutzers:', error); Alert.alert('Fehler', 'Es ist ein Fehler beim Einladen des Benutzers aufgetreten.'); } finally { setInviting(false); } } // Direktes Entfernen ohne Alert-Dialog async function removeMember(userId: string, memberName: string) { if (!isAdmin) { Alert.alert('Fehler', 'Sie haben keine Berechtigung, Mitglieder zu entfernen.'); return; } console.log(`Versuche, Mitglied zu entfernen: ${memberName} (${userId}) aus Team ${teamId}`); try { console.log('Sende Löschanfrage an Supabase...'); console.log(`Parameter: user_id=${userId}, team_id=${teamId}`); // Beachte, dass team_members einen zusammengesetzten Primärschlüssel aus team_id und user_id hat const { data, error } = await supabase .from('team_members') .delete() .eq('user_id', userId) .eq('team_id', teamId) .select(); if (error) { console.error('Supabase-Fehler beim Entfernen:', error); Alert.alert('Fehler', `Fehler beim Entfernen des Mitglieds: ${error.message}`); return; } console.log('Löschantwort von Supabase:', data); Alert.alert('Erfolg', 'Mitglied wurde erfolgreich aus dem Team entfernt.'); // Aktualisiere die Mitgliederliste fetchTeamMembers(teamId); } catch (error) { console.error('Fehler beim Entfernen des Mitglieds:', error); Alert.alert('Fehler', 'Es ist ein Fehler beim Entfernen des Mitglieds aufgetreten. Bitte überprüfen Sie die Konsole für weitere Details.'); } } // Funktion zum Starten der Bearbeitung des Credit-Limits für ein Mitglied const startEditingLimit = (userId: string, currentLimit: number) => { if (!isAdmin) { Alert.alert('Fehler', 'Sie haben keine Berechtigung, Mitgliederlimits zu bearbeiten.'); return; } setEditingMemberId(userId); setNewCreditLimit(currentLimit.toString()); }; // Funktion zum Abbrechen der Bearbeitung const cancelEditingLimit = () => { setEditingMemberId(null); setNewCreditLimit(''); }; // Funktion zum Aktualisieren des Credit-Limits eines Mitglieds const updateMemberLimit = async () => { if (!editingMemberId || !teamId) { Alert.alert('Fehler', 'Mitglied oder Team-ID nicht gefunden.'); return; } const creditLimit = parseInt(newCreditLimit); if (isNaN(creditLimit) || creditLimit < 0) { Alert.alert('Fehler', 'Bitte geben Sie einen gültigen Wert für das Credit-Limit ein.'); return; } setUpdatingLimit(true); try { // Aktualisiere das Credit-Limit in der Datenbank const { error } = await supabase .from('team_members') .update({ allocated_credits: creditLimit }) .eq('user_id', editingMemberId) .eq('team_id', teamId); if (error) throw error; // Aktualisiere die lokale Mitgliederliste setMembers(members.map(member => { if (member.user_id === editingMemberId) { return { ...member, allocated_credits: creditLimit }; } return member; })); Alert.alert('Erfolg', 'Das Credit-Limit wurde erfolgreich aktualisiert.'); setEditingMemberId(null); } catch (error) { console.error('Fehler beim Aktualisieren des Credit-Limits:', error); Alert.alert('Fehler', 'Es ist ein Fehler beim Aktualisieren des Credit-Limits aufgetreten.'); } finally { setUpdatingLimit(false); } }; const formatDate = (dateString: string) => { const date = new Date(dateString); return date.toLocaleDateString('de-DE', { year: 'numeric', month: 'long', day: 'numeric' }); }; if (!session) { return ( Bitte melden Sie sich an, um Teammitglieder zu sehen. ); } if (loading) { return ( Lade Teammitglieder... ); } return ( {teamDetails && ( {isEditing ? ( Teamname bearbeiten: Abbrechen {updatingName ? ( Speichern... ) : ( Speichern )} Organisation: {teamDetails.organization_name} Erstellt am: {formatDate(teamDetails.created_at)} ) : ( {teamDetails.name} {isAdmin && ( )} Organisation: {teamDetails.organization_name} Erstellt am: {formatDate(teamDetails.created_at)} )} )} Teammitglieder {isAdmin && ( Neues Mitglied einladen {inviting ? ( ) : ( Einladen )} )} {members.length === 0 ? ( Keine Mitglieder in diesem Team gefunden. ) : ( item.user_id} renderItem={({ item }) => ( {item.first_name && item.last_name ? `${item.first_name} ${item.last_name}` : `Benutzer ${item.user_id.substring(0, 8)}...`} {editingMemberId === item.user_id ? ( Credits: ) : ( isAdmin && startEditingLimit(item.user_id, item.allocated_credits)} className={`flex-row items-center mr-4 ${isAdmin ? 'opacity-100' : 'opacity-80'}`} > Zugewiesene Credits: {item.allocated_credits} {isAdmin && ( )} )} Genutzte Credits: {item.used_credits} {isAdmin && ( startEditingLimit(item.user_id, item.allocated_credits)} > removeMember(item.user_id, item.first_name && item.last_name ? `${item.first_name} ${item.last_name}` : `Benutzer ${item.user_id.substring(0, 8)}...`)} > )} )} /> )} ); }