From 41349e5303d8a030d26611a2983b106ce13013a0 Mon Sep 17 00:00:00 2001 From: "Kemas M. Aryadary Rasyad" <112590882+aryadary0706@users.noreply.github.com> Date: Wed, 29 Jul 2026 01:29:16 +0700 Subject: [PATCH] feat: implement certificate history, intern submission views, and task management hooks --- src/Pages/Landing.tsx | 6 - .../internify/intern/InternCertDetail.tsx | 14 ++- .../intern/components/CertificateAvailabe.tsx | 21 ++-- .../intern/components/CertificateHistory.tsx | 5 +- .../components/CertificateNotAvailable.tsx | 17 ++- .../internify/mentor/ViewInternSubmission.tsx | 6 +- .../mentor/components/EditSubmissionTask.tsx | 21 +++- .../mentor/components/EditTaskDialog.tsx | 2 - src/Pages/utils/testlayout.html | 108 ------------------ src/assets/template.png | Bin 228883 -> 0 bytes src/hooks/useTasks.ts | 3 +- 11 files changed, 56 insertions(+), 147 deletions(-) delete mode 100644 src/Pages/utils/testlayout.html delete mode 100644 src/assets/template.png diff --git a/src/Pages/Landing.tsx b/src/Pages/Landing.tsx index b7a5d27..0880609 100644 --- a/src/Pages/Landing.tsx +++ b/src/Pages/Landing.tsx @@ -58,12 +58,6 @@ const Landing = () => { return feedbacks[displayIndex]; }, [feedbacks, displayIndex]); - // 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 fetch(`${import.meta.env.VITE_API_BASE_URL}/lowongan-magang-api/get`) diff --git a/src/Pages/internify/intern/InternCertDetail.tsx b/src/Pages/internify/intern/InternCertDetail.tsx index de7f6ad..bfaa0f4 100644 --- a/src/Pages/internify/intern/InternCertDetail.tsx +++ b/src/Pages/internify/intern/InternCertDetail.tsx @@ -32,7 +32,12 @@ export default function InternCertificateDetail() { }; }, [projectDetail, projectFromList]); - const allTasksDone = !projectLoading && !!project && project.task_done >= project.total_tasks; + + const allTasksDone = + !projectLoading && + !!project && + (project.total_tasks ?? 0) > 0 && + project.task_done >= project.total_tasks; const progress = project && project.total_tasks > 0 @@ -50,10 +55,8 @@ export default function InternCertificateDetail() {
- {/* Kolom kiri: certificate box */}
- {/* Kolom kanan: history box */}
@@ -68,9 +71,9 @@ export default function InternCertificateDetail() {
- {myCertificateForProject ? ( + {myCertificateForProject && (project?.total_tasks ?? 0) > 0 ? ( @@ -79,6 +82,7 @@ export default function InternCertificateDetail() { progress={progress} remainingTasks={remainingTasks} allTasksDone={allTasksDone} + noTasks={(project?.total_tasks ?? 0) === 0} /> )}
diff --git a/src/Pages/internify/intern/components/CertificateAvailabe.tsx b/src/Pages/internify/intern/components/CertificateAvailabe.tsx index fbceb0d..aea9320 100644 --- a/src/Pages/internify/intern/components/CertificateAvailabe.tsx +++ b/src/Pages/internify/intern/components/CertificateAvailabe.tsx @@ -123,7 +123,7 @@ export default function CertificateAvailable({ project, certificate, templateUrl
{/* Program Summary */} -
+

Ringkasan Program

@@ -138,13 +138,13 @@ export default function CertificateAvailable({ project, certificate, templateUrl key={row.label} className="flex justify-between items-center text-sm border-b border-card-outline pb-2 last:border-0" > - {row.label} - {row.value} + {row.label} + {row.value}
))}
- + {/* End Program Summary */}
{/* Unduh Sertifikat */} @@ -174,20 +174,19 @@ export default function CertificateAvailable({ project, certificate, templateUrl
diff --git a/src/Pages/internify/intern/components/CertificateHistory.tsx b/src/Pages/internify/intern/components/CertificateHistory.tsx index 5cea127..235380d 100644 --- a/src/Pages/internify/intern/components/CertificateHistory.tsx +++ b/src/Pages/internify/intern/components/CertificateHistory.tsx @@ -35,11 +35,12 @@ export default function SertificateHistory() { {displayed.map((item: Certificate) => (

{new Date(item.issued_at).toLocaleDateString("id-ID", { + day: "numeric", year: "numeric", month: "long", })} @@ -47,7 +48,7 @@ export default function SertificateHistory() {

{item.project.project_name}

-

{item.certificate_no}

+

{item.certificate_no}

))} diff --git a/src/Pages/internify/intern/components/CertificateNotAvailable.tsx b/src/Pages/internify/intern/components/CertificateNotAvailable.tsx index c1e9faa..0fde6c9 100644 --- a/src/Pages/internify/intern/components/CertificateNotAvailable.tsx +++ b/src/Pages/internify/intern/components/CertificateNotAvailable.tsx @@ -1,16 +1,19 @@ import { Clock, Lock } from "lucide-react"; import { FaAward } from "react-icons/fa"; +import { ListTodo } from "lucide-react"; interface CertificateNotAvailableProps { progress: number; remainingTasks: number; allTasksDone?: boolean; + noTasks?: boolean; } export default function CertificateNotAvailable({ progress, remainingTasks, allTasksDone = false, + noTasks = false, }: CertificateNotAvailableProps) { return (
@@ -18,7 +21,9 @@ export default function CertificateNotAvailable({
- {allTasksDone ? ( + {noTasks ? ( + + ) : allTasksDone ? ( ) : ( @@ -30,7 +35,15 @@ export default function CertificateNotAvailable({
- {allTasksDone ? ( + {noTasks ? ( + <> +

Sertifikat Belum Tersedia

+

+ Proyek ini belum memiliki tugas yang ditetapkan. + Sertifikat akan tersedia setelah semua tugas proyek diselesaikan. +

+ + ) : allTasksDone ? ( <>

Selamat!

diff --git a/src/Pages/internify/mentor/ViewInternSubmission.tsx b/src/Pages/internify/mentor/ViewInternSubmission.tsx index e43778e..c3cf86e 100644 --- a/src/Pages/internify/mentor/ViewInternSubmission.tsx +++ b/src/Pages/internify/mentor/ViewInternSubmission.tsx @@ -1,5 +1,5 @@ import { useParams, useLocation } from "react-router-dom"; -import { Download, Clock, AlertCircle } from "lucide-react"; +import { Download, AlertCircle, User2 } from "lucide-react"; import { useTaskSubmissions } from "../../../hooks/useTasks"; import type { DisplayStatus } from "../../../types/task.types"; import { StatusTable } from "./components/StatusSubmissionTable"; @@ -50,8 +50,8 @@ export default function ViewInternSubmission() { {task.title}

- - {internSubmission.full_name} — {internSubmission.email} + + {internSubmission.full_name}

diff --git a/src/Pages/internify/mentor/components/EditSubmissionTask.tsx b/src/Pages/internify/mentor/components/EditSubmissionTask.tsx index 886c0fc..44d0c51 100644 --- a/src/Pages/internify/mentor/components/EditSubmissionTask.tsx +++ b/src/Pages/internify/mentor/components/EditSubmissionTask.tsx @@ -20,8 +20,6 @@ export default function EditSubmissionModal({ }: EditTaskModalProps) { const dialogRef = useRef(null); const { update, loading, error } = useUpdateTask(); - - // Form States — diinisialisasi dari props task const [taskTitle, setTaskTitle] = useState(task.title); const [description, setDescription] = useState(task.description); const [deadlineDate, setDeadlineDate] = useState( @@ -32,7 +30,9 @@ export default function EditSubmissionModal({ ); const [submissionType, setSubmissionType] = useState(task.submission_type); - // Sync form ketika task berubah (misal modal dibuka untuk task berbeda) + const today = new Date().toISOString().split("T")[0]; + const isDeadlinePast = !!deadlineDate && deadlineDate < today; + useEffect(() => { setTaskTitle(task.title); setDescription(task.description); @@ -108,7 +108,7 @@ export default function EditSubmissionModal({ {/* Error Message */} {error && ( -
+
{error}
)} @@ -148,9 +148,18 @@ export default function EditSubmissionModal({ required value={deadlineDate} onChange={(e) => setDeadlineDate(e.target.value)} - className="w-full p-3 py-2.5 bg-white border border-gray-200 rounded-lg text-sm font-medium text-gray-800 focus:outline-none focus:border-[#B30000] focus:ring-1 focus:ring-[#B30000] appearance-none" + className={`w-full p-3 py-2.5 bg-white border rounded-lg text-sm font-medium text-gray-800 focus:outline-none appearance-none ${ + isDeadlinePast + ? "border-red-400 focus:border-red-500 focus:ring-1 focus:ring-red-400" + : "border-gray-200 focus:border-[#B30000] focus:ring-1 focus:ring-[#B30000]" + }`} />
+ {isDeadlinePast && ( +

+ Tenggat waktu tidak boleh sebelum hari ini. +

+ )}
@@ -200,7 +209,7 @@ export default function EditSubmissionModal({