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 [customName, setCustomName] = useState(group.owner_name_original ? group.name : ''); const [savedCustomName, setSavedCustomName] = useState(group.owner_name_original ? group.name : ''); const [savingCustom, setSavingCustom] = useState(false); 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]); const handleCustomName = async () => { setSavingCustom(true); try { const saved = customName.trim(); await api.setCustomGroupName(group.id, saved); setSavedCustomName(saved); toast(saved ? 'Custom name saved' : 'Custom name removed', 'success'); onUpdated(); } catch (e) { toast(e.message, 'error'); } finally { setSavingCustom(false); } }; 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 (
Showing as: {customName.trim() || group.owner_name_original} {customName.trim() && ({group.owner_name_original})}
)}