Repository: IgnisDa/ryot (language: rust)

Issue:
Allow editing workouts



Discussion / hints:
also look into jotai atoms to simplify current-workout.

Fix patch:
diff --git a/README.md b/README.md
index 0914b24422..654b9b9355 100644
--- a/README.md
+++ b/README.md
@@ -30,11 +30,6 @@
 Ryot (**R**oll **Y**our **O**wn **T**racker), pronounced "riot", aims to be the only self
 hosted tracker you will ever need!
 
-## IMPORTANT NOTE FOR `v6.*` USERS
-
-If you were using `v6.*` of Ryot, please read the
-[migration guide](https://docs.ryot.io/migration.html#from-v6-to-v7) for instructions.
-
 ## Pro version
 
 Ryot is available in two versions - community and pro. The pro version has additional
diff --git a/apps/backend/src/main.rs b/apps/backend/src/main.rs
index d4b0e18762..1c2ad8bb27 100644
--- a/apps/backend/src/main.rs
+++ b/apps/backend/src/main.rs
@@ -55,8 +55,13 @@ async fn main() -> Result<()> {
     #[cfg(debug_assertions)]
     dotenvy::dotenv().ok();
 
-    if env::var("RUST_LOG").is_err() {
-        env::set_var("RUST_LOG", "ryot=info,sea_orm=info");
+    match env::var("RUST_LOG").ok() {
+        Some(v) => {
+            if !v.contains("sea_orm") {
+                env::set_var("RUST_LOG", format!("{},sea_orm=info", v));
+            }
+        }
+        None => env::set_var("RUST_LOG", "ryot=info,sea_orm=info"),
     }
     init_tracing()?;
 
diff --git a/apps/frontend/app/entry.worker.ts b/apps/frontend/app/entry.worker.ts
index d2b771b0da..c95b96781f 100644
--- a/apps/frontend/app/entry.worker.ts
+++ b/apps/frontend/app/entry.worker.ts
@@ -1,8 +1,15 @@
 /// <reference lib="WebWorker" />
 
-export type {};
+import { logger } from "@remix-pwa/sw";
+import { match } from "ts-pattern";
+import type {
+	AppServiceWorkerNotificationTag,
+	AppServiceWorkerMessageData,
+	AppServiceWorkerNotificationData,
+} from "~/lib/generals";
 
 declare let self: ServiceWorkerGlobalScope;
+declare let clients: Clients;
 
 self.addEventListener("install", (event) => {
 	event.waitUntil(self.skipWaiting());
@@ -14,4 +21,44 @@ self.addEventListener("activate", (event) => {
 
 self.addEventListener("notificationclick", (event) => {
 	event.notification.close();
+	if (event.notification.data) {
+		logger.debug("Received notification data", event.notification.data);
+		const data = event.notification.data as AppServiceWorkerNotificationData;
+		match(data.event)
+			.with("open-link", () => {
+				const urlToOpen = data.link;
+				if (!urlToOpen) return;
+				event.waitUntil(
+					clients
+						.matchAll({ type: "window", includeUncontrolled: true })
+						.then((clientList) => {
+							for (let i = 0; i < clientList.length; i++) {
+								const client = clientList[i];
+								if (client.url === urlToOpen && "focus" in client) {
+									return client.focus();
+								}
+							}
+							if (clients.openWindow) {
+								return clients.openWindow(urlToOpen);
+							}
+						}),
+				);
+			})
+			.exhaustive();
+	}
+});
+
+self.addEventListener("message", (event) => {
+	const data = event.data as AppServiceWorkerMessageData;
+	logger.debug("Received message", data);
+	match(data.event)
+		.with("remove-timer-completed-notification", () => {
+			self.registration.getNotifications().then((notifications) => {
+				for (const notification of notifications) {
+					const tag = notification.tag as AppServiceWorkerNotificationTag;
+					if (tag === "timer-completed") notification.close();
+				}
+			});
+		})
+		.exhaustive();
 });
diff --git a/apps/frontend/app/lib/generals.ts b/apps/frontend/app/lib/generals.ts
index 2acc3f4283..bcab2ff009 100644
--- a/apps/frontend/app/lib/generals.ts
+++ b/apps/frontend/app/lib/generals.ts
@@ -98,6 +98,47 @@ export enum ThreePointSmileyRating {
 	Sad = "Sad",
 }
 
+export enum FitnessAction {
+	LogWorkout = "log-workout",
+	UpdateWorkout = "update-workout",
+	CreateTemplate = "create-template",
+}
+
+export type AppServiceWorkerNotificationTag = "timer-completed";
+
+export type AppServiceWorkerNotificationData = {
+	event: "open-link";
+	link?: string;
+};
+
+export const sendNotificationToServiceWorker = (
+	title: string,
+	body: string,
+	tag?: AppServiceWorkerNotificationTag,
+	data?: AppServiceWorkerNotificationData,
+) => {
+	navigator.serviceWorker.ready.then((registration) => {
+		registration.showNotification(title, {
+			tag,
+			body,
+			data,
+			silent: true,
+			icon: LOGO_IMAGE_URL,
+		});
+	});
+};
+
+export type AppServiceWorkerMessageData = {
+	event: "remove-timer-completed-notification";
+};
+
+export const postMessageToServiceWorker = (
+	message: AppServiceWorkerMessageData,
+) => {
+	if (navigator.serviceWorker.controller)
+		navigator.serviceWorker.controller.postMessage(message);
+};
+
 export const convertDecimalToThreePointSmiley = (rating: number) =>
 	inRange(rating, 0, 33.4)
 		? ThreePointSmileyRating.Sad
diff --git a/apps/frontend/app/lib/hooks.ts b/apps/frontend/app/lib/hooks.ts
index 3bfcef2d3f..2a538e7b07 100644
--- a/apps/frontend/app/lib/hooks.ts
+++ b/apps/frontend/app/lib/hooks.ts
@@ -17,6 +17,7 @@ import { useInterval } from "usehooks-ts";
 import {
 	CurrentWorkoutKey,
 	dayjsLib,
+	type FitnessAction,
 	getMetadataDetailsQuery,
 	getStringAsciiValue,
 	getUserMetadataDetailsQuery,
@@ -96,17 +97,13 @@ export const useGetWorkoutStarter = () => {
 	const revalidator = useRevalidator();
 	const [_, setCurrentWorkout] = useCurrentWorkout();
 
-	const fn = (wkt: InProgressWorkout, value: "workouts" | "templates") => {
+	const fn = (wkt: InProgressWorkout, action: FitnessAction) => {
 		setCurrentWorkout(wkt);
-		Cookies.set(CurrentWorkoutKey, value, {
+		Cookies.set(CurrentWorkoutKey, action, {
 			expires: 2,
 			sameSite: "Strict",
 		});
-		navigate(
-			$path("/fitness/:action", {
-				action: value === "workouts" ? "log-workout" : "create-template",
-			}),
-		);
+		navigate($path("/fitness/:action", { action }));
 		revalidator.revalidate();
 	};
 	return fn;
diff --git a/apps/frontend/app/lib/state/fitness.ts b/apps/frontend/app/lib/state/fitness.ts
index ed38ed241d..d641548df8 100644
--- a/apps/frontend/app/lib/state/fitness.ts
+++ b/apps/frontend/app/lib/state/fitness.ts
@@ -1,16 +1,16 @@
 import type { NavigateFunction } from "@remix-run/react";
 import {
-	type CreateUserWorkoutMutationVariables,
+	type CreateOrUpdateUserWorkoutMutationVariables,
 	ExerciseDetailsDocument,
 	type ExerciseLot,
 	SetLot,
 	UserExerciseDetailsDocument,
 	type UserWorkoutSetRecord,
+	UserWorkoutTemplateDetailsDocument,
 	WorkoutDetailsDocument,
 	type WorkoutDetailsQuery,
 	type WorkoutInformation,
 	type WorkoutSetStatistic,
-	WorkoutTemplateDetailsDocument,
 } from "@ryot/generated/graphql/backend/graphql";
 import { isString } from "@ryot/ts-utils";
 import { queryOptions } from "@tanstack/react-query";
@@ -60,6 +60,7 @@ export type Exercise = {
 };
 
 export type InProgressWorkout = {
+	updateWorkoutId?: string;
 	updateWorkoutTemplateId?: string;
 	repeatedFrom?: string;
 	templateId?: string;
@@ -149,8 +150,8 @@ export const getWorkoutTemplateDetailsQuery = (workoutTemplateId: string) =>
 			queryFactory.fitness.workoutTemplateDetails(workoutTemplateId).queryKey,
 		queryFn: () =>
 			clientGqlService
-				.request(WorkoutTemplateDetailsDocument, { workoutTemplateId })
-				.then((data) => data.workoutTemplateDetails),
+				.request(UserWorkoutTemplateDetailsDocument, { workoutTemplateId })
+				.then((data) => data.userWorkoutTemplateDetails),
 	});
 
 type TWorkoutDetails = WorkoutDetailsQuery["workoutDetails"];
@@ -160,33 +161,43 @@ export const convertHistorySetToCurrentSet = (
 		TWorkoutDetails["details"]["information"]["exercises"][number]["sets"][number],
 		"statistic" | "lot"
 	>,
+	confirmedAt?: string | null,
 ) =>
 	({
 		lot: s.lot,
-		confirmedAt: null,
 		statistic: s.statistic,
+		confirmedAt: confirmedAt ?? null,
 	}) satisfies ExerciseSet;
 
 export const duplicateOldWorkout = async (
 	workoutInformation: WorkoutInformation,
 	name: string,
 	coreDetails: ReturnType<typeof useCoreDetails>,
-	repeatedFromId?: string,
-	templateId?: string,
-	updateWorkoutTemplateId?: string,
-	defaultRestTimer?: number | null,
+	params: {
+		repeatedFromId?: string;
+		templateId?: string;
+		updateWorkoutId?: string;
+		updateWorkoutTemplateId?: string;
+		defaultRestTimer?: number | null;
+	},
 ) => {
 	const inProgress = getDefaultWorkout();
 	inProgress.name = name;
-	inProgress.repeatedFrom = repeatedFromId;
-	inProgress.templateId = templateId;
-	inProgress.updateWorkoutTemplateId = updateWorkoutTemplateId;
+	inProgress.repeatedFrom = params.repeatedFromId;
+	inProgress.templateId = params.templateId;
+	inProgress.updateWorkoutId = params.updateWorkoutId;
+	inProgress.updateWorkoutTemplateId = params.updateWorkoutTemplateId;
 	inProgress.comment = workoutInformation.comment || undefined;
-	inProgress.defaultRestTimer = defaultRestTimer;
+	inProgress.defaultRestTimer = params.defaultRestTimer;
 	for (const [exerciseIdx, ex] of workoutInformation.exercises.entries()) {
-		const sets = ex.sets.map(convertHistorySetToCurrentSet);
+		const sets = ex.sets.map((v) =>
+			convertHistorySetToCurrentSet(
+				v,
+				params.updateWorkoutId ? v.confirmedAt : undefined,
+			),
+		);
 		const exerciseDetails = await getExerciseDetails(ex.name);
-		const defaultRestTime = defaultRestTimer || ex.restTime;
+		const defaultRestTime = params.defaultRestTimer || ex.restTime;
 		inProgress.exercises.push({
 			identifier: randomUUID(),
 			isShowDetailsOpen: exerciseIdx === 0,
@@ -261,12 +272,10 @@ export const addExerciseToWorkout = async (
 	const finishedDraft = finishDraft(draft);
 	setCurrentWorkout(finishedDraft);
 	const currentEntity = Cookies.get(CurrentWorkoutKey);
+	if (!currentEntity) return;
 	navigate(
 		withFragment(
-			$path("/fitness/:action", {
-				action:
-					currentEntity === "workouts" ? "log-workout" : "create-template",
-			}),
+			$path("/fitness/:action", { action: currentEntity }),
 			idxOfNextExercise.toString(),
 		),
 	);
@@ -276,10 +285,11 @@ export const currentWorkoutToCreateWorkoutInput = (
 	currentWorkout: InProgressWorkout,
 	isCreatingTemplate: boolean,
 ) => {
-	const input: CreateUserWorkoutMutationVariables = {
+	const input: CreateOrUpdateUserWorkoutMutationVariables = {
 		input: {
 			endTime: new Date().toISOString(),
 			templateId: currentWorkout.templateId,
+			updateWorkoutId: currentWorkout.updateWorkoutId,
 			updateWorkoutTemplateId: currentWorkout.updateWorkoutTemplateId,
 			startTime: new Date(currentWorkout.startTime).toISOString(),
 			name: currentWorkout.name,
diff --git a/apps/frontend/app/lib/utilities.server.ts b/apps/frontend/app/lib/utilities.server.ts
index 4928aa69f7..b3d1c7d6c2 100644
--- a/apps/frontend/app/lib/utilities.server.ts
+++ b/apps/frontend/app/lib/utilities.server.ts
@@ -34,6 +34,7 @@ import {
 	AUTH_COOKIE_NAME,
 	CurrentWorkoutKey,
 	dayjsLib,
+	FitnessAction,
 	pageQueryParam,
 	queryClient,
 	queryFactory,
@@ -398,7 +399,9 @@ export const getWorkoutCookieValue = (request: Request) => {
 };
 
 export const isWorkoutActive = (request: Request) => {
-	const inProgress = getWorkoutCookieValue(request) === "workouts";
+	const inProgress = [FitnessAction.LogWorkout, FitnessAction.UpdateWorkout]
+		.map(String)
+		.includes(getWorkoutCookieValue(request));
 	return inProgress;
 };
 
diff --git a/apps/frontend/app/routes/_dashboard.fitness.$action.tsx b/apps/frontend/app/routes/_dashboard.fitness.$action.tsx
index 7c3ba2b7c2..4a88f6392d 100644
--- a/apps/frontend/app/routes/_dashboard.fitness.$action.tsx
+++ b/apps/frontend/app/routes/_dashboard.fitness.$action.tsx
@@ -51,14 +51,15 @@ import {
 } from "@remix-run/react";
 import type { MetaArgs_SingleFetch } from "@remix-run/react";
 import {
-	CreateOrUpdateWorkoutTemplateDocument,
-	CreateUserWorkoutDocument,
+	CreateOrUpdateUserWorkoutDocument,
+	CreateOrUpdateUserWorkoutTemplateDocument,
 	ExerciseLot,
 	SetLot,
 	UserUnitSystem,
 	type WorkoutSetStatistic,
 } from "@ryot/generated/graphql/backend/graphql";
 import {
+	changeCase,
 	isEqual,
 	isNumber,
 	isString,
@@ -107,14 +108,16 @@ import {
 } from "~/components/fitness";
 import {
 	CurrentWorkoutKey,
+	FitnessAction,
 	FitnessEntity,
-	LOGO_IMAGE_URL,
 	PRO_REQUIRED_MESSAGE,
 	dayjsLib,
 	getSetColor,
 	getSurroundingElements,
+	postMessageToServiceWorker,
 	queryClient,
 	queryFactory,
+	sendNotificationToServiceWorker,
 } from "~/lib/generals";
 import {
 	forceUpdateEverySecond,
@@ -145,15 +148,12 @@ import {
 const workoutCookieName = CurrentWorkoutKey;
 const defaultTimerLocalStorageKey = "DefaultExerciseRestTimer";
 
-enum Action {
-	LogWorkout = "log-workout",
-	CreateTemplate = "create-template",
-}
-
 export const loader = unstable_defineLoader(async ({ params, request }) => {
-	const { action } = zx.parseParams(params, { action: z.nativeEnum(Action) });
+	const { action } = zx.parseParams(params, {
+		action: z.nativeEnum(FitnessAction),
+	});
 	await match(action)
-		.with(Action.LogWorkout, async () => {
+		.with(FitnessAction.LogWorkout, FitnessAction.UpdateWorkout, async () => {
 			const inProgress = isWorkoutActive(request);
 			if (!inProgress)
 				throw await redirectWithToast($path("/"), {
@@ -161,19 +161,17 @@ export const loader = unstable_defineLoader(async ({ params, request }) => {
 					message: "No workout in progress",
 				});
 		})
-		.with(Action.CreateTemplate, async () => {})
+		.with(FitnessAction.CreateTemplate, async () => {})
 		.exhaustive();
-	return { action, isCreatingTemplate: action === Action.CreateTemplate };
+	return {
+		action,
+		isUpdatingWorkout: action === FitnessAction.UpdateWorkout,
+		isCreatingTemplate: action === FitnessAction.CreateTemplate,
+	};
 });
 
 export const meta = ({ data }: MetaArgs_SingleFetch<typeof loader>) => {
-	return [
-		{
-			title: `${
-				data?.action === Action.LogWorkout ? "Log Workout" : "Create Template"
-			} | Ryot`,
-		},
-	];
+	return [{ title: `${changeCase(data?.action || "")} | Ryot` }];
 };
 
 export const action = unstable_defineAction(async ({ request }) => {
@@ -181,30 +179,31 @@ export const action = unstable_defineAction(async ({ request }) => {
 	const workout = JSON.parse(formData.get("workout") as string);
 	return namedAction(request, {
 		createWorkout: async () => {
-			const { createUserWorkout } = await serverGqlService.authenticatedRequest(
-				request,
-				CreateUserWorkoutDocument,
-				workout,
-			);
+			const { createOrUpdateUserWorkout } =
+				await serverGqlService.authenticatedRequest(
+					request,
+					CreateOrUpdateUserWorkoutDocument,
+					workout,
+				);
 			return redirectWithToast(
 				$path("/fitness/:entity/:id", {
 					entity: "workouts",
-					id: createUserWorkout,
+					id: createOrUpdateUserWorkout,
 				}),
 				{ message: "Workout completed successfully", type: "success" },
 			);
 		},
 		createTemplate: async () => {
-			const { createOrUpdateWorkoutTemplate } =
+			const { createOrUpdateUserWorkoutTemplate } =
 				await serverGqlService.authenticatedRequest(
 					request,
-					CreateOrUpdateWorkoutTemplateDocument,
+					CreateOrUpdateUserWorkoutTemplateDocument,
 					workout,
 				);
 			return redirectWithToast(
 				$path("/fitness/:entity/:id", {
 					entity: "templates",
-					id: createOrUpdateWorkoutTemplate,
+					id: createOrUpdateUserWorkoutTemplate,
 				}),
 				{ message: "Template created successfully", type: "success" },
 			);
@@ -222,7 +221,7 @@ const deleteUploadedAsset = (key: string) => {
 };
 
 export default function Page() {
-	const { isCreatingTemplate } = useLoaderData<typeof loader>();
+	const loaderData = useLoaderData<typeof loader>();
 	const userPreferences = useUserPreferences();
 	const unitSystem = useUserUnitSystem();
 	const events = useApplicationEvents();
@@ -234,14 +233,23 @@ export default function Page() {
 		const sound = new Howl({ src: ["/timer-completed.mp3"] });
 		sound.play();
 		if (document.visibilityState === "visible") return;
-		navigator.serviceWorker.ready.then((registration) => {
-			registration.showNotification("Timer completed", {
-				body: "Let's get this done!",
-				icon: LOGO_IMAGE_URL,
-				silent: true,
-			});
-		});
+		sendNotificationToServiceWorker(
+			"Timer completed",
+			"Let's get this done!",
+			"timer-completed",
+			{ event: "open-link", link: window.location.href },
+		);
 	};
+	useInterval(() => {
+		if (
+			loaderData.action === FitnessAction.LogWorkout &&
+			navigator.serviceWorker.controller &&
+			document.visibilityState === "visible"
+		)
+			postMessageToServiceWorker({
+				event: "remove-timer-completed-notification",
+			});
+	}, 5000);
 	const [
 		timerDrawerOpened,
 		{
@@ -304,7 +312,7 @@ export default function Page() {
 							<Stack ref={parent}>
 								<Group justify="space-between">
 									<TextInput
-										w={isCreatingTemplate ? "65%" : "100%"}
+										w={loaderData.isCreatingTemplate ? "65%" : "100%"}
 										size="sm"
 										label="Name"
 										placeholder="A name for your workout"
@@ -318,7 +326,7 @@ export default function Page() {
 											)
 										}
 									/>
-									{isCreatingTemplate ? (
+									{loaderData.isCreatingTemplate ? (
 										<NumberInput
 											w="30%"
 											suffix="s"
@@ -354,7 +362,7 @@ export default function Page() {
 									<StatDisplay
 										name="Exercises"
 										value={
-											isCreatingTemplate
+											loaderData.isCreatingTemplate
 												? currentWorkout.exercises.length.toString()
 												: `${
 														currentWorkout.exercises
@@ -371,7 +379,7 @@ export default function Page() {
 												currentWorkout.exercises
 													.flatMap((e) => e.sets)
 													.flatMap((s) =>
-														isCreatingTemplate || s.confirmedAt
+														loaderData.isCreatingTemplate || s.confirmedAt
 															? Number(s.statistic.reps || 0) *
 																Number(s.statistic.weight || 0)
 															: 0,
@@ -385,7 +393,9 @@ export default function Page() {
 											currentWorkout.exercises
 												.flatMap((e) => e.sets)
 												.flatMap((s) =>
-													isCreatingTemplate || s.confirmedAt ? 1 : 0,
+													loaderData.isCreatingTemplate || s.confirmedAt
+														? 1
+														: 0,
 												),
 										).toString()}
 									/>
@@ -394,7 +404,10 @@ export default function Page() {
 								<SimpleGrid
 									cols={
 										2 +
-										(isCreatingTemplate ? -1 : 0) +
+										(loaderData.isCreatingTemplate ||
+										loaderData.isUpdatingWorkout
+											? -1
+											: 0) +
 										Number(currentWorkout.exercises.length > 0) +
 										Number(currentWorkout.exercises.length > 1)
 									}
@@ -405,7 +418,12 @@ export default function Page() {
 										variant="subtle"
 										size="compact-sm"
 										onClick={timerDrawerToggle}
-										style={isCreatingTemplate ? { display: "none" } : undefined}
+										style={
+											loaderData.isCreatingTemplate ||
+											loaderData.isUpdatingWorkout
+												? { display: "none" }
+												: undefined
+										}
 									>
 										<RestTimer />
 									</Button>
@@ -434,20 +452,22 @@ export default function Page() {
 														notifications.show({
 															color: "red",
 															message: `Please give a name to the ${
-																isCreatingTemplate ? "template" : "workout"
+																loaderData.isCreatingTemplate
+																	? "template"
+																	: "workout"
 															}`,
 														});
 														return;
 													}
 													const yes = await confirmWrapper({
-														confirmation: isCreatingTemplate
+														confirmation: loaderData.isCreatingTemplate
 															? "Only sets that have data will added. Are you sure you want to save this template?"
 															: "Only sets marked as confirmed will be recorded. Are you sure you want to finish this workout?",
 													});
 													if (yes) {
 														const input = currentWorkoutToCreateWorkoutInput(
 															currentWorkout,
-															isCreatingTemplate,
+															loaderData.isCreatingTemplate,
 														);
 														for (const exercise of currentWorkout.exercises) {
 															queryClient.removeQueries({
@@ -458,7 +478,7 @@ export default function Page() {
 															});
 														}
 														stopTimer();
-														if (!isCreatingTemplate) {
+														if (!loaderData.isCreatingTemplate) {
 															events.createWorkout();
 															Cookies.remove(workoutCookieName);
 														}
@@ -467,7 +487,7 @@ export default function Page() {
 															{
 																method: "post",
 																action: withQuery(".", {
-																	intent: isCreatingTemplate
+																	intent: loaderData.isCreatingTemplate
 																		? "createTemplate"
 																		: "createWorkout",
 																}),
@@ -477,7 +497,10 @@ export default function Page() {
 													}
 												}}
 											>
-												{isCreatingTemplate ? "Save" : "Finish"}
+												{loaderData.isCreatingTemplate ||
+												loaderData.isUpdatingWorkout
+													? "Save"
+													: "Finish"}
 											</Button>
 										</>
 									) : null}
@@ -489,7 +512,7 @@ export default function Page() {
 										onClick={async () => {
 											const yes = await confirmWrapper({
 												confirmation: `Are you sure you want to cancel this ${
-													isCreatingTemplate ? "template" : "workout"
+													loaderData.isCreatingTemplate ? "template" : "workout"
 												}?`,
 											});
 											if (yes) {
@@ -526,7 +549,9 @@ export default function Page() {
 											variant="subtle"
 											onClick={() => setMeasurementsDrawerOpen(true)}
 											style={
-												isCreatingTemplate ? { display: "none" } : undefined
+												loaderData.isCreatingTemplate
+													? { display: "none" }
+													: undefined
 											}
 										>
 											Add measurement
@@ -545,7 +570,9 @@ export default function Page() {
 					)}
 				</ClientOnly>
 			) : (
-				<Text>Loading {isCreatingTemplate ? "template" : "workout"}...</Text>
+				<Text>
+					Loading {loaderData.isCreatingTemplate ? "template" : "workout"}...
+				</Text>
 			)}
 		</Container>
 	);
@@ -583,10 +610,12 @@ const RestTimer = () => {
 };
 
 const DurationTimer = () => {
-	forceUpdateEverySecond();
+	const { isCreatingTemplate, isUpdatingWorkout } =
+		useLoaderData<typeof loader>();
 	const [currentWorkout] = useCurrentWorkout();
 	const seconds = offsetDate(currentWorkout?.startTime);
-	const { isCreatingTemplate } = useLoaderData<typeof loader>();
+
+	forceUpdateEverySecond();
 
 	let format = "mm:ss";
 	if (seconds > 3600) format = `H:${format}`;
@@ -595,7 +624,7 @@ const DurationTimer = () => {
 		<StatDisplay
 			name="Duration"
 			value={dayjsLib.duration(seconds * 1000).format(format)}
-			isHidden={isCreatingTemplate}
+			isHidden={isCreatingTemplate || isUpdatingWorkout}
 		/>
 	);
 };
@@ -1152,8 +1181,8 @@ const ExerciseDisplay = (props: {
 																		workout.details.information.exercises[
 																			history.idx
 																		].sets;
-																	const converted = sets.map(
-																		convertHistorySetToCurrentSet,
+																	const converted = sets.map((s) =>
+																		convertHistorySetToCurrentSet(s),
 																	);
 																	setCurrentWorkout(
 																		produce(currentWorkout, (draft) => {
@@ -1317,6 +1346,33 @@ const RestTimerProgress = (props: { onClick: () => void }) => {
 	);
 };
 
+const getNextSetInWorkout = (
+	currentWorkout: InProgressWorkout,
+	currentExerciseIdx: number,
+	currentSetIdx: number,
+) => {
+	const currentExercise = currentWorkout.exercises[currentExerciseIdx];
+	if (currentExercise.supersetWith.length === 0) {
+		const isLastSet = currentSetIdx === currentExercise.sets.length - 1;
+		if (isLastSet)
+			return {
+				exerciseIdx: currentExerciseIdx + 1,
+				setIdx: 0,
+				wasLastSet: true,
+			};
+		return {
+			exerciseIdx: currentExerciseIdx,
+			setIdx: currentSetIdx + 1,
+			wasLastSet: false,
+		};
+	}
+	return {
+		exerciseIdx: currentExerciseIdx,
+		setIdx: currentSetIdx,
+		wasLastSet: false,
+	};
+};
+
 const SetDisplay = (props: {
 	setIdx: number;
 	repsCol: boolean;
@@ -1358,7 +1414,10 @@ const SetDisplay = (props: {
 			withBorder
 			id={`${props.exerciseIdx}-${props.setIdx}`}
 			shadow={isHighlighted ? "xl" : undefined}
-			style={{ borderColor: isHighlighted ? undefined : "transparent" }}
+			style={{
+				transition: "border-color 0.2s ease-in-out",
+				borderColor: isHighlighted ? undefined : "transparent",
+			}}
 		>
 			<Flex justify="space-between" align="center" py={4}>
 				<Menu>
@@ -1582,36 +1641,23 @@ const SetDisplay = (props: {
 												draft.exercises[props.exerciseIdx];
 											currentExercise.sets[props.setIdx].confirmedAt =
 												newConfirmed ? dayjsLib().toISOString() : null;
-											const isLastSet =
-												props.setIdx === currentExercise.sets.length - 1;
-											const nextExerciseIdx = props.exerciseIdx + 1;
-											const nextExercise = draft.exercises[nextExerciseIdx];
+											const nextSet = getNextSetInWorkout(
+												currentWorkout,
+												props.exerciseIdx,
+												props.setIdx,
+											);
 											if (newConfirmed) {
-												draft.highlightedSet = isLastSet
-													? {
-															exerciseIdx: nextExerciseIdx,
-															setIdx: 0,
-														}
-													: {
-															exerciseIdx: props.exerciseIdx,
-															setIdx: props.setIdx + 1,
-														};
-												setTimeout(() => {
-													setCurrentWorkout((w) =>
-														produce(w, (innerDraft) => {
-															if (innerDraft)
-																innerDraft.highlightedSet = undefined;
-														}),
-													);
-												}, 2000);
-												if (isLastSet) {
+												focusOnExercise(nextSet.exerciseIdx);
+												draft.highlightedSet = nextSet;
+												if (nextSet.wasLastSet) {
 													currentExercise.isShowDetailsOpen = false;
+													const nextExercise =
+														draft.exercises[nextSet.exerciseIdx];
 													const nextExerciseHasDetailsToShow =
 														nextExercise &&
 														exerciseHasDetailsToShow(nextExercise);
 													if (nextExerciseHasDetailsToShow)
 														nextExercise.isShowDetailsOpen = true;
-													focusOnExercise(nextExerciseIdx);
 												}
 											}
 										}),
diff --git a/apps/frontend/app/routes/_dashboard.fitness.$entity.$id._index.tsx b/apps/frontend/app/routes/_dashboard.fitness.$entity.$id._index.tsx
index 7261b9c760..cd800eff66 100644
--- a/apps/frontend/app/routes/_dashboard.fitness.$entity.$id._index.tsx
+++ b/apps/frontend/app/routes/_dashboard.fitness.$entity.$id._index.tsx
@@ -22,11 +22,11 @@ import type { MetaArgs_SingleFetch } from "@remix-run/react";
 import { Form, Link, useLoaderData } from "@remix-run/react";
 import {
 	DeleteUserWorkoutDocument,
-	DeleteWorkoutTemplateDocument,
+	DeleteUserWorkoutTemplateDocument,
 	EntityLot,
 	UpdateUserWorkoutDocument,
+	UserWorkoutTemplateDetailsDocument,
 	WorkoutDetailsDocument,
-	WorkoutTemplateDetailsDocument,
 } from "@ryot/generated/graphql/backend/graphql";
 import {
 	changeCase,
@@ -62,7 +62,12 @@ import {
 	displayDistanceWithUnit,
 	displayWeightWithUnit,
 } from "~/components/fitness";
-import { FitnessEntity, PRO_REQUIRED_MESSAGE, dayjsLib } from "~/lib/generals";
+import {
+	FitnessAction,
+	FitnessEntity,
+	PRO_REQUIRED_MESSAGE,
+	dayjsLib,
+} from "~/lib/generals";
 import {
 	useConfirmSubmit,
 	useCoreDetails,
@@ -105,15 +110,15 @@ export const loader = unstable_defineLoader(async ({ request, params }) => {
 			}
 			let template = null;
 			if (workoutDetails.details.templateId) {
-				const { workoutTemplateDetails } =
+				const { userWorkoutTemplateDetails } =
 					await serverGqlService.authenticatedRequest(
 						request,
-						WorkoutTemplateDetailsDocument,
+						UserWorkoutTemplateDetailsDocument,
 						{ workoutTemplateId: workoutDetails.details.templateId },
 					);
 				template = {
 					id: workoutDetails.details.templateId,
-					name: workoutTemplateDetails.details.name,
+					name: userWorkoutTemplateDetails.details.name,
 				};
 			}
 			return {
@@ -130,23 +135,23 @@ export const loader = unstable_defineLoader(async ({ request, params }) => {
 			};
 		})
 		.with(FitnessEntity.Templates, async () => {
-			const [{ workoutTemplateDetails }] = await Promise.all([
+			const [{ userWorkoutTemplateDetails }] = await Promise.all([
 				serverGqlService.authenticatedRequest(
 					request,
-					WorkoutTemplateDetailsDocument,
+					UserWorkoutTemplateDetailsDocument,
 					{ workoutTemplateId: entityId },
 				),
 			]);
 			return {
-				entityName: workoutTemplateDetails.details.name,
-				startTime: workoutTemplateDetails.details.createdOn,
+				entityName: userWorkoutTemplateDetails.details.name,
+				startTime: userWorkoutTemplateDetails.details.createdOn,
 				endTime: null,
-				information: workoutTemplateDetails.details.information,
-				summary: workoutTemplateDetails.details.summary,
+				information: userWorkoutTemplateDetails.details.information,
+				summary: userWorkoutTemplateDetails.details.summary,
 				repeatedWorkout: null,
 				template: null,
-				collections: workoutTemplateDetails.collections,
-				defaultRestTimer: workoutTemplateDetails.details.defaultRestTimer,
+				collections: userWorkoutTemplateDetails.collections,
+				defaultRestTimer: userWorkoutTemplateDetails.details.defaultRestTimer,
 			};
 		})
 		.exhaustive();
@@ -185,7 +190,7 @@ export const action = unstable_defineAction(async ({ request }) => {
 			else if (submission.templateId)
 				await serverGqlService.authenticatedRequest(
 					request,
-					DeleteWorkoutTemplateDocument,
+					DeleteUserWorkoutTemplateDocument,
 					{ workoutTemplateId: submission.templateId },
 				);
 			const { entity } = submission;
@@ -226,24 +231,22 @@ export default function Page() {
 		.with(FitnessEntity.Templates, () => EntityLot.WorkoutTemplate)
 		.exhaustive();
 
-	const performDecision = async (
-		entity: FitnessEntity,
-		repeatedFromId?: string,
-		templateId?: string,
-		updateWorkoutTemplateId?: string,
-		defaultRestTimer?: number | null,
-	) => {
+	const performDecision = async (params: {
+		action: FitnessAction;
+		repeatedFromId?: string;
+		templateId?: string;
+		updateWorkoutId?: string;
+		updateWorkoutTemplateId?: string;
+		defaultRestTimer?: number | null;
+	}) => {
 		setIsWorkoutLoading(true);
 		const workout = await duplicateOldWorkout(
 			loaderData.information,
 			loaderData.entityName,
 			coreDetails,
-			repeatedFromId,
-			templateId,
-			updateWorkoutTemplateId,
-			defaultRestTimer,
+			params,
 		);
-		startWorkout(workout, entity);
+		startWorkout(workout, params.action);
 		setIsWorkoutLoading(false);
 	};
 
@@ -304,13 +307,11 @@ export default function Page() {
 										<>
 											<Menu.Item
 												onClick={() =>
-													performDecision(
-														FitnessEntity.Workouts,
-														undefined,
-														loaderData.entityId,
-														undefined,
-														loaderData.defaultRestTimer,
-													)
+													performDecision({
+														action: FitnessAction.LogWorkout,
+														templateId: loaderData.entityId,
+														defaultRestTimer: loaderData.defaultRestTimer,
+													})
 												}
 												leftSection={<IconPlayerPlay size={14} />}
 											>
@@ -318,13 +319,11 @@ export default function Page() {
 											</Menu.Item>
 											<Menu.Item
 												onClick={() =>
-													performDecision(
-														FitnessEntity.Templates,
-														undefined,
-														undefined,
-														loaderData.entityId,
-														loaderData.defaultRestTimer,
-													)
+													performDecision({
+														action: FitnessAction.CreateTemplate,
+														updateWorkoutTemplateId: loaderData.entityId,
+														defaultRestTimer: loaderData.defaultRestTimer,
+													})
 												}
 												leftSection={<IconPencil size={14} />}
 											>
@@ -336,15 +335,27 @@ export default function Page() {
 										<>
 											<Menu.Item
 												onClick={() =>
-													performDecision(
-														FitnessEntity.Workouts,
-														loaderData.entityId,
-													)
+													performDecision({
+														action: FitnessAction.LogWorkout,
+														repeatedFromId: loaderData.entityId,
+													})
 												}
 												leftSection={<IconRepeat size={14} />}
 											>
 												Duplicate
 											</Menu.Item>
+											<Menu.Item
+												onClick={() =>
+													performDecision({
+														action: FitnessAction.UpdateWorkout,
+														updateWorkoutId: loaderData.entityId,
+														defaultRestTimer: loaderData.defaultRestTimer,
+													})
+												}
+												leftSection={<IconPencil size={14} />}
+											>
+												Edit workout
+											</Menu.Item>
 											<Menu.Item
 												onClick={adjustTimeModalOpen}
 												leftSection={<IconClockEdit size={14} />}
@@ -360,7 +371,9 @@ export default function Page() {
 														});
 														return;
 													}
-													performDecision(FitnessEntity.Templates);
+													performDecision({
+														action: FitnessAction.CreateTemplate,
+													});
 												}}
 												leftSection={<IconTemplate size={14} />}
 											>
diff --git a/apps/frontend/app/routes/_dashboard.fitness.$entity.list.tsx b/apps/frontend/app/routes/_dashboard.fitness.$entity.list.tsx
index c1a98e3d42..3bc4d38587 100644
--- a/apps/frontend/app/routes/_dashboard.fitness.$entity.list.tsx
+++ b/apps/frontend/app/routes/_dashboard.fitness.$entity.list.tsx
@@ -45,6 +45,7 @@ import {
 	getSetStatisticsTextToDisplay,
 } from "~/components/fitness";
 import {
+	FitnessAction,
 	FitnessEntity,
 	PRO_REQUIRED_MESSAGE,
 	dayjsLib,
@@ -159,7 +160,16 @@ export default function Page() {
 								});
 								return;
 							}
-							startWorkout(getDefaultWorkout(), loaderData.entity);
+							startWorkout(
+								getDefaultWorkout(),
+								match(loaderData.entity)
+									.with(FitnessEntity.Workouts, () => FitnessAction.LogWorkout)
+									.with(
+										FitnessEntity.Templates,
+										() => FitnessAction.CreateTemplate,
+									)
+									.exhaustive(),
+							);
 						}}
 					>
 						<IconPlus size={16} />
diff --git a/apps/frontend/app/routes/_dashboard.tsx b/apps/frontend/app/routes/_dashboard.tsx
index 82cc60502f..baa43ec154 100644
--- a/apps/frontend/app/routes/_dashboard.tsx
+++ b/apps/frontend/app/routes/_dashboard.tsx
@@ -105,6 +105,7 @@ import { $path } from "remix-routes";
 import { match } from "ts-pattern";
 import { joinURL, withQuery } from "ufo";
 import {
+	FitnessAction,
 	LOGO_IMAGE_URL,
 	ThreePointSmileyRating,
 	Verb,
@@ -393,8 +394,9 @@ export default function Layout() {
 	return (
 		<>
 			{loaderData.workoutInProgress &&
-			location.pathname !==
-				$path("/fitness/:action", { action: "log-workout" }) ? (
+			Object.values(FitnessAction)
+				.map((action) => $path("/fitness/:action", { action }))
+				.includes(location.pathname) ? (
 				<Tooltip label="You have an active workout" position="left">
 					<Affix
 						position={{
@@ -414,7 +416,11 @@ export default function Layout() {
 							radius="xl"
 							size="xl"
 							onClick={() =>
-								navigate($path("/fitness/:action", { action: "log-workout" }))
+								navigate(
+									$path("/fitness/:action", {
+										action: FitnessAction.LogWorkout,
+									}),
+								)
 							}
 						>
 							<IconStretching size={32} />
diff --git a/apps/frontend/package.json b/apps/frontend/package.json
index 71283dbae6..0dd0e7c555 100644
--- a/apps/frontend/package.json
+++ b/apps/frontend/package.json
@@ -19,6 +19,7 @@
 		"@mantine/form": "7.12.1",
 		"@mantine/hooks": "7.12.1",
 		"@mantine/notifications": "7.12.1",
+		"@remix-pwa/sw": "3.0.10",
 		"@remix-pwa/worker-runtime": "2.1.4",
 		"@remix-run/node": "2.11.2",
 		"@remix-run/react": "2.11.2",
diff --git a/crates/models/fitness/src/lib.rs b/crates/models/fitness/src/lib.rs
index af24fa847c..7dccd950fa 100644
--- a/crates/models/fitness/src/lib.rs
+++ b/crates/models/fitness/src/lib.rs
@@ -513,9 +513,6 @@ pub struct UserExerciseInput {
 #[derive(Clone, Debug, Deserialize, Serialize, InputObject)]
 pub struct UserWorkoutInput {
     pub name: String,
-    // If specified, the workout will be created with this ID.
-    #[graphql(skip_input)]
-    pub id: Option<String>,
     pub end_time: DateTimeUtc,
     pub comment: Option<String>,
     pub start_time: DateTimeUtc,
@@ -523,7 +520,11 @@ pub struct UserWorkoutInput {
     pub assets: Option<EntityAssets>,
     pub repeated_from: Option<String>,
     pub default_rest_timer: Option<i32>,
+    // If specified, the workout will be created with this ID.
+    #[graphql(skip_input)]
+    pub create_workout_id: Option<String>,
     pub exercises: Vec<UserExerciseInput>,
+    pub update_workout_id: Option<String>,
     pub update_workout_template_id: Option<String>,
 }
 
diff --git a/crates/resolvers/fitness/src/lib.rs b/crates/resolvers/fitness/src/lib.rs
index 1af176b8fa..664170ac35 100644
--- a/crates/resolvers/fitness/src/lib.rs
+++ b/crates/resolvers/fitness/src/lib.rs
@@ -34,7 +34,7 @@ impl ExerciseQuery {
     }
 
     /// Get information about a workout template.
-    async fn workout_template_details(
+    async fn user_workout_template_details(
         &self,
         gql_ctx: &Context<'_>,
         workout_template_id: String,
@@ -42,7 +42,7 @@ impl ExerciseQuery {
         let service = gql_ctx.data_unchecked::<Arc<ExerciseService>>();
         let user_id = self.user_id_from_ctx(gql_ctx).await?;
         service
-            .workout_template_details(user_id, workout_template_id)
+            .user_workout_template_details(user_id, workout_template_id)
             .await
     }
 
@@ -130,7 +130,7 @@ impl AuthProvider for ExerciseMutation {
 #[Object]
 impl ExerciseMutation {
     /// Create or update a workout template.
-    async fn create_or_update_workout_template(
+    async fn create_or_update_user_workout_template(
         &self,
         gql_ctx: &Context<'_>,
         input: UserWorkoutInput,
@@ -138,12 +138,12 @@ impl ExerciseMutation {
         let service = gql_ctx.data_unchecked::<Arc<ExerciseService>>();
         let user_id = self.user_id_from_ctx(gql_ctx).await?;
         service
-            .create_or_update_workout_template(user_id, input)
+            .create_or_update_user_workout_template(user_id, input)
             .await
     }
 
     /// Delete a workout template.
-    async fn delete_workout_template(
+    async fn delete_user_workout_template(
         &self,
         gql_ctx: &Context<'_>,
         workout_template_id: String,
@@ -151,7 +151,7 @@ impl ExerciseMutation {
         let service = gql_ctx.data_unchecked::<Arc<ExerciseService>>();
         let user_id = self.user_id_from_ctx(gql_ctx).await?;
         service
-            .delete_workout_template(user_id, workout_template_id)
+            .delete_user_workout_template(user_id, workout_template_id)
             .await
     }
 
@@ -178,14 +178,14 @@ impl ExerciseMutation {
     }
 
     /// Take a user workout, process it and commit it to database.
-    async fn create_user_workout(
+    async fn create_or_update_user_workout(
         &self,
         gql_ctx: &Context<'_>,
         input: UserWorkoutInput,
     ) -> Result<String> {
         let service = gql_ctx.data_unchecked::<Arc<ExerciseService>>();
         let user_id = self.user_id_from_ctx(gql_ctx).await?;
-        service.create_user_workout(&user_id, input).await
+        service.create_or_update_user_workout(&user_id, input).await
     }
 
     /// Change the details about a user's workout.
diff --git a/crates/services/fitness/src/lib.rs b/crates/services/fitness/src/lib.rs
index 59d165cbc3..e39f1486b8 100644
--- a/crates/services/fitness/src/lib.rs
+++ b/crates/services/fitness/src/lib.rs
@@ -16,8 +16,9 @@ use database_models::{
     user_measurement, user_to_entity, workout, workout_template,
 };
 use database_utils::{
-    add_entity_to_collection, entity_in_collections, ilike_sql, item_reviews, pro_instance_guard,
-    user_measurements_list, workout_details, workout_template_details,
+    add_entity_to_collection, deploy_job_to_re_evaluate_user_workouts, entity_in_collections,
+    ilike_sql, item_reviews, pro_instance_guard, user_measurements_list, workout_details,
+    workout_template_details,
 };
 use dependent_models::{
     SearchResults, UpdateCustomExerciseInput, UserExerciseDetails, UserWorkoutDetails,
@@ -46,7 +47,7 @@ use sea_orm::{
 use sea_query::{extension::postgres::PgExpr, Alias, Condition, Expr, Func, JoinType, OnConflict};
 use slug::slugify;
 
-use logic::{calculate_and_commit, delete_existing_workout};
+use logic::{create_or_update_workout, delete_existing_workout};
 
 mod logic;
 
@@ -128,7 +129,7 @@ impl ExerciseService {
         })
     }
 
-    pub async fn workout_template_details(
+    pub async fn user_workout_template_details(
         &self,
         user_id: String,
         workout_template_id: String,
@@ -136,7 +137,7 @@ impl ExerciseService {
         workout_template_details(&self.db, &user_id, workout_template_id).await
     }
 
-    pub async fn create_or_update_workout_template(
+    pub async fn create_or_update_user_workout_template(
         &self,
         user_id: String,
         input: UserWorkoutInput,
@@ -212,7 +213,7 @@ impl ExerciseService {
         Ok(template.id)
     }
 
-    pub async fn delete_workout_template(
+    pub async fn delete_user_workout_template(
         &self,
         user_id: String,
         workout_template_id: String,
@@ -572,12 +573,14 @@ impl ExerciseService {
         }
     }
 
-    pub async fn create_user_workout(
+    pub async fn create_or_update_user_workout(
         &self,
         user_id: &String,
         input: UserWorkoutInput,
     ) -> Result<String> {
-        let identifier = calculate_and_commit(input, user_id, &self.db).await?;
+        let identifier =
+            create_or_update_workout(input, user_id, &self.db, &self.perform_application_job)
+                .await?;
         Ok(identifier)
     }
 
@@ -601,10 +604,8 @@ impl ExerciseService {
             }
             if new_wkt.is_changed() {
                 new_wkt.update(&self.db).await?;
-                self.perform_application_job
-                    .enqueue(ApplicationJob::ReEvaluateUserWorkouts(user_id))
-                    .await
-                    .unwrap();
+                deploy_job_to_re_evaluate_user_workouts(&self.perform_application_job, &user_id)
+                    .await;
                 Ok(true)
             } else {
                 Ok(false)
@@ -687,7 +688,8 @@ impl ExerciseService {
         for (idx, workout) in workouts.into_iter().enumerate() {
             workout.clone().delete(&self.db).await?;
             let workout_input = self.db_workout_to_workout_input(workout);
-            self.create_user_workout(&user_id, workout_input).await?;
+            self.create_or_update_user_workout(&user_id, workout_input)
+                .await?;
             ryot_log!(debug, "Re-evaluated workout: {}/{}", idx + 1, total);
         }
         Ok(())
@@ -696,7 +698,8 @@ impl ExerciseService {
     pub fn db_workout_to_workout_input(&self, user_workout: workout::Model) -> UserWorkoutInput {
         UserWorkoutInput {
             name: user_workout.name,
-            id: Some(user_workout.id),
+            create_workout_id: Some(user_workout.id),
+            update_workout_id: None,
             default_rest_timer: None,
             end_time: user_workout.end_time,
             update_workout_template_id: None,
diff --git a/crates/services/fitness/src/logic.rs b/crates/services/fitness/src/logic.rs
index 492fd9a9cd..0ee1a72d4a 100644
--- a/crates/services/fitness/src/logic.rs
+++ b/crates/services/fitness/src/logic.rs
@@ -1,9 +1,12 @@
 use anyhow::{bail, Result};
+use apalis::prelude::MemoryStorage;
+use background::ApplicationJob;
 use common_utils::ryot_log;
 use database_models::{
     prelude::{Exercise, UserToEntity, Workout},
     user_to_entity, workout,
 };
+use database_utils::deploy_job_to_re_evaluate_user_workouts;
 use fitness_models::{
     ExerciseBestSetRecord, ProcessedExercise, UserToExerciseBestSetExtraInformation,
     UserToExerciseExtraInformation, UserToExerciseHistoryExtraInformation, UserWorkoutInput,
@@ -53,16 +56,29 @@ fn get_index_of_highest_pb(
     record.and_then(|r| records.iter().position(|l| l == r))
 }
 
-/// Create a workout in the database and also update user and exercise associations.
-pub async fn calculate_and_commit(
+/// Create or update a workout in the database and also update user and exercise associations.
+pub async fn create_or_update_workout(
     input: UserWorkoutInput,
     user_id: &String,
     db: &DatabaseConnection,
+    perform_application_job: &MemoryStorage<ApplicationJob>,
 ) -> Result<String> {
     let end_time = input.end_time;
     let mut input = input;
-    let id = input.id.unwrap_or_else(|| format!("wor_{}", nanoid!(12)));
-    ryot_log!(debug, "Creating new workout with id = {}", id);
+    let (new_workout_id, to_update_workout) = match &input.update_workout_id {
+        Some(id) => (
+            id.to_owned(),
+            // DEV: Unwrap to make sure we error out early if the workout to edit does not exist
+            Some(Workout::find_by_id(id).one(db).await?.unwrap()),
+        ),
+        None => (
+            input
+                .create_workout_id
+                .unwrap_or_else(|| format!("wor_{}", nanoid!(12))),
+            None,
+        ),
+    };
+    ryot_log!(debug, "Creating new workout with id = {}", new_workout_id);
     let mut exercises = vec![];
     let mut workout_totals = vec![];
     if input.exercises.is_empty() {
@@ -99,7 +115,7 @@ pub async fn calculate_and_commit(
         let history_item = UserToExerciseHistoryExtraInformation {
             best_set: None,
             idx: exercise_idx,
-            workout_id: id.clone(),
+            workout_id: new_workout_id.clone(),
             workout_end_on: end_time,
         };
         let association = match association {
@@ -223,7 +239,7 @@ pub async fn calculate_and_commit(
             if let Some(set_personal_bests) = &set.personal_bests {
                 for best in set_personal_bests.iter() {
                     let to_insert_record = ExerciseBestSetRecord {
-                        workout_id: id.clone(),
+                        workout_id: new_workout_id.clone(),
                         exercise_idx,
                         set_idx,
                     };
@@ -269,12 +285,12 @@ pub async fn calculate_and_commit(
     }
     let summary_total = workout_totals.into_iter().sum();
     let model = workout::Model {
-        id,
         end_time,
+        name: input.name,
+        user_id: user_id.clone(),
+        id: new_workout_id.clone(),
         start_time: input.start_time,
         repeated_from: input.repeated_from,
-        user_id: user_id.clone(),
-        name: input.name,
         summary: WorkoutSummary {
             total: Some(summary_total),
             exercises: exercises
@@ -298,7 +314,16 @@ pub async fn calculate_and_commit(
     };
     let mut insert: workout::ActiveModel = model.into();
     insert.duration = ActiveValue::NotSet;
+    if let Some(old_workout) = to_update_workout.clone() {
+        insert.end_time = ActiveValue::Set(old_workout.end_time);
+        insert.start_time = ActiveValue::Set(old_workout.start_time);
+        insert.repeated_from = ActiveValue::Set(old_workout.repeated_from.clone());
+        old_workout.delete(db).await?;
+    }
     let data = insert.insert(db).await?;
+    if to_update_workout.is_some() {
+        deploy_job_to_re_evaluate_user_workouts(perform_application_job, user_id).await;
+    }
     Ok(data.id)
 }
 
diff --git a/crates/services/importer/src/lib.rs b/crates/services/importer/src/lib.rs
index 5aa9e7765c..956f6af763 100644
--- a/crates/services/importer/src/lib.rs
+++ b/crates/services/importer/src/lib.rs
@@ -419,7 +419,7 @@ impl ImporterService {
         for workout in import.workouts.clone() {
             if let Err(err) = self
                 .exercise_service
-                .create_user_workout(&user_id, workout)
+                .create_or_update_user_workout(&user_id, workout)
                 .await
             {
                 import.failed_items.push(ImportFailedItem {
diff --git a/crates/services/importer/src/strong_app.rs b/crates/services/importer/src/strong_app.rs
index 96668b78d5..aae3a67c98 100644
--- a/crates/services/importer/src/strong_app.rs
+++ b/crates/services/importer/src/strong_app.rs
@@ -122,7 +122,7 @@ pub async fn import(
                 Duration::try_seconds(0).unwrap()
             };
             workouts.push(UserWorkoutInput {
-                id: None,
+                create_workout_id: None,
                 template_id: None,
                 repeated_from: None,
                 default_rest_timer: None,
@@ -132,6 +132,7 @@ pub async fn import(
                 end_time: ndt + workout_duration,
                 exercises,
                 assets: None,
+                update_workout_id: None,
                 update_workout_template_id: None,
             });
             exercises = vec![];
diff --git a/crates/services/miscellaneous/src/lib.rs b/crates/services/miscellaneous/src/lib.rs
index e4dde1986d..a6e978c192 100644
--- a/crates/services/miscellaneous/src/lib.rs
+++ b/crates/services/miscellaneous/src/lib.rs
@@ -1,5 +1,6 @@
 use std::{
     collections::{HashMap, HashSet},
+    hash::Hash as StdHash,
     iter::zip,
     sync::Arc,
 };
@@ -32,9 +33,10 @@ use database_models::{
 };
 use database_utils::{
     add_entity_to_collection, admin_account_guard, apply_collection_filter,
-    calculate_user_activities_and_summary, entity_in_collections,
-    entity_in_collections_with_collection_to_entity_ids, ilike_sql, item_reviews,
-    remove_entity_from_collection, revoke_access_link, user_by_id, user_preferences_by_id,
+    calculate_user_activities_and_summary, deploy_job_to_re_evaluate_user_workouts,
+    entity_in_collections, entity_in_collections_with_collection_to_entity_ids, ilike_sql,
+    item_reviews, remove_entity_from_collection, revoke_access_link, user_by_id,
+    user_preferences_by_id,
 };
 use dependent_models::{
     CoreDetails, GenreDetails, MetadataBaseData, MetadataGroupDetails, PersonDetails,
@@ -145,14 +147,14 @@ pub struct MiscellaneousService {
     db: DatabaseConnection,
     timezone: Arc<chrono_tz::Tz>,
     config: Arc<config::AppConfig>,
+    commit_cache: Cache<CommitCache, ()>,
     file_storage_service: Arc<FileStorageService>,
-    perform_application_job: MemoryStorage<ApplicationJob>,
     seen_progress_cache: Cache<ProgressUpdateCache, ()>,
+    perform_application_job: MemoryStorage<ApplicationJob>,
     perform_core_application_job: MemoryStorage<CoreApplicationJob>,
-    commit_cache: Cache<CommitCache, ()>,
 }
 
-fn create_disk_cache<T: Eq + std::hash::Hash + Sync + Send + 'static>(hours: i64) -> Cache<T, ()> {
+fn create_disk_cache<T: Eq + StdHash + Sync + Send + 'static>(hours: i64) -> Cache<T, ()> {
     Cache::builder()
         .time_to_live(ChronoDuration::try_hours(hours).unwrap().to_std().unwrap())
         .build()
@@ -1125,7 +1127,7 @@ ORDER BY RANDOM() LIMIT 10;
         &self,
         input: ProgressUpdateInput,
         user_id: &String,
-        // update only if media has not been consumed for this user in the last `n` duration
+        // DEV: update only if media has not been consumed for this user in the last `n` duration
         respect_cache: bool,
     ) -> Result<ProgressUpdateResultUnion> {
         let cache = ProgressUpdateCache {
@@ -1140,6 +1142,7 @@ ORDER BY RANDOM() LIMIT 10;
         };
         let in_cache = self.seen_progress_cache.get(&cache).await;
         if respect_cache && in_cache.is_some() {
+            ryot_log!(debug, "Seen is already in cache");
             return Ok(ProgressUpdateResultUnion::Error(ProgressUpdateError {
                 error: ProgressUpdateErrorVariant::AlreadySeen,
             }));
@@ -1203,6 +1206,7 @@ ORDER BY RANDOM() LIMIT 10;
                 let progress = input.progress.unwrap();
                 let watched_on = prev_seen.provider_watched_on.clone();
                 if prev_seen.progress == progress && watched_on == input.provider_watched_on {
+                    ryot_log!(debug, "No progress update required");
                     return Ok(ProgressUpdateResultUnion::Error(ProgressUpdateError {
                         error: ProgressUpdateErrorVariant::UpdateWithoutProgressUpdate,
                     }));
@@ -1440,10 +1444,7 @@ ORDER BY RANDOM() LIMIT 10;
                     .unwrap();
             }
             BackgroundJob::ReEvaluateUserWorkouts => {
-                storage
-                    .enqueue(ApplicationJob::ReEvaluateUserWorkouts(user_id.to_owned()))
-                    .await
-                    .unwrap();
+                deploy_job_to_re_evaluate_user_workouts(storage, user_id).await;
             }
         };
         Ok(true)
diff --git a/crates/services/user/src/lib.rs b/crates/services/user/src/lib.rs
index b7fcc7128c..eb279c50b4 100644
--- a/crates/services/user/src/lib.rs
+++ b/crates/services/user/src/lib.rs
@@ -342,7 +342,7 @@ impl UserService {
             &user.id,
             false,
         )
-        .await?;
+        .await;
         Ok(RegisterResult::Ok(StringIdObject { id: user.id }))
     }
 
diff --git a/crates/utils/database/src/lib.rs b/crates/utils/database/src/lib.rs
index 836985e5b2..66c59c96a2 100644
--- a/crates/utils/database/src/lib.rs
+++ b/crates/utils/database/src/lib.rs
@@ -791,7 +791,7 @@ pub async fn deploy_job_to_calculate_user_activities_and_summary(
     perform_application_job: &MemoryStorage<ApplicationJob>,
     user_id: &String,
     calculate_from_beginning: bool,
-) -> Result<()> {
+) {
     perform_application_job
         .clone()
         .enqueue(ApplicationJob::RecalculateUserActivitiesAndSummary(
@@ -800,5 +800,15 @@ pub async fn deploy_job_to_calculate_user_activities_and_summary(
         ))
         .await
         .unwrap();
-    Ok(())
+}
+
+pub async fn deploy_job_to_re_evaluate_user_workouts(
+    perform_application_job: &MemoryStorage<ApplicationJob>,
+    user_id: &String,
+) {
+    perform_application_job
+        .clone()
+        .enqueue(ApplicationJob::ReEvaluateUserWorkouts(user_id.to_owned()))
+        .await
+        .unwrap();
 }
diff --git a/libs/generated/src/graphql/backend/gql.ts b/libs/generated/src/graphql/backend/gql.ts
index f7a012509e..8f09970948 100644
--- a/libs/generated/src/graphql/backend/gql.ts
+++ b/libs/generated/src/graphql/backend/gql.ts
@@ -13,7 +13,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
  * Therefore it is highly recommended to use the babel or swc plugin for production.
  */
 const documents = {
-    "mutation RegisterUser($input: RegisterUserInput!) {\n  registerUser(input: $input) {\n    __typename\n    ... on RegisterError {\n      error\n    }\n    ... on StringIdObject {\n      id\n    }\n  }\n}\n\nmutation LoginUser($input: AuthUserInput!) {\n  loginUser(input: $input) {\n    __typename\n    ... on LoginError {\n      error\n    }\n    ... on LoginResponse {\n      apiKey\n    }\n  }\n}\n\nmutation AddEntityToCollection($input: ChangeCollectionToEntityInput!) {\n  addEntityToCollection(input: $input)\n}\n\nmutation CommitMetadata($input: CommitMediaInput!) {\n  commitMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CommitMetadataGroup($input: CommitMediaInput!) {\n  commitMetadataGroup(input: $input) {\n    id\n  }\n}\n\nmutation CommitPerson($input: CommitPersonInput!) {\n  commitPerson(input: $input) {\n    id\n  }\n}\n\nmutation CreateCustomExercise($input: ExerciseInput!) {\n  createCustomExercise(input: $input)\n}\n\nmutation UpdateCustomExercise($input: UpdateCustomExerciseInput!) {\n  updateCustomExercise(input: $input)\n}\n\nmutation UpdateUserIntegration($input: UpdateUserIntegrationInput!) {\n  updateUserIntegration(input: $input)\n}\n\nmutation CreateCustomMetadata($input: CreateCustomMetadataInput!) {\n  createCustomMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateCollection($input: CreateOrUpdateCollectionInput!) {\n  createOrUpdateCollection(input: $input) {\n    id\n  }\n}\n\nmutation CreateReviewComment($input: CreateReviewCommentInput!) {\n  createReviewComment(input: $input)\n}\n\nmutation CreateUserMeasurement($input: UserMeasurementInput!) {\n  createUserMeasurement(input: $input)\n}\n\nmutation CreateUserNotificationPlatform($input: CreateUserNotificationPlatformInput!) {\n  createUserNotificationPlatform(input: $input)\n}\n\nmutation CreateUserIntegration($input: CreateUserIntegrationInput!) {\n  createUserIntegration(input: $input) {\n    id\n  }\n}\n\nmutation CreateUserWorkout($input: UserWorkoutInput!) {\n  createUserWorkout(input: $input)\n}\n\nmutation CreateOrUpdateWorkoutTemplate($input: UserWorkoutInput!) {\n  createOrUpdateWorkoutTemplate(input: $input)\n}\n\nmutation DeleteCollection($collectionName: String!) {\n  deleteCollection(collectionName: $collectionName)\n}\n\nmutation DeleteReview($reviewId: String!) {\n  deleteReview(reviewId: $reviewId)\n}\n\nmutation DeleteS3Object($key: String!) {\n  deleteS3Object(key: $key)\n}\n\nmutation DeleteSeenItem($seenId: String!) {\n  deleteSeenItem(seenId: $seenId) {\n    id\n  }\n}\n\nmutation DeleteUser($toDeleteUserId: String!) {\n  deleteUser(toDeleteUserId: $toDeleteUserId)\n}\n\nmutation DeleteUserIntegration($integrationId: String!) {\n  deleteUserIntegration(integrationId: $integrationId)\n}\n\nmutation DeleteUserMeasurement($timestamp: DateTime!) {\n  deleteUserMeasurement(timestamp: $timestamp)\n}\n\nmutation DeleteUserNotificationPlatform($notificationId: String!) {\n  deleteUserNotificationPlatform(notificationId: $notificationId)\n}\n\nmutation DeleteUserWorkout($workoutId: String!) {\n  deleteUserWorkout(workoutId: $workoutId)\n}\n\nmutation DeleteWorkoutTemplate($workoutTemplateId: String!) {\n  deleteWorkoutTemplate(workoutTemplateId: $workoutTemplateId)\n}\n\nmutation DeployBackgroundJob($jobName: BackgroundJob!) {\n  deployBackgroundJob(jobName: $jobName)\n}\n\nmutation DeployBulkProgressUpdate($input: [ProgressUpdateInput!]!) {\n  deployBulkProgressUpdate(input: $input)\n}\n\nmutation DeployExportJob {\n  deployExportJob\n}\n\nmutation DeployImportJob($input: DeployImportJobInput!) {\n  deployImportJob(input: $input)\n}\n\nmutation DeployUpdateMetadataJob($metadataId: String!) {\n  deployUpdateMetadataJob(metadataId: $metadataId)\n}\n\nmutation DeployUpdatePersonJob($personId: String!) {\n  deployUpdatePersonJob(personId: $personId)\n}\n\nmutation DeployUpdateMetadataGroupJob($metadataGroupId: String!) {\n  deployUpdateMetadataGroupJob(metadataGroupId: $metadataGroupId)\n}\n\nmutation UpdateSeenItem($input: UpdateSeenItemInput!) {\n  updateSeenItem(input: $input)\n}\n\nmutation UpdateUserNotificationPlatform($input: UpdateUserNotificationPlatformInput!) {\n  updateUserNotificationPlatform(input: $input)\n}\n\nmutation UpdateUserWorkout($input: UpdateUserWorkoutInput!) {\n  updateUserWorkout(input: $input)\n}\n\nmutation GenerateAuthToken {\n  generateAuthToken\n}\n\nmutation MergeMetadata($mergeFrom: String!, $mergeInto: String!) {\n  mergeMetadata(mergeFrom: $mergeFrom, mergeInto: $mergeInto)\n}\n\nmutation DisassociateMetadata($metadataId: String!) {\n  disassociateMetadata(metadataId: $metadataId)\n}\n\nmutation PostReview($input: PostReviewInput!) {\n  postReview(input: $input) {\n    id\n  }\n}\n\nmutation PresignedPutS3Url($input: PresignedPutUrlInput!) {\n  presignedPutS3Url(input: $input) {\n    key\n    uploadUrl\n  }\n}\n\nmutation RemoveEntityFromCollection($input: ChangeCollectionToEntityInput!) {\n  removeEntityFromCollection(input: $input) {\n    id\n  }\n}\n\nmutation TestUserNotificationPlatforms {\n  testUserNotificationPlatforms\n}\n\nmutation UpdateUser($input: UpdateUserInput!) {\n  updateUser(input: $input) {\n    id\n  }\n}\n\nmutation UpdateUserPreference($input: UpdateUserPreferenceInput!) {\n  updateUserPreference(input: $input)\n}\n\nmutation CreateAccessLink($input: CreateAccessLinkInput!) {\n  createAccessLink(input: $input) {\n    id\n  }\n}\n\nmutation ProcessAccessLink($input: ProcessAccessLinkInput!) {\n  processAccessLink(input: $input) {\n    __typename\n    ... on ProcessAccessLinkError {\n      error\n    }\n    ... on ProcessAccessLinkResponse {\n      apiKey\n      redirectTo\n      tokenValidForDays\n    }\n  }\n}\n\nmutation revokeAccessLink($accessLinkId: String!) {\n  revokeAccessLink(accessLinkId: $accessLinkId)\n}": types.RegisterUserDocument,
+    "mutation RegisterUser($input: RegisterUserInput!) {\n  registerUser(input: $input) {\n    __typename\n    ... on RegisterError {\n      error\n    }\n    ... on StringIdObject {\n      id\n    }\n  }\n}\n\nmutation LoginUser($input: AuthUserInput!) {\n  loginUser(input: $input) {\n    __typename\n    ... on LoginError {\n      error\n    }\n    ... on LoginResponse {\n      apiKey\n    }\n  }\n}\n\nmutation AddEntityToCollection($input: ChangeCollectionToEntityInput!) {\n  addEntityToCollection(input: $input)\n}\n\nmutation CommitMetadata($input: CommitMediaInput!) {\n  commitMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CommitMetadataGroup($input: CommitMediaInput!) {\n  commitMetadataGroup(input: $input) {\n    id\n  }\n}\n\nmutation CommitPerson($input: CommitPersonInput!) {\n  commitPerson(input: $input) {\n    id\n  }\n}\n\nmutation CreateCustomExercise($input: ExerciseInput!) {\n  createCustomExercise(input: $input)\n}\n\nmutation UpdateCustomExercise($input: UpdateCustomExerciseInput!) {\n  updateCustomExercise(input: $input)\n}\n\nmutation UpdateUserIntegration($input: UpdateUserIntegrationInput!) {\n  updateUserIntegration(input: $input)\n}\n\nmutation CreateCustomMetadata($input: CreateCustomMetadataInput!) {\n  createCustomMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateCollection($input: CreateOrUpdateCollectionInput!) {\n  createOrUpdateCollection(input: $input) {\n    id\n  }\n}\n\nmutation CreateReviewComment($input: CreateReviewCommentInput!) {\n  createReviewComment(input: $input)\n}\n\nmutation CreateUserMeasurement($input: UserMeasurementInput!) {\n  createUserMeasurement(input: $input)\n}\n\nmutation CreateUserNotificationPlatform($input: CreateUserNotificationPlatformInput!) {\n  createUserNotificationPlatform(input: $input)\n}\n\nmutation CreateUserIntegration($input: CreateUserIntegrationInput!) {\n  createUserIntegration(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateUserWorkout($input: UserWorkoutInput!) {\n  createOrUpdateUserWorkout(input: $input)\n}\n\nmutation CreateOrUpdateUserWorkoutTemplate($input: UserWorkoutInput!) {\n  createOrUpdateUserWorkoutTemplate(input: $input)\n}\n\nmutation DeleteCollection($collectionName: String!) {\n  deleteCollection(collectionName: $collectionName)\n}\n\nmutation DeleteReview($reviewId: String!) {\n  deleteReview(reviewId: $reviewId)\n}\n\nmutation DeleteS3Object($key: String!) {\n  deleteS3Object(key: $key)\n}\n\nmutation DeleteSeenItem($seenId: String!) {\n  deleteSeenItem(seenId: $seenId) {\n    id\n  }\n}\n\nmutation DeleteUser($toDeleteUserId: String!) {\n  deleteUser(toDeleteUserId: $toDeleteUserId)\n}\n\nmutation DeleteUserIntegration($integrationId: String!) {\n  deleteUserIntegration(integrationId: $integrationId)\n}\n\nmutation DeleteUserMeasurement($timestamp: DateTime!) {\n  deleteUserMeasurement(timestamp: $timestamp)\n}\n\nmutation DeleteUserNotificationPlatform($notificationId: String!) {\n  deleteUserNotificationPlatform(notificationId: $notificationId)\n}\n\nmutation DeleteUserWorkout($workoutId: String!) {\n  deleteUserWorkout(workoutId: $workoutId)\n}\n\nmutation DeleteUserWorkoutTemplate($workoutTemplateId: String!) {\n  deleteUserWorkoutTemplate(workoutTemplateId: $workoutTemplateId)\n}\n\nmutation DeployBackgroundJob($jobName: BackgroundJob!) {\n  deployBackgroundJob(jobName: $jobName)\n}\n\nmutation DeployBulkProgressUpdate($input: [ProgressUpdateInput!]!) {\n  deployBulkProgressUpdate(input: $input)\n}\n\nmutation DeployExportJob {\n  deployExportJob\n}\n\nmutation DeployImportJob($input: DeployImportJobInput!) {\n  deployImportJob(input: $input)\n}\n\nmutation DeployUpdateMetadataJob($metadataId: String!) {\n  deployUpdateMetadataJob(metadataId: $metadataId)\n}\n\nmutation DeployUpdatePersonJob($personId: String!) {\n  deployUpdatePersonJob(personId: $personId)\n}\n\nmutation DeployUpdateMetadataGroupJob($metadataGroupId: String!) {\n  deployUpdateMetadataGroupJob(metadataGroupId: $metadataGroupId)\n}\n\nmutation UpdateSeenItem($input: UpdateSeenItemInput!) {\n  updateSeenItem(input: $input)\n}\n\nmutation UpdateUserNotificationPlatform($input: UpdateUserNotificationPlatformInput!) {\n  updateUserNotificationPlatform(input: $input)\n}\n\nmutation UpdateUserWorkout($input: UpdateUserWorkoutInput!) {\n  updateUserWorkout(input: $input)\n}\n\nmutation GenerateAuthToken {\n  generateAuthToken\n}\n\nmutation MergeMetadata($mergeFrom: String!, $mergeInto: String!) {\n  mergeMetadata(mergeFrom: $mergeFrom, mergeInto: $mergeInto)\n}\n\nmutation DisassociateMetadata($metadataId: String!) {\n  disassociateMetadata(metadataId: $metadataId)\n}\n\nmutation PostReview($input: PostReviewInput!) {\n  postReview(input: $input) {\n    id\n  }\n}\n\nmutation PresignedPutS3Url($input: PresignedPutUrlInput!) {\n  presignedPutS3Url(input: $input) {\n    key\n    uploadUrl\n  }\n}\n\nmutation RemoveEntityFromCollection($input: ChangeCollectionToEntityInput!) {\n  removeEntityFromCollection(input: $input) {\n    id\n  }\n}\n\nmutation TestUserNotificationPlatforms {\n  testUserNotificationPlatforms\n}\n\nmutation UpdateUser($input: UpdateUserInput!) {\n  updateUser(input: $input) {\n    id\n  }\n}\n\nmutation UpdateUserPreference($input: UpdateUserPreferenceInput!) {\n  updateUserPreference(input: $input)\n}\n\nmutation CreateAccessLink($input: CreateAccessLinkInput!) {\n  createAccessLink(input: $input) {\n    id\n  }\n}\n\nmutation ProcessAccessLink($input: ProcessAccessLinkInput!) {\n  processAccessLink(input: $input) {\n    __typename\n    ... on ProcessAccessLinkError {\n      error\n    }\n    ... on ProcessAccessLinkResponse {\n      apiKey\n      redirectTo\n      tokenValidForDays\n    }\n  }\n}\n\nmutation revokeAccessLink($accessLinkId: String!) {\n  revokeAccessLink(accessLinkId: $accessLinkId)\n}": types.RegisterUserDocument,
     "query CollectionContents($input: CollectionContentsInput!) {\n  collectionContents(input: $input) {\n    user {\n      id\n      name\n    }\n    reviews {\n      ...ReviewItemPart\n    }\n    results {\n      details {\n        total\n        nextPage\n      }\n      items {\n        entityId\n        entityLot\n      }\n    }\n    details {\n      name\n      description\n      createdOn\n    }\n  }\n}": types.CollectionContentsDocument,
     "query CoreDetails {\n  coreDetails {\n    isPro\n    version\n    docsLink\n    pageLimit\n    websiteUrl\n    smtpEnabled\n    oidcEnabled\n    signupAllowed\n    repositoryLink\n    localAuthDisabled\n    fileStorageEnabled\n    tokenValidForDays\n  }\n}": types.CoreDetailsDocument,
     "query ExerciseDetails($exerciseId: String!) {\n  exerciseDetails(exerciseId: $exerciseId) {\n    id\n    lot\n    source\n    level\n    force\n    mechanic\n    equipment\n    muscles\n    createdByUserId\n    attributes {\n      instructions\n      images\n    }\n  }\n}": types.ExerciseDetailsDocument,
@@ -37,10 +37,10 @@ const documents = {
     "query UserMetadataGroupDetails($metadataGroupId: String!) {\n  userMetadataGroupDetails(metadataGroupId: $metadataGroupId) {\n    reviews {\n      ...ReviewItemPart\n    }\n    collections {\n      ...CollectionPart\n    }\n  }\n}": types.UserMetadataGroupDetailsDocument,
     "query UserPersonDetails($personId: String!) {\n  userPersonDetails(personId: $personId) {\n    collections {\n      ...CollectionPart\n    }\n    reviews {\n      ...ReviewItemPart\n    }\n  }\n}": types.UserPersonDetailsDocument,
     "query UserPreferences {\n  userPreferences {\n    general {\n      reviewScale\n      gridPacking\n      displayNsfw\n      disableVideos\n      persistQueries\n      watchProviders\n      disableReviews\n      disableIntegrations\n      disableWatchProviders\n      disableNavigationAnimation\n      dashboard {\n        section\n        hidden\n        numElements\n      }\n    }\n    fitness {\n      measurements {\n        custom {\n          name\n          dataType\n        }\n        inbuilt {\n          weight\n          bodyMassIndex\n          totalBodyWater\n          muscle\n          leanBodyMass\n          bodyFat\n          boneMass\n          visceralFat\n          waistCircumference\n          waistToHeightRatio\n          hipCircumference\n          waistToHipRatio\n          chestCircumference\n          thighCircumference\n          bicepsCircumference\n          neckCircumference\n          bodyFatCaliper\n          chestSkinfold\n          abdominalSkinfold\n          thighSkinfold\n          basalMetabolicRate\n          totalDailyEnergyExpenditure\n          calories\n        }\n      }\n      exercises {\n        unitSystem\n      }\n    }\n    notifications {\n      toSend\n      enabled\n    }\n    featuresEnabled {\n      others {\n        calendar\n        collections\n      }\n      fitness {\n        enabled\n        workouts\n        templates\n        measurements\n      }\n      media {\n        enabled\n        anime\n        audioBook\n        book\n        manga\n        movie\n        podcast\n        show\n        videoGame\n        visualNovel\n        people\n        groups\n        genres\n      }\n    }\n  }\n}": types.UserPreferencesDocument,
+    "query UserWorkoutTemplateDetails($workoutTemplateId: String!) {\n  userWorkoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      createdOn\n      visibility\n      defaultRestTimer\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}": types.UserWorkoutTemplateDetailsDocument,
     "query UserWorkoutTemplatesList($input: SearchInput!) {\n  userWorkoutTemplatesList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      createdOn\n      visibility\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}": types.UserWorkoutTemplatesListDocument,
     "query UserWorkoutsList($input: SearchInput!) {\n  userWorkoutsList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      endTime\n      duration\n      startTime\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}": types.UserWorkoutsListDocument,
     "query WorkoutDetails($workoutId: String!) {\n  workoutDetails(workoutId: $workoutId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      endTime\n      duration\n      startTime\n      templateId\n      repeatedFrom\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}": types.WorkoutDetailsDocument,
-    "query WorkoutTemplateDetails($workoutTemplateId: String!) {\n  workoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      createdOn\n      visibility\n      defaultRestTimer\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}": types.WorkoutTemplateDetailsDocument,
     "query GetOidcRedirectUrl {\n  getOidcRedirectUrl\n}\n\nquery UserByOidcIssuerId($oidcIssuerId: String!) {\n  userByOidcIssuerId(oidcIssuerId: $oidcIssuerId)\n}\n\nquery GetOidcToken($code: String!) {\n  getOidcToken(code: $code) {\n    subject\n    email\n  }\n}\n\nquery GetPresignedS3Url($key: String!) {\n  getPresignedS3Url(key: $key)\n}\n\nquery ProvidersLanguageInformation {\n  providersLanguageInformation {\n    supported\n    default\n    source\n  }\n}\n\nquery UserExports {\n  userExports {\n    url\n    size\n    endedAt\n    startedAt\n  }\n}\n\nquery UserCollectionsList($name: String) {\n  userCollectionsList(name: $name) {\n    id\n    name\n    count\n    isDefault\n    description\n    creator {\n      id\n      name\n    }\n    collaborators {\n      id\n      name\n    }\n    informationTemplate {\n      lot\n      name\n      required\n      description\n      defaultValue\n    }\n  }\n}\n\nquery UserIntegrations {\n  userIntegrations {\n    id\n    lot\n    provider\n    createdOn\n    isDisabled\n    maximumProgress\n    minimumProgress\n    lastTriggeredOn\n    syncToOwnedCollection\n  }\n}\n\nquery UserNotificationPlatforms {\n  userNotificationPlatforms {\n    id\n    lot\n    createdOn\n    isDisabled\n    description\n  }\n}\n\nquery UsersList($query: String) {\n  usersList(query: $query) {\n    id\n    lot\n    name\n    isDisabled\n  }\n}\n\nquery UserRecommendations {\n  userRecommendations\n}\n\nquery UserUpcomingCalendarEvents($input: UserUpcomingCalendarEventInput!) {\n  userUpcomingCalendarEvents(input: $input) {\n    ...CalendarEventPart\n  }\n}\n\nquery UserCalendarEvents($input: UserCalendarEventInput!) {\n  userCalendarEvents(input: $input) {\n    date\n    events {\n      ...CalendarEventPart\n    }\n  }\n}\n\nquery MetadataPartialDetails($metadataId: String!) {\n  metadataPartialDetails(metadataId: $metadataId) {\n    id\n    lot\n    title\n    image\n    publishYear\n  }\n}\n\nquery MetadataGroupsList($input: MetadataGroupsListInput!) {\n  metadataGroupsList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items\n  }\n}\n\nquery PeopleList($input: PeopleListInput!) {\n  peopleList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items\n  }\n}\n\nquery UserAccessLinks {\n  userAccessLinks {\n    id\n    name\n    isDemo\n    createdOn\n    expiresOn\n    timesUsed\n    isRevoked\n    maximumUses\n    isAccountDefault\n    isMutationAllowed\n  }\n}\n\nquery DailyUserActivities($input: DailyUserActivitiesInput!) {\n  dailyUserActivities(input: $input) {\n    groupedBy\n    totalCount\n    totalDuration\n    items {\n      day\n      totalReviewCount\n      workoutCount\n      measurementCount\n      audioBookCount\n      animeCount\n      bookCount\n      podcastCount\n      mangaCount\n      showCount\n      movieCount\n      videoGameCount\n      visualNovelCount\n    }\n  }\n}": types.GetOidcRedirectUrlDocument,
     "fragment SeenPodcastExtraInformationPart on SeenPodcastExtraInformation {\n  episode\n}\n\nfragment SeenShowExtraInformationPart on SeenShowExtraInformation {\n  episode\n  season\n}\n\nfragment SeenAnimeExtraInformationPart on SeenAnimeExtraInformation {\n  episode\n}\n\nfragment SeenMangaExtraInformationPart on SeenMangaExtraInformation {\n  chapter\n  volume\n}\n\nfragment CalendarEventPart on GraphqlCalendarEvent {\n  date\n  metadataId\n  metadataLot\n  episodeName\n  metadataTitle\n  metadataImage\n  calendarEventId\n  showExtraInformation {\n    ...SeenShowExtraInformationPart\n  }\n  podcastExtraInformation {\n    ...SeenPodcastExtraInformationPart\n  }\n  animeExtraInformation {\n    ...SeenAnimeExtraInformationPart\n  }\n}\n\nfragment SeenPart on Seen {\n  id\n  state\n  progress\n  startedOn\n  finishedOn\n  lastUpdatedOn\n  manualTimeSpent\n  numTimesUpdated\n  providerWatchedOn\n  showExtraInformation {\n    ...SeenShowExtraInformationPart\n  }\n  podcastExtraInformation {\n    ...SeenPodcastExtraInformationPart\n  }\n  animeExtraInformation {\n    ...SeenAnimeExtraInformationPart\n  }\n  mangaExtraInformation {\n    ...SeenMangaExtraInformationPart\n  }\n}\n\nfragment MetadataSearchItemPart on MetadataSearchItem {\n  identifier\n  title\n  image\n  publishYear\n}\n\nfragment WorkoutOrExerciseTotalsPart on WorkoutOrExerciseTotals {\n  personalBestsAchieved\n  weight\n  reps\n  distance\n  duration\n  restTime\n}\n\nfragment EntityAssetsPart on EntityAssets {\n  images\n  videos\n}\n\nfragment WorkoutSetStatisticPart on WorkoutSetStatistic {\n  duration\n  distance\n  reps\n  weight\n  oneRm\n  pace\n  volume\n}\n\nfragment WorkoutSetRecordPart on WorkoutSetRecord {\n  statistic {\n    ...WorkoutSetStatisticPart\n  }\n  lot\n  personalBests\n}\n\nfragment WorkoutSummaryPart on WorkoutSummary {\n  total {\n    ...WorkoutOrExerciseTotalsPart\n  }\n  exercises {\n    numSets\n    id\n    lot\n    bestSet {\n      ...WorkoutSetRecordPart\n    }\n  }\n}\n\nfragment CollectionPart on Collection {\n  id\n  name\n  userId\n}\n\nfragment ReviewItemPart on ReviewItem {\n  id\n  rating\n  textOriginal\n  textRendered\n  isSpoiler\n  visibility\n  postedOn\n  postedBy {\n    id\n    name\n  }\n  comments {\n    id\n    text\n    createdOn\n    user {\n      id\n      name\n    }\n    likedBy\n  }\n  showExtraInformation {\n    ...SeenShowExtraInformationPart\n  }\n  podcastExtraInformation {\n    ...SeenPodcastExtraInformationPart\n  }\n  animeExtraInformation {\n    ...SeenAnimeExtraInformationPart\n  }\n  mangaExtraInformation {\n    ...SeenMangaExtraInformationPart\n  }\n}\n\nfragment WorkoutInformationPart on WorkoutInformation {\n  comment\n  assets {\n    ...EntityAssetsPart\n  }\n  exercises {\n    name\n    lot\n    notes\n    restTime\n    total {\n      ...WorkoutOrExerciseTotalsPart\n    }\n    supersetWith\n    assets {\n      ...EntityAssetsPart\n    }\n    sets {\n      statistic {\n        ...WorkoutSetStatisticPart\n      }\n      note\n      lot\n      personalBests\n      confirmedAt\n    }\n  }\n}": types.SeenPodcastExtraInformationPartFragmentDoc,
 };
@@ -62,7 +62,7 @@ export function graphql(source: string): unknown;
 /**
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
  */
-export function graphql(source: "mutation RegisterUser($input: RegisterUserInput!) {\n  registerUser(input: $input) {\n    __typename\n    ... on RegisterError {\n      error\n    }\n    ... on StringIdObject {\n      id\n    }\n  }\n}\n\nmutation LoginUser($input: AuthUserInput!) {\n  loginUser(input: $input) {\n    __typename\n    ... on LoginError {\n      error\n    }\n    ... on LoginResponse {\n      apiKey\n    }\n  }\n}\n\nmutation AddEntityToCollection($input: ChangeCollectionToEntityInput!) {\n  addEntityToCollection(input: $input)\n}\n\nmutation CommitMetadata($input: CommitMediaInput!) {\n  commitMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CommitMetadataGroup($input: CommitMediaInput!) {\n  commitMetadataGroup(input: $input) {\n    id\n  }\n}\n\nmutation CommitPerson($input: CommitPersonInput!) {\n  commitPerson(input: $input) {\n    id\n  }\n}\n\nmutation CreateCustomExercise($input: ExerciseInput!) {\n  createCustomExercise(input: $input)\n}\n\nmutation UpdateCustomExercise($input: UpdateCustomExerciseInput!) {\n  updateCustomExercise(input: $input)\n}\n\nmutation UpdateUserIntegration($input: UpdateUserIntegrationInput!) {\n  updateUserIntegration(input: $input)\n}\n\nmutation CreateCustomMetadata($input: CreateCustomMetadataInput!) {\n  createCustomMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateCollection($input: CreateOrUpdateCollectionInput!) {\n  createOrUpdateCollection(input: $input) {\n    id\n  }\n}\n\nmutation CreateReviewComment($input: CreateReviewCommentInput!) {\n  createReviewComment(input: $input)\n}\n\nmutation CreateUserMeasurement($input: UserMeasurementInput!) {\n  createUserMeasurement(input: $input)\n}\n\nmutation CreateUserNotificationPlatform($input: CreateUserNotificationPlatformInput!) {\n  createUserNotificationPlatform(input: $input)\n}\n\nmutation CreateUserIntegration($input: CreateUserIntegrationInput!) {\n  createUserIntegration(input: $input) {\n    id\n  }\n}\n\nmutation CreateUserWorkout($input: UserWorkoutInput!) {\n  createUserWorkout(input: $input)\n}\n\nmutation CreateOrUpdateWorkoutTemplate($input: UserWorkoutInput!) {\n  createOrUpdateWorkoutTemplate(input: $input)\n}\n\nmutation DeleteCollection($collectionName: String!) {\n  deleteCollection(collectionName: $collectionName)\n}\n\nmutation DeleteReview($reviewId: String!) {\n  deleteReview(reviewId: $reviewId)\n}\n\nmutation DeleteS3Object($key: String!) {\n  deleteS3Object(key: $key)\n}\n\nmutation DeleteSeenItem($seenId: String!) {\n  deleteSeenItem(seenId: $seenId) {\n    id\n  }\n}\n\nmutation DeleteUser($toDeleteUserId: String!) {\n  deleteUser(toDeleteUserId: $toDeleteUserId)\n}\n\nmutation DeleteUserIntegration($integrationId: String!) {\n  deleteUserIntegration(integrationId: $integrationId)\n}\n\nmutation DeleteUserMeasurement($timestamp: DateTime!) {\n  deleteUserMeasurement(timestamp: $timestamp)\n}\n\nmutation DeleteUserNotificationPlatform($notificationId: String!) {\n  deleteUserNotificationPlatform(notificationId: $notificationId)\n}\n\nmutation DeleteUserWorkout($workoutId: String!) {\n  deleteUserWorkout(workoutId: $workoutId)\n}\n\nmutation DeleteWorkoutTemplate($workoutTemplateId: String!) {\n  deleteWorkoutTemplate(workoutTemplateId: $workoutTemplateId)\n}\n\nmutation DeployBackgroundJob($jobName: BackgroundJob!) {\n  deployBackgroundJob(jobName: $jobName)\n}\n\nmutation DeployBulkProgressUpdate($input: [ProgressUpdateInput!]!) {\n  deployBulkProgressUpdate(input: $input)\n}\n\nmutation DeployExportJob {\n  deployExportJob\n}\n\nmutation DeployImportJob($input: DeployImportJobInput!) {\n  deployImportJob(input: $input)\n}\n\nmutation DeployUpdateMetadataJob($metadataId: String!) {\n  deployUpdateMetadataJob(metadataId: $metadataId)\n}\n\nmutation DeployUpdatePersonJob($personId: String!) {\n  deployUpdatePersonJob(personId: $personId)\n}\n\nmutation DeployUpdateMetadataGroupJob($metadataGroupId: String!) {\n  deployUpdateMetadataGroupJob(metadataGroupId: $metadataGroupId)\n}\n\nmutation UpdateSeenItem($input: UpdateSeenItemInput!) {\n  updateSeenItem(input: $input)\n}\n\nmutation UpdateUserNotificationPlatform($input: UpdateUserNotificationPlatformInput!) {\n  updateUserNotificationPlatform(input: $input)\n}\n\nmutation UpdateUserWorkout($input: UpdateUserWorkoutInput!) {\n  updateUserWorkout(input: $input)\n}\n\nmutation GenerateAuthToken {\n  generateAuthToken\n}\n\nmutation MergeMetadata($mergeFrom: String!, $mergeInto: String!) {\n  mergeMetadata(mergeFrom: $mergeFrom, mergeInto: $mergeInto)\n}\n\nmutation DisassociateMetadata($metadataId: String!) {\n  disassociateMetadata(metadataId: $metadataId)\n}\n\nmutation PostReview($input: PostReviewInput!) {\n  postReview(input: $input) {\n    id\n  }\n}\n\nmutation PresignedPutS3Url($input: PresignedPutUrlInput!) {\n  presignedPutS3Url(input: $input) {\n    key\n    uploadUrl\n  }\n}\n\nmutation RemoveEntityFromCollection($input: ChangeCollectionToEntityInput!) {\n  removeEntityFromCollection(input: $input) {\n    id\n  }\n}\n\nmutation TestUserNotificationPlatforms {\n  testUserNotificationPlatforms\n}\n\nmutation UpdateUser($input: UpdateUserInput!) {\n  updateUser(input: $input) {\n    id\n  }\n}\n\nmutation UpdateUserPreference($input: UpdateUserPreferenceInput!) {\n  updateUserPreference(input: $input)\n}\n\nmutation CreateAccessLink($input: CreateAccessLinkInput!) {\n  createAccessLink(input: $input) {\n    id\n  }\n}\n\nmutation ProcessAccessLink($input: ProcessAccessLinkInput!) {\n  processAccessLink(input: $input) {\n    __typename\n    ... on ProcessAccessLinkError {\n      error\n    }\n    ... on ProcessAccessLinkResponse {\n      apiKey\n      redirectTo\n      tokenValidForDays\n    }\n  }\n}\n\nmutation revokeAccessLink($accessLinkId: String!) {\n  revokeAccessLink(accessLinkId: $accessLinkId)\n}"): (typeof documents)["mutation RegisterUser($input: RegisterUserInput!) {\n  registerUser(input: $input) {\n    __typename\n    ... on RegisterError {\n      error\n    }\n    ... on StringIdObject {\n      id\n    }\n  }\n}\n\nmutation LoginUser($input: AuthUserInput!) {\n  loginUser(input: $input) {\n    __typename\n    ... on LoginError {\n      error\n    }\n    ... on LoginResponse {\n      apiKey\n    }\n  }\n}\n\nmutation AddEntityToCollection($input: ChangeCollectionToEntityInput!) {\n  addEntityToCollection(input: $input)\n}\n\nmutation CommitMetadata($input: CommitMediaInput!) {\n  commitMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CommitMetadataGroup($input: CommitMediaInput!) {\n  commitMetadataGroup(input: $input) {\n    id\n  }\n}\n\nmutation CommitPerson($input: CommitPersonInput!) {\n  commitPerson(input: $input) {\n    id\n  }\n}\n\nmutation CreateCustomExercise($input: ExerciseInput!) {\n  createCustomExercise(input: $input)\n}\n\nmutation UpdateCustomExercise($input: UpdateCustomExerciseInput!) {\n  updateCustomExercise(input: $input)\n}\n\nmutation UpdateUserIntegration($input: UpdateUserIntegrationInput!) {\n  updateUserIntegration(input: $input)\n}\n\nmutation CreateCustomMetadata($input: CreateCustomMetadataInput!) {\n  createCustomMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateCollection($input: CreateOrUpdateCollectionInput!) {\n  createOrUpdateCollection(input: $input) {\n    id\n  }\n}\n\nmutation CreateReviewComment($input: CreateReviewCommentInput!) {\n  createReviewComment(input: $input)\n}\n\nmutation CreateUserMeasurement($input: UserMeasurementInput!) {\n  createUserMeasurement(input: $input)\n}\n\nmutation CreateUserNotificationPlatform($input: CreateUserNotificationPlatformInput!) {\n  createUserNotificationPlatform(input: $input)\n}\n\nmutation CreateUserIntegration($input: CreateUserIntegrationInput!) {\n  createUserIntegration(input: $input) {\n    id\n  }\n}\n\nmutation CreateUserWorkout($input: UserWorkoutInput!) {\n  createUserWorkout(input: $input)\n}\n\nmutation CreateOrUpdateWorkoutTemplate($input: UserWorkoutInput!) {\n  createOrUpdateWorkoutTemplate(input: $input)\n}\n\nmutation DeleteCollection($collectionName: String!) {\n  deleteCollection(collectionName: $collectionName)\n}\n\nmutation DeleteReview($reviewId: String!) {\n  deleteReview(reviewId: $reviewId)\n}\n\nmutation DeleteS3Object($key: String!) {\n  deleteS3Object(key: $key)\n}\n\nmutation DeleteSeenItem($seenId: String!) {\n  deleteSeenItem(seenId: $seenId) {\n    id\n  }\n}\n\nmutation DeleteUser($toDeleteUserId: String!) {\n  deleteUser(toDeleteUserId: $toDeleteUserId)\n}\n\nmutation DeleteUserIntegration($integrationId: String!) {\n  deleteUserIntegration(integrationId: $integrationId)\n}\n\nmutation DeleteUserMeasurement($timestamp: DateTime!) {\n  deleteUserMeasurement(timestamp: $timestamp)\n}\n\nmutation DeleteUserNotificationPlatform($notificationId: String!) {\n  deleteUserNotificationPlatform(notificationId: $notificationId)\n}\n\nmutation DeleteUserWorkout($workoutId: String!) {\n  deleteUserWorkout(workoutId: $workoutId)\n}\n\nmutation DeleteWorkoutTemplate($workoutTemplateId: String!) {\n  deleteWorkoutTemplate(workoutTemplateId: $workoutTemplateId)\n}\n\nmutation DeployBackgroundJob($jobName: BackgroundJob!) {\n  deployBackgroundJob(jobName: $jobName)\n}\n\nmutation DeployBulkProgressUpdate($input: [ProgressUpdateInput!]!) {\n  deployBulkProgressUpdate(input: $input)\n}\n\nmutation DeployExportJob {\n  deployExportJob\n}\n\nmutation DeployImportJob($input: DeployImportJobInput!) {\n  deployImportJob(input: $input)\n}\n\nmutation DeployUpdateMetadataJob($metadataId: String!) {\n  deployUpdateMetadataJob(metadataId: $metadataId)\n}\n\nmutation DeployUpdatePersonJob($personId: String!) {\n  deployUpdatePersonJob(personId: $personId)\n}\n\nmutation DeployUpdateMetadataGroupJob($metadataGroupId: String!) {\n  deployUpdateMetadataGroupJob(metadataGroupId: $metadataGroupId)\n}\n\nmutation UpdateSeenItem($input: UpdateSeenItemInput!) {\n  updateSeenItem(input: $input)\n}\n\nmutation UpdateUserNotificationPlatform($input: UpdateUserNotificationPlatformInput!) {\n  updateUserNotificationPlatform(input: $input)\n}\n\nmutation UpdateUserWorkout($input: UpdateUserWorkoutInput!) {\n  updateUserWorkout(input: $input)\n}\n\nmutation GenerateAuthToken {\n  generateAuthToken\n}\n\nmutation MergeMetadata($mergeFrom: String!, $mergeInto: String!) {\n  mergeMetadata(mergeFrom: $mergeFrom, mergeInto: $mergeInto)\n}\n\nmutation DisassociateMetadata($metadataId: String!) {\n  disassociateMetadata(metadataId: $metadataId)\n}\n\nmutation PostReview($input: PostReviewInput!) {\n  postReview(input: $input) {\n    id\n  }\n}\n\nmutation PresignedPutS3Url($input: PresignedPutUrlInput!) {\n  presignedPutS3Url(input: $input) {\n    key\n    uploadUrl\n  }\n}\n\nmutation RemoveEntityFromCollection($input: ChangeCollectionToEntityInput!) {\n  removeEntityFromCollection(input: $input) {\n    id\n  }\n}\n\nmutation TestUserNotificationPlatforms {\n  testUserNotificationPlatforms\n}\n\nmutation UpdateUser($input: UpdateUserInput!) {\n  updateUser(input: $input) {\n    id\n  }\n}\n\nmutation UpdateUserPreference($input: UpdateUserPreferenceInput!) {\n  updateUserPreference(input: $input)\n}\n\nmutation CreateAccessLink($input: CreateAccessLinkInput!) {\n  createAccessLink(input: $input) {\n    id\n  }\n}\n\nmutation ProcessAccessLink($input: ProcessAccessLinkInput!) {\n  processAccessLink(input: $input) {\n    __typename\n    ... on ProcessAccessLinkError {\n      error\n    }\n    ... on ProcessAccessLinkResponse {\n      apiKey\n      redirectTo\n      tokenValidForDays\n    }\n  }\n}\n\nmutation revokeAccessLink($accessLinkId: String!) {\n  revokeAccessLink(accessLinkId: $accessLinkId)\n}"];
+export function graphql(source: "mutation RegisterUser($input: RegisterUserInput!) {\n  registerUser(input: $input) {\n    __typename\n    ... on RegisterError {\n      error\n    }\n    ... on StringIdObject {\n      id\n    }\n  }\n}\n\nmutation LoginUser($input: AuthUserInput!) {\n  loginUser(input: $input) {\n    __typename\n    ... on LoginError {\n      error\n    }\n    ... on LoginResponse {\n      apiKey\n    }\n  }\n}\n\nmutation AddEntityToCollection($input: ChangeCollectionToEntityInput!) {\n  addEntityToCollection(input: $input)\n}\n\nmutation CommitMetadata($input: CommitMediaInput!) {\n  commitMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CommitMetadataGroup($input: CommitMediaInput!) {\n  commitMetadataGroup(input: $input) {\n    id\n  }\n}\n\nmutation CommitPerson($input: CommitPersonInput!) {\n  commitPerson(input: $input) {\n    id\n  }\n}\n\nmutation CreateCustomExercise($input: ExerciseInput!) {\n  createCustomExercise(input: $input)\n}\n\nmutation UpdateCustomExercise($input: UpdateCustomExerciseInput!) {\n  updateCustomExercise(input: $input)\n}\n\nmutation UpdateUserIntegration($input: UpdateUserIntegrationInput!) {\n  updateUserIntegration(input: $input)\n}\n\nmutation CreateCustomMetadata($input: CreateCustomMetadataInput!) {\n  createCustomMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateCollection($input: CreateOrUpdateCollectionInput!) {\n  createOrUpdateCollection(input: $input) {\n    id\n  }\n}\n\nmutation CreateReviewComment($input: CreateReviewCommentInput!) {\n  createReviewComment(input: $input)\n}\n\nmutation CreateUserMeasurement($input: UserMeasurementInput!) {\n  createUserMeasurement(input: $input)\n}\n\nmutation CreateUserNotificationPlatform($input: CreateUserNotificationPlatformInput!) {\n  createUserNotificationPlatform(input: $input)\n}\n\nmutation CreateUserIntegration($input: CreateUserIntegrationInput!) {\n  createUserIntegration(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateUserWorkout($input: UserWorkoutInput!) {\n  createOrUpdateUserWorkout(input: $input)\n}\n\nmutation CreateOrUpdateUserWorkoutTemplate($input: UserWorkoutInput!) {\n  createOrUpdateUserWorkoutTemplate(input: $input)\n}\n\nmutation DeleteCollection($collectionName: String!) {\n  deleteCollection(collectionName: $collectionName)\n}\n\nmutation DeleteReview($reviewId: String!) {\n  deleteReview(reviewId: $reviewId)\n}\n\nmutation DeleteS3Object($key: String!) {\n  deleteS3Object(key: $key)\n}\n\nmutation DeleteSeenItem($seenId: String!) {\n  deleteSeenItem(seenId: $seenId) {\n    id\n  }\n}\n\nmutation DeleteUser($toDeleteUserId: String!) {\n  deleteUser(toDeleteUserId: $toDeleteUserId)\n}\n\nmutation DeleteUserIntegration($integrationId: String!) {\n  deleteUserIntegration(integrationId: $integrationId)\n}\n\nmutation DeleteUserMeasurement($timestamp: DateTime!) {\n  deleteUserMeasurement(timestamp: $timestamp)\n}\n\nmutation DeleteUserNotificationPlatform($notificationId: String!) {\n  deleteUserNotificationPlatform(notificationId: $notificationId)\n}\n\nmutation DeleteUserWorkout($workoutId: String!) {\n  deleteUserWorkout(workoutId: $workoutId)\n}\n\nmutation DeleteUserWorkoutTemplate($workoutTemplateId: String!) {\n  deleteUserWorkoutTemplate(workoutTemplateId: $workoutTemplateId)\n}\n\nmutation DeployBackgroundJob($jobName: BackgroundJob!) {\n  deployBackgroundJob(jobName: $jobName)\n}\n\nmutation DeployBulkProgressUpdate($input: [ProgressUpdateInput!]!) {\n  deployBulkProgressUpdate(input: $input)\n}\n\nmutation DeployExportJob {\n  deployExportJob\n}\n\nmutation DeployImportJob($input: DeployImportJobInput!) {\n  deployImportJob(input: $input)\n}\n\nmutation DeployUpdateMetadataJob($metadataId: String!) {\n  deployUpdateMetadataJob(metadataId: $metadataId)\n}\n\nmutation DeployUpdatePersonJob($personId: String!) {\n  deployUpdatePersonJob(personId: $personId)\n}\n\nmutation DeployUpdateMetadataGroupJob($metadataGroupId: String!) {\n  deployUpdateMetadataGroupJob(metadataGroupId: $metadataGroupId)\n}\n\nmutation UpdateSeenItem($input: UpdateSeenItemInput!) {\n  updateSeenItem(input: $input)\n}\n\nmutation UpdateUserNotificationPlatform($input: UpdateUserNotificationPlatformInput!) {\n  updateUserNotificationPlatform(input: $input)\n}\n\nmutation UpdateUserWorkout($input: UpdateUserWorkoutInput!) {\n  updateUserWorkout(input: $input)\n}\n\nmutation GenerateAuthToken {\n  generateAuthToken\n}\n\nmutation MergeMetadata($mergeFrom: String!, $mergeInto: String!) {\n  mergeMetadata(mergeFrom: $mergeFrom, mergeInto: $mergeInto)\n}\n\nmutation DisassociateMetadata($metadataId: String!) {\n  disassociateMetadata(metadataId: $metadataId)\n}\n\nmutation PostReview($input: PostReviewInput!) {\n  postReview(input: $input) {\n    id\n  }\n}\n\nmutation PresignedPutS3Url($input: PresignedPutUrlInput!) {\n  presignedPutS3Url(input: $input) {\n    key\n    uploadUrl\n  }\n}\n\nmutation RemoveEntityFromCollection($input: ChangeCollectionToEntityInput!) {\n  removeEntityFromCollection(input: $input) {\n    id\n  }\n}\n\nmutation TestUserNotificationPlatforms {\n  testUserNotificationPlatforms\n}\n\nmutation UpdateUser($input: UpdateUserInput!) {\n  updateUser(input: $input) {\n    id\n  }\n}\n\nmutation UpdateUserPreference($input: UpdateUserPreferenceInput!) {\n  updateUserPreference(input: $input)\n}\n\nmutation CreateAccessLink($input: CreateAccessLinkInput!) {\n  createAccessLink(input: $input) {\n    id\n  }\n}\n\nmutation ProcessAccessLink($input: ProcessAccessLinkInput!) {\n  processAccessLink(input: $input) {\n    __typename\n    ... on ProcessAccessLinkError {\n      error\n    }\n    ... on ProcessAccessLinkResponse {\n      apiKey\n      redirectTo\n      tokenValidForDays\n    }\n  }\n}\n\nmutation revokeAccessLink($accessLinkId: String!) {\n  revokeAccessLink(accessLinkId: $accessLinkId)\n}"): (typeof documents)["mutation RegisterUser($input: RegisterUserInput!) {\n  registerUser(input: $input) {\n    __typename\n    ... on RegisterError {\n      error\n    }\n    ... on StringIdObject {\n      id\n    }\n  }\n}\n\nmutation LoginUser($input: AuthUserInput!) {\n  loginUser(input: $input) {\n    __typename\n    ... on LoginError {\n      error\n    }\n    ... on LoginResponse {\n      apiKey\n    }\n  }\n}\n\nmutation AddEntityToCollection($input: ChangeCollectionToEntityInput!) {\n  addEntityToCollection(input: $input)\n}\n\nmutation CommitMetadata($input: CommitMediaInput!) {\n  commitMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CommitMetadataGroup($input: CommitMediaInput!) {\n  commitMetadataGroup(input: $input) {\n    id\n  }\n}\n\nmutation CommitPerson($input: CommitPersonInput!) {\n  commitPerson(input: $input) {\n    id\n  }\n}\n\nmutation CreateCustomExercise($input: ExerciseInput!) {\n  createCustomExercise(input: $input)\n}\n\nmutation UpdateCustomExercise($input: UpdateCustomExerciseInput!) {\n  updateCustomExercise(input: $input)\n}\n\nmutation UpdateUserIntegration($input: UpdateUserIntegrationInput!) {\n  updateUserIntegration(input: $input)\n}\n\nmutation CreateCustomMetadata($input: CreateCustomMetadataInput!) {\n  createCustomMetadata(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateCollection($input: CreateOrUpdateCollectionInput!) {\n  createOrUpdateCollection(input: $input) {\n    id\n  }\n}\n\nmutation CreateReviewComment($input: CreateReviewCommentInput!) {\n  createReviewComment(input: $input)\n}\n\nmutation CreateUserMeasurement($input: UserMeasurementInput!) {\n  createUserMeasurement(input: $input)\n}\n\nmutation CreateUserNotificationPlatform($input: CreateUserNotificationPlatformInput!) {\n  createUserNotificationPlatform(input: $input)\n}\n\nmutation CreateUserIntegration($input: CreateUserIntegrationInput!) {\n  createUserIntegration(input: $input) {\n    id\n  }\n}\n\nmutation CreateOrUpdateUserWorkout($input: UserWorkoutInput!) {\n  createOrUpdateUserWorkout(input: $input)\n}\n\nmutation CreateOrUpdateUserWorkoutTemplate($input: UserWorkoutInput!) {\n  createOrUpdateUserWorkoutTemplate(input: $input)\n}\n\nmutation DeleteCollection($collectionName: String!) {\n  deleteCollection(collectionName: $collectionName)\n}\n\nmutation DeleteReview($reviewId: String!) {\n  deleteReview(reviewId: $reviewId)\n}\n\nmutation DeleteS3Object($key: String!) {\n  deleteS3Object(key: $key)\n}\n\nmutation DeleteSeenItem($seenId: String!) {\n  deleteSeenItem(seenId: $seenId) {\n    id\n  }\n}\n\nmutation DeleteUser($toDeleteUserId: String!) {\n  deleteUser(toDeleteUserId: $toDeleteUserId)\n}\n\nmutation DeleteUserIntegration($integrationId: String!) {\n  deleteUserIntegration(integrationId: $integrationId)\n}\n\nmutation DeleteUserMeasurement($timestamp: DateTime!) {\n  deleteUserMeasurement(timestamp: $timestamp)\n}\n\nmutation DeleteUserNotificationPlatform($notificationId: String!) {\n  deleteUserNotificationPlatform(notificationId: $notificationId)\n}\n\nmutation DeleteUserWorkout($workoutId: String!) {\n  deleteUserWorkout(workoutId: $workoutId)\n}\n\nmutation DeleteUserWorkoutTemplate($workoutTemplateId: String!) {\n  deleteUserWorkoutTemplate(workoutTemplateId: $workoutTemplateId)\n}\n\nmutation DeployBackgroundJob($jobName: BackgroundJob!) {\n  deployBackgroundJob(jobName: $jobName)\n}\n\nmutation DeployBulkProgressUpdate($input: [ProgressUpdateInput!]!) {\n  deployBulkProgressUpdate(input: $input)\n}\n\nmutation DeployExportJob {\n  deployExportJob\n}\n\nmutation DeployImportJob($input: DeployImportJobInput!) {\n  deployImportJob(input: $input)\n}\n\nmutation DeployUpdateMetadataJob($metadataId: String!) {\n  deployUpdateMetadataJob(metadataId: $metadataId)\n}\n\nmutation DeployUpdatePersonJob($personId: String!) {\n  deployUpdatePersonJob(personId: $personId)\n}\n\nmutation DeployUpdateMetadataGroupJob($metadataGroupId: String!) {\n  deployUpdateMetadataGroupJob(metadataGroupId: $metadataGroupId)\n}\n\nmutation UpdateSeenItem($input: UpdateSeenItemInput!) {\n  updateSeenItem(input: $input)\n}\n\nmutation UpdateUserNotificationPlatform($input: UpdateUserNotificationPlatformInput!) {\n  updateUserNotificationPlatform(input: $input)\n}\n\nmutation UpdateUserWorkout($input: UpdateUserWorkoutInput!) {\n  updateUserWorkout(input: $input)\n}\n\nmutation GenerateAuthToken {\n  generateAuthToken\n}\n\nmutation MergeMetadata($mergeFrom: String!, $mergeInto: String!) {\n  mergeMetadata(mergeFrom: $mergeFrom, mergeInto: $mergeInto)\n}\n\nmutation DisassociateMetadata($metadataId: String!) {\n  disassociateMetadata(metadataId: $metadataId)\n}\n\nmutation PostReview($input: PostReviewInput!) {\n  postReview(input: $input) {\n    id\n  }\n}\n\nmutation PresignedPutS3Url($input: PresignedPutUrlInput!) {\n  presignedPutS3Url(input: $input) {\n    key\n    uploadUrl\n  }\n}\n\nmutation RemoveEntityFromCollection($input: ChangeCollectionToEntityInput!) {\n  removeEntityFromCollection(input: $input) {\n    id\n  }\n}\n\nmutation TestUserNotificationPlatforms {\n  testUserNotificationPlatforms\n}\n\nmutation UpdateUser($input: UpdateUserInput!) {\n  updateUser(input: $input) {\n    id\n  }\n}\n\nmutation UpdateUserPreference($input: UpdateUserPreferenceInput!) {\n  updateUserPreference(input: $input)\n}\n\nmutation CreateAccessLink($input: CreateAccessLinkInput!) {\n  createAccessLink(input: $input) {\n    id\n  }\n}\n\nmutation ProcessAccessLink($input: ProcessAccessLinkInput!) {\n  processAccessLink(input: $input) {\n    __typename\n    ... on ProcessAccessLinkError {\n      error\n    }\n    ... on ProcessAccessLinkResponse {\n      apiKey\n      redirectTo\n      tokenValidForDays\n    }\n  }\n}\n\nmutation revokeAccessLink($accessLinkId: String!) {\n  revokeAccessLink(accessLinkId: $accessLinkId)\n}"];
 /**
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
  */
@@ -158,19 +158,19 @@ export function graphql(source: "query UserPreferences {\n  userPreferences {\n
 /**
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
  */
-export function graphql(source: "query UserWorkoutTemplatesList($input: SearchInput!) {\n  userWorkoutTemplatesList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      createdOn\n      visibility\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"): (typeof documents)["query UserWorkoutTemplatesList($input: SearchInput!) {\n  userWorkoutTemplatesList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      createdOn\n      visibility\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"];
+export function graphql(source: "query UserWorkoutTemplateDetails($workoutTemplateId: String!) {\n  userWorkoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      createdOn\n      visibility\n      defaultRestTimer\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"): (typeof documents)["query UserWorkoutTemplateDetails($workoutTemplateId: String!) {\n  userWorkoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      createdOn\n      visibility\n      defaultRestTimer\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"];
 /**
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
  */
-export function graphql(source: "query UserWorkoutsList($input: SearchInput!) {\n  userWorkoutsList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      endTime\n      duration\n      startTime\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"): (typeof documents)["query UserWorkoutsList($input: SearchInput!) {\n  userWorkoutsList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      endTime\n      duration\n      startTime\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"];
+export function graphql(source: "query UserWorkoutTemplatesList($input: SearchInput!) {\n  userWorkoutTemplatesList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      createdOn\n      visibility\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"): (typeof documents)["query UserWorkoutTemplatesList($input: SearchInput!) {\n  userWorkoutTemplatesList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      createdOn\n      visibility\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"];
 /**
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
  */
-export function graphql(source: "query WorkoutDetails($workoutId: String!) {\n  workoutDetails(workoutId: $workoutId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      endTime\n      duration\n      startTime\n      templateId\n      repeatedFrom\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"): (typeof documents)["query WorkoutDetails($workoutId: String!) {\n  workoutDetails(workoutId: $workoutId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      endTime\n      duration\n      startTime\n      templateId\n      repeatedFrom\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"];
+export function graphql(source: "query UserWorkoutsList($input: SearchInput!) {\n  userWorkoutsList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      endTime\n      duration\n      startTime\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"): (typeof documents)["query UserWorkoutsList($input: SearchInput!) {\n  userWorkoutsList(input: $input) {\n    details {\n      total\n      nextPage\n    }\n    items {\n      id\n      name\n      endTime\n      duration\n      startTime\n      summary {\n        ...WorkoutSummaryPart\n      }\n    }\n  }\n}"];
 /**
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
  */
-export function graphql(source: "query WorkoutTemplateDetails($workoutTemplateId: String!) {\n  workoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      createdOn\n      visibility\n      defaultRestTimer\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"): (typeof documents)["query WorkoutTemplateDetails($workoutTemplateId: String!) {\n  workoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      createdOn\n      visibility\n      defaultRestTimer\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"];
+export function graphql(source: "query WorkoutDetails($workoutId: String!) {\n  workoutDetails(workoutId: $workoutId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      endTime\n      duration\n      startTime\n      templateId\n      repeatedFrom\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"): (typeof documents)["query WorkoutDetails($workoutId: String!) {\n  workoutDetails(workoutId: $workoutId) {\n    collections {\n      ...CollectionPart\n    }\n    details {\n      id\n      name\n      endTime\n      duration\n      startTime\n      templateId\n      repeatedFrom\n      summary {\n        ...WorkoutSummaryPart\n      }\n      information {\n        ...WorkoutInformationPart\n      }\n    }\n  }\n}"];
 /**
  * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
  */
diff --git a/libs/generated/src/graphql/backend/graphql.ts b/libs/generated/src/graphql/backend/graphql.ts
index 4dd6dedff5..df35540d32 100644
--- a/libs/generated/src/graphql/backend/graphql.ts
+++ b/libs/generated/src/graphql/backend/graphql.ts
@@ -1074,8 +1074,10 @@ export type MutationRoot = {
   createCustomMetadata: StringIdObject;
   /** Create a new collection for the logged in user or edit details of an existing one. */
   createOrUpdateCollection: StringIdObject;
+  /** Take a user workout, process it and commit it to database. */
+  createOrUpdateUserWorkout: Scalars['String']['output'];
   /** Create or update a workout template. */
-  createOrUpdateWorkoutTemplate: Scalars['String']['output'];
+  createOrUpdateUserWorkoutTemplate: Scalars['String']['output'];
   /** Create, like or delete a comment on a review. */
   createReviewComment: Scalars['Boolean']['output'];
   /** Create an integration for the currently logged in user. */
@@ -1084,8 +1086,6 @@ export type MutationRoot = {
   createUserMeasurement: Scalars['DateTime']['output'];
   /** Add a notification platform for the currently logged in user. */
   createUserNotificationPlatform: Scalars['String']['output'];
-  /** Take a user workout, process it and commit it to database. */
-  createUserWorkout: Scalars['String']['output'];
   /** Delete a collection. */
   deleteCollection: Scalars['Boolean']['output'];
   /** Delete a review if it belongs to the currently logged in user. */
@@ -1105,7 +1105,7 @@ export type MutationRoot = {
   /** Delete a workout and remove all exercise associations. */
   deleteUserWorkout: Scalars['Boolean']['output'];
   /** Delete a workout template. */
-  deleteWorkoutTemplate: Scalars['Boolean']['output'];
+  deleteUserWorkoutTemplate: Scalars['Boolean']['output'];
   /** Start a background job. */
   deployBackgroundJob: Scalars['Boolean']['output'];
   /**
@@ -1216,7 +1216,12 @@ export type MutationRootCreateOrUpdateCollectionArgs = {
 };
 
 
-export type MutationRootCreateOrUpdateWorkoutTemplateArgs = {
+export type MutationRootCreateOrUpdateUserWorkoutArgs = {
+  input: UserWorkoutInput;
+};
+
+
+export type MutationRootCreateOrUpdateUserWorkoutTemplateArgs = {
   input: UserWorkoutInput;
 };
 
@@ -1241,11 +1246,6 @@ export type MutationRootCreateUserNotificationPlatformArgs = {
 };
 
 
-export type MutationRootCreateUserWorkoutArgs = {
-  input: UserWorkoutInput;
-};
-
-
 export type MutationRootDeleteCollectionArgs = {
   collectionName: Scalars['String']['input'];
 };
@@ -1291,7 +1291,7 @@ export type MutationRootDeleteUserWorkoutArgs = {
 };
 
 
-export type MutationRootDeleteWorkoutTemplateArgs = {
+export type MutationRootDeleteUserWorkoutTemplateArgs = {
   workoutTemplateId: Scalars['String']['input'];
 };
 
@@ -1712,6 +1712,8 @@ export type QueryRoot = {
   userRecommendations: Array<Scalars['String']['output']>;
   /** Get upcoming calendar events for the given filter. */
   userUpcomingCalendarEvents: Array<GraphqlCalendarEvent>;
+  /** Get information about a workout template. */
+  userWorkoutTemplateDetails: UserWorkoutTemplateDetails;
   /** Get a paginated list of templates created by the user. */
   userWorkoutTemplatesList: WorkoutTemplateListResults;
   /** Get a paginated list of workouts done by the user. */
@@ -1720,8 +1722,6 @@ export type QueryRoot = {
   usersList: Array<User>;
   /** Get details about a workout. */
   workoutDetails: UserWorkoutDetails;
-  /** Get information about a workout template. */
-  workoutTemplateDetails: UserWorkoutTemplateDetails;
 };
 
 
@@ -1860,6 +1860,11 @@ export type QueryRootUserUpcomingCalendarEventsArgs = {
 };
 
 
+export type QueryRootUserWorkoutTemplateDetailsArgs = {
+  workoutTemplateId: Scalars['String']['input'];
+};
+
+
 export type QueryRootUserWorkoutTemplatesListArgs = {
   input: SearchInput;
 };
@@ -1879,11 +1884,6 @@ export type QueryRootWorkoutDetailsArgs = {
   workoutId: Scalars['String']['input'];
 };
 
-
-export type QueryRootWorkoutTemplateDetailsArgs = {
-  workoutTemplateId: Scalars['String']['input'];
-};
-
 export type RegisterError = {
   error: RegisterErrorVariant;
 };
@@ -2487,6 +2487,7 @@ export type UserWorkoutInput = {
   repeatedFrom?: InputMaybe<Scalars['String']['input']>;
   startTime: Scalars['DateTime']['input'];
   templateId?: InputMaybe<Scalars['String']['input']>;
+  updateWorkoutId?: InputMaybe<Scalars['String']['input']>;
   updateWorkoutTemplateId?: InputMaybe<Scalars['String']['input']>;
 };
 
@@ -2735,19 +2736,19 @@ export type CreateUserIntegrationMutationVariables = Exact<{
 
 export type CreateUserIntegrationMutation = { createUserIntegration: { id: string } };
 
-export type CreateUserWorkoutMutationVariables = Exact<{
+export type CreateOrUpdateUserWorkoutMutationVariables = Exact<{
   input: UserWorkoutInput;
 }>;
 
 
-export type CreateUserWorkoutMutation = { createUserWorkout: string };
+export type CreateOrUpdateUserWorkoutMutation = { createOrUpdateUserWorkout: string };
 
-export type CreateOrUpdateWorkoutTemplateMutationVariables = Exact<{
+export type CreateOrUpdateUserWorkoutTemplateMutationVariables = Exact<{
   input: UserWorkoutInput;
 }>;
 
 
-export type CreateOrUpdateWorkoutTemplateMutation = { createOrUpdateWorkoutTemplate: string };
+export type CreateOrUpdateUserWorkoutTemplateMutation = { createOrUpdateUserWorkoutTemplate: string };
 
 export type DeleteCollectionMutationVariables = Exact<{
   collectionName: Scalars['String']['input'];
@@ -2812,12 +2813,12 @@ export type DeleteUserWorkoutMutationVariables = Exact<{
 
 export type DeleteUserWorkoutMutation = { deleteUserWorkout: boolean };
 
-export type DeleteWorkoutTemplateMutationVariables = Exact<{
+export type DeleteUserWorkoutTemplateMutationVariables = Exact<{
   workoutTemplateId: Scalars['String']['input'];
 }>;
 
 
-export type DeleteWorkoutTemplateMutation = { deleteWorkoutTemplate: boolean };
+export type DeleteUserWorkoutTemplateMutation = { deleteUserWorkoutTemplate: boolean };
 
 export type DeployBackgroundJobMutationVariables = Exact<{
   jobName: BackgroundJob;
@@ -3117,6 +3118,13 @@ export type UserPreferencesQueryVariables = Exact<{ [key: string]: never; }>;
 
 export type UserPreferencesQuery = { userPreferences: { general: { reviewScale: UserReviewScale, gridPacking: GridPacking, displayNsfw: boolean, disableVideos: boolean, persistQueries: boolean, watchProviders: Array<string>, disableReviews: boolean, disableIntegrations: boolean, disableWatchProviders: boolean, disableNavigationAnimation: boolean, dashboard: Array<{ section: DashboardElementLot, hidden: boolean, numElements?: number | null }> }, fitness: { measurements: { custom: Array<{ name: string, dataType: UserCustomMeasurementDataType }>, inbuilt: { weight: boolean, bodyMassIndex: boolean, totalBodyWater: boolean, muscle: boolean, leanBodyMass: boolean, bodyFat: boolean, boneMass: boolean, visceralFat: boolean, waistCircumference: boolean, waistToHeightRatio: boolean, hipCircumference: boolean, waistToHipRatio: boolean, chestCircumference: boolean, thighCircumference: boolean, bicepsCircumference: boolean, neckCircumference: boolean, bodyFatCaliper: boolean, chestSkinfold: boolean, abdominalSkinfold: boolean, thighSkinfold: boolean, basalMetabolicRate: boolean, totalDailyEnergyExpenditure: boolean, calories: boolean } }, exercises: { unitSystem: UserUnitSystem } }, notifications: { toSend: Array<MediaStateChanged>, enabled: boolean }, featuresEnabled: { others: { calendar: boolean, collections: boolean }, fitness: { enabled: boolean, workouts: boolean, templates: boolean, measurements: boolean }, media: { enabled: boolean, anime: boolean, audioBook: boolean, book: boolean, manga: boolean, movie: boolean, podcast: boolean, show: boolean, videoGame: boolean, visualNovel: boolean, people: boolean, groups: boolean, genres: boolean } } } };
 
+export type UserWorkoutTemplateDetailsQueryVariables = Exact<{
+  workoutTemplateId: Scalars['String']['input'];
+}>;
+
+
+export type UserWorkoutTemplateDetailsQuery = { userWorkoutTemplateDetails: { collections: Array<{ id: string, name: string, userId: string }>, details: { id: string, name: string, createdOn: string, visibility: Visibility, defaultRestTimer?: number | null, summary: { total?: { personalBestsAchieved: number, weight: string, reps: string, distance: string, duration: string, restTime: number } | null, exercises: Array<{ numSets: number, id: string, lot?: ExerciseLot | null, bestSet?: { lot: SetLot, personalBests?: Array<WorkoutSetPersonalBest> | null, statistic: { duration?: string | null, distance?: string | null, reps?: string | null, weight?: string | null, oneRm?: string | null, pace?: string | null, volume?: string | null } } | null }> }, information: { comment?: string | null, assets?: { images: Array<string>, videos: Array<string> } | null, exercises: Array<{ name: string, lot: ExerciseLot, notes: Array<string>, restTime?: number | null, supersetWith: Array<number>, total?: { personalBestsAchieved: number, weight: string, reps: string, distance: string, duration: string, restTime: number } | null, assets?: { images: Array<string>, videos: Array<string> } | null, sets: Array<{ note?: string | null, lot: SetLot, personalBests?: Array<WorkoutSetPersonalBest> | null, confirmedAt?: string | null, statistic: { duration?: string | null, distance?: string | null, reps?: string | null, weight?: string | null, oneRm?: string | null, pace?: string | null, volume?: string | null } }> }> } } } };
+
 export type UserWorkoutTemplatesListQueryVariables = Exact<{
   input: SearchInput;
 }>;
@@ -3138,13 +3146,6 @@ export type WorkoutDetailsQueryVariables = Exact<{
 
 export type WorkoutDetailsQuery = { workoutDetails: { collections: Array<{ id: string, name: string, userId: string }>, details: { id: string, name: string, endTime: string, duration: number, startTime: string, templateId?: string | null, repeatedFrom?: string | null, summary: { total?: { personalBestsAchieved: number, weight: string, reps: string, distance: string, duration: string, restTime: number } | null, exercises: Array<{ numSets: number, id: string, lot?: ExerciseLot | null, bestSet?: { lot: SetLot, personalBests?: Array<WorkoutSetPersonalBest> | null, statistic: { duration?: string | null, distance?: string | null, reps?: string | null, weight?: string | null, oneRm?: string | null, pace?: string | null, volume?: string | null } } | null }> }, information: { comment?: string | null, assets?: { images: Array<string>, videos: Array<string> } | null, exercises: Array<{ name: string, lot: ExerciseLot, notes: Array<string>, restTime?: number | null, supersetWith: Array<number>, total?: { personalBestsAchieved: number, weight: string, reps: string, distance: string, duration: string, restTime: number } | null, assets?: { images: Array<string>, videos: Array<string> } | null, sets: Array<{ note?: string | null, lot: SetLot, personalBests?: Array<WorkoutSetPersonalBest> | null, confirmedAt?: string | null, statistic: { duration?: string | null, distance?: string | null, reps?: string | null, weight?: string | null, oneRm?: string | null, pace?: string | null, volume?: string | null } }> }> } } } };
 
-export type WorkoutTemplateDetailsQueryVariables = Exact<{
-  workoutTemplateId: Scalars['String']['input'];
-}>;
-
-
-export type WorkoutTemplateDetailsQuery = { workoutTemplateDetails: { collections: Array<{ id: string, name: string, userId: string }>, details: { id: string, name: string, createdOn: string, visibility: Visibility, defaultRestTimer?: number | null, summary: { total?: { personalBestsAchieved: number, weight: string, reps: string, distance: string, duration: string, restTime: number } | null, exercises: Array<{ numSets: number, id: string, lot?: ExerciseLot | null, bestSet?: { lot: SetLot, personalBests?: Array<WorkoutSetPersonalBest> | null, statistic: { duration?: string | null, distance?: string | null, reps?: string | null, weight?: string | null, oneRm?: string | null, pace?: string | null, volume?: string | null } } | null }> }, information: { comment?: string | null, assets?: { images: Array<string>, videos: Array<string> } | null, exercises: Array<{ name: string, lot: ExerciseLot, notes: Array<string>, restTime?: number | null, supersetWith: Array<number>, total?: { personalBestsAchieved: number, weight: string, reps: string, distance: string, duration: string, restTime: number } | null, assets?: { images: Array<string>, videos: Array<string> } | null, sets: Array<{ note?: string | null, lot: SetLot, personalBests?: Array<WorkoutSetPersonalBest> | null, confirmedAt?: string | null, statistic: { duration?: string | null, distance?: string | null, reps?: string | null, weight?: string | null, oneRm?: string | null, pace?: string | null, volume?: string | null } }> }> } } } };
-
 export type GetOidcRedirectUrlQueryVariables = Exact<{ [key: string]: never; }>;
 
 
@@ -3317,8 +3318,8 @@ export const CreateReviewCommentDocument = {"kind":"Document","definitions":[{"k
 export const CreateUserMeasurementDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateUserMeasurement"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserMeasurementInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createUserMeasurement"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<CreateUserMeasurementMutation, CreateUserMeasurementMutationVariables>;
 export const CreateUserNotificationPlatformDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateUserNotificationPlatform"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateUserNotificationPlatformInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createUserNotificationPlatform"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<CreateUserNotificationPlatformMutation, CreateUserNotificationPlatformMutationVariables>;
 export const CreateUserIntegrationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateUserIntegration"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateUserIntegrationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createUserIntegration"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<CreateUserIntegrationMutation, CreateUserIntegrationMutationVariables>;
-export const CreateUserWorkoutDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateUserWorkout"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserWorkoutInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createUserWorkout"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<CreateUserWorkoutMutation, CreateUserWorkoutMutationVariables>;
-export const CreateOrUpdateWorkoutTemplateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOrUpdateWorkoutTemplate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserWorkoutInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOrUpdateWorkoutTemplate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<CreateOrUpdateWorkoutTemplateMutation, CreateOrUpdateWorkoutTemplateMutationVariables>;
+export const CreateOrUpdateUserWorkoutDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOrUpdateUserWorkout"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserWorkoutInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOrUpdateUserWorkout"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<CreateOrUpdateUserWorkoutMutation, CreateOrUpdateUserWorkoutMutationVariables>;
+export const CreateOrUpdateUserWorkoutTemplateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOrUpdateUserWorkoutTemplate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserWorkoutInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOrUpdateUserWorkoutTemplate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<CreateOrUpdateUserWorkoutTemplateMutation, CreateOrUpdateUserWorkoutTemplateMutationVariables>;
 export const DeleteCollectionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteCollection"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"collectionName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteCollection"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"collectionName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"collectionName"}}}]}]}}]} as unknown as DocumentNode<DeleteCollectionMutation, DeleteCollectionMutationVariables>;
 export const DeleteReviewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteReview"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"reviewId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteReview"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"reviewId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"reviewId"}}}]}]}}]} as unknown as DocumentNode<DeleteReviewMutation, DeleteReviewMutationVariables>;
 export const DeleteS3ObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteS3Object"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"key"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteS3Object"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"key"},"value":{"kind":"Variable","name":{"kind":"Name","value":"key"}}}]}]}}]} as unknown as DocumentNode<DeleteS3ObjectMutation, DeleteS3ObjectMutationVariables>;
@@ -3328,7 +3329,7 @@ export const DeleteUserIntegrationDocument = {"kind":"Document","definitions":[{
 export const DeleteUserMeasurementDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteUserMeasurement"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"timestamp"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DateTime"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteUserMeasurement"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"timestamp"},"value":{"kind":"Variable","name":{"kind":"Name","value":"timestamp"}}}]}]}}]} as unknown as DocumentNode<DeleteUserMeasurementMutation, DeleteUserMeasurementMutationVariables>;
 export const DeleteUserNotificationPlatformDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteUserNotificationPlatform"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"notificationId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteUserNotificationPlatform"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"notificationId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"notificationId"}}}]}]}}]} as unknown as DocumentNode<DeleteUserNotificationPlatformMutation, DeleteUserNotificationPlatformMutationVariables>;
 export const DeleteUserWorkoutDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteUserWorkout"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workoutId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteUserWorkout"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workoutId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workoutId"}}}]}]}}]} as unknown as DocumentNode<DeleteUserWorkoutMutation, DeleteUserWorkoutMutationVariables>;
-export const DeleteWorkoutTemplateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteWorkoutTemplate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteWorkoutTemplate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workoutTemplateId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}}}]}]}}]} as unknown as DocumentNode<DeleteWorkoutTemplateMutation, DeleteWorkoutTemplateMutationVariables>;
+export const DeleteUserWorkoutTemplateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteUserWorkoutTemplate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteUserWorkoutTemplate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workoutTemplateId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}}}]}]}}]} as unknown as DocumentNode<DeleteUserWorkoutTemplateMutation, DeleteUserWorkoutTemplateMutationVariables>;
 export const DeployBackgroundJobDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeployBackgroundJob"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"jobName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"BackgroundJob"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deployBackgroundJob"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"jobName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"jobName"}}}]}]}}]} as unknown as DocumentNode<DeployBackgroundJobMutation, DeployBackgroundJobMutationVariables>;
 export const DeployBulkProgressUpdateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeployBulkProgressUpdate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ProgressUpdateInput"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deployBulkProgressUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<DeployBulkProgressUpdateMutation, DeployBulkProgressUpdateMutationVariables>;
 export const DeployExportJobDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeployExportJob"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deployExportJob"}}]}}]} as unknown as DocumentNode<DeployExportJobMutation, DeployExportJobMutationVariables>;
@@ -3374,10 +3375,10 @@ export const UserMetadataDetailsDocument = {"kind":"Document","definitions":[{"k
 export const UserMetadataGroupDetailsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserMetadataGroupDetails"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"metadataGroupId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userMetadataGroupDetails"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"metadataGroupId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"metadataGroupId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"reviews"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ReviewItemPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"collections"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CollectionPart"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenShowExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenShowExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"episode"}},{"kind":"Field","name":{"kind":"Name","value":"season"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenPodcastExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenPodcastExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"episode"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenAnimeExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenAnimeExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"episode"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenMangaExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenMangaExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"chapter"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ReviewItemPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ReviewItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"rating"}},{"kind":"Field","name":{"kind":"Name","value":"textOriginal"}},{"kind":"Field","name":{"kind":"Name","value":"textRendered"}},{"kind":"Field","name":{"kind":"Name","value":"isSpoiler"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"postedOn"}},{"kind":"Field","name":{"kind":"Name","value":"postedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"comments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"text"}},{"kind":"Field","name":{"kind":"Name","value":"createdOn"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"likedBy"}}]}},{"kind":"Field","name":{"kind":"Name","value":"showExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenShowExtraInformationPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"podcastExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenPodcastExtraInformationPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"animeExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenAnimeExtraInformationPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"mangaExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenMangaExtraInformationPart"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CollectionPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Collection"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"userId"}}]}}]} as unknown as DocumentNode<UserMetadataGroupDetailsQuery, UserMetadataGroupDetailsQueryVariables>;
 export const UserPersonDetailsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserPersonDetails"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"personId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userPersonDetails"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"personId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"personId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"collections"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CollectionPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"reviews"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ReviewItemPart"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenShowExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenShowExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"episode"}},{"kind":"Field","name":{"kind":"Name","value":"season"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenPodcastExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenPodcastExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"episode"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenAnimeExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenAnimeExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"episode"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SeenMangaExtraInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SeenMangaExtraInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"chapter"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CollectionPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Collection"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"userId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ReviewItemPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ReviewItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"rating"}},{"kind":"Field","name":{"kind":"Name","value":"textOriginal"}},{"kind":"Field","name":{"kind":"Name","value":"textRendered"}},{"kind":"Field","name":{"kind":"Name","value":"isSpoiler"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"postedOn"}},{"kind":"Field","name":{"kind":"Name","value":"postedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"comments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"text"}},{"kind":"Field","name":{"kind":"Name","value":"createdOn"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"likedBy"}}]}},{"kind":"Field","name":{"kind":"Name","value":"showExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenShowExtraInformationPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"podcastExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenPodcastExtraInformationPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"animeExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenAnimeExtraInformationPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"mangaExtraInformation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SeenMangaExtraInformationPart"}}]}}]}}]} as unknown as DocumentNode<UserPersonDetailsQuery, UserPersonDetailsQueryVariables>;
 export const UserPreferencesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserPreferences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userPreferences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"general"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"reviewScale"}},{"kind":"Field","name":{"kind":"Name","value":"gridPacking"}},{"kind":"Field","name":{"kind":"Name","value":"displayNsfw"}},{"kind":"Field","name":{"kind":"Name","value":"disableVideos"}},{"kind":"Field","name":{"kind":"Name","value":"persistQueries"}},{"kind":"Field","name":{"kind":"Name","value":"watchProviders"}},{"kind":"Field","name":{"kind":"Name","value":"disableReviews"}},{"kind":"Field","name":{"kind":"Name","value":"disableIntegrations"}},{"kind":"Field","name":{"kind":"Name","value":"disableWatchProviders"}},{"kind":"Field","name":{"kind":"Name","value":"disableNavigationAnimation"}},{"kind":"Field","name":{"kind":"Name","value":"dashboard"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"section"}},{"kind":"Field","name":{"kind":"Name","value":"hidden"}},{"kind":"Field","name":{"kind":"Name","value":"numElements"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"fitness"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"measurements"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"custom"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"dataType"}}]}},{"kind":"Field","name":{"kind":"Name","value":"inbuilt"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"bodyMassIndex"}},{"kind":"Field","name":{"kind":"Name","value":"totalBodyWater"}},{"kind":"Field","name":{"kind":"Name","value":"muscle"}},{"kind":"Field","name":{"kind":"Name","value":"leanBodyMass"}},{"kind":"Field","name":{"kind":"Name","value":"bodyFat"}},{"kind":"Field","name":{"kind":"Name","value":"boneMass"}},{"kind":"Field","name":{"kind":"Name","value":"visceralFat"}},{"kind":"Field","name":{"kind":"Name","value":"waistCircumference"}},{"kind":"Field","name":{"kind":"Name","value":"waistToHeightRatio"}},{"kind":"Field","name":{"kind":"Name","value":"hipCircumference"}},{"kind":"Field","name":{"kind":"Name","value":"waistToHipRatio"}},{"kind":"Field","name":{"kind":"Name","value":"chestCircumference"}},{"kind":"Field","name":{"kind":"Name","value":"thighCircumference"}},{"kind":"Field","name":{"kind":"Name","value":"bicepsCircumference"}},{"kind":"Field","name":{"kind":"Name","value":"neckCircumference"}},{"kind":"Field","name":{"kind":"Name","value":"bodyFatCaliper"}},{"kind":"Field","name":{"kind":"Name","value":"chestSkinfold"}},{"kind":"Field","name":{"kind":"Name","value":"abdominalSkinfold"}},{"kind":"Field","name":{"kind":"Name","value":"thighSkinfold"}},{"kind":"Field","name":{"kind":"Name","value":"basalMetabolicRate"}},{"kind":"Field","name":{"kind":"Name","value":"totalDailyEnergyExpenditure"}},{"kind":"Field","name":{"kind":"Name","value":"calories"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"unitSystem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"notifications"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"toSend"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}}]}},{"kind":"Field","name":{"kind":"Name","value":"featuresEnabled"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"others"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"calendar"}},{"kind":"Field","name":{"kind":"Name","value":"collections"}}]}},{"kind":"Field","name":{"kind":"Name","value":"fitness"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"workouts"}},{"kind":"Field","name":{"kind":"Name","value":"templates"}},{"kind":"Field","name":{"kind":"Name","value":"measurements"}}]}},{"kind":"Field","name":{"kind":"Name","value":"media"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"anime"}},{"kind":"Field","name":{"kind":"Name","value":"audioBook"}},{"kind":"Field","name":{"kind":"Name","value":"book"}},{"kind":"Field","name":{"kind":"Name","value":"manga"}},{"kind":"Field","name":{"kind":"Name","value":"movie"}},{"kind":"Field","name":{"kind":"Name","value":"podcast"}},{"kind":"Field","name":{"kind":"Name","value":"show"}},{"kind":"Field","name":{"kind":"Name","value":"videoGame"}},{"kind":"Field","name":{"kind":"Name","value":"visualNovel"}},{"kind":"Field","name":{"kind":"Name","value":"people"}},{"kind":"Field","name":{"kind":"Name","value":"groups"}},{"kind":"Field","name":{"kind":"Name","value":"genres"}}]}}]}}]}}]}}]} as unknown as DocumentNode<UserPreferencesQuery, UserPreferencesQueryVariables>;
+export const UserWorkoutTemplateDetailsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserWorkoutTemplateDetails"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userWorkoutTemplateDetails"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workoutTemplateId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"collections"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CollectionPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"details"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdOn"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"defaultRestTimer"}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSummaryPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"information"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutInformationPart"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutOrExerciseTotals"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"personalBestsAchieved"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetStatisticPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetStatistic"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"oneRm"}},{"kind":"Field","name":{"kind":"Name","value":"pace"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetRecordPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetRecord"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"EntityAssetsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"EntityAssets"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"videos"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CollectionPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Collection"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"userId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSummaryPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSummary"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"numSets"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"bestSet"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetRecordPart"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"assets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"EntityAssetsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"notes"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}},{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"supersetWith"}},{"kind":"Field","name":{"kind":"Name","value":"assets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"EntityAssetsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"note"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}},{"kind":"Field","name":{"kind":"Name","value":"confirmedAt"}}]}}]}}]}}]} as unknown as DocumentNode<UserWorkoutTemplateDetailsQuery, UserWorkoutTemplateDetailsQueryVariables>;
 export const UserWorkoutTemplatesListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserWorkoutTemplatesList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SearchInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userWorkoutTemplatesList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"details"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"nextPage"}}]}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdOn"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSummaryPart"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutOrExerciseTotals"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"personalBestsAchieved"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetStatisticPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetStatistic"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"oneRm"}},{"kind":"Field","name":{"kind":"Name","value":"pace"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetRecordPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetRecord"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSummaryPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSummary"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"numSets"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"bestSet"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetRecordPart"}}]}}]}}]}}]} as unknown as DocumentNode<UserWorkoutTemplatesListQuery, UserWorkoutTemplatesListQueryVariables>;
 export const UserWorkoutsListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserWorkoutsList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SearchInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userWorkoutsList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"details"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"}},{"kind":"Field","name":{"kind":"Name","value":"nextPage"}}]}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"endTime"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"startTime"}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSummaryPart"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutOrExerciseTotals"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"personalBestsAchieved"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetStatisticPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetStatistic"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"oneRm"}},{"kind":"Field","name":{"kind":"Name","value":"pace"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetRecordPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetRecord"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSummaryPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSummary"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"numSets"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"bestSet"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetRecordPart"}}]}}]}}]}}]} as unknown as DocumentNode<UserWorkoutsListQuery, UserWorkoutsListQueryVariables>;
 export const WorkoutDetailsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"WorkoutDetails"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workoutId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workoutDetails"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workoutId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workoutId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"collections"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CollectionPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"details"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"endTime"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"startTime"}},{"kind":"Field","name":{"kind":"Name","value":"templateId"}},{"kind":"Field","name":{"kind":"Name","value":"repeatedFrom"}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSummaryPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"information"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutInformationPart"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutOrExerciseTotals"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"personalBestsAchieved"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetStatisticPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetStatistic"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"oneRm"}},{"kind":"Field","name":{"kind":"Name","value":"pace"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetRecordPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetRecord"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"EntityAssetsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"EntityAssets"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"videos"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CollectionPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Collection"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"userId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSummaryPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSummary"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"numSets"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"bestSet"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetRecordPart"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"assets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"EntityAssetsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"notes"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}},{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"supersetWith"}},{"kind":"Field","name":{"kind":"Name","value":"assets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"EntityAssetsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"note"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}},{"kind":"Field","name":{"kind":"Name","value":"confirmedAt"}}]}}]}}]}}]} as unknown as DocumentNode<WorkoutDetailsQuery, WorkoutDetailsQueryVariables>;
-export const WorkoutTemplateDetailsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"WorkoutTemplateDetails"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workoutTemplateDetails"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workoutTemplateId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workoutTemplateId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"collections"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CollectionPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"details"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdOn"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"defaultRestTimer"}},{"kind":"Field","name":{"kind":"Name","value":"summary"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSummaryPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"information"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutInformationPart"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutOrExerciseTotals"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"personalBestsAchieved"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetStatisticPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetStatistic"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"distance"}},{"kind":"Field","name":{"kind":"Name","value":"reps"}},{"kind":"Field","name":{"kind":"Name","value":"weight"}},{"kind":"Field","name":{"kind":"Name","value":"oneRm"}},{"kind":"Field","name":{"kind":"Name","value":"pace"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSetRecordPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSetRecord"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"EntityAssetsPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"EntityAssets"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"images"}},{"kind":"Field","name":{"kind":"Name","value":"videos"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CollectionPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Collection"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"userId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutSummaryPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutSummary"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"numSets"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"bestSet"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetRecordPart"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkoutInformationPart"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"WorkoutInformation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"assets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"EntityAssetsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"exercises"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"notes"}},{"kind":"Field","name":{"kind":"Name","value":"restTime"}},{"kind":"Field","name":{"kind":"Name","value":"total"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutOrExerciseTotalsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"supersetWith"}},{"kind":"Field","name":{"kind":"Name","value":"assets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"EntityAssetsPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sets"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"statistic"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkoutSetStatisticPart"}}]}},{"kind":"Field","name":{"kind":"Name","value":"note"}},{"kind":"Field","name":{"kind":"Name","value":"lot"}},{"kind":"Field","name":{"kind":"Name","value":"personalBests"}},{"kind":"Field","name":{"kind":"Name","value":"confirmedAt"}}]}}]}}]}}]} as unknown as DocumentNode<WorkoutTemplateDetailsQuery, WorkoutTemplateDetailsQueryVariables>;
 export const GetOidcRedirectUrlDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOidcRedirectUrl"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getOidcRedirectUrl"}}]}}]} as unknown as DocumentNode<GetOidcRedirectUrlQuery, GetOidcRedirectUrlQueryVariables>;
 export const UserByOidcIssuerIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"UserByOidcIssuerId"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"oidcIssuerId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userByOidcIssuerId"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"oidcIssuerId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"oidcIssuerId"}}}]}]}}]} as unknown as DocumentNode<UserByOidcIssuerIdQuery, UserByOidcIssuerIdQueryVariables>;
 export const GetOidcTokenDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOidcToken"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"code"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getOidcToken"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"code"},"value":{"kind":"Variable","name":{"kind":"Name","value":"code"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"subject"}},{"kind":"Field","name":{"kind":"Name","value":"email"}}]}}]}}]} as unknown as DocumentNode<GetOidcTokenQuery, GetOidcTokenQueryVariables>;
diff --git a/libs/graphql/src/backend/mutations/combined.gql b/libs/graphql/src/backend/mutations/combined.gql
index 2d87f8f9bd..7cb9e11ec0 100644
--- a/libs/graphql/src/backend/mutations/combined.gql
+++ b/libs/graphql/src/backend/mutations/combined.gql
@@ -86,12 +86,12 @@ mutation CreateUserIntegration($input: CreateUserIntegrationInput!) {
   }
 }
 
-mutation CreateUserWorkout($input: UserWorkoutInput!) {
-  createUserWorkout(input: $input)
+mutation CreateOrUpdateUserWorkout($input: UserWorkoutInput!) {
+  createOrUpdateUserWorkout(input: $input)
 }
 
-mutation CreateOrUpdateWorkoutTemplate($input: UserWorkoutInput!) {
-  createOrUpdateWorkoutTemplate(input: $input)
+mutation CreateOrUpdateUserWorkoutTemplate($input: UserWorkoutInput!) {
+  createOrUpdateUserWorkoutTemplate(input: $input)
 }
 
 mutation DeleteCollection($collectionName: String!) {
@@ -132,8 +132,8 @@ mutation DeleteUserWorkout($workoutId: String!) {
   deleteUserWorkout(workoutId: $workoutId)
 }
 
-mutation DeleteWorkoutTemplate($workoutTemplateId: String!) {
-  deleteWorkoutTemplate(workoutTemplateId: $workoutTemplateId)
+mutation DeleteUserWorkoutTemplate($workoutTemplateId: String!) {
+  deleteUserWorkoutTemplate(workoutTemplateId: $workoutTemplateId)
 }
 
 mutation DeployBackgroundJob($jobName: BackgroundJob!) {
diff --git a/libs/graphql/src/backend/queries/WorkoutTemplateDetails.gql b/libs/graphql/src/backend/queries/UserWorkoutTemplateDetails.gql
similarity index 66%
rename from libs/graphql/src/backend/queries/WorkoutTemplateDetails.gql
rename to libs/graphql/src/backend/queries/UserWorkoutTemplateDetails.gql
index b20e7ac0e3..cf2f67b274 100644
--- a/libs/graphql/src/backend/queries/WorkoutTemplateDetails.gql
+++ b/libs/graphql/src/backend/queries/UserWorkoutTemplateDetails.gql
@@ -1,5 +1,5 @@
-query WorkoutTemplateDetails($workoutTemplateId: String!) {
-  workoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {
+query UserWorkoutTemplateDetails($workoutTemplateId: String!) {
+  userWorkoutTemplateDetails(workoutTemplateId: $workoutTemplateId) {
     collections {
       ...CollectionPart
     }
diff --git a/yarn.lock b/yarn.lock
index 09a130f9f1..f437cc8af9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5478,6 +5478,23 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@remix-pwa/sw@npm:3.0.10":
+  version: 3.0.10
+  resolution: "@remix-pwa/sw@npm:3.0.10"
+  dependencies:
+    "@remix-run/server-runtime": "npm:^2.10.3"
+    idb: "npm:^8.0.0"
+    pako: "npm:^2.1.0"
+    tiny-invariant: "npm:^1.3.3"
+  peerDependencies:
+    "@remix-run/dev": ^2.5.1
+    "@remix-run/react": ^2.5.1
+    react: ^18.2.0
+    react-dom: ^18.2.0
+  checksum: 10/212b9a9e40459b536ba7e8a2d087f243e1e595db50c40f7a0b5e2267da84c83bdd2462001b166f978361bf1c3ad52c7c8951ea9ab0a227a05acce8313cf3fe64
+  languageName: node
+  linkType: hard
+
 "@remix-pwa/worker-runtime@npm:2.1.4":
   version: 2.1.4
   resolution: "@remix-pwa/worker-runtime@npm:2.1.4"
@@ -5772,7 +5789,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@remix-run/router@npm:^1.18.0":
+"@remix-run/router@npm:1.19.2, @remix-run/router@npm:^1.18.0":
   version: 1.19.2
   resolution: "@remix-run/router@npm:1.19.2"
   checksum: 10/31b62b66ea68bd62018189047de7b262700113438f62407df019f81a9856a08a705b2b77454be9293518e2f5f3bbf3f8b858ac19f48cb7d89f8ab56b7b630c19
@@ -5855,6 +5872,26 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@remix-run/server-runtime@npm:^2.10.3":
+  version: 2.12.1
+  resolution: "@remix-run/server-runtime@npm:2.12.1"
+  dependencies:
+    "@remix-run/router": "npm:1.19.2"
+    "@types/cookie": "npm:^0.6.0"
+    "@web3-storage/multipart-parser": "npm:^1.0.0"
+    cookie: "npm:^0.6.0"
+    set-cookie-parser: "npm:^2.4.8"
+    source-map: "npm:^0.7.3"
+    turbo-stream: "npm:2.4.0"
+  peerDependencies:
+    typescript: ^5.1.0
+  peerDependenciesMeta:
+    typescript:
+      optional: true
+  checksum: 10/fb8921bb16eff244e6320a3ac4390318388abc85c14c9c310bc1e713d9b941b66455d38b7e2864753b925fd162a736d594759e8d52f2c9ebcf4ea75e735b14a1
+  languageName: node
+  linkType: hard
+
 "@remix-run/web-blob@npm:^3.1.0":
   version: 3.1.0
   resolution: "@remix-run/web-blob@npm:3.1.0"
@@ -6210,6 +6247,7 @@ __metadata:
     "@mantine/hooks": "npm:7.12.1"
     "@mantine/notifications": "npm:7.12.1"
     "@remix-pwa/dev": "npm:3.1.0"
+    "@remix-pwa/sw": "npm:3.0.10"
     "@remix-pwa/worker-runtime": "npm:2.1.4"
     "@remix-run/dev": "npm:2.11.2"
     "@remix-run/node": "npm:2.11.2"
@@ -11524,6 +11562,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"idb@npm:^8.0.0":
+  version: 8.0.0
+  resolution: "idb@npm:8.0.0"
+  checksum: 10/6ff47b46ead4bf02ac3a9145bb2f48bac707b950cf33282a72eec8efcda610ffb0a09aab6eea58450f6c87373060bf50998d307085830a302e9e231eee6cd37d
+  languageName: node
+  linkType: hard
+
 "ieee754@npm:^1.1.13, ieee754@npm:^1.2.1":
   version: 1.2.1
   resolution: "ieee754@npm:1.2.1"
@@ -14122,6 +14167,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"pako@npm:^2.1.0":
+  version: 2.1.0
+  resolution: "pako@npm:2.1.0"
+  checksum: 10/38a04991d0ec4f4b92794a68b8c92bf7340692c5d980255c92148da96eb3e550df7a86a7128b5ac0c65ecddfe5ef3bbe9c6dab13e1bc315086e759b18f7c1401
+  languageName: node
+  linkType: hard
+
 "pako@npm:~0.2.0":
   version: 0.2.9
   resolution: "pako@npm:0.2.9"
@@ -17019,7 +17071,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"tiny-invariant@npm:1.3.3":
+"tiny-invariant@npm:1.3.3, tiny-invariant@npm:^1.3.3":
   version: 1.3.3
   resolution: "tiny-invariant@npm:1.3.3"
   checksum: 10/5e185c8cc2266967984ce3b352a4e57cb89dad5a8abb0dea21468a6ecaa67cd5bb47a3b7a85d08041008644af4f667fb8b6575ba38ba5fb00b3b5068306e59fe
@@ -17230,6 +17282,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"turbo-stream@npm:2.4.0":
+  version: 2.4.0
+  resolution: "turbo-stream@npm:2.4.0"
+  checksum: 10/7079bbc82b58340f783144cd669cc7e598288523103a8d68bb8a4c6bb28c64eccb71d389b33aab07788d3a9030638b795709e15cb8486f722b1cdac59cb58afc
+  languageName: node
+  linkType: hard
+
 "type-fest@npm:^0.18.0":
   version: 0.18.1
   resolution: "type-fest@npm:0.18.1"


Test patch: