From 328bcbcdc2129ffa034f83a728ada3a83a1dcbc6 Mon Sep 17 00:00:00 2001 From: "Kemas M. Aryadary Rasyad" <112590882+aryadary0706@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:24:56 +0700 Subject: [PATCH] Perbaikan pada landing page: Gambar Feedback menjadi statis Taskform type link: saat diupdate sudah diarahkan ke submission status Settings Page: Penambahan data user di samping gambar profile_picture Penambahan warning dialog pada saat melakukan archiveProject dan CompletedProject pada list mentor project Input durasi projek format string pada SertificateGenerator --- src/Pages/Landing.tsx | 21 +- src/Pages/internify/SettingsPage.tsx | 2 +- .../intern/components/TaskForm-link.tsx | 50 +++-- .../internify/mentor/BaseProjectsPage.tsx | 8 +- .../internify/mentor/CertificateForm.tsx | 27 ++- .../components/ArchiveProjectDialog.tsx | 108 ++++++++++ .../components/CompleteProjectDialog.tsx | 109 ++++++++++ .../mentor/components/CreateTaskDialog.tsx | 38 +++- .../mentor/components/EligibleInternTable.tsx | 8 +- .../mentor/components/MentorProjectCard.tsx | 190 ++++++++++++------ .../mentor/components/SidebarMentor.tsx | 4 +- src/Pages/utils/SertificateGenerator.ts | 4 +- src/hooks/useProjects.ts | 6 +- src/index.css | 25 +-- src/services/ProjectService.ts | 2 +- 15 files changed, 456 insertions(+), 146 deletions(-) create mode 100644 src/Pages/internify/mentor/components/ArchiveProjectDialog.tsx create mode 100644 src/Pages/internify/mentor/components/CompleteProjectDialog.tsx diff --git a/src/Pages/Landing.tsx b/src/Pages/Landing.tsx index 3f8fd24..e8346b6 100644 --- a/src/Pages/Landing.tsx +++ b/src/Pages/Landing.tsx @@ -57,10 +57,11 @@ const Landing = () => { return feedbacks[displayIndex]; }, [feedbacks, displayIndex]); - const currentImgUrl = useMemo(() => { - if (!currentFeedback) return ""; - return getFeedbackImageUrl(currentFeedback.image_path); - }, [currentFeedback]); + // Gambar statis: selalu pakai foto dari feedback pertama + const staticImgUrl = useMemo(() => { + if (feedbacks.length === 0) return ""; + return getFeedbackImageUrl(feedbacks[0].image_path); + }, [feedbacks]); useEffect(() => { // Fetch internships @@ -217,17 +218,11 @@ const Landing = () => {
{currentFeedback.nama}
diff --git a/src/Pages/internify/SettingsPage.tsx b/src/Pages/internify/SettingsPage.tsx index 62d3bfb..ed0c717 100644 --- a/src/Pages/internify/SettingsPage.tsx +++ b/src/Pages/internify/SettingsPage.tsx @@ -155,7 +155,7 @@ export default function MentorSettingsPage() {

{photoFile && (

- 📎 {photoFile.name} + {photoFile.name}

)}
diff --git a/src/Pages/internify/intern/components/TaskForm-link.tsx b/src/Pages/internify/intern/components/TaskForm-link.tsx index 2967480..e39780e 100644 --- a/src/Pages/internify/intern/components/TaskForm-link.tsx +++ b/src/Pages/internify/intern/components/TaskForm-link.tsx @@ -13,7 +13,12 @@ interface TaskFormLinkProps { initialSubmission?: TaskSubmissionData | null; } -export default function TaskFormLink({ taskId, projectId, deadline, initialSubmission }: TaskFormLinkProps) { +export default function TaskFormLink({ + taskId, + projectId, + deadline, + initialSubmission +}: TaskFormLinkProps) { const { submission, loading, submitLink, updateLink, remove } = useSubmission(taskId, initialSubmission, projectId); const [inputLink, setInputLink] = useState(initialSubmission?.url_link ?? ""); const [isEditing, setIsEditing] = useState(false); @@ -28,25 +33,30 @@ export default function TaskFormLink({ taskId, projectId, deadline, initialSubmi return; } - await customToast.promise( - isEditing ? updateLink(submission!.id, inputLink) : submitLink(inputLink), - { - loading: isEditing ? "Memperbarui Link..." : "Mengirim Link...", - success: () => ({ - title: isEditing ? "Link diperbaharui" : "Link berhasil dikirim", - description: isEditing - ? "Perubahan submission Anda telah disimpan." - : "Submission Anda telah 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", - }), - } - ); + try { + await customToast.promise( + isEditing ? updateLink(submission!.id, inputLink) : submitLink(inputLink), + { + loading: isEditing ? "Memperbarui Link..." : "Mengirim Link...", + success: () => ({ + title: isEditing ? "Link diperbaharui" : "Link berhasil dikirim", + description: isEditing + ? "Perubahan submission Anda telah disimpan." + : "Submission Anda telah 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", + }), + } + ); + setIsEditing(false); + } catch { + // error sudah ditangani toast, tetap di form + } }; const handleDelete = async () => { diff --git a/src/Pages/internify/mentor/BaseProjectsPage.tsx b/src/Pages/internify/mentor/BaseProjectsPage.tsx index 1dcbfd8..d78c925 100644 --- a/src/Pages/internify/mentor/BaseProjectsPage.tsx +++ b/src/Pages/internify/mentor/BaseProjectsPage.tsx @@ -2,7 +2,6 @@ import MentorProjectCard from './components/MentorProjectCard'; import { Plus } from 'lucide-react'; import { useState } from 'react'; import CreateProjectModal from './components/CreateProjectDialog'; -import { customToast } from '../../utils/showToast'; import { useProjectsByRole } from '../../../hooks/useListProjects'; export default function MentorProjectsPage() { @@ -50,7 +49,12 @@ export default function MentorProjectsPage() {
{projects.map(project => ( - + ))}
diff --git a/src/Pages/internify/mentor/CertificateForm.tsx b/src/Pages/internify/mentor/CertificateForm.tsx index 6da738f..74d22a3 100644 --- a/src/Pages/internify/mentor/CertificateForm.tsx +++ b/src/Pages/internify/mentor/CertificateForm.tsx @@ -45,14 +45,14 @@ export default function CertificateDetail() { description: err instanceof Error ? err.message : "Terjadi kesalahan saat upload.", }), } - ).then(async(result) => { + ).then(async (result) => { if (result) { setUploadSuccess(true); setSelectedFile(null); if (fileInputRef.current) fileInputRef.current.value = ""; await refetch(); } - }).catch(() => {}); + }).catch(() => { }); }; const handleClearFile = () => { @@ -97,23 +97,28 @@ export default function CertificateDetail() { Administrate, issue, and track professional certifications for all interns.

-
+
{/* Left Column */}

{project.project_name}

-
- - {new Date(project.start_date).toLocaleDateString("en-US", { month: "short", year: "numeric" })} - {" - "} - {new Date(project.end_date).toLocaleDateString("en-US", { month: "short", year: "numeric" })} +
+
+ + {new Date(project.start_date).toLocaleDateString("en-US", { month: "short", year: "numeric" })} + {" - "} + {new Date(project.end_date).toLocaleDateString("en-US", { month: "short", year: "numeric" })} +
+

+ Status: {project.status} +

-
-