t32 profesor raul vazquez y botones canceladora, mas algunos cambios en UI

This commit is contained in:
Meinar00
2025-02-15 00:37:35 +01:00
parent fbf4b2eebc
commit d3f4e9852e
8 changed files with 147 additions and 77 deletions

49
backend/app.py Normal file
View File

@@ -0,0 +1,49 @@
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)
# Datos de ejemplo (reemplaza con una base de datos)
datos = {
"Línea 1": [
"Zafra", "Julio Caro Baroja (Aqualon)", "Avda. Alemania (Esquina Ruiz de Alda)",
"Avda. Alemania (Plaza de Toros)", "Bda. Navidad", "Don Bosco",
"Plaza de los Dolores", "Barriada del Carmen", "Humilladero", "Cardeñas",
"Orden Baja", "Gonzalo de Berceo", "Plaza Niño Miguel", "Magnolia",
"Hospital JRJ", "Plaza las Amapolas", "Av. Andalucia (Castaño Robledo)",
"Monumento al Fútbol", "Relaciones Laborales (Universidad)",
"Vista Alegre-Universidad", "Centro Comercial Holea", "Cruce Romeralejo",
"Universidad. Avenida de las Artes", "Palacio de Deportes",
"Higueral (Fuerzas Armadas)", "Bda. José Antonio", "Isla Chica",
"Las Delicias", "El Árbol", "Gasolinera", "Estación de Ferrocarril",
"El punto", "Estación de Sevilla", "Nuevo Mercado"
],
"Línea 2": [
"Zafra", "Nuevo Mercado", "Villa de Madrid", "Avenida Italia",
"Estación de Sevilla", "El Punto", "Estación de Ferrocarril", "Juzgados",
"Barrio Obrero", "El Porvenir", "Las Delicias", "Isla Chica",
"Bda, José Antonio", "Fuerzas Armadas Los Rosales", "Palacio de Deporte",
"Ciencias de la Educación (Universidad)", "Biblioteca (Universidad)",
"Monumento al Fútbol", "Relaciones Laborales (Universidad)",
"Vista Alegre-Universidad", "Centro Comercial Holea", "Plaza las Amapolas",
"Hospital JRJ", "Magnolia", "Orden Alta", "Gonzalo de Berceo (Alto)",
"Gonzalo de Berceo (Bajo)", "Orden Baja", "Legión Española", "Cardeñas",
"Humilladero", "Bda. del Carmen", "Santa Lucía", "Santa Eulalia",
"Bda. Navidad", "Molino de la Vega", "Paseo de las Palmeras",
"Julio Caro Baroja (Aqualon)"
],
"Línea 131": ["Puente de Vallecas"]
}
@app.route("/")
def index():
return render_template("index.html", datos=datos)
@app.route("/paradas")
def obtener_paradas():
linea = request.args.get("linea")
if linea and linea in datos:
return jsonify(datos[linea])
return jsonify([])
if __name__ == "__main__":
app.run(debug=True)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -10,6 +10,7 @@ function App() {
const [volume, setVolume] = useState(1); const [volume, setVolume] = useState(1);
const audioRef = useRef(null); const audioRef = useRef(null);
const [theme, setTheme] = useState('light'); const [theme, setTheme] = useState('light');
const [playing, setPlaying] = useState(false);
const datos = { const datos = {
"Línea 1": [ "Línea 1": [
@@ -39,9 +40,9 @@ function App() {
"Bda. Navidad", "Molino de la Vega", "Paseo de las Palmeras", "Bda. Navidad", "Molino de la Vega", "Paseo de las Palmeras",
"Julio Caro Baroja (Aqualon)" "Julio Caro Baroja (Aqualon)"
], ],
"Línea 131": ["Puente de Vallecas"] "Línea 131": ["Puente de Vallecas"],
"Línea T32": ["Profesor Raúl Vázquez"]
}; };
const handleLineaChange = (event) => { const handleLineaChange = (event) => {
setLineaSeleccionada(event.target.value); setLineaSeleccionada(event.target.value);
setParadaSeleccionada(''); setParadaSeleccionada('');
@@ -63,21 +64,27 @@ function App() {
}; };
const reproducirAudio = () => { const reproducirAudio = () => {
if (audio) { if (audio && playing) {
audio.pause(); audio.pause();
} setPlaying(false);
} else if (lineaSeleccionada && paradaSeleccionada) {
if (lineaSeleccionada && paradaSeleccionada) {
const playAudio = (audioFile) => { const playAudio = (audioFile) => {
const nuevoAudio = new Audio(audioFile); const nuevoAudio = new Audio(audioFile);
nuevoAudio.play().catch(error => { nuevoAudio.play().catch(error => {
console.error("Error al reproducir audio:", error); console.error("Error al reproducir audio:", error);
}); });
nuevoAudio.onended = () => {
setPlaying(false);
};
return nuevoAudio; return nuevoAudio;
}; };
const lineaSinEspacios = lineaSeleccionada.split(" ")[1] || lineaSeleccionada.split(" ")[0];
if (tipoParada === "noUsar") { if (tipoParada === "noUsar") {
let paradaAudioFile = `/audio/${lineaSeleccionada.split(" ")[1]}-${paradaSeleccionada.toLowerCase().replace(/ /g, "_")}.wav`; let paradaAudioFile = `/audio/${lineaSinEspacios}-${paradaSeleccionada.toLowerCase().replace(/ /g, "_")}.wav`;
const paradaAudio = playAudio(paradaAudioFile); const paradaAudio = playAudio(paradaAudioFile);
setAudio(paradaAudio); setAudio(paradaAudio);
audioRef.current = paradaAudio; audioRef.current = paradaAudio;
@@ -89,19 +96,21 @@ function App() {
paradaTipoAudio.volume = volume; paradaTipoAudio.volume = volume;
paradaTipoAudio.onended = () => { paradaTipoAudio.onended = () => {
let paradaAudioFile = `/audio/${lineaSeleccionada.split(" ")[1]}-${paradaSeleccionada.toLowerCase().replace(/ /g, "_")}.wav`; let paradaAudioFile = `/audio/${lineaSinEspacios}-${paradaSeleccionada.toLowerCase().replace(/ /g, "_")}.wav`;
const paradaAudio = playAudio(paradaAudioFile); const paradaAudio = playAudio(paradaAudioFile);
setAudio(paradaAudio); setAudio(paradaAudio);
audioRef.current = paradaAudio; audioRef.current = paradaAudio;
paradaAudio.volume = volume; paradaAudio.volume = volume;
}; };
} }
setPlaying(true);
} else { } else {
console.log("Por favor, selecciona una línea y una parada."); console.log("Por favor, selecciona una línea y una parada.");
alert("Para reproducir el audio, selecciona una línea y una parada."); alert("Para reproducir el audio, selecciona una línea y una parada.");
} }
}; };
const reproducirColision = () => { const reproducirColision = () => {
const audioColision = new Audio('/audio/colision.wav'); const audioColision = new Audio('/audio/colision.wav');
audioColision.play().catch(error => { audioColision.play().catch(error => {
@@ -116,7 +125,8 @@ function App() {
for (const linea in datos) { for (const linea in datos) {
datos[linea].forEach(parada => { datos[linea].forEach(parada => {
const audio = new Audio(`/audio/${parada.toLowerCase().replace(/ /g, "_")}.wav`); const lineaSinEspacios = linea.split(" ")[1] || linea.split(" ")[0];
const audio = new Audio(`/audio/${lineaSinEspacios}-${parada.toLowerCase().replace(/ /g, "_")}.wav`);
}); });
} }
@@ -137,85 +147,96 @@ function App() {
setTheme(theme === 'light' ? 'dark' : 'light'); setTheme(theme === 'light' ? 'dark' : 'light');
}; };
const reproducirCanceladora = (audioNombre) => {
const audioCanceladora = new Audio(`/audio/${audioNombre}.mp3`);
audioCanceladora.play().catch(error => {
console.error("Error al reproducir audio:", error);
});
};
return ( return (
<div className="container"> <div className="container mt-4">
<h1>Aplicación de Megafonía</h1> <h1 className="mb-4">Aplicación de Megafonía</h1>
<div> <div className="card mb-4">
<label htmlFor="linea">Línea:</label> <div className="card-body">
<select id="linea" value={lineaSeleccionada} onChange={handleLineaChange} className="form-select"> <div className="mb-3">
<option value="">Selecciona una línea</option> <label htmlFor="linea" className="form-label">Línea:</label>
{Object.keys(datos).map((linea) => ( <select id="linea" value={lineaSeleccionada} onChange={handleLineaChange} className="form-select">
<option key={linea} value={linea}>{linea}</option> <option value="">Selecciona una línea</option>
))} {Object.keys(datos).map((linea) => (
</select> <option key={linea} value={linea}>{linea}</option>
))}
</select>
</div>
<div>
<label htmlFor="parada" className="form-label">Parada:</label>
<select id="parada" value={paradaSeleccionada} onChange={handleParadaChange} className="form-select">
<option value="">Selecciona una parada</option>
{datos[lineaSeleccionada]?.map((parada) => (
<option key={parada} value={parada}>{parada}</option>
))}
</select>
</div>
</div>
</div> </div>
<div> <div className="card mb-4">
<label htmlFor="parada">Parada:</label> <div className="card-body">hora_de_salida.wav
<select id="parada" value={paradaSeleccionada} onChange={handleParadaChange} className="form-select"> <div className="mb-3">
<option value="">Selecciona una parada</option> <div className="d-flex flex-column">
{datos[lineaSeleccionada]?.map((parada) => ( <label className="form-check-label">
<option key={parada} value={parada}>{parada}</option> <input type="radio" value="actual" checked={tipoParada === 'actual'} onChange={handleTipoParadaChange} className="form-check-input me-2" />
))} Parada actual
</select> </label>
<label className="form-check-label">
<input type="radio" value="siguiente" checked={tipoParada === 'siguiente'} onChange={handleTipoParadaChange} className="form-check-input me-2" />
Parada siguiente
</label>
<label className="form-check-label">
<input type="radio" value="noUsar" checked={tipoParada === 'noUsar'} onChange={handleTipoParadaChange} className="form-check-input me-2" />
No usar
</label>
</div>
</div>
<div>
<label htmlFor="volume" className="form-label">Volumen:</label>
<input type="range" id="volume" min="0" max="1" step="0.1" value={volume} onChange={handleVolumeChange} className="form-range" />
</div>
</div>
</div> </div>
<div className="d-flex flex-column"> <div className="d-grid gap-2">
<label> <button onClick={reproducirAudio} className="btn btn-primary" disabled={!lineaSeleccionada || !paradaSeleccionada}>
<input {playing ? "Detener" : "Reproducir"}
type="radio" </button>
value="actual" <button onClick={toggleTheme} className="btn btn-secondary">
checked={tipoParada === 'actual'} Cambiar tema a {theme === 'light' ? 'oscuro' : 'claro'}
onChange={handleTipoParadaChange} </button>
className="form-check-input" <button onClick={reproducirColision} className="btn btn-danger">Anti-Colisión</button>
/>
<span className="form-check-label">Parada actual</span>
</label>
<label>
<input
type="radio"
value="siguiente"
checked={tipoParada === 'siguiente'}
onChange={handleTipoParadaChange}
className="form-check-input"
/>
<span className="form-check-label">Parada siguiente</span>
</label>
<label>
<input
type="radio"
value="noUsar"
checked={tipoParada === 'noUsar'}
onChange={handleTipoParadaChange}
className="form-check-input"
/>
<span className="form-check-label">No usar</span>
</label>
</div> </div>
<div>
<label htmlFor="volume">Volumen:</label> <div className="card mb-4">
<input <div className="card-body">
type="range" <h5 className="card-title">Canceladora</h5>
id="volume" <div className="d-grid gap-2">
min="0" <button onClick={() => reproducirCanceladora('hora_de_salida')} className="btn btn-primary">
max="1" Hora de Salida
step="0.1" </button>
value={volume} <button onClick={() => reproducirCanceladora('atencion_a_su_saldo')} className="btn btn-primary">
onChange={handleVolumeChange} Atención a su Saldo
className="form-range" </button>
/> <button onClick={() => reproducirCanceladora('saldo_insuficiente')} className="btn btn-primary">
Saldo Insuficiente
</button>
</div>
</div>
</div> </div>
<button onClick={reproducirAudio} className="btn btn-primary">Reproducir</button>
<button onClick={toggleTheme} className="btn btn-secondary mt-3">
Cambiar tema a {theme === 'light' ? 'oscuro' : 'claro'}
</button>
<button onClick={reproducirColision} className="btn btn-danger mt-3 fixed-bottom">
Anti-Colisión
</button>
</div> </div>
); );
} }