|
|
@ -1,138 +1,150 @@ |
|
|
<h1 class="mb-4">Meine Einträge</h1> |
|
|
<h1 class="mb-4">Meine Einträge</h1> |
|
|
|
|
|
|
|
|
<h5 class="mt-4">📊 Fortschritt je Kombination</h5> |
|
|
|
|
|
|
|
|
|
|
|
<div class="container my-4 rounded border shadow-sm py-3 px-4"> |
|
|
|
|
|
|
|
|
|
|
|
<%= bar_chart @progress_chart_data, |
|
|
|
|
|
donut: false, |
|
|
|
|
|
height: "300px", |
|
|
|
|
|
library: { |
|
|
|
|
|
legend: { position: "bottom" }, |
|
|
|
|
|
|
|
|
<!-- 🧭 Tabs-Navigation --> |
|
|
|
|
|
<ul class="nav nav-tabs mt-4" id="dashboardTabs" role="tablist"> |
|
|
|
|
|
<li class="nav-item" role="presentation"> |
|
|
|
|
|
<button class="nav-link active" id="overview-tab" data-bs-toggle="tab" data-bs-target="#overview" type="button" role="tab">📈 Kombinationen</button> |
|
|
|
|
|
</li> |
|
|
|
|
|
<li class="nav-item" role="presentation"> |
|
|
|
|
|
<button class="nav-link" id="chart-tab" data-bs-toggle="tab" data-bs-target="#chart" type="button" role="tab">📊 Fortschritt</button> |
|
|
|
|
|
</li> |
|
|
|
|
|
<li class="nav-item" role="presentation"> |
|
|
|
|
|
<button class="nav-link" id="summary-tab" data-bs-toggle="tab" data-bs-target="#summary" type="button" role="tab">📋 Zusammenfassung</button> |
|
|
|
|
|
</li> |
|
|
|
|
|
</ul> |
|
|
|
|
|
|
|
|
|
|
|
<!-- 📑 Tab-Inhalte --> |
|
|
|
|
|
<div class="tab-content border rounded-bottom p-3 shadow-sm" id="dashboardTabsContent"> |
|
|
|
|
|
<!-- 📈 Kombinationen --> |
|
|
|
|
|
<div class="tab-pane fade show active" id="overview" role="tabpanel"> |
|
|
|
|
|
<div class="mb-4 rounded border shadow-sm p-3"> |
|
|
|
|
|
<h4>📊 Übersicht je Kombination</h4> |
|
|
|
|
|
<div class="table-responsive"> |
|
|
|
|
|
<table class="table table-bordered table-sm table-striped"> |
|
|
|
|
|
<thead class="table-light"> |
|
|
|
|
|
<tr> |
|
|
|
|
|
<th>Typ</th> |
|
|
|
|
|
<th>Art</th> |
|
|
|
|
|
<th>Verbleibend</th> |
|
|
|
|
|
<th>Soll (h)</th> |
|
|
|
|
|
<th>Wöchentlich</th> |
|
|
|
|
|
<th>Vorauss. Ende</th> |
|
|
|
|
|
<th>Fortschritt</th> |
|
|
|
|
|
</tr> |
|
|
|
|
|
</thead> |
|
|
|
|
|
<tbody> |
|
|
|
|
|
<% ["propädeutikum", "fachspezifikum"].each do |typ| %> |
|
|
|
|
|
<% ["Praktikum", "Selbsterfahrung", "Supervision"].each do |art| %> |
|
|
|
|
|
<% remaining = @remaining_minutes_matrix.dig(typ, art) %> |
|
|
|
|
|
<% soll = current_user.required_hours_matrix.dig(typ, art) %> |
|
|
|
|
|
<% weekly = current_user.weekly_target_matrix.dig(typ, art) %> |
|
|
|
|
|
<% ende = @estimated_end_by_typ_art.dig(typ, art) %> |
|
|
|
|
|
|
|
|
|
|
|
<% if remaining.present? || soll.present? || weekly.present? %> |
|
|
|
|
|
<tr> |
|
|
|
|
|
<td><%= typ.capitalize %></td> |
|
|
|
|
|
<td><%= art.capitalize %></td> |
|
|
|
|
|
<td><%= remaining ? "#{remaining / 60} h #{remaining % 60} min" : "—" %></td> |
|
|
|
|
|
<td><%= soll || "—" %> h</td> |
|
|
|
|
|
<td><%= weekly || "—" %> h/Woche</td> |
|
|
|
|
|
<td><%= ende.present? ? ende.strftime("%d.%m.%Y") : "—" %></td> |
|
|
|
|
|
<td> |
|
|
|
|
|
<% percent = @completion_percent_by_typ_art[[typ, art]] %> |
|
|
|
|
|
<%= percent ? "#{percent} %" : "—" %> |
|
|
|
|
|
</td> |
|
|
|
|
|
</tr> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</tbody> |
|
|
|
|
|
</table> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
tooltip: { |
|
|
|
|
|
callbacks: { |
|
|
|
|
|
label: %|function(context) { |
|
|
|
|
|
|
|
|
<!-- 📊 Fortschritt (Bar Chart) --> |
|
|
|
|
|
<div class="tab-pane fade" id="chart" role="tabpanel"> |
|
|
|
|
|
<div class="container my-4 rounded border shadow-sm py-3 px-4"> |
|
|
|
|
|
<%= bar_chart @progress_chart_data, |
|
|
|
|
|
donut: false, |
|
|
|
|
|
height: "300px", |
|
|
|
|
|
library: { |
|
|
|
|
|
legend: { position: "bottom" }, |
|
|
|
|
|
tooltip: { |
|
|
|
|
|
callbacks: { |
|
|
|
|
|
label: %|function(context) { |
|
|
return context.label + ": " + context.parsed + "%"; |
|
|
return context.label + ": " + context.parsed + "%"; |
|
|
}| |
|
|
}| |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} %> |
|
|
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
<!-- 🔢 Zusammenfassung --> |
|
|
|
|
|
<div class="container my-4 rounded border shadow-sm py-3 px-4"> |
|
|
|
|
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4"> |
|
|
|
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>🚗 Fahrtkosten (Kilometergeld)</h5> |
|
|
|
|
|
<% @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) : "?" %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
<i>(<%= km %> km bei <%= number_to_currency(rate, unit: "€", separator: ",", delimiter: ".", precision: 2) %>/km)</i> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>💶 Fortbildungskosten</h5> |
|
|
|
|
|
<% @fortbildungskosten_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} %> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>🧠 Selbsterfahrungskosten</h5> |
|
|
|
|
|
<% @selbsterfahrungskosten_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<!-- 📋 Zusammenfassung --> |
|
|
|
|
|
<div class="tab-pane fade" id="summary" role="tabpanel"> |
|
|
|
|
|
<div class="container my-4 rounded border shadow-sm py-3 px-4"> |
|
|
|
|
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4"> |
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>🚗 Fahrtkosten (Kilometergeld)</h5> |
|
|
|
|
|
<% @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) : "?" %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
<i>(<%= km %> km bei <%= number_to_currency(rate, unit: "€", separator: ",", delimiter: ".", precision: 2) %>/km)</i> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>👨🏫 Supervision</h5> |
|
|
|
|
|
<% @selbstsupervision_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>💶 Fortbildungskosten</h5> |
|
|
|
|
|
<% @fortbildungskosten_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>📊 Gesamtkosten (Werbungskosten)</h5> |
|
|
|
|
|
<% @allekosten_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>🧠 Selbsterfahrungskosten</h5> |
|
|
|
|
|
<% @selbsterfahrungskosten_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>🕒 Gesamtzeit</h5> |
|
|
|
|
|
<p><strong>Total: <%= @total_minutes / 60 %>h <%= @total_minutes % 60 %> min</strong></p> |
|
|
|
|
|
<p>Propädeutikum: <%= @total_minutes_praktikum_prop / 60 %>h <%= @total_minutes_praktikum_prop % 60 %> min</p> |
|
|
|
|
|
<p>Fachspezifikum: <%= @total_minutes_praktikum_fach / 60 %>h <%= @total_minutes_praktikum_fach % 60 %> min</p> |
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>👨🏫 Supervision</h5> |
|
|
|
|
|
<% @selbstsupervision_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>📊 Gesamtkosten (Werbungskosten)</h5> |
|
|
|
|
|
<% @allekosten_by_year.each do |year, sum| %> |
|
|
|
|
|
<p><strong><%= year %>:</strong> |
|
|
|
|
|
<%= number_to_currency(sum, unit: "€", separator: ",", delimiter: ".", precision: 2) %> |
|
|
|
|
|
</p> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div class="col rounded border shadow-sm p-3"> |
|
|
|
|
|
<h5>🕒 Gesamtzeit</h5> |
|
|
|
|
|
<p><strong>Total: <%= @total_minutes / 60 %>h <%= @total_minutes % 60 %> min</strong></p> |
|
|
|
|
|
<p>Propädeutikum: <%= @total_minutes_praktikum_prop / 60 %>h <%= @total_minutes_praktikum_prop % 60 %> min</p> |
|
|
|
|
|
<p>Fachspezifikum: <%= @total_minutes_praktikum_fach / 60 %>h <%= @total_minutes_praktikum_fach % 60 %> min</p> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 📊 Übersicht je Kombination --> |
|
|
|
|
|
<div class="mb-4 rounded border shadow-sm p-3"> |
|
|
|
|
|
<h4>📊 Übersicht je Kombination</h4> |
|
|
|
|
|
<div class="table-responsive"> |
|
|
|
|
|
<table class="table table-bordered table-sm table-striped"> |
|
|
|
|
|
<thead class="table-light"> |
|
|
|
|
|
<tr> |
|
|
|
|
|
<th>Typ</th> |
|
|
|
|
|
<th>Art</th> |
|
|
|
|
|
<th>Verbleibend</th> |
|
|
|
|
|
<th>Soll (h)</th> |
|
|
|
|
|
<th>Wöchentlich</th> |
|
|
|
|
|
<th>Vorauss. Ende</th> |
|
|
|
|
|
<th>Fortschritt</th> |
|
|
|
|
|
</tr> |
|
|
|
|
|
</thead> |
|
|
|
|
|
<tbody> |
|
|
|
|
|
<% ["propädeutikum", "fachspezifikum"].each do |typ| %> |
|
|
|
|
|
<% ["Praktikum", "Selbsterfahrung", "Supervision"].each do |art| %> |
|
|
|
|
|
<% remaining = @remaining_minutes_matrix.dig(typ, art) %> |
|
|
|
|
|
<% soll = current_user.required_hours_matrix.dig(typ, art) %> |
|
|
|
|
|
<% weekly = current_user.weekly_target_matrix.dig(typ, art) %> |
|
|
|
|
|
<% ende = @estimated_end_by_typ_art.dig(typ, art) %> |
|
|
|
|
|
|
|
|
|
|
|
<% if remaining.present? || soll.present? || weekly.present? %> |
|
|
|
|
|
<tr> |
|
|
|
|
|
<td><%= typ.capitalize %></td> |
|
|
|
|
|
<td><%= art.capitalize %></td> |
|
|
|
|
|
<td><%= remaining ? "#{remaining / 60} h #{remaining % 60} min" : "—" %></td> |
|
|
|
|
|
<td><%= soll || "—" %> h</td> |
|
|
|
|
|
<td><%= weekly || "—" %> h/Woche</td> |
|
|
|
|
|
<td><%= ende.present? ? ende.strftime("%d.%m.%Y") : "—" %></td> |
|
|
|
|
|
<td> |
|
|
|
|
|
<% percent = @completion_percent_by_typ_art[[typ, art]] %> |
|
|
|
|
|
<%= percent ? "#{percent} %" : "—" %> |
|
|
|
|
|
</td> |
|
|
|
|
|
</tr> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</tbody> |
|
|
|
|
|
</table> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div class="container my-4 rounded border shadow-sm p-3"> |
|
|
<div class="container my-4 rounded border shadow-sm p-3"> |
|
|
<h4 class="mb-4">⏱ Timer</h4> |
|
|
<h4 class="mb-4">⏱ Timer</h4> |
|
|
<% if @running_entry.present? %> |
|
|
<% if @running_entry.present? %> |
|
|
|