-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Squashed commit of the following: commit feb75ac4eb2dbe56a311337d22fbccdac0c3e603 Author: Ethan Swan <[email protected]> Date: Mon Sep 4 19:10:49 2023 -0500 ... commit f34f9af8f4bb3bab45647b641069e5c2dfd00a18 Author: Ethan Swan <[email protected]> Date: Mon Sep 4 18:30:32 2023 -0500 Start wiring up MoreWorkoutTypesModal. commit 8690b7962628b57b0189757a63cd184a640c8729 Author: Ethan Swan <[email protected]> Date: Mon Sep 4 16:43:32 2023 -0500 Start working on workout types modal.
- Loading branch information
Showing
5 changed files
with
228 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import ClientModal from "@/components/ClientModal"; | ||
import { Workout, WorkoutType } from "@/lib/resources/apiTypes"; | ||
import { useRouter } from "next/navigation"; | ||
|
||
type MoreWorkoutTypesModalProps = { | ||
workoutTypes: WorkoutType[]; | ||
handleClose: () => void; | ||
createAndStartWorkout: ( | ||
workoutTypeId: string | undefined, | ||
) => Promise<Workout>; | ||
}; | ||
|
||
export default function MoreWorkoutTypesModal({ | ||
workoutTypes, | ||
handleClose, | ||
createAndStartWorkout, | ||
}: MoreWorkoutTypesModalProps) { | ||
const router = useRouter(); | ||
// Start by alphabetizing the workout types. | ||
workoutTypes.sort((a, b) => { | ||
if (!a.name || !b.name) throw new Error("Workout type name is null"); | ||
return a.name.localeCompare(b.name); | ||
}); | ||
const rows = workoutTypes.map((workoutType) => { | ||
const onClick = () => { | ||
createAndStartWorkout(workoutType.id).then((workout) => { | ||
router.push(`/live/workouts/${workout.id}`); | ||
}); | ||
}; | ||
return ( | ||
<tr | ||
className="cursor-pointer even:bg-gray-50 border-y-[1px] border-gray-200" | ||
onClick={onClick} | ||
key={workoutType.id} | ||
title={workoutType.name} | ||
> | ||
<td className="px-2 py-1">{workoutType.name}</td> | ||
<td> | ||
<i className="fi fi-rr-arrow-alt-circle-right text-xl inline-flex align-[-0.2rem] text-gold px-1" /> | ||
</td> | ||
</tr> | ||
); | ||
}); | ||
const createAndStartCustomWorkout = () => { | ||
createAndStartWorkout(undefined).then((workout) => { | ||
router.push(`/live/workouts/${workout.id}`); | ||
}); | ||
}; | ||
const createNewWorkoutType = () => { | ||
router.push("/workout-types/new"); | ||
}; | ||
return ( | ||
<ClientModal handleClose={handleClose}> | ||
<div className="flex flex-col max-w-md h-128 m-auto gap-6"> | ||
<h2 className="text-lg lg:text-2xl font-bold">Start a Workout</h2> | ||
<div className="flex flex-row justify-between items-center w-full gap-2 lg:gap-4 lg:pb-4"> | ||
<div className="flex flex-col px-2"> | ||
<h3 className="text-lg">Workout Types</h3> | ||
<div className="w-48 h-48 overflow-y-scroll flex-grow flex-shrink-0 mx-auto"> | ||
<table className="w-full table-auto border-collapse"> | ||
<tbody>{rows}</tbody> | ||
</table> | ||
</div> | ||
</div> | ||
<div> | ||
<p className="text-lg text-gray-500">OR</p> | ||
</div> | ||
<div className="w-[40%] flex-shrink flex flex-col items-center text-gold text-sm gap-6 max-w-xl"> | ||
<button onClick={createNewWorkoutType}> | ||
<div className="flex flex-row justify-between items-center gap-2 px-2"> | ||
<i className="fi fi-rr-square-plus inline-flex align-[-0.5rem] text-3xl" /> | ||
<p className="text-left"> | ||
Create a <span className="font-bold">new</span> type of | ||
workout | ||
</p> | ||
</div> | ||
</button> | ||
<button onClick={createAndStartCustomWorkout}> | ||
<div className="flex flex-row justify-between items-center gap-2 px-2"> | ||
<i className="fi fi-rr-square-plus inline-flex align-[-0.5rem] text-3xl" /> | ||
<p className="text-left"> | ||
Start a <span className="font-bold">custom</span> workout | ||
</p> | ||
</div> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</ClientModal> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
"use client"; | ||
|
||
import { useState } from "react"; | ||
import { useRouter } from "next/navigation"; | ||
import Link from "next/link"; | ||
import Input from "@/components/forms/Input"; | ||
import LoadingSpinner from "@/components/LoadingSpinner"; | ||
import { WorkoutType } from "@/lib/resources/apiTypes"; | ||
|
||
export default function NewWorkoutTypeForm() { | ||
const router = useRouter(); | ||
const [loading, setLoading] = useState(false); | ||
const [name, setName] = useState(""); | ||
const [notes, setNotes] = useState(""); | ||
const onNameChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
setName(event.target.value); | ||
}; | ||
const onNotesChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
setNotes(e.target.value); | ||
}; | ||
|
||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => { | ||
event.preventDefault(); | ||
setLoading(true); | ||
/* todo ... */ | ||
}; | ||
|
||
return ( | ||
<form className="flex flex-col w-full" onSubmit={handleSubmit}> | ||
<h1 className="text-2xl font-bold">New Workout Type</h1> | ||
<label | ||
htmlFor="name" | ||
className="mb-3 text-gray-700 dark:text-gray-100 flex flex-col" | ||
> | ||
<p className="mb-1">Workout Type Name</p> | ||
<input | ||
className="dark:text-gray-900 rounded-md border border-gray-300" | ||
id="name" | ||
type="text" | ||
name="name" | ||
value={name} | ||
onChange={onNameChange} | ||
/> | ||
</label> | ||
<label | ||
htmlFor="notes" | ||
className="mb-3 text-gray-700 dark:text-gray-100 flex flex-col" | ||
> | ||
<p className="mb-1">Notes (optional)</p> | ||
<textarea | ||
className="dark:text-gray-900 rounded-md border border-gray-300" | ||
id="notes" | ||
name="notes" | ||
value={notes} | ||
onChange={onNotesChange} | ||
/> | ||
</label> | ||
|
||
<div className="flex w-full justify-center font-bold"> | ||
{loading ? ( | ||
<LoadingSpinner /> | ||
) : ( | ||
<button | ||
className="flex flex-row justify-center items-center | ||
rounded-full text-white bg-gold | ||
py-2 px-4 m-2 gap-2" | ||
type="submit" | ||
> | ||
<p>Create</p> | ||
<i className="text-lg fi fi-sr-arrow-circle-right inline-flex align-[-0.2rem]" /> | ||
</button> | ||
)} | ||
</div> | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import NewWorkoutTypeForm from "./NewWorkoutTypeForm"; | ||
|
||
export const metadata = { | ||
title: "New Workout Type", | ||
description: "Create a new type of workout", | ||
}; | ||
|
||
export default async function NewWorkoutTypePage() { | ||
return ( | ||
<main className="flex flex-col items-center justify-start"> | ||
<NewWorkoutTypeForm /> | ||
</main> | ||
); | ||
} |