Enhance routine run UI with selectable items, check icons, and weight select dropdown
This commit is contained in:
@@ -113,15 +113,20 @@
|
|||||||
<div class="list">
|
<div class="list">
|
||||||
@foreach (var entry in RunEntries)
|
@foreach (var entry in RunEntries)
|
||||||
{
|
{
|
||||||
<div class="list-item @(entry.Completed ? "done" : string.Empty)">
|
<div class="list-item selectable @(entry.Completed ? "selected" : string.Empty)" @onclick="() => ToggleRunCompleted(entry.ExerciseId)">
|
||||||
<label class="checkbox-row">
|
<div class="item-title">@GetExerciseName(entry.ExerciseId)</div>
|
||||||
<input type="checkbox" checked="@entry.Completed" @onchange="() => ToggleRunCompleted(entry.ExerciseId)" />
|
<div class="item-actions" @onclick:stopPropagation="true">
|
||||||
<span>@GetExerciseName(entry.ExerciseId)</span>
|
<div class="input-unit">
|
||||||
</label>
|
<select class="input input-sm" @bind="entry.Weight">
|
||||||
<div class="input-unit">
|
@foreach (var w in WeightOptions)
|
||||||
<input class="input input-sm" type="number" step="0.5" @bind="entry.Weight" @bind:event="oninput" />
|
{
|
||||||
<span class="unit">kg</span>
|
<option value="@w">@w</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
<span class="unit">kg</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="check-icon @(entry.Completed ? "visible" : string.Empty)" aria-hidden="true">✓</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,6 +32,42 @@ public partial class Routines
|
|||||||
private RoutineDto? ActiveRun { get; set; }
|
private RoutineDto? ActiveRun { get; set; }
|
||||||
private List<RoutineRunEntryDto> RunEntries { get; set; } = new();
|
private List<RoutineRunEntryDto> RunEntries { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Available weight options for the routine run select input.
|
||||||
|
/// 10–40 kg in 2.5 kg steps, then 40–100 kg in 5 kg steps.
|
||||||
|
/// </summary>
|
||||||
|
private static readonly List<double> WeightOptions = BuildWeightOptions();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds the list of available weight options for the routine run select input.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of double values representing weight options.</returns>
|
||||||
|
private static List<double> BuildWeightOptions()
|
||||||
|
{
|
||||||
|
var options = new List<double>();
|
||||||
|
for (var w = 10.0; w <= 40.0; w += 2.5)
|
||||||
|
{
|
||||||
|
options.Add(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var w = 45.0; w <= 100.0; w += 5.0)
|
||||||
|
{
|
||||||
|
options.Add(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Snaps a weight value to the nearest available option.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="weight">The weight value to snap to the nearest option.</param>
|
||||||
|
/// <returns>The nearest available weight option.</returns>
|
||||||
|
private static double SnapToNearest(double weight)
|
||||||
|
{
|
||||||
|
return WeightOptions.OrderBy(w => Math.Abs(w - weight)).First();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
@@ -197,7 +233,7 @@ public partial class Routines
|
|||||||
.Select(e =>
|
.Select(e =>
|
||||||
{
|
{
|
||||||
var last = lastRun.Entries.FirstOrDefault(x => x.ExerciseId == e.ExerciseId);
|
var last = lastRun.Entries.FirstOrDefault(x => x.ExerciseId == e.ExerciseId);
|
||||||
return new RoutineRunEntryDto(e.ExerciseId, last?.Weight ?? 0, false);
|
return new RoutineRunEntryDto(e.ExerciseId, SnapToNearest(last?.Weight ?? WeightOptions[0]), false);
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ p {
|
|||||||
|
|
||||||
.input-sm {
|
.input-sm {
|
||||||
max-width: 110px;
|
max-width: 110px;
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary {
|
.primary {
|
||||||
@@ -173,6 +175,13 @@ p {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.item-subtitle {
|
.item-subtitle {
|
||||||
color: #bdbdbd;
|
color: #bdbdbd;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user