details for the admin
This commit is contained in:
@@ -52,3 +52,4 @@ theme-dark = Dark
|
|||||||
settings = Settings
|
settings = Settings
|
||||||
settings-language = Language
|
settings-language = Language
|
||||||
settings-theme = Theme
|
settings-theme = Theme
|
||||||
|
view-details = Details
|
||||||
|
|||||||
@@ -52,3 +52,4 @@ theme-dark = Tmavý
|
|||||||
settings = Nastavenia
|
settings = Nastavenia
|
||||||
settings-language = Jazyk
|
settings-language = Jazyk
|
||||||
settings-theme = Téma
|
settings-theme = Téma
|
||||||
|
view-details = Detaily
|
||||||
|
|||||||
@@ -2,6 +2,37 @@
|
|||||||
|
|
||||||
{% block title %}{{ t(key="calendar-title", lang=lang) }}{% endblock title %}
|
{% block title %}{{ t(key="calendar-title", lang=lang) }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{% if is_admin %}
|
||||||
|
<style>
|
||||||
|
/* Admin calendar — detailed-view toggle. The public calendar is unaffected. */
|
||||||
|
.cal-detail { display: none; }
|
||||||
|
#cal.cal--detailed .cal-chip {
|
||||||
|
position: static;
|
||||||
|
inset: auto;
|
||||||
|
margin: 0.25rem;
|
||||||
|
min-height: 3rem;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
#cal.cal--detailed .cal-name {
|
||||||
|
white-space: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
#cal.cal--detailed .cal-detail {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
margin-top: 2px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.25;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock head %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="mb-4 flex flex-wrap items-center justify-between gap-3">
|
<div class="mb-4 flex flex-wrap items-center justify-between gap-3">
|
||||||
<h1 class="text-2xl font-bold">
|
<h1 class="text-2xl font-bold">
|
||||||
@@ -22,19 +53,32 @@
|
|||||||
|
|
||||||
{% if has_courts %}
|
{% if has_courts %}
|
||||||
<div class="mb-3 flex flex-wrap items-center justify-between gap-2">
|
<div class="mb-3 flex flex-wrap items-center justify-between gap-2">
|
||||||
<div class="join">
|
<div class="flex flex-wrap items-center gap-2">
|
||||||
<a href="{{ base_path }}?court={{ court_id }}&week={{ prev_week }}"
|
<div class="join">
|
||||||
class="btn btn-sm join-item">« {{ t(key="prev-week", lang=lang) }}</a>
|
<a href="{{ base_path }}?court={{ court_id }}&week={{ prev_week }}"
|
||||||
<a href="{{ base_path }}?court={{ court_id }}&week={{ this_week }}"
|
class="btn btn-sm join-item">« {{ t(key="prev-week", lang=lang) }}</a>
|
||||||
class="btn btn-sm join-item">{{ t(key="this-week", lang=lang) }}</a>
|
<a href="{{ base_path }}?court={{ court_id }}&week={{ this_week }}"
|
||||||
<a href="{{ base_path }}?court={{ court_id }}&week={{ next_week }}"
|
class="btn btn-sm join-item">{{ t(key="this-week", lang=lang) }}</a>
|
||||||
class="btn btn-sm join-item">{{ t(key="next-week", lang=lang) }} »</a>
|
<a href="{{ base_path }}?court={{ court_id }}&week={{ next_week }}"
|
||||||
|
class="btn btn-sm join-item">{{ t(key="next-week", lang=lang) }} »</a>
|
||||||
|
</div>
|
||||||
|
{% if is_admin %}
|
||||||
|
<button type="button" id="cal-detail-toggle" class="btn btn-sm gap-1" aria-pressed="false"
|
||||||
|
title="{{ t(key='view-details', lang=lang) }}">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||||
|
stroke="currentColor" class="h-4 w-4">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
d="M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0ZM3.75 12h.007v.008H3.75V12Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm-.375 5.25h.007v.008H3.75v-.008Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
|
||||||
|
</svg>
|
||||||
|
{{ t(key="view-details", lang=lang) }}
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm font-medium opacity-60">{{ court_name }} · {{ week_label }}</div>
|
<div class="text-sm font-medium opacity-60">{{ court_name }} · {{ week_label }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="overflow-x-auto rounded-lg border border-base-300 bg-base-100 shadow-sm">
|
<div class="overflow-x-auto rounded-lg border border-base-300 bg-base-100 shadow-sm">
|
||||||
<table class="w-full border-collapse text-sm">
|
<table id="cal" class="w-full border-collapse text-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-base-200">
|
<tr class="bg-base-200">
|
||||||
<th class="w-16 border border-base-300 p-2"></th>
|
<th class="w-16 border border-base-300 p-2"></th>
|
||||||
@@ -55,9 +99,16 @@
|
|||||||
{% if cell.booked %}
|
{% if cell.booked %}
|
||||||
{% if is_admin %}
|
{% if is_admin %}
|
||||||
<a href="/admin/booking/{{ cell.booking_id }}"
|
<a href="/admin/booking/{{ cell.booking_id }}"
|
||||||
class="absolute inset-1 flex items-center overflow-hidden rounded px-1.5 text-xs font-medium text-white shadow-sm transition hover:opacity-90"
|
class="cal-chip absolute inset-1 flex items-center overflow-hidden rounded px-1.5 text-xs font-medium text-white shadow-sm transition hover:opacity-90"
|
||||||
style="background-color: {{ cell.color }}">
|
style="background-color: {{ cell.color }}">
|
||||||
<span class="min-w-0 truncate">{{ cell.name }}</span>
|
<span class="cal-name min-w-0 truncate">{{ cell.name }}</span>
|
||||||
|
{% if cell.title or cell.contact or cell.note %}
|
||||||
|
<span class="cal-detail">
|
||||||
|
{%- if cell.title %}<span class="truncate opacity-95">{{ cell.title }}</span>{% endif -%}
|
||||||
|
{%- if cell.contact %}<span class="truncate opacity-80">{{ cell.contact }}</span>{% endif -%}
|
||||||
|
{%- if cell.note %}<span class="opacity-80">{{ cell.note }}</span>{% endif -%}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="absolute inset-1 flex items-center overflow-hidden rounded px-1.5 text-xs font-medium text-white shadow-sm"
|
<div class="absolute inset-1 flex items-center overflow-hidden rounded px-1.5 text-xs font-medium text-white shadow-sm"
|
||||||
@@ -88,3 +139,29 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{% if is_admin %}
|
||||||
|
<script>
|
||||||
|
// Detailed-view toggle for the admin calendar. The choice is remembered
|
||||||
|
// per browser; the public calendar never loads this script.
|
||||||
|
(function () {
|
||||||
|
var KEY = 'cal_detailed';
|
||||||
|
var tbl = document.getElementById('cal');
|
||||||
|
var btn = document.getElementById('cal-detail-toggle');
|
||||||
|
if (!tbl || !btn) return;
|
||||||
|
function apply(on) {
|
||||||
|
tbl.classList.toggle('cal--detailed', on);
|
||||||
|
btn.classList.toggle('btn-active', on);
|
||||||
|
btn.setAttribute('aria-pressed', on ? 'true' : 'false');
|
||||||
|
}
|
||||||
|
apply(localStorage.getItem(KEY) === '1');
|
||||||
|
btn.addEventListener('click', function () {
|
||||||
|
var on = !tbl.classList.contains('cal--detailed');
|
||||||
|
localStorage.setItem(KEY, on ? '1' : '0');
|
||||||
|
apply(on);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock js %}
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ pub struct Cell {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
/// Public-facing label shown on the calendar when set.
|
/// Public-facing label shown on the calendar when set.
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
/// Private — admin only. Shown in the dashboard's detailed view.
|
||||||
|
pub contact: String,
|
||||||
|
/// Private — admin only. Shown in the dashboard's detailed view.
|
||||||
|
pub note: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@@ -177,6 +181,8 @@ pub async fn build_calendar(
|
|||||||
booking_id: b.id,
|
booking_id: b.id,
|
||||||
name: b.name.clone(),
|
name: b.name.clone(),
|
||||||
title: b.title.clone().unwrap_or_default(),
|
title: b.title.clone().unwrap_or_default(),
|
||||||
|
contact: b.contact.clone().unwrap_or_default(),
|
||||||
|
note: b.note.clone().unwrap_or_default(),
|
||||||
},
|
},
|
||||||
None => Cell {
|
None => Cell {
|
||||||
date: iso,
|
date: iso,
|
||||||
@@ -186,6 +192,8 @@ pub async fn build_calendar(
|
|||||||
booking_id: 0,
|
booking_id: 0,
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
title: String::new(),
|
title: String::new(),
|
||||||
|
contact: String::new(),
|
||||||
|
note: String::new(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user