Files
makelore/src/pages/Chat/CodingRecoveryCard.tsx
T

33 lines
1.7 KiB
TypeScript

import { useRef, useState } from 'react';
import { Button } from '@/components/ui/button';
import { normalizeAppError } from '@/lib/error-model';
import { codingRecovery, type CodingRecoveryAction } from '../../../shared/coding-recovery';
export function CodingRecoveryCard({ code, work, onRecovery }: {
code?: string;
work: boolean;
onRecovery(action: CodingRecoveryAction, work: boolean): Promise<void> | void;
}) {
const [busy, setBusy] = useState(false);
const [retryCode, setRetryCode] = useState<string>();
const [retryFailed, setRetryFailed] = useState(false);
const flight = useRef(false);
const recovery = codingRecovery(retryCode ?? code, work);
return <div role="status" className="rounded-xl border border-brand/15 bg-brand/5 p-4 text-sm" data-testid="coding-recovery-card">
<p className="font-medium">{work ? '作品还没有打开' : '这一步需要再接着做'}</p>
<p className="mt-1 text-muted-foreground">{retryFailed ? '暂时还没连接上。可以稍后再试,已输入的内容会保留。' : recovery.message}</p>
<Button className="mt-3" size="sm" variant="outline" disabled={busy} onClick={async () => {
if (flight.current) return;
flight.current = true;
setBusy(true);
setRetryFailed(false);
try { await onRecovery(recovery.action, work); }
catch (error) {
const failure = normalizeAppError(error);
setRetryCode(typeof failure.details?.backendCode === 'string' ? failure.details.backendCode : failure.code);
setRetryFailed(failure.code !== 'AUTH_INVALID');
} finally { flight.current = false; setBusy(false); }
}}>{busy ? '正在接着处理…' : recovery.label}</Button>
</div>;
}