{% load i18n %} {% comment %} calendar_grid.html — CSS Grid-based scheduling calendar. Context: calendar — CalendarGridData instance (codex_django.cabinet.types.CalendarGridData) Layout: Columns = calendar.cols (masters, rooms, days — anything) Rows = calendar.rows (time slots — "8:00", "8:30", ...) Events = calendar.events (CalendarSlot: col, row, span, title, color, url) Backend computes col/row/span; template only renders. Click on empty slot → HTMX GET new_event_url?col=N&row=N → opens modal. Click on event → HTMX GET event.url → opens modal. Usage: {% include "cabinet/components/calendar_grid.html" with calendar=calendar %} {% include "cabinet/includes/_modal_base.html" %} {% endcomment %} {% with col_count=calendar.cols|length row_count=calendar.rows|length %}
{# Header: Navigation Controls #}
{% if calendar.prev_url %} {% endif %}
{% if calendar.next_url %} {% endif %} {% if calendar.today_url %} {% trans "Today" %} {% endif %}
{% block calendar_controls %}{% endblock %} {% if calendar.new_event_url %} {% trans "New booking" %} {% endif %}
{# Column headers #}
{% for col in calendar.cols %}
{% if col.name %}
{% if col.avatar %}
{% if "/" in col.avatar %}{% else %}{{ col.avatar }}{% endif %}
{% endif %}
{{ col.name }}
{% if col.info %}
{{ col.info }}
{% endif %}
{% else %} {{ col }} {% endif %}
{% endfor %}
{# Scrollable area #}
{# Background cells: time labels + empty slot cells #} {% for slot in calendar.rows %}
{% if slot.hour %} {% if slot.min == "00" or not slot.min %} {{ slot.hour }} {% else %} {{ slot.min }} {% endif %} {% else %} {{ slot }} {% endif %}
{% for col in calendar.cols %} {% with col_idx=forloop.counter row_idx=forloop.parentloop.counter %}
{% endwith %} {% endfor %} {% endfor %} {# Events overlay #} {% for event in calendar.events %}
{{ event.title }}
{{ event.subtitle }}
{% if event.note %}
"{{ event.note|truncatechars:100 }}"
{% endif %} {% for tag in event.details %} {{ tag.text }} {% endfor %}
{% endfor %}
{# /.cab-calendar__grid #}
{# /.cab-calendar__scroll #}
{# /.cab-calendar #} {% endwith %}