Spaces:
Running
Running
youssefkatry907
commited on
Commit
·
2703d15
1
Parent(s):
a46fc66
Workout module
Browse files- src/common/models/workout.model.ts +33 -1
- src/helpers/pagination.ts +2 -2
- src/lib/guards/gen-guard.ts +25 -25
- src/modules/console/modules/admins/controllers/workouts.controller.ts +91 -0
- src/modules/console/modules/admins/services/workouts.service.ts +4 -0
- src/modules/console/modules/admins/validations/create-workout.validation.ts +33 -0
- src/modules/console/modules/admins/validations/update-workout.validation.ts +30 -0
src/common/models/workout.model.ts
CHANGED
@@ -3,13 +3,45 @@ const { Schema } = mongoose;
|
|
3 |
|
4 |
export interface IWorkout {
|
5 |
name: string;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
}
|
7 |
|
8 |
const workoutSchema = new Schema({
|
9 |
name: { type: String, required: true, unique: true, dropDups: true },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
});
|
11 |
|
12 |
|
13 |
export type WorkoutDocument = IWorkout & mongoose.Document;
|
14 |
|
15 |
-
export const Workout = mongoose.model<WorkoutDocument>("workouts", workoutSchema);
|
|
|
3 |
|
4 |
export interface IWorkout {
|
5 |
name: string;
|
6 |
+
type: string;
|
7 |
+
created_by: mongoose.Types.ObjectId;
|
8 |
+
templateWeeks: [
|
9 |
+
{
|
10 |
+
days: [
|
11 |
+
{
|
12 |
+
day: number,
|
13 |
+
exercises: [
|
14 |
+
{
|
15 |
+
exercise: mongoose.Types.ObjectId,
|
16 |
+
},
|
17 |
+
],
|
18 |
+
},
|
19 |
+
],
|
20 |
+
},
|
21 |
+
]
|
22 |
}
|
23 |
|
24 |
const workoutSchema = new Schema({
|
25 |
name: { type: String, required: true, unique: true, dropDups: true },
|
26 |
+
type: { type: String, required: true },
|
27 |
+
created_by: { type: mongoose.Types.ObjectId, ref: "users" },
|
28 |
+
templateWeeks: [
|
29 |
+
{
|
30 |
+
days: [
|
31 |
+
{
|
32 |
+
day: Number,
|
33 |
+
exercises: [
|
34 |
+
{
|
35 |
+
exercise: { type: mongoose.Types.ObjectId, ref: "exercises" },
|
36 |
+
},
|
37 |
+
],
|
38 |
+
},
|
39 |
+
],
|
40 |
+
},
|
41 |
+
]
|
42 |
});
|
43 |
|
44 |
|
45 |
export type WorkoutDocument = IWorkout & mongoose.Document;
|
46 |
|
47 |
+
export const Workout = mongoose.model<WorkoutDocument>("workouts", workoutSchema);
|
src/helpers/pagination.ts
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
import { Request } from "express";
|
2 |
|
3 |
export const parsePaginationQuery = (query: Request["query"]) => {
|
4 |
-
const limit = query.
|
5 |
-
const skip = query.skip && parseInt(query.skip as string);
|
6 |
|
7 |
return {
|
8 |
limit,
|
|
|
1 |
import { Request } from "express";
|
2 |
|
3 |
export const parsePaginationQuery = (query: Request["query"]) => {
|
4 |
+
const limit = query.limit && parseInt(query.limit as string) || 10;
|
5 |
+
const skip = query.skip && parseInt(query.skip as string) || 0;
|
6 |
|
7 |
return {
|
8 |
limit,
|
src/lib/guards/gen-guard.ts
CHANGED
@@ -17,33 +17,33 @@ export const genGuard =
|
|
17 |
res: Response
|
18 |
) => boolean | Promise<boolean>
|
19 |
): OptionalIfUndefined<T> =>
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
17 |
res: Response
|
18 |
) => boolean | Promise<boolean>
|
19 |
): OptionalIfUndefined<T> =>
|
20 |
+
(args: T) =>
|
21 |
+
async (req: Request, res: Response, next: NextFunction) => {
|
22 |
+
// get token from cookie
|
23 |
+
const token = req.headers.authorization?.split(" ")[1];
|
24 |
+
let payload: IJwtLoginPayload;
|
25 |
|
26 |
+
// validate token
|
27 |
+
if (!token) {
|
28 |
+
return next(new HttpError(401, "Unauthorized"));
|
29 |
+
}
|
30 |
|
31 |
+
try {
|
32 |
+
payload = verify(token, config.jwt.secret);
|
33 |
+
} catch (err) {
|
34 |
+
return next(new HttpError(401, "Unauthorized"));
|
35 |
+
}
|
36 |
|
37 |
+
if (
|
38 |
+
validationMethod &&
|
39 |
+
!(await validationMethod(args, payload, req, res))
|
40 |
+
) {
|
41 |
+
return next(new HttpError(401, "Unauthorized"));
|
42 |
+
}
|
43 |
|
44 |
+
// inject payload in request
|
45 |
+
(req as unknown as { jwtPayload: JwtPayload }).jwtPayload = payload;
|
46 |
|
47 |
+
// go on
|
48 |
+
next();
|
49 |
+
};
|
src/modules/console/modules/admins/controllers/workouts.controller.ts
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { WorkoutService } from "../services/workouts.service";
|
2 |
+
import { Request, Response } from "express";
|
3 |
+
import { JsonResponse } from "@lib/responses/json-response";
|
4 |
+
import { parsePaginationQuery } from "@helpers/pagination";
|
5 |
+
import { asyncHandler } from "@helpers/async-handler";
|
6 |
+
import { paramsValidator, bodyValidator } from "@helpers/validation.helper";
|
7 |
+
import { BaseController } from "@lib/controllers/controller.base";
|
8 |
+
import { Prefix } from "@lib/decorators/prefix.decorator";
|
9 |
+
import { serialize } from "@helpers/serialize";
|
10 |
+
import { WorkoutSerialization } from "@common/serializers/workout.serializtion";
|
11 |
+
import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
|
12 |
+
import { UsersGuardMiddleware } from "modules/users/common/guards/users.guard";
|
13 |
+
|
14 |
+
@Prefix("/admins/workouts")
|
15 |
+
@ControllerMiddleware(UsersGuardMiddleware())
|
16 |
+
|
17 |
+
export class WorkoutController extends BaseController {
|
18 |
+
private workoutsService = new WorkoutService();
|
19 |
+
|
20 |
+
setRoutes() {
|
21 |
+
this.router.get("/", asyncHandler(this.list));
|
22 |
+
this.router.get("/:id", paramsValidator("id"), asyncHandler(this.get));
|
23 |
+
}
|
24 |
+
|
25 |
+
list = async (req: Request, res: Response) => {
|
26 |
+
const paginationQuery = parsePaginationQuery(req.query);
|
27 |
+
const { docs, paginationData } = await this.workoutsService.list(
|
28 |
+
{},
|
29 |
+
paginationQuery
|
30 |
+
);
|
31 |
+
|
32 |
+
// const response = new JsonResponse({
|
33 |
+
// data: serialize(docs, WorkoutSerialization),
|
34 |
+
// meta: paginationData,
|
35 |
+
// });
|
36 |
+
// return res.json(response);
|
37 |
+
return JsonResponse.success(
|
38 |
+
{
|
39 |
+
data: serialize(docs, WorkoutSerialization),
|
40 |
+
meta: paginationData,
|
41 |
+
},
|
42 |
+
res
|
43 |
+
);
|
44 |
+
};
|
45 |
+
|
46 |
+
get = async (req: Request, res: Response) => {
|
47 |
+
const data = await this.workoutsService.findOneOrFail({
|
48 |
+
_id: req.params.id,
|
49 |
+
});
|
50 |
+
return JsonResponse.success(
|
51 |
+
{
|
52 |
+
data: serialize(data.toJSON(), WorkoutSerialization),
|
53 |
+
},
|
54 |
+
res
|
55 |
+
);
|
56 |
+
};
|
57 |
+
|
58 |
+
create = async (req: Request, res: Response) => {
|
59 |
+
const data = await this.workoutsService.create(req.body);
|
60 |
+
return JsonResponse.success(
|
61 |
+
{
|
62 |
+
status: 201,
|
63 |
+
data: serialize(data.toJSON(), WorkoutSerialization),
|
64 |
+
},
|
65 |
+
res
|
66 |
+
);
|
67 |
+
};
|
68 |
+
|
69 |
+
update = async (req: Request, res: Response) => {
|
70 |
+
const data = await this.workoutsService.update(
|
71 |
+
{ _id: req.params.id },
|
72 |
+
req.body
|
73 |
+
);
|
74 |
+
return JsonResponse.success(
|
75 |
+
{
|
76 |
+
data: serialize(data.toJSON(), WorkoutSerialization),
|
77 |
+
},
|
78 |
+
res
|
79 |
+
);
|
80 |
+
};
|
81 |
+
|
82 |
+
delete = async (req: Request, res: Response) => {
|
83 |
+
const data = await this.workoutsService.delete({ _id: req.params.id });
|
84 |
+
return JsonResponse.success(
|
85 |
+
{
|
86 |
+
data: serialize(data.toJSON(), WorkoutSerialization),
|
87 |
+
},
|
88 |
+
res
|
89 |
+
);
|
90 |
+
};
|
91 |
+
};
|
src/modules/console/modules/admins/services/workouts.service.ts
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Workout } from "@common/models/workout.model";
|
2 |
+
import { CrudService } from "@lib/services/crud.service";
|
3 |
+
|
4 |
+
export class WorkoutService extends CrudService(Workout) {};
|
src/modules/console/modules/admins/validations/create-workout.validation.ts
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as joi from "joi";
|
2 |
+
import { createSchema } from "@helpers/create-schema";
|
3 |
+
|
4 |
+
export interface ICreateWorkout {
|
5 |
+
name: string;
|
6 |
+
type: string;
|
7 |
+
created_by: string;
|
8 |
+
templateWeeks: string[];
|
9 |
+
};
|
10 |
+
|
11 |
+
|
12 |
+
export const createWorkoutSchema = createSchema<ICreateWorkout>({
|
13 |
+
name: joi.string().empty().required().messages({
|
14 |
+
"string.base": "please enter a valid name",
|
15 |
+
"any.required": "name is required",
|
16 |
+
"string.empty": "name can not be empty",
|
17 |
+
}),
|
18 |
+
type: joi.string().empty().required().messages({
|
19 |
+
"string.base": "please enter a valid type",
|
20 |
+
"any.required": "type is required",
|
21 |
+
"string.empty": "type can not be empty",
|
22 |
+
}),
|
23 |
+
created_by: joi.string().empty().required().messages({
|
24 |
+
"string.base": "please enter a valid created_by",
|
25 |
+
"any.required": "created_by is required",
|
26 |
+
"string.empty": "created_by can not be empty",
|
27 |
+
}),
|
28 |
+
templateWeeks: joi.array().empty().required().messages({
|
29 |
+
"string.base": "please enter a valid templateWeeks",
|
30 |
+
"any.required": "templateWeeks is required",
|
31 |
+
"string.empty": "templateWeeks can not be empty",
|
32 |
+
}),
|
33 |
+
});
|
src/modules/console/modules/admins/validations/update-workout.validation.ts
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as joi from "joi";
|
2 |
+
import { createSchema } from "@helpers/create-schema";
|
3 |
+
|
4 |
+
export interface IUpdateWorkout {
|
5 |
+
name?: string;
|
6 |
+
type?: string;
|
7 |
+
created_by?: string;
|
8 |
+
templateWeeks?: string[];
|
9 |
+
};
|
10 |
+
|
11 |
+
|
12 |
+
export const updateWorkoutSchema = createSchema<IUpdateWorkout>({
|
13 |
+
name: joi.string().empty().optional().messages({
|
14 |
+
"string.base": "please enter a valid name",
|
15 |
+
"string.empty": "name can not be empty",
|
16 |
+
}),
|
17 |
+
type: joi.string().empty().optional().messages({
|
18 |
+
"string.base": "please enter a valid type",
|
19 |
+
"string.empty": "type can not be empty",
|
20 |
+
}),
|
21 |
+
created_by: joi.string().empty().optional().messages({
|
22 |
+
"string.base": "please enter a valid created_by",
|
23 |
+
"string.empty": "created_by can not be empty",
|
24 |
+
}),
|
25 |
+
templateWeeks: joi.array().empty().optional().messages({
|
26 |
+
"string.base": "please enter a valid templateWeeks",
|
27 |
+
"string.empty": "templateWeeks can not be empty",
|
28 |
+
}),
|
29 |
+
|
30 |
+
});
|