141 lines
6.3 KiB
Plaintext
141 lines
6.3 KiB
Plaintext
@page "/routines"
|
|
@page "/{UserId}/routines"
|
|
|
|
@inject ApiClient Api
|
|
@inject NavigationManager Navigation
|
|
@inject UserContext UserContext
|
|
@inject IJSRuntime JS
|
|
|
|
<PageTitle>Routines</PageTitle>
|
|
|
|
<div class="page">
|
|
<header class="page-header">
|
|
<h1>Routines</h1>
|
|
<p>Build routines from your exercise list.</p>
|
|
<button class="primary" @onclick="ToggleCreate">@(ShowCreateRoutine ? "x" : "+")</button>
|
|
</header>
|
|
|
|
@if (ActiveRun is null)
|
|
{
|
|
@if (ExerciseList.Count == 0)
|
|
{
|
|
<section class="card">
|
|
<h2>No exercises yet</h2>
|
|
<p class="muted">Add exercises first, then create routines.</p>
|
|
<button class="primary" @onclick="GoToExercises">Go to Exercises</button>
|
|
</section>
|
|
}
|
|
|
|
@if (EditingRoutine is null)
|
|
{
|
|
@if (ShowCreateRoutine)
|
|
{
|
|
<section class="card">
|
|
<h2>Create Routine</h2>
|
|
<input class="input" placeholder="Routine name" @bind="NewRoutineName" @bind:event="oninput" />
|
|
<div class="list">
|
|
@foreach (var exercise in ExerciseList)
|
|
{
|
|
var isSelected = SelectedExerciseIds.Contains(exercise.Id);
|
|
<div class="list-item selectable @(isSelected ? "selected" : string.Empty)" @onclick="() => ToggleExercise(exercise.Id)">
|
|
<div class="item-title">@exercise.Name</div>
|
|
<span class="check-icon @(isSelected ? "visible" : string.Empty)" aria-hidden="true">✓</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
<button class="primary" @onclick="CreateRoutineAsync" disabled="@string.IsNullOrWhiteSpace(NewRoutineName)">Save Routine</button>
|
|
</section>
|
|
}
|
|
|
|
@if (ExerciseList.Count > 0 || RoutineList.Count > 0)
|
|
{
|
|
<section class="card">
|
|
<h2>Your Routines</h2>
|
|
@if (IsLoading)
|
|
{
|
|
<p>Loading...</p>
|
|
}
|
|
else if (RoutineList.Count == 0)
|
|
{
|
|
<p class="muted">No routines yet. Create one above.</p>
|
|
}
|
|
else
|
|
{
|
|
<div class="list">
|
|
@foreach (var routine in RoutineList)
|
|
{
|
|
<div class="list-item">
|
|
<div>
|
|
<div class="item-title">@routine.Name</div>
|
|
<div class="item-subtitle">@string.Join(" · ", routine.Exercises.Select(e => e.Name))</div>
|
|
</div>
|
|
<div class="actions">
|
|
<KebabMenu AriaLabel="Routine actions" Context="menu">
|
|
<button class="kebab-menu__item" role="menuitem" @onclick="() => { StartEdit(routine); menu.Close(); }">Edit</button>
|
|
<button class="kebab-menu__item danger" role="menuitem" @onclick="async () => { await DeleteRoutineAsync(routine.Id); menu.Close(); }">Delete</button>
|
|
</KebabMenu>
|
|
<button class="primary start-button" @onclick="() => StartRun(routine)" aria-label="Start routine">▶</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
</section>
|
|
}
|
|
}
|
|
|
|
@if (EditingRoutine is not null)
|
|
{
|
|
<section class="card">
|
|
<h2>Edit Routine</h2>
|
|
<input class="input" @bind="EditingName" @bind:event="oninput" />
|
|
<div class="list">
|
|
@foreach (var exercise in ExerciseList)
|
|
{
|
|
var isSelected = EditingExerciseIds.Contains(exercise.Id);
|
|
<div class="list-item selectable @(isSelected ? "selected" : string.Empty)" @onclick="() => ToggleEditExercise(exercise.Id)">
|
|
<div class="item-title">@exercise.Name</div>
|
|
<span class="check-icon @(isSelected ? "visible" : string.Empty)" aria-hidden="true">✓</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
<div class="actions">
|
|
<button class="primary" @onclick="SaveEditAsync">Save Changes</button>
|
|
<button class="ghost" @onclick="CancelEdit">Cancel</button>
|
|
</div>
|
|
</section>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<section class="card">
|
|
<h2>Routine Run: @ActiveRun.Name</h2>
|
|
<div class="list">
|
|
@foreach (var entry in RunEntries)
|
|
{
|
|
<div class="list-item selectable @(entry.Completed ? "selected" : string.Empty)" @onclick="() => ToggleRunCompleted(entry.ExerciseId)">
|
|
<div class="item-title">@GetExerciseName(entry.ExerciseId)</div>
|
|
<div class="item-actions" @onclick:stopPropagation="true">
|
|
<div class="input-unit">
|
|
<select class="input input-sm" @bind="entry.Weight">
|
|
@foreach (var w in WeightOptions)
|
|
{
|
|
<option value="@w">@w</option>
|
|
}
|
|
</select>
|
|
<span class="unit">kg</span>
|
|
</div>
|
|
</div>
|
|
<span class="check-icon @(entry.Completed ? "visible" : string.Empty)" aria-hidden="true">✓</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
<div class="actions">
|
|
<button class="ghost" @onclick="AbortRun">Abort</button>
|
|
<button class="primary" @onclick="SaveRunAsync">Save Run</button>
|
|
</div>
|
|
</section>
|
|
}
|
|
</div>
|
|
|