Skip to content

Commit 90c5e79

Browse files
Admin Treatments page: Set Create Card functionality
1 parent f396f9c commit 90c5e79

18 files changed

Lines changed: 175 additions & 42 deletions

File tree

backend/src/app.module.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,5 @@ import { PartnershipModule } from '@modules/partnership';
4040
})
4141
export class AppModule {
4242
constructor() {
43-
console.log(join(process.cwd(), 'uploads'));
44-
console.log(process.cwd());
4543
}
4644
}

backend/src/common/utils/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './object';
2+
export * from './file-system';

backend/src/common/utils/object.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function deleteProperties<T>(object: T, properties: (keyof T)[]): Omit<T, keyof T> {
2+
const newObject = { ...object };
3+
properties.forEach((property) => {
4+
if (!newObject[property]) {
5+
return;
6+
}
7+
delete newObject[property];
8+
});
9+
return newObject;
10+
}

backend/src/modules/treatments/domain/treatments.entity.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ export class Treatments {
44
public readonly name: string,
55
public readonly description: string,
66
public readonly price: number,
7-
public readonly durationMinutes: number,
7+
public readonly duration: number,
88
public readonly category: 'medical' | 'beauty',
9+
public readonly imageUrl: string,
10+
public readonly active: boolean = true,
911
public readonly createdAt: Date = new Date(),
12+
public readonly updatedAt: Date = new Date(),
1013
) {}
1114
}

backend/src/modules/treatments/infrastructure/repositories/treatments.repository.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ export class TreatmentsRepository {
5858
doc.price,
5959
doc.duration,
6060
doc.category as 'medical' | 'beauty',
61+
doc.imageUrl,
62+
doc.active,
6163
doc.createdAt,
64+
doc.updatedAt,
6265
);
6366
}
6467
}

backend/src/modules/treatments/infrastructure/schemas/treatments.schema.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@ export class TreatmentsSchemaEntity {
1717
@Prop({ required: true })
1818
duration: number;
1919

20-
@Prop({ required: true, enum: ['medical', 'beauty'] })
20+
@Prop({ required: true })
2121
category: string;
2222

23+
@Prop()
24+
imageUrl: string;
25+
26+
@Prop({ default: true })
27+
active: boolean;
28+
2329
createdAt?: Date;
2430
updatedAt?: Date;
2531
}
Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,58 @@
11
import { Type } from 'class-transformer';
2-
import { IsEnum, IsNotEmpty, IsNumber, IsString } from 'class-validator';
2+
import {
3+
IsBoolean,
4+
IsNotEmpty,
5+
IsNumber,
6+
IsOptional,
7+
IsString,
8+
Min,
9+
} from 'class-validator';
10+
11+
export enum TreatmentCategory {
12+
Medical = 'medical',
13+
Beauty = 'beauty',
14+
Injectables = 'injectables',
15+
Massage = 'massage',
16+
Skin = 'skin',
17+
Hair = 'hair',
18+
Nails = 'nails',
19+
Other = 'other',
20+
}
321

422
export class CreateServiceDto {
5-
@IsString()
623
@IsNotEmpty()
24+
@IsString()
725
name: string;
826

9-
@IsString()
1027
@IsNotEmpty()
28+
@IsString()
1129
description: string;
1230

13-
@IsNumber()
1431
@IsNotEmpty()
1532
@Type(() => Number)
33+
@IsNumber()
34+
@Min(1)
1635
price: number;
1736

18-
@IsNumber()
37+
@IsOptional()
38+
@Type(() => Boolean)
39+
@IsBoolean()
40+
active: boolean;
41+
1942
@IsNotEmpty()
2043
@Type(() => Number)
44+
@IsNumber()
45+
@Min(1)
2146
duration: number;
2247

23-
@IsEnum(['medical', 'beauty'])
2448
@IsNotEmpty()
25-
category: 'medical' | 'beauty';
49+
@IsString()
50+
category: string;
51+
52+
@IsOptional()
53+
image: string;
54+
55+
@IsOptional()
56+
@IsString()
57+
imageUrl: string;
2658
}
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
import { PartialType } from '@nestjs/mapped-types';
22
import { CreateServiceDto } from './create-treatments.dto';
3+
import { Type } from 'class-transformer';
34

4-
export class UpdateServiceDto extends PartialType(CreateServiceDto) {}
5+
export class UpdateServiceDto extends PartialType(CreateServiceDto) {
6+
@Type(() => Date)
7+
createdAt?: Date;
8+
9+
@Type(() => Date)
10+
updatedAt?: Date;
11+
}

backend/src/modules/treatments/presentation/treatments.controller.ts

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@ import {
77
Param,
88
Delete,
99
UploadedFiles,
10+
UseInterceptors,
1011
} from '@nestjs/common';
12+
import { FilesInterceptor } from '@nestjs/platform-express';
13+
import { diskStorage } from 'multer';
14+
import { extname } from 'path';
1115
import { TreatmentsService } from '@modules/treatments';
1216
import { Treatments } from '@modules/treatments';
1317
import { CreateServiceDto as CreateTreatmentDto } from '@modules/treatments';
1418
import { UpdateServiceDto as UpdateTreatmentDto } from '@modules/treatments';
1519
import { title } from 'process';
20+
import { deleteProperties } from '@common/utils';
1621

1722
@Controller('treatments')
1823
export class TreatmentsController {
@@ -29,29 +34,70 @@ export class TreatmentsController {
2934
}
3035

3136
@Post()
37+
@UseInterceptors(
38+
FilesInterceptor('image', 10, {
39+
storage: diskStorage({
40+
destination: './uploads/treatments',
41+
filename: (req, file, callback) => {
42+
const uniqueSuffix =
43+
Date.now() + '-' + Math.round(Math.random() * 1e9);
44+
const ext = extname(file.originalname);
45+
callback(null, `${file.fieldname}-${uniqueSuffix}${ext}`);
46+
},
47+
}),
48+
}),
49+
)
3250
async create(
33-
@Body() createTreatmentDto: any,
51+
@Body() createTreatmentDto: CreateTreatmentDto,
3452
@UploadedFiles() files: Array<Express.Multer.File>,
3553
): Promise<any> {
36-
console.log('Create Treatments');
37-
console.log(createTreatmentDto);
38-
39-
const treatment = createTreatmentDto as unknown as Omit<
40-
Treatments,
41-
'id' | 'createdAt'
42-
>;
43-
return { title: 'string' };
54+
const imagePath =
55+
files && files.length > 0
56+
? `/uploads/treatments/${files[0].filename}`
57+
: '';
58+
59+
const treatment = {
60+
...createTreatmentDto,
61+
imageUrl: imagePath,
62+
} as unknown as Omit<Treatments, 'id' | 'createdAt'>;
4463
return this.treatmentsService.create(treatment);
4564
}
4665

4766
@Put(':id')
67+
@UseInterceptors(
68+
FilesInterceptor('files', 10, {
69+
storage: diskStorage({
70+
destination: './uploads/treatments',
71+
filename: (req, file, callback) => {
72+
const uniqueSuffix =
73+
Date.now() + '-' + Math.round(Math.random() * 1e9);
74+
const ext = extname(file.originalname);
75+
callback(null, `${file.fieldname}-${uniqueSuffix}${ext}`);
76+
},
77+
}),
78+
}),
79+
)
4880
async update(
4981
@Param('id') id: string,
5082
@Body() updateTreatmentDto: UpdateTreatmentDto,
83+
@UploadedFiles() files: Array<Express.Multer.File>,
5184
): Promise<Treatments> {
85+
const imagePath =
86+
files && files.length > 0
87+
? `/uploads/treatments/${files[0].filename}`
88+
: null;
89+
90+
const treatmentData = {
91+
...updateTreatmentDto,
92+
};
93+
94+
if (imagePath) {
95+
(treatmentData as any).imageUrl = imagePath;
96+
}
97+
5298
return this.treatmentsService.update(
5399
id,
54-
updateTreatmentDto as unknown as Partial<Treatments>,
100+
treatmentData as unknown as Partial<Treatments>,
55101
);
56102
}
57103

backend/src/modules/veil/presentation/veil.controller.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ export class VeilController {
100100

101101
@Delete(':id')
102102
async remove(@Param('id') id: string): Promise<void> {
103-
console.log('lorem', id);
104103
return this.veilService.remove(id);
105104
}
106105
}

0 commit comments

Comments
 (0)