feat: PWA instalable, cambio de contraseña y dashboards por rol
- POST /api/auth/cambiar-password (bcrypt 12, política ≥8+1 número) + modal en las 6 apps con auth - PWA: manifest + íconos de marca en las 7 apps (sin service worker a propósito, documentado); instalable en celular - Dashboards: 'Mi tablero' para vendedor (sus KPIs y funnel) y sección Equipo para coordinador/corporativo/admin - mi-dia: equipo.porVendedor gana leadsNuevosSemana - Tests: api 271, cotizador 88, alta 88, cobranza 81, agente-ia 19, dashboards 15, mi-dia 11, landing 4
This commit is contained in:
55
scripts/generar-iconos-pwa.py
Normal file
55
scripts/generar-iconos-pwa.py
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Genera los íconos PWA de las 7 apps del ecosistema FRASA.
|
||||
|
||||
Ícono: cuadrado #1B4332 (verde marca) con la inicial del módulo en blanco,
|
||||
en 192×192 y 512×512 PNG, en apps/<app>/public/icons/.
|
||||
|
||||
Uso: /root/.venv-tools/bin/python scripts/generar-iconos-pwa.py
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
VERDE = (0x1B, 0x43, 0x32) # #1B4332, --color-accent StudioBlank
|
||||
BLANCO = (0xFF, 0xFF, 0xFF)
|
||||
TAMANOS = (192, 512)
|
||||
FUENTE = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
|
||||
|
||||
# app → letra del ícono
|
||||
APPS = {
|
||||
"landing": "F",
|
||||
"cotizador": "C",
|
||||
"alta-clientes": "A",
|
||||
"cobranza": "$",
|
||||
"agente-ia": "I",
|
||||
"dashboards": "D",
|
||||
"mi-dia": "H",
|
||||
}
|
||||
|
||||
RAIZ = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def generar(letra: str, tamano: int, destino: Path) -> None:
|
||||
imagen = Image.new("RGB", (tamano, tamano), VERDE)
|
||||
dibujo = ImageDraw.Draw(imagen)
|
||||
fuente = ImageFont.truetype(FUENTE, size=int(tamano * 0.55))
|
||||
caja = dibujo.textbbox((0, 0), letra, font=fuente)
|
||||
ancho, alto = caja[2] - caja[0], caja[3] - caja[1]
|
||||
x = (tamano - ancho) / 2 - caja[0]
|
||||
y = (tamano - alto) / 2 - caja[1]
|
||||
dibujo.text((x, y), letra, font=fuente, fill=BLANCO)
|
||||
imagen.save(destino, "PNG")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
for app, letra in APPS.items():
|
||||
directorio = RAIZ / "apps" / app / "public" / "icons"
|
||||
directorio.mkdir(parents=True, exist_ok=True)
|
||||
for tamano in TAMANOS:
|
||||
destino = directorio / f"icon-{tamano}.png"
|
||||
generar(letra, tamano, destino)
|
||||
print(f"{app}: {destino.relative_to(RAIZ)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user