propuesta · ago 2026
Cliente · Fletes y Envíos

Lista o galería, tú eliges.

Hoy Fletes y Envíos son una pared de cards: con treinta fletes, diez pantallas de scroll para encontrar uno. La propuesta pone una sola barra —búsqueda, chips de estatus, filtros y un control de dos íconos— que sirve igual a la lista y a la galería. La elección se recuerda en el dispositivo; los filtros siguen viviendo en la URL.

Cambiar de vista
1 clic · 0 recargas
Listados
Fletes · Envíos
Preferencia
localStorage
Migraciones
0

Hoy: una pared de cards

freights-list.tsx · shipments-list.tsx

Cada flete es una card de 384 px con nueve datos y un botón «Ver detalle». Con cuatro o cinco fletes se lee bien; con treinta, comparar tarifas o encontrar el que está demorado es bajar y subir. Los cuatro filtros de arriba son selects con etiqueta: ocupan una fila entera y no dicen cuántos fletes hay detrás de cada opción.

Hoy

Cuatro selects y una pared que no termina

  1. Buscar el demorado — leer estatus card por card, 3 por fila.
  2. Comparar tarifas — imposible: cada monto está a 240 px del siguiente.
  3. Filtrar — abrir un select, elegir, esperar; sin conteos.
30 fletes
10 pantallas
Vistas
1
Propuesta

Una barra, dos vistas, la misma data

  1. Lista — 30 fletes en una pantalla y media; el estatus y la tarifa alineados en columna.
  2. Galería — la card de hoy, en rejilla de tres, para quien prefiere leer uno a uno.
  3. Chips con conteo — «En tránsito 7» filtra en un clic y dice cuántos hay.
  4. Se recuerda — el dispositivo abre la vista que elegiste la última vez.
30 fletes
1,5 pantallas
Vistas
2

La barra: sirve a las dos vistas

una fila · 40 px

La barra no sabe en qué vista está. Lee y escribe los mismos filtros de la URL que hoy (useQueryFilters), y el control de la derecha solo cambia cómo se pinta lo que ya llegó.

  1. Búsqueda con atajo

    El mismo campo de hoy (debounce 300 ms, search en la URL), con / para enfocarlo desde el teclado. Sin etiqueta encima: el ícono y el placeholder ya lo dicen.

  2. Chips de estatus con conteo

    Atajos del filtro status. Agrupan los nueve estatus en cuatro que el cliente entiende: Todos · En tránsito · Por pagar · Entregados. El conteo viene del mismo endpoint (fase 3).

  3. «Filtros», lo secundario

    Tipo de envío y estatus de pago (Fletes) o aprobación (Envíos) viven en un menú. La insignia dice cuántos hay aplicados; la línea de resumen debajo los nombra.

  4. El control de dos íconos

    Lista y galería, 44 × 34 px cada uno, el activo se levanta en blanco. No pide datos: la misma página de useInfiniteFreights se pinta distinto. Guarda la elección en localStorage.

Lista: la tabla que se lee de un vistazo

Fletes · 8 columnas · Envíos · 6

Cabecera en hueso, hairlines entre filas, sin zebra. El código en Neue Haas 500, las cifras tabulares para que las tarifas y las fechas queden en columna, y las mismas pills del Badge que ya usa la card, con punto y texto: el color nunca va solo. La fila entera lleva al detalle; el chevrón de la derecha solo lo anuncia.

  1. Una columna manda

    El código (o el tracking del proveedor, como en la card) es la única celda en display. Debajo, en 10 px, el código Mogos cuando el tracking protagoniza.

  2. Ruta en una celda

    Origen → destino con la flecha en gris: dos datos de la card se vuelven uno, y se lee como viaje.

  3. Orden por columna

    Las cabeceras con flecha ordenan (sortBy ya existe en el API de fletes). Por defecto, más reciente primero, como hoy. Fase 4.

  4. Números a la derecha

    Envíos, tarifa y fecha alineados a la derecha con cifras tabulares: comparar treinta tarifas es bajar la vista por una línea.

  5. Scroll infinito, igual

    El sentinel de hoy sigue al pie; el pie de tabla dice cuántos se ven de cuántos hay. Los esqueletos son filas, no cards.

Galería: la card de hoy, en rejilla

default · 3 columnas

La galería se queda como la vista por defecto: es lo que el cliente conoce. Cambia solo el contenedor —de flex-wrap a una rejilla de tres— para que las cards no dejen huecos a la derecha y las columnas queden alineadas con la barra. La card no se toca.

La card se muestra resumida en la maqueta; en el producto sigue siendo FreightCard tal cual, con corredor, promo y estatus de pago.

Memoria: qué se guarda dónde

URL para lo que se comparte · dispositivo para el gusto

Dos memorias con dos dueños. Los filtros son parte de lo que ves y quieres compartir o volver atrás: siguen en la URL. La vista es un gusto de pantalla: vive en el dispositivo y no ensucia el enlace.

Igual que hoy

Los filtros, en la URL

Búsqueda, estatus, tipo, pago o aprobación viajan como query. Un enlace pegado en WhatsApp abre exactamente lo que el otro estaba viendo; el botón atrás deshace un filtro.

/account/freights?status=IN_TRANSIT&shippingType=AIR
· lo lee useQueryFilters · lo consume useInfiniteFreights
Nuevo

La vista, en el dispositivo

Una clave por listado. Se lee al montar (con la galería como valor de fábrica) y se escribe al tocar el control. Sin clave, sin cuenta, sin migración.

localStorage
  mogos:view:fletes  = "list"
  mogos:view:envios  = "gallery"
· useViewMode('fletes') → ['list' | 'gallery', set]
· SSR: primer render en galería, sin salto

Un hook de veinte líneas. En el primer render del servidor no existe localStorage: se pinta la galería y se corrige antes de que el usuario la vea (useSyncExternalStore), sin parpadeo de layout.

Móvil: sin control, siempre cards

390 px · FreightsMobileSwitcher

Una tabla de ocho columnas a 390 px es scroll horizontal y texto cortado. En el teléfono el control no existe: la barra se reduce a búsqueda y chips, y la lista son las cards de hoy a una columna. La preferencia guardada en el escritorio no se aplica aquí.

  1. La barra cabe en dos filas

    Búsqueda arriba, chips deslizables debajo con el desvanecido al borde. «Filtros» pasa a un bottom sheet cuando la fase 3 lo traiga.

  2. Cards a una columna

    Las mismas de hoy. No hay «lista» que elegir porque la card ya es la fila del teléfono.

  3. Si algún día hace falta densidad

    La alternativa es una fila compacta —código, ruta, pill— no una tabla. Queda documentada, no en el alcance.

    MG-FL-2481En tránsitoGuangzhou → La Guaira · $1.240,00
    MG-FL-2477En destinoShenzhen → Caracas · $312,50

Decisiones

9 decisiones · 2026-08-25

Lo que quedó aprobado, por qué, y la alternativa que se descartó.

DecisiónPor quéAlternativa descartada
01Alcance: Fletes y EnvíosSon los dos listados que crecen con el tiempo y comparten patrón (useQueryFilters + scroll infinito). Un solo componente de tabla sirve a los dos.Catálogo también — es una vitrina; una tabla de productos no ayuda a comprar.
02Las dos vistas conviven siempreNi la lista reemplaza a la galería ni al revés. La barra es una y no cambia al alternar; solo cambia el render.Migrar todo a tabla — pierde a quien lee de a uno.
03Solo la vista va a localStorageEs un gusto de pantalla, por listado y por dispositivo. Los filtros siguen en la URL: se comparten y se deshacen con atrás.Filtros en localStorage — el enlace deja de decir lo que se ve.
04Default = galeríaContinuidad: nadie abre la app y encuentra otra cosa. La lista es una elección, y una vez tomada se respeta.Lista por defecto en escritorio — cambia el producto sin que el usuario lo pida.
05Control segmentado de dos íconosUn clic, sin texto ni menú, a la derecha de la barra, a 40 px como todo lo demás. Con aria-pressed y tooltip.Dropdown «Ver como…» — dos clics para un gesto de uno.
06Cambiar de vista no pide datosLas dos vistas consumen las mismas páginas de useInfiniteFreights; el toggle es puro render.Query distinta por vista — doble caché, doble spinner.
07Chips de estatus con conteoCuatro grupos que el cliente entiende, sobre el mismo filtro status. El conteo evita filtrar a ciegas.Select de nueve estatus — se queda, pero dentro de «Filtros».
08Móvil sin controlA 390 px una tabla es scroll horizontal. La card ya es la fila del teléfono.Tabla con scroll horizontal — texto cortado y pulgar cansado.
09Sin sincronizar al servidorCero migraciones. Si un día se quiere «mi vista en todos mis dispositivos», es un campo en UserPreference, no un rediseño.Preferencia en la cuenta — una migración para un gusto de pantalla.

Lo que se reutiliza y lo que nace

apps/client
Existe · se reutiliza

Datos y filtros

  • useInfiniteFreights / useInfiniteOrders — las páginas que ya llegan.
  • useQueryFilters — la URL como estado de filtros.
  • InfiniteScrollSentinel — el pie que carga más.
  • sortBy en freight-query.dto.ts — el API ya ordena.
Existe · se reutiliza

Piezas visuales

  • Badge con sus variantes por estatus (freight.constants.ts, order.constants.ts).
  • FreightCard / ShipmentCard — intactas, en rejilla.
  • PageFrame — título, migas y acciones.
  • MobileSubNav — Fletes / Mis envíos en el teléfono.
Nace

Tres piezas pequeñas

  • useViewMode(key) — lee y escribe mogos:view:{key}, SSR-safe.
  • ViewToggle — el control segmentado, con aria-pressed.
  • ListTable — tabla base (cabecera, fila, pie, esqueleto); FreightsTable y ShipmentsTable le pasan columnas.
  • ListToolbar — búsqueda · chips · Filtros · toggle (fase 3).

Fases

4 fases · 0 migraciones
  1. 1

    El control y la tabla de Fletes

    solo cliente

    useViewMode, ViewToggle a la derecha de los filtros actuales, ListTable + FreightsTable con las ocho columnas. Los filtros de hoy se quedan como están. Se puede usar al final de la fase.

  2. 2

    Envíos

    solo cliente

    ShipmentsTable sobre la misma tabla base, con tracking del proveedor como columna manda y el código Mogos debajo. Clave mogos:view:envios.

  3. 3

    La barra

    cliente + 1 endpoint

    ListToolbar: búsqueda con atajo, chips de estatus con conteo (un endpoint pequeño de conteos por grupo o un campo en la respuesta paginada), menú «Filtros» con insignia. Bottom sheet en móvil.

  4. 4

    Orden por columna

    cliente + DTO de envíos

    Exponer sortBy/sortOrder en PaginationParams y en la URL; cabeceras clicables en tarifa, fecha y estatus. Envíos necesita el mismo parámetro en su DTO.

Qué no hacemos

alcance

Cinco cosas que suelen venir pegadas a «una tabla» y quedan fuera, con la razón.

Tabla en móvil Preferencia en el servidor Columnas configurables Selección múltiple Exportar a Excel
  • Tabla en móvil — scroll horizontal y texto cortado; la card ya es la fila.
  • Preferencia en el servidor — una migración para un gusto de pantalla. Si hace falta, es un campo, no un rediseño.
  • Columnas configurables — ocho columnas bien elegidas valen más que un menú de casillas. El admin es otro producto.
  • Selección múltiple — el cliente no tiene acciones en lote sobre fletes; una casilla sin acción es ruido.
  • Exportar a Excel — existe en el admin (v2). Si el cliente lo pide, es un botón, no parte de la tabla.

Una barra, dos vistas, y la app recuerda cuál.

Treinta fletes en pantalla y media, la tarifa alineada en columna, el estatus a un chip de distancia — o la galería de siempre. Cero migraciones, tres piezas pequeñas.