import { useState, useEffect } from 'react'; import { useAuth } from '../contexts/AuthContext.jsx'; import { api } from '../utils/api.js'; import { useToast } from '../contexts/ToastContext.jsx'; import Avatar from './Avatar.jsx'; export default function GroupInfoModal({ group, onClose, onUpdated, onBack }) { const { user } = useAuth(); const toast = useToast(); const [members, setMembers] = useState([]); const [editing, setEditing] = useState(false); const [newName, setNewName] = useState(group.name); const [addSearch, setAddSearch] = useState(''); const [addResults, setAddResults] = useState([]); const isDirect = !!group.is_direct; const isOwner = group.owner_id === user.id; const isAdmin = user.role === 'admin'; const canManage = !isDirect && ((group.type === 'private' && isOwner) || (group.type === 'public' && isAdmin)); const canRename = !isDirect && !group.is_default && ((group.type === 'public' && isAdmin) || (group.type === 'private' && isOwner)); useEffect(() => { if (group.type === 'private') { api.getMembers(group.id).then(({ members }) => setMembers(members)).catch(() => {}); } }, [group.id]); useEffect(() => { if (addSearch) { api.searchUsers(addSearch).then(({ users }) => setAddResults(users)).catch(() => {}); } }, [addSearch]); const handleRename = async () => { if (!newName.trim() || newName === group.name) { setEditing(false); return; } try { await api.renameGroup(group.id, newName.trim()); toast('Renamed', 'success'); onUpdated(); setEditing(false); } catch (e) { toast(e.message, 'error'); } }; const handleLeave = async () => { if (!confirm('Leave this message?')) return; try { await api.leaveGroup(group.id); toast('Left message', 'success'); onClose(); if (isDirect) { // For direct messages: socket group:deleted fired by server handles // removing from sidebar and clearing active group — no manual refresh needed } else { onUpdated(); if (onBack) onBack(); } } catch (e) { toast(e.message, 'error'); } }; const handleTakeOwnership = async () => { if (!confirm('Take ownership of this private group?')) return; try { await api.takeOwnership(group.id); toast('Ownership taken', 'success'); onUpdated(); onClose(); } catch (e) { toast(e.message, 'error'); } }; const handleAdd = async (u) => { try { await api.addMember(group.id, u.id); toast(`${u.name} added`, 'success'); api.getMembers(group.id).then(({ members }) => setMembers(members)); setAddSearch(''); setAddResults([]); } catch (e) { toast(e.message, 'error'); } }; const handleRemove = async (member) => { if (!confirm(`Remove ${member.name}?`)) return; try { await api.removeMember(group.id, member.id); toast(`${member.name} removed`, 'success'); setMembers(prev => prev.filter(m => m.id !== member.id)); } catch (e) { toast(e.message, 'error'); } }; const handleDelete = async () => { if (!confirm('Delete this message? This cannot be undone.')) return; try { await api.deleteGroup(group.id); toast('Deleted', 'success'); onUpdated(); onClose(); if (onBack) onBack(); } catch (e) { toast(e.message, 'error'); } }; // For direct messages: only show Delete button (owner = remaining user after other left) const canDeleteDirect = isDirect && isOwner; const canDeleteRegular = !isDirect && (isOwner || (isAdmin && group.type === 'public')) && !group.is_default; return (
e.target === e.currentTarget && onClose()}>

Message Info

{/* Name */}
{editing ? (
setNewName(e.target.value)} autoFocus onKeyDown={e => e.key === 'Enter' && handleRename()} />
) : (

{group.name}

{canRename && ( )}
)}
{isDirect ? 'Direct message' : group.type === 'public' ? 'Public message' : 'Private message'} {!!group.is_readonly && Read-only}
{/* Members — shown for private non-direct groups */} {group.type === 'private' && !isDirect && (
Members ({members.length})
{members.map(m => (
{m.name} {m.id === group.owner_id && Owner} {canManage && m.id !== group.owner_id && ( )}
))}
{canManage && (
setAddSearch(e.target.value)} /> {addResults.length > 0 && addSearch && (
{addResults.filter(u => !members.find(m => m.id === u.id)).map(u => ( ))}
)}
)}
)} {/* Actions */}
{/* Direct message: leave (if not already owner/last person) */} {isDirect && !isOwner && ( )} {/* Regular private: leave if not owner */} {!isDirect && group.type === 'private' && !isOwner && ( )} {/* Admin take ownership (non-direct only) */} {!isDirect && isAdmin && group.type === 'private' && !isOwner && ( )} {/* Delete */} {(canDeleteDirect || canDeleteRegular) && ( )}
); }