- panel de colores puestos en la configuracion

- oscurecido el tb6.
- ordenado el bsucador
- añadido switch de parametros en historial compartido
This commit is contained in:
2026-09-01 08:07:37 +02:00
parent b52cea97b1
commit 402ce90a95
9 changed files with 359 additions and 50 deletions

View File

@@ -55,6 +55,9 @@ public partial class PlanificadorRutas : ComponentBase
private const double UmbralPendienteSubidaRutaPorDefecto = 2.0; private const double UmbralPendienteSubidaRutaPorDefecto = 2.0;
private const double UmbralPendienteSubidaMediaRutaPorDefecto = 5.0; private const double UmbralPendienteSubidaMediaRutaPorDefecto = 5.0;
private const double UmbralPendienteSubidaFuerteRutaPorDefecto = 10.0; private const double UmbralPendienteSubidaFuerteRutaPorDefecto = 10.0;
private const string ColorPendienteSubidaSuaveRutaPorDefecto = "#d946ef";
private const string ColorPendienteSubidaMediaRutaPorDefecto = "#4c1d95";
private const string ColorPendienteSubidaFuerteRutaPorDefecto = "#000000";
private const double UmbralPendienteBajadaRutaPorDefecto = 5.0; private const double UmbralPendienteBajadaRutaPorDefecto = 5.0;
private const double UmbralAlturaAlertaPendienteRutaMetrosPorDefecto = 6.0; private const double UmbralAlturaAlertaPendienteRutaMetrosPorDefecto = 6.0;
private const double MetrosPorPiso = 3.0; private const double MetrosPorPiso = 3.0;
@@ -372,6 +375,9 @@ public partial class PlanificadorRutas : ComponentBase
private double _umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto; private double _umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto;
private double _umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto; private double _umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto;
private double _umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto; private double _umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto;
private string _colorPendienteSubidaSuaveRuta = ColorPendienteSubidaSuaveRutaPorDefecto;
private string _colorPendienteSubidaMediaRuta = ColorPendienteSubidaMediaRutaPorDefecto;
private string _colorPendienteSubidaFuerteRuta = ColorPendienteSubidaFuerteRutaPorDefecto;
private double _umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto; private double _umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto;
private double _umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto; private double _umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto;
private double _alturaPendientePositivaSignificativaRutaMetros = 0.0; private double _alturaPendientePositivaSignificativaRutaMetros = 0.0;

View File

@@ -160,12 +160,22 @@ public partial class PlanificadorRutas
.Concat(lugares.Select(CrearSugerenciaLugar)) .Concat(lugares.Select(CrearSugerenciaLugar))
.GroupBy(sugerencia => NormalizarClaveSugerencia(sugerencia), StringComparer.Ordinal) .GroupBy(sugerencia => NormalizarClaveSugerencia(sugerencia), StringComparer.Ordinal)
.Select(grupo => grupo.First()) .Select(grupo => grupo.First())
.OrderBy(sugerencia => sugerencia.Titulo, StringComparer.CurrentCultureIgnoreCase) .OrderBy(sugerencia => OrdenTipoSugerencia(sugerencia.Tipo))
.ThenBy(sugerencia => sugerencia.Titulo, StringComparer.CurrentCultureIgnoreCase)
.ThenBy(sugerencia => sugerencia.Subtitulo, StringComparer.CurrentCultureIgnoreCase) .ThenBy(sugerencia => sugerencia.Subtitulo, StringComparer.CurrentCultureIgnoreCase)
.Take(Math.Clamp(maxResultados, 1, 50)) .Take(Math.Clamp(maxResultados, 1, 50))
.ToList(); .ToList();
} }
private static int OrdenTipoSugerencia(string? tipo)
=> tipo switch
{
"Parada" => 0,
"Direccion" => 1,
"Lugar" => 2,
_ => 3
};
private IReadOnlyList<SugerenciaBusquedaMapa> BuscarSugerenciasParadas(string texto, int maxResultados) private IReadOnlyList<SugerenciaBusquedaMapa> BuscarSugerenciasParadas(string texto, int maxResultados)
{ {
var consulta = NormalizeForSearch(texto); var consulta = NormalizeForSearch(texto);

View File

@@ -2,6 +2,7 @@
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using RutasDBUS.Modelos.Historial; using RutasDBUS.Modelos.Historial;
@@ -40,8 +41,11 @@ public partial class PlanificadorRutas
private bool _refrescandoHistorialCompartido = false; private bool _refrescandoHistorialCompartido = false;
private bool _omitirRegistroHistorialEnSiguienteCalculo = false; private bool _omitirRegistroHistorialEnSiguienteCalculo = false;
private bool _aplicandoRegistroHistorial = false; private bool _aplicandoRegistroHistorial = false;
private bool _usarParametrosActualesHistorial = false;
private bool _cambiandoParametrosHistorial = false;
private string? _historialCompartidoPendienteEliminarId; private string? _historialCompartidoPendienteEliminarId;
private ConfiguracionLocalPlanificador? _configuracionTemporalPreviaHistorial; private ConfiguracionLocalPlanificador? _configuracionTemporalPreviaHistorial;
private ConfiguracionLocalPlanificador? _configuracionParametrosActualesHistorial;
private Task<bool>? _tareaCargaHistorialLocal; private Task<bool>? _tareaCargaHistorialLocal;
private bool _historialLocalCargado = false; private bool _historialLocalCargado = false;
private bool _historialLocalCargando = false; private bool _historialLocalCargando = false;
@@ -837,6 +841,68 @@ public partial class PlanificadorRutas
_historialCompartidoSeleccionadoId = string.Empty; _historialCompartidoSeleccionadoId = string.Empty;
} }
private RegistroHistorialRuta? ObtenerRegistroHistorialSeleccionado()
{
if (!string.IsNullOrWhiteSpace(_historialLocalSeleccionadoId))
return _historialLocal.FirstOrDefault(x => x.Id == _historialLocalSeleccionadoId);
if (!string.IsNullOrWhiteSpace(_historialCompartidoSeleccionadoId))
return _historialCompartido.FirstOrDefault(x => x.Id == _historialCompartidoSeleccionadoId);
return null;
}
private async Task CambiarUsoParametrosActualesHistorialAsync(ChangeEventArgs e)
{
if (_cambiandoParametrosHistorial)
return;
var usarParametrosActuales = e.Value switch
{
bool valor => valor,
string texto when bool.TryParse(texto, out var valor) => valor,
_ => !_usarParametrosActualesHistorial
};
if (usarParametrosActuales == _usarParametrosActualesHistorial)
return;
_cambiandoParametrosHistorial = true;
try
{
var itemSeleccionado = ObtenerRegistroHistorialSeleccionado();
if (!usarParametrosActuales && _usarParametrosActualesHistorial)
_configuracionParametrosActualesHistorial = CrearConfiguracionLocal();
_usarParametrosActualesHistorial = usarParametrosActuales;
if (usarParametrosActuales && _configuracionParametrosActualesHistorial is not null)
AplicarConfiguracionLocal(_configuracionParametrosActualesHistorial);
if (itemSeleccionado is null)
return;
await AplicarRegistroHistorialAsync(itemSeleccionado);
MostrarMensajeHistorial(
usarParametrosActuales
? "Ruta recalculada con los parámetros actuales."
: "Ruta recalculada con los parámetros guardados.");
}
catch (Exception ex)
{
RegistrarErrorHistorialLocal(
"cambio del modo de parámetros del historial",
ex);
MostrarMensajeHistorial(
"No he podido recalcular la ruta con esos parámetros.",
esError: true);
}
finally
{
_cambiandoParametrosHistorial = false;
}
}
private bool PrepararDerivacionHistorialParaRecalculo() private bool PrepararDerivacionHistorialParaRecalculo()
{ {
var procedeDeHistorial = _tipoReferenciaHistorial != TipoReferenciaHistorial.Ninguna && var procedeDeHistorial = _tipoReferenciaHistorial != TipoReferenciaHistorial.Ninguna &&
@@ -1348,6 +1414,8 @@ public partial class PlanificadorRutas
_coordenadasOrigen = new[] { item.OrigenLatitud, item.OrigenLongitud }; _coordenadasOrigen = new[] { item.OrigenLatitud, item.OrigenLongitud };
_coordenadasDestino = new[] { item.DestinoLatitud, item.DestinoLongitud }; _coordenadasDestino = new[] { item.DestinoLatitud, item.DestinoLongitud };
if (!_usarParametrosActualesHistorial)
{
_usarHorariosTeoricos = item.UsarHorariosTeoricos; _usarHorariosTeoricos = item.UsarHorariosTeoricos;
_usarHoraSimulada = item.UsarHoraSimulada; _usarHoraSimulada = item.UsarHoraSimulada;
@@ -1375,6 +1443,8 @@ public partial class PlanificadorRutas
_lineasPermitidas.Clear(); _lineasPermitidas.Clear();
foreach (var linea in NormalizarLineasHistorial(item.LineasPermitidas)) foreach (var linea in NormalizarLineasHistorial(item.LineasPermitidas))
_lineasPermitidas.Add(linea); _lineasPermitidas.Add(linea);
}
_busFilteredCache.Clear(); _busFilteredCache.Clear();
SincronizarSegundosPorParadaConHorarios(); SincronizarSegundosPorParadaConHorarios();
@@ -1410,15 +1480,19 @@ public partial class PlanificadorRutas
return; return;
_configuracionTemporalPreviaHistorial = CrearConfiguracionLocal(); _configuracionTemporalPreviaHistorial = CrearConfiguracionLocal();
_configuracionParametrosActualesHistorial = CrearConfiguracionLocal();
} }
private async Task RestaurarConfiguracionTemporalHistorialAsync() private async Task RestaurarConfiguracionTemporalHistorialAsync()
{ {
var configuracionPrevia = _configuracionTemporalPreviaHistorial; var configuracionPrevia = _configuracionTemporalPreviaHistorial;
_configuracionTemporalPreviaHistorial = null;
_configuracionParametrosActualesHistorial = null;
_usarParametrosActualesHistorial = false;
if (configuracionPrevia is null) if (configuracionPrevia is null)
return; return;
_configuracionTemporalPreviaHistorial = null;
AplicarConfiguracionLocal(configuracionPrevia); AplicarConfiguracionLocal(configuracionPrevia);
StopClock(); StopClock();

View File

@@ -1202,7 +1202,7 @@ public partial class PlanificadorRutas : ComponentBase
private bool _elevPopupMinimizado = false; private bool _elevPopupMinimizado = false;
private const string _versionApp = "(v-20260828a)"; private const string _versionApp = "(v-20260831a)";
private double? _paradaElevIdee; private double? _paradaElevIdee;

View File

@@ -51,6 +51,9 @@ public partial class PlanificadorRutas
public double? UmbralPendienteSubidaRuta { get; set; } public double? UmbralPendienteSubidaRuta { get; set; }
public double? UmbralPendienteSubidaMediaRuta { get; set; } public double? UmbralPendienteSubidaMediaRuta { get; set; }
public double? UmbralPendienteSubidaFuerteRuta { get; set; } public double? UmbralPendienteSubidaFuerteRuta { get; set; }
public string? ColorPendienteSubidaSuaveRuta { get; set; }
public string? ColorPendienteSubidaMediaRuta { get; set; }
public string? ColorPendienteSubidaFuerteRuta { get; set; }
public double? UmbralPendienteBajadaRuta { get; set; } public double? UmbralPendienteBajadaRuta { get; set; }
public double? UmbralAlturaAlertaPendienteRutaMetros { get; set; } public double? UmbralAlturaAlertaPendienteRutaMetros { get; set; }
// Compatibilidad con configuraciones guardadas cuando el umbral se expresaba en pisos. // Compatibilidad con configuraciones guardadas cuando el umbral se expresaba en pisos.
@@ -171,6 +174,9 @@ public partial class PlanificadorRutas
UmbralPendienteSubidaRuta = _umbralPendienteSubidaRuta, UmbralPendienteSubidaRuta = _umbralPendienteSubidaRuta,
UmbralPendienteSubidaMediaRuta = _umbralPendienteSubidaMediaRuta, UmbralPendienteSubidaMediaRuta = _umbralPendienteSubidaMediaRuta,
UmbralPendienteSubidaFuerteRuta = _umbralPendienteSubidaFuerteRuta, UmbralPendienteSubidaFuerteRuta = _umbralPendienteSubidaFuerteRuta,
ColorPendienteSubidaSuaveRuta = _colorPendienteSubidaSuaveRuta,
ColorPendienteSubidaMediaRuta = _colorPendienteSubidaMediaRuta,
ColorPendienteSubidaFuerteRuta = _colorPendienteSubidaFuerteRuta,
UmbralPendienteBajadaRuta = _umbralPendienteBajadaRuta, UmbralPendienteBajadaRuta = _umbralPendienteBajadaRuta,
UmbralAlturaAlertaPendienteRutaMetros = _umbralAlturaAlertaPendienteRutaMetros, UmbralAlturaAlertaPendienteRutaMetros = _umbralAlturaAlertaPendienteRutaMetros,
VelocidadPieKmH = _velocidadPieKmH, VelocidadPieKmH = _velocidadPieKmH,
@@ -276,6 +282,15 @@ public partial class PlanificadorRutas
double.IsFinite(umbralSubidaFuerte) double.IsFinite(umbralSubidaFuerte)
? NormalizarUmbralPendienteRuta(umbralSubidaFuerte) ? NormalizarUmbralPendienteRuta(umbralSubidaFuerte)
: UmbralPendienteSubidaFuerteRutaPorDefecto; : UmbralPendienteSubidaFuerteRutaPorDefecto;
_colorPendienteSubidaSuaveRuta = NormalizarColorHexRuta(
config.ColorPendienteSubidaSuaveRuta,
ColorPendienteSubidaSuaveRutaPorDefecto);
_colorPendienteSubidaMediaRuta = NormalizarColorHexRuta(
config.ColorPendienteSubidaMediaRuta,
ColorPendienteSubidaMediaRutaPorDefecto);
_colorPendienteSubidaFuerteRuta = NormalizarColorHexRuta(
config.ColorPendienteSubidaFuerteRuta,
ColorPendienteSubidaFuerteRutaPorDefecto);
NormalizarOrdenUmbralesColorSubidaRuta(); NormalizarOrdenUmbralesColorSubidaRuta();
if (config.UmbralPendienteBajadaRuta is { } umbralBajada && double.IsFinite(umbralBajada)) if (config.UmbralPendienteBajadaRuta is { } umbralBajada && double.IsFinite(umbralBajada))
_umbralPendienteBajadaRuta = _umbralPendienteBajadaRuta =
@@ -408,6 +423,9 @@ public partial class PlanificadorRutas
_umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto; _umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto;
_umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto; _umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto;
_umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto; _umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto;
_colorPendienteSubidaSuaveRuta = ColorPendienteSubidaSuaveRutaPorDefecto;
_colorPendienteSubidaMediaRuta = ColorPendienteSubidaMediaRutaPorDefecto;
_colorPendienteSubidaFuerteRuta = ColorPendienteSubidaFuerteRutaPorDefecto;
_umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto; _umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto;
_umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto; _umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto;
_velocidadPieKmH = 3.6; _velocidadPieKmH = 3.6;
@@ -463,6 +481,9 @@ public partial class PlanificadorRutas
_umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto; _umbralPendienteSubidaRuta = UmbralPendienteSubidaRutaPorDefecto;
_umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto; _umbralPendienteSubidaMediaRuta = UmbralPendienteSubidaMediaRutaPorDefecto;
_umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto; _umbralPendienteSubidaFuerteRuta = UmbralPendienteSubidaFuerteRutaPorDefecto;
_colorPendienteSubidaSuaveRuta = ColorPendienteSubidaSuaveRutaPorDefecto;
_colorPendienteSubidaMediaRuta = ColorPendienteSubidaMediaRutaPorDefecto;
_colorPendienteSubidaFuerteRuta = ColorPendienteSubidaFuerteRutaPorDefecto;
_umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto; _umbralPendienteBajadaRuta = UmbralPendienteBajadaRutaPorDefecto;
_umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto; _umbralAlturaAlertaPendienteRutaMetros = UmbralAlturaAlertaPendienteRutaMetrosPorDefecto;
_velocidadPieKmH = 3.6; _velocidadPieKmH = 3.6;

View File

@@ -134,6 +134,47 @@ public partial class PlanificadorRutas : ComponentBase
StateHasChanged(); StateHasChanged();
} }
private enum NivelColorSubidaRuta
{
Suave,
Media,
Fuerte
}
private async Task CambiarColorPendienteSubidaRutaAsync(
ChangeEventArgs e,
NivelColorSubidaRuta nivel)
{
var (actual, porDefecto) = nivel switch
{
NivelColorSubidaRuta.Media =>
(_colorPendienteSubidaMediaRuta, ColorPendienteSubidaMediaRutaPorDefecto),
NivelColorSubidaRuta.Fuerte =>
(_colorPendienteSubidaFuerteRuta, ColorPendienteSubidaFuerteRutaPorDefecto),
_ =>
(_colorPendienteSubidaSuaveRuta, ColorPendienteSubidaSuaveRutaPorDefecto)
};
var nuevo = NormalizarColorHexRuta(
Convert.ToString(e.Value, CultureInfo.InvariantCulture),
NormalizarColorHexRuta(actual, porDefecto));
switch (nivel)
{
case NivelColorSubidaRuta.Media:
_colorPendienteSubidaMediaRuta = nuevo;
break;
case NivelColorSubidaRuta.Fuerte:
_colorPendienteSubidaFuerteRuta = nuevo;
break;
default:
_colorPendienteSubidaSuaveRuta = nuevo;
break;
}
await PersistirConfiguracionAsync();
StateHasChanged();
}
private async Task RecalcularRankingTrasCambioEsfuerzoPendienteAsync(bool forzarRepintado = false) private async Task RecalcularRankingTrasCambioEsfuerzoPendienteAsync(bool forzarRepintado = false)
{ {
if (_opcionesRuta.Count == 0) if (_opcionesRuta.Count == 0)
@@ -244,6 +285,32 @@ public partial class PlanificadorRutas : ComponentBase
100.0); 100.0);
} }
private static string NormalizarColorHexRuta(string? valor, string porDefecto)
{
var color = valor?.Trim();
if (EsColorHexRutaValido(color))
return color!.ToLowerInvariant();
var respaldo = porDefecto?.Trim();
return EsColorHexRutaValido(respaldo)
? respaldo!.ToLowerInvariant()
: "#000000";
}
private static bool EsColorHexRutaValido(string? color)
{
if (color is null || color.Length != 7 || color[0] != '#')
return false;
for (var i = 1; i < color.Length; i++)
{
if (!Uri.IsHexDigit(color[i]))
return false;
}
return true;
}
private static double ParseUmbralAlturaAlertaPendienteRutaMetros(object? valor, double actual) private static double ParseUmbralAlturaAlertaPendienteRutaMetros(object? valor, double actual)
{ {
var texto = Convert.ToString(valor, CultureInfo.InvariantCulture)?.Replace(',', '.'); var texto = Convert.ToString(valor, CultureInfo.InvariantCulture)?.Replace(',', '.');
@@ -473,13 +540,25 @@ public partial class PlanificadorRutas : ComponentBase
100.0); 100.0);
if (pendientePorcentaje.Value >= umbralSubidaFuerte) if (pendientePorcentaje.Value >= umbralSubidaFuerte)
return ("subida-fuerte", "#000000"); return (
"subida-fuerte",
NormalizarColorHexRuta(
_colorPendienteSubidaFuerteRuta,
ColorPendienteSubidaFuerteRutaPorDefecto));
if (pendientePorcentaje.Value >= umbralSubidaMedia) if (pendientePorcentaje.Value >= umbralSubidaMedia)
return ("subida-media", "#4c1d95"); return (
"subida-media",
NormalizarColorHexRuta(
_colorPendienteSubidaMediaRuta,
ColorPendienteSubidaMediaRutaPorDefecto));
if (pendientePorcentaje.Value >= umbralSubida) if (pendientePorcentaje.Value >= umbralSubida)
return ("subida-suave", "#d946ef"); return (
"subida-suave",
NormalizarColorHexRuta(
_colorPendienteSubidaSuaveRuta,
ColorPendienteSubidaSuaveRutaPorDefecto));
if (pendientePorcentaje.Value <= -umbralBajada) if (pendientePorcentaje.Value <= -umbralBajada)
return ("bajada", "#2563eb"); return ("bajada", "#2563eb");

View File

@@ -1083,6 +1083,18 @@
</div> </div>
<div class="history-panel-body"> <div class="history-panel-body">
<label class="history-parameters-toggle @(_usarParametrosActualesHistorial ? "history-parameters-toggle--active" : "")"
title="Recalcular las rutas del historial con la configuración actual">
<span class="history-parameters-toggle__label">Usar parámetros actuales</span>
<input type="checkbox"
checked="@_usarParametrosActualesHistorial"
disabled="@(_aplicandoRegistroHistorial || _cambiandoParametrosHistorial)"
@onchange="CambiarUsoParametrosActualesHistorialAsync" />
<span class="history-parameters-toggle__track" aria-hidden="true">
<span class="history-parameters-toggle__thumb"></span>
</span>
</label>
<div class="history-section"> <div class="history-section">
<label class="history-section-label">Personal:</label> <label class="history-section-label">Personal:</label>
@if (_historialLocalCargando) @if (_historialLocalCargando)
@@ -1830,44 +1842,65 @@
</select> </select>
</label> </label>
<label class="pendientes-config-modal__field"> <div class="pendientes-config-modal__field">
<span class="pendientes-config-modal__threshold-label"> <span class="pendientes-config-modal__threshold-label">
<span class="pendientes-config-modal__swatch pendientes-config-modal__swatch--suave" aria-hidden="true"></span> <input type="color"
Umbral Subida (%) class="pendientes-config-modal__swatch"
value="@_colorPendienteSubidaSuaveRuta"
title="Elegir color de subida"
aria-label="Elegir color de subida"
disabled="@_pintandoElevacionesRuta"
@onchange="@(e => CambiarColorPendienteSubidaRutaAsync(e, NivelColorSubidaRuta.Suave))" />
<span>Umbral Subida (%)</span>
</span> </span>
<input type="text" <input type="text"
class="config-input" class="config-input"
inputmode="decimal" inputmode="decimal"
aria-label="Umbral Subida (%)"
value="@_umbralPendienteSubidaRuta.ToString("0.#", CultureInfo.InvariantCulture)" value="@_umbralPendienteSubidaRuta.ToString("0.#", CultureInfo.InvariantCulture)"
disabled="@_pintandoElevacionesRuta" disabled="@_pintandoElevacionesRuta"
@onchange="@(e => CambiarUmbralElevacionRutaAsync(e, true))" /> @onchange="@(e => CambiarUmbralElevacionRutaAsync(e, true))" />
</label> </div>
<label class="pendientes-config-modal__field"> <div class="pendientes-config-modal__field">
<span class="pendientes-config-modal__threshold-label"> <span class="pendientes-config-modal__threshold-label">
<span class="pendientes-config-modal__swatch pendientes-config-modal__swatch--media" aria-hidden="true"></span> <input type="color"
Subida Media (%) class="pendientes-config-modal__swatch"
value="@_colorPendienteSubidaMediaRuta"
title="Elegir color de subida media"
aria-label="Elegir color de subida media"
disabled="@_pintandoElevacionesRuta"
@onchange="@(e => CambiarColorPendienteSubidaRutaAsync(e, NivelColorSubidaRuta.Media))" />
<span>Subida Media (%)</span>
</span> </span>
<input type="text" <input type="text"
class="config-input" class="config-input"
inputmode="decimal" inputmode="decimal"
aria-label="Subida Media (%)"
value="@_umbralPendienteSubidaMediaRuta.ToString("0.#", CultureInfo.InvariantCulture)" value="@_umbralPendienteSubidaMediaRuta.ToString("0.#", CultureInfo.InvariantCulture)"
disabled="@_pintandoElevacionesRuta" disabled="@_pintandoElevacionesRuta"
@onchange="@(e => CambiarUmbralColorSubidaRutaAsync(e, false))" /> @onchange="@(e => CambiarUmbralColorSubidaRutaAsync(e, false))" />
</label> </div>
<label class="pendientes-config-modal__field"> <div class="pendientes-config-modal__field">
<span class="pendientes-config-modal__threshold-label"> <span class="pendientes-config-modal__threshold-label">
<span class="pendientes-config-modal__swatch pendientes-config-modal__swatch--fuerte" aria-hidden="true"></span> <input type="color"
Subida Fuerte (%) class="pendientes-config-modal__swatch"
value="@_colorPendienteSubidaFuerteRuta"
title="Elegir color de subida fuerte"
aria-label="Elegir color de subida fuerte"
disabled="@_pintandoElevacionesRuta"
@onchange="@(e => CambiarColorPendienteSubidaRutaAsync(e, NivelColorSubidaRuta.Fuerte))" />
<span>Subida Fuerte (%)</span>
</span> </span>
<input type="text" <input type="text"
class="config-input" class="config-input"
inputmode="decimal" inputmode="decimal"
aria-label="Subida Fuerte (%)"
value="@_umbralPendienteSubidaFuerteRuta.ToString("0.#", CultureInfo.InvariantCulture)" value="@_umbralPendienteSubidaFuerteRuta.ToString("0.#", CultureInfo.InvariantCulture)"
disabled="@_pintandoElevacionesRuta" disabled="@_pintandoElevacionesRuta"
@onchange="@(e => CambiarUmbralColorSubidaRutaAsync(e, true))" /> @onchange="@(e => CambiarUmbralColorSubidaRutaAsync(e, true))" />
</label> </div>
<label class="pendientes-config-modal__field"> <label class="pendientes-config-modal__field">
<span>Umbral Bajada (%)</span> <span>Umbral Bajada (%)</span>

View File

@@ -10,6 +10,7 @@ public class RedBusServicio : IRedBusServicio
{ {
private const string ColorVisualLinea16Argb = "FF5AAED6"; private const string ColorVisualLinea16Argb = "FF5AAED6";
private const string ColorVisualLinea40Argb = "FF9A7B00"; private const string ColorVisualLinea40Argb = "FF9A7B00";
private const string ColorVisualLineaTb6Argb = "FF607A38";
private readonly OpcionesRedBus _opciones; private readonly OpcionesRedBus _opciones;
private readonly ILogger<RedBusServicio> _logger; private readonly ILogger<RedBusServicio> _logger;
private readonly IServicioArchivoImportacionDbus _archiveService; private readonly IServicioArchivoImportacionDbus _archiveService;
@@ -148,6 +149,9 @@ public class RedBusServicio : IRedBusServicio
linea.ColorArgb = ColorVisualLinea16Argb; linea.ColorArgb = ColorVisualLinea16Argb;
else if (string.Equals(linea.Codigo, "40", StringComparison.OrdinalIgnoreCase)) else if (string.Equals(linea.Codigo, "40", StringComparison.OrdinalIgnoreCase))
linea.ColorArgb = ColorVisualLinea40Argb; linea.ColorArgb = ColorVisualLinea40Argb;
else if (string.Equals(linea.Codigo, "TB6", StringComparison.OrdinalIgnoreCase) ||
string.Equals(linea.IdRuta, "6", StringComparison.OrdinalIgnoreCase))
linea.ColorArgb = ColorVisualLineaTb6Argb;
} }
/// <summary> /// <summary>

View File

@@ -1222,6 +1222,72 @@ html, body {
gap: .75rem; gap: .75rem;
} }
.history-parameters-toggle {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: .65rem;
min-height: 30px;
padding-bottom: .6rem;
border-bottom: 1px solid rgba(148,163,184,.2);
color: #cbd5e1;
cursor: pointer;
user-select: none;
}
.history-parameters-toggle__label {
min-width: 0;
font-size: .78rem;
font-weight: 700;
}
.history-parameters-toggle input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.history-parameters-toggle__track {
position: relative;
width: 36px;
height: 20px;
border: 1px solid rgba(148,163,184,.55);
border-radius: 999px;
background: rgba(2,6,23,.72);
transition: background .15s ease, border-color .15s ease;
}
.history-parameters-toggle__thumb {
position: absolute;
top: 2px;
left: 2px;
width: 14px;
height: 14px;
border-radius: 999px;
background: #94a3b8;
box-shadow: 0 1px 4px rgba(0,0,0,.35);
transition: transform .15s ease, background .15s ease;
}
.history-parameters-toggle--active {
color: #f8fafc;
}
.history-parameters-toggle--active .history-parameters-toggle__track {
border-color: rgba(59,130,246,.85);
background: rgba(37,99,235,.82);
}
.history-parameters-toggle--active .history-parameters-toggle__thumb {
transform: translateX(16px);
background: #f8fafc;
}
.history-parameters-toggle:has(input:disabled) {
cursor: default;
opacity: .6;
}
.history-section { .history-section {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -2217,24 +2283,40 @@ html, body {
} }
.pendientes-config-modal__swatch { .pendientes-config-modal__swatch {
width: .68rem; width: 1.25rem;
height: .68rem; height: 1.25rem;
flex: 0 0 .68rem; flex: 0 0 1.25rem;
padding: 0;
border: 1px solid rgba(226, 232, 240, .7); border: 1px solid rgba(226, 232, 240, .7);
border-radius: 2px; border-radius: 2px;
background: transparent;
box-sizing: border-box; box-sizing: border-box;
cursor: pointer;
overflow: hidden;
} }
.pendientes-config-modal__swatch--suave { .pendientes-config-modal__swatch::-webkit-color-swatch-wrapper {
background: #d946ef; padding: 0;
} }
.pendientes-config-modal__swatch--media { .pendientes-config-modal__swatch::-webkit-color-swatch {
background: #4c1d95; border: 0;
} }
.pendientes-config-modal__swatch--fuerte { .pendientes-config-modal__swatch::-moz-color-swatch {
background: #000; border: 0;
}
.pendientes-config-modal__swatch:hover,
.pendientes-config-modal__swatch:focus-visible {
border-color: #f8fafc;
outline: 2px solid rgba(96, 165, 250, .72);
outline-offset: 2px;
}
.pendientes-config-modal__swatch:disabled {
cursor: default;
opacity: .55;
} }
.config-row-map-opacity { .config-row-map-opacity {