Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"db:create": "mikro-orm database:create && pnpm db:migration:up",
"db:sync": "mikro-orm schema:update --run",
"db:fresh": "mikro-orm schema:fresh --seed --run",
"db:migration:up": "mikro-orm migration:up",
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AppService } from './app.service';
//import { devOrmConfig, testOrmConfig } from './mikro-orm.config';
import config from './mikro-orm.config';
import { ExerciseModule } from './modules/exercise/exercise.module';
import { ExerciseTypeModule } from './modules/exerciseType/exerciseType.module';
import { ExerciseCategoryModule } from './modules/exerciseCategory/exerciseCategory.module';
import { VideoModule } from './modules/video/video.module';

@Module({
Expand All @@ -15,7 +15,7 @@ import { VideoModule } from './modules/video/video.module';
MikroOrmModule.forRoot(config),
ExerciseModule,
VideoModule,
ExerciseTypeModule,
ExerciseCategoryModule,
],
controllers: [AppController],
providers: [AppService],
Expand Down
6 changes: 3 additions & 3 deletions apps/api/src/entities/exercise.entity.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Entity, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core';
import { ExerciseType } from './exerciseType.entity';
import { ExerciseCategory } from './exerciseCategory.entity';
import { Video } from './video.entity';

@Entity()
export class Exercise {
@PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
id!: string;

@ManyToOne(() => ExerciseType)
exerciseType!: ExerciseType;
@ManyToOne(() => ExerciseCategory)
exerciseCategory!: ExerciseCategory;

@ManyToOne(() => Video, { nullable: true })
video?: Video;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {
import { Exercise } from './exercise.entity';

@Entity()
export class ExerciseType {
export class ExerciseCategory {
@PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
id!: string;

@OneToMany(
() => Exercise,
(exercise) => exercise.exerciseType
(exercise) => exercise.exerciseCategory
)
exercises = new Collection<Exercise>(this);

Expand Down
16 changes: 8 additions & 8 deletions apps/api/src/migrations/.snapshot-dropit.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@
"mappedType": "datetime"
}
},
"name": "exercise_type",
"name": "exercise_category",
"schema": "public",
"indexes": [
{
"keyName": "exercise_type_pkey",
"keyName": "exercise_category_pkey",
"columnNames": [
"id"
],
Expand Down Expand Up @@ -209,8 +209,8 @@
"default": "gen_random_uuid()",
"mappedType": "uuid"
},
"exercise_type_id": {
"name": "exercise_type_id",
"exercise_category_id": {
"name": "exercise_category_id",
"type": "uuid",
"unsigned": false,
"autoincrement": false,
Expand Down Expand Up @@ -304,16 +304,16 @@
],
"checks": [],
"foreignKeys": {
"exercise_exercise_type_id_foreign": {
"constraintName": "exercise_exercise_type_id_foreign",
"exercise_exercise_category_id_foreign": {
"constraintName": "exercise_exercise_category_id_foreign",
"columnNames": [
"exercise_type_id"
"exercise_category_id"
],
"localTableName": "public.exercise",
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.exercise_type",
"referencedTableName": "public.exercise_category",
"updateRule": "cascade"
},
"exercise_video_id_foreign": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20250103214146_exerciseTypeToExerciseCategory extends Migration {

override async up(): Promise<void> {
this.addSql(`alter table "exercise" drop constraint "exercise_exercise_type_id_foreign";`);

this.addSql(`create table "exercise_category" ("id" uuid not null default gen_random_uuid(), "name" varchar(255) not null, "created_at" timestamptz not null, "updated_at" timestamptz not null, constraint "exercise_category_pkey" primary key ("id"));`);

this.addSql(`drop table if exists "exercise_type" cascade;`);

this.addSql(`alter table "exercise" rename column "exercise_type_id" to "exercise_category_id";`);
this.addSql(`alter table "exercise" add constraint "exercise_exercise_category_id_foreign" foreign key ("exercise_category_id") references "exercise_category" ("id") on update cascade;`);
}

override async down(): Promise<void> {
this.addSql(`alter table "exercise" drop constraint "exercise_exercise_category_id_foreign";`);

this.addSql(`create table "exercise_type" ("id" uuid not null default gen_random_uuid(), "name" varchar(255) not null, "created_at" timestamptz not null, "updated_at" timestamptz not null, constraint "exercise_type_pkey" primary key ("id"));`);

this.addSql(`drop table if exists "exercise_category" cascade;`);

this.addSql(`alter table "exercise" rename column "exercise_category_id" to "exercise_type_id";`);
this.addSql(`alter table "exercise" add constraint "exercise_exercise_type_id_foreign" foreign key ("exercise_type_id") references "exercise_type" ("id") on update cascade;`);
}

}
70 changes: 33 additions & 37 deletions apps/api/src/modules/exercise/exercise.service.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import {
CreateExercise,
ExerciseResponse,
UpdateExercise,
} from '@dropit/schemas';
import { CreateExercise, ExerciseDto, UpdateExercise } from '@dropit/schemas';
import { EntityManager, wrap } from '@mikro-orm/postgresql';
import {
BadRequestException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { Exercise } from '../../entities/exercise.entity';
import { ExerciseType } from '../../entities/exerciseType.entity';
import { ExerciseCategory } from '../../entities/exerciseCategory.entity';

@Injectable()
export class ExerciseService {
constructor(private readonly em: EntityManager) {}

async getExercises(): Promise<ExerciseResponse[]> {
async getExercises(): Promise<ExerciseDto[]> {
const exercises = await this.em.findAll(Exercise, {
populate: ['exerciseType'],
populate: ['exerciseCategory'],
});

if (!exercises || exercises.length === 0) {
Expand All @@ -29,9 +25,9 @@ export class ExerciseService {
return {
id: exercise.id,
name: exercise.name,
exerciseType: {
id: exercise.exerciseType.id,
name: exercise.exerciseType.name,
exerciseCategory: {
id: exercise.exerciseCategory.id,
name: exercise.exerciseCategory.name,
},
video: exercise.video?.id ?? undefined,
description: exercise.description ?? '',
Expand All @@ -41,12 +37,12 @@ export class ExerciseService {
});
}

async getExercise(id: string): Promise<ExerciseResponse> {
async getExercise(id: string): Promise<ExerciseDto> {
const exercise = await this.em.findOne(
Exercise,
{ id },
{
populate: ['exerciseType'],
populate: ['exerciseCategory'],
}
);

Expand All @@ -57,9 +53,9 @@ export class ExerciseService {
return {
id: exercise.id,
name: exercise.name,
exerciseType: {
id: exercise.exerciseType.id,
name: exercise.exerciseType.name,
exerciseCategory: {
id: exercise.exerciseCategory.id,
name: exercise.exerciseCategory.name,
},
video: exercise.video?.id,
description: exercise.description,
Expand All @@ -68,18 +64,18 @@ export class ExerciseService {
};
}

async createExercise(newExercise: CreateExercise): Promise<ExerciseResponse> {
async createExercise(newExercise: CreateExercise): Promise<ExerciseDto> {
if (!newExercise.name) {
throw new BadRequestException('Exercise name is required');
}

const exerciseType = await this.em.findOne(ExerciseType, {
id: newExercise.exerciseType,
const exerciseCategory = await this.em.findOne(ExerciseCategory, {
id: newExercise.exerciseCategory,
});

if (!exerciseType) {
if (!exerciseCategory) {
throw new NotFoundException(
`Exercise type with ID ${newExercise.exerciseType} not found`
`Exercise category with ID ${newExercise.exerciseCategory} not found`
);
}

Expand All @@ -88,7 +84,7 @@ export class ExerciseService {
if (newExercise.description) {
exerciseToCreate.description = newExercise.description;
}
exerciseToCreate.exerciseType = exerciseType;
exerciseToCreate.exerciseCategory = exerciseCategory;

await this.em.persistAndFlush(exerciseToCreate);

Expand All @@ -98,7 +94,7 @@ export class ExerciseService {
id: exerciseToCreate.id,
},
{
populate: ['exerciseType'],
populate: ['exerciseCategory'],
}
);

Expand All @@ -109,9 +105,9 @@ export class ExerciseService {
return {
id: exerciseCreated.id,
name: exerciseCreated.name,
exerciseType: {
id: exerciseCreated.exerciseType.id,
name: exerciseCreated.exerciseType.name,
exerciseCategory: {
id: exerciseCreated.exerciseCategory.id,
name: exerciseCreated.exerciseCategory.name,
},
video: exerciseCreated.video?.id,
description: exerciseCreated.description,
Expand All @@ -123,12 +119,12 @@ export class ExerciseService {
async updateExercise(
id: string,
exercise: UpdateExercise
): Promise<ExerciseResponse> {
): Promise<ExerciseDto> {
const exerciseToUpdate = await this.em.findOne(
Exercise,
{ id },
{
populate: ['exerciseType'],
populate: ['exerciseCategory'],
}
);

Expand All @@ -146,7 +142,7 @@ export class ExerciseService {
id: exerciseToUpdate.id,
},
{
populate: ['exerciseType'],
populate: ['exerciseCategory'],
}
);

Expand All @@ -157,9 +153,9 @@ export class ExerciseService {
return {
id: exerciseUpdated.id,
name: exerciseUpdated.name,
exerciseType: {
id: exerciseUpdated.exerciseType.id,
name: exerciseUpdated.exerciseType.name,
exerciseCategory: {
id: exerciseUpdated.exerciseCategory.id,
name: exerciseUpdated.exerciseCategory.name,
},
video: exerciseUpdated.video?.id,
description: exerciseUpdated.description,
Expand All @@ -182,14 +178,14 @@ export class ExerciseService {
};
}

async searchExercises(query: string): Promise<ExerciseResponse[]> {
async searchExercises(query: string): Promise<ExerciseDto[]> {
const exercises = await this.em.find(
Exercise,
{
name: { $ilike: `%${query}%` },
},
{
populate: ['exerciseType'],
populate: ['exerciseCategory'],
}
);

Expand All @@ -201,9 +197,9 @@ export class ExerciseService {
return {
id: exercise.id,
name: exercise.name,
exerciseType: {
id: exercise.exerciseType.id,
name: exercise.exerciseType.name,
exerciseCategory: {
id: exercise.exerciseCategory.id,
name: exercise.exerciseCategory.name,
},
video: exercise.video?.id,
description: exercise.description,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
} from '@nestjs/common';
import { ExerciseCategory } from '../../entities/exerciseCategory.entity';
import { ExerciseCategoryService } from './exerciseCategory.service';

@Controller('exercise-category')
export class ExerciseCategoryController {
constructor(
private readonly exerciseCategoryService: ExerciseCategoryService
) {}

@Get()
async getExerciseCategories() {
return this.exerciseCategoryService.getExerciseCategories();
}

@Get(':id')
async getExerciseCategory(@Param('id') id: string) {
return this.exerciseCategoryService.getExerciseCategory(id);
}

@Post()
async createExerciseCategory(@Body() exerciseCategory: ExerciseCategory) {
return this.exerciseCategoryService.createExerciseCategory(
exerciseCategory
);
}

@Put(':id')
async updateExerciseCategory(
@Param('id') id: string,
@Body() exerciseCategory: ExerciseCategory
) {
return this.exerciseCategoryService.updateExerciseCategory(
id,
exerciseCategory
);
}

@Delete(':id')
async deleteExerciseCategory(@Param('id') id: string) {
return this.exerciseCategoryService.deleteExerciseCategory(id);
}
}
3 changes: 3 additions & 0 deletions apps/api/src/modules/exerciseCategory/exerciseCategory.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type ExerciseCategoryDto = {
name: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { ExerciseCategoryController } from './exerciseCategory.controller';
import { ExerciseCategoryService } from './exerciseCategory.service';

@Module({
controllers: [ExerciseCategoryController],
providers: [ExerciseCategoryService],
})
export class ExerciseCategoryModule {}
Loading
Loading