Files
family_budget/frontend/src/components/family/InviteModal.tsx
2026-01-29 15:32:22 +03:00

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>
);
}