2 Commits

5 changed files with 364 additions and 0 deletions

Binary file not shown.

135
alertas.html Normal file
View File

@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Configurar alertas</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: Arial, sans-serif; background: #f5f5f5; color: #222; }
.header { background: #6a1b9a; color: white; padding: 20px 16px 16px; }
.header p { font-size: 13px; opacity: 0.85; margin-top: 4px; }
.seccion { background: white; margin: 16px 16px 0; border-radius: 12px; padding: 4px 20px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); }
.item { display: flex; align-items: center; justify-content: space-between; padding: 16px 0; border-bottom: 1px solid #f0f0f0; }
.item:last-child { border-bottom: none; }
.item-info { display: flex; align-items: center; gap: 14px; }
.icono { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 18px; }
.item-texto strong { display: block; font-size: 14px; font-weight: 600; }
.item-texto span { font-size: 12px; color: #777; }
.toggle { position: relative; width: 50px; height: 28px; }
.toggle input { opacity: 0; width: 0; height: 0; }
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background: #ccc; border-radius: 28px; transition: 0.3s; }
.slider:before { position: absolute; content: ""; height: 22px; width: 22px; left: 3px; bottom: 3px; background: white; border-radius: 50%; transition: 0.3s; }
input:checked + .slider { background: #6a1b9a; }
input:checked + .slider:before { transform: translateX(22px); }
.guardado { display: none; margin: 12px 16px; background: #f3e5f5; border-radius: 10px; padding: 12px 16px; font-size: 13px; color: #6a1b9a; text-align: center; }
.btn { display: block; width: calc(100% - 32px); margin: 12px 16px 80px; padding: 14px; background: #6a1b9a; color: white; border: none; border-radius: 10px; font-size: 16px; font-weight: 600; cursor: pointer; }
.warning-bar { margin: 0 16px 16px; background: #fff8e1; border-radius: 10px; padding: 12px 14px; font-size: 13px; color: #e65100; }
.menu { position:fixed; bottom:0; left:0; right:0; background:white; border-top:1px solid #ddd; display:flex; justify-content:space-around; padding:10px 0; }
.menu a { text-decoration:none; text-align:center; }
.menu div { font-size:22px; }
.menu span { font-size:11px; display:block; }
</style>
</head>
<body>
<div class="header">
<h1 style="font-size:20px; font-weight:600;">Configurar alertas</h1>
<p>Elige cuándo quieres recibir notificaciones</p>
</div>
<div class="warning-bar">
🔔 Las alertas te ayudan a sacar la basura a tiempo sin esperar afuera.
</div>
<div class="seccion">
<div class="item">
<div class="item-info">
<div class="icono" style="background:#e8f5e9;">🚛</div>
<div class="item-texto">
<strong>Ruta por iniciar</strong>
<span>Aviso cuando el camión salga del depósito</span>
</div>
</div>
<label class="toggle">
<input type="checkbox" id="a1" checked onchange="guardar()">
<span class="slider"></span>
</label>
</div>
<div class="item">
<div class="item-info">
<div class="icono" style="background:#e3f2fd;">📍</div>
<div class="item-texto">
<strong>Camión aproximándose</strong>
<span>Aviso 15 minutos antes de llegar</span>
</div>
</div>
<label class="toggle">
<input type="checkbox" id="a2" checked onchange="guardar()">
<span class="slider"></span>
</label>
</div>
<div class="item">
<div class="item-info">
<div class="icono" style="background:#ffebee;">⚠️</div>
<div class="item-texto">
<strong>Retrasos o fallas</strong>
<span>Aviso si el camión tiene un problema</span>
</div>
</div>
<label class="toggle">
<input type="checkbox" id="a3" checked onchange="guardar()">
<span class="slider"></span>
</label>
</div>
<div class="item">
<div class="item-info">
<div class="icono" style="background:#ede7f6;">🌙</div>
<div class="item-texto">
<strong>Ruta nocturna</strong>
<span>Servicio especial desde las 10:00 p.m.</span>
</div>
</div>
<label class="toggle">
<input type="checkbox" id="a4" onchange="guardar()">
<span class="slider"></span>
</label>
</div>
</div>
<div class="guardado" id="guardado">✅ Preferencias guardadas correctamente</div>
<button class="btn" onclick="guardar()">Guardar preferencias</button>
<nav class="menu">
<a href="/guia" style="color:#888;">
<div>♻️</div>
<span>Guía</span>
</a>
<a href="/reportes" style="color:#888;">
<div>📋</div>
<span>Reportes</span>
</a>
<a href="/alertas" style="color:#6a1b9a;">
<div>🔔</div>
<span>Alertas</span>
</a>
</nav>
<script>
const ids = ["a1","a2","a3","a4"];
window.onload = function() {
ids.forEach(id => {const val = localStorage.getItem(id);
if (val !== null) document.getElementById(id).checked = val === "true";
});
};
function guardar() {
ids.forEach(id => {
localStorage.setItem(id, document.getElementById(id).checked);
});
const msg = document.getElementById("guardado");
msg.style.display = "block";
setTimeout(() => msg.style.display = "none", 2000);
}
</script>
</body>
</html>

91
guia.html Normal file
View File

@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guia de Separacion de Residuos</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: Arial, sans-serif; background: #f5f5f5; color: #222; padding-bottom: 70px; }
.header { background: #2e7d32; color: white; padding: 20px 16px 16px; }
.header p { font-size: 13px; opacity: 0.85; margin-top: 4px; }
.categories { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 16px; }
.cat-card { background: white; border-radius: 12px; padding: 16px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); }
.cat-icon { width: 44px; height: 44px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-bottom: 10px; font-size: 22px; }
.cat-title { font-size: 15px; font-weight: 600; margin-bottom: 3px; }
.cat-sub { font-size: 12px; color: #666; margin-bottom: 10px; }
.tag { display: inline-block; font-size: 11px; padding: 3px 8px; border-radius: 20px; margin: 2px 2px 2px 0; }
.green .cat-icon { background: #e8f5e9; }
.green .cat-title { color: #2e7d32; }
.green .tag { background: #e8f5e9; color: #2e7d32; }
.blue .cat-icon { background: #e3f2fd; }
.blue .cat-title { color: #1565c0; }
.blue .tag { background: #e3f2fd; color: #1565c0; }
.red .cat-icon { background: #ffebee; }
.red .cat-title { color: #c62828; }
.red .tag { background: #ffebee; color: #c62828; }
.amber .cat-icon { background: #fff8e1; }
.amber .cat-title { color: #e65100; }
.amber .tag { background: #fff8e1; color: #e65100; }
.warning-bar { margin: 0 16px 16px; background: #fff8e1; border-radius: 10px; padding: 12px 14px; font-size: 13px; color: #e65100; }
.menu { position: fixed; bottom: 0; left: 0; right: 0; background: white; border-top: 2px solid #ddd; display: flex; justify-content: space-around; padding: 12px 0; z-index: 9999; }
.menu a { text-decoration: none; text-align: center; font-size: 13px; font-weight: 600; }
</style>
</head>
<body>
<div class="header">
<h1 style="font-size:20px; font-weight:600;">Guia de separacion</h1>
<p>Aprende a clasificar tus residuos correctamente</p>
</div>
<div class="categories">
<div class="cat-card green">
<div class="cat-icon" style="background:#e8f5e9;">🌿</div>
<div class="cat-title">Organicos</div>
<div class="cat-sub">Se descomponen naturalmente</div>
<span class="tag">Cascaras de fruta</span>
<span class="tag">Restos de comida</span>
<span class="tag">Cafe y te</span>
<span class="tag">Cascaras de huevo</span>
</div>
<div class="cat-card blue">
<div class="cat-icon" style="background:#e3f2fd;"></div>
<div class="cat-title">Reciclables</div>
<div class="cat-sub">Limpios y secos</div>
<span class="tag">Botellas PET</span>
<span class="tag">Latas de aluminio</span>
<span class="tag">Carton limpio</span>
<span class="tag">Vidrio</span>
</div>
<div class="cat-card red">
<div class="cat-icon" style="background:#ffebee;"></div>
<div class="cat-title">Sanitarios</div>
<div class="cat-sub">No se reciclan</div>
<span class="tag">Panales</span>
<span class="tag">Toallas sanitarias</span>
<span class="tag">Cubrebocas</span>
<span class="tag">Papel higienico</span>
</div>
<div class="cat-card amber">
<div class="cat-icon" style="background:#fff8e1;">!</div>
<div class="cat-title">Especiales</div>
<div class="cat-sub">Requieren manejo especial</div>
<span class="tag">Pilas y baterias</span>
<span class="tag">Medicamentos</span>
<span class="tag">Electronicos</span>
<span class="tag">Aceite usado</span>
</div>
</div>
<div class="warning-bar">
Saca tu basura solo cuando recibas la alerta. No persigas al camion.
</div>
<nav class="menu">
<a href="/guia" style="color:#2e7d32;">Guia</a>
<a href="/reportes" style="color:#1565c0;">Reportes</a>
<a href="/alertas" style="color:#6a1b9a;">Alertas</a>
</nav>
</body>
</html>

29
main.py Normal file
View File

@@ -0,0 +1,29 @@
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from datetime import datetime
app = FastAPI()
reportes = []
@app.get("/guia", response_class=HTMLResponse)
def guia_separacion():
with open("guia.html", "r", encoding="utf-8") as f:
return f.read()
@app.get("/reportes", response_class=HTMLResponse)
def pagina_reportes():
with open("reportes.html", "r", encoding="utf-8") as f:
return f.read()
@app.get("/alertas", response_class=HTMLResponse)
def pagina_alertas():
with open("alertas.html", "r", encoding="utf-8") as f:
return f.read()
@app.post("/api/reportes")
async def recibir_reporte(request: Request):
datos = await request.json()
datos["fecha"] = datetime.now().strftime("%d/%m/%Y %H:%M")
reportes.append(datos)
return {"mensaje": "Reporte recibido correctamente", "total": len(reportes)}

109
reportes.html Normal file
View File

@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reportar incidencia</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: Arial, sans-serif; background: #f5f5f5; color: #222; }
.header { background: #1565c0; color: white; padding: 20px 16px 16px; }
.header p { font-size: 13px; opacity: 0.85; margin-top: 4px; }
.form-card { background: white; margin: 16px 16px 80px; border-radius: 12px; padding: 20px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); }
label { display: block; font-size: 13px; color: #555; margin-bottom: 6px; margin-top: 16px; }
select, textarea { width: 100%; padding: 10px 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; font-family: Arial, sans-serif; background: white; }
textarea { height: 100px; resize: none; }
.btn { display: block; width: 100%; margin-top: 20px; padding: 14px; background: #1565c0; color: white; border: none; border-radius: 10px; font-size: 16px; font-weight: 600; cursor: pointer; }
.exito { display: none; margin: 16px 16px 80px; background: #e8f5e9; border-radius: 12px; padding: 20px; text-align: center; }
.exito p { color: #2e7d32; font-size: 15px; margin-top: 8px; }
.warning-bar { margin: 0 16px 16px; background: #fff8e1; border-radius: 10px; padding: 12px 14px; font-size: 13px; color: #e65100; }
.menu { position:fixed; bottom:0; left:0; right:0; background:white; border-top:1px solid #ddd; display:flex; justify-content:space-around; padding:10px 0; }
.menu a { text-decoration:none; text-align:center; }
.menu div { font-size:22px; }
.menu span { font-size:11px; display:block; }
</style>
</head>
<body>
<div class="header">
<h1 style="font-size:20px; font-weight:600;">Buzón de reportes</h1>
<p>Ayúdanos a mejorar el servicio</p>
</div>
<div class="warning-bar">
⏰ Recuerda: solo saca la basura cuando recibas la alerta de llegada.
</div>
<div class="form-card" id="formulario">
<label>Tipo de reporte</label>
<select id="tipo">
<option value="">Selecciona una opción...</option>
<option value="no_paso">El camión no pasó</option>
<option value="muy_tarde">Pasó muy tarde</option>
<option value="muy_rapido">Pasó muy rápido</option>
<option value="mal_servicio">Mal servicio</option>
<option value="otro">Otro</option>
</select>
<label>Descripción (opcional)</label>
<textarea id="descripcion" placeholder="Describe lo que pasó..."></textarea>
<label>Tu domicilio</label>
<select id="domicilio">
<option value="casa">Casa — Calle Reforma 45</option>
<option value="trabajo">Trabajo — Av. Juárez 120</option>
</select>
<button class="btn" onclick="enviarReporte()">Enviar reporte</button>
</div>
<div class="exito" id="exito">
<div style="font-size:40px;"></div>
<p><strong>¡Reporte enviado!</strong></p>
<p style="margin-top:8px; font-size:13px; color:#555;">Gracias por ayudarnos a mejorar el servicio de recolección.</p>
<button class="btn" style="background:#2e7d32;" onclick="nuevoReporte()">Enviar otro reporte</button>
</div>
<nav class="menu">
<a href="/guia" style="color:#888;">
<div>♻️</div>
<span>Guía</span>
</a>
<a href="/reportes" style="color:#1565c0;">
<div>📋</div>
<span>Reportes</span>
</a>
<a href="/alertas" style="color:#888;">
<div>🔔</div>
<span>Alertas</span>
</a>
</nav>
<script>
async function enviarReporte() {
const tipo = document.getElementById("tipo").value;
if (!tipo) { alert("Por favor selecciona el tipo de reporte."); return; }
const datos = {
tipo: tipo,
descripcion: document.getElementById("descripcion").value,
domicilio: document.getElementById("domicilio").value
};
try {
await fetch("/api/reportes", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(datos)
});
} catch(e) {}
document.getElementById("formulario").style.display = "none";
document.getElementById("exito").style.display = "block";
}
function nuevoReporte() {
document.getElementById("tipo").value = "";
document.getElementById("descripcion").value = "";
document.getElementById("formulario").style.display = "block";
document.getElementById("exito").style.display = "none";
}
</script>
</body>
</html>