import { useEffect, useState } from 'react'; import { Dialog } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { ConfirmationDialog } from '@/components/ui/confirmation-dialog'; import { getRoomMembers, kickMember, leaveConversation } from '../services/conversationService'; import type { RoomMemberWithRole } from '../services/conversationService'; import { useChatStore } from '../store/chatStore'; import { useToast } from '@/hooks/useToast'; import { UserMinus, Loader2, Crown, Shield, User, LogOut } from 'lucide-react'; interface RoomMembersModalProps { open: boolean; onOpenChange: (open: boolean) => void; conversationId: string; } function RoleBadge({ role }: { role: string }) { const config = role === 'owner' ? { icon: Crown, label: 'Propriétaire', className: 'text-amber-500' } : role === 'admin' ? { icon: Shield, label: 'Admin', className: 'text-primary' } : { icon: User, label: 'Membre', className: 'text-muted-foreground' }; const Icon = config.icon; return ( {config.label} ); } /** * RoomMembersModal (v0.9.7): List members with roles, kick for owner/admin */ export function RoomMembersModal({ open, onOpenChange, conversationId, }: RoomMembersModalProps) { const { userId } = useChatStore(); const [members, setMembers] = useState([]); const [myRole, setMyRole] = useState(''); const [loading, setLoading] = useState(true); const [kicking, setKicking] = useState(null); const [leaving, setLeaving] = useState(false); const [pendingKick, setPendingKick] = useState<{ userId: string; username: string } | null>(null); const [pendingLeave, setPendingLeave] = useState(false); const { success: showSuccess, error: showError } = useToast(); const canKick = myRole === 'owner' || myRole === 'admin'; useEffect(() => { if (!open || !conversationId) return; setLoading(true); getRoomMembers(conversationId) .then((res) => { setMembers(res.members); setMyRole(res.my_role); }) .catch(() => setMembers([])) .finally(() => setLoading(false)); }, [open, conversationId]); const handleKickClick = (m: RoomMemberWithRole) => { setPendingKick({ userId: m.user_id, username: m.username }); }; const handleKickConfirm = async () => { if (!pendingKick || !canKick || pendingKick.userId === userId) return; setKicking(pendingKick.userId); setPendingKick(null); try { await kickMember(conversationId, pendingKick.userId); setMembers((prev) => prev.filter((m) => m.user_id !== pendingKick.userId)); showSuccess('Membre exclu'); } catch (err) { showError(err instanceof Error ? err.message : 'Impossible d\'exclure'); } finally { setKicking(null); } }; const handleLeaveClick = () => setPendingLeave(true); const handleLeaveConfirm = async () => { if (!pendingLeave) return; setLeaving(true); setPendingLeave(false); try { await leaveConversation(conversationId); showSuccess('Vous avez quitté la conversation'); onOpenChange(false); useChatStore.getState().setCurrentConversation(null); } catch (err) { showError(err instanceof Error ? err.message : 'Impossible de quitter'); } finally { setLeaving(false); } }; return ( {leaving ? ( ) : ( <> Quitter la conversation )} ) } showCancel={false} > {loading ? (
) : (
    {members.map((m) => (
  • {m.username}
    {canKick && m.user_id !== userId && m.role !== 'owner' && ( )}
  • ))}
)} setPendingKick(null)} onConfirm={handleKickConfirm} title="Exclure un membre" description={ pendingKick ? `Êtes-vous sûr de vouloir exclure ${pendingKick.username} du canal ?` : '' } confirmLabel="Exclure" variant="destructive" isLoading={!!kicking} /> setPendingLeave(false)} onConfirm={handleLeaveConfirm} title="Quitter la conversation" description="Vous ne recevrez plus de messages de ce canal. Vous pourrez le rejoindre à nouveau via une invitation." confirmLabel="Quitter" variant="destructive" isLoading={leaving} />
); }