Refactor feedback handling across components: Replace alert and confirm calls with centralized feedback functions for improved user experience. Update various components to utilize showError, showSuccess, and confirmAction for consistent messaging and confirmation dialogs. Enhance UI responsiveness and maintainability by streamlining feedback logic.
This commit is contained in:
@@ -29,55 +29,44 @@
|
||||
{{ $t('socialnetwork.vocab.courses.continueCurrentLesson') }}
|
||||
</button>
|
||||
</div>
|
||||
<h3>{{ $t('socialnetwork.vocab.courses.lessons') }}</h3>
|
||||
<table class="lessons-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-number">#</th>
|
||||
<th class="col-title">{{ $t('socialnetwork.vocab.courses.title') }}</th>
|
||||
<th class="col-status">Status</th>
|
||||
<th class="col-actions">Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="lesson in course.lessons" :key="lesson.id" class="lesson-row">
|
||||
<td class="lesson-number">{{ lesson.lessonNumber }}</td>
|
||||
<td class="lesson-title">
|
||||
<div class="lesson-title-content">
|
||||
<span class="title-label">{{ lesson.title }}</span>
|
||||
<span v-if="lesson.description" class="lesson-description">{{ lesson.description }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="lesson-status">
|
||||
<div class="lesson-status-content">
|
||||
<span v-if="getLessonProgress(lesson.id)?.completed" class="badge completed">
|
||||
{{ $t('socialnetwork.vocab.courses.completed') }}
|
||||
</span>
|
||||
<span v-else-if="getLessonProgress(lesson.id)?.score" class="score">
|
||||
{{ $t('socialnetwork.vocab.courses.score') }}: {{ getLessonProgress(lesson.id).score }}%
|
||||
</span>
|
||||
<span v-else class="status-new">
|
||||
{{ $t('socialnetwork.vocab.courses.notStarted') }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="lesson-actions">
|
||||
<div class="lesson-actions-content">
|
||||
<button
|
||||
@click="openLesson(lesson.id)"
|
||||
class="btn-start"
|
||||
:disabled="!canStartLesson(lesson)"
|
||||
:title="!canStartLesson(lesson) ? $t('socialnetwork.vocab.courses.previousLessonRequired') : ''"
|
||||
>
|
||||
{{ getLessonProgress(lesson.id)?.completed ? $t('socialnetwork.vocab.courses.review') : $t('socialnetwork.vocab.courses.start') }}
|
||||
</button>
|
||||
<button v-if="isOwner" @click="editLesson(lesson.id)" class="btn-edit">{{ $t('socialnetwork.vocab.courses.edit') }}</button>
|
||||
<button v-if="isOwner" @click="deleteLesson(lesson.id)" class="btn-delete">{{ $t('general.delete') }}</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="lessons-header">
|
||||
<h3>{{ $t('socialnetwork.vocab.courses.lessons') }}</h3>
|
||||
<span class="lessons-count">{{ course.lessons.length }} Lektionen</span>
|
||||
</div>
|
||||
<div class="lesson-cards">
|
||||
<article v-for="lesson in course.lessons" :key="lesson.id" class="lesson-card">
|
||||
<div class="lesson-card__header">
|
||||
<span class="lesson-number">#{{ lesson.lessonNumber }}</span>
|
||||
<div class="lesson-status-content">
|
||||
<span v-if="getLessonProgress(lesson.id)?.completed" class="badge completed">
|
||||
{{ $t('socialnetwork.vocab.courses.completed') }}
|
||||
</span>
|
||||
<span v-else-if="getLessonProgress(lesson.id)?.score" class="score">
|
||||
{{ $t('socialnetwork.vocab.courses.score') }}: {{ getLessonProgress(lesson.id).score }}%
|
||||
</span>
|
||||
<span v-else class="status-new">
|
||||
{{ $t('socialnetwork.vocab.courses.notStarted') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lesson-title-content">
|
||||
<span class="title-label">{{ lesson.title }}</span>
|
||||
<span v-if="lesson.description" class="lesson-description">{{ lesson.description }}</span>
|
||||
</div>
|
||||
<div class="lesson-actions-content">
|
||||
<button
|
||||
@click="openLesson(lesson.id)"
|
||||
class="btn-start"
|
||||
:disabled="!canStartLesson(lesson)"
|
||||
:title="!canStartLesson(lesson) ? $t('socialnetwork.vocab.courses.previousLessonRequired') : ''"
|
||||
>
|
||||
{{ getLessonProgress(lesson.id)?.completed ? $t('socialnetwork.vocab.courses.review') : $t('socialnetwork.vocab.courses.start') }}
|
||||
</button>
|
||||
<button v-if="isOwner" @click="editLesson(lesson.id)" class="btn-edit">{{ $t('socialnetwork.vocab.courses.edit') }}</button>
|
||||
<button v-if="isOwner" @click="deleteLesson(lesson.id)" class="btn-delete">{{ $t('general.delete') }}</button>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p class="surface-card course-state">{{ $t('socialnetwork.vocab.courses.noLessons') }}</p>
|
||||
@@ -122,7 +111,7 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import { showApiError, showSuccess } from '@/utils/feedback.js';
|
||||
import { confirmAction, showApiError, showSuccess } from '@/utils/feedback.js';
|
||||
|
||||
export default {
|
||||
name: 'VocabCourseView',
|
||||
@@ -274,7 +263,11 @@ export default {
|
||||
}
|
||||
},
|
||||
async deleteLesson(lessonId) {
|
||||
if (!confirm(this.$t('socialnetwork.vocab.courses.confirmDelete'))) {
|
||||
const confirmed = await confirmAction(this, {
|
||||
title: 'Lektion löschen',
|
||||
message: this.$t('socialnetwork.vocab.courses.confirmDelete')
|
||||
});
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -370,6 +363,20 @@ export default {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.lessons-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.lessons-count {
|
||||
color: var(--color-text-muted);
|
||||
font-size: 0.84rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.course-state {
|
||||
padding: 18px;
|
||||
text-align: center;
|
||||
@@ -403,93 +410,40 @@ export default {
|
||||
border: 1px solid #5D4037;
|
||||
}
|
||||
|
||||
.lessons-table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.lessons-table th,
|
||||
.lessons-table td {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.lessons-table thead {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.lessons-table th {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
font-size: 0.9em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.lessons-table th.col-number,
|
||||
.lessons-table td.lesson-number {
|
||||
width: 50px;
|
||||
min-width: 50px;
|
||||
max-width: 50px;
|
||||
overflow: visible;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lessons-table th.col-number {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lessons-table th.col-title,
|
||||
.lessons-table td.lesson-title {
|
||||
width: auto;
|
||||
min-width: 200px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.lessons-table th.col-status,
|
||||
.lessons-table td.lesson-status {
|
||||
width: 200px;
|
||||
min-width: 200px;
|
||||
max-width: 200px;
|
||||
overflow: visible;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.lessons-table th.col-actions,
|
||||
.lessons-table td.lesson-actions {
|
||||
width: 250px;
|
||||
min-width: 250px;
|
||||
max-width: 250px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.lessons-table tbody tr {
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.lessons-table tbody tr:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.lessons-table td {
|
||||
padding: 15px;
|
||||
vertical-align: top;
|
||||
display: table-cell;
|
||||
.lesson-cards {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.lesson-number {
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
font-size: 0.95em;
|
||||
text-align: center;
|
||||
display: block;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 48px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
background: rgba(248, 162, 43, 0.12);
|
||||
}
|
||||
|
||||
.lesson-title {
|
||||
display: block;
|
||||
.lesson-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
padding: 16px 18px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.lesson-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.lesson-title-content {
|
||||
@@ -510,10 +464,6 @@ export default {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.lesson-status {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lesson-status-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user