Skip to content

Commit 17125df

Browse files
committed
Update student dashboard
1 parent 65a2efa commit 17125df

File tree

4 files changed

+255
-10
lines changed

4 files changed

+255
-10
lines changed

My_path_team9/student/routes.py

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,24 @@ def survey():
104104
@student_bp.route('/dashboard')
105105
@login_required
106106
def dashboard():
107-
"""
108-
Renders the student dashboard.
107+
if current_user.role != 'student':
108+
return "Access denied", 403
109109

110-
Returns:
111-
The student dashboard page.
112-
"""
113-
return render_template('student_dashboard.html')
110+
videos = MotivationalVideo.query.all()
114111

112+
video_data = []
113+
for video in videos:
114+
ratings = [r.rating for r in video.ratings]
115+
avg_rating = round(sum(ratings) / len(ratings), 1) if ratings else None
116+
my_rating = next((r.rating for r in video.ratings if r.student_id == current_user.id), None)
117+
118+
video_data.append({
119+
'video': video,
120+
'average_rating': avg_rating,
121+
'my_rating': my_rating
122+
})
123+
124+
return render_template('student_dashboard.html', videos=video_data)
115125

116126
@student_bp.route('/submit', methods=['GET', 'POST'])
117127
@login_required
@@ -395,3 +405,46 @@ def recommendations(survey_id):
395405
recommendations = recommendations[:5]
396406

397407
return render_template('recommendations.html', recommendations=recommendations)
408+
409+
410+
from ..teacher.models import MotivationalVideo, VideoRating
411+
412+
@student_bp.route('/rate_video', methods=['POST'])
413+
@login_required
414+
def rate_video():
415+
if current_user.role != 'student':
416+
return "Access denied", 403
417+
418+
video_id = request.form.get('video_id')
419+
rating_str = request.form.get('rating')
420+
421+
# Validate video_id and rating presence
422+
if not video_id or not rating_str:
423+
flash('Video ID and rating are required.', 'danger')
424+
return redirect(url_for('student.dashboard'))
425+
426+
try:
427+
video_id = int(video_id)
428+
rating = int(rating_str)
429+
except ValueError:
430+
flash('Invalid video ID or rating.', 'danger')
431+
return redirect(url_for('student.dashboard'))
432+
433+
# Check if the video exists to avoid FK violation
434+
video = MotivationalVideo.query.get(video_id)
435+
if not video:
436+
flash('Video not found.', 'danger')
437+
return redirect(url_for('student.dashboard'))
438+
439+
# Check for existing rating and update or create new
440+
existing = VideoRating.query.filter_by(student_id=current_user.id, video_id=video_id).first()
441+
if existing:
442+
existing.rating = rating
443+
else:
444+
new_rating = VideoRating(student_id=current_user.id, video_id=video_id, rating=rating)
445+
db.session.add(new_rating)
446+
447+
db.session.commit()
448+
flash('Your rating was saved!', 'success')
449+
return redirect(url_for('student.dashboard'))
450+
Lines changed: 190 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,193 @@
11
{% extends "base.html" %}
22

3+
{% block styles %}
4+
<style>
5+
.container {
6+
max-width: 1200px;
7+
margin: 0 auto;
8+
padding: 2rem;
9+
}
10+
11+
h1 {
12+
font-weight: 700;
13+
color: #4f46e5;
14+
}
15+
16+
.videos-grid {
17+
display: grid;
18+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
19+
gap: 1.5rem;
20+
margin-top: 1rem;
21+
}
22+
23+
.video-card {
24+
background: #fff;
25+
border-radius: 1rem;
26+
padding: 1.5rem;
27+
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
28+
display: flex;
29+
flex-direction: column;
30+
justify-content: space-between;
31+
transition: box-shadow 0.3s ease;
32+
}
33+
.video-card:hover {
34+
box-shadow: 0 8px 24px rgba(79, 70, 229, 0.2);
35+
}
36+
37+
.video-title {
38+
font-size: 1.25rem;
39+
font-weight: 700;
40+
color: #4f46e5;
41+
margin-bottom: 0.75rem;
42+
}
43+
44+
.btn-watch {
45+
background: linear-gradient(135deg, #4f46e5, #7c3aed);
46+
color: white;
47+
padding: 0.5rem 1rem;
48+
border: none;
49+
border-radius: 0.5rem;
50+
font-weight: 600;
51+
text-decoration: none;
52+
cursor: pointer;
53+
display: inline-block;
54+
margin-bottom: 1rem;
55+
transition: background-color 0.3s ease;
56+
}
57+
.btn-watch:hover {
58+
background: linear-gradient(135deg, #4338ca, #6b21a8);
59+
}
60+
61+
.rating-stars {
62+
display: inline-flex;
63+
gap: 2px;
64+
font-size: 1.2rem;
65+
margin-bottom: 0.5rem;
66+
}
67+
.star {
68+
color: #fbbf24;
69+
}
70+
.star.empty {
71+
color: #e5e7eb;
72+
}
73+
74+
.rating-info {
75+
color: #64748b;
76+
font-size: 0.9rem;
77+
margin-bottom: 1rem;
78+
}
79+
80+
form.rate-form {
81+
display: flex;
82+
gap: 0.5rem;
83+
align-items: center;
84+
}
85+
86+
select.form-select-sm {
87+
padding: 0.3rem 0.5rem;
88+
border-radius: 0.5rem;
89+
border: 1px solid #d1d5db;
90+
font-size: 0.9rem;
91+
background: white;
92+
cursor: pointer;
93+
}
94+
95+
button.btn-rate {
96+
background-color: #10b981;
97+
color: white;
98+
border: none;
99+
padding: 0.4rem 1rem;
100+
border-radius: 0.5rem;
101+
font-weight: 600;
102+
cursor: pointer;
103+
transition: background-color 0.3s ease;
104+
}
105+
button.btn-rate:hover {
106+
background-color: #059669;
107+
}
108+
109+
@media (max-width: 600px) {
110+
.videos-grid {
111+
grid-template-columns: 1fr;
112+
}
113+
}
114+
</style>
115+
{% endblock %}
116+
3117
{% block content %}
4-
<h1>Welcome, {{ current_user.username }}!</h1>
5-
<p>This is your student dashboard.</p>
6-
{% endblock %}
118+
<div class="container mt-4">
119+
120+
<h1 class="mb-3">Welcome, {{ current_user.username }}!</h1>
121+
<p class="text-muted">Your student dashboard — here are your motivational videos:</p>
122+
123+
<hr class="my-4">
124+
<h2 class="h4 mb-3">Motivational Videos</h2>
125+
126+
{% if videos %}
127+
<div class="videos-grid">
128+
{% for video in videos %}
129+
<div class="video-card">
130+
<div>
131+
<h3 class="video-title">{{ video.video.title }}</h3>
132+
133+
{% if video.video.video_link %}
134+
<a href="{{ video.video.video_link }}" target="_blank" rel="noopener noreferrer" class="btn-watch">▶️ Watch</a>
135+
{% else %}
136+
<span class="rating-info">Video link not available</span>
137+
{% endif %}
138+
139+
<div><strong>Your Rating:</strong>
140+
{% if video.my_rating %}
141+
{% for i in range(1, 6) %}
142+
{% if i <= video.my_rating %}
143+
<span style="color:#fbbf24; font-size:1.2rem;"></span>
144+
{% else %}
145+
<span style="color:#e5e7eb; font-size:1.2rem;"></span>
146+
{% endif %}
147+
{% endfor %}
148+
{% else %}
149+
<span>Not rated yet</span>
150+
{% endif %}
151+
</div>
152+
153+
<div>
154+
<strong>Average Rating:</strong>
155+
{% if video.average_rating %}
156+
{% set avg = video.average_rating %}
157+
<span class="rating-stars" aria-label="Average rating: {{ "%.1f"|format(avg) }} out of 5 stars">
158+
{% for i in range(1, 6) %}
159+
{% if i <= avg %}
160+
<span class="star" aria-hidden="true"></span>
161+
{% elif i - avg < 1 %}
162+
<span class="star" aria-hidden="true"></span>
163+
{% else %}
164+
<span class="star empty" aria-hidden="true"></span>
165+
{% endif %}
166+
{% endfor %}
167+
</span>
168+
<span class="rating-info">({{ "%.1f"|format(avg) }})</span>
169+
{% else %}
170+
<span class="rating-info">No ratings yet</span>
171+
{% endif %}
172+
</div>
173+
</div>
174+
175+
<form method="POST" action="{{ url_for('student.rate_video') }}" class="rate-form mt-3">
176+
<input type="hidden" name="video_id" value="{{ video.video.id }}">
177+
<select name="rating" class="form-select-sm" required>
178+
<option value="" disabled selected>Rate</option>
179+
{% for num in range(1, 6) %}
180+
<option value="{{ num }}">{{ num }} ⭐</option>
181+
{% endfor %}
182+
</select>
183+
<button class="btn-rate" type="submit">Rate</button>
184+
</form>
185+
</div>
186+
{% endfor %}
187+
</div>
188+
{% else %}
189+
<p class="text-muted">No videos have been uploaded yet.</p>
190+
{% endif %}
191+
192+
</div>
193+
{% endblock %}

My_path_team9/student/templates/submit.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ <h1>Submit Video</h1>
227227
<div class="video-form-group">
228228
<label class="video-form-label" for="{{ form.video_link.id }}">Video Link</label>
229229
<div class="video-input-icon">
230-
{{ form.video_link(class="video-form-input", placeholder="Paste your YouTube, Vimeo, or other video URL here...") }}
230+
{{ form.video_link(class="video-form-input", placeholder="Paste your YouTube or other video URL here...") }}
231231
</div>
232232
{% for error in form.video_link.errors %}
233233
<span class="video-error-message">{{ error }}</span>

My_path_team9/templates/base.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,11 @@
701701
<a class="nav-link" href="{{ url_for('teacher.students_list') }}">Students</a>
702702
</li>
703703
{% endif %}
704+
{% if current_user.is_authenticated and current_user.role == 'teacher' %}
705+
<li class="nav-item">
706+
<a class="nav-link" href="{{ url_for('teacher.send_video') }}">Videos</a>
707+
</li>
708+
{% endif %}
704709

705710
<!-- Profile Dropdown (for all roles) -->
706711
<li class="nav-item dropdown">

0 commit comments

Comments
 (0)