diff --git a/ht_booking/assets/i18n/en/main.ftl b/ht_booking/assets/i18n/en/main.ftl index 3857787..f50c45b 100644 --- a/ht_booking/assets/i18n/en/main.ftl +++ b/ht_booking/assets/i18n/en/main.ftl @@ -30,7 +30,8 @@ edit-booking = Edit Booking date = Date hour = Hour booking-color = Colour -booking-name = Name +booking-name = Name (private) +booking-title = Title (public) booking-contact = Contact booking-note = Note save = Save @@ -48,3 +49,6 @@ court-delete-error = Court name did not match — nothing was removed. theme-system = System theme-light = Light theme-dark = Dark +settings = Settings +settings-language = Language +settings-theme = Theme diff --git a/ht_booking/assets/i18n/sk/main.ftl b/ht_booking/assets/i18n/sk/main.ftl index e53c99a..63b4fde 100644 --- a/ht_booking/assets/i18n/sk/main.ftl +++ b/ht_booking/assets/i18n/sk/main.ftl @@ -30,7 +30,8 @@ edit-booking = Upraviť rezerváciu date = Dátum hour = Hodina booking-color = Farba -booking-name = Meno +booking-name = Meno (súkromné) +booking-title = Názov (verejný) booking-contact = Kontakt booking-note = Poznámka save = Uložiť @@ -48,3 +49,6 @@ court-delete-error = Názov kurtu sa nezhodoval — nič sa neodstránilo. theme-system = Systém theme-light = Svetlý theme-dark = Tmavý +settings = Nastavenia +settings-language = Jazyk +settings-theme = Téma diff --git a/ht_booking/assets/views/admin/booking_form.html b/ht_booking/assets/views/admin/booking_form.html index 77307a9..88064fc 100644 --- a/ht_booking/assets/views/admin/booking_form.html +++ b/ht_booking/assets/views/admin/booking_form.html @@ -41,6 +41,10 @@ +
+ + +
diff --git a/ht_booking/assets/views/base.html b/ht_booking/assets/views/base.html index 626bc14..da3a289 100644 --- a/ht_booking/assets/views/base.html +++ b/ht_booking/assets/views/base.html @@ -12,8 +12,11 @@ document.documentElement.setAttribute('data-theme', dark ? 'dark' : 'light'); } function highlightTheme(t) { - document.querySelectorAll('#theme-switch [data-theme-opt]').forEach(function (b) { - b.classList.toggle('btn-neutral', b.getAttribute('data-theme-opt') === t); + document.querySelectorAll('[data-theme-opt]').forEach(function (b) { + var on = b.getAttribute('data-theme-opt') === t; + b.classList.toggle('active', on); + var chk = b.querySelector('.opt-check'); + if (chk) chk.classList.toggle('hidden', !on); }); } function setTheme(t) { @@ -54,19 +57,96 @@ {% else %} {{ t(key="nav-admin", lang=lang) }} {% endif %} -
- - -
-
- - - + +
diff --git a/ht_booking/assets/views/calendar/week.html b/ht_booking/assets/views/calendar/week.html index 0462d0e..4b4b844 100644 --- a/ht_booking/assets/views/calendar/week.html +++ b/ht_booking/assets/views/calendar/week.html @@ -51,22 +51,28 @@ {{ row.hour_label }} {% for cell in row.cells %} - + {% if cell.booked %} {% if is_admin %} {{ cell.name }} + 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" + style="background-color: {{ cell.color }}"> + {{ cell.name }} + {% else %} -
{{ t(key="booked", lang=lang) }}
+
+ + {%- if cell.title %}{{ cell.title }}{% else %}{{ t(key="booked", lang=lang) }}{% endif -%} + +
{% endif %} {% else %} {% if is_admin %} + + class="absolute inset-0 flex items-center justify-center text-lg opacity-30 transition hover:bg-base-200 hover:opacity-100">+ {% else %} -
{{ t(key="free", lang=lang) }}
+
{{ t(key="free", lang=lang) }}
{% endif %} {% endif %} diff --git a/ht_booking/migration/src/lib.rs b/ht_booking/migration/src/lib.rs index a2c3d64..77d3856 100644 --- a/ht_booking/migration/src/lib.rs +++ b/ht_booking/migration/src/lib.rs @@ -5,6 +5,7 @@ mod m20220101_000001_users; mod m20260515_162423_courts; mod m20260515_170417_bookings; +mod m20260516_111747_add_title_to_bookings; pub struct Migrator; #[async_trait::async_trait] @@ -14,6 +15,7 @@ impl MigratorTrait for Migrator { Box::new(m20220101_000001_users::Migration), Box::new(m20260515_162423_courts::Migration), Box::new(m20260515_170417_bookings::Migration), + Box::new(m20260516_111747_add_title_to_bookings::Migration), // inject-above (do not remove this comment) ] } diff --git a/ht_booking/migration/src/m20260516_111747_add_title_to_bookings.rs b/ht_booking/migration/src/m20260516_111747_add_title_to_bookings.rs new file mode 100644 index 0000000..91dddb1 --- /dev/null +++ b/ht_booking/migration/src/m20260516_111747_add_title_to_bookings.rs @@ -0,0 +1,18 @@ +use loco_rs::schema::*; +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, m: &SchemaManager) -> Result<(), DbErr> { + add_column(m, "bookings", "title", ColType::StringNull).await?; + Ok(()) + } + + async fn down(&self, m: &SchemaManager) -> Result<(), DbErr> { + remove_column(m, "bookings", "title").await?; + Ok(()) + } +} diff --git a/ht_booking/src/controllers/admin.rs b/ht_booking/src/controllers/admin.rs index 6e9fc46..70a6056 100644 --- a/ht_booking/src/controllers/admin.rs +++ b/ht_booking/src/controllers/admin.rs @@ -301,6 +301,7 @@ pub async fn booking_new( "hour": q.hour.unwrap_or(FIRST_HOUR), "color": "#3b82f6", "name": "", + "title": "", "contact": "", "note": "", "hours": hour_options(), @@ -316,6 +317,7 @@ pub struct BookingForm { pub hour: i32, pub color: String, pub name: String, + pub title: Option, pub contact: Option, pub note: Option, } @@ -338,6 +340,7 @@ pub async fn booking_create( hour: Set(form.hour), color: Set(form.color), name: Set(form.name), + title: Set(form.title.filter(|s| !s.is_empty())), contact: Set(form.contact.filter(|s| !s.is_empty())), note: Set(form.note.filter(|s| !s.is_empty())), ..Default::default() @@ -381,6 +384,7 @@ pub async fn booking_edit( "hour": booking.hour, "color": booking.color, "name": booking.name, + "title": booking.title.unwrap_or_default(), "contact": booking.contact.unwrap_or_default(), "note": booking.note.unwrap_or_default(), "hours": hour_options(), @@ -407,6 +411,7 @@ pub async fn booking_update( active.hour = Set(form.hour); active.color = Set(form.color); active.name = Set(form.name); + active.title = Set(form.title.filter(|s| !s.is_empty())); active.contact = Set(form.contact.filter(|s| !s.is_empty())); active.note = Set(form.note.filter(|s| !s.is_empty())); active.update(&ctx.db).await?; diff --git a/ht_booking/src/controllers/calendar.rs b/ht_booking/src/controllers/calendar.rs index b652ed0..ccfc456 100644 --- a/ht_booking/src/controllers/calendar.rs +++ b/ht_booking/src/controllers/calendar.rs @@ -50,7 +50,10 @@ pub struct Cell { pub booked: bool, pub color: String, pub booking_id: i32, + /// Private — admin only. Never rendered on the public calendar. pub name: String, + /// Public-facing label shown on the calendar when set. + pub title: String, } #[derive(Debug, Serialize)] @@ -173,6 +176,7 @@ pub async fn build_calendar( color: b.color.clone(), booking_id: b.id, name: b.name.clone(), + title: b.title.clone().unwrap_or_default(), }, None => Cell { date: iso, @@ -181,6 +185,7 @@ pub async fn build_calendar( color: String::new(), booking_id: 0, name: String::new(), + title: String::new(), }, } }) diff --git a/ht_booking/src/models/_entities/bookings.rs b/ht_booking/src/models/_entities/bookings.rs index 366935b..5122c4b 100644 --- a/ht_booking/src/models/_entities/bookings.rs +++ b/ht_booking/src/models/_entities/bookings.rs @@ -18,6 +18,7 @@ pub struct Model { #[sea_orm(column_type = "Text", nullable)] pub note: Option, pub court_id: i32, + pub title: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]