diff --git a/car/app.py b/car/app.py index fb9396d..f58ab2c 100644 --- a/car/app.py +++ b/car/app.py @@ -407,6 +407,24 @@ def settings(): return render_template("settings.html") +@app.route("/search/", methods=["GET", "POST"]) +def search(): + query = request.form.get("query") + if request.method == "GET" or not query: + return render_template("search.html", query="", results=None) + + parts = query.strip().lower().split() + + def matches_voter(v: Voter) -> bool: + return any( + part in "".join(map(str, v.model_dump().values())).lower() for part in parts + ) + + results = list(itertools.islice(filter(matches_voter, db.voters), 50)) + + return render_template("search.html", query=query, results=results) + + @app.route("/turf//") @browser_cache def show_turf(id: ID): diff --git a/car/static/search.css b/car/static/search.css new file mode 100644 index 0000000..e9157c3 --- /dev/null +++ b/car/static/search.css @@ -0,0 +1,79 @@ +.results-table { + width: 100%; + border-collapse: collapse; + font-size: 14pt; +} + +.results-table th, +.results-table td { + text-align: left; + padding: 6px 8px; +} + +.results-table thead th { + border-bottom: 1px solid var(--heading-border); + font-weight: bold; +} + +.results-table tbody tr:nth-child(odd) { + background-color: var(--stripe-bg); +} + +.voter-status { + font-size: 80%; + padding: 2px 6px; + border-radius: 4px; +} + +.voter-status-A { + color: var(--success-color); +} + +.voter-status-I { + color: var(--muted-color); +} + + +.search-bar { + display: flex; + align-items: stretch; + border: 1px solid var(--btn-border); + border-radius: 6px; + overflow: hidden; + background-color: var(--bg-color); +} + +.search-bar input[type="text"] { + flex: 1; + border: none; + background: transparent; + font-size: 14pt; + padding: 0.5em 0.75em; + color: var(--text-color); +} + +.search-bar input[type="text"]:focus { + outline: none; +} + +.search-bar button { + width: auto; + margin-top: 0; + padding: 0 1em; + border: none; + border-radius: 0; + background-color: var(--btn-bg); + color: var(--btn-text); +} + +.search-bar button:hover { background-color: var(--btn-hover-bg); } +.search-bar button:active { background-color: var(--btn-active-bg); } + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0,0,0,0); + white-space: nowrap; +} diff --git a/car/templates/base.html b/car/templates/base.html index 5531aae..a9efb28 100644 --- a/car/templates/base.html +++ b/car/templates/base.html @@ -128,6 +128,8 @@ Add turf {% endif %} + · Search + · Logout {% else %} diff --git a/car/templates/search.html b/car/templates/search.html new file mode 100644 index 0000000..2a85da3 --- /dev/null +++ b/car/templates/search.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} +{% block title %}car search{% endblock %} + +{% block content %} + +

🔎 Search Voters

+
+ +
+{% if results is not none %} +
+

Results:

+ + + + + + + + + + {% for voter in results %} + + + + + + {% endfor %} + +
NameDemographicsParty
{{ voter.firstname }} {{ voter.middlename }} {{ voter.lastname }}{{ voter.age() }} {{ voter.gender}}{{ voter.party }}
+ {% if results | length == 50 %} +
For better results, refine your query!
+ {% endif %} +
+{% endif %} +{% endblock %}