Introducción
Contigo Burrito es un proyecto que busca lograr el seguimiento en tiempo real del autobús (¡o autobuses!) de transporte interno de la UNMSM para facilitar la vida de los estudiantes. Además, incluye las siguientes características:
- Notificaciones en la aplicación en forma de banners, ventanas emergentes y publicaciones.
- Seguimiento en tiempo real de la ubicación del autobús, su estado y el nivel de batería del dispositivo.
- Versionado de la aplicación y forzar actualizaciones en los clientes.
- Información de paradas y rutas, incluyendo la distancia a la próxima parada.
- Sesiones de usuario (para analíticas) y autenticación (para recursos protegidos).
- Flags de características tanto para el servidor como para los clientes.
- Integración para subir multimedia con Cloudinary.
El siguiente documento contiene toda la documentación técnica de alto nivel del proyecto, incluyendo la configuración de desarrollo, compilación, distribución, despliegue y otra información relevante.
Soporte y Contacto
No dudes en contactar al equipo si tienes preguntas o necesitas ayuda con el proyecto:
-
Paolo Flores @paoloose, pflores.fisi22@gmail.com
-
Luis Calle @luedu1103
-
Sebastian Rojas @SebastianRojas6
Resumen
A continuación, se presenta una descripción general del proyecto Contigo Burrito y cómo sus componentes interactúan entre sí. Para información más detallada, consulta la documentación específica de cada componente.
Componentes
El proyecto está dividido en cuatro componentes principales, cada uno con su propio repositorio:
Repositorio | Descripción | Tecnologías |
---|---|---|
burrito-app | La app que los estudiantes usan para verificar el estado del autobús. | Flutter, Riverpod, Google Maps |
burrito-server | Servidor REST API responsable. | Rust, Rocket |
burrito-driver | Aplicación para el conductor del autobús que envía datos de ubicación. | Flutter, Geolocator |
burrito-dashboard | Panel de administración para interactuar con el sistema. | Vite, React |
Ten en cuenta que estos son repositorios privados, por lo que es posible que necesites solicitar acceso a ellos.
Arquitectura
El proyecto sigue una arquitectura cliente-servidor, donde el servidor y la aplicación del conductor son responsables de gestionar los datos y los clientes se encargan de mostrarlos.
Burrito App
Status: production ready
La aplicación que los estudiantes usan para verificar el estado del autobús.
Consume los registros de estado desde el burrito-server realizando
consultas constantes al endpoint /status
.
Está escrita en Flutter y se compila para las plataformas Android y web.
Consulta el directorio docs/
para más información.
Protocolo de actualización de la aplicación
El endpoint GET /pending_updates?version=1.0.0
devolverá una lista de versiones de la aplicación que son más recientes que la proporcionada en el parámetro de consulta.
// Ejemplo
{
"must_update": true,
"versions": [
{
"banner_url": "https://picsum.photos/id/866/400",
"is_mandatory": false,
"release_date": "2019-10-12T07:20:50.52Z",
"release_notes": "Este es un resumen extenso de los cambios introducidos en la nueva versión, que puede incluir saltos de línea.\n\n- Característica 1\n- Característica 2",
"semver": "1.1.0"
}
]
}
El cliente NO DEBE permitir que el usuario continúe con la aplicación si alguna versión está marcada como is_mandatory
. Si el cliente lo decide, puede mostrar un diálogo al usuario con el registro de cambios y la opción de actualizar, almacenando el reconocimiento en el almacenamiento local.
Un ejemplo del flujo de trabajo sería:
Acto 1: la primera vez
>el cliente solicita /pending_updates?version=1.0.0
>el servidor devuelve dos versiones pendientes, ninguna obligatoria
>se muestran dos opciones [Actualizar ahora] y [Más tarde] al usuario junto con los registros de cambios
>el usuario reconoce
>el cliente almacena la más alta como "latest_acknowledged_version" en el almacenamiento local
>el usuario decide no actualizar
Acto 2: al día siguiente, otra actualización
>el cliente solicita /pending_updates?version=1.0.0
>el servidor devuelve tres versiones, aún ninguna obligatoria
>como una de ellas es más reciente que "latest_acknowledged_version", el cliente muestra el diálogo
>el usuario reconoce
>el cliente almacena la más alta como "latest_acknowledged_version" en el almacenamiento local
>el usuario decide no actualizar
Acto 3: la actualización urgente
>el cliente solicita /pending_updates?version=1.0.0
>el servidor devuelve cuatro versiones, donde la última (2.0.0) es obligatoria
>el cliente combina los registros de cambios y los muestra al usuario junto con el botón [Actualizar ahora]
>el usuario reconoce y la única opción es actualizar
>el cliente almacena la más alta como "latest_acknowledged_version" en el almacenamiento local
>el usuario actualiza
Acto 4: la calma después de la tormenta
>el cliente solicita /pending_updates?version=2.0.0
>el servidor devuelve una lista vacía
>el cliente continúa con la aplicación
El ejemplo anterior describe nuestra implementación actual. Podríamos cambiarla en el futuro, pero la idea general seguirá siendo la misma.
Compliando el cliente móvil
Para obtener información más detallada, consulte Los documentos oficiales de flutter.
Hay un action llamado "ios-compilation.yml" en el directorio .github/workflows que puedes consultar para más información.
Compliando el APK
Para crear APK para múltiples arquitecturas (ej., ARM, ARM64, x86), utilice el siguiente comando. Esto generará archivos APK separados para cada ABI (interfaz binaria de aplicación), lo que permitirá a los usuarios descargar el APK apropiado para la arquitectura de su dispositivo:
flutter build apk --split-per-abi
Los APK se guardarán en build/app/outputs/flutter-apk/
directorio. En esa carpeta se encuentran los APK generados, listos para probar o distribuir.
Crea un paquete de aplicaciones para su lanzamiento
Además de crear archivos APK, también es una buena práctica generar un paquete de aplicaciones (.aab) para lanzar la aplicación en Google Play Store. El paquete de aplicaciones contiene todo lo necesario para la distribución y Google Play optimizará la aplicación para diferentes configuraciones de dispositivos de manera automática.
Para crear una versión de lanzamiento de la App Bundle, utilice el siguiente comando:
flutter build appbundle --release
Una vez que se complete la compilación, el archivo .aab estará disponible en build/app/outputs/bundle/release/
Puedes cargar este archivo en Google Play Console o en cualquier otra tienda de aplicaciones que admita App Bundles.
Publicando tu aplicación en Google Play Store
Hay algunas cosas que debes verificar antes de enviar la aplicación a Google Play Store (o cualquier otra tienda).
-
Asegúrate de que el servidor esté en funcionamiento
Antes de enviar tu aplicación a una tienda, es importante verificar que el servidor del que depende esté activo, funcional y listo para manejar solicitudes. Muchas tiendas requieren que las aplicaciones proporcionen funcionalidad real y no solo marcadores de posición; por lo tanto, podrían revisar las respuestas de la aplicación para confirmar que funciona como se espera.
Si aún no tienes un controlador enviando los datos, consulta la sección Usando rutas simuladas.
- Verifica las respuestas esperadas: Prueba que la API proporcione correctamente la ubicación del burrito.
- Monitorea el tiempo de actividad: Muchas tiendas pueden revisar periódicamente la funcionalidad de tu aplicación durante el proceso de revisión. Considera usar un servicio de monitoreo para recibir alertas si tu servidor deja de estar disponible inesperadamente.
-
Asegúrate de que la aplicación esté usando la API correcta y no localhost
Revisa el archivo
lib/services/dio_client.dart
para asegurarte de que la aplicación esté conectada al punto final correcto de la API. ElbaseUrl
debe estar configurado en la URL de tu API en vivo, no en localhost:baseUrl: 'https://yourAPI.com',
Ahora estás listo para publicar la aplicación en la tienda de tu elección.
Desplegando la aplicación en la web usando Cloudflare Pages
El despliegue en Cloudflare Pages ya está configurado como un flujo de trabajo de GitHub que se activa con cada push a la rama main
.
Para más detalles, consulta el archivo .github/workflows/deploy.yml
.
Usando un dominio personalizado
Por defecto, las páginas de Cloudflare se despliegan en el dominio *.pages.dev
.
Para usar un dominio personalizado, sigue las instrucciones proporcionadas por Cloudflare en el panel de Pages.
Construyendo manualmente la aplicación web
Construye la aplicación para web con:
flutter build web -t lib/main.dart
Burrito server
Status: Production ready
La API de Burrito sirve todos los datos del servidor (versiones de la app, notificaciones, flags, sesiones) y actúa como puente de comunicación entre la aplicación del conductor del autobús y la aplicación del usuario.
El servidor está escrito en Rust y utiliza el framework web Rocket.
Documentación de la API
Para la documentación de la API seguimos un enfoque de código primero. La documentación
se genera a partir del código fuente utilizando utoipa
,
que genera un archivo de especificación OpenAPI 3.1 en tiempo de compilación.
Esta especificación es luego consumida y renderizada por
Scalar. El resultado final del documento es servido
por la propia API y puede ser accedido públicamente en /docs
.
Puedes consultar la documentación online en https://api.contigosanmarcos.com/docs.
Documentar los endpoints de la API
Para documentar una ruta se utiliza la macro path
del atributo de utoipa
.
Esta macro toma varios argumentos para documentar el endpoint. Los más
importantes se muestran en este ejemplo de PATCH /flag/id
:
#[utoipa::path(
tag = docs::tags::APP_VERSIONS_TAG,
description = "Edits an existing app version. All columns are optional.",
request_body(content = schemas::AppVersionPatchPayload),
responses(
(status = 200, body = schemas::AppVersion),
(status = 400),
(status = 401),
),
security(("staff_user_auth" = [])),
)]
#[patch("/<id>", format = "json", data = "<payload>")]
async fn patch_app_version(
id: i32,
_user: StaffUser,
payload: JsonResult<'_, schemas::AppVersionPatchPayload>,
state: &State<AppState>,
) -> ApiResponse<Json<schemas::AppVersion>> {
// ...
}
Consulta la documentación de utoipa::path para más detalles.
Gestión de la base de datos
Nuestro driver de base de datos, sqlx, resuelve la mayoría de los problemas relacionados con la gestión de bases de datos.
Si no estás familiarizado con sqlx, este video es un buen punto de partida.
Primero, asegúrate de tener instalado el cliente sqlx.
cargo install sqlx-cli
Creación de migraciones de base de datos
Las migraciones de base de datos se encuentran en el directorio migrations/
.
Crea una nueva migración para cada cambio que quieras hacer en el esquema de
la base de datos.
Por ejemplo, si necesitas añadir una nueva columna profile_image
a la tabla
users
, puedes crear una migración con el siguiente comando:
sqlx migrate add -rs add_users_profile_image
Esto generará dos archivos en el directorio migrations/
:
migrations/000x_add_users_profile_image.up.sql
migrations/000x_add_users_profile_image.down.sql
Edita el archivo up.sql
para añadir la nueva columna:
ALTER TABLE users
ADD COLUMN profile_image TEXT;
Luego, edita el archivo down.sql
para revertir la migración:
ALTER TABLE users
DROP COLUMN profile_image;
La idea es que el archivo down.sql
revierta los cambios realizados en up.sql
,
dejando la base de datos exactamente en el mismo estado que antes de aplicar
la migración.
Después de eso, puedes ejecutar o revertir las migraciones con:
sqlx migrate run
sqlx migrate revert
O reiniciar completamente la base de datos con:
sqlx database reset --force
Una vez que hagas commit a tus migraciones, no necesitas hacer nada más para aplicarlas en producción, ya que siempre se verifican y ejecutan automáticamente al iniciar el servidor.
Compilación de consultas en "offline mode"
La idea de sqlx es que las consultas SQL planas se verifican en tiempo de compilación y se traducen a tipos primitivos de Rust. Sin embargo, esto requiere una conexión a la base de datos para verificar las consultas.
Por esta razón existe la compilación en "offline mode". Lo único que necesitas tener en cuenta aquí es que cada vez que hagas un commit ejecutes lo siguiente:
cargo sqlx prepare
Las consultas compiladas se guardarán en el directorio .sqlx/
y deben incluirse en el repositorio. Para más detalles, consulta la
documentación sobre el offline mode de sqlx.
Variables de entorno
El archivo .env.example
muestra una lista actualizada de todas las variables de entorno que utiliza el servidor. Comienza copiando el archivo de ejemplo a .env
:
cp .env.example .env
Todas las variables definidas aquí se corresponden directamente con una variable global estática de Rust definida en el archivo src/env.rs
, por lo que puedes utilizarlas en tu código de esta forma:
fn main() { let port: u16 = *crate::env::PORT; println!("Server running on port {}", port); }
Ejemplos
Un archivo .env listo para usar en desarrollo se vería así:
IS_MOCKED=false
ROOT_SECRET="root_secret"
AUTH_DRIVER_PASSPHRASE="driver_pass"
AUTH_WHATSAPP_ACCESS_TOKEN="none"
POSTGRES_PASSWORD="dontship"
DATABASE_URL="postgres://admin:${POSTGRES_PASSWORD}@localhost/burrito_app"
CLOUDINARY_API_KEY="438453545385499"
CLOUDINARY_CLOUD_NAME="sea1jk51z"
CLOUDINARY_API_SECRET="mJd3bbkWa5mPVKuNBgCLxjY5FSM"
Un archivo .env para producción se vería así:
IS_MOCKED=false
ROOT_SECRET="burrito_prod_6z3g5z2t5z2g5Z2t5g3X"
AUTH_DRIVER_PASSPHRASE="burrito_prod_K4ZVf3g1zS6x2TcjdyDztkbvh4CQHrF6"
# Leave it empty ("") if you don't plan to use the WhatsApp API
AUTH_WHATSAPP_ACCESS_TOKEN="EAAjnKUIiz4ABOzMXloXZCVvifdfFHJGHvlFFWENYE1zFyfg0Ikh0ExDWnkTO1q9CllVXQgKZBvrD3XUucr6Bxk9RIZAITIvzAxWZB2KbZApppIbSwsk2Ozu54emMqb6QlpBRrUM7WAvrRWa8ZApj5p4ZBY9ROIcHKI6CXujoAg1Q1jnv7pJCnVeLDUblAND97J7Q5LliGPZCdiZAHKI16boABdPHo6p2mm8lFCIYZD"
POSTGRES_PASSWORD="MM3ky4RhgpFSbfoXmUh42r0REZzCYXyu"
DATABASE_URL="postgres://admin:${POSTGRES_PASSWORD}@burrito_db/burrito_app"
CLOUDINARY_API_KEY="438453545385499"
CLOUDINARY_CLOUD_NAME="sea1jk51z"
CLOUDINARY_API_SECRET="mJd3bbkWa5mPVKuNBgCLxjY5FSM"
Subiendo las variables de producción a GitHub
Si estás utilizando el pipeline de GitHub CI, asegúrate de configurar las variables en
la configuración del repositorio de GitHub. Puedes encontrarlas en la pestaña Settings
, bajo
Secrets and Variables > Actions
.
Descripción de los secretos:
ENV_FILE
: Una copia exacta del contenido del archivo .env de producción.SSH_KEY
: La clave SSH privada que se utilizará para conectarse al servidor. Esto asume que la clave pública ya está en el archivoauthorized_keys
del servidor.
Descripción de las variables:
SSH_HOST
: El host donde se ejecuta el servidor.SSH_USERNAME
: El usuario que se utilizará para conectarse al servidor.SSH_REPO_PATH
: La ruta donde ya está clonado el repositorio en el servidor.
Creando un nuevo usuario de la aplicación
Actualmente no hay forma de crear un nuevo usuario desde la API, necesitarás
acceso directo a la base de datos al esquema internal
.
Recordar que la aplicación no depende de usuarios para funcionar. Actualmente los usuarios son solo usados para propósitos administrativos.
Existe un procedure llamado internal.create_user
específicamente para este propósito.
\df internal.create_user
Su definición (actual) es la siguiente:
CREATE OR REPLACE PROCEDURE internal.create_user(
p_username citext,
p_display_name varchar(255),
p_password text,
p_is_active boolean,
p_is_staff boolean
)
Por ejemplo, en el contenedor de desarrollo local harías lo siguiente:
$ psql 'postgres://admin:dontship@localhost/burrito_app'
burrito_app=# CALL internal.create_user('username', 'Display Name', 'pass123', true, true);
Cambiando la contraseña del usuario
Existe un procedure llamado internal.change_password
para cambiar la
contraseña de un usuario.
\df internal.change_password
Por ejemplo, para cambiar la contraseña del usuario creado en el paso anterior:
$ psql 'postgres://admin:dontship@localhost/burrito_app'
burrito_app=# CALL internal.change_password('username', 'newpass123');
Verifying the user
De manera similar, existe una function llamada internal.get_auth_user
para consultar un usuario por su nombre de usuario y contraseña.
\df internal.get_auth_user
Por ejemplo, para verificar el usuario creado en el paso anterior:
$ psql 'postgres://admin:dontship@localhost/burrito_app'
burrito_app=# SELECT * FROM internal.get_auth_user('username', 'pass123');
Esta función se utiliza internamente en las rutas de la aplicación que requieren autenticación.
¿Por qué hacerlo de esta forma?
De esta forma, Postgres es responsable de hashear la contraseña y almacenarla de forma segura. El servidor no es responsable de hashear ni verificar nada.
Si se desean exponer endpoints de registro/login de usuarios, se tendrían
que llamar estas funciones desde el backend. Puedes ver un ejemplo de esto en
src/features/auth/handlers/login.rs
.
Usando una ruta de autobús simulada
¿No hay conductor del burrito? ¡No hay problema! Puedes iniciar la aplicación con una ruta simulada
configurando IS_MOCKED=true
en el archivo .env.
La ruta simulada se leerá desde static/mocks/*.json
. Consulta mock.rs
para más
detalles.
Una vez que configures IS_MOCKED=true
, puedes iniciar el servidor como de costumbre.
La simulación funciona enviando solicitudes POST /driver
a nosotros mismos,
iterando sobre los registros de la ruta simulada.
¿Para qué se podría utilizar esta simulación de ruta?
Esta función es útil para mostrar la aplicación sin tener que depender de un conductor de autobús real, o para fines de prueba y NO DEBE usarse en producción.
Despliegue del servidor
El repositorio del servidor contiene todos los componentes necesarios para configurar fácilmente la integración y el despliegue continuos utilizando solo un VPS y GitHub Actions.
Configuración del VPS
La configuración inicial del VPS debería ser sencilla. Asumiendo que estás en un servidor Debian bookworm con privilegios de root:
Dependencias
- Instala Docker y Docker Compose siguiendo la guía oficial: https://docs.docker.com/engine/install/debian/.
Autenticación SSH
-
Crea un nuevo usuario que utilizarás para desplegar el servidor. Nómbralo como desees.
# adduser burrito # usermod -aG sudo burrito
-
Genera un par de claves SSH (o sube una existente) para el nuevo usuario
# su burrito $ ssh-keygen -t ed25519 -C "admin@burrito" -f ~/.ssh/id_ed25519
-
Copia la clave pública en el archivo
authorized_keys
del servidor$ cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
-
Prueba la conexión al servidor
$ ssh burrito@localhost
Configuración del repositorio
-
Ahora clona el repositorio del servidor
$ sudo mkdir -p /opt/burrito/repo $ git clone git@github.com:burrito/server.git /opt/burrito/repo
-
Si estás utilizando el pipeline de CI de GitHub, configura las variables en los ajustes del repositorio de GitHub y estarás listo. Consulta Subiendo las variables de producción a GitHub.
De lo contrario, rellena manualmente un archivo
.env
.
Certificados TLS
-
Lee cuidadosamente el archivo
docker/prod/nginx/nginx.conf
, que contiene la configuración del servidor y las rutas a los certificados TLS. -
Sigue las instrucciones de tu CA (por ejemplo, Let's Encrypt) para generar los certificados. Probablemente necesitarás crear un nuevo registro DNS apuntando a la dirección IP del servidor o un registro TXT de desafío.
-
Genera un par de certificados TLS usando Let's Encrypt u otra CA. Por ejemplo, utilizando Certbot:
# certbot certonly --standalone -d api.contigosanmarcos.com
-
Cualquiera que sea el dominio que hayas utilizado, asegúrate de actualizar la variable
DOMAIN_NAME
en el archivodocker-compose.prod.yml
. -
Si deseas guardar los certificados en una ruta personalizada (como /opt/burrito/certs), asegúrate de actualizar el archivo
docker/prod/nginx/nginx.conf
. -
Usa un verificador de propagación DNS para comprobar si tu dominio apunta correctamente a la dirección IP del servidor.
Iniciar el contenedor
Si estás utilizando GH Actions, no necesitas correr estos comandos. En su lugar, inicia el action de deploy.
-
Puedes levantar el servidor utilizando Docker Compose
$ cd /opt/burrito/repo $ docker compose -f docker-compose.prod.yml up --build
-
Cada vez que desees actualizar el servidor, simplemente descarga los cambios y reinicia el servidor.
$ cd /opt/burrito/repo $ git pull origin main $ docker compose -f docker-compose.prod.yml up --build
Aunque se recomienda usar el pipeline de GitHub Actions en lugar de lanzar comandos manuales.
Production checks
Antes de desplegar en producción, asegúrate de cumplir con las siguientes verificaciones:
-
Has configurado correctamente las variables de entorno requeridas.
-
Has compilado las consultas para modo offline ejecutando
cargo sqlx prepare
-
Las database migrations están actualizadas y han sido probadas localmente.
-
Te has asegurado de que el servidor compila y se ejecuta sin errores localmente.
Bus Driver Application
Estado: Listo para producción
Una aplicación Flutter que envía la ubicación, el nivel de batería y el estado del transporte en autobús de la UNMSM a intervalos regulares para ser consumidos por los clientes de la aplicación.
La aplicación del conductor es responsable de recopilar información del dispositivo, la ubicación y el estado del servicio informado por el conductor, todo en intervalos regulares para ser consumido por las aplicaciones clientes.
La aplicación debe ser simple y consumir la menor cantidad de batería posible.
Escrita con React y Vite.
Compilación de la aplicación del conductor del burrito
Para información más detallada, consulta la documentación oficial de Flutter.
Hay un flujo de trabajo funcional llamado ios-compilation.yml en el directorio .github/workflows que puedes consultar.
Compilación del APK
Para construir APKs para múltiples arquitecturas (por ejemplo, ARM, ARM64, x86), utiliza el siguiente comando. Esto generará archivos APK separados para cada ABI (Interfaz Binaria de Aplicación), permitiendo a los usuarios descargar el APK adecuado para la arquitectura de su dispositivo:
flutter build apk --split-per-abi
Los APKs se guardarán en el directorio build/app/outputs/flutter-apk/
. Puedes encontrar los APKs generados en esa carpeta, listos para pruebas o distribución.
Construir un paquete de la aplicación para la liberación
Además de construir los APKs, también es una buena práctica generar un Paquete de la Aplicación (.aab) para liberar la aplicación en la Google Play Store. El Paquete de la Aplicación contiene todo lo necesario para la distribución, y Google Play optimizará automáticamente la aplicación para diferentes configuraciones de dispositivos.
Para construir una versión de liberación del Paquete de la Aplicación, utiliza el siguiente comando:
flutter build appbundle --release
Una vez que la construcción esté completa, el archivo .aab estará disponible en el directorio build/app/outputs/bundle/release/
. Puedes subir este archivo a la Google Play Console o cualquier otra tienda de aplicaciones que soporte Paquetes de Aplicación.
Cómo funciona la aplicación del conductor
Servicio de ubicación en segundo plano
Esta aplicación utiliza un servicio de ubicación en segundo plano para realizar un seguimiento continuo de la posición del autobús, incluso cuando la aplicación está en segundo plano o cuando la pantalla está apagada. Este servicio se ejecuta de forma silenciosa, asegurando que la ubicación del autobús se envíe al servidor sin necesidad de que el usuario tenga la aplicación abierta.
Enviar la ubicación a la API
La aplicación envía periódicamente las coordenadas GPS del autobús a un servidor. Esto se hace a través de un endpoint de la API, que la aplicación consulta en segundo plano.
Enviar la batería del teléfono
Al mismo tiempo que la aplicación envía una coordenada al servidor, también envía el estado de la batería del teléfono.
Botón simple para iniciar o finalizar el servicio
La aplicación incluye un botón simple que permite a los usuarios iniciar o detener el servicio de ubicación en segundo plano. Cuando el servicio está iniciado, la aplicación comenzará a enviar actualizaciones de ubicación al servidor. Cuando se detiene, la aplicación dejará de hacer un seguimiento o enviar datos de ubicación, lo que finaliza el seguimiento de ubicación para el autobús.
Cambiar el estado del burrito
La aplicación permite cambiar el estado del autobús, denominado "burrito," entre diferentes estados operacionales. Estos estados representan la condición actual del autobús:
- En ruta ("In route"): El autobús está en camino a su destino.
- Fuera de servicio ("Out of service"): El autobús no está operativo o no está disponible.
- En descanso ("At rest"): El autobús está temporalmente detenido o inactivo.
- Accidente ("Accident"): El autobús ha estado involucrado en un accidente.
- Error ("Error"): Hay un problema con el autobús o con los datos de su ubicación.
- Cargando ("Loading"): El autobús está siendo cargado o está en preparación.
- Desconocido ("Unknown"): El estado del autobús no es conocido.
Burrito Admin Dashboard
Estado: listo para producción, pero parcialmente terminado
Dashboard para usuarios del personal/admin para gestionar recursos protegidos.
Características
- Notificaciones: Añadir y eliminar banners de la aplicación. Actualmente no se soportan popups ni publicaciones.
- Batería: Vista rápida de la batería restante de la aplicación.
Escrito con React y Vite.
Despliegue del Dashboard
El dashboard es una simple aplicación de React Vite, por lo que debería ser fácil de desplegar.
Cloudflare Pages
Con la ayuda de GitHub Actions, el despliegue está mayormente automatizado. Asegúrate de tener lo siguiente configurado:
-
Configurar GitHub Secrets: Añade tu
CLOUDFLARE_API_TOKEN
yCLOUDFLARE_ACCOUNT_ID
en los secretos de tu repositorio de GitHub. -
Verificar el flujo de trabajo de GitHub Actions: Asegúrate de que el archivo de flujo de trabajo esté configurado correctamente para construir y desplegar la aplicación. La configuración está en
.github/workflows/cloudflare-deploy.yml
Desplegado en https://burrito-dashboard.pages.dev/
Notas adicionales
Antes de desplegar el dashboard, asegúrate de:
-
Verificar que se haya creado una cuenta de usuario con los permisos adecuados en la base de datos. Esto permite el control de acceso y asegura que cada usuario pueda interactuar con el dashboard como se espera.
-
Verificar que el servidor backend esté funcionando y sea accesible. El dashboard depende del servidor para la recuperación de datos y actualizaciones, por lo que una conexión en vivo es esencial para su funcionalidad completa.