24 changed files with 331 additions and 96 deletions
@ -1,8 +0,0 @@ |
|||
# Default ignored files |
|||
/shelf/ |
|||
/workspace.xml |
|||
# Editor-based HTTP Client requests |
|||
/httpRequests/ |
|||
# Datasource local storage ignored files |
|||
/dataSources/ |
|||
/dataSources.local.xml |
|||
@ -1,4 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="ProjectRootManager" version="2" project-jdk-name="ruby-3.2.4-p170" project-jdk-type="RUBY_SDK" /> |
|||
</project> |
|||
@ -1,8 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="ProjectModuleManager"> |
|||
<modules> |
|||
<module fileurl="file://$PROJECT_DIR$/.idea/praktikum.iml" filepath="$PROJECT_DIR$/.idea/praktikum.iml" /> |
|||
</modules> |
|||
</component> |
|||
</project> |
|||
@ -1,28 +0,0 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<module type="RUBY_MODULE" version="4"> |
|||
<component name="ModuleRunConfigurationManager"> |
|||
<shared /> |
|||
</component> |
|||
<component name="NewModuleRootManager"> |
|||
<content url="file://$MODULE_DIR$"> |
|||
<sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" /> |
|||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" /> |
|||
</content> |
|||
<orderEntry type="inheritedJdk" /> |
|||
<orderEntry type="sourceFolder" forTests="false" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="bcrypt (v3.1.20, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="builder (v3.3.0, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.3.5, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="crass (v1.0.6, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="devise (v4.9.4, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="mini_mime (v1.1.5, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="net-pop (v0.1.2, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="net-protocol (v0.2.2, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="orm_adapter (v0.5.0, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="racc (v1.8.1, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="tzinfo (v2.0.6, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="warden (v1.2.9, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
<orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.5, ruby-3.2.4-p170) [gem]" level="application" /> |
|||
</component> |
|||
</module> |
|||
@ -1,6 +1,6 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="VcsDirectoryMappings"> |
|||
<mapping directory="" vcs="Git" /> |
|||
<mapping directory="$PROJECT_DIR$" vcs="Git" /> |
|||
</component> |
|||
</project> |
|||
@ -0,0 +1,9 @@ |
|||
//= require rails-ujs
|
|||
//= require turbolinks
|
|||
//= require_tree .
|
|||
|
|||
import "@hotwired/turbo-rails" |
|||
import * as ActiveStorage from "@rails/activestorage" |
|||
import "channels" |
|||
|
|||
console.log("HALLO RAILS JS") |
|||
@ -1,2 +1,9 @@ |
|||
class ApplicationController < ActionController::Base |
|||
before_action :configure_permitted_parameters, if: :devise_controller? |
|||
|
|||
|
|||
def configure_permitted_parameters |
|||
devise_parameter_sanitizer.permit(:account_update, keys: [:total_required_hours, :weekly_target_hours, required_hours_matrix: {}, required_hours_matrix: {}]) |
|||
end |
|||
|
|||
end |
|||
@ -1,35 +1,124 @@ |
|||
<h1 class="mb-4">🕒 Praktikumszeit Tracker</h1> |
|||
<h1>Meine Einträge</h1> |
|||
|
|||
<% if notice %> |
|||
<p class="alert alert-success"><%= notice %></p> |
|||
<% end %> |
|||
|
|||
<!-- 🔢 Zusammenfassung --> |
|||
<div class="mb-3"> |
|||
<p><strong>Gesamtzeit:</strong> <%= @total_minutes / 60 %> h <%= @total_minutes % 60 %> min</p> |
|||
<p><strong>Fehlend:</strong> <%= @remaining_minutes / 60 %> h <%= @remaining_minutes % 60 %> min</p> |
|||
<p><strong>Geplante Stunden/Woche:</strong> <%= current_user.weekly_target_hours %> h</p> |
|||
<% if @estimated_end_date.present? %> |
|||
<p><strong>Voraussichtliches Ende:</strong> <%= @estimated_end_date.strftime("%d.%m.%Y") %></p> |
|||
<% end %> |
|||
<%= link_to '➕ Neuer Eintrag', new_entry_path, class: 'btn btn-primary' %> |
|||
<p><strong>Fahrtkosten gesamt:</strong> |
|||
<%= number_to_currency(@total_kilometer_pauschale, unit: "€", separator: ",", delimiter: ".") %> |
|||
</p> |
|||
|
|||
<hr> |
|||
|
|||
<h4 class="mt-4">📊 Übersicht je Kombination</h4> |
|||
|
|||
<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> |
|||
</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 %></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> |
|||
</tr> |
|||
<% end %> |
|||
<% end %> |
|||
<% end %> |
|||
</tbody> |
|||
</table> |
|||
|
|||
|
|||
|
|||
<%= link_to '➕ Neuer Eintrag', new_entry_path, class: 'btn btn-light mt-3' %> |
|||
</div> |
|||
|
|||
<table class="table table-striped"> |
|||
<!-- 📋 Tabelle --> |
|||
<table class="table table-striped table-hover"> |
|||
<thead> |
|||
<tr> |
|||
<th>Datum</th> |
|||
<th>Stunden</th> |
|||
<th>Minuten</th> |
|||
<th>Zeit</th> |
|||
<th>Typ</th> |
|||
<th>Art</th> |
|||
<th>Kilometer</th> |
|||
<th>Pauschale</th> |
|||
<th>Aktionen</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<% @entries.each do |entry| %> |
|||
<tr> |
|||
<td><%= entry.date %></td> |
|||
<td><%= entry.hours %></td> |
|||
<td><%= entry.minutes %></td> |
|||
<td><%= entry.date.strftime('%d.%m.%Y') %></td> |
|||
<td><%= entry.hours.to_i %>h <%= entry.minutes.to_i %>min</td> |
|||
<td><%= entry.praktikums_typ %></td> |
|||
<td><%= entry.entry_art %></td> |
|||
<td><%= entry.distance_km.to_f %> km</td> |
|||
<td><%= number_to_currency(entry.kilometer_pauschale, unit: "€", separator: ",", delimiter: ".") %></td> |
|||
<td> |
|||
<%= link_to '✏️ Bearbeiten', edit_entry_path(entry), class: 'btn btn-sm btn-primary' %> |
|||
<%= link_to '🗑️ Löschen', entry, method: :delete, data: { confirm: 'Sicher?' }, class: 'btn btn-sm btn-danger' %> |
|||
<%= link_to '🗑️ Löschen', entry_path(entry), class: 'btn btn-sm btn-danger open-delete-modal' %> |
|||
</td> |
|||
</tr> |
|||
<% end %> |
|||
</tbody> |
|||
</table> |
|||
|
|||
<!-- 🔒 Modal zur Bestätigung --> |
|||
<div class="modal fade" id="deleteConfirmModal" tabindex="-1" aria-labelledby="deleteConfirmModalLabel" aria-hidden="true"> |
|||
<div class="modal-dialog modal-dialog-centered"> |
|||
<div class="modal-content"> |
|||
<div class="modal-header"> |
|||
<h5 class="modal-title">Löschen bestätigen</h5> |
|||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Schließen"></button> |
|||
</div> |
|||
<div class="modal-body"> |
|||
Bist du sicher, dass du diesen Eintrag löschen möchtest? |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button> |
|||
<form id="modal-delete-form" method="post"> |
|||
<input type="hidden" name="_method" value="delete"> |
|||
<%= hidden_field_tag :authenticity_token, form_authenticity_token %> |
|||
<button type="submit" class="btn btn-danger">Löschen</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- JS für Modal --> |
|||
<script> |
|||
document.addEventListener('DOMContentLoaded', function () { |
|||
document.querySelectorAll('.open-delete-modal').forEach(button => { |
|||
button.addEventListener('click', function (e) { |
|||
e.preventDefault(); |
|||
const targetUrl = this.getAttribute('href'); |
|||
document.getElementById('modal-delete-form').setAttribute('action', targetUrl); |
|||
const modal = new bootstrap.Modal(document.getElementById('deleteConfirmModal')); |
|||
modal.show(); |
|||
}); |
|||
}); |
|||
}); |
|||
</script> |
|||
@ -1,9 +1,15 @@ |
|||
<p style="color: green"><%= notice %></p> |
|||
|
|||
<%= render @entry %> |
|||
<% if @entry.present? %> |
|||
<%= render @entry %> |
|||
<% else %> |
|||
<p>⚠️ Kein Eintrag gefunden.</p> |
|||
<% end %> |
|||
|
|||
<div> |
|||
<% if @entry.present? %> |
|||
<%= link_to "Edit this entry", edit_entry_path(@entry) %> | |
|||
<% end %> |
|||
<%= link_to "Back to entries", entries_path %> |
|||
|
|||
<%= button_to "Destroy this entry", @entry, method: :delete %> |
|||
|
|||
@ -0,0 +1,7 @@ |
|||
class AddFieldsToEntries < ActiveRecord::Migration[7.1] |
|||
def change |
|||
add_column :entries, :praktikums_typ, :string, null: false, default: "propädeutikum" |
|||
add_column :entries, :entry_art, :string, null: false, default: "Praktikum" |
|||
add_column :entries, :distance_km, :integer, null: false, default: 0 |
|||
end |
|||
end |
|||
@ -0,0 +1,5 @@ |
|||
class AddRequiredHoursMatrixToUsers < ActiveRecord::Migration[7.1] |
|||
def change |
|||
add_column :users, :required_hours_matrix, :jsonb, default: {}, null: false |
|||
end |
|||
end |
|||
@ -0,0 +1,5 @@ |
|||
class AddWeeklyTargetMatrixToUsers < ActiveRecord::Migration[7.1] |
|||
def change |
|||
add_column :users, :weekly_target_matrix, :jsonb, default: {}, null: false |
|||
end |
|||
end |
|||
Loading…
Reference in new issue