inaktive veranstaltungen zeigen keinen teilnahmeberreich mehr, veranstaltungsortsuche verbessert

This commit is contained in:
kai
2026-08-25 13:15:08 +02:00
parent 60d8c941de
commit 714194615f
3 changed files with 85 additions and 7 deletions
+26 -3
View File
@@ -2,6 +2,7 @@ import os
import uuid
import secrets
import hashlib
import re
from contextlib import asynccontextmanager
from datetime import datetime, timedelta
@@ -1147,6 +1148,7 @@ def concert_detail(request: Request, concert_id: int):
]
attending_users = [item for item in attendance if item["status"] == "attending"]
ticket_seekers = [item for item in attendance if item["status"] == "ticket_search"]
maybe_users = [item for item in attendance if item["status"] == "maybe"]
current_attendance = next(
(item["status"] for item in attendance if item["user_id"] == user["id"]),
None,
@@ -1165,6 +1167,8 @@ def concert_detail(request: Request, concert_id: int):
attending_count=len(attending_users),
ticket_seekers=ticket_seekers,
ticket_seeker_count=len(ticket_seekers),
maybe_users=maybe_users,
maybe_count=len(maybe_users),
)
@@ -1606,6 +1610,12 @@ def search_venues(q: str):
return []
results = []
query_tokens = [
token
for token in re.findall(r"[a-z0-9]+", q.lower())
if len(token) >= 3
]
token_match = " AND ".join("name ILIKE %s" for _ in query_tokens) or "FALSE"
# ========================================================
@@ -1616,7 +1626,7 @@ def search_venues(q: str):
with connection.cursor() as cursor:
cursor.execute("""
cursor.execute(f"""
SELECT
id,
name,
@@ -1633,6 +1643,7 @@ def search_venues(q: str):
name ILIKE %s
OR city ILIKE %s
OR street ILIKE %s
OR ({token_match})
ORDER BY
CASE
WHEN LOWER(name) = LOWER(%s)
@@ -1653,11 +1664,13 @@ def search_venues(q: str):
f"%{q}%",
*[f"%{token}%" for token in query_tokens],
q,
f"{q}%",
f"%{q}%"
f"%{q}%",
))
@@ -1717,9 +1730,11 @@ def search_venues(q: str):
"User-Agent": "PinguConcerts/1.0"
}
external_query = re.sub(r"\bhall\b", "halle", q, flags=re.IGNORECASE)
params = {
"q": q,
"q": external_query,
"format": "jsonv2",
@@ -1876,6 +1891,14 @@ def search_venues(q: str):
score = 0
name_tokens = re.findall(r"[a-z0-9]+", name_lower)
matched_tokens = sum(
any(candidate.startswith(token) or token.startswith(candidate)
for candidate in name_tokens)
for token in query_tokens
)
score += matched_tokens * 30
if name_lower == query_lower:
+19
View File
@@ -196,6 +196,8 @@
{% endif %}
{% if not concert.is_past %}
<section class="attendance-section" id="attendance">
<h2>
@@ -241,6 +243,7 @@
<details class="attendance-list">
<summary>
{{ attending_count }} Zusage{% if attending_count != 1 %}n{% endif %}
· {{ maybe_count }} Vielleicht
· {{ ticket_seeker_count }} sucht Ticket
</summary>
@@ -260,6 +263,20 @@
{% endif %}
</div>
<div>
<h3>? Vielleicht</h3>
{% if maybe_users %}
<ul>
{% for maybe_user in maybe_users %}
<li>{{ maybe_user.name }}</li>
{% endfor %}
</ul>
{% else %}
<p>Noch keine Vielleicht-Angaben.</p>
{% endif %}
</div>
<div>
<h3>🎟️ Sucht ein Ticket</h3>
@@ -279,6 +296,8 @@
</section>
{% endif %}
<section class="comments-section" id="comments">
<h2>💬 Kommentare</h2>
+38 -2
View File
@@ -389,6 +389,27 @@ const selectedVenue =
let searchTimeout = null;
let venueRequestController = null;
function clearVenueSelection() {
[
"venue-id",
"venue-name",
"venue-city",
"venue-street",
"venue-postal-code",
"venue-country",
"venue-latitude",
"venue-longitude"
].forEach(
id => {
document.getElementById(id).value = "";
}
);
}
venueSearch.addEventListener(
@@ -410,6 +431,8 @@ venueSearch.addEventListener(
selectedVenue.style.display =
"none";
clearVenueSelection();
if (query.length < 2) {
@@ -426,7 +449,7 @@ venueSearch.addEventListener(
);
},
300
450
);
}
@@ -443,9 +466,18 @@ async function searchVenues(
try {
if (venueRequestController) {
venueRequestController.abort();
}
venueRequestController = new AbortController();
const response =
await fetch(
`/api/venues/search?q=${encodeURIComponent(query)}`
`/api/venues/search?q=${encodeURIComponent(query)}`,
{
signal: venueRequestController.signal
}
);
@@ -554,6 +586,10 @@ async function searchVenues(
} catch (error) {
if (error.name === "AbortError") {
return;
}
console.error(
"Venue search failed:",
error