From a1d485b673e28c16879ae54d59af6446e7455c6d Mon Sep 17 00:00:00 2001 From: Felix Ohnesorge Date: Wed, 17 Apr 2024 15:42:29 +0000 Subject: [PATCH] create and view workouts WIP --- apps/gateway/src/workouts.controller.ts | 37 +++++++--- ...xcercise.dto.ts => create-exercise.dto.ts} | 2 +- apps/workouts/src/dto/create-workout.dto.ts | 2 +- .../workouts/src/entities/excercise.schema.ts | 12 ---- apps/workouts/src/entities/exercise.schema.ts | 12 ++++ .../src/entities/workout-log-schema.ts | 6 +- apps/workouts/src/entities/workout.schema.ts | 8 +-- apps/workouts/src/workouts.controller.ts | 27 +++++--- apps/workouts/src/workouts.module.ts | 4 +- apps/workouts/src/workouts.service.ts | 56 +++++++++------ frontend/app/home.tsx | 58 ++++++++++------ frontend/app/workout/[id].tsx | 45 ++++++++++++ frontend/app/workout/create.tsx | 57 ++++++++++------ ...xcerciseModal.tsx => AddExerciseModal.tsx} | 37 +++++----- frontend/components/ExerciseCard.tsx | 17 +++++ frontend/components/HorizontalScollView.tsx | 20 ++++++ frontend/components/NumericInput.tsx | 68 +++++++++++++++++++ frontend/styles/index.js | 6 ++ http-requests/workouts.http | 18 +++-- libs/common/src/lib/validate-objectid-pipe.ts | 12 ++++ 20 files changed, 375 insertions(+), 129 deletions(-) rename apps/workouts/src/dto/{create-excercise.dto.ts => create-exercise.dto.ts} (69%) delete mode 100644 apps/workouts/src/entities/excercise.schema.ts create mode 100644 apps/workouts/src/entities/exercise.schema.ts create mode 100644 frontend/app/workout/[id].tsx rename frontend/components/{AddExcerciseModal.tsx => AddExerciseModal.tsx} (62%) create mode 100644 frontend/components/ExerciseCard.tsx create mode 100644 frontend/components/HorizontalScollView.tsx create mode 100644 frontend/components/NumericInput.tsx create mode 100644 libs/common/src/lib/validate-objectid-pipe.ts diff --git a/apps/gateway/src/workouts.controller.ts b/apps/gateway/src/workouts.controller.ts index a73e52b..2d210cc 100644 --- a/apps/gateway/src/workouts.controller.ts +++ b/apps/gateway/src/workouts.controller.ts @@ -1,10 +1,20 @@ -import { Body, Controller, Get, Inject, Post, Query } from '@nestjs/common'; +import { + Body, + Controller, + Get, + Inject, + Param, + Post, + Query, +} from '@nestjs/common'; import { GatewayService } from './gateway.service'; import { ClientProxy } from '@nestjs/microservices'; import { Public } from '@app/common/lib/auth.guard'; -import { CreateExcerciseDto } from 'apps/workouts/src/dto/create-excercise.dto'; +import { CreateExerciseDto } from 'apps/workouts/src/dto/create-exercise.dto'; import { CreateWorkoutDto } from 'apps/workouts/src/dto/create-workout.dto'; import { CreateWorkoutLogDto } from 'apps/workouts/src/dto/create-workout-log.dto'; +import { ObjectId } from 'mongoose'; +import { ValidateObjectIdPipe } from '@app/common/lib/validate-objectid-pipe'; @Public() //TODO: Remove this line to make this endpoint private @Controller('workouts') @@ -14,24 +24,24 @@ export class WorkoutsController { @Inject('WORKOUTS_SERVICE') private readonly workoutsClient: ClientProxy, ) {} - @Post('create-excercise') - async createExcercise( - @Body() createExcerciseDto: CreateExcerciseDto, + @Post('create-exercise') + async createExercise( + @Body() createExerciseDto: CreateExerciseDto, ): Promise { return this.workoutsClient.send( - { cmd: 'createExcercise' }, - createExcerciseDto, + { cmd: 'createExercise' }, + createExerciseDto, ); } - @Get('excercises') - async getExcercises( + @Get('exercises') + async getExercises( @Query('page') page: number = 1, @Query('limit') limit: number = 10, @Query('filter') filter: string = '', ): Promise { return this.workoutsClient.send( - { cmd: 'getExcercises' }, + { cmd: 'getExercises' }, { page, limit, filter }, ); } @@ -55,6 +65,13 @@ export class WorkoutsController { ); } + @Get('workout/:id') + async getWorkoutById( + @Param('id', new ValidateObjectIdPipe()) id: ObjectId, + ): Promise { + return this.workoutsClient.send({ cmd: 'getWorkoutById' }, id); + } + @Post('save-workout') async saveWorkout(@Body() workout: CreateWorkoutLogDto): Promise { return this.workoutsClient.send({ cmd: 'saveWorkout' }, workout); diff --git a/apps/workouts/src/dto/create-excercise.dto.ts b/apps/workouts/src/dto/create-exercise.dto.ts similarity index 69% rename from apps/workouts/src/dto/create-excercise.dto.ts rename to apps/workouts/src/dto/create-exercise.dto.ts index ae0e87c..87d769f 100644 --- a/apps/workouts/src/dto/create-excercise.dto.ts +++ b/apps/workouts/src/dto/create-exercise.dto.ts @@ -1,6 +1,6 @@ import { IsString } from 'class-validator'; -export class CreateExcerciseDto { +export class CreateExerciseDto { @IsString() name: string; } diff --git a/apps/workouts/src/dto/create-workout.dto.ts b/apps/workouts/src/dto/create-workout.dto.ts index e808517..dbe45bd 100644 --- a/apps/workouts/src/dto/create-workout.dto.ts +++ b/apps/workouts/src/dto/create-workout.dto.ts @@ -18,5 +18,5 @@ export class CreateWorkoutDto { @ValidateNested({ each: true }) @Type(() => WorkoutExerciseDto) - excercises: WorkoutExerciseDto[]; + exercises: WorkoutExerciseDto[]; } diff --git a/apps/workouts/src/entities/excercise.schema.ts b/apps/workouts/src/entities/excercise.schema.ts deleted file mode 100644 index f8f6702..0000000 --- a/apps/workouts/src/entities/excercise.schema.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; -import { HydratedDocument } from 'mongoose'; - -export type ExcerciseDocument = HydratedDocument; - -@Schema() -export class Excercise { - @Prop() - name: string; -} - -export const ExcerciseSchema = SchemaFactory.createForClass(Excercise); diff --git a/apps/workouts/src/entities/exercise.schema.ts b/apps/workouts/src/entities/exercise.schema.ts new file mode 100644 index 0000000..c2941c2 --- /dev/null +++ b/apps/workouts/src/entities/exercise.schema.ts @@ -0,0 +1,12 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { HydratedDocument } from 'mongoose'; + +export type ExerciseDocument = HydratedDocument; + +@Schema() +export class Exercise { + @Prop() + name: string; +} + +export const ExerciseSchema = SchemaFactory.createForClass(Exercise); diff --git a/apps/workouts/src/entities/workout-log-schema.ts b/apps/workouts/src/entities/workout-log-schema.ts index 15f85be..38d5ad8 100644 --- a/apps/workouts/src/entities/workout-log-schema.ts +++ b/apps/workouts/src/entities/workout-log-schema.ts @@ -1,6 +1,6 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { HydratedDocument, Types } from 'mongoose'; -import { Excercise } from './excercise.schema'; +import { Exercise } from './exercise.schema'; import { Workout } from './workout.schema'; export type WorkoutLogDocument = HydratedDocument; @@ -16,7 +16,7 @@ export class WorkoutLog { @Prop({ type: [ { - excercise: { type: Types.ObjectId, ref: 'Excercise' }, + exercise: { type: Types.ObjectId, ref: 'Exercise' }, sets: Number, reps: Number, weight: Number, @@ -24,7 +24,7 @@ export class WorkoutLog { ], }) exercises: { - exercise: Types.ObjectId | Excercise; + exercise: Types.ObjectId | Exercise; sets: number; reps: number; weight: number; diff --git a/apps/workouts/src/entities/workout.schema.ts b/apps/workouts/src/entities/workout.schema.ts index aa294a3..2994d0f 100644 --- a/apps/workouts/src/entities/workout.schema.ts +++ b/apps/workouts/src/entities/workout.schema.ts @@ -1,6 +1,6 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { HydratedDocument, Types } from 'mongoose'; -import { Excercise } from './excercise.schema'; +import { Exercise } from './exercise.schema'; export type WorkoutDocument = HydratedDocument; @@ -12,14 +12,14 @@ export class Workout { @Prop({ type: [ { - excercise: { type: Types.ObjectId, ref: 'Excercise' }, + exercise: { type: Types.ObjectId, ref: 'Exercise' }, sets: Number, reps: Number, }, ], }) - excercises: { - excercise: Types.ObjectId | Excercise; + exercises: { + exercise: Types.ObjectId | Exercise; sets: number; reps: number; }[]; diff --git a/apps/workouts/src/workouts.controller.ts b/apps/workouts/src/workouts.controller.ts index 6a2e03b..f4355ae 100644 --- a/apps/workouts/src/workouts.controller.ts +++ b/apps/workouts/src/workouts.controller.ts @@ -1,8 +1,8 @@ import { Controller } from '@nestjs/common'; import { WorkoutsService } from './workouts.service'; import { MessagePattern } from '@nestjs/microservices'; -import { CreateExcerciseDto } from './dto/create-excercise.dto'; -import { Excercise } from './entities/excercise.schema'; +import { CreateExerciseDto } from './dto/create-exercise.dto'; +import { Exercise } from './entities/exercise.schema'; import { PaginatedResult } from '@app/common/lib/paginated-result'; import { CreateWorkoutDto } from './dto/create-workout.dto'; import { Workout } from './entities/workout.schema'; @@ -13,22 +13,22 @@ import { CreateWorkoutLogDto } from './dto/create-workout-log.dto'; export class WorkoutsController { constructor(private readonly workoutsService: WorkoutsService) {} - @MessagePattern({ cmd: 'createExcercise' }) - async createExcercise( - createExcerciseDto: CreateExcerciseDto, - ): Promise { + @MessagePattern({ cmd: 'createExercise' }) + async createExercise( + createExerciseDto: CreateExerciseDto, + ): Promise { return this.workoutsService - .createExcercise(createExcerciseDto) + .createExercise(createExerciseDto) .then((result) => result); } - @MessagePattern({ cmd: 'getExcercises' }) - async getExcercises({ + @MessagePattern({ cmd: 'getExercises' }) + async getExercises({ page, limit, filter, - }): Promise> { - return this.workoutsService.getExcercises({ page, limit, filter }); + }): Promise> { + return this.workoutsService.getExercises({ page, limit, filter }); } @MessagePattern({ cmd: 'createWorkout' }) @@ -45,6 +45,11 @@ export class WorkoutsController { return this.workoutsService.getWorkouts({ page, limit, filter }); } + @MessagePattern({ cmd: 'getWorkoutById' }) + async getWorkoutById(id: string): Promise { + return this.workoutsService.getWorkoutById(id); + } + @MessagePattern({ cmd: 'saveWorkout' }) async saveWorkout(workout: CreateWorkoutLogDto): Promise { return this.workoutsService.saveWorkout(workout); diff --git a/apps/workouts/src/workouts.module.ts b/apps/workouts/src/workouts.module.ts index 3dbd7fa..ddc76a6 100644 --- a/apps/workouts/src/workouts.module.ts +++ b/apps/workouts/src/workouts.module.ts @@ -3,7 +3,7 @@ import { WorkoutsController } from './workouts.controller'; import { WorkoutsService } from './workouts.service'; import { MongooseModule } from '@nestjs/mongoose'; import { WorkoutSchema } from './entities/workout.schema'; -import { ExcerciseSchema } from './entities/excercise.schema'; +import { ExerciseSchema } from './entities/exercise.schema'; import { WorkoutLogSchema } from './entities/workout-log-schema'; @Module({ @@ -13,7 +13,7 @@ import { WorkoutLogSchema } from './entities/workout-log-schema'; ), MongooseModule.forFeature([ { name: 'Workout', schema: WorkoutSchema }, - { name: 'Excercise', schema: ExcerciseSchema }, + { name: 'Exercise', schema: ExerciseSchema }, { name: 'WorkoutLog', schema: WorkoutLogSchema }, ]), ], diff --git a/apps/workouts/src/workouts.service.ts b/apps/workouts/src/workouts.service.ts index bc02904..b0fd2f1 100644 --- a/apps/workouts/src/workouts.service.ts +++ b/apps/workouts/src/workouts.service.ts @@ -1,7 +1,7 @@ -import { Injectable } from '@nestjs/common'; -import { CreateExcerciseDto } from './dto/create-excercise.dto'; +import { Injectable, NotFoundException } from '@nestjs/common'; +import { CreateExerciseDto } from './dto/create-exercise.dto'; import { InjectModel } from '@nestjs/mongoose'; -import { Excercise, ExcerciseDocument } from './entities/excercise.schema'; +import { Exercise, ExerciseDocument } from './entities/exercise.schema'; import { Model } from 'mongoose'; import { RpcException } from '@nestjs/microservices'; import { PaginatedResult } from '@app/common/lib/paginated-result'; @@ -13,36 +13,36 @@ import { CreateWorkoutLogDto } from './dto/create-workout-log.dto'; @Injectable() export class WorkoutsService { constructor( - @InjectModel(Excercise.name) - private excerciseModel: Model, + @InjectModel(Exercise.name) + private exerciseModel: Model, @InjectModel(Workout.name) private workoutModel: Model, @InjectModel(WorkoutLog.name) private workoutLogModel: Model, ) {} - async createExcercise(createExcerciseDto: CreateExcerciseDto): Promise { - const createdExcercise = new this.excerciseModel(createExcerciseDto); + async createExercise(createExerciseDto: CreateExerciseDto): Promise { + const createdExercise = new this.exerciseModel(createExerciseDto); try { - return await createdExcercise.save(); + return await createdExercise.save(); } catch (error) { throw new RpcException(error); } } - async getExcercises({ + async getExercises({ page, limit, filter = '', - }): Promise> { + }): Promise> { const skip = (page - 1) * limit; - const data = await this.excerciseModel + const data = await this.exerciseModel .find({ name: { $regex: filter, $options: 'i' } }) .skip(skip) .limit(limit) .exec(); - const totalCount = await this.excerciseModel + const totalCount = await this.exerciseModel .countDocuments({ name: { $regex: filter, $options: 'i' } }) .exec(); @@ -56,23 +56,23 @@ export class WorkoutsService { async createWorkout(createWorkoutDto: CreateWorkoutDto): Promise { try { - const excercises = []; + const exercises = []; - for (const excerciseDto of createWorkoutDto.excercises) { - const excercise = new this.excerciseModel({ - name: excerciseDto.exercise, + for (const exerciseDto of createWorkoutDto.exercises) { + const exercise = new this.exerciseModel({ + name: exerciseDto.exercise, }); - await excercise.save(); //TODO: check if excercises already exist. Do we want to assume that they exist and expect an id here? - excercises.push({ - excercise: excercise._id, - sets: excerciseDto.sets, - reps: excerciseDto.reps, + await exercise.save(); //TODO: check if exercises already exist. Do we want to assume that they exist and expect an id here? + exercises.push({ + exercise: exercise._id, + sets: exerciseDto.sets, + reps: exerciseDto.reps, }); } const createdWorkout = new this.workoutModel({ ...createWorkoutDto, - excercises: excercises, + exercises: exercises, }); return await createdWorkout.save(); @@ -105,6 +105,18 @@ export class WorkoutsService { }; } + async getWorkoutById(id: string): Promise { + const workout = await this.workoutModel + .findById(id) + .populate('exercises.exercise') + .exec(); + + if (!workout) { + throw new RpcException(new NotFoundException('Workout not found')); + } + return workout; + } + async saveWorkout(workout: CreateWorkoutLogDto): Promise { const createdWorkoutLog = new this.workoutLogModel(workout); diff --git a/frontend/app/home.tsx b/frontend/app/home.tsx index 1126fd9..30f6876 100644 --- a/frontend/app/home.tsx +++ b/frontend/app/home.tsx @@ -1,41 +1,61 @@ -import { TouchableOpacity, Text, ScrollView, SafeAreaView } from 'react-native'; +import { TouchableOpacity, Text, SafeAreaView } from 'react-native'; import { Stack, useRouter } from 'expo-router'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import ProfileButton from '../components/ProfileButton'; import styles from '../styles'; import Card from '../components/Card'; import AddCard from '../components/AddCard'; +import HorizontalScrollView from '../components/HorizontalScollView'; +import customFetch from '../customFetch'; const HomeScreen = () => { const router = useRouter(); + const [workouts, setWorkouts] = useState([]); + + useEffect(() => { + const fetchWorkouts = async () => { + try { + const response = await customFetch( + 'http://192.168.178.79:3000/workouts/workouts', + ); + if (!response.ok) { + throw new Error('Failed to fetch workouts'); + } + const data = await response.json(); + setWorkouts(data.data); + } catch (error) { + console.error(error); + } + }; + + fetchWorkouts(); + }, []); + return ( <> ( - router.push('login')} /> + router.navigate('login')} /> ), }} /> - {}}> - Start Workout - - {}}> - Create Workout - - - - Workout 1 - - router.push('workout/create')}> + + {workouts.map((workout, index) => ( + router.navigate(`/workout/${workout._id}`)} + key={index} + > + + {workout.name} + + + ))} + router.navigate('workout/create')}> - + ); diff --git a/frontend/app/workout/[id].tsx b/frontend/app/workout/[id].tsx new file mode 100644 index 0000000..8ed3804 --- /dev/null +++ b/frontend/app/workout/[id].tsx @@ -0,0 +1,45 @@ +import { useLocalSearchParams } from 'expo-router'; +import React, { useEffect, useState } from 'react'; +import { SafeAreaView, Text } from 'react-native'; +import styles from '../../styles'; +import ExerciseCard from '../../components/ExerciseCard'; +import HorizontalScrollView from '../../components/HorizontalScollView'; + +const WorkoutPage = () => { + const { id } = useLocalSearchParams(); + const [workout, setWorkout] = useState(null); + + useEffect(() => { + const fetchWorkout = async () => { + try { + const response = await fetch( + `http://192.168.178.79:3000/workouts/workout/${id}`, + ); + + if (!response.ok) { + throw new Error('Failed to fetch workout'); + } + + const data = await response.json(); + setWorkout(data); + } catch (error) { + console.error(error); + } + }; + + fetchWorkout(); + }, [id]); + + return ( + + {workout?.name ?? 'Workout Name'} + + {workout?.exercises.map((exercise, index) => ( + + ))} + + + ); +}; + +export default WorkoutPage; diff --git a/frontend/app/workout/create.tsx b/frontend/app/workout/create.tsx index 1817677..b775921 100644 --- a/frontend/app/workout/create.tsx +++ b/frontend/app/workout/create.tsx @@ -1,24 +1,47 @@ import React, { useState } from 'react'; -import { - Text, - TextInput, - TouchableOpacity, - ScrollView, - SafeAreaView, -} from 'react-native'; +import { Text, TextInput, TouchableOpacity, SafeAreaView } from 'react-native'; import styles from '../../styles'; -import AddExerciseModal from '../../components/AddExcerciseModal'; -import Card from '../../components/Card'; +import AddExerciseModal from '../../components/AddExerciseModal'; import AddCard from '../../components/AddCard'; +import ExerciseCard from '../../components/ExerciseCard'; +import HorizontalScrollView from '../../components/HorizontalScollView'; +import { useRouter } from 'expo-router'; +import customFetch from '../../customFetch'; const CreateWorkout = () => { + const router = useRouter(); const [name, setName] = useState(''); const [exercises, setExercises] = useState([]); const [modalVisible, setModalVisible] = useState(false); - const handleSubmit = () => { - // Handle the form submission here - // For example, you can call an API to create a workout + const handleSubmit = async () => { + try { + //TODO: shoener machen + const flatExercises = exercises.map((item) => ({ + exercise: item.exercise.name, + reps: item.reps, + sets: item.sets, + })); + const response = await customFetch( + 'http://192.168.178.79:3000/workouts/create-workout', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, exercises: flatExercises }), + }, + ); + + if (!response.ok) { + console.log(JSON.stringify({ name, exercises: flatExercises })); + throw new Error('Failed to create workout'); + } + + router.navigate('home'); + } catch (error) { + console.error(error); + } }; const handleAddExercise = (exercise) => { @@ -35,18 +58,14 @@ const CreateWorkout = () => { value={name} onChangeText={setName} /> - + {exercises.map((exercise, index) => ( - - {exercise.name} - {exercise.reps} - {exercise.sets} - + ))} setModalVisible(true)}> - + Create Workout diff --git a/frontend/components/AddExcerciseModal.tsx b/frontend/components/AddExerciseModal.tsx similarity index 62% rename from frontend/components/AddExcerciseModal.tsx rename to frontend/components/AddExerciseModal.tsx index ca0d7d0..f963997 100644 --- a/frontend/components/AddExcerciseModal.tsx +++ b/frontend/components/AddExerciseModal.tsx @@ -2,11 +2,12 @@ import React, { useState } from 'react'; import { Modal, Text, TextInput, TouchableOpacity } from 'react-native'; import styles from '../styles'; import { SafeAreaView } from 'react-native-safe-area-context'; +import NumericInput from './NumericInput'; const AddExerciseModal = ({ modalVisible, onClose, onAddExercise }) => { - const [name, setName] = useState(''); - const [reps, setReps] = useState(''); - const [sets, setSets] = useState(''); + const [exerciseName, setExerciseName] = useState(''); + const [reps, setReps] = useState(12); + const [sets, setSets] = useState(3); return ( { - - + + onAddExercise({ name, reps, sets })} + onPress={() => + onAddExercise({ exercise: { name: exerciseName }, reps, sets }) + } > Add Exercise diff --git a/frontend/components/ExerciseCard.tsx b/frontend/components/ExerciseCard.tsx new file mode 100644 index 0000000..3947d0c --- /dev/null +++ b/frontend/components/ExerciseCard.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { Text } from 'react-native'; +import Card from './Card'; +import styles from '../styles'; + +const ExerciseCard = ({ exercise }) => { + return ( + + {exercise.exercise.name} + + {exercise.sets}x{exercise.reps} + + + ); +}; + +export default ExerciseCard; diff --git a/frontend/components/HorizontalScollView.tsx b/frontend/components/HorizontalScollView.tsx new file mode 100644 index 0000000..ff09886 --- /dev/null +++ b/frontend/components/HorizontalScollView.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { ScrollView, View, Text } from 'react-native'; +import styles from '../styles'; + +const HorizontalScrollView = ({ title, children }) => { + return ( + + {title} + + {children} + + + ); +}; + +export default HorizontalScrollView; diff --git a/frontend/components/NumericInput.tsx b/frontend/components/NumericInput.tsx new file mode 100644 index 0000000..ec8f903 --- /dev/null +++ b/frontend/components/NumericInput.tsx @@ -0,0 +1,68 @@ +import React, { useState } from 'react'; +import { View, Text, TouchableOpacity } from 'react-native'; +import { MaterialIcons } from '@expo/vector-icons'; +import styles from '../styles'; + +const NumericInput = ({ + title, + initialValue, + onChange, + min = 0, + max = 100, +}) => { + const [value, setValue] = useState(initialValue); + + const handleMinus = () => { + if (value > min) { + const newValue = value - 1; + setValue(newValue); + onChange(newValue); + } + }; + + const handlePlus = () => { + if (value < max) { + const newValue = value + 1; + setValue(newValue); + onChange(newValue); + } + }; + + return ( + + {title} + + + + + + + {value} + + + + + + + ); +}; + +export default NumericInput; diff --git a/frontend/styles/index.js b/frontend/styles/index.js index 8afb41e..7157bbc 100644 --- a/frontend/styles/index.js +++ b/frontend/styles/index.js @@ -67,10 +67,16 @@ const styles = StyleSheet.create({ buttonText: { color: COLORS.textColor1, fontSize: 16, + textAlign: 'center', }, headerButton: { marginRight: 15, }, + subtitile: { + fontSize: 16, + color: COLORS.textColor2, + textAlign: 'left', + }, }); export default styles; diff --git a/http-requests/workouts.http b/http-requests/workouts.http index d8b90c6..6ef68fc 100644 --- a/http-requests/workouts.http +++ b/http-requests/workouts.http @@ -1,6 +1,6 @@ @baseUrl = http://localhost:3000 -POST {{baseUrl}}/workouts/create-excercise +POST {{baseUrl}}/workouts/create-exercise content-type: application/json { @@ -8,21 +8,21 @@ content-type: application/json } ### -# @name excercises -GET {{baseUrl}}/workouts/excercises +# @name exercises +GET {{baseUrl}}/workouts/exercises ### -GET {{baseUrl}}/workouts/excercises?filter=bench +GET {{baseUrl}}/workouts/exercises?filter=bench ### - +# @name create_workout POST {{baseUrl}}/workouts/create-workout content-type: application/json { "name": "First Workout", - "excercises": [ + "exercises": [ { "exercise": "testitest", "sets": 3, @@ -35,6 +35,10 @@ content-type: application/json GET {{baseUrl}}/workouts/workouts +### + +GET {{baseUrl}}/workouts/workout/{{create_workout.response.body._id}} + ### # @name save_workout @@ -46,7 +50,7 @@ content-type: application/json "endTime": "2022-01-01T00:00:10Z", "exercises": [ { - "exercise": "{{excercises.response.body.data.[0]._id}}", + "exercise": "{{exercises.response.body.data.[0]._id}}", "sets": 3, "reps": 10, "weight": 100 diff --git a/libs/common/src/lib/validate-objectid-pipe.ts b/libs/common/src/lib/validate-objectid-pipe.ts new file mode 100644 index 0000000..287c6c5 --- /dev/null +++ b/libs/common/src/lib/validate-objectid-pipe.ts @@ -0,0 +1,12 @@ +import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; +import mongoose from 'mongoose'; + +@Injectable() +export class ValidateObjectIdPipe implements PipeTransform { + async transform(value: string) { + if (!mongoose.isValidObjectId(value)) { + throw new BadRequestException('Invalid ID!'); + } + return value; + } +}