Browse Source

add dashboard

main
Christoph Marzell 1 month ago
parent
commit
b8be114b70
  1. 55
      app/controllers/dashboards_controller.rb
  2. 18
      app/views/dashboards/_summary_tiles.html.erb
  3. 66
      app/views/dashboards/show.html.erb

55
app/controllers/dashboards_controller.rb

@ -1,29 +1,50 @@
# app/controllers/dashboards_controller.rb
class DashboardsController < ApplicationController class DashboardsController < ApplicationController
def show def show
@entries = current_user.entries.order(date: :desc)
@spent_minutes_matrix = {}
@remaining_minutes_matrix = {}
valid_entries = @entries.select { |e| e.date.present? }
# Alle Kombinationen holen
@time_by_typ_art = current_user.entries
.group(:praktikums_typ, :entry_art)
.select(:praktikums_typ, :entry_art)
.group_by(&:praktikums_typ)
.transform_values { |entries| entries.map(&:entry_art).uniq }
@report = valid_entries.group_by { |e| e.date.beginning_of_month }
.transform_values do |entries|
entries.group_by { |e| [e.praktikums_typ, e.entry_art] }
.transform_values do |subset|
minutes = subset.sum(&:total_minutes)
{ hours: minutes / 60, minutes: minutes % 60 }
# Matrix-Daten aufbauen (muss zuerst passieren!)
@time_by_typ_art.each do |typ, arts|
@spent_minutes_matrix[typ] ||= {}
@remaining_minutes_matrix[typ] ||= {}
arts.each do |art|
spent_minutes = current_user.entries
.where(praktikums_typ: typ, entry_art: art)
.sum { |e| e.total_minutes.to_i }
target = current_user.required_hours_matrix.dig(typ, art).to_i * 60
remaining = [target - spent_minutes, 0].max
@spent_minutes_matrix[typ][art] = spent_minutes
@remaining_minutes_matrix[typ][art] = remaining
end end
end end
@monthly_minutes_chart_data = @report.transform_keys { |date| date.strftime("%b") }
.transform_values do |groups|
groups.values.sum { |data| data[:hours] * 60 + data[:minutes] }
# Jetzt können wir sauber summieren!
@total_minutes = 0
@remaining_total = 0
@spent_minutes_matrix.each do |typ, arts|
arts.each do |art, spent|
@total_minutes += spent.to_i
@remaining_total += @remaining_minutes_matrix.dig(typ, art).to_i
end
end end
@monthly_targets = Hash.new(1500) # z.B. 25h im Monat als Ziel → 1500min
@completed_percent = if (@total_minutes + @remaining_total) > 0
((@total_minutes.to_f / (@total_minutes + @remaining_total)) * 100).round(1)
else
0
end
@total_minutes = @entries.sum(&:total_minutes)
@last_entry = @entries.first
@completed_percent = ((@total_minutes.to_f / 10000) * 100).round(1)
@remaining_total = [10000 - @total_minutes, 0].max
@last_entry = current_user.entries.order(date: :desc).first
end end
end end

18
app/views/dashboards/_summary_tiles.html.erb

@ -1,9 +1,12 @@
<!-- Summary-Kacheln -->
<% total_minutes = @total_minutes.to_i %>
<% remaining_minutes = @remaining_total.to_i %>
<% completed_percent = @completed_percent.to_f %>
<div class="col-sm-6 col-lg-3"> <div class="col-sm-6 col-lg-3">
<div class="card shadow-sm text-center"> <div class="card shadow-sm text-center">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">🕒 Gesamtzeit</h5> <h5 class="card-title">🕒 Gesamtzeit</h5>
<p class="display-6"><%= @total_minutes / 60 %>h <%= @total_minutes % 60 %>min</p>
<p class="display-6"><%= total_minutes / 60 %>h <%= total_minutes % 60 %>min</p>
</div> </div>
</div> </div>
</div> </div>
@ -12,7 +15,7 @@
<div class="card shadow-sm text-center"> <div class="card shadow-sm text-center">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">🚧 Offen</h5> <h5 class="card-title">🚧 Offen</h5>
<p class="display-6 text-warning"><%= @remaining_total / 60 %>h</p>
<p class="display-6 text-warning"><%= remaining_minutes / 60 %>h</p>
</div> </div>
</div> </div>
</div> </div>
@ -21,7 +24,7 @@
<div class="card shadow-sm text-center"> <div class="card shadow-sm text-center">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">✅ Erledigt</h5> <h5 class="card-title">✅ Erledigt</h5>
<p class="display-6 text-success"><%= @completed_percent %>%</p>
<p class="display-6 text-success"><%= completed_percent %>%</p>
</div> </div>
</div> </div>
</div> </div>
@ -30,7 +33,12 @@
<div class="card shadow-sm text-center"> <div class="card shadow-sm text-center">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">📅 Letzter Eintrag</h5> <h5 class="card-title">📅 Letzter Eintrag</h5>
<p class="text-muted"><%= l(@last_entry.date, format: :long) if @last_entry %></p>
<% if @last_entry.present? %>
<p class="display-6 text-muted"><%= l(@last_entry.date, format: :long) %></p>
<% else %>
<p class="display-6 text-muted">—</p>
<% end %>
</div> </div>
</div> </div>
</div> </div>

66
app/views/dashboards/show.html.erb

@ -4,36 +4,44 @@
<div class="row g-4 mb-4"> <div class="row g-4 mb-4">
<%= render partial: 'dashboards/summary_tiles' %> <%= render partial: 'dashboards/summary_tiles' %>
</div> </div>
<!-- Monatsverlauf als Bar Chart -->
<div class="card shadow-sm mb-4"> <div class="card shadow-sm mb-4">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">📈 Monatsverlauf</h5>
<%= column_chart @monthly_minutes_chart_data, height: "250px", colors: ["#0d6efd"] %>
</div>
</div>
<!-- Scrollbare Monatsübersicht mit ProgressBars -->
<div class="d-flex overflow-auto gap-3 pb-3">
<% @report.each do |month, groups| %>
<% total_minutes = groups.values.map { |data| (data[:hours] * 60 + data[:minutes]) }.sum %>
<% total_hours = total_minutes / 60 %>
<% rest_min = total_minutes % 60 %>
<% percent = ((total_minutes.to_f / @monthly_targets[month]) * 100).round rescue 0 %>
<div class="card flex-shrink-0 shadow-sm" style="min-width: 320px;">
<div class="card-header bg-white fw-bold"><%= month.strftime("%B %Y") %></div>
<div class="card-body">
<p class="mb-2">⏱️ <strong><%= total_hours %>h <%= rest_min %>min</strong></p>
<p class="mb-1">🎯 Ziel: <%= @monthly_targets[month] / 60 %>h</p>
<div class="progress" style="height: 20px;">
<div class="progress-bar <%= percent >= 100 ? 'bg-success' : 'bg-primary' %>" role="progressbar"
style="width: <%= [percent, 100].min %>%;" aria-valuenow="<%= percent %>"
aria-valuemin="0" aria-valuemax="100">
<%= percent %>%
</div>
</div>
</div>
<h5 class="card-title">🎯 Fortschritt je Kombination</h5>
<div class="table-responsive">
<table class="table table-bordered align-middle text-center">
<thead class="table-light">
<tr>
<th>Typ</th>
<th>Art</th>
<th>Geleistet</th>
<th>Ziel</th>
<th>Fortschritt</th>
</tr>
</thead>
<tbody>
<% @spent_minutes_matrix.each do |typ, arts| %>
<% arts.each do |art, spent| %>
<% target = current_user.required_hours_matrix.dig(typ, art).to_i * 60 %>
<% percent = target > 0 ? ((spent.to_f / target) * 100).round : 0 %>
<tr>
<td><%= typ.capitalize %></td>
<td><%= art.capitalize %></td>
<td><%= spent / 60 %>h <%= spent % 60 %>min</td>
<td><%= target / 60 %>h</td>
<td>
<div class="progress" style="height: 20px;">
<div class="progress-bar <%= percent >= 100 ? 'bg-success' : 'bg-primary' %>" role="progressbar"
style="width: <%= [percent, 100].min %>%;" aria-valuenow="<%= percent %>"
aria-valuemin="0" aria-valuemax="100">
<%= percent %>%
</div>
</div>
</td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
</div> </div>
<% end %>
</div>
</div> </div>
Loading…
Cancel
Save