diff --git a/src/Pages/internify/intern/components/ProjectTimeline.tsx b/src/Pages/internify/intern/components/ProjectTimeline.tsx
index fde4be4..c13dbdb 100644
--- a/src/Pages/internify/intern/components/ProjectTimeline.tsx
+++ b/src/Pages/internify/intern/components/ProjectTimeline.tsx
@@ -29,11 +29,11 @@ export default function ProjectTimeline({ tasks }: { tasks: InternTaskItem[] })
active ? 'bg-red' : 'bg-gray-400'
} ${isToday ? 'shadow-md' : ''}`}
/>
-
- {isToday ? 'Hari ini' : formatDate(task.deadline_at)}
+
+ {task.title}
- {task.title}
+ {isToday ? 'Hari ini' : formatDate(task.deadline_at)}
);
diff --git a/src/Pages/internify/intern/components/TaskForm-link.tsx b/src/Pages/internify/intern/components/TaskForm-link.tsx
index 84d46ee..ecfef0c 100644
--- a/src/Pages/internify/intern/components/TaskForm-link.tsx
+++ b/src/Pages/internify/intern/components/TaskForm-link.tsx
@@ -34,18 +34,14 @@ export default function TaskFormLink({
loading: isEditing ? "Memperbarui Link..." : "Mengirim Link...",
success: (res) => ({
title: isEditing ? "Link diperbaharui" : "Link berhasil dikirim",
- description:
- res?.message ??
- (isEditing
- ? "Perubahan submission Anda telah disimpan."
- : "Link berhasil dikirim."),
+ description: res?.message
+ // ?? (isEditing ? "Perubahan submission Anda telah disimpan." : "Link berhasil dikirim."),
}),
error: (err) => ({
title: isEditing ? "Gagal memperbarui link!" : "Gagal mengirim link!",
description:
- err?.response?.data?.message ||
- err?.message ||
- "Link yang anda submit gagal dikirim",
+ err?.response?.data?.message || err?.message
+ // || "Link yang anda submit gagal dikirim",
}),
}
);
diff --git a/src/Pages/internify/mentor/components/AddInternsToProjects.tsx b/src/Pages/internify/mentor/components/AddInternsToProjects.tsx
index 5c4de51..2f3bd9c 100644
--- a/src/Pages/internify/mentor/components/AddInternsToProjects.tsx
+++ b/src/Pages/internify/mentor/components/AddInternsToProjects.tsx
@@ -19,8 +19,6 @@ export default function AddInternsModal({ isOpen, onClose, userId }: AddInternsM
const { projects, loading: loadingProjects } = useProjects("active");
const { interns, loading: loadingInterns } = useAssignableInterns();
- console.log(projects)
-
useEffect(() => {
const dialog = dialogRef.current;
if (!dialog) return;
diff --git a/src/Pages/internify/mentor/components/CreateProjectDialog.tsx b/src/Pages/internify/mentor/components/CreateProjectDialog.tsx
index 9a9c6f7..cdcd3ff 100644
--- a/src/Pages/internify/mentor/components/CreateProjectDialog.tsx
+++ b/src/Pages/internify/mentor/components/CreateProjectDialog.tsx
@@ -33,6 +33,7 @@ export default function CreateProjectModal({ isOpen, onClose, onSuccess }: Creat
icon: PROJECT_ICON_MAP[id],
}));
+ //open/close doalog komponen
useEffect(() => {
const dialog = dialogRef.current;
if (!dialog) return;
@@ -54,8 +55,22 @@ export default function CreateProjectModal({ isOpen, onClose, onSuccess }: Creat
};
}, [isOpen, onClose]);
- const handleAddEmail = (emailToAdd?: string) => {
- const email = (emailToAdd ?? emailInput).trim();
+ // tutup dropdown email di luar kotak
+ useEffect(() => {
+ if (!showDropdown) return;
+
+ const handleClickOutside = (e: MouseEvent) => {
+ if (emailSectionRef.current && !emailSectionRef.current.contains(e.target as Node)) {
+ setShowDropdown(false);
+ }
+ };
+
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, [showDropdown]);
+
+
+ const handleAddEmail = (email: string) => {
if (email && !invitedEmails.includes(email)) {
setInvitedEmails([...invitedEmails, email]);
setEmailInput("");
@@ -182,34 +197,23 @@ export default function CreateProjectModal({ isOpen, onClose, onSuccess }: Creat
- {/* Input email + dropdown sugesti intern */}
+ {/* filterisasi email */}
{ setEmailInput(e.target.value); setShowDropdown(true); }}
onFocus={() => setShowDropdown(true)}
onKeyDown={(e) => {
- if (e.key === 'Enter') {
- e.preventDefault();
- handleAddEmail();
- }
- if (e.key === 'Escape') setShowDropdown(false);
+ if (e.key === 'Escape') setShowDropdown(false)
}}
- className="w-full pl-10 pr-20 py-2.5 bg-white border border-card-outline rounded-lg text-sm placeholder-gray-400 text-gray-800 focus:outline-none focus:border-red-600 focus:ring-1 focus:ring-red-600 font-medium"
+ className="w-full pl-10 pr-20 py-2.5 bg-white border border-card-outline rounded-lg text-sm placeholder-gray-400 text-gray-800 focus:outline-none focus:border-red-600 focus:ring-1 focus:ring-red-600 font-medium"
/>
-
{/* Dropdown daftar intern */}
@@ -231,12 +235,16 @@ export default function CreateProjectModal({ isOpen, onClose, onSuccess }: Creat
))
diff --git a/src/Pages/internify/mentor/components/InternsTable.tsx b/src/Pages/internify/mentor/components/InternsTable.tsx
index c6dfdc6..fe716cd 100644
--- a/src/Pages/internify/mentor/components/InternsTable.tsx
+++ b/src/Pages/internify/mentor/components/InternsTable.tsx
@@ -80,7 +80,7 @@ export default function InternsTable({
className="w-10 h-10 rounded-full object-cover border border-gray-100 shadow-sm hidden md:block"
/>
) : (
-
+
{intern.name.charAt(0)}
)}
diff --git a/src/Pages/internify/mentor/components/MentorTaskCard.tsx b/src/Pages/internify/mentor/components/MentorTaskCard.tsx
index acb92ff..9f23adb 100644
--- a/src/Pages/internify/mentor/components/MentorTaskCard.tsx
+++ b/src/Pages/internify/mentor/components/MentorTaskCard.tsx
@@ -15,6 +15,11 @@ export default function MentorTaskCard({ task }: {task: InternTaskItem}) {
navigate(`/mentor/projects/${slug}/${task.slug}?type=${task.submission_type}`)
};
+ function truncateText(text: string) {
+ if (text.length <= 230) return text;
+ return text.slice(0, 230) + "...";
+ }
+
return (
- {task.description}
+ {truncateText(task.description)}
diff --git a/src/Pages/utils/showToast.tsx b/src/Pages/utils/showToast.tsx
index bbb023b..6a7e6ca 100644
--- a/src/Pages/utils/showToast.tsx
+++ b/src/Pages/utils/showToast.tsx
@@ -3,6 +3,7 @@ import { FiX } from 'react-icons/fi';
import { FaCheck } from "react-icons/fa";
import { IoAlertCircleOutline } from "react-icons/io5";
+// Komponen Toast Card dengan Tailwind untuk pesan sukses dan pesan error
function ToastCard({ t, type, title, description }: {
t: Toast;
type: 'success' | 'error';
@@ -27,13 +28,15 @@ function ToastCard({ t, type, title, description }: {
{description &&
{description}
}
-
);
}
+
+// pemanggilan function ToastCard dengan params
export const customToast = {
success: (title: string, description?: string) =>
toast.custom((t) =>
),
@@ -55,19 +58,19 @@ export const customToast = {
const isHookFailure = typeof data === 'object' && data !== null && 'success' in data && (data as { success?: boolean }).success === false;
if (isHookFailure) {
- toast.dismiss(loadingId);
+ toast.remove(loadingId);
const result = data as { success: boolean; message?: string };
const { title, description } = messages.error(result);
customToast.error(title, description ?? result.message);
throw new Error(result.message ?? 'Operasi gagal.');
}
- toast.dismiss(loadingId);
+ toast.remove(loadingId);
const { title, description } = messages.success(data);
customToast.success(title, description);
return data;
} catch (err) {
- toast.dismiss(loadingId);
+ toast.remove(loadingId);
const { title, description } = messages.error(err);
customToast.error(title, description ?? (err as Error)?.message);
throw err;