feat: nambahin API assign member, list interns, update profile, serta list projects/tasks

This commit is contained in:
Rafi Athallah
2026-06-08 17:28:37 +07:00
parent f0df564499
commit edc287968d
14 changed files with 1295 additions and 36 deletions
@@ -4,6 +4,7 @@ const {
BadRequestError,
NotFoundError,
ForbiddenError,
ConflictError,
} = require("../../../helpers/error");
class ProjectService {
@@ -305,6 +306,209 @@ class ProjectService {
updated_at: member.updated_at,
};
}
async getMyProjects(actor = {}) {
try {
if (!actor?.id) {
return error(new BadRequestError("User ID is required"));
}
if (actor.role !== "intern") {
return error(
new ForbiddenError("Access denied: only interns can view their projects"),
);
}
const projects = await projectRepository.findProjectsByIntern(actor.id);
const mappedProjects = projects.map((project) => ({
id: project.id,
project_icon: project.project_icon,
project_name: project.project_name,
description: project.description,
start_date: project.start_date,
end_date: project.end_date,
max_members: project.max_members,
status: project.status,
admin: this.mapAdmin(project.admin),
total_members: project.members?.length || 0,
total_tasks: project.tasks?.length || 0,
created_at: project.created_at,
updated_at: project.updated_at,
}));
return data(mappedProjects);
} catch (err) {
return error(err);
}
}
async getMyTasks(actor = {}) {
try {
if (!actor?.id) {
return error(new BadRequestError("User ID is required"));
}
if (actor.role !== "intern") {
return error(
new ForbiddenError("Access denied: only interns can view their tasks"),
);
}
const tasks = await projectRepository.findTasksByIntern(actor.id);
const mappedTasks = tasks.map((task) => {
const submission = task.submissions?.[0] || null;
return {
id: task.id,
id_project: task.id_project,
project_name: task.project?.project_name || null,
project_icon: task.project?.project_icon || null,
title: task.title,
description: task.description,
deadline_at: task.deadline_at,
submission_type: task.submission_type,
created_at: task.created_at,
updated_at: task.updated_at,
submission_status: submission ? "submitted" : "not_submitted",
submission_details: submission ? {
id: submission.id,
file_path: submission.file_path,
url_link: submission.url_link,
submitted_at: submission.submitted_at,
updated_at: submission.updated_at,
} : null,
};
});
return data(mappedTasks);
} catch (err) {
return error(err);
}
}
async getMentorProjects(actor = {}) {
try {
if (!actor?.id) {
return error(new BadRequestError("Admin ID is required"));
}
if (actor.role !== "admin") {
return error(
new ForbiddenError("Access denied: only mentors/admins can view their created projects"),
);
}
const projects = await projectRepository.findProjectsByMentor(actor.id);
const mappedProjects = projects.map((project) => ({
id: project.id,
project_icon: project.project_icon,
project_name: project.project_name,
description: project.description,
start_date: project.start_date,
end_date: project.end_date,
max_members: project.max_members,
status: project.status,
admin: this.mapAdmin(project.admin),
total_members: project.members?.length || 0,
total_tasks: project.tasks?.length || 0,
created_at: project.created_at,
updated_at: project.updated_at,
}));
return data(mappedProjects);
} catch (err) {
return error(err);
}
}
async getInterns(actor = {}) {
try {
if (!actor?.id) {
return error(new BadRequestError("Admin ID is required"));
}
if (actor.role !== "admin") {
return error(
new ForbiddenError("Access denied: only admin/mentor can access interns list"),
);
}
const interns = await projectRepository.findActiveInternsWithProjects();
const mappedInterns = interns.map((intern) => {
const activeMembership = intern.project_members?.[0] || null;
const projectName = activeMembership?.project?.project_name || "Unassigned";
const role = intern.lamaran_magang?.lowongan_magang?.posisi || "-";
return {
id: intern.id,
name: intern.full_name,
email: intern.email,
projectName: projectName,
role: role,
isAssignedByMentor: projectName !== "Unassigned",
avatar: null
};
});
return data(mappedInterns);
} catch (err) {
return error(err);
}
}
async assignMember(payload, actor = {}) {
try {
if (!actor?.id) {
return error(new BadRequestError("Admin ID is required"));
}
if (actor.role !== "admin") {
return error(
new ForbiddenError("Access denied: only mentors/admins can assign members"),
);
}
const { id_project, id_user } = payload;
if (!id_project || !id_user) {
return error(new BadRequestError("Project ID and User ID are required"));
}
// Check if project exists
const project = await projectRepository.findById(id_project);
if (!project) {
return error(new NotFoundError("Project not found"));
}
// Check if user exists and is active
const user = await projectRepository.findUserByIdAndActive(id_user);
if (!user) {
return error(new NotFoundError("User not found or inactive"));
}
// Check if already a member of this project
const existingMembership = await projectRepository.findMembership(id_project, id_user);
let membership;
if (existingMembership) {
if (existingMembership.status === 'active') {
return error(new ConflictError("User is already an active member of this project"));
}
// Reactivate membership
membership = await projectRepository.updateMembershipStatus(existingMembership.id, 'active');
} else {
// Create new membership
membership = await projectRepository.assignMember(id_project, id_user);
}
return data(membership);
} catch (err) {
return error(err);
}
}
}
module.exports = new ProjectService();