diff --git a/src/app/(app)/dashboard/rec-cards.tsx b/src/app/(app)/dashboard/rec-cards.tsx index 7de8b62..b84a92b 100644 --- a/src/app/(app)/dashboard/rec-cards.tsx +++ b/src/app/(app)/dashboard/rec-cards.tsx @@ -9,6 +9,7 @@ import { type RecCard, } from '@/app/actions/recommendations'; import { sendHelpRequest } from '@/app/actions/help'; +import { CooldownTimer } from '@/components/cooldown-timer'; const PR_URL_RE = /^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+$/; @@ -24,6 +25,13 @@ export default function RecCards({ recs: initial }: { recs: RecCard[] }) { const [pending, startTransition] = useTransition(); const [busyId, setBusyId] = useState(null); const [error, setError] = useState(null); + const [cooldownUntil, setCooldownUntil] = useState(null); + + function handleRateLimit(resetAt?: number) { + if (resetAt) { + setCooldownUntil(resetAt); + } + } function handleClaim(rec: RecCard) { setBusyId(rec.id); @@ -33,6 +41,10 @@ export default function RecCards({ recs: initial }: { recs: RecCard[] }) { if (res.ok) { setRecs((prev) => prev.map((r) => (r.id === rec.id ? { ...r, status: 'claimed' } : r))); } else { + if (res.error.code === 'rate_limited') { + handleRateLimit(res.error.resetAt); + } + setError(`${rec.title}: ${res.error.message}`); } setBusyId(null); @@ -50,6 +62,10 @@ export default function RecCards({ recs: initial }: { recs: RecCard[] }) { return res.data.replacement ? [...without, res.data.replacement] : without; }); } else { + if (res.error.code === 'rate_limited') { + handleRateLimit(res.error.resetAt); + } + setError(`${rec.title}: ${res.error.message}`); } setBusyId(null); @@ -66,13 +82,28 @@ export default function RecCards({ recs: initial }: { recs: RecCard[] }) { return (
- {error && ( + {cooldownUntil ? (
- {error} + { + setCooldownUntil(null); + setError(null); + }} + />
+ ) : ( + error && ( +
+ {error} +
+ ) )}
    @@ -107,19 +138,30 @@ export default function RecCards({ recs: initial }: { recs: RecCard[] }) {
    {rec.status === 'claimed' ? ( - + Date.now()} + /> ) : (