Skip to content

Commit d180288

Browse files
Merge pull request #9 from call-0f-code/Acheivements-Routes
Achievements and Interviews routes
2 parents 6bb530c + 49875d5 commit d180288

13 files changed

Lines changed: 1649 additions & 10 deletions
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { Request, Response } from "express";
2+
import * as achievementService from "../services/achievement.service";
3+
import { uploadImage } from "../utils/imageUtils";
4+
import { supabase } from "../app";
5+
import { ApiError } from "../utils/apiError";
6+
7+
export const getAchievements = async (req: Request, res: Response) => {
8+
const achievements = await achievementService.getAchievements();
9+
10+
res.status(200).json({
11+
success: true,
12+
count: achievements.length,
13+
data: achievements,
14+
});
15+
};
16+
17+
18+
export const getAchievementById = async (req: Request, res: Response) => {
19+
const achievementId = parseInt(req.params.achievementId);
20+
21+
if (!achievementId || isNaN(achievementId)) {
22+
throw new ApiError("Invalid achievement ID", 400);
23+
}
24+
25+
const achievement = await achievementService.getAchievementById(achievementId);
26+
27+
if (!achievement) {
28+
throw new ApiError("Achievement not found", 404);
29+
}
30+
31+
res.status(200).json({
32+
success: true,
33+
data: achievement,
34+
});
35+
};
36+
37+
export const createAchievement = async (req: Request, res: Response) => {
38+
const file = req.file;
39+
if (!file) {
40+
throw new ApiError('Image file is not found', 400);
41+
}
42+
43+
const imageUrl = await uploadImage(supabase, file, 'achievements');
44+
if (!imageUrl) {
45+
throw new ApiError('Image URL is missing', 400);
46+
}
47+
48+
const { title, description, achievedAt, memberIds, createdById } = req.body.achievementData;
49+
50+
if (!title || !description || !achievedAt || !createdById) {
51+
throw new ApiError('Title, description, achievedAt, and createdById are required', 400);
52+
}
53+
54+
if (!Array.isArray(memberIds)) {
55+
throw new ApiError('memberIds must be an array', 400);
56+
}
57+
58+
const achievement = await achievementService.createAchievement({
59+
title,
60+
description,
61+
achievedAt,
62+
imageUrl,
63+
memberIds,
64+
createdById,
65+
});
66+
67+
res.status(201).json({
68+
success: true,
69+
data: achievement,
70+
});
71+
};
72+
73+
74+
export const updateAchievementById = async (req: Request, res: Response) => {
75+
const achievementId = parseInt(req.params.achievementId);
76+
if (!achievementId || isNaN(achievementId)) {
77+
throw new ApiError("Invalid achievement ID", 400);
78+
}
79+
80+
const file = req.file;
81+
let imageUrl: string | undefined;
82+
83+
if (file) {
84+
imageUrl = await uploadImage(supabase, file, 'achievements');
85+
}
86+
87+
let achievementData = req.body.achievementData;
88+
if (typeof achievementData === 'string') {
89+
try {
90+
achievementData = JSON.parse(achievementData);
91+
} catch (e) {
92+
throw new ApiError("Invalid JSON in achievementData field", 400);
93+
}
94+
}
95+
96+
const { title, description, achievedAt, updatedById, memberIds } = achievementData;
97+
98+
if (!updatedById) {
99+
throw new ApiError("updatedById is required", 400);
100+
}
101+
102+
if (
103+
!title &&
104+
!description &&
105+
!achievedAt &&
106+
!imageUrl &&
107+
(!Array.isArray(memberIds) || memberIds.length === 0)
108+
) {
109+
throw new ApiError("At least one field must be provided for update", 400);
110+
}
111+
112+
const existingAchievement = await achievementService.getAchievementById(achievementId);
113+
if (!existingAchievement) {
114+
throw new ApiError("Achievement not found", 404);
115+
}
116+
117+
if (imageUrl) {
118+
achievementData.imageUrl = imageUrl;
119+
}
120+
121+
const updatedAchievement = await achievementService.updateAchievementById(
122+
achievementId,
123+
achievementData
124+
);
125+
126+
if (Array.isArray(memberIds) && memberIds.length > 0) {
127+
await achievementService.addMembersToAchievement(achievementId, memberIds);
128+
}
129+
130+
res.status(200).json({
131+
success: true,
132+
data: updatedAchievement,
133+
});
134+
};
135+
136+
137+
export const deleteAchievementById = async (req: Request, res: Response) => {
138+
const achievementId = parseInt(req.params.achievementId);
139+
140+
if (!achievementId || isNaN(achievementId)) {
141+
throw new ApiError("Invalid achievement ID", 400);
142+
}
143+
144+
await achievementService.deleteAchievementById(achievementId);
145+
146+
res.status(200).json({
147+
success: true,
148+
message: "Achievement deleted successfully",
149+
});
150+
};
151+
152+
153+
export const removeMemberFromAchievement = async (req: Request, res: Response) => {
154+
const achievementId = parseInt(req.params.achievementId);
155+
const memberId = req.params.memberId;
156+
157+
if (!achievementId || isNaN(achievementId)) {
158+
throw new ApiError("Invalid achievement ID", 400);
159+
}
160+
161+
if (!memberId) {
162+
throw new ApiError("Member ID is required", 400);
163+
}
164+
165+
await achievementService.removeMemberFromAchievement(achievementId, memberId);
166+
167+
res.status(200).json({
168+
success: true,
169+
message: "Member removed from achievement successfully",
170+
});
171+
};
172+
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { Request, Response } from "express";
2+
import * as interviewService from "../services/interview.service";
3+
import { ApiError } from "../utils/apiError";
4+
5+
export const getInterviews = async (req: Request, res: Response) => {
6+
const interviews = await interviewService.getInterviews();
7+
8+
res.status(200).json({
9+
success: true,
10+
data: interviews,
11+
});
12+
};
13+
14+
export const getInterviewById = async (req: Request, res: Response) => {
15+
const interviewId = parseInt(req.params.id);
16+
17+
if (!interviewId) {
18+
throw new ApiError("Invalid interview ID", 400);
19+
}
20+
21+
const interview = await interviewService.getInterviewById(interviewId);
22+
23+
if (!interview) {
24+
throw new ApiError("Interview experience not found", 404);
25+
}
26+
27+
res.status(200).json({
28+
success: true,
29+
data: interview,
30+
});
31+
};
32+
33+
34+
export const createInterview = async (req: Request, res: Response) => {
35+
const memberId = req.params.memberId;
36+
37+
if (!memberId) {
38+
throw new ApiError("Member ID is required", 400);
39+
}
40+
41+
const { company, role, verdict, content, isAnonymous } = req.body;
42+
43+
if (!company || !role || !verdict || !content || isAnonymous === undefined) {
44+
throw new ApiError("All fields are required", 400);
45+
}
46+
47+
const interview = await interviewService.createInterview(memberId, {
48+
company,
49+
role,
50+
verdict,
51+
content,
52+
isAnonymous,
53+
});
54+
55+
res.status(201).json({
56+
success: true,
57+
data: interview,
58+
});
59+
};
60+
61+
export const updateInterviewById = async (req: Request, res: Response) => {
62+
const interviewId = parseInt(req.params.id);
63+
64+
if (!interviewId) {
65+
throw new ApiError("Invalid interview ID", 400);
66+
}
67+
68+
const { memberId, company, role, verdict, content, isAnonymous } = req.body;
69+
70+
if (!memberId) {
71+
throw new ApiError("Member ID is required for verification", 400);
72+
}
73+
74+
if(!company && !role && !verdict && !content && !isAnonymous){
75+
throw new ApiError("Atleast one field is required for update", 400);
76+
}
77+
78+
const existingInterview = await interviewService.getInterviewById(interviewId);
79+
80+
if (!existingInterview) {
81+
throw new ApiError("Interview experience not found", 404);
82+
}
83+
84+
if (existingInterview.memberId !== memberId) {
85+
throw new ApiError("You are not authorized to update this interview experience", 403);
86+
}
87+
88+
const updatedInterview = await interviewService.updateInterviewById(interviewId, {
89+
memberId,
90+
company,
91+
role,
92+
verdict,
93+
content,
94+
isAnonymous,
95+
});
96+
97+
res.status(200).json({
98+
success: true,
99+
data: updatedInterview,
100+
});
101+
};
102+
103+
104+
export const deleteInterviewById = async (req: Request, res: Response) => {
105+
const interviewId = parseInt(req.params.id);
106+
107+
if (!interviewId) {
108+
throw new ApiError("Invalid interview ID", 400);
109+
}
110+
111+
const existingInterview = await interviewService.getInterviewById(interviewId);
112+
113+
if (!existingInterview) {
114+
throw new ApiError("Interview experience not found", 404);
115+
}
116+
117+
await interviewService.deleteInterviewById(interviewId);
118+
119+
res.status(200).json({
120+
success: true,
121+
message: "Interview experience deleted successfully",
122+
});
123+
};
124+
125+

src/db/client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ import { PrismaClient } from "../generated/prisma";
33
const prisma = new PrismaClient();
44

55
export { prisma };
6+

0 commit comments

Comments
 (0)