feat: fixing certificate and block

This commit is contained in:
2026-04-14 13:07:45 -04:00
parent e0e6655b91
commit 169a0a18a2
21 changed files with 837 additions and 1226 deletions
+69 -3
View File
@@ -9,6 +9,8 @@ import { useAuth } from "@/context/AuthContext";
import DiscussionBoard from "@/components/DiscussionBoard";
import { AnnouncementsList } from "@/components/AnnouncementsList";
import AboutCourse from "@/components/AboutCourse";
import CertificateModal from "@/components/CertificateModal";
import { CertificateResponse } from "@/lib/api";
export default function CourseOutlinePage({ params }: { params: { id: string } }) {
const { user } = useAuth();
@@ -22,6 +24,11 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
const [instructors, setInstructors] = useState<any[]>([]);
const [meetings, setMeetings] = useState<Meeting[]>([]);
const [activeTab, setActiveTab] = useState<'outline' | 'about'>('outline');
const [progress, setProgress] = useState(0);
const [certificate, setCertificate] = useState<CertificateResponse | null>(null);
const [showCertificateModal, setShowCertificateModal] = useState(false);
const [loadingCertificate, setLoadingCertificate] = useState(false);
const [orgSettings, setOrgSettings] = useState<any>(null);
useEffect(() => {
const fetchData = async () => {
@@ -37,11 +44,15 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
setUserGrades(grades);
const enrollmentData = await lmsApi.getEnrollments(user.id);
const enrolled = enrollmentData.some(e => e.course_id === params.id);
const enrollment = enrollmentData.find(e => e.course_id === params.id);
// Allow preview token to override enrollment status
const isPreview = typeof window !== 'undefined' && !!sessionStorage.getItem('preview_token');
setIsEnrolled(enrolled || isPreview);
setIsEnrolled(!!enrollment || isPreview);
if (enrollment) {
setProgress(enrollment.progress * 100);
}
} else {
// Even if not logged in, if there's a preview token, consider "enrolled" for UI
const isPreview = typeof window !== 'undefined' && !!sessionStorage.getItem('preview_token');
@@ -65,6 +76,11 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
lmsApi.getMeetings(params.id)
.then(setMeetings)
.catch(console.error);
// Load organization settings (branding includes the certificates_enabled flag)
lmsApi.getBranding()
.then(res => setOrgSettings(res.organization))
.catch(console.error);
}, [params.id, user]);
const handleEnrollOrBuy = async () => {
@@ -120,6 +136,38 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
});
};
const handleViewCertificate = async () => {
if (certificate) {
setShowCertificateModal(true);
return;
}
setLoadingCertificate(true);
try {
const data = await lmsApi.getCertificate(params.id);
setCertificate(data);
setShowCertificateModal(true);
} catch (error: any) {
console.error("No se pudo obtener el certificado", error);
if (error.status === 404 || error.status === 403) {
// Try to issue it if completed but not issued
if (progress >= 100) {
try {
const issued = await lmsApi.issueCertificate(params.id);
setCertificate(issued);
setShowCertificateModal(true);
} catch (issueError) {
alert("No se pudo generar el certificado. Asegúrate de haber aprobado todas las lecciones.");
}
} else {
alert("Aún no has completado este curso.");
}
}
} finally {
setLoadingCertificate(false);
}
};
const getStatusIcon = (lessonId: string, isGraded: boolean, allowRetry: boolean) => {
if (isLessonLocked(lessonId)) {
return <Lock size={18} className="text-gray-600" />;
@@ -274,6 +322,17 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
📊 Progreso
</button>
</Link>
{isEnrolled && orgSettings?.certificates_enabled !== false && progress >= 100 && (
<button
onClick={handleViewCertificate}
disabled={loadingCertificate}
className="btn-premium px-8 py-3 !bg-emerald-600 !text-white shadow-lg shadow-emerald-500/20 active:scale-95 flex items-center gap-2"
>
<Award size={16} />
{loadingCertificate ? "Preparando..." : "Mi Certificado"}
</button>
)}
</div>
</div>
@@ -485,6 +544,13 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
</div>
)}
</div>
{showCertificateModal && certificate && (
<CertificateModal
certificate={certificate}
onClose={() => setShowCertificateModal(false)}
/>
)}
</div>
);
}
+1 -3
View File
@@ -40,9 +40,7 @@ export default function MyLearningPage() {
try {
const { course, modules } = await lmsApi.getCourseOutline(enrollment.course_id);
// TODO: Implement actual progress tracking
// For now, show 0% progress for all courses
const progress = 0;
const progress = enrollment.progress || 0;
enrichedEnrollments.push({
course: { ...course, modules },