diff --git a/apps/web/src/app/recibos/[id]/page.tsx b/apps/web/src/app/recibos/[id]/page.tsx
index d63d497..8983ef5 100644
--- a/apps/web/src/app/recibos/[id]/page.tsx
+++ b/apps/web/src/app/recibos/[id]/page.tsx
@@ -132,9 +132,7 @@ function BatchReview({ id }: { id: string }) {
{error &&
{error}
}
{processing && (
-
- Leyendo los recibos… esta pantalla se actualiza sola.
-
+
)}
@@ -170,6 +168,55 @@ const STATUS_LABEL_BATCH: Record = {
FAILED: "Falló",
};
+/**
+ * Live readout while OCR is running. The backend tells us how many pages are
+ * still PENDING_OCR, so we can show real progress instead of "loading…". When
+ * the docs list hasn't caught up to the upload yet (total === 0) we fall back
+ * to the indeterminate bar.
+ */
+function ProcessingBanner({
+ docsLength,
+ pendingOcr,
+}: {
+ docsLength: number;
+ pendingOcr: number;
+}) {
+ const done = Math.max(docsLength - pendingOcr, 0);
+ const pct =
+ docsLength > 0 ? Math.min(100, Math.round((done / docsLength) * 100)) : null;
+ return (
+
+
+
+
+ {pct === null ? (
+ Leyendo los recibos…
+ ) : (
+ <>
+ {pct}%
+
+ {done} de {docsLength} página(s) leídas
+
+ {pendingOcr > 0 && {pendingOcr} en cola}
+ >
+ )}
+
+ Esta pantalla se actualiza sola.
+
+
+
+
+ );
+}
+
function SummaryCard({
batch,
readyCount,