97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
import { useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { Copy, Check, Loader2 } from 'lucide-react';
|
|
import { Modal, Button } from '../ui';
|
|
import { useInviteLink } from '../../hooks';
|
|
import type { InviteLinkResponse } from '../../types';
|
|
|
|
interface InviteModalProps {
|
|
onClose: () => void;
|
|
}
|
|
|
|
export function InviteModal({ onClose }: InviteModalProps) {
|
|
const { t } = useTranslation();
|
|
const { createLink } = useInviteLink();
|
|
const [inviteLink, setInviteLink] = useState<InviteLinkResponse | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
const [copied, setCopied] = useState(false);
|
|
|
|
const handleCreateLink = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const link = await createLink({ expires_in_hours: 168 });
|
|
setInviteLink(link);
|
|
} catch (error) {
|
|
console.error(error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleCopy = async () => {
|
|
if (!inviteLink) return;
|
|
try {
|
|
await navigator.clipboard.writeText(inviteLink.invite_url);
|
|
setCopied(true);
|
|
setTimeout(() => setCopied(false), 2000);
|
|
} catch (error) {
|
|
console.error('Failed to copy:', error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal isOpen={true} onClose={onClose} title={t('family.inviteMember')}>
|
|
{!inviteLink ? (
|
|
<div className="text-center py-6">
|
|
<p className="text-gray-700 dark:text-gray-300 mb-6">
|
|
{t('invite.description')}
|
|
</p>
|
|
<Button
|
|
variant="primary"
|
|
onClick={handleCreateLink}
|
|
disabled={loading}
|
|
fullWidth
|
|
>
|
|
{loading ? (
|
|
<>
|
|
<Loader2 className="w-5 h-5 mr-2 animate-spin" />
|
|
{t('common.loading')}
|
|
</>
|
|
) : (
|
|
t('invite.create')
|
|
)}
|
|
</Button>
|
|
</div>
|
|
) : (
|
|
<div className="space-y-4">
|
|
<div className="p-4 bg-gray-100 dark:bg-gray-700 rounded-lg">
|
|
<p className="text-sm text-gray-600 dark:text-gray-400 mb-2">
|
|
{t('invite.link')}
|
|
</p>
|
|
<p className="text-sm font-mono break-all text-gray-900 dark:text-white">
|
|
{inviteLink.invite_url}
|
|
</p>
|
|
</div>
|
|
<Button
|
|
variant="primary"
|
|
onClick={handleCopy}
|
|
fullWidth
|
|
>
|
|
{copied ? (
|
|
<>
|
|
<Check className="w-5 h-5 mr-2" />
|
|
{t('invite.copied')}
|
|
</>
|
|
) : (
|
|
<>
|
|
<Copy className="w-5 h-5 mr-2" />
|
|
{t('invite.copy')}
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</Modal>
|
|
);
|
|
}
|