mirror of
https://github.com/kkhattabi213/megafonias-react.git
synced 2026-01-30 09:13:40 +00:00
cambios generales en interfaz, metodo de gestion de lineas y otros arreglos menores
This commit is contained in:
@@ -18,10 +18,10 @@ datos = {
|
|||||||
"El punto", "Estación de Sevilla", "Nuevo Mercado"
|
"El punto", "Estación de Sevilla", "Nuevo Mercado"
|
||||||
],
|
],
|
||||||
"Línea 2": [
|
"Línea 2": [
|
||||||
"Zafra", "Nuevo Mercado", "Villa de Madrid", "Avenida Italia",
|
"Zafra", "Nuevo Mercado", "Villa de Madrid", "Avenida Italia Estación de Sevilla",
|
||||||
"Estación de Sevilla", "El Punto", "Estación de Ferrocarril", "Juzgados",
|
"El Punto", "Estación de Ferrocarril", "Juzgados",
|
||||||
"Barrio Obrero", "El Porvenir", "Las Delicias", "Isla Chica",
|
"Barrio Obrero", "El Porvenir", "Las Delicias", "Isla Chica",
|
||||||
"Bda, José Antonio", "Fuerzas Armadas Los Rosales", "Palacio de Deporte",
|
"Bda. José Antonio", "Fuerzas Armadas Los Rosales", "Palacio de Deportes",
|
||||||
"Ciencias de la Educación (Universidad)", "Biblioteca (Universidad)",
|
"Ciencias de la Educación (Universidad)", "Biblioteca (Universidad)",
|
||||||
"Monumento al Fútbol", "Relaciones Laborales (Universidad)",
|
"Monumento al Fútbol", "Relaciones Laborales (Universidad)",
|
||||||
"Vista Alegre-Universidad", "Centro Comercial Holea", "Plaza las Amapolas",
|
"Vista Alegre-Universidad", "Centro Comercial Holea", "Plaza las Amapolas",
|
||||||
@@ -31,7 +31,7 @@ datos = {
|
|||||||
"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 141": ["Puente de Vallecas"]
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
|
|||||||
89
package-lock.json
generated
89
package-lock.json
generated
@@ -8,11 +8,14 @@
|
|||||||
"name": "mi-app-paradas-react",
|
"name": "mi-app-paradas-react",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fontsource/roboto": "^5.2.6",
|
||||||
|
"@material/web": "^2.3.0",
|
||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
"cra-template": "1.2.0",
|
"cra-template": "^1.2.0",
|
||||||
|
"flask": "^0.2.10",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"web-vitals": "^4.2.4"
|
"web-vitals": "^4.2.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2305,6 +2308,15 @@
|
|||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fontsource/roboto": {
|
||||||
|
"version": "5.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.6.tgz",
|
||||||
|
"integrity": "sha512-hzarG7yAhMoP418smNgfY4fO7UmuUEm5JUtbxCoCcFHT0hOJB+d/qAEyoNjz7YkPU5OjM2LM8rJnW8hfm0JLaA==",
|
||||||
|
"license": "OFL-1.1",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ayuhito"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.13.0",
|
"version": "0.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
||||||
@@ -2778,6 +2790,34 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
|
||||||
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="
|
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@lit-labs/ssr-dom-shim": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/@lit/reactive-element": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-L2qyoZSQClcBmq0qajBVbhYEcG6iK0XfLn66ifLe/RfC0/ihpc+pl0Wdn8bJ8o+hj38cG0fGXRgSS20MuXn7qA==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"@lit-labs/ssr-dom-shim": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/web": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/web/-/web-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-r7ccZHthMk5tM05goPJ965hQ99ptMyZt7i8Xi8+RmEqK3ZXaMtjx+s4p+9OVX+vgOS3zpop+g1yGYXtOOlrwUg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"workspaces": [
|
||||||
|
"catalog"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"lit": "^2.8.0 || ^3.0.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||||
"version": "5.1.1-v1",
|
"version": "5.1.1-v1",
|
||||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||||
@@ -4804,6 +4844,7 @@
|
|||||||
"url": "https://opencollective.com/bootstrap"
|
"url": "https://opencollective.com/bootstrap"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@popperjs/core": "^2.11.8"
|
"@popperjs/core": "^2.11.8"
|
||||||
}
|
}
|
||||||
@@ -5433,6 +5474,7 @@
|
|||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/cra-template/-/cra-template-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/cra-template/-/cra-template-1.2.0.tgz",
|
||||||
"integrity": "sha512-06WBUmTq79NvqU91Y9OPCXv/ENy/UkUmQS0lBrOYCl/4f4l67idnGbBARDGLopCHfff6pf6UftcFRWHg+CVfRw==",
|
"integrity": "sha512-06WBUmTq79NvqU91Y9OPCXv/ENy/UkUmQS0lBrOYCl/4f4l67idnGbBARDGLopCHfff6pf6UftcFRWHg+CVfRw==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
@@ -7459,6 +7501,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/flask": {
|
||||||
|
"version": "0.2.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/flask/-/flask-0.2.10.tgz",
|
||||||
|
"integrity": "sha512-Zy69KIuFsoX0o2W5uDHHk1GHMwRT8QT0AboPQY7b1soCfJ2pfwKxHF2AGVwJmDUjzawgOavoY/UsXnZ7fk3lVQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/flat-cache": {
|
"node_modules/flat-cache": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
|
||||||
@@ -10178,6 +10226,37 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
|
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/lit": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"@lit/reactive-element": "^2.1.0",
|
||||||
|
"lit-element": "^4.2.0",
|
||||||
|
"lit-html": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lit-element": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-MGrXJVAI5x+Bfth/pU9Kst1iWID6GHDLEzFEnyULB/sFiRLgkd8NPK/PeeXxktA3T6EIIaq8U3KcbTU5XFcP2Q==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"@lit-labs/ssr-dom-shim": "^1.2.0",
|
||||||
|
"@lit/reactive-element": "^2.1.0",
|
||||||
|
"lit-html": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lit-html": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-RHoswrFAxY2d8Cf2mm4OZ1DgzCoBKUKSPvA1fhtSELxUERq2aQQ2h05pO9j81gS1o7RIRJ+CePLogfyahwmynw==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/trusted-types": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/loader-runner": {
|
"node_modules/loader-runner": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
||||||
@@ -12595,6 +12674,7 @@
|
|||||||
"version": "19.0.0",
|
"version": "19.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz",
|
||||||
"integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==",
|
"integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -12723,6 +12803,7 @@
|
|||||||
"version": "19.0.0",
|
"version": "19.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz",
|
||||||
"integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==",
|
"integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.25.0"
|
"scheduler": "^0.25.0"
|
||||||
},
|
},
|
||||||
@@ -12752,6 +12833,7 @@
|
|||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||||
"integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==",
|
"integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.16.0",
|
"@babel/core": "^7.16.0",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
|
||||||
@@ -15234,7 +15316,8 @@
|
|||||||
"node_modules/web-vitals": {
|
"node_modules/web-vitals": {
|
||||||
"version": "4.2.4",
|
"version": "4.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
|
||||||
"integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="
|
"integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
|
|||||||
@@ -3,11 +3,14 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fontsource/roboto": "^5.2.6",
|
||||||
|
"@material/web": "^2.3.0",
|
||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
"cra-template": "1.2.0",
|
"cra-template": "^1.2.0",
|
||||||
|
"flask": "^0.2.10",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"web-vitals": "^4.2.4"
|
"web-vitals": "^4.2.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/audio/141-puente_de_vallecas.wav
Normal file
BIN
public/audio/141-puente_de_vallecas.wav
Normal file
Binary file not shown.
377
src/App.js
377
src/App.js
@@ -1,6 +1,15 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
||||||
|
import '@material/web/button/filled-button.js';
|
||||||
|
import '@material/web/button/outlined-button.js';
|
||||||
|
import '@material/web/select/filled-select.js';
|
||||||
|
import '@material/web/select/select-option.js';
|
||||||
|
import '@material/web/radio/radio.js';
|
||||||
|
import '@material/web/slider/slider.js';
|
||||||
|
// import '@material/web/card/card.js'; // Temporalmente comentado
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
|
||||||
|
// Importa la fuente Roboto de Google Fonts
|
||||||
|
import "@fontsource/roboto"; // npm install @fontsource/roboto
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [lineaSeleccionada, setLineaSeleccionada] = useState('');
|
const [lineaSeleccionada, setLineaSeleccionada] = useState('');
|
||||||
@@ -11,8 +20,10 @@ function App() {
|
|||||||
const audioRef = useRef(null);
|
const audioRef = useRef(null);
|
||||||
const [theme, setTheme] = useState('light');
|
const [theme, setTheme] = useState('light');
|
||||||
const [playing, setPlaying] = useState(false);
|
const [playing, setPlaying] = useState(false);
|
||||||
|
const [ciudadSeleccionada, setCiudadSeleccionada] = useState('');
|
||||||
|
|
||||||
const datos = {
|
// Diccionario de paradas por línea para evitar mezclas y garantizar independencia
|
||||||
|
const paradasPorLinea = useMemo(() => ({
|
||||||
"Línea 1": [
|
"Línea 1": [
|
||||||
"Zafra", "Julio Caro Baroja (Aqualon)", "Avda. Alemania (Esquina Ruiz de Alda)",
|
"Zafra", "Julio Caro Baroja (Aqualon)", "Avda. Alemania (Esquina Ruiz de Alda)",
|
||||||
"Avda. Alemania (Plaza de Toros)", "Bda. Navidad", "Don Bosco",
|
"Avda. Alemania (Plaza de Toros)", "Bda. Navidad", "Don Bosco",
|
||||||
@@ -27,10 +38,10 @@ function App() {
|
|||||||
"El punto", "Estación de Sevilla", "Nuevo Mercado"
|
"El punto", "Estación de Sevilla", "Nuevo Mercado"
|
||||||
],
|
],
|
||||||
"Línea 2": [
|
"Línea 2": [
|
||||||
"Zafra", "Nuevo Mercado", "Villa de Madrid", "Avenida Italia",
|
"Zafra", "Nuevo Mercado", "Villa de Madrid", "Avenida Italia Estación de Sevilla",
|
||||||
"Estación de Sevilla", "El Punto", "Estación de Ferrocarril", "Juzgados",
|
"El Punto", "Estación de Ferrocarril", "Juzgados",
|
||||||
"Barrio Obrero", "El Porvenir", "Las Delicias", "Isla Chica",
|
"Barrio Obrero", "El Porvenir", "Las Delicias", "Isla Chica",
|
||||||
"Bda, José Antonio", "Fuerzas Armadas Los Rosales", "Palacio de Deporte",
|
"Bda. José Antonio", "Fuerzas Armadas Los Rosales", "Palacio de Deportes",
|
||||||
"Ciencias de la Educación (Universidad)", "Biblioteca (Universidad)",
|
"Ciencias de la Educación (Universidad)", "Biblioteca (Universidad)",
|
||||||
"Monumento al Fútbol", "Relaciones Laborales (Universidad)",
|
"Monumento al Fútbol", "Relaciones Laborales (Universidad)",
|
||||||
"Vista Alegre-Universidad", "Centro Comercial Holea", "Plaza las Amapolas",
|
"Vista Alegre-Universidad", "Centro Comercial Holea", "Plaza las Amapolas",
|
||||||
@@ -40,25 +51,60 @@ 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 3": [
|
||||||
"Línea T32": ["Profesor Raúl Vázquez"],
|
"Zafra", "Plaza de la Vera Cruz", "San Andrés", "Av. Manuel Siurot", "La Morana",
|
||||||
"xx": ["tristante"]
|
"Obispado", "Colegio Mayor San Pablo", "Ciudad Deportiva", "Av. Manuel Siurot (Montessori)",
|
||||||
};
|
"Santuario Nuestra Sra. de la Cinta", "Legión Española (O. Alta)", "Montevideo (Legión Española)",
|
||||||
|
"Orden Baja", "Zenobia (IPFD)", "Cruce Cementerio", "La Orden", "Avda. Santa Marta",
|
||||||
|
"Gómez de Avellaneda", "Urb. Santa Mª del Pilar (Verdeluz)", "Honduras (Saladillo)",
|
||||||
|
"Alanís de la Sierra", "Galaroza (H. Palomo)", "Jabugo", "Pérez Cubillas", "Jabugo",
|
||||||
|
"Isla Chica", "Las Delicias", "El Árbol", "Polideportivo Andrés Estrada", "Bomberos",
|
||||||
|
"San Sebastián (Bomberos)", "San Sebastián (Plaza los Litri)", "San Andrés",
|
||||||
|
"Plaza de la Merced (Universidad)", "Molino de la Vega", "Paseo de las Palmeras", "Zafra"
|
||||||
|
],
|
||||||
|
"Línea 141": ["Puente de Vallecas"],
|
||||||
|
"Línea T32": ["Profesor Raúl Vázquez"]
|
||||||
|
}), []);
|
||||||
|
|
||||||
|
// Estructura de líneas con ciudad
|
||||||
|
const datos = [
|
||||||
|
{ ciudad: "Huelva", linea: "Línea 1" },
|
||||||
|
{ ciudad: "Huelva", linea: "Línea 2" },
|
||||||
|
{ ciudad: "Huelva", linea: "Línea 3" },
|
||||||
|
{ ciudad: "Madrid", linea: "Línea 141" },
|
||||||
|
{ ciudad: "Madrid", linea: "Línea T32" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const ciudades = [
|
||||||
|
"Huelva",
|
||||||
|
"Madrid",
|
||||||
|
"Sevilla"
|
||||||
|
];
|
||||||
|
|
||||||
|
// Filtra las líneas por ciudad seleccionada
|
||||||
|
const lineasFiltradas = datos.filter(d => d.ciudad === ciudadSeleccionada);
|
||||||
|
|
||||||
|
// Busca las paradas de la línea seleccionada de forma segura
|
||||||
|
const paradasFiltradas = paradasPorLinea[lineaSeleccionada] || [];
|
||||||
|
|
||||||
const handleLineaChange = (event) => {
|
const handleLineaChange = (event) => {
|
||||||
setLineaSeleccionada(event.target.value);
|
setLineaSeleccionada(event.target.value);
|
||||||
setParadaSeleccionada('');
|
setParadaSeleccionada('');
|
||||||
|
// Recarga interna: fuerza el componente de paradas a "resetearse"
|
||||||
|
// Si usas un key en el select de paradas, cambiará el componente y limpiará el menú
|
||||||
|
setParadasKey(Math.random());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Key para forzar recarga del select de paradas
|
||||||
|
const [paradasKey, setParadasKey] = useState(0);
|
||||||
|
|
||||||
const handleParadaChange = (event) => {
|
const handleParadaChange = (event) => {
|
||||||
setParadaSeleccionada(event.target.value);
|
setParadaSeleccionada(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTipoParadaChange = (event) => {
|
|
||||||
setTipoParada(event.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleVolumeChange = (event) => {
|
const handleVolumeChange = (event) => {
|
||||||
setVolume(event.target.value);
|
setVolume(event.target.value);
|
||||||
|
// Aplica el volumen global a cualquier audio que esté sonando
|
||||||
if (audioRef.current) {
|
if (audioRef.current) {
|
||||||
audioRef.current.volume = event.target.value;
|
audioRef.current.volume = event.target.value;
|
||||||
}
|
}
|
||||||
@@ -71,6 +117,7 @@ function App() {
|
|||||||
} else if (lineaSeleccionada && paradaSeleccionada) {
|
} else if (lineaSeleccionada && paradaSeleccionada) {
|
||||||
const playAudio = (audioFile) => {
|
const playAudio = (audioFile) => {
|
||||||
const nuevoAudio = new Audio(audioFile);
|
const nuevoAudio = new Audio(audioFile);
|
||||||
|
nuevoAudio.volume = volume; // Aplica volumen global
|
||||||
nuevoAudio.play().catch(error => {
|
nuevoAudio.play().catch(error => {
|
||||||
console.error("Error al reproducir audio:", error);
|
console.error("Error al reproducir audio:", error);
|
||||||
});
|
});
|
||||||
@@ -111,35 +158,114 @@ function App() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const reproducirColision = () => {
|
const reproducirColision = () => {
|
||||||
const audioColision = new Audio('/audio/colision.wav');
|
const audioColision = new Audio('/audio/colision.wav');
|
||||||
|
audioColision.volume = volume; // Aplica volumen global
|
||||||
audioColision.play().catch(error => {
|
audioColision.play().catch(error => {
|
||||||
console.error("Error al reproducir audio:", error);
|
console.error("Error al reproducir audio:", error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const reproducirCanceladora = (audioNombre) => {
|
||||||
|
const audioCanceladora = new Audio(`/audio/${audioNombre}.mp3`);
|
||||||
|
audioCanceladora.volume = volume; // Aplica volumen global
|
||||||
|
audioCanceladora.play().catch(error => {
|
||||||
|
console.error("Error al reproducir audio:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const cargarAudios = () => {
|
// Elimina variables no usadas
|
||||||
const audioActual = new Audio(`/audio/parada_actual.wav`);
|
// const audioActual = new Audio(`/audio/parada_actual.wav`);
|
||||||
const audioSiguiente = new Audio(`/audio/parada_siguiente.wav`);
|
// const audioSiguiente = new Audio(`/audio/parada_siguiente.wav`);
|
||||||
|
|
||||||
for (const linea in datos) {
|
// Usar paradasPorLinea para evitar error de undefined
|
||||||
datos[linea].forEach(parada => {
|
Object.entries(paradasPorLinea).forEach(([linea, paradas]) => {
|
||||||
const lineaSinEspacios = linea.split(" ")[1] || linea.split(" ")[0];
|
paradas.forEach(parada => {
|
||||||
const audio = new Audio(`/audio/${lineaSinEspacios}-${parada.toLowerCase().replace(/ /g, "_")}.wav`);
|
const lineaSinEspacios = linea.split(" ")[1] || linea.split(" ")[0];
|
||||||
});
|
// Solo crea el objeto, no lo asignes a una variable no usada
|
||||||
}
|
new Audio(`/audio/${lineaSinEspacios}-${parada.toLowerCase().replace(/ /g, "_")}.wav`);
|
||||||
|
});
|
||||||
const audioVallecas = new Audio(`/audio/vallecas.wav`);
|
});
|
||||||
const audioColision = new Audio(`/audio/colision.m4a`);
|
}, [paradasPorLinea]);
|
||||||
};
|
|
||||||
|
|
||||||
cargarAudios();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
localStorage.setItem('theme', theme);
|
localStorage.setItem('theme', theme);
|
||||||
|
|
||||||
|
// Material 3 green-based color schemes (from your images)
|
||||||
|
const lightScheme = {
|
||||||
|
'--md-sys-color-primary': '#4C7A1F', // P-40
|
||||||
|
'--md-sys-color-on-primary': '#FFFFFF', // P-100
|
||||||
|
'--md-sys-color-primary-container': '#B6F397', // P-90
|
||||||
|
'--md-sys-color-on-primary-container': '#17360D', // P-10
|
||||||
|
'--md-sys-color-secondary': '#6A745F', // S-40
|
||||||
|
'--md-sys-color-on-secondary': '#FFFFFF', // S-100
|
||||||
|
'--md-sys-color-secondary-container': '#D7E2C7', // S-90
|
||||||
|
'--md-sys-color-on-secondary-container': '#23281B', // S-10
|
||||||
|
'--md-sys-color-tertiary': '#2B6A78', // T-40
|
||||||
|
'--md-sys-color-on-tertiary': '#FFFFFF', // T-100
|
||||||
|
'--md-sys-color-tertiary-container': '#B6EAF3', // T-90
|
||||||
|
'--md-sys-color-on-tertiary-container': '#102A2F', // T-10
|
||||||
|
'--md-sys-color-error': '#BA1A1A', // E-40
|
||||||
|
'--md-sys-color-on-error': '#FFFFFF', // E-100
|
||||||
|
'--md-sys-color-error-container': '#FFDAD6', // E-90
|
||||||
|
'--md-sys-color-on-error-container': '#410002', // E-10
|
||||||
|
'--md-sys-color-background': '#F7F9F3', // N-98
|
||||||
|
'--md-sys-color-on-background': '#1A1C18', // N-10
|
||||||
|
'--md-sys-color-surface': '#F7F9F3', // N-98
|
||||||
|
'--md-sys-color-on-surface': '#1A1C18', // N-10
|
||||||
|
'--md-sys-color-surface-variant': '#E1E3D6', // NV-80
|
||||||
|
'--md-sys-color-on-surface-variant': '#45483C', // NV-30
|
||||||
|
'--md-sys-color-outline': '#76786B', // NV-50
|
||||||
|
'--md-sys-color-outline-variant': '#C5C8B7', // NV-80
|
||||||
|
'--md-sys-color-surface-dim': '#E3E3DB', // N-87
|
||||||
|
'--md-sys-color-surface-bright': '#F7F9F3', // N-98
|
||||||
|
'--md-sys-color-surface-container-lowest': '#FFFFFF', // N-100
|
||||||
|
'--md-sys-color-surface-container-low': '#F1F3EB', // N-96
|
||||||
|
'--md-sys-color-surface-container': '#ECEEE6', // N-94
|
||||||
|
'--md-sys-color-surface-container-high': '#E7E9E1', // N-92
|
||||||
|
'--md-sys-color-surface-container-highest': '#E3E3DB', // N-90
|
||||||
|
};
|
||||||
|
|
||||||
|
const darkScheme = {
|
||||||
|
'--md-sys-color-primary': '#B6F397', // P-80
|
||||||
|
'--md-sys-color-on-primary': '#17360D', // P-20
|
||||||
|
'--md-sys-color-primary-container': '#2B5A1B', // P-30
|
||||||
|
'--md-sys-color-on-primary-container': '#D6FFD6', // P-90
|
||||||
|
'--md-sys-color-secondary': '#B6BFA8', // S-80
|
||||||
|
'--md-sys-color-on-secondary': '#23281B', // S-20
|
||||||
|
'--md-sys-color-secondary-container': '#3C4430', // S-30
|
||||||
|
'--md-sys-color-on-secondary-container': '#E7F3D7', // S-90
|
||||||
|
'--md-sys-color-tertiary': '#8FE6F3', // T-80
|
||||||
|
'--md-sys-color-on-tertiary': '#102A2F', // T-20
|
||||||
|
'--md-sys-color-tertiary-container': '#1B4A5A', // T-30
|
||||||
|
'--md-sys-color-on-tertiary-container': '#D6F6FF', // T-90
|
||||||
|
'--md-sys-color-error': '#FFDAD6', // E-80
|
||||||
|
'--md-sys-color-on-error': '#BA1A1A', // E-20
|
||||||
|
'--md-sys-color-error-container': '#93000A', // E-30
|
||||||
|
'--md-sys-color-on-error-container': '#FFDAD6', // E-90
|
||||||
|
'--md-sys-color-background': '#23281B', // N-6
|
||||||
|
'--md-sys-color-on-background': '#E3E3DB', // N-90
|
||||||
|
'--md-sys-color-surface': '#23281B', // N-6
|
||||||
|
'--md-sys-color-on-surface': '#E3E3DB', // N-90
|
||||||
|
'--md-sys-color-surface-variant': '#45483C', // NV-30
|
||||||
|
'--md-sys-color-on-surface-variant': '#C5C8B7', // NV-80
|
||||||
|
'--md-sys-color-outline': '#76786B', // NV-60
|
||||||
|
'--md-sys-color-outline-variant': '#45483C', // NV-30
|
||||||
|
'--md-sys-color-surface-dim': '#1A1C18', // N-4
|
||||||
|
'--md-sys-color-surface-bright': '#3C4430', // N-24
|
||||||
|
'--md-sys-color-surface-container-lowest': '#181A14', // N-4
|
||||||
|
'--md-sys-color-surface-container-low': '#23281B', // N-10
|
||||||
|
'--md-sys-color-surface-container': '#23281B', // N-12
|
||||||
|
'--md-sys-color-surface-container-high': '#2B2F23', // N-17
|
||||||
|
'--md-sys-color-surface-container-highest': '#353A2B', // N-22
|
||||||
|
};
|
||||||
|
|
||||||
|
const scheme = theme === 'dark' ? darkScheme : lightScheme;
|
||||||
|
for (const [key, value] of Object.entries(scheme)) {
|
||||||
|
document.body.style.setProperty(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
document.body.classList.toggle('dark-theme', theme === 'dark');
|
document.body.classList.toggle('dark-theme', theme === 'dark');
|
||||||
document.body.classList.toggle('light-theme', theme === 'light');
|
document.body.classList.toggle('light-theme', theme === 'light');
|
||||||
}, [theme]);
|
}, [theme]);
|
||||||
@@ -148,91 +274,172 @@ 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 mt-4">
|
<div
|
||||||
<h1 className="mb-4">Aplicación de Megafonía</h1>
|
style={{
|
||||||
|
maxWidth: 480,
|
||||||
|
margin: "2rem auto",
|
||||||
|
fontFamily: "'Roboto', Arial, Helvetica, sans-serif"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h1 style={{ marginBottom: "1.5rem" }}>Aplicación de Megafonía</h1>
|
||||||
|
|
||||||
<div className="card mb-4">
|
{/* Dropdown de ciudad */}
|
||||||
<div className="card-body">
|
<div style={{ marginBottom: "1.5rem" }}>
|
||||||
<div className="mb-3">
|
<label htmlFor="ciudad">Ciudad:</label>
|
||||||
<label htmlFor="linea" className="form-label">Línea:</label>
|
<md-filled-select
|
||||||
<select id="linea" value={lineaSeleccionada} onChange={handleLineaChange} className="form-select">
|
id="ciudad"
|
||||||
<option value="">Selecciona una línea</option>
|
value={ciudadSeleccionada}
|
||||||
{Object.keys(datos).map((linea) => (
|
onInput={e => {
|
||||||
<option key={linea} value={linea}>{linea}</option>
|
setCiudadSeleccionada(e.target.value);
|
||||||
|
setLineaSeleccionada('');
|
||||||
|
setParadaSeleccionada('');
|
||||||
|
setParadasKey(Math.random());
|
||||||
|
}}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
>
|
||||||
|
<md-select-option value="">
|
||||||
|
<div slot="headline">Selecciona una ciudad</div>
|
||||||
|
</md-select-option>
|
||||||
|
{ciudades.map((ciudad) => (
|
||||||
|
<md-select-option key={ciudad} value={ciudad}>
|
||||||
|
<div slot="headline">{ciudad}</div>
|
||||||
|
</md-select-option>
|
||||||
|
))}
|
||||||
|
</md-filled-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ border: "1px solid #ccc", borderRadius: 12, marginBottom: "1.5rem", boxShadow: "0 2px 4px #0001" }}>
|
||||||
|
<div style={{ padding: "1rem" }}>
|
||||||
|
<div style={{ marginBottom: "1.5rem" }}>
|
||||||
|
<label htmlFor="linea">Línea:</label>
|
||||||
|
<md-filled-select
|
||||||
|
id="linea"
|
||||||
|
value={lineaSeleccionada}
|
||||||
|
onInput={e => handleLineaChange({ target: { value: e.target.value } })}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
disabled={!ciudadSeleccionada}
|
||||||
|
>
|
||||||
|
<md-select-option value="">
|
||||||
|
<div slot="headline">Selecciona una línea</div>
|
||||||
|
</md-select-option>
|
||||||
|
{lineasFiltradas.map((l) => (
|
||||||
|
<md-select-option key={l.linea} value={l.linea}>
|
||||||
|
<div slot="headline">{l.linea}</div>
|
||||||
|
</md-select-option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</md-filled-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="parada" className="form-label">Parada:</label>
|
<label htmlFor="parada">Parada:</label>
|
||||||
<select id="parada" value={paradaSeleccionada} onChange={handleParadaChange} className="form-select">
|
<md-filled-select
|
||||||
<option value="">Selecciona una parada</option>
|
key={paradasKey}
|
||||||
{datos[lineaSeleccionada]?.map((parada) => (
|
id="parada"
|
||||||
<option key={parada} value={parada}>{parada}</option>
|
value={paradaSeleccionada}
|
||||||
|
onInput={e => handleParadaChange({ target: { value: e.target.value } })}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
disabled={!lineaSeleccionada}
|
||||||
|
>
|
||||||
|
<md-select-option value="">
|
||||||
|
<div slot="headline">Selecciona una parada</div>
|
||||||
|
</md-select-option>
|
||||||
|
{paradasFiltradas.map((parada) => (
|
||||||
|
<md-select-option key={parada} value={parada}>
|
||||||
|
<div slot="headline">{parada}</div>
|
||||||
|
</md-select-option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</md-filled-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="card mb-4">
|
<div style={{ border: "1px solid #ccc", borderRadius: 12, marginBottom: "1.5rem", boxShadow: "0 2px 4px #0001" }}>
|
||||||
<div className="card-body">hora_de_salida.wav
|
<div style={{ padding: "1rem" }}>
|
||||||
<div className="mb-3">
|
<div style={{ marginBottom: "1.5rem" }}>
|
||||||
<div className="d-flex flex-column">
|
<label htmlFor="tipoParada" style={{ marginBottom: 8, display: "block", fontWeight: 500 }}>
|
||||||
<label className="form-check-label">
|
Tipo de parada:
|
||||||
<input type="radio" value="actual" checked={tipoParada === 'actual'} onChange={handleTipoParadaChange} className="form-check-input me-2" />
|
</label>
|
||||||
|
<div
|
||||||
|
id="tipoParada"
|
||||||
|
style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}
|
||||||
|
>
|
||||||
|
<label style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }}>
|
||||||
|
<md-radio
|
||||||
|
name="tipoParada"
|
||||||
|
value="actual"
|
||||||
|
checked={tipoParada === "actual"}
|
||||||
|
onChange={e => setTipoParada(e.target.value)}
|
||||||
|
style={{ verticalAlign: "middle" }}
|
||||||
|
></md-radio>
|
||||||
Parada actual
|
Parada actual
|
||||||
</label>
|
</label>
|
||||||
<label className="form-check-label">
|
<label style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }}>
|
||||||
<input type="radio" value="siguiente" checked={tipoParada === 'siguiente'} onChange={handleTipoParadaChange} className="form-check-input me-2" />
|
<md-radio
|
||||||
|
name="tipoParada"
|
||||||
|
value="siguiente"
|
||||||
|
checked={tipoParada === "siguiente"}
|
||||||
|
onChange={e => setTipoParada(e.target.value)}
|
||||||
|
style={{ verticalAlign: "middle" }}
|
||||||
|
></md-radio>
|
||||||
Parada siguiente
|
Parada siguiente
|
||||||
</label>
|
</label>
|
||||||
<label className="form-check-label">
|
<label style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }}>
|
||||||
<input type="radio" value="noUsar" checked={tipoParada === 'noUsar'} onChange={handleTipoParadaChange} className="form-check-input me-2" />
|
<md-radio
|
||||||
No usar
|
name="tipoParada"
|
||||||
|
value="noUsar"
|
||||||
|
checked={tipoParada === "noUsar"}
|
||||||
|
onChange={e => setTipoParada(e.target.value)}
|
||||||
|
style={{ verticalAlign: "middle" }}
|
||||||
|
></md-radio>
|
||||||
|
No usar (para EMT Madrid)
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="volume" className="form-label">Volumen:</label>
|
<label htmlFor="volume">Volumen:</label>
|
||||||
<input type="range" id="volume" min="0" max="1" step="0.1" value={volume} onChange={handleVolumeChange} className="form-range" />
|
<md-slider
|
||||||
|
id="volume"
|
||||||
|
min={0}
|
||||||
|
max={1}
|
||||||
|
step={0.1}
|
||||||
|
value={volume}
|
||||||
|
onInput={e => handleVolumeChange({ target: { value: Number(e.target.value) } })}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
></md-slider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="d-grid gap-2">
|
<div style={{ display: "flex", flexDirection: "column", gap: "1rem", marginBottom: "1.5rem" }}>
|
||||||
<button onClick={reproducirAudio} className="btn btn-primary" disabled={!lineaSeleccionada || !paradaSeleccionada}>
|
<md-filled-button
|
||||||
|
onClick={reproducirAudio}
|
||||||
|
disabled={!lineaSeleccionada || !paradaSeleccionada}
|
||||||
|
>
|
||||||
{playing ? "Detener" : "Reproducir"}
|
{playing ? "Detener" : "Reproducir"}
|
||||||
</button>
|
</md-filled-button>
|
||||||
<button onClick={toggleTheme} className="btn btn-secondary">
|
<md-outlined-button onClick={toggleTheme}>
|
||||||
Cambiar tema a {theme === 'light' ? 'oscuro' : 'claro'}
|
Cambiar tema a {theme === 'light' ? 'oscuro' : 'claro'}
|
||||||
</button>
|
</md-outlined-button>
|
||||||
<button onClick={reproducirColision} className="btn btn-danger">Anti-Colisión</button>
|
<md-filled-button onClick={reproducirColision} style={{ background: "#d32f2f", color: "#fff" }}>
|
||||||
|
Anti-Colisión
|
||||||
|
</md-filled-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style={{ border: "1px solid #ccc", borderRadius: 12, marginBottom: "1.5rem", boxShadow: "0 2px 4px #0001" }}>
|
||||||
<div className="card mb-4">
|
<div style={{ padding: "1rem" }}>
|
||||||
<div className="card-body">
|
<h5>Canceladora</h5>
|
||||||
<h5 className="card-title">Canceladora</h5>
|
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
|
||||||
<div className="d-grid gap-2">
|
<md-filled-button onClick={() => reproducirCanceladora('hora_de_salida')}>
|
||||||
<button onClick={() => reproducirCanceladora('hora_de_salida')} className="btn btn-primary">
|
|
||||||
Hora de Salida
|
Hora de Salida
|
||||||
</button>
|
</md-filled-button>
|
||||||
<button onClick={() => reproducirCanceladora('atencion_a_su_saldo')} className="btn btn-primary">
|
<md-filled-button onClick={() => reproducirCanceladora('atencion_a_su_saldo')}>
|
||||||
Atención a su Saldo
|
Atención a su Saldo
|
||||||
</button>
|
</md-filled-button>
|
||||||
<button onClick={() => reproducirCanceladora('saldo_insuficiente')} className="btn btn-primary">
|
<md-filled-button onClick={() => reproducirCanceladora('saldo_insuficiente')}>
|
||||||
Saldo Insuficiente
|
Saldo Insuficiente
|
||||||
</button>
|
</md-filled-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user