// Project members management modal const MBIcons = window.Icons; function MembersModal({ project, currentUser, onClose }) { const [members, setMembers] = React.useState([]); const [pending, setPending] = React.useState([]); const [email, setEmail] = React.useState(''); const [role, setRole] = React.useState('editor'); const [loading, setLoading] = React.useState(true); const [inviting, setInviting] = React.useState(false); const [inviteLink, setInviteLink] = React.useState(''); const [msg, setMsg] = React.useState(null); // { type: 'ok'|'err', text } const load = async () => { setLoading(true); try { const res = await fetch(`./api/invite.php?action=members&projectKey=${encodeURIComponent(project.id)}`, { credentials: 'include' }); const data = await res.json(); if (data.ok) { setMembers(data.members || []); setPending(data.pending || []); } } catch (e) {} setLoading(false); }; React.useEffect(() => { load(); }, [project.id]); const invite = async () => { if (!email.trim()) return; setInviting(true); setMsg(null); try { const res = await fetch('./api/invite.php?action=invite', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ projectKey: project.id, projectName: project.name, email: email.trim(), role }), }); const data = await res.json(); if (data.ok) { setInviteLink(data.inviteUrl); setMsg({ type: 'ok', text: 'Davet bağlantısı oluşturuldu.' }); setEmail(''); load(); } else { setMsg({ type: 'err', text: data.error || 'Hata oluştu.' }); } } catch (e) { setMsg({ type: 'err', text: 'Ağ hatası.' }); } setInviting(false); }; const removeMember = async (memberId) => { try { await fetch('./api/invite.php?action=remove', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ projectKey: project.id, memberId }), }); load(); } catch (e) {} }; const revokeInvite = async (invEmail) => { try { await fetch('./api/invite.php?action=revoke', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ projectKey: project.id, email: invEmail }), }); load(); } catch (e) {} }; const copyLink = () => { navigator.clipboard?.writeText(inviteLink).then(() => setMsg({ type: 'ok', text: 'Bağlantı kopyalandı!' })); }; return (
e.stopPropagation()}> {/* Header */}
{project.name}
Proje üyeleri
{/* Body */}
{/* Owner */}
Sahip
{currentUser.avatarUrl ? :
{window.projectAbbr(currentUser.name || 'U')}
}
{currentUser.name}
{currentUser.email}
Sahip
{/* Members */} {!loading && members.length > 0 && ( <>
Üyeler ({members.length})
{members.map(m => (
{m.avatarUrl ? :
{window.projectAbbr(m.name || m.email)}
}
{m.name || m.email}
{m.email}
{m.role === 'editor' ? 'Editör' : 'Görüntüleyici'}
))} )} {/* Pending invites */} {!loading && pending.length > 0 && ( <>
Bekleyen Davetler
{pending.map((p, i) => (
{p.email}
Davet süresi: {p.expires_at?.slice(0, 10)}
{p.role === 'editor' ? 'Editör' : 'Görüntüleyici'}
))} )} {loading &&
Yükleniyor...
} {/* Invite form */}
Davet Et
setEmail(e.target.value)} onKeyDown={e => e.key === 'Enter' && invite()} style={{ flex: 1, height: 40, fontSize: 13 }} />
{msg && (
{msg.text}
)} {inviteLink && (
{inviteLink}
)}
Editör: Görev ekleyebilir, düzenleyebilir.   Görüntüleyici: Sadece okuyabilir.
); } window.MembersModal = MembersModal;