109 lines
3.6 KiB
C#
109 lines
3.6 KiB
C#
using System.Text.Json;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Server.WatchBody.Core.Dal.Src.Repository;
|
||
using Server.WatchBody.Web.Dto;
|
||
|
||
namespace Server.WatchBody.Web.Controllers;
|
||
|
||
/// <summary>
|
||
/// Чтение тренировок (spec 04-workouts-get):
|
||
/// GET api/v1/workouts (пагинация), GET api/v1/workouts/{"id"} (карточка).
|
||
/// </summary>
|
||
public class WorkoutController : Controller
|
||
{
|
||
private readonly IWorkoutRepository _workouts;
|
||
|
||
public WorkoutController(IWorkoutRepository workouts) => _workouts = workouts;
|
||
|
||
public ActionResult List(int? limit, int? offset)
|
||
{
|
||
var athleteId = AthleteId();
|
||
if (athleteId < 0) return Error(401, "unauthorized");
|
||
|
||
var take = limit ?? 20;
|
||
var skip = offset ?? 0;
|
||
if (take is < 1 or > 100) return Error(400, "limit 1–100");
|
||
if (skip < 0) return Error(400, "offset ≥ 0");
|
||
|
||
var all = _workouts.Select(new WorkoutFilter { AthleteId = athleteId })
|
||
.OrderByDescending(w => w.StartedAt).ToList();
|
||
var page = all.Skip(skip).Take(take)
|
||
.Select(Map).ToList();
|
||
return new JsonResult(new WorkoutListResponse { Items = page, Total = all.Count });
|
||
}
|
||
|
||
public ActionResult Get(string id)
|
||
{
|
||
var athleteId = AthleteId();
|
||
if (athleteId < 0) return Error(401, "unauthorized");
|
||
if (!Guid.TryParse(id, out var workoutId)) return Error(400, "id не uuid");
|
||
var w = _workouts.Get(athleteId, workoutId);
|
||
if (w == null) return Error(404, "not_found");
|
||
|
||
return new JsonResult(new WorkoutCardResponse
|
||
{
|
||
WorkoutId = w.Id,
|
||
StartedAt = w.StartedAt,
|
||
EndedAt = w.EndedAt,
|
||
Status = w.Status,
|
||
SessionKind = w.SessionKind,
|
||
AvgHr = w.AvgHr,
|
||
Sets = w.Sets.Select(s => new WorkoutSetDto
|
||
{
|
||
SetId = s.Id,
|
||
ExerciseId = s.ExerciseId,
|
||
Seq = s.Seq,
|
||
WeightKg = s.WeightKg,
|
||
Reps = s.Reps,
|
||
DoneAt = s.DoneAt,
|
||
Source = s.Source,
|
||
InPlan = s.InPlan,
|
||
Rpe = s.Rpe,
|
||
KneePain = s.KneePain,
|
||
}).ToList(),
|
||
CommandLog = w.Commands.Select(c => new CommandLogDto
|
||
{
|
||
Id = c.Id,
|
||
TOffsetS = c.TOffsetS,
|
||
RecognizedText = c.RecognizedText,
|
||
Semantics = JsonDocument.Parse(c.Semantics).RootElement.Clone(),
|
||
Accepted = c.Accepted,
|
||
}).ToList(),
|
||
});
|
||
}
|
||
|
||
private static WorkoutDto Map(Core.Dal.Src.Domain.Workout w) => new()
|
||
{
|
||
WorkoutId = w.Id,
|
||
StartedAt = w.StartedAt,
|
||
EndedAt = w.EndedAt,
|
||
Status = w.Status,
|
||
SessionKind = w.SessionKind,
|
||
AvgHr = w.AvgHr,
|
||
Sets = w.Sets.Select(s => new WorkoutSetDto
|
||
{
|
||
SetId = s.Id,
|
||
ExerciseId = s.ExerciseId,
|
||
Seq = s.Seq,
|
||
WeightKg = s.WeightKg,
|
||
Reps = s.Reps,
|
||
DoneAt = s.DoneAt,
|
||
Source = s.Source,
|
||
InPlan = s.InPlan,
|
||
Rpe = s.Rpe,
|
||
KneePain = s.KneePain,
|
||
}).ToList(),
|
||
};
|
||
|
||
private int AthleteId() =>
|
||
HttpContext.Items.TryGetValue(Middleware.ApiKeyMiddleware.AthleteIdItem, out var value)
|
||
? (int)value!
|
||
: -1;
|
||
|
||
private ActionResult Error(int statusCode, string message)
|
||
{
|
||
Response.StatusCode = statusCode;
|
||
return new JsonResult(new ErrorResponse { Error = message });
|
||
}
|
||
}
|