Enhance VocabService and VocabCourseView for improved multiple choice handling and table layout

- Updated VocabService to support multiple correct answers in multiple choice exercises, allowing for better answer validation and user feedback.
- Enhanced the extraction of correct answers and alternatives to accommodate both single and multiple correct indices.
- Improved CSS styles in VocabCourseView for better table layout, including adjustments for overflow handling and vertical alignment, enhancing overall user experience.
This commit is contained in:
Torsten Schulz (local)
2026-01-20 14:46:07 +01:00
parent 4d97f24531
commit 175a61c81c
2 changed files with 61 additions and 18 deletions

View File

@@ -1405,15 +1405,30 @@ export default class VocabService {
let correctAnswer = null; let correctAnswer = null;
let alternatives = []; let alternatives = [];
// Für Multiple Choice: Extrahiere die richtige Antwort aus dem Index // Für Multiple Choice: Extrahiere die richtige(n) Antwort(en) aus dem Index/den Indizes
if (exercise.exerciseTypeId === 2 && answerData.correctAnswer !== undefined) { if (exercise.exerciseTypeId === 2 && answerData.correctAnswer !== undefined) {
const options = questionData?.options || []; const options = questionData?.options || [];
const correctIndex = answerData.correctAnswer;
if (options[correctIndex] !== undefined) { // Unterstütze sowohl einzelne korrekte Antwort als auch Array von korrekten Antworten
correctAnswer = options[correctIndex]; let correctIndices = [];
if (Array.isArray(answerData.correctAnswer)) {
correctIndices = answerData.correctAnswer.map(idx => Number(idx));
} else {
correctIndices = [Number(answerData.correctAnswer)];
} }
// Alternativen sind alle anderen Optionen
alternatives = options.filter((opt, idx) => idx !== correctIndex); // Extrahiere alle korrekten Antworten
const correctAnswersList = correctIndices
.map(idx => options[idx])
.filter(opt => opt !== undefined);
if (correctAnswersList.length > 0) {
// Wenn mehrere richtige Antworten: Zeige alle an, getrennt durch " / "
correctAnswer = correctAnswersList.join(' / ');
}
// Alternativen sind alle anderen Optionen (nicht korrekte)
alternatives = options.filter((opt, idx) => !correctIndices.includes(idx));
} }
// Für Gap Fill: Extrahiere aus answers Array // Für Gap Fill: Extrahiere aus answers Array
else if (exercise.exerciseTypeId === 1 && answerData.answers) { else if (exercise.exerciseTypeId === 1 && answerData.answers) {
@@ -1460,14 +1475,32 @@ export default class VocabService {
const parsedAnswerData = typeof answerData === 'string' ? JSON.parse(answerData) : answerData; const parsedAnswerData = typeof answerData === 'string' ? JSON.parse(answerData) : answerData;
const parsedQuestionData = typeof questionData === 'string' ? JSON.parse(questionData) : questionData; const parsedQuestionData = typeof questionData === 'string' ? JSON.parse(questionData) : questionData;
// Für Multiple Choice: Prüfe ob userAnswer (Index) mit correctAnswer (Index) übereinstimmt // Für Multiple Choice: Prüfe ob userAnswer (Index) mit correctAnswer (Index oder Array von Indizes) übereinstimmt
if (exerciseTypeId === 2) { // multiple_choice if (exerciseTypeId === 2) { // multiple_choice
const correctIndex = parsedAnswerData.correctAnswer !== undefined // Unterstütze sowohl einzelne korrekte Antwort als auch Array von korrekten Antworten
? parsedAnswerData.correctAnswer let correctIndices = [];
: (parsedAnswerData.correct !== undefined ? parsedAnswerData.correct : null);
if (correctIndex === null) return false; if (parsedAnswerData.correctAnswer !== undefined) {
// Kann ein einzelner Index oder ein Array von Indizes sein
if (Array.isArray(parsedAnswerData.correctAnswer)) {
correctIndices = parsedAnswerData.correctAnswer.map(idx => Number(idx));
} else {
correctIndices = [Number(parsedAnswerData.correctAnswer)];
}
} else if (parsedAnswerData.correct !== undefined) {
// Fallback: Prüfe auch 'correct' Feld
if (Array.isArray(parsedAnswerData.correct)) {
correctIndices = parsedAnswerData.correct.map(idx => Number(idx));
} else {
correctIndices = [Number(parsedAnswerData.correct)];
}
}
if (correctIndices.length === 0) return false;
// userAnswer ist der Index (0, 1, 2, ...) // userAnswer ist der Index (0, 1, 2, ...)
return Number(userAnswer) === Number(correctIndex); const userIndex = Number(userAnswer);
return correctIndices.includes(userIndex);
} }
// Für Lückentext: Normalisiere und vergleiche // Für Lückentext: Normalisiere und vergleiche

View File

@@ -257,6 +257,11 @@ export default {
table-layout: fixed; table-layout: fixed;
} }
.lessons-table th,
.lessons-table td {
box-sizing: border-box;
}
.lessons-table thead { .lessons-table thead {
background: #f8f9fa; background: #f8f9fa;
} }
@@ -276,12 +281,14 @@ export default {
width: 80px; width: 80px;
min-width: 80px; min-width: 80px;
max-width: 80px; max-width: 80px;
overflow: visible;
} }
.lessons-table th.col-title, .lessons-table th.col-title,
.lessons-table td.lesson-title { .lessons-table td.lesson-title {
width: auto; width: auto;
min-width: 200px; min-width: 200px;
overflow: visible;
} }
.lessons-table th.col-status, .lessons-table th.col-status,
@@ -289,6 +296,8 @@ export default {
width: 200px; width: 200px;
min-width: 200px; min-width: 200px;
max-width: 200px; max-width: 200px;
overflow: visible;
word-wrap: break-word;
} }
.lessons-table th.col-actions, .lessons-table th.col-actions,
@@ -296,6 +305,7 @@ export default {
width: 250px; width: 250px;
min-width: 250px; min-width: 250px;
max-width: 250px; max-width: 250px;
overflow: visible;
} }
.lessons-table tbody tr { .lessons-table tbody tr {
@@ -308,13 +318,15 @@ export default {
.lessons-table td { .lessons-table td {
padding: 15px; padding: 15px;
vertical-align: middle; vertical-align: top;
} }
.lesson-number { .lesson-number {
font-weight: 600; font-weight: 600;
color: #666; color: #666;
font-size: 0.95em; font-size: 0.95em;
vertical-align: top;
padding-top: 15px;
} }
.lesson-title { .lesson-title {
@@ -340,11 +352,9 @@ export default {
flex-direction: column; flex-direction: column;
gap: 5px; gap: 5px;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: flex-start;
min-height: 60px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: visible;
text-overflow: ellipsis;
} }
.badge.completed { .badge.completed {
@@ -372,7 +382,7 @@ export default {
display: flex; display: flex;
gap: 8px; gap: 8px;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: flex-start;
justify-content: flex-start; justify-content: flex-start;
} }