|
|
|
@ -1,4 +1,4 @@ |
|
|
|
<div class="container my-4"> |
|
|
|
|
|
|
|
<h1 class="mb-4">Meine Einträge</h1> |
|
|
|
|
|
|
|
<!-- 🔢 Zusammenfassung --> |
|
|
|
@ -99,17 +99,67 @@ |
|
|
|
</table> |
|
|
|
</div> |
|
|
|
|
|
|
|
<%= link_to '➕ Neuer Eintrag', new_entry_path, class: 'btn btn-light mt-3 w-100 w-md-auto' %> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="mb-3"> |
|
|
|
<input type="text" id="entryFilter" class="form-control" placeholder="🔍 Filter nach Datum, Typ, Art …"> |
|
|
|
<div class="container my-4 rounded border shadow-sm p-3"> |
|
|
|
<h4 class="mb-4">⏱ Timer</h4> |
|
|
|
<% if @running_entry.present? %> |
|
|
|
<div class="alert alert-info d-flex justify-content-between align-items-center"> |
|
|
|
<div> |
|
|
|
<strong>Laufender Eintrag:</strong> |
|
|
|
<%= @running_entry.praktikums_typ %> – <%= @running_entry.entry_art %><br> |
|
|
|
Gestartet: <%= l(@running_entry.start_time, format: :short) %><br> |
|
|
|
Dauer: <span id="live-timer">Berechne …</span> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<%= button_to '⏹️ Stoppen', stop_timer_entry_path(@running_entry), method: :post, class: "btn btn-danger" %> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<% end %> |
|
|
|
|
|
|
|
<div class="mb-4 row" > |
|
|
|
|
|
|
|
|
|
|
|
<%= form_with url: start_timer_entries_path, method: :post, local: true do %> |
|
|
|
<div class="row g-2 align-items-end"> |
|
|
|
<div class="col-md-4"> |
|
|
|
<%= label_tag :typ, 'Typ' %> |
|
|
|
<%= select_tag :typ, options_for_select(Entry::PRAKTIKUMSTYPEN), class: "form-select" %> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="col-md-4"> |
|
|
|
<%= label_tag :art, 'Art' %> |
|
|
|
<%= select_tag :art, options_for_select(Entry::ENTRY_ARTEN), class: "form-select" %> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="col-md-4"> |
|
|
|
<%= submit_tag '▶️ Start', class: "btn btn-success w-100", disabled: @running_entry.present? %> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<% end %> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<%= link_to '➕ Neuer Eintrag', new_entry_path, class: 'btn btn-info mt-3 w-100 w-md-auto mb-3' %> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 📋 Tabelle aller Einträge --> |
|
|
|
<div class="m-1"> |
|
|
|
<h4 class="mb-3">📋 Einträge</h4> |
|
|
|
|
|
|
|
<div class="mb-3"> |
|
|
|
<input type="text" id="entryFilter" class="form-control" placeholder="🔍 Filter nach Datum, Typ, Art …"> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="table-responsive"> |
|
|
|
<table class="table table-striped table-hover table-bordered" id="entriesTable"> |
|
|
|
<thead> |
|
|
|
@ -150,8 +200,6 @@ |
|
|
|
<%= number_to_currency(entry.kosten, unit: "€", separator: ",", delimiter: ".") %> |
|
|
|
</td> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<td class="text-end"> |
|
|
|
<div class="d-flex justify-content-between"> |
|
|
|
<%= link_to 'Bearbeiten', edit_entry_path(entry), class: 'btn btn-sm btn-outline-primary' %> |
|
|
|
@ -240,4 +288,25 @@ |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function () { |
|
|
|
const timerElement = document.getElementById('live-timer'); |
|
|
|
if (!timerElement) return; |
|
|
|
|
|
|
|
<% if @running_entry&.start_time.present? %> |
|
|
|
const startedAt = new Date("<%= @running_entry.start_time.iso8601 %>"); |
|
|
|
<% end %> |
|
|
|
|
|
|
|
if (!startedAt) return; |
|
|
|
const updateTimer = () => { |
|
|
|
const now = new Date(); |
|
|
|
const diffMs = now - startedAt; |
|
|
|
const totalMinutes = Math.floor(diffMs / 60000); |
|
|
|
const hours = Math.floor(totalMinutes / 60); |
|
|
|
const minutes = totalMinutes % 60; |
|
|
|
timerElement.textContent = `${hours}h ${minutes}min (${totalMinutes}min)`; |
|
|
|
}; |
|
|
|
|
|
|
|
updateTimer(); |
|
|
|
setInterval(updateTimer, 60000); // alle Minute aktualisieren |
|
|
|
}); |
|
|
|
</script> |