Skip to content

Commit edef97f

Browse files
committed
Acheivement controller and services modified
1 parent 00b4be9 commit edef97f

5 files changed

Lines changed: 202 additions & 37 deletions

File tree

src/config/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ export default {
33
DATABASE_URL: process.env.DATABASE_URL!,
44
DIRECT_URL: process.env.DIRECT_URL!,
55
SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY!,
6-
ALLOWED_ORIGINS: process.env.ALLOWED_ORIGINS || '*'
7-
}
6+
ALLOWED_ORIGINS: process.env.ALLOWED_ORIGINS || '*',
7+
};

src/controllers/achievement.controller.ts

Lines changed: 112 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from "express";
22
import * as achievementService from "../services/achievement.service";
33
import { ApiError } from "../utils/apiError";
44

5-
export const getAchievements = async (req: Request, res: Response, next: NextFunction) => {
5+
export const getAchievements = async (req: Request, res: Response) => {
66
const achievements = await achievementService.getAchievements();
77

88
if (!achievements || achievements.length === 0) {
@@ -17,9 +17,13 @@ export const getAchievements = async (req: Request, res: Response, next: NextFun
1717
};
1818

1919

20-
export const getAchievementById = async (req: Request, res: Response, next: NextFunction) => {
20+
export const getAchievementById = async (req: Request, res: Response) => {
2121
const achievementId = parseInt(req.params.achievementId);
2222

23+
if (!achievementId || isNaN(achievementId)) {
24+
throw new ApiError("Invalid achievement ID", 400);
25+
}
26+
2327
const achievement = await achievementService.getAchievementById(achievementId);
2428

2529
if (!achievement) {
@@ -33,16 +37,90 @@ export const getAchievementById = async (req: Request, res: Response, next: Next
3337
};
3438

3539

36-
export const updateAchievementById = async (req: Request, res: Response, next: NextFunction) => {
40+
// export const createAchievement = async (req: Request, res: Response) => {
41+
// const { title, achievedAt, imageUrl} = req.body;
42+
43+
// if (!title || !achievedAt ) {
44+
// throw new ApiError("title, achievedAt, and adminId are required", 400);
45+
// }
46+
47+
// const newAchievement = await achievementService.createAchievement({
48+
// title,
49+
// achievedAt,
50+
// imageUrl,
51+
// });
52+
53+
// res.status(201).json({
54+
// success: true,
55+
// data: newAchievement,
56+
// });
57+
// };
58+
59+
60+
export const createAchievement = async (req: Request, res: Response) => {
61+
const { title, achievedAt, imageUrl, memberIds } = req.body;
62+
63+
if (!title || !achievedAt) {
64+
throw new ApiError("Title, achievedAt, and adminId are required", 400);
65+
}
66+
67+
if (!Array.isArray(memberIds)) {
68+
throw new ApiError("memberIds must be an array", 400);
69+
}
70+
71+
const achievement = await achievementService.createAchievement({
72+
title,
73+
achievedAt,
74+
imageUrl,
75+
memberIds,
76+
});
77+
78+
res.status(201).json({
79+
success: true,
80+
data: achievement,
81+
});
82+
};
83+
84+
85+
// export const addMemberToAchievement = async (req: Request, res: Response) => {
86+
// const achievementId = parseInt(req.params.achievementId);
87+
// const { memberId } = req.body;
88+
89+
// if (!achievementId || isNaN(achievementId)) {
90+
// throw new ApiError("Invalid achievement ID", 400);
91+
// }
92+
93+
// if (!memberId) {
94+
// throw new ApiError("Member ID is required", 400);
95+
// }
96+
97+
// const newLink = await achievementService.addMemberToAchievement({
98+
// achievementId,
99+
// memberId,
100+
// });
101+
102+
// res.status(201).json({
103+
// success: true,
104+
// data: newLink,
105+
// });
106+
// };
107+
108+
109+
export const updateAchievementById = async (req: Request, res: Response) => {
37110
const achievementId = parseInt(req.params.achievementId);
38111

39-
if (!achievementId) {
112+
if (!achievementId || isNaN(achievementId)) {
40113
throw new ApiError("Invalid achievement ID", 400);
41114
}
42115

43-
const { title, achievedAt, imageUrl} = req.body;
116+
const { title, achievedAt, imageUrl, memberIds } = req.body;
44117

45-
const existingAchievement = await achievementService.getAchievementById(achievementId);
118+
// if (!adminId) {
119+
// return next(new ApiError("Admin ID is required", 400));
120+
// }
121+
122+
123+
const existingAchievement = await achievementService.getAchievementById(achievementId);
46124

47125
if (!existingAchievement) {
48126
throw new ApiError("Achievement not found", 404);
@@ -54,20 +132,22 @@ export const updateAchievementById = async (req: Request, res: Response, next: N
54132
imageUrl,
55133
});
56134

135+
if (Array.isArray(memberIds) && memberIds.length > 0) {
136+
await achievementService.addMembersToAchievement(achievementId, memberIds);
137+
}
138+
139+
57140
res.status(200).json({
58141
success: true,
59142
data: updatedAchievement,
60143
});
61144
};
62145

63-
64-
export const deleteAchievementById = async (req: Request, res: Response, next: NextFunction) => {
146+
export const deleteAchievementById = async (req: Request, res: Response) => {
65147
const achievementId = parseInt(req.params.achievementId);
66148

67-
const existingAchievement = await achievementService.getAchievementById(achievementId);
68-
69-
if (!existingAchievement) {
70-
throw new ApiError("Achievement not found", 404);
149+
if (!achievementId || isNaN(achievementId)) {
150+
throw new ApiError("Invalid achievement ID", 400);
71151
}
72152

73153
await achievementService.deleteAchievementById(achievementId);
@@ -78,3 +158,23 @@ export const deleteAchievementById = async (req: Request, res: Response, next: N
78158
});
79159
};
80160

161+
162+
export const removeMemberFromAchievement = async (req: Request, res: Response, next: NextFunction) => {
163+
const achievementId = parseInt(req.params.achievementId);
164+
const { memberId } = req.body;
165+
166+
if (!achievementId || isNaN(achievementId)) {
167+
return next(new ApiError("Invalid achievement ID", 400));
168+
}
169+
170+
if (!memberId) {
171+
return next(new ApiError("Member ID is required", 400));
172+
}
173+
174+
await achievementService.removeMemberFromAchievement(achievementId, memberId);
175+
176+
res.status(200).json({
177+
success: true,
178+
message: "Member removed from achievement successfully",
179+
});
180+
};

src/routes/achievements.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ export default function acheivementsRouter(upload: Multer, supabase: SupabaseCli
1212

1313

1414
router.get('/', acheivementsCtrl.getAchievements);
15-
router.get('/:acheivementId',acheivementsCtrl.getAchievementById);
16-
router.patch('/:acheivementId',acheivementsCtrl.updateAchievementById);
17-
router.delete('/:acheivementId',acheivementsCtrl.deleteAchievementById);
18-
15+
router.get("/:achievementId", acheivementsCtrl.getAchievementById);
16+
router.post("/", acheivementsCtrl.createAchievement);
17+
router.patch("/:achievementId", acheivementsCtrl.updateAchievementById);
18+
router.delete("/:achievementId", acheivementsCtrl.deleteAchievementById);
19+
// router.post("/:achievementId/members", acheivementsCtrl.addMemberToAchievement); // add single member
20+
router.delete("/:achievementId/members", acheivementsCtrl.removeMemberFromAchievement);
1921

2022

2123
return router

src/services/achievement.service.ts

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
import { prisma } from "../db/client";
2-
3-
4-
export interface AchievementUpdateInput {
5-
title?: string;
6-
achievedAt?: string;
7-
imageUrl?: string | null;
8-
}
9-
2+
// import { UpdateAchievementInput, CreateAchievementInput } from "../types/acheivement.types";
103

114
export const getAchievements = async () => {
125
return await prisma.achievement.findMany({
@@ -16,11 +9,26 @@ export const getAchievements = async () => {
169
});
1710
};
1811

19-
export const getAchievementById = async (achievementId : number) => {
20-
return await prisma.achievement.findFirst({
21-
where: {
22-
id: Number(achievementId),
12+
13+
export const createAchievement = async (data: CreateAchievementInput) => {
14+
return await prisma.achievement.create({
15+
data: {
16+
title: data.title,
17+
achievedAt: new Date(data.achievedAt),
18+
imageUrl: data.imageUrl,
19+
members: {
20+
create: data.memberIds.map((memberId) => ({
21+
memberId,
22+
})),
23+
},
2324
},
25+
});
26+
};
27+
28+
29+
export const getAchievementById = async (achievementId: number) => {
30+
return await prisma.achievement.findUnique({
31+
where: { id: achievementId },
2432
select: {
2533
id: true,
2634
title: true,
@@ -42,20 +50,55 @@ export const getAchievementById = async (achievementId : number) => {
4250
});
4351
};
4452

45-
46-
export const updateAchievementById = async (achievementId : number, updateContent : AchievementUpdateInput) => {
53+
export const updateAchievementById = async (
54+
achievementId: number,
55+
updateContent: UpdateAchievementInput) => {
4756
return await prisma.achievement.update({
48-
where: {
49-
id: Number(achievementId),
57+
where: { id: achievementId },
58+
data: {
59+
...updateContent,
60+
// achievedAt: updateContent.achievedAt ? new Date(updateContent.achievedAt) : undefined,
5061
},
51-
data: updateContent
5262
});
5363
};
5464

65+
// export const addMemberToAchievement = async (data: { achievementId: number; memberId: string }) => {
66+
// return await prisma.memberAchievement.create({
67+
// data: {
68+
// achievementId: data.achievementId,
69+
// memberId: data.memberId,
70+
// },
71+
// });
72+
// };
73+
74+
75+
export const addMembersToAchievement = async (achievementId: number, memberIds: string[]) => {
76+
if (!Array.isArray(memberIds) || memberIds.length === 0) return;
77+
78+
await prisma.memberAchievement.createMany({
79+
data: memberIds.map((memberId) => ({
80+
memberId,
81+
achievementId,
82+
})),
83+
skipDuplicates: true,
84+
});
85+
};
86+
87+
5588
export const deleteAchievementById = async (achievementId: number) => {
56-
await prisma.achievement.delete({
89+
return await prisma.achievement.delete({
90+
where: { id: achievementId },
91+
});
92+
};
93+
94+
95+
export const removeMemberFromAchievement = async (achievementId: number, memberId: string) => {
96+
return await prisma.memberAchievement.delete({
5797
where: {
58-
id: achievementId,
98+
memberId_achievementId: {
99+
memberId,
100+
achievementId,
101+
},
59102
},
60103
});
61104
};

src/types/acheivement.d.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
3+
import 'express';
4+
export { }
5+
6+
declare global {
7+
8+
interface UpdateAchievementInput {
9+
title?: string;
10+
achievedAt?: string | Date;
11+
imageUrl?: string;
12+
}
13+
14+
interface CreateAchievementInput {
15+
title: string;
16+
achievedAt: string | Date;
17+
imageUrl?: string;
18+
memberIds: string[];
19+
}
20+
}

0 commit comments

Comments
 (0)