Dos piezas sobre el historial existente (screens-historial, que no se rediseña): el sheet de filtros (tipo de operación, activo, rango de fechas, estado) con chips de filtros activos sobre la lista y "Limpiar filtros"; y el sheet de export (rango + CSV/PDF + estado de generación). Ambos entran por acciones del app bar del historial.
filtros · sheetexport CSV / PDFGET /v1/transactions/exportestado sin-resultados propio
Layout anotado · lista filtrada + sheet de filtros
Los filtros viven en un bottom sheet (no una pantalla) — aplican al cerrar. Los activos quedan como chips removibles sobre la lista: visibilidad permanente del filtro sin re-abrir el sheet.
acciones · filtrar + exportar
chips activos · removibles
lista filtrada · tx-list
9:41
Historial
ComprasBTCÚltimos 30 díasLimpiar filtros
Compra BTC
5 jul · completada
0,00109 BTC
$500.000
Compra BTC
28 jun · completada
0,00218 BTC
$1.000.000
Compra BTC
15 jun · completada
0,00055 BTC
$250.000
Composición
Acciones en app barsliders-horizontal (filtros) con dot badge cuando hay filtros activos, y download (export). Únicas dos acciones — el historial no gana más chrome.
Chips activosUn chip por filtro aplicado, removible con ✕ individual (target 44dp con padding). Row con scroll horizontal si exceden el ancho. Limpiar filtros siempre al final, outlined neutro.
Filtros combinablesTipo (compra/venta/swap/retiro/depósito) · activo (BTC, ETH, USDT, COP) · rango de fechas (presets + custom) · estado (Completado / Procesando / En revisión / Devuelta — los 4 canónicos; "Fallida" no existe). Se combinan con AND.
La lista no cambiaMismas filas tx-list del historial canónico — el patrón solo agrega la capa de filtrado encima.
Sheet de filtros · y sin-resultados
Chips seleccionables por grupo dentro del sheet; "Ver resultados" muestra el conteo antes de aplicar. Sin resultados ≠ historial vacío: el copy culpa a los filtros y ofrece limpiarlos.
Sheet de filtros
9:41
Historial
Filtrar historial
Tipo de operación
ComprasVentasSwapsRetirosDepósitos
Activo
BTCETHUSDTCOP
Rango de fechas
Desde
08 jun 2026
Hasta
08 jul 2026
Estado
CompletadoProcesandoEn revisiónDevuelta
Ver 3 resultados
Limpiar todo
Sin resultados
9:41
Historial
SwapsDevueltaLimpiar filtros
Nada con estos filtros
No hay operaciones que coincidan. Prueba con otro rango o limpia los filtros.
Reglas del sheet
Conteo previoEl CTA dice "Ver N resultados" — consulta con debounce al cambiar chips. Con 0, el CTA dice "Sin resultados" y queda disabled.
Multi-select por grupoChips toggle (varios tipos y activos a la vez). Rango con presets (7/30/90 días, este año) + fechas custom con date picker M3.
Sin-resultados propioÍcono search-x neutro (no error), chips visibles arriba para editar sin re-abrir, CTA "Limpiar filtros". Nunca se confunde con el historial vacío legítimo ("Aún no tienes operaciones").
PersistenciaLos filtros sobreviven navegación dentro de la sesión, no entre sesiones — cada apertura del historial arranca limpia.
Export · rango + formato + generación
Export como sheet independiente: rango, formato (CSV para contadores/DIAN, PDF legible) y estado de generación inline. El archivo se genera en backend y se descarga/comparte al terminar.
Sheet de export
9:41
Historial
Exportar historial
Rango
Este mesEste añoTodoPersonalizado
Formato
CSV · para contabilidadPDF · legible
Generar archivo
Generando → listo
9:41
Historial
Generando tu archivo…
CSV · ene–jul 2026 · unos segundos
Archivo listo
micapi_historial_2026.csv · 18 KB
Compartir
No se pudo generar
Intenta de nuevo en un momento.
Reintentar
Reglas del export
Respeta los filtros… noEl export es independiente de los filtros activos de la lista — exporta por su propio rango. Evita el CSV accidentalmente incompleto para la DIAN.
Generación async3 estados inline en el sheet: generando (spinner + estimado) → listo (nombre mono + peso + Compartir vía share sheet del SO) → error (reintentar). El sheet no se cierra solo.
CSV vs PDFCSV: columnas completas (fecha ISO, tipo, activo, montos, comisión, IVA, tasa, estado, ID) — insumo contable. PDF: layout legible con la marca, mismo pie legal del comprobante (A12).
OfflineCTA disabled + banner. Un export ya descargado sigue disponible desde el gestor de archivos del SO.
Dark · 360dp
Dark · lista filtrada
9:41
Historial
ComprasBTCLimpiar filtros
Compra BTC
5 jul · completada
0,00109 BTC
$500.000
Compra BTC
28 jun · completada
0,00218 BTC
$1.000.000
Notas de implementación · Flutter
Query params + export async
Filtros · query
GET /v1/transactions?types=buy&assets=BTC&from=…&to=…&status=…. El conteo previo usa el mismo endpoint con count_only=true + debounce 400ms.
Estado de filtros
FilterState inmutable en provider de la pantalla (no global). Chips de lista y sheet leen el mismo estado — una sola fuente.
Export
GET /v1/transactions/export?format=csv&from=…&to=… → 202 + job_id; polling a /export/{job_id} cada 1,5s hasta ready con URL firmada. Descarga con dio + share_plus para el share sheet.
Formato es-CO
El CSV usa punto y coma como separador (convención es-CO por la coma decimal) y montos sin formato de miles. El PDF reusa la plantilla de comprobante (A12) en modo multi-operación.
Accesibilidad
Chips con Semantics(toggled); el badge del ícono de filtros anuncia "Filtros activos: 3". El estado de generación se anuncia con liveRegion.
Reduced-motion
Spinner → indicador estático "Generando…" con puntos suspensivos de texto; sheets entran con fade ≤80ms.