From b8be114b70e0162a526ed4e6ff6d9faa85d3ab1a Mon Sep 17 00:00:00 2001 From: Christoph Marzell Date: Sun, 8 Feb 2026 09:20:44 +0100 Subject: [PATCH] add dashboard --- app/controllers/dashboards_controller.rb | 55 +++++++++++----- app/views/dashboards/_summary_tiles.html.erb | 18 ++++-- app/views/dashboards/show.html.erb | 66 +++++++++++--------- 3 files changed, 88 insertions(+), 51 deletions(-) diff --git a/app/controllers/dashboards_controller.rb b/app/controllers/dashboards_controller.rb index aa8f360..2e1dd7a 100644 --- a/app/controllers/dashboards_controller.rb +++ b/app/controllers/dashboards_controller.rb @@ -1,29 +1,50 @@ -# app/controllers/dashboards_controller.rb class DashboardsController < ApplicationController 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 - @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 - @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 diff --git a/app/views/dashboards/_summary_tiles.html.erb b/app/views/dashboards/_summary_tiles.html.erb index 79ca1b8..1c2dab8 100644 --- a/app/views/dashboards/_summary_tiles.html.erb +++ b/app/views/dashboards/_summary_tiles.html.erb @@ -1,9 +1,12 @@ - +<% total_minutes = @total_minutes.to_i %> +<% remaining_minutes = @remaining_total.to_i %> +<% completed_percent = @completed_percent.to_f %> +
🕒 Gesamtzeit
-

<%= @total_minutes / 60 %>h <%= @total_minutes % 60 %>min

+

<%= total_minutes / 60 %>h <%= total_minutes % 60 %>min

@@ -12,7 +15,7 @@
🚧 Offen
-

<%= @remaining_total / 60 %>h

+

<%= remaining_minutes / 60 %>h

@@ -21,7 +24,7 @@
✅ Erledigt
-

<%= @completed_percent %>%

+

<%= completed_percent %>%

@@ -30,7 +33,12 @@
📅 Letzter Eintrag
-

<%= l(@last_entry.date, format: :long) if @last_entry %>

+ <% if @last_entry.present? %> +

<%= l(@last_entry.date, format: :long) %>

+ <% else %> +

+ <% end %>
+ diff --git a/app/views/dashboards/show.html.erb b/app/views/dashboards/show.html.erb index da88090..148b648 100644 --- a/app/views/dashboards/show.html.erb +++ b/app/views/dashboards/show.html.erb @@ -4,36 +4,44 @@
<%= render partial: 'dashboards/summary_tiles' %>
- -
-
📈 Monatsverlauf
- <%= column_chart @monthly_minutes_chart_data, height: "250px", colors: ["#0d6efd"] %> -
-
- - -
- <% @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 %> - -
-
<%= month.strftime("%B %Y") %>
-
-

⏱️ <%= total_hours %>h <%= rest_min %>min

-

🎯 Ziel: <%= @monthly_targets[month] / 60 %>h

-
-
- <%= percent %>% -
-
-
+
🎯 Fortschritt je Kombination
+
+ + + + + + + + + + + + <% @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 %> + + + + + + + + <% end %> + <% end %> + +
TypArtGeleistetZielFortschritt
<%= typ.capitalize %><%= art.capitalize %><%= spent / 60 %>h <%= spent % 60 %>min<%= target / 60 %>h +
+
+ <%= percent %>% +
+
+
- <% end %> +