fix(ancpi): UAT debounce + list tooltips + expired download + ePay retry
1. UAT search: 150ms debounce prevents slow re-renders on keystroke 2. Lista mea tooltips: "Scoate Extrase CF" shows exact credit cost, status badges show expiry dates and clear instructions 3. Expired extracts: both Descarcă (old version) + Actualizează shown 4. ePay auto-connect: retry 2x with 3s delay, check session before connect, re-attempt on disconnect detection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,7 @@ export function EpayConnect({
|
||||
const cbRef = useRef(onStatusChange);
|
||||
cbRef.current = onStatusChange;
|
||||
const autoConnectAttempted = useRef(false);
|
||||
const autoConnectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
const fetchStatus = useCallback(async () => {
|
||||
try {
|
||||
@@ -55,15 +56,23 @@ export function EpayConnect({
|
||||
setStatus(data);
|
||||
cbRef.current?.(data);
|
||||
if (data.connected) setError("");
|
||||
return data;
|
||||
} catch {
|
||||
/* silent */
|
||||
return null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Poll every 30s
|
||||
// Poll every 30s — detect disconnection and allow re-connect
|
||||
useEffect(() => {
|
||||
void fetchStatus();
|
||||
pollRef.current = setInterval(() => void fetchStatus(), 30_000);
|
||||
pollRef.current = setInterval(() => {
|
||||
void fetchStatus().then((data) => {
|
||||
if (data && !data.connected && autoConnectAttempted.current) {
|
||||
autoConnectAttempted.current = false;
|
||||
}
|
||||
});
|
||||
}, 30_000);
|
||||
return () => {
|
||||
if (pollRef.current) clearInterval(pollRef.current);
|
||||
};
|
||||
@@ -92,13 +101,70 @@ export function EpayConnect({
|
||||
}
|
||||
}, [connecting, status.connected, fetchStatus]);
|
||||
|
||||
// Auto-connect when triggerConnect becomes true
|
||||
// Auto-connect when triggerConnect becomes true, with retry on failure
|
||||
useEffect(() => {
|
||||
if (triggerConnect && !status.connected && !connecting && !autoConnectAttempted.current) {
|
||||
autoConnectAttempted.current = true;
|
||||
void connect();
|
||||
}
|
||||
}, [triggerConnect, status.connected, connecting, connect]);
|
||||
if (!triggerConnect || status.connected || connecting || autoConnectAttempted.current) return;
|
||||
autoConnectAttempted.current = true;
|
||||
|
||||
let cancelled = false;
|
||||
const maxRetries = 2;
|
||||
|
||||
const attemptConnect = async (attempt: number) => {
|
||||
if (cancelled) return;
|
||||
|
||||
// On first attempt, check session to avoid unnecessary connect
|
||||
if (attempt === 0) {
|
||||
const current = await fetchStatus();
|
||||
if (cancelled) return;
|
||||
if (current?.connected) return;
|
||||
}
|
||||
|
||||
setConnecting(true);
|
||||
setError("");
|
||||
let shouldRetry = false;
|
||||
try {
|
||||
const res = await fetch("/api/ancpi/session", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
const data = (await res.json()) as { success?: boolean; credits?: number; error?: string };
|
||||
if (cancelled) return;
|
||||
|
||||
if (!res.ok || data.error) {
|
||||
setError(data.error ?? "Eroare conectare ePay");
|
||||
shouldRetry = attempt < maxRetries;
|
||||
} else {
|
||||
await fetchStatus();
|
||||
}
|
||||
} catch {
|
||||
if (cancelled) return;
|
||||
setError("Eroare retea");
|
||||
shouldRetry = attempt < maxRetries;
|
||||
}
|
||||
|
||||
if (cancelled) return;
|
||||
|
||||
if (shouldRetry) {
|
||||
// Keep connecting state true during retry wait
|
||||
autoConnectTimerRef.current = setTimeout(() => {
|
||||
void attemptConnect(attempt + 1);
|
||||
}, 3000);
|
||||
} else {
|
||||
setConnecting(false);
|
||||
}
|
||||
};
|
||||
|
||||
void attemptConnect(0);
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
if (autoConnectTimerRef.current) {
|
||||
clearTimeout(autoConnectTimerRef.current);
|
||||
autoConnectTimerRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [triggerConnect, status.connected, connecting, fetchStatus]);
|
||||
|
||||
const disconnect = async () => {
|
||||
try {
|
||||
@@ -108,6 +174,10 @@ export function EpayConnect({
|
||||
body: JSON.stringify({ action: "disconnect" }),
|
||||
});
|
||||
autoConnectAttempted.current = false;
|
||||
if (autoConnectTimerRef.current) {
|
||||
clearTimeout(autoConnectTimerRef.current);
|
||||
autoConnectTimerRef.current = null;
|
||||
}
|
||||
await fetchStatus();
|
||||
} catch {
|
||||
/* silent */
|
||||
|
||||
Reference in New Issue
Block a user