some bugfixes
All checks were successful
Build & Push Docker Image / docker (push) Successful in 1m50s

This commit is contained in:
Ahmed Darrazi 2025-12-18 22:57:40 +01:00
parent da407e95e8
commit 60cc9db469
3 changed files with 40 additions and 40 deletions

View File

@ -20,7 +20,7 @@ const CertificateGenerator = () => {
const handleGenerateCertificate = async () => {
if (!studentName || !courseName || !completionDate) {
toast.error('Please fill in all required fields.');
toast.error('Bitte fülle alle Pflichtfelder aus.');
return;
}
@ -29,7 +29,7 @@ const CertificateGenerator = () => {
// Simulate certificate generation
setTimeout(() => {
setIsGenerating(false);
toast.success('Your course completion certificate has been created successfully.');
toast.success('Dein Kursabschlusszertifikat wurde erfolgreich erstellt.');
}, 2000);
};
@ -73,7 +73,7 @@ const CertificateGenerator = () => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
toast.success('Your PNG certificate has been saved to your downloads folder.');
toast.success('Dein PNG-Zertifikat wurde in deinem Download-Ordner gespeichert.');
}, 'image/png');
};
@ -107,7 +107,7 @@ const CertificateGenerator = () => {
// Save the PDF
pdf.save(`${studentName}_${courseName}_Certificate.pdf`);
toast.success('Your PDF certificate has been saved to your downloads folder.');
toast.success('Dein PDF-Zertifikat wurde in deinem Download-Ordner gespeichert.');
};
const drawCertificate = (ctx: CanvasRenderingContext2D, dimensions: { width: number; height: number }) => {
@ -135,7 +135,7 @@ const CertificateGenerator = () => {
// Title
ctx.font = 'bold 42px serif';
ctx.fillText('Certificate of Completion', dimensions.width / 2, 120);
ctx.fillText('Abschlusszertifikat', dimensions.width / 2, 120);
// Decorative line under title
ctx.strokeStyle = '#f59e0b';
@ -148,7 +148,7 @@ const CertificateGenerator = () => {
// "This is to certify that"
ctx.font = '22px serif';
ctx.fillStyle = '#4b5563';
ctx.fillText('This is to certify that', dimensions.width / 2, 190);
ctx.fillText('Hiermit wird bescheinigt, dass', dimensions.width / 2, 190);
// Student name with underline
ctx.font = 'bold 36px serif';
@ -167,7 +167,7 @@ const CertificateGenerator = () => {
// "has successfully completed the course"
ctx.font = '22px serif';
ctx.fillStyle = '#4b5563';
ctx.fillText('has successfully completed the course', dimensions.width / 2, 320);
ctx.fillText('den Kurs erfolgreich abgeschlossen hat', dimensions.width / 2, 320);
// Course name
ctx.font = 'bold 28px serif';
@ -177,7 +177,7 @@ const CertificateGenerator = () => {
// Completion date
ctx.font = '18px serif';
ctx.fillStyle = '#6b7280';
ctx.fillText(`Completed on: ${completionDate}`, dimensions.width / 2, 430);
ctx.fillText(`Abgeschlossen am: ${completionDate}`, dimensions.width / 2, 430);
// Footer
ctx.font = '16px serif';
@ -190,8 +190,8 @@ const CertificateGenerator = () => {
return (
<div className="space-y-8">
<div className="text-center">
<h1 className="mb-4 text-4xl font-bold text-gray-800">Course Certificate Generator</h1>
<p className="text-muted-foreground text-lg">Generate your official course completion certificate</p>
<h1 className="mb-4 text-4xl font-bold text-gray-800">Zertifikatsgenerator</h1>
<p className="text-muted-foreground text-lg">Erstelle dein offizielles Kursabschlusszertifikat</p>
</div>
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
@ -200,23 +200,23 @@ const CertificateGenerator = () => {
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Award className="h-5 w-5 text-amber-600" />
Certificate Details
Zertifikatsdetails
</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<div className="space-y-2">
<Label htmlFor="studentName">Student Name *</Label>
<Label htmlFor="studentName">Name des Teilnehmers *</Label>
<Input
id="studentName"
value={studentName}
onChange={(e) => setStudentName(e.target.value)}
placeholder="Enter your full name"
placeholder="Gib deinen vollständigen Namen ein"
/>
</div>
<div className="space-y-2">
<Label htmlFor="courseName">Course Name *</Label>
<Input id="courseName" value={courseName} onChange={(e) => setCourseName(e.target.value)} placeholder="Enter the course name" />
<Label htmlFor="courseName">Kursname *</Label>
<Input id="courseName" value={courseName} onChange={(e) => setCourseName(e.target.value)} placeholder="Gib den Kursnamen ein" />
</div>
<div className="space-y-2">
@ -232,33 +232,33 @@ const CertificateGenerator = () => {
<div className="space-y-4">
<div className="space-y-2">
<Label>Certificate Size</Label>
<Label>Zertifikatsgröße</Label>
<Select value={certificateSize} onValueChange={setCertificateSize}>
<SelectTrigger>
<SelectValue placeholder="Select certificate size" />
<SelectValue placeholder="Wähle Zertifikatsgröße" />
</SelectTrigger>
<SelectContent>
<SelectItem value="standard">Standard (800x600)</SelectItem>
<SelectItem value="a4">A4 Landscape (842x595)</SelectItem>
<SelectItem value="standard">Standard (800×600)</SelectItem>
<SelectItem value="a4">A4 Querformat (842×595)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-3">
<Label>Download Format</Label>
<Label>Download-Format</Label>
<RadioGroup value={downloadFormat} onValueChange={setDownloadFormat} className="flex space-x-6">
<div className="flex items-center space-x-2">
<RadioGroupItem className="cursor-pointer" value="png" id="png" />
<Label htmlFor="png" className="flex cursor-pointer items-center gap-2">
<FileImage className="h-4 w-4" />
PNG Image
PNG-Bild
</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem className="cursor-pointer" value="pdf" id="pdf" />
<Label htmlFor="pdf" className="flex cursor-pointer items-center gap-2">
<FileText className="h-4 w-4" />
PDF Document
PDF-Dokument
</Label>
</div>
</RadioGroup>
@ -269,12 +269,12 @@ const CertificateGenerator = () => {
{isGenerating ? (
<>
<div className="mr-2 h-4 w-4 animate-spin rounded-full border-b-2 border-white" />
Generating Certificate...
Zertifikat wird erstellt...
</>
) : (
<>
<Award className="mr-2 h-4 w-4" />
Generate Certificate
Zertifikat erstellen
</>
)}
</Button>
@ -284,7 +284,7 @@ const CertificateGenerator = () => {
{/* Preview Section */}
<Card>
<CardHeader>
<CardTitle>Certificate Preview</CardTitle>
<CardTitle>Zertifikatsvorschau</CardTitle>
</CardHeader>
<CardContent>
<div
@ -297,26 +297,26 @@ const CertificateGenerator = () => {
<div className="relative z-10">
<div className="mb-6">
<Award className="mx-auto mb-3 h-12 w-12 text-amber-600" />
<h2 className="mb-2 font-serif text-2xl font-bold text-gray-800">Certificate of Completion</h2>
<h2 className="mb-2 font-serif text-2xl font-bold text-gray-800">Abschlusszertifikat</h2>
<div className="mx-auto h-0.5 w-32 bg-amber-400"></div>
</div>
<div className="space-y-4 text-gray-700">
<p className="font-serif text-lg">This is to certify that</p>
<p className="font-serif text-lg">Hiermit wird bescheinigt, dass</p>
<div className="relative">
<p className="mx-8 pb-2 font-serif text-2xl font-bold text-indigo-800">{studentName || 'Student Name'}</p>
<div className="absolute bottom-0 left-1/2 h-0.5 w-48 -translate-x-1/2 transform bg-amber-400"></div>
</div>
<p className="font-serif text-lg">has successfully completed the course</p>
<p className="font-serif text-xl font-semibold text-indigo-700">{courseName || 'Course Name'}</p>
<p className="font-serif text-lg">den Kurs erfolgreich abgeschlossen hat</p>
<p className="font-serif text-xl font-semibold text-indigo-700">{courseName || 'Kursname'}</p>
<div className="mt-6 flex items-center justify-center gap-2">
<Calendar className="text-muted-foreground h-4 w-4" />
<p className="text-muted-foreground font-serif text-sm">Completed on: {completionDate || 'Date'}</p>
<p className="text-muted-foreground font-serif text-sm">Abgeschlossen am: {completionDate || 'Datum'}</p>
</div>
</div>
<div className="mt-6 border-t border-amber-400 pt-4">
<p className="font-serif text-sm text-gray-500">Authorized Certificate of Achievement</p>
<p className="font-serif text-sm text-gray-500">Autorisierte Leistungsurkunde</p>
</div>
</div>
</div>
@ -324,7 +324,7 @@ const CertificateGenerator = () => {
{studentName && courseName && completionDate && (
<Button variant="outline" className="mt-4 w-full" onClick={handleDownloadCertificate}>
<Download className="mr-2 h-4 w-4" />
Download as {downloadFormat.toUpperCase()}
Herunterladen als {downloadFormat.toUpperCase()}
</Button>
)}
</CardContent>

View File

@ -28,7 +28,7 @@ interface ContentListProps {
const ContentList = ({ completedContents, courseCompletion }: ContentListProps) => {
const { props } = usePage<CoursePlayerProps>();
const { course, zoomConfig, section, watchHistory, translate, direction } = props;
const { button, common } = translate;
const { button, common, frontend } = translate;
// Get live classes from course data
const liveClasses = course.live_classes || [];
@ -119,7 +119,7 @@ const ContentList = ({ completedContents, courseCompletion }: ContentListProps)
})}
>
<Button className="w-full" variant="secondary" size="lg" disabled={courseCompletion.percentage !== '100.00'}>
Course Certificate
{frontend.course_certificate}
</Button>
</Link>
</div>
@ -127,11 +127,11 @@ const ContentList = ({ completedContents, courseCompletion }: ContentListProps)
<div>
{!watchHistory.next_watching_id ? (
<Button className="w-full" variant="secondary" size="lg" onClick={finishCourseHandler}>
Finish Course
Kurs abschließen
</Button>
) : (
<Button className="w-full" variant="secondary" size="lg" disabled>
Finish Course
Kurs abschließen
</Button>
)}
</div>

View File

@ -117,7 +117,7 @@ const CoursePreview = () => {
<Mail className="h-5 w-5" />
{frontend.certificate_included}
</span>
<span>Yes</span>
<span>{course.certificate_included ? 'Ja' : 'Nein'}</span>
</div>
</div>
</div>