[UNTEST] CERTIFICATE GENERATION AND BACKEND ENDPOINT IMPLEMENTATION ON CERTIFICATES (CLAIM, GENERATE, FETCH DATA)
- Updated AddInternsModal to allow selection of interns via dropdown instead of email input. - Introduced CertResultTable component for displaying certificate results with search and pagination. - Modified CreateProjectDialog to accept an onSuccess callback for better project creation handling. - Integrated certificate generation functionality in EligibleInternTable with improved error handling. - Enhanced HomeMentorProject and MentorProjectCard to dynamically display project icons and statuses. - Refactored SidebarMentor to improve active route detection. - Added utility functions for certificate preview and download in Certificates.ts. - Removed unused DownloadImagetoDevice utility and related hooks. - Implemented useProjectsByRole hook for fetching projects based on user role. - Updated types for certificates and projects to reflect recent changes in the data structure.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
// src/pages/intern/SertificatePage.tsx
|
||||
import { useMemo } from "react";
|
||||
import { useParams, useLocation } from "react-router-dom";
|
||||
import CertificateAvailable from "./components/CertificateAvailabe";
|
||||
import CertificateNotAvailable from "./components/CertificateNotAvailable";
|
||||
import SertificateHistory from "./components/CertificateHistory";
|
||||
|
||||
import { useClaimCertificate } from "../../../hooks/useCertificates";
|
||||
import { useProjectDetail } from "../../../hooks/useProjects";
|
||||
|
||||
import { useProjectCertificates } from "../../../hooks/useCertificates";
|
||||
import type { Project } from "../../../types/project.types";
|
||||
|
||||
export default function InternCertificateDetail () {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
const location = useLocation();
|
||||
const projectFromList = location.state?.project as Project | undefined;
|
||||
|
||||
const { project: projectDetail, loading: projectLoading } = useProjectDetail(slug ?? "");
|
||||
const { certificates, loading: certLoading, refetch: refetchCertificates } = useProjectCertificates(projectDetail?.id ?? 0);
|
||||
const { claim, loading: claiming, error: claimError } = useClaimCertificate();
|
||||
|
||||
const myCertificateForProject = useMemo(() => {
|
||||
if (!projectDetail) return null;
|
||||
return certificates.find((cert) => cert.id_project === projectDetail.id);
|
||||
}, [projectDetail, certificates]);
|
||||
|
||||
const project = useMemo(() => {
|
||||
if (!projectDetail) return null;
|
||||
return {
|
||||
...projectDetail,
|
||||
task_done: projectFromList?.task_done ?? 0,
|
||||
total_tasks: projectFromList?.total_tasks ?? projectDetail.total_tasks,
|
||||
};
|
||||
}, [projectDetail, projectFromList]);
|
||||
|
||||
const allTasksDone = !projectLoading && !!project && project.task_done >= project.total_tasks;
|
||||
|
||||
const progress =
|
||||
project && project.total_tasks > 0
|
||||
? Math.round((project.task_done / project.total_tasks) * 100)
|
||||
: 0;
|
||||
const remainingTasks = project ? project.total_tasks - project.task_done : 0;
|
||||
const isLoading = projectLoading || certLoading;
|
||||
|
||||
const handleClaim = async () => {
|
||||
if (!project?.id) return;
|
||||
const result = await claim(project.id);
|
||||
if (result) {
|
||||
refetchCertificates();
|
||||
}
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center py-20 text-gray-400 text-sm">
|
||||
Memuat Data...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-4 flex flex-col gap-1">
|
||||
<h1 className="page-title">Certificates</h1>
|
||||
<p className="page-title-desc">View and download internship certificates</p>
|
||||
</div>
|
||||
<div className="flex flex-col lg:flex-row gap-6 items-stretch">
|
||||
<div className="w-full lg:w-5/8 flex flex-col">
|
||||
{myCertificateForProject ? (
|
||||
<CertificateAvailable
|
||||
project={project}
|
||||
certificate={myCertificateForProject}
|
||||
templateUrl = {project?.certificate_template ?? ""}
|
||||
/>
|
||||
) : (
|
||||
<CertificateNotAvailable
|
||||
progress={progress}
|
||||
remainingTasks={remainingTasks}
|
||||
allTasksDone={allTasksDone}
|
||||
onClaim={handleClaim}
|
||||
claiming={claiming}
|
||||
claimError={claimError}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-full lg:w-3/8 flex-shrink-0">
|
||||
<SertificateHistory />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user