|
|
@ -18,9 +18,28 @@ |
|
|
<!-- 📈 Kombinationen --> |
|
|
<!-- 📈 Kombinationen --> |
|
|
<div class="tab-pane fade show active" id="overview" role="tabpanel"> |
|
|
<div class="tab-pane fade show active" id="overview" role="tabpanel"> |
|
|
<div class="mb-4 rounded border shadow-sm p-3"> |
|
|
<div class="mb-4 rounded border shadow-sm p-3"> |
|
|
<h4>📊 Übersicht je Kombination</h4> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3"> |
|
|
|
|
|
<h4 class="mb-0">📊 Übersicht je Kombination</h4> |
|
|
|
|
|
|
|
|
|
|
|
<div class="form-check form-switch"> |
|
|
|
|
|
<input |
|
|
|
|
|
class="form-check-input" |
|
|
|
|
|
type="checkbox" |
|
|
|
|
|
role="switch" |
|
|
|
|
|
id="showAllCombinations" |
|
|
|
|
|
> |
|
|
|
|
|
<label class="form-check-label" for="showAllCombinations"> |
|
|
|
|
|
Alle anzeigen |
|
|
|
|
|
</label> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="table-responsive"> |
|
|
<div class="table-responsive"> |
|
|
<table class="table table-bordered table-sm table-striped"> |
|
|
|
|
|
|
|
|
<table |
|
|
|
|
|
class="table table-bordered table-sm table-striped" |
|
|
|
|
|
id="combinationOverviewTable" |
|
|
|
|
|
> |
|
|
<thead class="table-light"> |
|
|
<thead class="table-light"> |
|
|
<tr> |
|
|
<tr> |
|
|
<th>Typ</th> |
|
|
<th>Typ</th> |
|
|
@ -34,44 +53,99 @@ |
|
|
<th>Fortschritt</th> |
|
|
<th>Fortschritt</th> |
|
|
</tr> |
|
|
</tr> |
|
|
</thead> |
|
|
</thead> |
|
|
|
|
|
|
|
|
<tbody> |
|
|
<tbody> |
|
|
<% Entry::PRAKTIKUMSTYPEN.each do |typ| %> |
|
|
<% Entry::PRAKTIKUMSTYPEN.each do |typ| %> |
|
|
<% Entry::ENTRY_ARTEN.each do |art| %> |
|
|
<% Entry::ENTRY_ARTEN.each do |art| %> |
|
|
|
|
|
|
|
|
<% remaining = @remaining_minutes_matrix.dig(typ, art) %> |
|
|
<% remaining = @remaining_minutes_matrix.dig(typ, art) %> |
|
|
<% spent = @spent_minutes_matrix.dig(typ, art) %> |
|
|
<% spent = @spent_minutes_matrix.dig(typ, art) %> |
|
|
<% next if spent.blank? %> |
|
|
|
|
|
<% soll = current_user.required_hours_matrix.dig(typ, art) %> |
|
|
<% soll = current_user.required_hours_matrix.dig(typ, art) %> |
|
|
<% next if soll.blank? %> |
|
|
|
|
|
<% weekly = current_user.weekly_target_matrix.dig(typ, art) %> |
|
|
<% weekly = current_user.weekly_target_matrix.dig(typ, art) %> |
|
|
<% ende = @estimated_end_by_typ_art.dig(typ, art) %> |
|
|
<% ende = @estimated_end_by_typ_art.dig(typ, art) %> |
|
|
|
|
|
|
|
|
|
|
|
<% next if spent.blank? %> |
|
|
|
|
|
<% next if soll.blank? %> |
|
|
|
|
|
|
|
|
<% if (remaining.present? || soll.present? || weekly.present?) %> |
|
|
|
|
|
<tr> |
|
|
|
|
|
|
|
|
<% |
|
|
|
|
|
# Standardmäßig zeigen wir nur Einträge, |
|
|
|
|
|
# bei denen tatsächlich noch etwas offen ist. |
|
|
|
|
|
has_remaining = remaining.to_i.positive? |
|
|
|
|
|
%> |
|
|
|
|
|
|
|
|
|
|
|
<% if remaining.present? || soll.present? || weekly.present? %> |
|
|
|
|
|
<tr |
|
|
|
|
|
data-has-remaining="<%= has_remaining %>" |
|
|
|
|
|
class="<%= 'd-none' unless has_remaining %>" |
|
|
|
|
|
> |
|
|
<td><%= typ.capitalize %></td> |
|
|
<td><%= typ.capitalize %></td> |
|
|
|
|
|
|
|
|
<td><%= art.capitalize %></td> |
|
|
<td><%= art.capitalize %></td> |
|
|
<td><%= remaining ? "#{remaining / 60} h #{remaining % 60} min" : "—" %></td> |
|
|
|
|
|
<td><%= spent ? "#{spent / 60} h #{spent % 60} min" : "—" %></td> |
|
|
|
|
|
<td><%= soll || "—" %> h</td> |
|
|
|
|
|
<td><%= weekly || "—" %> h/Woche</td> |
|
|
|
|
|
<td><%= @actual_hours_per_week[[typ, art]] ? "#{@actual_hours_per_week[[typ, art]]} h/Woche" : "—" %></td> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
<% if remaining.present? %> |
|
|
|
|
|
<%= remaining / 60 %> h <%= remaining % 60 %> min |
|
|
|
|
|
<% else %> |
|
|
|
|
|
— |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
<% if spent.present? %> |
|
|
|
|
|
<%= spent / 60 %> h <%= spent % 60 %> min |
|
|
|
|
|
<% else %> |
|
|
|
|
|
— |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
<% if soll.present? %> |
|
|
|
|
|
<%= soll %> h |
|
|
|
|
|
<% else %> |
|
|
|
|
|
— |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
<% if weekly.present? %> |
|
|
|
|
|
<%= weekly %> h/Woche |
|
|
|
|
|
<% else %> |
|
|
|
|
|
— |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
<% actual = @actual_hours_per_week[[typ, art]] %> |
|
|
|
|
|
|
|
|
|
|
|
<% if actual.present? %> |
|
|
|
|
|
<%= actual %> h/Woche |
|
|
|
|
|
<% else %> |
|
|
|
|
|
— |
|
|
|
|
|
<% end %> |
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
|
|
|
|
<td> |
|
|
|
|
|
<%= ende.present? ? ende.strftime("%d.%m.%Y") : "—" %> |
|
|
|
|
|
</td> |
|
|
|
|
|
|
|
|
<td><%= ende.present? ? ende.strftime("%d.%m.%Y") : "—" %></td> |
|
|
|
|
|
<td> |
|
|
<td> |
|
|
<% percent = @completion_percent_by_typ_art[[typ, art]] %> |
|
|
<% percent = @completion_percent_by_typ_art[[typ, art]] %> |
|
|
<%= percent ? "#{percent} %" : "—" %> |
|
|
|
|
|
|
|
|
<%= percent.present? ? "#{percent} %" : "—" %> |
|
|
</td> |
|
|
</td> |
|
|
</tr> |
|
|
</tr> |
|
|
<% end %> |
|
|
<% end %> |
|
|
|
|
|
|
|
|
<% end %> |
|
|
<% end %> |
|
|
<% end %> |
|
|
<% end %> |
|
|
</tbody> |
|
|
</tbody> |
|
|
</table> |
|
|
</table> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div class="small text-muted mt-2"> |
|
|
|
|
|
Standardmäßig werden nur Einträge angezeigt, bei denen noch Stunden offen sind. |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<!-- 📊 Fortschritt (Bar Chart) --> |
|
|
<!-- 📊 Fortschritt (Bar Chart) --> |
|
|
<div class="tab-pane fade" id="chart" role="tabpanel"> |
|
|
<div class="tab-pane fade" id="chart" role="tabpanel"> |
|
|
<div class="container my-4 rounded border shadow-sm py-3 px-4"> |
|
|
<div class="container my-4 rounded border shadow-sm py-3 px-4"> |
|
|
|