lang bugfix
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
fd6ca8221f
commit
6ba9651f34
@ -4,48 +4,48 @@ import { format } from 'date-fns';
|
||||
import { AlertCircle, Clock } from 'lucide-react';
|
||||
import AssignmentDialog from './assignment-dialog';
|
||||
|
||||
// Function to format date
|
||||
// Funktion zum Formatieren des Datums
|
||||
const formatDate = (dateString: string | undefined) => {
|
||||
if (!dateString) return 'N/A';
|
||||
if (!dateString) return 'k.A.';
|
||||
const date = new Date(dateString);
|
||||
return format(date, 'MMMM dd, yyyy, hh:mm a');
|
||||
};
|
||||
|
||||
// Function to check if deadline has passed
|
||||
// Funktion zum Prüfen, ob die Frist abgelaufen ist
|
||||
const isDeadlinePassed = (deadline: string) => {
|
||||
if (!deadline) return false;
|
||||
return new Date() > new Date(deadline);
|
||||
};
|
||||
|
||||
// Function to get submission status
|
||||
// Funktion, um den Abgabestatus zu ermitteln
|
||||
const getSubmissionStatus = (assignment: CourseAssignment) => {
|
||||
if (!assignment.submissions || assignment.submissions.length === 0) {
|
||||
return { status: 'not_submitted', label: 'Not Submitted', variant: 'secondary' as const };
|
||||
return { status: 'not_submitted', label: 'Nicht eingereicht', variant: 'secondary' as const };
|
||||
}
|
||||
|
||||
const latestSubmission = assignment.submissions[0];
|
||||
|
||||
if (latestSubmission.status === 'graded') {
|
||||
return { status: 'graded', label: 'Graded', variant: 'default' as const };
|
||||
return { status: 'graded', label: 'Bewertet', variant: 'default' as const };
|
||||
} else if (latestSubmission.is_late) {
|
||||
return { status: 'late', label: 'Late Submission', variant: 'destructive' as const };
|
||||
return { status: 'late', label: 'Verspätete Abgabe', variant: 'destructive' as const };
|
||||
} else {
|
||||
return { status: 'submitted', label: 'Submitted', variant: 'default' as const };
|
||||
return { status: 'submitted', label: 'Eingereicht', variant: 'default' as const };
|
||||
}
|
||||
};
|
||||
|
||||
export const AssignmentColumns: ColumnDef<CourseAssignment>[] = [
|
||||
{
|
||||
accessorKey: 'title',
|
||||
header: 'Title',
|
||||
header: 'Titel',
|
||||
cell: ({ row }) => {
|
||||
const assignment = row.original;
|
||||
return (
|
||||
<div className="space-y-1 py-1">
|
||||
<p className="font-medium">{assignment.title}</p>
|
||||
<div className="text-muted-foreground flex items-center gap-4 text-sm">
|
||||
<span>Total Marks: {assignment.total_mark}</span>
|
||||
<span>Pass Marks: {assignment.pass_mark}</span>
|
||||
<span>Gesamtpunktzahl: {assignment.total_mark}</span>
|
||||
<span>Bestehenspunktzahl: {assignment.pass_mark}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -53,7 +53,7 @@ export const AssignmentColumns: ColumnDef<CourseAssignment>[] = [
|
||||
},
|
||||
{
|
||||
accessorKey: 'deadline',
|
||||
header: 'Deadline',
|
||||
header: 'Frist',
|
||||
cell: ({ row }) => {
|
||||
const assignment = row.original;
|
||||
const deadlinePassed = isDeadlinePassed(assignment.deadline);
|
||||
@ -68,7 +68,7 @@ export const AssignmentColumns: ColumnDef<CourseAssignment>[] = [
|
||||
},
|
||||
{
|
||||
accessorKey: 'marks_obtained',
|
||||
header: () => <div className="text-center">Obtained Marks</div>,
|
||||
header: () => <div className="text-center">Erhaltene Punkte</div>,
|
||||
cell: ({ row }) => {
|
||||
const assignment = row.original;
|
||||
const hasSubmission = assignment.submissions && assignment.submissions.length > 0;
|
||||
@ -87,11 +87,11 @@ export const AssignmentColumns: ColumnDef<CourseAssignment>[] = [
|
||||
<p className="font-semibold">
|
||||
{latestSubmission?.marks_obtained} / {totalMarks}
|
||||
</p>
|
||||
{isLate && <p className="text-muted-foreground text-xs">(Late: Max {latestSubmission?.assignment?.late_total_mark})</p>}
|
||||
{isLate && <p className="text-muted-foreground text-xs">(Verspätet: Max {latestSubmission?.assignment?.late_total_mark})</p>}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<p className="text-muted-foreground text-sm">Not Graded</p>
|
||||
<p className="text-muted-foreground text-sm">Nicht bewertet</p>
|
||||
<p className="text-muted-foreground text-xs">Max: {totalMarks}</p>
|
||||
</div>
|
||||
)}
|
||||
@ -115,7 +115,7 @@ export const AssignmentColumns: ColumnDef<CourseAssignment>[] = [
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
header: () => <div className="text-right">Action</div>,
|
||||
header: () => <div className="text-right">Aktion</div>,
|
||||
cell: ({ row }) => {
|
||||
const assignment = row.original;
|
||||
|
||||
|
||||
@ -21,12 +21,12 @@ const QuizIcon = ({ quiz, latestSubmission }: { quiz: SectionQuiz; latestSubmiss
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Quiz Icon */}
|
||||
{/* Quiz-Symbol */}
|
||||
<div className="bg-primary/10 flex h-12 w-12 items-center justify-center rounded-lg">
|
||||
<ClipboardList className="text-primary h-6 w-6" />
|
||||
</div>
|
||||
|
||||
{/* Quiz Info */}
|
||||
{/* Quiz-Info */}
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-primary text-base font-medium">{quiz.title}</p>
|
||||
@ -37,7 +37,7 @@ const QuizIcon = ({ quiz, latestSubmission }: { quiz: SectionQuiz; latestSubmiss
|
||||
)}
|
||||
{!hasAttempted && (
|
||||
<Badge variant="destructive" className="text-xs">
|
||||
Not Submitted
|
||||
Nicht eingereicht
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
@ -90,15 +90,15 @@ const QuizStatus = ({ quiz, completed }: Props) => {
|
||||
<QuizResultDialog quiz={quiz} submission={latestSubmission} />
|
||||
) : (
|
||||
<Button size="sm" asChild>
|
||||
<Link
|
||||
href={route('course.player', {
|
||||
type: 'quiz',
|
||||
watch_history: watchHistory.id,
|
||||
lesson_id: quiz.id,
|
||||
})}
|
||||
>
|
||||
{'Take Quiz'}
|
||||
</Link>
|
||||
<Link
|
||||
href={route('course.player', {
|
||||
type: 'quiz',
|
||||
watch_history: watchHistory.id,
|
||||
lesson_id: quiz.id,
|
||||
})}
|
||||
>
|
||||
Quiz starten
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@ -112,7 +112,7 @@ const QuizStatus = ({ quiz, completed }: Props) => {
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Marks Display */}
|
||||
{/* Punkteanzeige */}
|
||||
{hasAttempted && (
|
||||
<div className="text-right">
|
||||
<p className="text-sm font-medium text-gray-500">
|
||||
|
||||
@ -25,7 +25,7 @@ const CourseQuizzes = () => {
|
||||
section.section_quizzes.map((quiz) => <QuizStatus key={quiz.id} quiz={quiz} completed={completed} />)
|
||||
) : (
|
||||
<div className="px-4 py-3 text-center">
|
||||
<p>There is no quiz added</p>
|
||||
<p>Kein Quiz vorhanden</p>
|
||||
</div>
|
||||
)}
|
||||
</AccordionContent>
|
||||
@ -35,7 +35,7 @@ const CourseQuizzes = () => {
|
||||
</Accordion>
|
||||
) : (
|
||||
<div className="p-6 text-center">
|
||||
<p>There is no quiz added</p>
|
||||
<p>Kein Quiz vorhanden</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
@ -10,21 +10,21 @@ const CourseResources = () => {
|
||||
const { props } = usePage<StudentCourseProps>();
|
||||
const { resources } = props;
|
||||
|
||||
// Function to format date in Bengali style if needed
|
||||
// Funktion zum Formatieren von Datum/Uhrzeit (bei Bedarf auf Deutsch)
|
||||
const formatDate = (dateString: string) => {
|
||||
const date = new Date(dateString);
|
||||
return format(date, 'MMMM dd, yyyy, hh:mm a');
|
||||
};
|
||||
|
||||
// Helper to handle file download
|
||||
// Helferfunktion zum Herunterladen von Dateien
|
||||
const handleDownload = async (resource: LessonResource, e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
// For non-link resources, use the download endpoint
|
||||
// Für nicht-verlinkte Ressourcen den Download-Endpunkt verwenden
|
||||
const url = route('resources.download', resource.id);
|
||||
window.open(url, '_blank');
|
||||
} catch (error) {
|
||||
// Fallback to direct download if the endpoint fails
|
||||
// Fallback: Direktes Öffnen/Herunterladen, falls der Endpunkt fehlschlägt
|
||||
window.open(resource.resource, '_blank');
|
||||
}
|
||||
};
|
||||
@ -34,12 +34,12 @@ const CourseResources = () => {
|
||||
{resources && resources.length > 0 ? (
|
||||
resources.map((section, sectionIndex) => (
|
||||
<Card key={section.id}>
|
||||
{/* Module Header */}
|
||||
{/* Modul-Überschrift */}
|
||||
<div className="bg-muted rounded-t-lg px-4 py-3">
|
||||
<h3 className="text-lg font-semibold">Module: {section.title}</h3>
|
||||
<h3 className="text-lg font-semibold">Modul: {section.title}</h3>
|
||||
</div>
|
||||
|
||||
{/* Lessons Table */}
|
||||
{/* Lektionen-Tabelle */}
|
||||
<div className="space-y-4 p-4">
|
||||
{section.section_lessons && section.section_lessons.length > 0 ? (
|
||||
section.section_lessons.map((lesson) =>
|
||||
@ -48,7 +48,7 @@ const CourseResources = () => {
|
||||
{/* Lesson Title */}
|
||||
<div className="p-4">
|
||||
<p className="text-base font-medium">
|
||||
<span className="font-semibold">Lesson:</span> {lesson.title}
|
||||
<span className="font-semibold">Lektion:</span> {lesson.title}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -57,9 +57,9 @@ const CourseResources = () => {
|
||||
<Table>
|
||||
<TableHeader className="bg-muted/50">
|
||||
<TableRow>
|
||||
<TableHead className="px-4 font-semibold">Title</TableHead>
|
||||
<TableHead className="px-4 font-semibold">Date & Time</TableHead>
|
||||
<TableHead className="px-4 text-right font-semibold">Action</TableHead>
|
||||
<TableHead className="px-4 font-semibold">Titel</TableHead>
|
||||
<TableHead className="px-4 font-semibold">Datum & Uhrzeit</TableHead>
|
||||
<TableHead className="px-4 text-right font-semibold">Aktion</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@ -73,13 +73,13 @@ const CourseResources = () => {
|
||||
<Button asChild size="sm" variant="secondary">
|
||||
<a target="_blank" href={resource.resource}>
|
||||
<ExternalLink className="h-3 w-3" />
|
||||
Check
|
||||
Ansehen
|
||||
</a>
|
||||
</Button>
|
||||
) : (
|
||||
<Button size="sm" variant="secondary" onClick={(e) => handleDownload(resource, e)}>
|
||||
<Download className="h-3 w-3" />
|
||||
Download
|
||||
Herunterladen
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@ -93,14 +93,14 @@ const CourseResources = () => {
|
||||
) : null,
|
||||
)
|
||||
) : (
|
||||
<div className="text-muted-foreground py-8 text-center">No lessons found in this module.</div>
|
||||
<div className="text-muted-foreground py-8 text-center">Keine Lektionen in diesem Modul gefunden.</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
))
|
||||
) : (
|
||||
<div className="py-12 text-center">
|
||||
<p className="text-muted-foreground text-lg">No resources available for this course yet.</p>
|
||||
<p className="text-muted-foreground text-lg">Für diesen Kurs sind noch keine Ressourcen verfügbar.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -25,7 +25,7 @@ const Quizzes = () => {
|
||||
section.section_quizzes.map((quiz) => <QuizStatus key={quiz.id} quiz={quiz} completed={completed} />)
|
||||
) : (
|
||||
<div className="px-4 py-3 text-center">
|
||||
<p>There is no quiz added</p>
|
||||
<p>Kein Quiz vorhanden</p>
|
||||
</div>
|
||||
)}
|
||||
</AccordionContent>
|
||||
@ -35,7 +35,7 @@ const Quizzes = () => {
|
||||
</Accordion>
|
||||
) : (
|
||||
<div className="p-6 text-center">
|
||||
<p>There is no quiz added</p>
|
||||
<p>Kein Quiz vorhanden</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
@ -10,21 +10,21 @@ const Resources = () => {
|
||||
const { props } = usePage<StudentCourseProps>();
|
||||
const { resources } = props;
|
||||
|
||||
// Function to format date in Bengali style if needed
|
||||
// Funktion zum Formatieren von Datum/Uhrzeit (bei Bedarf auf Deutsch)
|
||||
const formatDate = (dateString: string) => {
|
||||
const date = new Date(dateString);
|
||||
return format(date, 'MMMM dd, yyyy, hh:mm a');
|
||||
};
|
||||
|
||||
// Helper to handle file download
|
||||
// Helferfunktion zum Herunterladen von Dateien
|
||||
const handleDownload = async (resource: LessonResource, e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
// For non-link resources, use the download endpoint
|
||||
// Für nicht-verlinkte Ressourcen den Download-Endpunkt verwenden
|
||||
const url = route('resources.download', resource.id);
|
||||
window.open(url, '_blank');
|
||||
} catch (error) {
|
||||
// Fallback to direct download if the endpoint fails
|
||||
// Fallback: Direktes Öffnen/Herunterladen, falls der Endpunkt fehlschlägt
|
||||
window.open(resource.resource, '_blank');
|
||||
}
|
||||
};
|
||||
@ -34,12 +34,12 @@ const Resources = () => {
|
||||
{resources && resources.length > 0 ? (
|
||||
resources.map((section, sectionIndex) => (
|
||||
<Card key={section.id}>
|
||||
{/* Module Header */}
|
||||
{/* Modul-Überschrift */}
|
||||
<div className="bg-muted rounded-t-lg px-4 py-3">
|
||||
<h3 className="text-lg font-semibold">Module: {section.title}</h3>
|
||||
<h3 className="text-lg font-semibold">Modul: {section.title}</h3>
|
||||
</div>
|
||||
|
||||
{/* Lessons Table */}
|
||||
{/* Lektionen-Tabelle */}
|
||||
<div className="space-y-4 p-4">
|
||||
{section.section_lessons && section.section_lessons.length > 0 ? (
|
||||
section.section_lessons.map((lesson) =>
|
||||
@ -48,7 +48,7 @@ const Resources = () => {
|
||||
{/* Lesson Title */}
|
||||
<div className="p-4">
|
||||
<p className="text-base font-medium">
|
||||
<span className="font-semibold">Lesson:</span> {lesson.title}
|
||||
<span className="font-semibold">Lektion:</span> {lesson.title}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -57,9 +57,9 @@ const Resources = () => {
|
||||
<Table>
|
||||
<TableHeader className="bg-muted/50">
|
||||
<TableRow>
|
||||
<TableHead className="px-4 font-semibold">Title</TableHead>
|
||||
<TableHead className="px-4 font-semibold">Date & Time</TableHead>
|
||||
<TableHead className="px-4 text-right font-semibold">Action</TableHead>
|
||||
<TableHead className="px-4 font-semibold">Titel</TableHead>
|
||||
<TableHead className="px-4 font-semibold">Datum & Uhrzeit</TableHead>
|
||||
<TableHead className="px-4 text-right font-semibold">Aktion</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@ -73,13 +73,13 @@ const Resources = () => {
|
||||
<Button asChild size="sm" variant="secondary">
|
||||
<a target="_blank" href={resource.resource}>
|
||||
<ExternalLink className="h-3 w-3" />
|
||||
Check
|
||||
Ansehen
|
||||
</a>
|
||||
</Button>
|
||||
) : (
|
||||
<Button size="sm" variant="secondary" onClick={(e) => handleDownload(resource, e)}>
|
||||
<Download className="h-3 w-3" />
|
||||
Download
|
||||
Herunterladen
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@ -93,14 +93,14 @@ const Resources = () => {
|
||||
) : null,
|
||||
)
|
||||
) : (
|
||||
<div className="text-muted-foreground py-8 text-center">No lessons found in this module.</div>
|
||||
<div className="text-muted-foreground py-8 text-center">Keine Lektionen in diesem Modul gefunden.</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
))
|
||||
) : (
|
||||
<div className="py-12 text-center">
|
||||
<p className="text-muted-foreground text-lg">No resources available for this course yet.</p>
|
||||
<p className="text-muted-foreground text-lg">Für diesen Kurs sind noch keine Ressourcen verfügbar.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user