diff --git a/src/Pages/internify/intern/ForumTab.tsx b/src/Pages/internify/intern/ForumTab.tsx
index ace03e0..0441557 100644
--- a/src/Pages/internify/intern/ForumTab.tsx
+++ b/src/Pages/internify/intern/ForumTab.tsx
@@ -10,7 +10,6 @@ export default function ForumTab({ project }: { project: Project }) {
const { tasks, loading, error } = useProjectTasks(slug ?? "");
return (
- {/* Hero banner */}
{/* Loading */}
diff --git a/src/Pages/internify/intern/ProjectDetailPage.tsx b/src/Pages/internify/intern/ProjectDetailPage.tsx
index 5249e58..d27c2c0 100644
--- a/src/Pages/internify/intern/ProjectDetailPage.tsx
+++ b/src/Pages/internify/intern/ProjectDetailPage.tsx
@@ -8,8 +8,6 @@ export default function ProjectDetailPage() {
const { slug } = useParams<{ slug: string }>();
const { project, loading, error } = useProjectDetail(slug ?? "");
const [activeTab, setActiveTab] = useState<'forum' | 'participants'>('forum');
-
- // Fallback sederhana
if (loading) return
Memuat project...
;
if (error) return
{error}
;
if (!project) return
Project tidak ditemukan.
;
diff --git a/src/Pages/internify/mentor/CertificatePage.tsx b/src/Pages/internify/mentor/CertificatePage.tsx
index 92a5396..45c66d1 100644
--- a/src/Pages/internify/mentor/CertificatePage.tsx
+++ b/src/Pages/internify/mentor/CertificatePage.tsx
@@ -11,7 +11,6 @@ import {
} from 'lucide-react';
import { LuHistory, LuSendHorizontal } from 'react-icons/lu';
-// Mock Data untuk Tabel Riwayat Sertifikat
const initialHistoryData = [
{ id: 1, name: "Jonathan Kristina", email: "JonathanKristina@gmail.com", project: "Internify Project", date: "24 Oct 2024", initials: "JK" },
{ id: 2, name: "Ahmad Faisal", email: "ahmad.faisal@gmail.com", project: "Web Dev Fundamentals", date: "15 Sep 2024", initials: "AF" },
diff --git a/src/Pages/internify/mentor/ProjectsInternTab.tsx b/src/Pages/internify/mentor/ProjectsInternTab.tsx
index 3c4426d..006cd8e 100644
--- a/src/Pages/internify/mentor/ProjectsInternTab.tsx
+++ b/src/Pages/internify/mentor/ProjectsInternTab.tsx
@@ -2,10 +2,21 @@ import { useState } from 'react';
import { Plus } from 'lucide-react';
import ManageInternsModal from './components/AddInternsDialog';
import type { ProjectDetail, ProjectMember } from '../../../types/project.types';
-import { useProjectInterns } from '../../../hooks/useProjects';
+import { useRemoveMember } from '../../../hooks/useProjects';
export default function InternsTab({ project }: { project: ProjectDetail }) {
const [isModalOpen, setIsModalOpen] = useState(false);
+ const { remove, loading } = useRemoveMember();
+
+ const handleRemove = async (id_user: number) => {
+ if (window.confirm('Are you sure you want to remove this member?')) {
+ const res = await remove({ id_project: project.id, id_user });
+ if (res !== null) {
+ alert('Member removed successfully');
+ window.location.reload();
+ }
+ }
+ };
return (
@@ -62,7 +73,11 @@ export default function InternsTab({ project }: { project: ProjectDetail }) {
{member.position}
-
diff --git a/src/Pages/internify/mentor/components/CreateProjectDialog.tsx b/src/Pages/internify/mentor/components/CreateProjectDialog.tsx
index 91d565a..602b0cd 100644
--- a/src/Pages/internify/mentor/components/CreateProjectDialog.tsx
+++ b/src/Pages/internify/mentor/components/CreateProjectDialog.tsx
@@ -11,16 +11,11 @@ interface CreateProjectModalProps {
export default function CreateProjectModal({ isOpen, onClose }: CreateProjectModalProps) {
const dialogRef = useRef
(null);
-
- // State Form Management
const [selectedIcon, setSelectedIcon] = useState(PROJECT_ICON_CODES[0]);
const [projectName, setProjectName] = useState("");
const [projectDescription, setProjectDescription] = useState("");
const [emailInput, setEmailInput] = useState("");
- const [invitedEmails, setInvitedEmails] = useState([
- "alex.dev@gmail.com",
- "sarah.engineer@gmail.com"
- ]);
+ const [invitedEmails, setInvitedEmails] = useState([]);
const [startDate, setStartDate] = useState("");
const [endDate, setEndDate] = useState("");
const { create, loading, error } = useCreateProject();
@@ -54,7 +49,6 @@ export default function CreateProjectModal({ isOpen, onClose }: CreateProjectMod
};
}, [isOpen, onClose]);
- // Fungsi menambah email undangan baru
const handleAddEmail = (e: React.FormEvent) => {
e.preventDefault();
if (emailInput.trim() && !invitedEmails.includes(emailInput.trim())) {
@@ -63,7 +57,6 @@ export default function CreateProjectModal({ isOpen, onClose }: CreateProjectMod
}
};
- // Fungsi menghapus email undangan
const handleRemoveEmail = (emailToRemove: string) => {
setInvitedEmails(invitedEmails.filter(email => email !== emailToRemove));
};
@@ -71,14 +64,19 @@ export default function CreateProjectModal({ isOpen, onClose }: CreateProjectMod
// Handler Submit Utama
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
- const result = await create({
+ const payload: any = {
project_icon: selectedIcon,
project_name: projectName,
description: projectDescription,
- member_emails: invitedEmails,
start_date: startDate,
end_date: endDate,
- });
+ };
+
+ if (invitedEmails.length > 0) {
+ payload.member_emails = invitedEmails;
+ }
+
+ const result = await create(payload);
if (result) {
onClose();
}
@@ -226,7 +224,7 @@ export default function CreateProjectModal({ isOpen, onClose }: CreateProjectMod
required
value={startDate}
onChange={(e) => setStartDate(e.target.value)}
- className="w-full pl-4 pr-10 py-2.5 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:outline-none focus:border-red-600 focus:ring-1 focus:ring-red-600 font-medium appearance-none"
+ className="w-full px-3 py-2.5 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:outline-none focus:border-red-600 focus:ring-1 focus:ring-red-600 font-medium appearance-none"
/>
@@ -244,7 +242,7 @@ export default function CreateProjectModal({ isOpen, onClose }: CreateProjectMod
required
value={endDate}
onChange={(e) => setEndDate(e.target.value)}
- className="w-full pl-4 pr-10 py-2.5 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:outline-none focus:border-red-600 focus:ring-1 focus:ring-red-600 font-medium appearance-none"
+ className="w-full px-3 py-2.5 bg-white border border-gray-200 rounded-lg text-sm text-gray-800 focus:outline-none focus:border-red-600 focus:ring-1 focus:ring-red-600 font-medium appearance-none"
/>
diff --git a/src/Pages/internify/mentor/components/CreateTaskDialog.tsx b/src/Pages/internify/mentor/components/CreateTaskDialog.tsx
index 34f12b0..d3da25b 100644
--- a/src/Pages/internify/mentor/components/CreateTaskDialog.tsx
+++ b/src/Pages/internify/mentor/components/CreateTaskDialog.tsx
@@ -80,7 +80,7 @@ export default function CreateTaskModal({ isOpen, onClose, projectId, onSuccess
required
value={deadlineDate}
onChange={(e) => setDeadlineDate(e.target.value)}
- className="w-full pl-3 pr-9 py-3 bg-white border border-gray-200 rounded-lg text-xs font-medium text-gray-800 focus:outline-none focus:border-[#B30000] focus:ring-1 focus:ring-[#B30000]" />
+ className="w-full px-3 py-3 bg-white border border-gray-200 rounded-lg text-xs font-medium text-gray-800 focus:outline-none focus:border-[#B30000] focus:ring-1 focus:ring-[#B30000]" />
@@ -89,7 +89,7 @@ export default function CreateTaskModal({ isOpen, onClose, projectId, onSuccess
required
value={specificTime}
onChange={(e) => setSpecificTime(e.target.value)}
- className="w-full pl-3 pr-9 py-3 bg-white border border-gray-200 rounded-lg text-xs font-medium text-gray-800 focus:outline-none focus:border-[#B30000] focus:ring-1 focus:ring-[#B30000]" />
+ className="w-full px-3 py-3 bg-white border border-gray-200 rounded-lg text-xs font-medium text-gray-800 focus:outline-none focus:border-[#B30000] focus:ring-1 focus:ring-[#B30000]" />
diff --git a/src/Pages/internify/mentor/components/EditSubmissionTask.tsx b/src/Pages/internify/mentor/components/EditSubmissionTask.tsx
index a306d37..985c898 100644
--- a/src/Pages/internify/mentor/components/EditSubmissionTask.tsx
+++ b/src/Pages/internify/mentor/components/EditSubmissionTask.tsx
@@ -1,6 +1,6 @@
import { useRef, useEffect, useState } from "react";
import { X } from "lucide-react";
-import { LuSave, LuCalendar } from "react-icons/lu";
+import { LuSave } from "react-icons/lu";
interface EditTaskModalProps {
isOpen: boolean;
diff --git a/src/Pages/internify/mentor/components/MentorProjectCard.tsx b/src/Pages/internify/mentor/components/MentorProjectCard.tsx
index 1a6c657..b850c12 100644
--- a/src/Pages/internify/mentor/components/MentorProjectCard.tsx
+++ b/src/Pages/internify/mentor/components/MentorProjectCard.tsx
@@ -20,13 +20,14 @@ export default function MentorProjectCard(project: Project) {
const Icon = getDynamicIcon(project.project_icon);
const handleDeleteClick = (e: React.MouseEvent
) => {
+ e.stopPropagation();
}
return (
{/* Thumbnail */}
-
+
diff --git a/src/hooks/useProjects.ts b/src/hooks/useProjects.ts
index c23951c..2cb267c 100644
--- a/src/hooks/useProjects.ts
+++ b/src/hooks/useProjects.ts
@@ -21,7 +21,8 @@ import {
updateProject,
archiveProject,
assignMember,
- getProjectMembers
+ getProjectMembers,
+ removeMember
} from "../services/ProjectService";
// GET /project-api/get
@@ -227,4 +228,24 @@ export const useAssignMember = () => {
};
return { assign, loading, error };
+};
+
+export const useRemoveMember = () => {
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState
(null);
+
+ const remove = async (payload: { id_project: string | number, id_user: number }) => {
+ setLoading(true);
+ setError(null);
+ try {
+ return await removeMember(payload);
+ } catch {
+ setError("Gagal remove member.");
+ return null;
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return { remove, loading, error };
};
\ No newline at end of file
diff --git a/src/services/ProjectService.ts b/src/services/ProjectService.ts
index a5a9b07..5f5e2e6 100644
--- a/src/services/ProjectService.ts
+++ b/src/services/ProjectService.ts
@@ -15,7 +15,7 @@ import type {
// POST /project-api/add
export const createProject = async (
payload: CreateProjectPayload
-): Promise => {
+): Promise => {
const res = await api.post("/project-api/add", payload);
return res.data.data;
};
@@ -23,7 +23,7 @@ export const createProject = async (
// GET /project-api/get
export const getProjects = async (
status?: "active" | "completed" | "archived"
-): Promise => {
+): Promise => {
const res = await api.get("/project-api/get", {
params: status ? { status } : undefined,
});
@@ -115,4 +115,14 @@ export const assignMember = async (
): Promise => {
const res = await api.post("/project-api/assign-member", payload);
return res.data.data;
+};
+
+export const removeMember = async (
+ payload: {
+ id_project: string | number;
+ id_user: number;
+ }
+): Promise => {
+ const res = await api.post("/project-api/remove-member", { id_project: payload.id_project, id_user: payload.id_user });
+ return res.data.data;
};
\ No newline at end of file
diff --git a/src/types/project.types.ts b/src/types/project.types.ts
index df5a146..ad8e362 100644
--- a/src/types/project.types.ts
+++ b/src/types/project.types.ts
@@ -16,6 +16,7 @@ export interface Project {
id: number;
slug: string;
project_icon: string;
+ background_color: string;
project_name: string;
description: string;
start_date: string;