Skip to content

SubniC/fidelity-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FidelityTracker

Aplicación web full-stack (Laravel 12 + Inertia 2 + Vue 3 + TypeScript) que sustituye las tarjetas de fidelización físicas de cartón (N sellos → 1 producto gratis) por tarjetas digitales, para negocios de mascotas: residencias, tiendas y servicios caninos. Incluye panel de administración para el mostrador y portal de cliente mobile-first, con escáner QR por cámara, alta por invitación email, auditoría de dominio y branding configurable por despliegue.

Suite Pest 4 (unit + feature) en verde. Gate de calidad: Pint, PHPStan (level 5, baseline vacío), PHPMD, ESLint y Prettier. Ver CHANGELOG.md.

Documentación:

Lo más destacable

  • Arquitectura por capas con Actions de dominio. La lógica de negocio vive en actions explícitas y testeables (app/Actions/Loyalty/AddStampToLoyaltyCard, VoidStamp, CompleteLoyaltyCard, GenerateReward, RedeemReward, CancelLoyaltyCard…). Los controllers son finos: autorizan, validan vía Form Requests y delegan. Reglas codificadas y blindadas con tests: required_stamps congelado en la tarjeta al crearla, firma bloqueada en tarjetas no activas, premio modelado como entidad separada, discrepancia de producto como aviso (no bloqueo).
  • Auditoría propia. Tabla audit_events alimentada por RecordAuditEvent desde las actions críticas (firma añadida/anulada, tarjeta completada/cancelada, premio generado/redimido, invitación enviada…), para reconstruir qué pasó ante cualquier disputa.
  • Operativa de mostrador sin fricción. Buscador global con debounce, atajos de teclado (/, Ctrl+K, flechas, Enter) y escáner QR desde la cámara; compatible también con lector USB de códigos de barras. La pantalla estrella es el detalle de tarjeta: tarjeta visual grande, botón gigante "Añadir firma", historial cronológico y anulación con motivo.
  • Portal de cliente mobile-first. Tarjetas activas con QR escaneable, banner de premios pendientes, historial, y ajustes propios (perfil, contraseña, tema claro/oscuro/sistema, eliminar cuenta sin afectar al Customer del admin).
  • Alta por invitación email. Sin registro público: el admin crea la cuenta y, en el mismo gesto, invita al portal. El cliente recibe un email, fija su contraseña (portal/setup) y entra con auto-login. Flujo endurecido contra accesos directos sin token.
  • Multi-instancia por configuración. config/branding.php lee de env('BRAND_*'): cada despliegue aplica su propia paleta, logos y favicon sin tocar código, gracias a tokens semánticos de marca (bg-brand-primary, bg-brand-reward…) que resuelven a variables CSS.

Stack

  • Laravel 12 · PHP 8.2+
  • Inertia 2 + Vue 3 + TypeScript
  • Tailwind 3 + tokens semánticos de marca
  • Pest 4 (Unit + Feature)
  • SQLite (por defecto, también para tests en memoria); MariaDB soportado
  • qr-scanner (cámara) + qrcode (renderizado)
  • Calidad: Pint (formato), PHPStan + larastan (level 5, baseline vacío), PHPMD; ESLint + Prettier en el frontend; cabeceras de modelos con barryvdh/laravel-ide-helper

Estructura del repositorio

docs/    Documentación de producto y técnica
src/     Proyecto Laravel completo

Puesta en marcha local

Requiere PHP 8.2+, Composer y Node 20+. Por defecto usa SQLite (sin servidor de BD); para MariaDB, ajusta DB_* en .env.

cd src
composer install
npm install

cp .env.example .env
php artisan key:generate

php artisan migrate --seed   # admin + 2 clientes + tarjetas en distintos estados

npm run dev                   # frontend en modo dev (HMR)

La aplicación no tiene registro público: el admin crea las cuentas y, opcionalmente, invita al portal en el mismo gesto.

Login de desarrollo (sembrado con php artisan db:seed):

Email Password Rol
admin@local password admin
[email protected] password customer

Personalizar la marca

config/branding.php lee de env. Para reaprovechar la codebase con otro negocio basta con un .env distinto en su despliegue:

BRAND_NAME="Nombre del negocio"
BRAND_TAGLINE="Tu eslogan aquí"
BRAND_COLOR_PRIMARY_DARK="#1a4f5e"
BRAND_LOGO_HORIZONTAL=/branding/cliente-horizontal.svg
BRAND_FAVICON=/branding/cliente-favicon.svg

Los SVG personalizados se colocan en public/branding/.

Comandos habituales

cd src
./vendor/bin/pest        # suite Pest (SQLite en memoria; no toca la BD de desarrollo)
npm run build            # build de producción
php artisan migrate:fresh --seed   # reset completo de la BD de desarrollo

Gate de calidad (lo mismo que corre el CI)

cd src
composer lint        # Pint en modo --test (formato)
composer analyse     # PHPStan (larastan, level 5)
composer mess        # PHPMD (ruleset pragmático)
composer quality     # los tres anteriores en cadena
npm run lint         # ESLint (check)
npm run format:check # Prettier (check)

PHPStan arranca con baseline vacío (phpstan-baseline.neon); PHPMD mantiene un baseline acotado al ruido del seeder de demo. La idea es empezar en verde y ratchetear a futuro.

Convenciones

  • Capa de dominio: actions explícitas en app/Actions/...; controllers finos (autorizan, validan, delegan).
  • Estados: enums PHP backed by string, almacenados como VARCHAR para compatibilidad SQLite/MariaDB.
  • Auditoría: tabla audit_events propia, RecordAuditEvent invocada desde las actions críticas.
  • Branding: nunca clases Tailwind "duras" tipo bg-amber-500 para conceptos de marca; usar tokens semánticos (bg-brand-reward, bg-brand-primary-soft, etc.) que resuelven a variables CSS configurables.
  • Tests: Pest 4 con sintaxis closure; feature tests con RefreshDatabase. Necesitan un build previo (npm run build) porque las páginas Inertia renderizan @vite.

Licencia

MIT © 2026 mdps


Un proyecto de mdps · 2026 · desarrollado en Murcia.

About

Full-stack digital loyalty-card app for pet businesses: Laravel 12 + Inertia + Vue 3 + TypeScript, with admin back office and customer portal.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors