gilded / client /src /components /modals /InviteModal.jsx
OmegaOne
Upload 41 files
0a8fe79 verified
import React, { useState } from 'react';
export default function InviteModal({ server, onClose, token }) {
const [inviteCode, setInviteCode] = useState('');
const [loading, setLoading] = useState(false);
const [copied, setCopied] = useState(false);
const [error, setError] = useState('');
const generateInvite = async () => {
setLoading(true);
setError('');
try {
const res = await fetch(`/api/invites/servers/${server.id}/invites`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
});
if (!res.ok) throw new Error('Failed to generate invite');
const data = await res.json();
setInviteCode(data.code);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
const inviteLink = inviteCode ? `${window.location.origin}/invite/${inviteCode}` : '';
const copyToClipboard = async () => {
try {
await navigator.clipboard.writeText(inviteLink);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
// Fallback
const ta = document.createElement('textarea');
ta.value = inviteLink;
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
return (
<div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50" onClick={onClose}>
<div className="bg-[#1e1e22] rounded-xl p-6 max-w-md w-full mx-4 shadow-2xl" onClick={e => e.stopPropagation()}>
<h2 className="text-lg font-bold text-gray-100 mb-1">
Invite Friends to <span className="text-[#FFD700]">{server?.name}</span>
</h2>
<p className="text-gray-500 text-sm mb-6">Share this link to let others join your server</p>
{!inviteCode ? (
<button
onClick={generateInvite}
disabled={loading}
className="w-full py-2.5 bg-[#FFD700] text-black font-semibold rounded-lg hover:bg-yellow-400 disabled:opacity-50 transition-colors duration-200"
>
{loading ? 'Generating…' : 'Generate Invite Link'}
</button>
) : (
<div className="space-y-3">
<div className="flex items-center gap-2">
<input
type="text"
readOnly
value={inviteLink}
className="flex-1 bg-[#111114] border border-[#3a3a42] rounded-lg px-4 py-2.5 text-gray-100 text-sm outline-none"
/>
<button
onClick={copyToClipboard}
className={`px-4 py-2.5 rounded-lg font-semibold text-sm transition-colors duration-200 flex-shrink-0 ${
copied
? 'bg-green-600 text-white'
: 'bg-[#FFD700] text-black hover:bg-yellow-400'
}`}
>
{copied ? 'Copied!' : 'Copy'}
</button>
</div>
</div>
)}
{error && <p className="text-red-400 text-sm mt-3">{error}</p>}
<button
onClick={onClose}
className="mt-4 w-full py-2 text-gray-400 hover:text-gray-200 text-sm transition-colors duration-200"
>
Close
</button>
</div>
</div>
);
}