From f5882e3cdca3897382884c6e3e49f74cc2f68efc Mon Sep 17 00:00:00 2001 From: Maulana Sodiqin Date: Thu, 11 Dec 2025 00:16:29 +0700 Subject: [PATCH] feat: integrate new certificate endpoint from backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Updated certificate page to use useCertificatePublicData hook - Removed old multi-API-call approach - Now uses single /certificates/{userId} endpoint - Simplified data fetching for user, team, submission data - Certificate now works for unauthenticated users - Removed duplicate certificate hook file 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../src/app/certificate/[certId]/page.tsx | 99 +++++++++---------- 1 file changed, 45 insertions(+), 54 deletions(-) diff --git a/apps/hackathon/src/app/certificate/[certId]/page.tsx b/apps/hackathon/src/app/certificate/[certId]/page.tsx index 144016b..8268913 100644 --- a/apps/hackathon/src/app/certificate/[certId]/page.tsx +++ b/apps/hackathon/src/app/certificate/[certId]/page.tsx @@ -3,10 +3,7 @@ import { useParams, useNavigate } from 'react-router'; import { Button } from '@imphnen-frontend-service/ui/atoms'; import { decodeCertificateId } from '../../../utils/certificate'; import { - useTeamById, - useTeamSubmission, - useAuthStore, - useUserById, + useCertificatePublicData, } from '@imphnen-frontend-service/service'; import QRCode from 'qrcode'; import html2canvas from 'html2canvas'; @@ -20,7 +17,6 @@ interface DecodedCert { const CertificatePage: FC = (): ReactElement => { const { certId } = useParams<{ certId: string }>(); const navigate = useNavigate(); - const { session } = useAuthStore(); const [decodedInfo, setDecodedInfo] = useState(null); const [error, setError] = useState(null); const teamNameRef = useRef(null); @@ -43,6 +39,12 @@ const CertificatePage: FC = (): ReactElement => { } }, [certId]); + // Fetch certificate data using the new endpoint + const { data: certificateData, isLoading: isLoadingCertificate } = useCertificatePublicData( + decodedInfo?.userId || '', + !!decodedInfo?.userId + ); + // Generate QR Code useEffect(() => { if (certId) { @@ -62,28 +64,15 @@ const CertificatePage: FC = (): ReactElement => { } }, [certId]); - const { data: teamData, isLoading: isLoadingTeam } = useTeamById( - decodedInfo?.teamId || '', - !!decodedInfo?.teamId - ); - const { data: submissionData, isLoading: isLoadingSubmission } = - useTeamSubmission(decodedInfo?.teamId || '', !!decodedInfo?.teamId); + const certificate = certificateData?.data; + const team = certificate?.team; + const submission = certificate?.submission; + const certificateUser = certificate?.user; - // Fetch the certificate owner's user data - const { data: certificateUserData, isLoading: isLoadingCertUser } = useUserById( - decodedInfo?.userId || '', - !!decodedInfo?.userId - ); + const isLoading = (!decodedInfo && !error) || isLoadingCertificate; - const team = teamData?.data; - const submission = submissionData?.data; - const certificateUser = certificateUserData?.data; - - const isLoading = - (!decodedInfo && !error) || isLoadingTeam || isLoadingSubmission || isLoadingCertUser; - - // Certificate name: Use the user from the certificate ID, fallback to team leader - const certificateName = certificateUser?.fullname || team?.leader?.fullname; + // Certificate name from the user data + const certificateName = certificateUser?.fullname; // Dynamic font sizing: shrink by 2px if height exceeds 80px useEffect(() => { @@ -216,7 +205,7 @@ const CertificatePage: FC = (): ReactElement => { ); } - if (!submission || submission.id !== decodedInfo?.submissionId) { + if (!certificateUser) { return (
📄
@@ -224,7 +213,7 @@ const CertificatePage: FC = (): ReactElement => { Certificate Not Found

- The submission associated with this certificate could not be found. + The user associated with this certificate could not be found.

@@ -292,14 +281,16 @@ const CertificatePage: FC = (): ReactElement => { {team?.name}

- + {team && ( + + )} @@ -445,16 +436,14 @@ const CertificatePage: FC = (): ReactElement => { margin: 0, }} > - {submission.submitted_at - ? new Date(submission.submitted_at).toLocaleDateString( - 'id-ID', - { - day: 'numeric', - month: 'long', - year: 'numeric', - } - ) - : 'N/A'} + {new Date().toLocaleDateString( + 'id-ID', + { + day: 'numeric', + month: 'long', + year: 'numeric', + } + )}

@@ -500,15 +489,17 @@ const CertificatePage: FC = (): ReactElement => { > {isGenerating ? '⏳ Generating...' : '🖨️ Print'} - + {team && ( + + )}