feat: nambahin API assign member, list interns, update profile, serta list projects/tasks
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user