working card for existing reservation

This commit is contained in:
Priec
2026-05-16 21:00:09 +02:00
parent b5d1fd46ed
commit 1b4b79a642
4 changed files with 108 additions and 1 deletions

View File

@@ -27,6 +27,8 @@ manage-courts = Courts
back-to-calendar = Back to calendar back-to-calendar = Back to calendar
add-booking = New Booking add-booking = New Booking
edit-booking = Edit Booking edit-booking = Edit Booking
booking-details = Booking details
edit = Edit
date = Date date = Date
hour = Hour hour = Hour
booking-color = Colour booking-color = Colour

View File

@@ -27,6 +27,8 @@ manage-courts = Kurty
back-to-calendar = Späť na kalendár back-to-calendar = Späť na kalendár
add-booking = Nová rezervácia add-booking = Nová rezervácia
edit-booking = Upraviť rezerváciu edit-booking = Upraviť rezerváciu
booking-details = Detail rezervácie
edit = Upraviť
date = Dátum date = Dátum
hour = Hodina hour = Hodina
booking-color = Farba booking-color = Farba

View File

@@ -0,0 +1,58 @@
{% extends "base.html" %}
{% block title %}{{ t(key="booking-details", lang=lang) }}{% endblock title %}
{% block content %}
<div class="mx-auto max-w-md">
<div class="mb-4 flex items-center justify-between">
<h1 class="text-2xl font-bold">{{ t(key="booking-details", lang=lang) }}</h1>
<a href="/admin?court={{ court_id }}&week={{ date }}" class="btn btn-ghost btn-sm">« {{ t(key="back-to-calendar", lang=lang) }}</a>
</div>
<div class="card border border-base-300 bg-base-100 shadow-sm">
<div class="card-body gap-0">
<dl class="divide-y divide-base-300">
<div class="flex justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="court-label", lang=lang) }}</dt>
<dd class="text-right text-sm font-medium">{{ court_name }}</dd>
</div>
<div class="flex justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="date", lang=lang) }}</dt>
<dd class="text-right text-sm font-medium">{{ date_label }}</dd>
</div>
<div class="flex justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="hour", lang=lang) }}</dt>
<dd class="text-right text-sm font-medium">{{ hour_label }}</dd>
</div>
<div class="flex items-center justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="booking-color", lang=lang) }}</dt>
<dd class="flex items-center gap-2">
<span class="inline-block h-5 w-8 rounded border border-base-300" style="background-color: {{ color }}"></span>
<span class="text-sm font-medium">{{ color }}</span>
</dd>
</div>
<div class="flex justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="booking-name", lang=lang) }}</dt>
<dd class="text-right text-sm font-medium">{{ name }}</dd>
</div>
<div class="flex justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="booking-title", lang=lang) }}</dt>
<dd class="text-right text-sm font-medium">{% if title %}{{ title }}{% else %}<span class="opacity-40"></span>{% endif %}</dd>
</div>
<div class="flex justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="booking-contact", lang=lang) }}</dt>
<dd class="text-right text-sm font-medium">{% if contact %}{{ contact }}{% else %}<span class="opacity-40"></span>{% endif %}</dd>
</div>
<div class="flex justify-between gap-4 py-2">
<dt class="text-sm opacity-70">{{ t(key="booking-note", lang=lang) }}</dt>
<dd class="whitespace-pre-line text-right text-sm font-medium">{% if note %}{{ note }}{% else %}<span class="opacity-40"></span>{% endif %}</dd>
</div>
</dl>
<div class="flex items-center gap-2 pt-4">
<a href="/admin/booking/{{ booking_id }}/edit" class="btn btn-neutral">{{ t(key="edit", lang=lang) }}</a>
<a href="/admin?court={{ court_id }}&week={{ date }}" class="btn btn-ghost">{{ t(key="back-to-calendar", lang=lang) }}</a>
</div>
</div>
</div>
</div>
{% endblock content %}

View File

@@ -421,6 +421,50 @@ pub async fn booking_create(
Ok(Redirect::to(&format!("/admin?court={}&week={}", form.court_id, form.date)).into_response()) Ok(Redirect::to(&format!("/admin?court={}&week={}", form.court_id, form.date)).into_response())
} }
/// Read-only detail card for an existing booking. Clicking a booking in the
/// calendar lands here first, so a stray click can never change anything; the
/// card's "Edit" button is the only way through to the editable form.
#[debug_handler]
pub async fn booking_view(
_auth: AdminAuth,
ViewEngine(v): ViewEngine<TeraView>,
State(ctx): State<AppContext>,
jar: CookieJar,
Path(id): Path<i32>,
) -> Result<Response> {
let lang = current_lang(&jar);
let booking = bookings::Entity::find_by_id(id)
.one(&ctx.db)
.await?
.ok_or(Error::NotFound)?;
let court_name = courts::Entity::find_by_id(booking.court_id)
.one(&ctx.db)
.await?
.and_then(|c| c.name)
.unwrap_or_else(|| format!("Court {}", booking.court_id));
format::render().view(
&v,
"admin/booking_detail.html",
data!({
"lang": lang,
"is_admin": true,
"logged_in": true,
"court_id": booking.court_id,
"court_name": court_name,
"date": booking.date.format("%Y-%m-%d").to_string(),
"date_label": booking.date.format("%d %b %Y").to_string(),
"hour_label": format!("{:02}:00 {:02}:00", booking.hour, booking.hour + 1),
"color": booking.color,
"name": booking.name,
"title": booking.title.unwrap_or_default(),
"contact": booking.contact.unwrap_or_default(),
"note": booking.note.unwrap_or_default(),
"booking_id": id,
}),
)
}
#[debug_handler] #[debug_handler]
pub async fn booking_edit( pub async fn booking_edit(
_auth: AdminAuth, _auth: AdminAuth,
@@ -515,7 +559,8 @@ pub fn routes() -> Routes {
.add("/courts/{id}/delete", post(delete_court)) .add("/courts/{id}/delete", post(delete_court))
.add("/booking", get(booking_new)) .add("/booking", get(booking_new))
.add("/booking", post(booking_create)) .add("/booking", post(booking_create))
.add("/booking/{id}", get(booking_edit)) .add("/booking/{id}", get(booking_view))
.add("/booking/{id}/edit", get(booking_edit))
.add("/booking/{id}", post(booking_update)) .add("/booking/{id}", post(booking_update))
.add("/booking/{id}/delete", post(booking_delete)) .add("/booking/{id}/delete", post(booking_delete))
} }