intern project and user fix bug and implementation
This commit is contained in:
@@ -1,59 +0,0 @@
|
||||
// hooks/useProjectDetail.ts
|
||||
/**
|
||||
* Bagian Detail dari Project: Ketika User sudah masuk ke dalam Project Card
|
||||
* Komponen yang masuk: IDProject, ParticipantTab, ForumTab, Submissions
|
||||
*/
|
||||
import { useEffect, useState } from "react";
|
||||
import { getProjectById, getProjectInterns, getProjectTasks } from "../services/ProjectService";
|
||||
import type { Project, Intern, ProjectTask } from "../types/project.types";
|
||||
|
||||
export const useProjectDetail = (id: string) => {
|
||||
const [project, setProject] = useState<Project | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) return;
|
||||
setLoading(true);
|
||||
getProjectById(id)
|
||||
.then(setProject)
|
||||
.catch(() => setError("Gagal memuat detail project."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [id]);
|
||||
|
||||
return { project, loading, error };
|
||||
};
|
||||
|
||||
export const useProjectInterns = (projectId: string) => {
|
||||
const [interns, setInterns] = useState<Intern[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
setLoading(true);
|
||||
getProjectInterns(projectId)
|
||||
.then(setInterns)
|
||||
.catch(() => setError("Gagal memuat participants."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [projectId]);
|
||||
|
||||
return { interns, loading, error };
|
||||
};
|
||||
|
||||
export const useProjectTasks = (projectId: string) => {
|
||||
const [tasks, setTasks] = useState<ProjectTask[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
setLoading(true);
|
||||
getProjectTasks(projectId)
|
||||
.then(setTasks)
|
||||
.catch(() => setError("Gagal memuat tasks."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [projectId]);
|
||||
|
||||
return { tasks, loading, error };
|
||||
};
|
||||
+203
-13
@@ -1,34 +1,109 @@
|
||||
import { useEffect, useState } from "react";
|
||||
// Projects
|
||||
import { getMyProjects } from "../services/ProjectService";
|
||||
import type { Project } from "../types/project.types";
|
||||
// Tasks
|
||||
import { getMyTasks } from "../services/ProjectService";
|
||||
import type { InternTask } from "../types/project.types";
|
||||
// hooks/useProject.ts
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import type {
|
||||
Project,
|
||||
ProjectDetail,
|
||||
InternTaskItem,
|
||||
InternDetail,
|
||||
CreateProjectPayload,
|
||||
UpdateProjectPayload,
|
||||
AssignMemberPayload,
|
||||
ProjectMember
|
||||
} from "../types/project.types";
|
||||
import {
|
||||
getProjects,
|
||||
getProjectById,
|
||||
getMyProjects,
|
||||
getMyTasks,
|
||||
getMentorProjects,
|
||||
getAllInterns,
|
||||
createProject,
|
||||
updateProject,
|
||||
archiveProject,
|
||||
assignMember,
|
||||
getProjectMembers
|
||||
} from "../services/ProjectService";
|
||||
|
||||
export const useProjects = () => {
|
||||
// GET /project-api/get
|
||||
export const useProjects = (status?: "active" | "completed" | "archived") => {
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const refetch = useCallback(() => {
|
||||
setLoading(true);
|
||||
getProjects(status)
|
||||
.then(setProjects)
|
||||
.catch(() => setError("Gagal memuat projects."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [status]);
|
||||
|
||||
useEffect(() => { refetch(); }, [refetch]);
|
||||
|
||||
return { projects, loading, error, refetch };
|
||||
};
|
||||
|
||||
// GET /project-api/get/{id}
|
||||
export const useProjectDetail = (id: string) => {
|
||||
const [project, setProject] = useState<ProjectDetail | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const refetch = useCallback(() => {
|
||||
if (!id) return;
|
||||
setLoading(true);
|
||||
getProjectById(id)
|
||||
.then(setProject)
|
||||
.catch(() => setError("Gagal memuat detail project."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [id]);
|
||||
|
||||
useEffect(() => { refetch(); }, [refetch]);
|
||||
|
||||
return { project, loading, error, refetch };
|
||||
};
|
||||
|
||||
//Khusus Ambil Intern dari Project/{id}
|
||||
export const useProjectInterns = (projectId: string) => {
|
||||
const [interns, setInterns] = useState<ProjectMember[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
setLoading(true);
|
||||
getProjectMembers(projectId)
|
||||
.then(setInterns)
|
||||
.catch(() => setError("Gagal memuat participants."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [projectId]);
|
||||
|
||||
return { interns, loading, error };
|
||||
};
|
||||
|
||||
// GET /project-api/my-projects
|
||||
export const useMyProjects = () => {
|
||||
const [projects, setProjects] = useState<ProjectDetail[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getMyProjects()
|
||||
.then(setProjects)
|
||||
.catch(() => setError("Gagal memuat project."))
|
||||
.catch(() => setError("Gagal memuat my projects."))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
return { projects, loading, error };
|
||||
};
|
||||
|
||||
export const useInternTasks = () => {
|
||||
const [tasks, setTasks] = useState<InternTask[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// GET /project-api/my-tasks
|
||||
export const useMyTasks = () => {
|
||||
const [tasks, setTasks] = useState<InternTaskItem[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
getMyTasks()
|
||||
.then(setTasks)
|
||||
.catch(() => setError("Gagal memuat tasks."))
|
||||
@@ -38,3 +113,118 @@ export const useInternTasks = () => {
|
||||
return { tasks, loading, error };
|
||||
};
|
||||
|
||||
// GET /project-api/mentor-projects
|
||||
export const useMentorProjects = () => {
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getMentorProjects()
|
||||
.then(setProjects)
|
||||
.catch(() => setError("Gagal memuat mentor projects."))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
return { projects, loading, error };
|
||||
};
|
||||
|
||||
// GET /project-api/interns
|
||||
export const useAllInterns = () => {
|
||||
const [interns, setInterns] = useState<InternDetail[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getAllInterns()
|
||||
.then(setInterns)
|
||||
.catch(() => setError("Gagal memuat data interns."))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
return { interns, loading, error };
|
||||
};
|
||||
|
||||
// POST /project-api/add
|
||||
export const useCreateProject = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const create = async (payload: CreateProjectPayload) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
return await createProject(payload);
|
||||
} catch {
|
||||
setError("Gagal membuat project.");
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return { create, loading, error };
|
||||
};
|
||||
|
||||
// PATCH /project-api/update/{id}
|
||||
export const useUpdateProject = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const update = async (id: string | number, payload: UpdateProjectPayload) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
return await updateProject(id, payload);
|
||||
} catch {
|
||||
setError("Gagal mengupdate project.");
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return { update, loading, error };
|
||||
};
|
||||
|
||||
// DELETE /project-api/delete/{id}
|
||||
export const useArchiveProject = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const archive = async (id: string | number) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
return await archiveProject(id);
|
||||
} catch {
|
||||
setError("Gagal mengarsipkan project.");
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return { archive, loading, error };
|
||||
};
|
||||
|
||||
// POST /project-api/assign-member
|
||||
export const useAssignMember = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const assign = async (payload: AssignMemberPayload) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
return await assignMember(payload);
|
||||
} catch {
|
||||
setError("Gagal assign member.");
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return { assign, loading, error };
|
||||
};
|
||||
@@ -0,0 +1,180 @@
|
||||
// hooks/useTasks.ts
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import type { ProjectTask, ProjectTaskDetail, CreateTaskPayload, UpdateTaskPayload, TaskSubmissionData } from "../types/task.types";
|
||||
import {
|
||||
getProjectTasks,
|
||||
getTaskById,
|
||||
createTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
submitTaskFile,
|
||||
submitTaskLink,
|
||||
updateSubmissionFile,
|
||||
updateSubmissionLink,
|
||||
deleteSubmission,
|
||||
} from "../services/TaskService";
|
||||
|
||||
// GET /task-api/projects/{id_project}/tasks
|
||||
export const useProjectTasks = (projectId: string) => {
|
||||
const [tasks, setTasks] = useState<ProjectTask[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
setLoading(true);
|
||||
getProjectTasks(projectId)
|
||||
.then(setTasks)
|
||||
.catch(() => setError("Gagal memuat task."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [projectId]);
|
||||
|
||||
return { tasks, loading, error };
|
||||
};
|
||||
|
||||
// GET /task-api/tasks/{id}
|
||||
export const useTaskDetail = (taskId: string, projectId?: string) => {
|
||||
const [task, setTask] = useState<ProjectTaskDetail | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const refetch = useCallback(() => {
|
||||
if (!taskId) return;
|
||||
setLoading(true);
|
||||
getTaskById(taskId, projectId)
|
||||
.then(setTask)
|
||||
.catch(() => setError("Gagal memuat detail task."))
|
||||
.finally(() => setLoading(false));
|
||||
}, [taskId, projectId]);
|
||||
|
||||
useEffect(() => { refetch(); }, [refetch]);
|
||||
|
||||
return { task, loading, error, refetch };
|
||||
};
|
||||
|
||||
// POST /task-api/projects/{id_project}/tasks
|
||||
export const useCreateTask = (projectId: string) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const create = async (payload: CreateTaskPayload): Promise<ProjectTask | null> => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
return await createTask(projectId, payload);
|
||||
} catch {
|
||||
setError("Gagal membuat task.");
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return { create, loading, error };
|
||||
};
|
||||
|
||||
// PATCH /task-api/tasks/{id}
|
||||
export const useUpdateTask = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const update = async (
|
||||
taskId: string | number,
|
||||
payload: UpdateTaskPayload,
|
||||
projectId?: string
|
||||
) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
return await updateTask(taskId, payload, projectId);
|
||||
} catch {
|
||||
setError("Gagal mengupdate task.");
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return { update, loading, error };
|
||||
};
|
||||
|
||||
// DELETE /task-api/tasks/{id}
|
||||
export const useDeleteTask = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const remove = async (taskId: string | number, projectId?: string) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
await deleteTask(taskId, projectId);
|
||||
return true;
|
||||
} catch {
|
||||
setError("Gagal menghapus task.");
|
||||
return false;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return { remove, loading, error };
|
||||
};
|
||||
|
||||
// POST + PATCH + DELETE submission — digabung dalam satu hook per task
|
||||
export const useSubmission = (taskId: string, initialSubmission?: TaskSubmissionData | null, projectId?: string) => {
|
||||
const [submission, setSubmission] = useState<TaskSubmissionData | null>(initialSubmission ?? null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const submitFile = async (file: File) => {
|
||||
setLoading(true); setError(null);
|
||||
try {
|
||||
const res = await submitTaskFile(taskId, file, projectId);
|
||||
if (res) setSubmission(res);
|
||||
return res;
|
||||
} catch { setError("Gagal submit file."); return null; }
|
||||
finally { setLoading(false); }
|
||||
};
|
||||
|
||||
const submitLink = async (url: string) => {
|
||||
setLoading(true); setError(null);
|
||||
try {
|
||||
const res = await submitTaskLink(taskId, url, projectId);
|
||||
if (res) setSubmission(res);
|
||||
return res;
|
||||
} catch { setError("Gagal submit link."); return null; }
|
||||
finally { setLoading(false); }
|
||||
};
|
||||
|
||||
const updateFile = async (submissionId: number, file: File) => {
|
||||
setLoading(true); setError(null);
|
||||
try {
|
||||
const res = await updateSubmissionFile(submissionId, file);
|
||||
if (res) setSubmission(res);
|
||||
return res;
|
||||
} catch { setError("Gagal update submission."); return null; }
|
||||
finally { setLoading(false); }
|
||||
};
|
||||
|
||||
const updateLink = async (submissionId: number, url: string) => {
|
||||
setLoading(true); setError(null);
|
||||
try {
|
||||
const res = await updateSubmissionLink(submissionId, url);
|
||||
if (res) setSubmission(res);
|
||||
return res;
|
||||
} catch { setError("Gagal update submission."); return null; }
|
||||
finally { setLoading(false); }
|
||||
};
|
||||
|
||||
const remove = async (submissionId: number) => {
|
||||
setLoading(true); setError(null);
|
||||
try {
|
||||
await deleteSubmission(submissionId);
|
||||
setSubmission(null);
|
||||
return true;
|
||||
} catch { setError("Gagal hapus submission."); return false; }
|
||||
finally { setLoading(false); }
|
||||
};
|
||||
|
||||
return { submission, submitFile, submitLink, updateFile, updateLink, remove, loading, error };
|
||||
};
|
||||
Reference in New Issue
Block a user