some bugfixes
All checks were successful
Build & Push Docker Image / docker (push) Successful in 1m50s
All checks were successful
Build & Push Docker Image / docker (push) Successful in 1m50s
This commit is contained in:
parent
da407e95e8
commit
60cc9db469
@ -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;
|
||||
}
|
||||
|
||||
@ -28,8 +28,8 @@ const CertificateGenerator = () => {
|
||||
|
||||
// Simulate certificate generation
|
||||
setTimeout(() => {
|
||||
setIsGenerating(false);
|
||||
toast.success('Your course completion certificate has been created successfully.');
|
||||
setIsGenerating(false);
|
||||
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,9 +190,9 @@ 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>
|
||||
</div>
|
||||
<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">
|
||||
{/* Form Section */}
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
<Button className="w-full" variant="secondary" size="lg" disabled>
|
||||
Kurs abschließen
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user