xtablo-source/backend/templates/events.templ
2026-05-16 00:27:58 +02:00

167 lines
6.7 KiB
Text

package templates
import (
"backend/internal/db/sqlc"
"backend/internal/web/ui"
"github.com/google/uuid"
)
templ EventsTabFragment(tablo sqlc.Tablo, calendar EventsCalendar, csrfToken string) {
<div id="events-tab" class="space-y-6">
<div class="flex flex-wrap items-center justify-between gap-3">
<div>
<h2 class="text-xl font-semibold leading-snug text-slate-800">Events</h2>
<p class="text-sm text-slate-600">{ calendar.MonthLabel }</p>
</div>
<div class="flex flex-wrap items-center gap-2">
<a
href={ templ.SafeURL(EventMonthURL(tablo.ID, calendar.PrevMonth)) }
hx-get={ EventMonthURL(tablo.ID, calendar.PrevMonth) }
hx-target="#tab-content"
hx-swap="innerHTML"
hx-push-url={ EventMonthURL(tablo.ID, calendar.PrevMonth) }
class="ui-button ui-button-soft-neutral-md"
aria-label={ "Previous month: " + calendar.PrevMonth }
>Previous month</a>
<a
href={ templ.SafeURL(EventMonthURL(tablo.ID, calendar.NextMonth)) }
hx-get={ EventMonthURL(tablo.ID, calendar.NextMonth) }
hx-target="#tab-content"
hx-swap="innerHTML"
hx-push-url={ EventMonthURL(tablo.ID, calendar.NextMonth) }
class="ui-button ui-button-soft-neutral-md"
aria-label={ "Next month: " + calendar.NextMonth }
>Next month</a>
@ui.Button(ui.ButtonProps{
Label: "New event",
Variant: ui.ButtonVariantDefault,
Tone: ui.ButtonToneSolid,
Size: ui.SizeMD,
Type: "button",
Attrs: templ.Attributes{
"hx-get": EventNewURL(tablo.ID, calendar.Month),
"hx-target": "#event-form-slot",
"hx-swap": "innerHTML",
"aria-label": "New event",
},
})
</div>
</div>
<div id="event-form-slot"></div>
<div class="overflow-x-auto">
<div class="grid min-w-[680px] grid-cols-7 gap-px rounded border border-slate-200 bg-slate-200">
for _, label := range calendar.WeekdayLabs {
<div class="bg-slate-50 px-2 py-2 text-sm font-semibold text-slate-700">{ label }</div>
}
for _, day := range calendar.Days {
@EventDayCell(tablo.ID, calendar.Month, day)
}
</div>
</div>
</div>
}
templ EventDayCell(tabloID uuid.UUID, month string, day EventCalendarDay) {
<div
class="min-h-24 bg-white p-2"
if !day.InMonth {
class="min-h-24 bg-slate-50 p-2 text-slate-400"
}
>
<div class="flex items-start justify-between gap-2">
<span class="text-sm font-semibold">{ day.DayNumber }</span>
if day.InMonth {
<button
type="button"
class="text-xs text-slate-500 hover:text-slate-800"
hx-get={ EventNewForDayURL(tabloID, day.Date, month) }
hx-target="#event-form-slot"
hx-swap="innerHTML"
aria-label={ "Create event on " + day.Date }
>+</button>
}
</div>
if len(day.Events) > 0 {
<div class="mt-2 space-y-1">
for _, event := range EventDayEvents(day.Events) {
<button
type="button"
class="block w-full truncate rounded border border-slate-200 bg-slate-50 px-2 py-1 text-left text-sm text-slate-800 hover:border-slate-400"
hx-get={ "/tablos/" + tabloID.String() + "/events/" + event.ID.String() + "/edit?month=" + month }
hx-target="#event-form-slot"
hx-swap="innerHTML"
aria-label={ "Edit event: " + event.Title }
>{ event.Title }</button>
}
if day.MoreCount > 0 {
<p class="text-xs text-slate-500">{ EventMoreLabel(day.MoreCount) }</p>
}
</div>
}
</div>
}
templ EventCreateFormFragment(tabloID uuid.UUID, form EventCreateForm, errs EventCreateErrors, csrfToken string, month string) {
<form
method="POST"
action={ templ.SafeURL(EventPostURL(tabloID, month)) }
hx-post={ EventPostURL(tabloID, month) }
hx-target="#events-tab"
hx-swap="outerHTML"
class="rounded border border-slate-200 bg-white p-3 shadow-sm space-y-3"
>
@ui.CSRFField(csrfToken)
@GeneralError(errs.General)
<div>
<label for="event-title" class="block text-sm font-medium text-slate-700">Title</label>
<input id="event-title" type="text" name="title" value={ form.Title } maxlength="255" required class="mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm placeholder-slate-400 focus:border-slate-500 focus:outline-none"/>
@FieldError(errs.Title)
</div>
<div class="grid gap-3 sm:grid-cols-3">
<div>
<label for="event-date" class="block text-sm font-medium text-slate-700">Date</label>
<input id="event-date" type="date" name="event_date" value={ form.EventDate } required class="mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm focus:border-slate-500 focus:outline-none"/>
@FieldError(errs.EventDate)
</div>
<div>
<label for="event-start-time" class="block text-sm font-medium text-slate-700">Start time</label>
<input id="event-start-time" type="time" name="start_time" value={ form.StartTime } required class="mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm focus:border-slate-500 focus:outline-none"/>
@FieldError(errs.StartTime)
</div>
<div>
<label for="event-end-time" class="block text-sm font-medium text-slate-700">End time <span class="text-slate-400">(optional)</span></label>
<input id="event-end-time" type="time" name="end_time" value={ form.EndTime } class="mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm focus:border-slate-500 focus:outline-none"/>
@FieldError(errs.EndTime)
</div>
</div>
<div>
<label for="event-location" class="block text-sm font-medium text-slate-700">Location <span class="text-slate-400">(optional)</span></label>
<input id="event-location" type="text" name="location" value={ form.Location } maxlength="255" class="mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm placeholder-slate-400 focus:border-slate-500 focus:outline-none"/>
</div>
<div>
<label for="event-description" class="block text-sm font-medium text-slate-700">Description <span class="text-slate-400">(optional)</span></label>
<textarea id="event-description" name="description" rows="3" class="mt-1 block w-full rounded border border-slate-300 px-3 py-2 text-sm placeholder-slate-400 focus:border-slate-500 focus:outline-none">{ form.Description }</textarea>
</div>
<div class="flex items-center gap-2">
@ui.Button(ui.ButtonProps{
Label: "Create event",
Variant: ui.ButtonVariantDefault,
Tone: ui.ButtonToneSolid,
Size: ui.SizeMD,
Type: "submit",
})
@ui.Button(ui.ButtonProps{
Label: "Close form",
Variant: ui.ButtonVariantNeutral,
Tone: ui.ButtonToneSoft,
Size: ui.SizeMD,
Type: "button",
Attrs: templ.Attributes{
"hx-get": "/tablos/" + tabloID.String() + "/events/cancel-new",
"hx-target": "#event-form-slot",
"hx-swap": "innerHTML",
},
})
</div>
</form>
}