Meine Einträge

📊 Übersicht je Kombination

<% Entry::PRAKTIKUMSTYPEN.each do |typ| %> <% Entry::ENTRY_ARTEN.each do |art| %> <% remaining = @remaining_minutes_matrix.dig(typ, art).to_i %> <% spent = @spent_minutes_matrix.dig(typ, art).to_i %> <% soll = current_user.required_hours_for(typ, art).to_f %> <% weekly = current_user.weekly_target_for(typ, art).to_f %> <% ende = @estimated_end_by_typ_art.dig(typ, art) %> <% # Ohne Sollwert und ohne geleistete Zeit ist die Kombination # für die Übersicht nicht relevant. next if soll.zero? && spent.zero? # Standardmäßig nur Anforderungen anzeigen, # bei denen tatsächlich noch etwas offen ist. has_remaining = remaining.positive? %> <% percent = @completion_percent_by_typ_art[[typ, art]] %> <% zero_percent = percent.to_i.zero? && soll.positive? %> <% type_class = case typ when "propädeutikum" "type-propaedeutikum" when "fachspezifikum" "type-fachspezifikum" when "mediation" "type-mediation" else "" end row_classes = [ type_class, ("d-none" unless has_remaining && !zero_percent) ].compact.reject(&:blank?).join(" ") %> <% end %> <% end %>
Typ Art Verbleibend Erledigt Soll (h) Wöchentlich Stunden/Woche Vorauss. Ende Fortschritt
<%= typ.capitalize %> <%= art %> <%= remaining / 60 %> h <%= remaining % 60 %> min <%= spent / 60 %> h <%= spent % 60 %> min <%= number_with_precision(soll, precision: 2, strip_insignificant_zeros: true) %> h <% if weekly.positive? %> <%= number_with_precision(weekly, precision: 2, strip_insignificant_zeros: true) %> h/Woche <% else %> — <% end %> <% actual = @actual_hours_per_week[[typ, art]] %> <% if actual.present? %> <%= actual %> h/Woche <% else %> — <% end %> <%= ende.present? ? ende.strftime("%d.%m.%Y") : "—" %> <%= percent.nil? ? "—" : "#{percent} %" %>
Standardmäßig werden nur bereits begonnene Einträge angezeigt, bei denen noch Stunden offen sind.
<%= bar_chart @progress_chart_data, colors: @progress_colors.values, suffix: "%", donut: false, height: "300px", plugins: { tooltip: { callbacks: { label: %|function(context) { return context.dataset.label + ": " + context.raw + "%"; }| } }, legend: { position: "bottom" } }, library: { datasets: [ { backgroundColor: %|function(context) { const value = context.raw; if (value < 40) return "rgba(54, 162, 235, 0.7)"; // blau if (value < 80) return "rgba(75, 192, 192, 0.7)"; // grün return "rgba(255, 99, 132, 0.7)"; // rot }| } ], legend: { position: "bottom" }, tooltip: { callbacks: { label: %|function(context) { return context.label + ": " + context.parsed + "%"; }| } } } %>
🚗 Fahrtkosten (Kilometergeld)
<% @total_kilometer_costs_by_year.each do |year, sum| %> <% rate = MileageRate.find_by(year: year)&.rate_per_km || 0.42 %> <% km = rate > 0 ? (sum.to_f / rate).round(1) : "?" %>

<%= year %>: <%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> (<%= km %> km bei <%= number_to_currency(rate, unit: "€", separator: ",", delimiter: ".", precision: 2) %>/km)

<% end %>
💶 Fortbildungskosten
<% @fortbildungskosten_by_year.each do |year, sum| %>

<%= year %>: <%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %>

<% end %>
🧠 Selbsterfahrungskosten
<% @selbsterfahrungskosten_by_year.each do |year, sum| %>

<%= year %>: <%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %>

<% end %>
👨‍🏫 Supervision
<% @selbstsupervision_by_year.each do |year, sum| %>

<%= year %>: <%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %>

<% end %>
🧾 Gesamtkosten (Weiterbildungskosten + Kilometergeld)
<% @gesamtkosten_by_year.each do |year, sum| %>

<%= year %>: <%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %>

<% end %>
🕒 Gesamtzeit

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

Propädeutikum: <%= @total_minutes_praktikum_prop / 60 %>h <%= @total_minutes_praktikum_prop % 60 %> min

Fachspezifikum: <%= @total_minutes_praktikum_fach / 60 %>h <%= @total_minutes_praktikum_fach % 60 %> min

Mediation: <%= @total_minutes_praktikum_mediation / 60 %>h <%= @total_minutes_praktikum_mediation % 60 %> min

⏱ Timer

<% if @running_entry.present? %>
Laufender Eintrag: <%= @running_entry.praktikums_typ %> – <%= @running_entry.entry_art %>
Gestartet: <%= l(@running_entry.start_time, format: :short) %>
Dauer: Berechne …
<%= form_with url: stop_timer_entry_path(@running_entry), method: :post, local: true do |f| %>
<%= f.check_box :lunch_break, class: 'form-check-input', id: 'lunch_break' %> <%= f.label :lunch_break, '30 Min Mittagspause abziehen', class: 'form-check-label' %>
<%= f.submit '⏹️ Stoppen', class: "btn btn-danger" %> <% end %>
<% end %>
<%= form_with url: start_timer_entries_path, method: :post, local: true do %>
<%= label_tag :typ, 'Typ' %> <%= select_tag :typ, options_for_select( current_user.praepedeutikum_abgeschlossen? ? Entry::PRAKTIKUMSTYPEN.reject { |typ| typ == 'propädeutikum' } : Entry::PRAKTIKUMSTYPEN ), class: "form-select" %>
<%= label_tag :art, 'Art' %> <%= select_tag :art, options_for_select(Entry::ENTRY_ARTEN), class: "form-select" %>
<%= submit_tag '▶️ Start', class: "btn btn-success w-100", disabled: @running_entry.present? %>
<% end %>
<%= link_to '➕ Neuer Eintrag', new_entry_path, class: 'btn btn-outline-primary mt-3 w-100 w-md-auto mb-3' %>

📋 Einträge

<% @entries.each do |entry| %> <% duration_in_minutes = entry.hours.to_i * 60 + entry.minutes.to_i %> <% is_today = entry.date == Date.current %> <% end %>
Datum Zeit Typ Art Beschreibung Kilometer Pauschale Kosten Zählt als Fortbildung Aktionen
<%= entry.date.strftime('%d.%m.%Y') %> <% if is_today %> Heute <% end %> <% if duration_in_minutes > 0 %> <%= formatted_duration(entry) %> <% else %> — <% end %> <%= entry.praktikums_typ&.capitalize%> <%= entry.entry_art&.capitalize %> <%= entry.beschreibung %> <%= entry.distance_km.to_f %> km <%= number_to_currency(entry.kilometer_pauschale, unit: "€", separator: ",", delimiter: ".") %> <%= number_to_currency(entry.kosten, unit: "€", separator: ",", delimiter: ".") %> <%= check_box_tag "fortbildung_#{entry.id}", '1', entry.zaehlt_als_fortbildung, disabled: true %>
<%= link_to 'Bearbeiten', edit_entry_path(entry), class: 'btn btn-sm btn-outline-primary' %>
Aktuell angezeigt: 0 · Gesamt: 0
<%= link_to "Export als CSV", export_csv_entries_path(format: :csv), class: "btn btn-outline-secondary mt-3 w-100 w-md-auto" %>