{# The live part of an outing. While open it re-fetches itself on the SSE
`changed` event (connected by the wrapper in show.html, which isn't
swapped, so the stream survives), with a slow poll as a backstop. Buttons
inside inherit hx-target/hx-select/hx-swap from here, so each action
returns a fresh panel too. #}
<div id="outing-panel" class="space-y-4"
hx-target="#outing-panel" hx-select="#outing-panel" hx-swap="outerHTML"
{% if outing.status == "open" %}
hx-get="/outings/{{ outing.id }}/panel" hx-trigger="sse:changed, every 30s"
{% endif %}>
<div class="flex items-center justify-between gap-3 flex-wrap">
<p class="text-sm">
<span class="opacity-70">Going:</span>
{% if going %}{{ going | join(", ") }}{% else %}<span class="opacity-70">nobody yet</span>{% endif %}
</p>
{% if outing.status == "open" %}
{% if am_going %}
<button type="button" class="btn btn-ghost btn-xs" hx-post="/outings/{{ outing.id }}/leave">
<i class="fas fa-person-walking-arrow-right"></i> I'm out
</button>
{% else %}
<button type="button" class="btn btn-primary btn-sm" hx-post="/outings/{{ outing.id }}/join">
<i class="fas fa-hand"></i> I'm in
</button>
{% endif %}
{% endif %}
</div>
{% if outing.status == "decided" %}
<div class="card bg-success/10 border border-success p-5 text-center space-y-1">
<p class="text-xs uppercase tracking-widest opacity-70">Decided</p>
{% if decided %}
<a href="/restaurants/{{ decided.id }}" class="text-2xl font-bold link link-hover">{{ decided.name }}</a>
{% if decided.address %}<p class="text-sm opacity-70">{{ decided.address }}</p>{% endif %}
{% endif %}
<p class="text-xs opacity-70">Logged to <a class="link" href="/areas/{{ area.id }}/history">{{ area.name }}'s history</a>.</p>
</div>
{% elif outing.status == "cancelled" %}
<div class="alert text-sm"><i class="fas fa-ban"></i> This lunch was called off.</div>
{% elif options | length == 0 %}
<div class="alert alert-warning text-sm">
<span>Nothing to vote on: everything in {{ area.name }} is vetoed by someone going or closed at {{ outing.meal_time[:5] }}, or there are no restaurants yet.
<a class="link" href="/areas/{{ area.id }}/restaurants/new">Add some</a>.</span>
</div>
{% else %}
<p class="text-xs opacity-70">
Vote for every option you'd happily go to. Re-roll swaps only the options nobody voted for.
</p>
<ul class="space-y-2">
{% for o in options %}
{% set leading = o.votes > 0 and o.votes == leader_votes %}
<li class="card bg-base-200 border {{ 'border-success' if leading else 'border-base-300' }} p-4">
<div class="flex items-start justify-between gap-3 flex-wrap">
<div class="min-w-0">
<a href="/restaurants/{{ o.restaurant.id }}" class="font-bold text-lg link link-hover">{{ o.restaurant.name }}</a>
{% if leading %}<span class="badge badge-success badge-sm align-middle">leading</span>{% endif %}
{% if outing.rolls > 1 and o.roll == outing.rolls %}<span class="badge badge-info badge-sm align-middle">new</span>{% endif %}
<p class="text-xs opacity-70">
{{ [o.restaurant.cuisine, o.restaurant.address] | select | join(" · ") }}
{%- if o.restaurant.cuisine or o.restaurant.address %} · {% endif %}{{ (o.probability * 100) | round | int }}% odds when drawn
</p>
{% if o.vetoed_by %}
<p class="text-xs text-error mt-1"><i class="fas fa-ban"></i> {{ o.vetoed_by | join(", ") }} ranked this "never" (joined after it was drawn)</p>
{% endif %}
<p class="text-sm mt-1">
<span class="font-mono">{{ o.votes }}</span> vote{{ "" if o.votes == 1 else "s" }}{% if o.voters %}: {{ o.voters | join(", ") }}{% endif %}
</p>
</div>
<div class="flex gap-2 shrink-0">
<button type="button" class="btn btn-sm {{ 'btn-success' if o.mine else 'btn-outline' }}"
aria-pressed="{{ 'true' if o.mine else 'false' }}"
hx-post="/outings/{{ outing.id }}/vote" hx-vals='{"restaurant_id": "{{ o.restaurant.id }}"}'>
<i class="fas {{ 'fa-check' if o.mine else 'fa-thumbs-up' }}"></i> {{ "Voted" if o.mine else "Vote" }}
</button>
<button type="button" class="btn btn-sm btn-ghost"
hx-post="/outings/{{ outing.id }}/decide" hx-vals='{"restaurant_id": "{{ o.restaurant.id }}"}'
hx-confirm="Go to {{ o.restaurant.name }}? This logs the lunch for everyone going.">
<i class="fas fa-flag-checkered"></i> Go here
</button>
</div>
</div>
</li>
{% endfor %}
</ul>
{% endif %}
{% if outing.status == "open" %}
<div class="flex items-center justify-between gap-3 flex-wrap">
<div class="flex items-center gap-3">
<button type="button" class="btn btn-sm" hx-post="/outings/{{ outing.id }}/reroll"
{% if all_voted %}disabled title="Every option has a vote, so there's nothing to swap"{% endif %}>
<i class="fas fa-dice"></i> Re-roll the rest
</button>
<span class="text-xs opacity-70">
roll {{ outing.rolls }}{% if rolled_away %} · {{ rolled_away }} rolled away{% endif %}
</span>
</div>
<button type="button" class="btn btn-ghost btn-xs" hx-post="/outings/{{ outing.id }}/cancel"
hx-confirm="Call off this lunch?">
Call it off
</button>
</div>
{% endif %}
</div>
neiam
/fieri-forever
the flavortown lunch engine
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
5.5 KiB · text
History
6dd7389