Files
WebDrop/web/src/features/home/InvitationInbox.tsx
T

26 lines
1.6 KiB
TypeScript

import { useEffect, useState } from 'react';
import { accountApi, type AccountInvitation } from '@/core-bridge/account';
import { useChannels } from '@/store/channels';
import { Button } from '@/ui/Button';
import { channelPath, navigate } from '@/app/navigation';
import styles from './AccountPanel.module.css';
export function InvitationInbox() {
const [invitations, setInvitations] = useState<AccountInvitation[]>([]);
const [error, setError] = useState('');
const [busy, setBusy] = useState<string>();
useEffect(() => { void accountApi.invitations().then(setInvitations).catch(() => setError('读取邀请失败')); }, []);
async function accept(id: string) {
setBusy(id); setError('');
try { await accountApi.acceptInvitation(id); await useChannels.getState().refresh(); navigate(channelPath(id)); }
catch (cause) { setError(cause instanceof Error ? cause.message : '加入失败'); }
finally { setBusy(undefined); }
}
return <div><strong>空间邀请</strong>
<Button variant="ghost" disabled={Boolean(busy)} onClick={() => { void accountApi.invitations().then(setInvitations).catch(() => setError('读取邀请失败')); }}>刷新邀请</Button>
{invitations.length === 0 ? <p className={styles.note}>暂无邀请。</p> : invitations.map((row) => <div className={styles.actions} key={row.channel_id}>
<span>空间 {row.channel_id.slice(0, 8)}…</span><Button disabled={Boolean(busy)} onClick={() => { void accept(row.channel_id); }}>{busy === row.channel_id ? '加入中…' : '接受邀请'}</Button>
</div>)}
{error ? <p className={styles.error} role="alert">{error}</p> : null}
</div>;
}