Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions car/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/<int:id>/")
@browser_cache
def show_turf(id: ID):
Expand Down
79 changes: 79 additions & 0 deletions car/static/search.css
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 2 additions & 0 deletions car/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@
<a href="{{ url_for('login') }}">Add turf</a>
{% endif %}

&middot; <a href="{{ url_for('search') }}">Search</a>

&middot; <a href="{{ url_for('logout') }}">Logout</a>

{% else %}
Expand Down
45 changes: 45 additions & 0 deletions car/templates/search.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{% extends "base.html" %}
{% block title %}car search{% endblock %}

{% block content %}
<link rel="stylesheet" href="/static/search.css">
<h1 class="comfy">🔎 Search Voters</h1>
<form method="POST">
<div class="search-bar">
<label for="query" class="sr-only">Search by name</label>
<input type="text" id="query" name="query" placeholder="Search by name..." value="{{ query }}" />
<button type="submit" aria-label="Search">
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="7"/>
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
</svg>
</button>
</div>
</form>
{% if results is not none %}
<div>
<h1 class="comfy">Results:</h1>
<table class="results-table">
<thead>
<tr>
<th>Name</th>
<th>Demographics</th>
<th>Party</th>
</tr>
</thead>
<tbody>
{% for voter in results %}
<tr>
<td><a href="{{ url_for('show_voter', id=voter.id_) }}">{{ voter.firstname }} {{ voter.middlename }} {{ voter.lastname }}</a></td>
<td>{{ voter.age() }} {{ voter.gender}}</td>
<td>{{ voter.party }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if results | length == 50 %}
<div>For better results, refine your query!</div>
{% endif %}
</div>
{% endif %}
{% endblock %}
Loading