Skip to content

Commit

Permalink
Start exercise detail card.
Browse files Browse the repository at this point in the history
  • Loading branch information
eswan18 committed Nov 23, 2023
1 parent 0818ed0 commit dc06735
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 24 deletions.
3 changes: 2 additions & 1 deletion app/(protected)/live/workouts/[workoutId]/LiveWorkout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@ export default function LiveWorkout({
reps: number;
weight: number;
}) => {
const newExercise = {
const newExercise: Exercise = {
reps,
weight,
start_time: new Date(),
exercise_type_id: exerciseType.id as string,
workout_id: workout.id,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,74 @@ import { SaveStatus } from "@/components/indicators/SaveStatusIndicator";
import SaveStatusOverlayContainer from "./SaveStatusOverlayContainer";
import { Card, CardContent } from "@/components/ui/card";
import { X } from "lucide-react";
import {
Dialog,
DialogTrigger,
DialogHeader,
DialogTitle,
DialogContent,
DialogFooter,
DialogClose,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { ExerciseWithType } from "@/lib/resources/apiTypes";
import { formatDateYMD } from "@/lib/time";

interface ExerciseWidgetProps {
weight: number;
reps: number;
exercise: ExerciseWithType;
saveStatus: SaveStatus;
}

export default function ExerciseCard({
weight,
reps,
exercise,
saveStatus,
}: ExerciseWidgetProps) {
return (
<Card className="w-20 h-20 flex-shrink-0">
<CardContent className="h-full flex flex-col justify-center items-center p-0">
<SaveStatusOverlayContainer saveStatus={saveStatus} />
<div className="text-2xl font-bold">{weight}</div>
<div className="text-lg">
<X size={14} className="inline-flex text-muted-foreground mr-0.5" />
{reps}
<Dialog>
<DialogTrigger asChild>
{/* This button has to be inline in this function (not a separate component) for the alert trigger to work */}
<Card className="w-20 h-20 flex-shrink-0 cursor-pointer">
<ExerciseCardContent exercise={exercise} saveStatus={saveStatus} />
</Card>
</DialogTrigger>
<DialogContent className="flex flex-row justify-center">
<div className="sm:w-64">
<div className="flex flex-row justify-evenly items-start">
<DialogHeader>
<DialogTitle>{exercise.exercise_type_name}</DialogTitle>
</DialogHeader>
<span className="text-sm text-muted-foreground">
{exercise.start_time
? formatDateYMD(exercise.start_time, true)
: "unknown"}
</span>
</div>
<div className="grid grid-cols-2 py-2 gap-2 items-end w-fit">
<div className="text-2xl text-right">{exercise.weight}</div>
<div className="text-lg text-muted-foreground">pounds</div>
<div className="text-2xl text-right">{exercise.reps}</div>
<div className="text-lg text-muted-foreground">reps</div>
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="secondary">Close</Button>
</DialogClose>
</DialogFooter>
</div>
</CardContent>
</Card>
</DialogContent>
</Dialog>
);
}

function ExerciseCardContent({ exercise, saveStatus }: ExerciseWidgetProps) {
return (
<CardContent className="h-full flex flex-col justify-center items-center p-0">
<SaveStatusOverlayContainer saveStatus={saveStatus} />
<div className="text-2xl font-bold">{exercise.weight}</div>
<div className="text-lg">
<X size={14} className="inline-flex text-muted-foreground mr-0.5" />
{exercise.reps}
</div>
</CardContent>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
"use client";

import { Exercise, ExerciseType } from "@/lib/resources/apiTypes";
import {
Exercise,
ExerciseType,
ExerciseWithType,
} from "@/lib/resources/apiTypes";
import CreateNewExerciseButton from "./CreateNewExerciseButton";
import ExerciseCard from "./ExerciseCard";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
Expand All @@ -26,6 +30,18 @@ export default function ExerciseGroupCard({
onAddExercise,
supportsAddingExercise = false,
}: ExerciseGroupWidgetProps) {
const exercisesWithTypes: ExerciseWithType[] = exercises
.filter((ex): ex is Exercise => !("isLoading" in ex))
.map((ex) => {
return {
...ex,
id: ex.id as string,
user_id: ex.user_id as string,
exercise_type_name: exerciseType.name,
exercise_type_id: exerciseType.id as string,
exercise_type_owner_user_id: exerciseType.owner_user_id,
};
});
return (
<Card>
<CardHeader>
Expand All @@ -34,18 +50,11 @@ export default function ExerciseGroupCard({
</CardTitle>
</CardHeader>
<CardContent className="flex flex-row justify-left gap-2 overflow-x-scroll">
{exercises.map((ex) => {
{exercisesWithTypes.map((ex) => {
if ("isLoading" in ex) {
return;
}
return (
<ExerciseCard
weight={ex.weight as number}
reps={ex.reps as number}
saveStatus="saved"
key={ex.id}
/>
);
return <ExerciseCard exercise={ex} saveStatus="saved" key={ex.id} />;
})}
{supportsAddingExercise && (
<CreateNewExerciseButton
Expand Down
12 changes: 12 additions & 0 deletions lib/resources/exercises/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,17 @@ export async function getExercisesByWorkoutId(
route: ROUTE,
params: { workout_id: workoutId },
})) as RequestResult<Exercise[]>;
if (result.success) {
result.data = result.data.map(fixTypes);
}
return result;
}

function fixTypes(exercise: Exercise): Exercise {
exercise = { ...exercise };
// if "start_time" is a string, convert it to a Date
if (typeof exercise.start_time === "string") {
exercise.start_time = new Date(exercise.start_time);
}
return exercise;
}

0 comments on commit dc06735

Please sign in to comment.