Add edit my rides
Deploy PBT / deploy (push) Successful in 17s

This commit is contained in:
2026-09-11 08:03:19 +02:00
parent 36d97f5e79
commit ca90346f0b
4 changed files with 104 additions and 32 deletions
+37 -14
View File
@@ -200,24 +200,25 @@ def register_routes(app):
return None return None
return stop.id if stop is not None else None return stop.id if stop is not None else None
def fill_trip_from_form(fahrt):
fahrt.transport_mode = request.form["transport_mode"]
fahrt.line = request.form.get("line", "").strip()
fahrt.origin = request.form["origin"].strip()
fahrt.origin_stop_id = resolve_stop_id(request.form.get("origin_stop_id"))
fahrt.destination = request.form["destination"].strip()
fahrt.destination_stop_id = resolve_stop_id(
request.form.get("destination_stop_id")
)
fahrt.trip_date = parse_trip_date(request.form.get("trip_date"))
fahrt.rating = int(request.form["rating"])
fahrt.comment = request.form.get("comment", "").strip()
@app.route("/fahrt/neu", methods=["GET", "POST"]) @app.route("/fahrt/neu", methods=["GET", "POST"])
@login_required @login_required
def neue_fahrt(): def neue_fahrt():
if request.method == "POST": if request.method == "POST":
fahrt = Trip( fahrt = Trip(user_id=current_user.id)
user_id=current_user.id, fill_trip_from_form(fahrt)
transport_mode=request.form["transport_mode"],
line=request.form.get("line", "").strip(),
origin=request.form["origin"].strip(),
origin_stop_id=resolve_stop_id(request.form.get("origin_stop_id")),
destination=request.form["destination"].strip(),
destination_stop_id=resolve_stop_id(
request.form.get("destination_stop_id")
),
trip_date=parse_trip_date(request.form.get("trip_date")),
rating=int(request.form["rating"]),
comment=request.form.get("comment", "").strip(),
)
db.session.add(fahrt) db.session.add(fahrt)
db.session.commit() db.session.commit()
flash("Fahrt gespeichert.", "success") flash("Fahrt gespeichert.", "success")
@@ -227,6 +228,28 @@ def register_routes(app):
"add_entry.html", "add_entry.html",
verkehrsmittel_optionen=VERKEHRSMITTEL_OPTIONEN, verkehrsmittel_optionen=VERKEHRSMITTEL_OPTIONEN,
heute=date.today().isoformat(), heute=date.today().isoformat(),
fahrt=None,
)
@app.route("/fahrt/<int:fahrt_id>/bearbeiten", methods=["GET", "POST"])
@login_required
def fahrt_bearbeiten(fahrt_id):
fahrt = Trip.query.get_or_404(fahrt_id)
if fahrt.user_id != current_user.id:
flash("Nicht erlaubt.", "error")
return redirect(url_for("dashboard"))
if request.method == "POST":
fill_trip_from_form(fahrt)
db.session.commit()
flash("Fahrt aktualisiert.", "success")
return redirect(url_for("dashboard"))
return render_template(
"add_entry.html",
verkehrsmittel_optionen=VERKEHRSMITTEL_OPTIONEN,
heute=fahrt.trip_date.isoformat(),
fahrt=fahrt,
) )
@app.route("/fahrt/<int:fahrt_id>/loeschen", methods=["POST"]) @app.route("/fahrt/<int:fahrt_id>/loeschen", methods=["POST"])
+25 -15
View File
@@ -1,14 +1,14 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Neue Fahrt PBT{% endblock %} {% block title %}{{ "Fahrt bearbeiten" if fahrt else "Neue Fahrt" }} PBT{% endblock %}
{% block content %} {% block content %}
<div class="card"> <div class="card">
<h2>Neue Fahrt erfassen</h2> <h2>{{ "Fahrt bearbeiten" if fahrt else "Neue Fahrt erfassen" }}</h2>
<form method="post"> <form method="post" action="{{ url_for('fahrt_bearbeiten', fahrt_id=fahrt.id) if fahrt else url_for('neue_fahrt') }}">
<div class="field"> <div class="field">
<label for="transport_mode">Verkehrsmittel<span class="required">*</span></label> <label for="transport_mode">Verkehrsmittel<span class="required">*</span></label>
<select id="transport_mode" name="transport_mode" required> <select id="transport_mode" name="transport_mode" required>
{% for option in verkehrsmittel_optionen %} {% for option in verkehrsmittel_optionen %}
<option value="{{ option }}">{{ option }}</option> <option value="{{ option }}" {{ "selected" if fahrt and fahrt.transport_mode == option }}>{{ option }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
@@ -17,23 +17,32 @@
<label for="origin">Von<span class="required">*</span></label> <label for="origin">Von<span class="required">*</span></label>
<input type="text" id="origin" name="origin" required <input type="text" id="origin" name="origin" required
placeholder="Haltestelle suchen …" placeholder="Haltestelle suchen …"
value="{{ fahrt.origin if fahrt else '' }}"
data-stop-input data-stop-target="#origin_stop_id"> data-stop-input data-stop-target="#origin_stop_id">
<input type="hidden" id="origin_stop_id" name="origin_stop_id"> <input type="hidden" id="origin_stop_id" name="origin_stop_id"
<p class="field-hint" data-stop-hint></p> value="{{ fahrt.origin_stop_id if fahrt and fahrt.origin_stop_id else '' }}">
<p class="field-hint {{ 'matched' if fahrt and fahrt.origin_stop }}" data-stop-hint>{{
"✓ " ~ fahrt.origin_stop.name ~ (", " ~ fahrt.origin_stop.municipality if fahrt.origin_stop.municipality else "")
if fahrt and fahrt.origin_stop else "" }}</p>
</div> </div>
<div class="field combo"> <div class="field combo">
<label for="destination">Nach<span class="required">*</span></label> <label for="destination">Nach<span class="required">*</span></label>
<input type="text" id="destination" name="destination" required <input type="text" id="destination" name="destination" required
placeholder="Haltestelle suchen …" placeholder="Haltestelle suchen …"
value="{{ fahrt.destination if fahrt else '' }}"
data-stop-input data-stop-target="#destination_stop_id"> data-stop-input data-stop-target="#destination_stop_id">
<input type="hidden" id="destination_stop_id" name="destination_stop_id"> <input type="hidden" id="destination_stop_id" name="destination_stop_id"
<p class="field-hint" data-stop-hint></p> value="{{ fahrt.destination_stop_id if fahrt and fahrt.destination_stop_id else '' }}">
<p class="field-hint {{ 'matched' if fahrt and fahrt.destination_stop }}" data-stop-hint>{{
"✓ " ~ fahrt.destination_stop.name ~ (", " ~ fahrt.destination_stop.municipality if fahrt.destination_stop.municipality else "")
if fahrt and fahrt.destination_stop else "" }}</p>
</div> </div>
<div class="field combo"> <div class="field combo">
<label for="line">Linie</label> <label for="line">Linie</label>
<input type="text" id="line" name="line" placeholder="z.B. S3, 693" <input type="text" id="line" name="line" placeholder="z.B. S3, 693"
value="{{ fahrt.line if fahrt else '' }}"
data-line-input> data-line-input>
<p class="field-hint" data-line-hint>Halte oben wählen für Linienvorschläge.</p> <p class="field-hint" data-line-hint>Halte oben wählen für Linienvorschläge.</p>
</div> </div>
@@ -46,20 +55,21 @@
<div class="field"> <div class="field">
<label for="rating">Bewertung<span class="required">*</span></label> <label for="rating">Bewertung<span class="required">*</span></label>
<select id="rating" name="rating" required> <select id="rating" name="rating" required>
<option value="5">★★★★★ Sehr gut</option> {% set current_rating = fahrt.rating if fahrt else 3 %}
<option value="4">★★★★☆ Gut</option> <option value="5" {{ "selected" if current_rating == 5 }}>★★★★★ Sehr gut</option>
<option value="3" selected>★★★Okay</option> <option value="4" {{ "selected" if current_rating == 4 }}>★★★Gut</option>
<option value="2">★★☆☆ Schlecht</option> <option value="3" {{ "selected" if current_rating == 3 }}>★★☆☆ Okay</option>
<option value="1">☆☆☆ Sehr schlecht</option> <option value="2" {{ "selected" if current_rating == 2 }}>☆☆☆ Schlecht</option>
<option value="1" {{ "selected" if current_rating == 1 }}>★☆☆☆☆ Sehr schlecht</option>
</select> </select>
</div> </div>
<div class="field"> <div class="field">
<label for="comment">Kommentar</label> <label for="comment">Kommentar</label>
<textarea id="comment" name="comment" rows="3"></textarea> <textarea id="comment" name="comment" rows="3">{{ fahrt.comment if fahrt else "" }}</textarea>
</div> </div>
<button type="submit">Speichern</button> <button type="submit">{{ "Änderungen speichern" if fahrt else "Speichern" }}</button>
</form> </form>
</div> </div>
{% endblock %} {% endblock %}
+20
View File
@@ -136,6 +136,26 @@
.stars { color: #e3b341; white-space: nowrap; } .stars { color: #e3b341; white-space: nowrap; }
.stop-dot { color: var(--success); font-size: 0.7rem; vertical-align: middle; } .stop-dot { color: var(--success); font-size: 0.7rem; vertical-align: middle; }
.row-actions { display: flex; gap: 0.4rem; }
.row-actions form { display: contents; }
.icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
padding: 0;
border: 1px solid var(--panel-border);
border-radius: 6px;
background: transparent;
color: var(--text-muted);
cursor: pointer;
}
.icon-btn svg { width: 16px; height: 16px; }
.icon-btn.edit:hover { color: var(--accent); border-color: var(--accent); background: rgba(74, 158, 255, 0.1); }
.icon-btn.delete { color: var(--danger); }
.icon-btn.delete:hover { background: rgba(248, 81, 73, 0.12); border-color: var(--danger); }
.combo { position: relative; display: flex; flex-direction: column; } .combo { position: relative; display: flex; flex-direction: column; }
.combo-list { .combo-list {
position: absolute; position: absolute;
+22 -3
View File
@@ -32,9 +32,28 @@
</td> </td>
<td class="stars">{{ "★" * f.rating }}{{ "☆" * (5 - f.rating) }}</td> <td class="stars">{{ "★" * f.rating }}{{ "☆" * (5 - f.rating) }}</td>
<td> <td>
<form method="post" action="{{ url_for('fahrt_loeschen', fahrt_id=f.id) }}" onsubmit="return confirm('Fahrt wirklich löschen?');" style="margin: 0;"> <div class="row-actions">
<button type="submit" class="secondary" style="width: auto; padding: 0.35rem 0.7rem; font-size: 0.8rem;">Löschen</button> <a class="icon-btn edit" href="{{ url_for('fahrt_bearbeiten', fahrt_id=f.id) }}"
</form> title="Fahrt bearbeiten" aria-label="Fahrt bearbeiten">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
</svg>
</a>
<form method="post" action="{{ url_for('fahrt_loeschen', fahrt_id=f.id) }}"
onsubmit="return confirm('Fahrt wirklich löschen?');">
<button type="submit" class="icon-btn delete" title="Fahrt löschen" aria-label="Fahrt löschen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"></path>
<path d="M10 11v6"></path>
<path d="M14 11v6"></path>
<path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"></path>
</svg>
</button>
</form>
</div>
</td> </td>
</tr> </tr>
{% if f.comment %} {% if f.comment %}