progress
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\ExerciseResource;
|
||||
use App\Http\Resources\WorkoutExerciseResource;
|
||||
use App\Http\Resources\WorkoutResource;
|
||||
use App\Models\Exercise;
|
||||
use App\Models\Workout;
|
||||
use App\Models\WorkoutExercise;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class WorkoutController extends Controller
|
||||
{
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$workouts = Auth::user()->workouts()->with('assignedByTrainer')->latest()->paginate(10);
|
||||
|
||||
return $this->paginated($workouts);
|
||||
}
|
||||
|
||||
public function community(Request $request): JsonResponse
|
||||
{
|
||||
$q = trim((string) $request->query('q', ''));
|
||||
|
||||
$workouts = Workout::query()
|
||||
->where('is_public', true)
|
||||
->with(['user:id,name', 'items'])
|
||||
->when($q !== '', fn ($qb) => $qb->where('title', 'like', "%{$q}%"))
|
||||
->latest()
|
||||
->paginate(12)
|
||||
->withQueryString();
|
||||
|
||||
return $this->paginated($workouts);
|
||||
}
|
||||
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$data = $request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'notes' => 'nullable|string',
|
||||
'estimated_minutes' => 'nullable|integer|min:1|max:600',
|
||||
]);
|
||||
$workout = Auth::user()->workouts()->create($data);
|
||||
|
||||
return response()->json(['workout' => new WorkoutResource($workout)], 201);
|
||||
}
|
||||
|
||||
public function show(Workout $workout): JsonResponse
|
||||
{
|
||||
$this->authorizeView($workout);
|
||||
$workout->load(['items.exercise', 'assignedByTrainer', 'user:id,name']);
|
||||
|
||||
return response()->json(['workout' => new WorkoutResource($workout)]);
|
||||
}
|
||||
|
||||
public function searchExercises(Request $request, Workout $workout): JsonResponse
|
||||
{
|
||||
$this->authorizeWorkout($workout);
|
||||
$q = trim((string) $request->query('q', ''));
|
||||
|
||||
$exercises = Exercise::query()
|
||||
->with(['aliases' => fn ($rel) => $rel->where('user_id', Auth::id())])
|
||||
->when($q !== '', fn ($qb) => $qb->where('name', 'like', "%{$q}%"))
|
||||
->orderBy('name')
|
||||
->limit(20)
|
||||
->get(['id', 'name']);
|
||||
|
||||
return response()->json(ExerciseResource::collection($exercises));
|
||||
}
|
||||
|
||||
public function togglePublic(Workout $workout): JsonResponse
|
||||
{
|
||||
if ($workout->user_id !== Auth::id()) {
|
||||
abort(403);
|
||||
}
|
||||
$workout->is_public = !$workout->is_public;
|
||||
$workout->save();
|
||||
|
||||
return response()->json(['workout' => new WorkoutResource($workout)]);
|
||||
}
|
||||
|
||||
public function copy(Workout $workout): JsonResponse
|
||||
{
|
||||
if (!$workout->is_public && $workout->user_id !== Auth::id()) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$workout->loadMissing('items');
|
||||
|
||||
$copy = Auth::user()->workouts()->create([
|
||||
'title' => $workout->title.' (copy)',
|
||||
'notes' => $workout->notes,
|
||||
'estimated_minutes' => $workout->estimated_minutes,
|
||||
]);
|
||||
|
||||
foreach ($workout->items as $item) {
|
||||
$copy->items()->create([
|
||||
'exercise_id' => $item->exercise_id,
|
||||
'position' => $item->position,
|
||||
'sets' => $item->sets,
|
||||
'reps' => $item->reps,
|
||||
'weight' => $item->weight,
|
||||
'rest_seconds' => $item->rest_seconds,
|
||||
'notes' => $item->notes,
|
||||
]);
|
||||
}
|
||||
|
||||
$copy->load(['items.exercise']);
|
||||
|
||||
return response()->json(['workout' => new WorkoutResource($copy)], 201);
|
||||
}
|
||||
|
||||
public function addExercise(Request $request, Workout $workout): JsonResponse
|
||||
{
|
||||
$this->authorizeWorkout($workout);
|
||||
$data = $request->validate([
|
||||
'exercise_id' => 'required|exists:exercises,id',
|
||||
'position' => 'nullable|integer|min:1',
|
||||
'sets' => 'nullable|integer|min:1|max:20',
|
||||
'reps' => 'nullable|integer|min:1|max:200',
|
||||
'weight' => 'nullable|numeric|min:0|max:999.99',
|
||||
'rest_seconds' => 'nullable|integer|min:0|max:600',
|
||||
'notes' => 'nullable|string',
|
||||
]);
|
||||
$nextPos = ($workout->items()->max('position') ?? 0) + 1;
|
||||
$data['position'] = $data['position'] ?? $nextPos;
|
||||
$item = $workout->items()->create($data);
|
||||
$item->load('exercise');
|
||||
|
||||
return response()->json(['item' => new WorkoutExerciseResource($item)], 201);
|
||||
}
|
||||
|
||||
public function updateExercise(Request $request, Workout $workout, WorkoutExercise $item): JsonResponse
|
||||
{
|
||||
$this->authorizeWorkout($workout);
|
||||
if ($item->workout_id !== $workout->id) {
|
||||
abort(404);
|
||||
}
|
||||
$data = $request->validate([
|
||||
'position' => 'nullable|integer|min:1',
|
||||
'sets' => 'nullable|integer|min:1|max:20',
|
||||
'reps' => 'nullable|integer|min:1|max:200',
|
||||
'weight' => 'nullable|numeric|min:0|max:999.99',
|
||||
'rest_seconds' => 'nullable|integer|min:0|max:600',
|
||||
'notes' => 'nullable|string',
|
||||
]);
|
||||
$item->update($data);
|
||||
$item->load('exercise');
|
||||
|
||||
return response()->json(['item' => new WorkoutExerciseResource($item)]);
|
||||
}
|
||||
|
||||
public function removeExercise(Workout $workout, WorkoutExercise $item): JsonResponse
|
||||
{
|
||||
$this->authorizeWorkout($workout);
|
||||
if ($item->workout_id !== $workout->id) {
|
||||
abort(404);
|
||||
}
|
||||
$item->delete();
|
||||
|
||||
return response()->json(['message' => 'Exercise removed']);
|
||||
}
|
||||
|
||||
public function destroy(Workout $workout): JsonResponse
|
||||
{
|
||||
if ($workout->user_id !== Auth::id()) {
|
||||
abort(403);
|
||||
}
|
||||
$workout->delete();
|
||||
|
||||
return response()->json(['message' => 'Workout deleted']);
|
||||
}
|
||||
|
||||
protected function authorizeWorkout(Workout $workout): void
|
||||
{
|
||||
if ($workout->user_id === Auth::id()) {
|
||||
return;
|
||||
}
|
||||
if ($workout->assigned_by_trainer_id && $workout->assigned_by_trainer_id === Auth::id()) {
|
||||
return;
|
||||
}
|
||||
abort(403);
|
||||
}
|
||||
|
||||
protected function authorizeView(Workout $workout): void
|
||||
{
|
||||
if ($workout->is_public) {
|
||||
return;
|
||||
}
|
||||
$this->authorizeWorkout($workout);
|
||||
}
|
||||
|
||||
protected function paginated($paginator): JsonResponse
|
||||
{
|
||||
return response()->json([
|
||||
'data' => WorkoutResource::collection($paginator->items()),
|
||||
'meta' => [
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'last_page' => $paginator->lastPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'total' => $paginator->total(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user