Paso 16 de 19
Streamlit: módulo de Clientes y Conductores
En este paso construyes los módulos de Clientes y Conductores. Siguen el mismo patrón del módulo de Envíos: tabs para listar y crear, con formularios y mensajes de error claros.
Módulo de Clientes
Crea cargo_track_ui/pages/clientes.py:
cargo_track_ui/pages/clientes.py
python
import streamlit as st
from api_client import get, post, APIError
def mostrar():
st.title("Gestión de Clientes")
tab_lista, tab_crear = st.tabs(["Ver clientes", "Nuevo cliente"])
with tab_lista:
_tab_lista()
with tab_crear:
_tab_crear()
def _tab_lista():
st.subheader("Clientes registrados")
with st.spinner("Cargando clientes..."):
try:
clientes = get("/clientes/")
except APIError as e:
st.error(f"Error {e.status_code}: {e.mensaje}")
return
except Exception:
st.error("No se pudo conectar con el API.")
return
if not clientes:
st.info("No hay clientes registrados.")
return
st.dataframe(
clientes,
column_config={
"id": "ID",
"nombre": "Nombre",
"email": "Correo",
"telefono": "Teléfono",
},
use_container_width=True,
hide_index=True,
)
def _tab_crear():
st.subheader("Registrar nuevo cliente")
with st.form("form_crear_cliente"):
nombre = st.text_input("Nombre completo")
email = st.text_input("Correo electrónico")
telefono = st.text_input("Teléfono (opcional)")
enviado = st.form_submit_button("Registrar cliente", use_container_width=True)
if enviado:
if not nombre or not email:
st.warning("El nombre y el correo son obligatorios.")
return
try:
nuevo = post("/clientes/", {
"nombre": nombre,
"email": email,
"telefono": telefono or None,
})
st.success(f"Cliente '{nuevo['nombre']}' registrado con ID #{nuevo['id']}.")
except APIError as e:
st.error(f"Error {e.status_code}: {e.mensaje}")
except Exception:
st.error("No se pudo conectar con el API.")
El router de conductores en el API
Antes de crear el módulo en Streamlit, necesitas el router en el API. Crea cargo_track/routers/conductores.py:
cargo_track/routers/conductores.py
python
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select
from ..database import get_session
from ..models import Conductor
from ..schemas import ConductorCreate, ConductorRead
from ..auth import verificar_api_key
router = APIRouter(prefix="/conductores", tags=["Conductores"])
@router.get("/", response_model=list[ConductorRead])
def listar_conductores(session: Session = Depends(get_session)):
return session.exec(select(Conductor)).all()
@router.get("/{conductor_id}", response_model=ConductorRead)
def obtener_conductor(conductor_id: int, session: Session = Depends(get_session)):
conductor = session.get(Conductor, conductor_id)
if not conductor:
raise HTTPException(status_code=404, detail="Conductor no encontrado")
return conductor
@router.post("/", response_model=ConductorRead, status_code=201)
def crear_conductor(
conductor: ConductorCreate,
session: Session = Depends(get_session),
_: str = Depends(verificar_api_key),
):
db_conductor = Conductor.model_validate(conductor)
session.add(db_conductor)
session.commit()
session.refresh(db_conductor)
return db_conductor
Registra el nuevo router en main.py:
cargo_track/main.py (agregar import y router)
python
from .routers import envios, clientes, conductores
# dentro de la app, después de los otros routers:
app.include_router(conductores.router)
Módulo de Conductores en Streamlit
Crea cargo_track_ui/pages/conductores.py:
cargo_track_ui/pages/conductores.py
python
import streamlit as st
from api_client import get, post, APIError
def mostrar():
st.title("Gestión de Conductores")
tab_lista, tab_crear = st.tabs(["Ver conductores", "Nuevo conductor"])
with tab_lista:
_tab_lista()
with tab_crear:
_tab_crear()
def _tab_lista():
st.subheader("Conductores registrados")
with st.spinner("Cargando conductores..."):
try:
conductores = get("/conductores/")
except APIError as e:
st.error(f"Error {e.status_code}: {e.mensaje}")
return
except Exception:
st.error("No se pudo conectar con el API.")
return
if not conductores:
st.info("No hay conductores registrados.")
return
st.dataframe(
conductores,
column_config={
"id": "ID",
"nombre": "Nombre",
"licencia": "Licencia",
"email": "Correo",
},
use_container_width=True,
hide_index=True,
)
def _tab_crear():
st.subheader("Registrar nuevo conductor")
with st.form("form_crear_conductor"):
nombre = st.text_input("Nombre completo")
licencia = st.text_input("Número de licencia")
email = st.text_input("Correo electrónico")
enviado = st.form_submit_button("Registrar conductor", use_container_width=True)
if enviado:
if not nombre or not licencia or not email:
st.warning("Todos los campos son obligatorios.")
return
try:
nuevo = post("/conductores/", {
"nombre": nombre,
"licencia": licencia,
"email": email,
})
st.success(f"Conductor '{nuevo['nombre']}' registrado con ID #{nuevo['id']}.")
except APIError as e:
st.error(f"Error {e.status_code}: {e.mensaje}")
except Exception:
st.error("No se pudo conectar con el API.")
Checkpoint
Prueba los dos módulos nuevos con el API corriendo:
- En "Clientes": registra un cliente y verifica que aparece en la tabla de la tab "Ver clientes"
- En "Conductores": registra un conductor y verifica que aparece en la tabla
- Intenta registrar un cliente con el mismo email dos veces y observa el mensaje de error que muestra Streamlit
Si los tres puntos funcionan, los módulos están completos.
Guarda tu progreso
Haz un commit con los cambios de este paso:
terminal
bash
git add cargo_track_ui/pages/clientes.py cargo_track_ui/pages/conductores.py cargo_track/routers/conductores.py cargo_track/main.py
git commit -m "feat: agregar módulos de clientes y conductores en frontend y API"