Layout Kursübersicht
This commit is contained in:
parent
1778bd1bae
commit
6789ac73c8
@ -1048,13 +1048,73 @@ def useradmin_user_edit(user_id):
|
||||
@app.route("/courses")
|
||||
@login_required
|
||||
def course_list():
|
||||
courses = get_available_courses_for_user()
|
||||
user_id = session.get("user_id")
|
||||
mandant_level = session.get("mandant_level", 0)
|
||||
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
# Alle aktiven Kurse laden
|
||||
cur.execute("""
|
||||
SELECT id, code, title, description, video_file, sort_order, is_active
|
||||
FROM course
|
||||
WHERE is_active = TRUE
|
||||
ORDER BY code
|
||||
""")
|
||||
all_courses = fetchall_dict(cur)
|
||||
|
||||
# Filter nach Level
|
||||
available_courses = [
|
||||
c for c in all_courses
|
||||
if is_course_allowed_for_level(c["code"], mandant_level)
|
||||
]
|
||||
|
||||
# Bestandene Assessments laden
|
||||
cur.execute("""
|
||||
SELECT DISTINCT course_id
|
||||
FROM user_assessment
|
||||
WHERE user_id = %s
|
||||
AND passed = TRUE
|
||||
""", (user_id,))
|
||||
passed_rows = cur.fetchall()
|
||||
passed_course_ids = {row[0] for row in passed_rows}
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# Kurse markieren + Modul bestimmen
|
||||
for course in available_courses:
|
||||
course["is_completed"] = course["id"] in passed_course_ids
|
||||
course["module_code"] = (course["code"] or "")[:1].upper()
|
||||
|
||||
# Gruppieren + Fortschritt berechnen
|
||||
grouped_courses = {}
|
||||
module_progress = {}
|
||||
|
||||
for module_code in ("A", "B", "C"):
|
||||
module_courses = [
|
||||
c for c in available_courses
|
||||
if c["module_code"] == module_code
|
||||
]
|
||||
|
||||
grouped_courses[module_code] = module_courses
|
||||
|
||||
total = len(module_courses)
|
||||
completed = sum(1 for c in module_courses if c["is_completed"])
|
||||
percent = int((completed / total) * 100) if total > 0 else 0
|
||||
|
||||
module_progress[module_code] = {
|
||||
"total": total,
|
||||
"completed": completed,
|
||||
"percent": percent
|
||||
}
|
||||
|
||||
return render_template(
|
||||
"course_list.html",
|
||||
"courses.html",
|
||||
grouped_courses=grouped_courses,
|
||||
module_progress=module_progress,
|
||||
page_title="Kurse",
|
||||
active_page="courses",
|
||||
courses=courses,
|
||||
**get_current_user()
|
||||
)
|
||||
|
||||
|
||||
@ -19,14 +19,13 @@
|
||||
</div>
|
||||
|
||||
<nav class="top-nav">
|
||||
<!-- <a href="/home" class="{% if active_page == 'home' %}active{% endif %}">Home</a> -->
|
||||
<a href="/preise" class="{% if active_page == 'preise' %}active{% endif %}">Preise</a>
|
||||
<!-- <a href="/allgemein" class="{% if active_page == 'allgemein' %}active{% endif %}">Allgemein</a> -->
|
||||
|
||||
{% if is_logged_in %}
|
||||
<a href="/courses" class="{% if active_page == 'courses' %}active{% endif %}">
|
||||
Kurse
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="/preise" class="{% if active_page == 'preise' %}active{% endif %}">Preise</a>
|
||||
{% endif %}
|
||||
|
||||
{% if is_logged_in %}
|
||||
|
||||
85
app/flask-postgres/app/templates/courses.html
Normal file
85
app/flask-postgres/app/templates/courses.html
Normal file
@ -0,0 +1,85 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Kurse</h1>
|
||||
<p class="intro-text">Ihre verfügbaren Schulungsmodule und Kurse.</p>
|
||||
</div>
|
||||
|
||||
{% for module_code, module_courses in grouped_courses.items() %}
|
||||
{% if module_courses %}
|
||||
<section class="admin-section">
|
||||
|
||||
<div class="admin-panel">
|
||||
|
||||
<!-- Modul Titel -->
|
||||
<div class="admin-panel-header">
|
||||
<h2>Modul {{ module_code }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- Fortschritt -->
|
||||
<div class="progress-box">
|
||||
<div class="progress-header">
|
||||
<span>
|
||||
{{ module_progress[module_code].completed }}
|
||||
/
|
||||
{{ module_progress[module_code].total }}
|
||||
abgeschlossen
|
||||
</span>
|
||||
<span>{{ module_progress[module_code].percent }}%</span>
|
||||
</div>
|
||||
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill"
|
||||
style="width: {{ module_progress[module_code].percent }}%;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if module_progress[module_code].percent == 100 %}
|
||||
<div style="margin-top:6px; font-size:12px; color:#15803d; font-weight:600;">
|
||||
✔ Modul abgeschlossen
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Kurse -->
|
||||
<div class="course-grid">
|
||||
|
||||
{% for course in module_courses %}
|
||||
<article class="course-card {% if course.is_completed %}course-card-completed{% endif %}">
|
||||
|
||||
<div class="course-card-header">
|
||||
<div class="course-code">{{ course.code }}</div>
|
||||
|
||||
{% if course.is_completed %}
|
||||
<span class="course-badge course-badge-completed">
|
||||
✔ abgeschlossen
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<h3>{{ course.title }}</h3>
|
||||
|
||||
{% if course.description %}
|
||||
<p>{{ course.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="course-actions">
|
||||
<a href="/course/{{ course.id }}" class="btn-primary btn-small">
|
||||
Kurs öffnen
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</article>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>Login</h1>
|
||||
<h1>Melden Sie sich mit Ihrer email-adresse an</h1>
|
||||
|
||||
{% if error_message %}
|
||||
<div class="error-box">{{ error_message }}</div>
|
||||
|
||||
@ -133,10 +133,6 @@
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="pricing-bottom-note">
|
||||
<div class="image-panel">
|
||||
<img src="/images/TabelleUebersicht.png" alt="Paketübersicht">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@ -1305,3 +1305,142 @@ button {
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
Kursübersicht User
|
||||
=============================== */
|
||||
|
||||
.course-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.course-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #dce3ea;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.course-card-completed {
|
||||
background: #eaf8ee;
|
||||
border: 1px solid #9fd3ac;
|
||||
}
|
||||
|
||||
.course-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.course-code {
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
color: #0d2f57;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.course-badge {
|
||||
display: inline-block;
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.course-badge-completed {
|
||||
background: #22c55e;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.course-card h3 {
|
||||
margin: 0 0 10px;
|
||||
color: #0d2f57;
|
||||
}
|
||||
|
||||
.course-card p {
|
||||
margin: 0 0 16px;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.course-actions {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* Kurs Grid */
|
||||
.course-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* Karte */
|
||||
.course-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #dce3ea;
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
/* Fertig */
|
||||
.course-card-completed {
|
||||
background: #eaf8ee;
|
||||
border: 1px solid #9fd3ac;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.course-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Code */
|
||||
.course-code {
|
||||
font-weight: 800;
|
||||
color: #0d2f57;
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
.course-badge {
|
||||
padding: 5px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.course-badge-completed {
|
||||
background: #22c55e;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Progress */
|
||||
.progress-box {
|
||||
margin: 10px 0 20px;
|
||||
}
|
||||
|
||||
.progress-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
margin-bottom: 6px;
|
||||
color: #475569;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
background: #e5eaf0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #22c55e, #15803d);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user