{% extends "admin/base_site.html" %}
{% load i18n static admin_extras tz %}

{% block extrastyle %}
  {{ block.super }}
  <link rel="stylesheet" href="{% static 'admin/css/dashboard.css' %}">
  <style>
    .dashboard {
        display: flex;
        flex-wrap: wrap;
        gap: 1rem;
        box-sizing: border-box;
    }
    #admin-home-header {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        align-items: center;
        gap: 1rem;
        margin-bottom: 1.25rem;
    }
    #admin-home-header h1 {
        margin: 0;
    }
    .admin-home-net-message {
        display: flex;
        align-items: center;
        align-content: right;
        gap: 0.75rem;
        padding: 0.35rem 0.75rem;
        border-radius: 6px;
        background: var(--darkened-bg);
        color: var(--body-fg);
        min-height: 2.25rem;
        box-sizing: border-box;
    }
    .admin-home-net-message__label {
        font-size: 0.75rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        color: var(--body-quiet-color);
        white-space: nowrap;
    }
    .admin-home-net-message__link {
        color: inherit;
        text-decoration: none;
    }
    .admin-home-net-message__link:focus-visible {
        outline: 2px solid var(--body-fg);
        outline-offset: 2px;
    }
    .admin-home-net-message__content {
        font-family: var(
            --font-family-monospace,
            SFMono-Regular,
            Menlo,
            Monaco,
            Consolas,
            'Liberation Mono',
            'Courier New',
            monospace
        );
        font-size: 0.875rem;
        white-space: pre-wrap;
        word-break: break-word;
        flex: 1 1 auto;
        color: inherit;
    }
    .admin-home-net-message__content--empty {
        color: var(--body-quiet-color);
    }
    .admin-home-actions {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 8px;
        flex-wrap: wrap;
    }
    .admin-dashboard-warning {
        margin-bottom: 1.25rem;
        padding: 0.9rem 1rem;
        border-radius: 8px;
        border: 1px solid rgba(240, 129, 15, 0.35);
        background: rgba(240, 129, 15, 0.12);
        color: inherit;
        line-height: 1.5;
    }
    .admin-dashboard-warning__title {
        margin: 0 0 0.35rem;
        font-size: 1rem;
        font-weight: 600;
    }
    .admin-dashboard-warning__body {
        margin: 0;
    }
    .admin-dashboard-warning__body a {
        color: inherit;
        font-weight: 600;
        text-decoration: underline;
    }
    [data-theme="dark"] .admin-dashboard-warning {
        border-color: rgba(240, 129, 15, 0.5);
        background: rgba(240, 129, 15, 0.2);
    }
    @media (max-width: 992px) {
        #admin-home-header {
            grid-template-columns: 1fr;
            gap: 0.75rem;
        }
        .admin-home-actions {
            justify-content: flex-start;
        }
        .admin-home-net-message {
            width: 100%;
        }
    }
    .dashboard-main {
        flex: 1 1 calc(70% - 0.5rem);
        min-width: 300px;
        max-width: 100%;
        box-sizing: border-box;
    }
    .dashboard-side {
        flex: 1 1 calc(30% - 0.5rem);
        min-width: 300px;
        max-width: 100%;
        box-sizing: border-box;
        background: var(--darkened-bg);
        padding-top: 12px;
        padding-left: 12px;
        padding-right: 12px;
    }
    .dashboard-side .module {
        background: none;
    }
    .dashboard-side .module h2 {
        background: none;
        padding-left: 16px;
        padding-right: 16px;
        padding-top: 0;
        padding-bottom: 0;
        margin-bottom: 16px;
        border-bottom: 1px solid var(--hairline-color);
        font-size: 1.125rem;
        color: var(--body-fg);
    }
    .dashboard-side h3 {
        color: var(--body-quiet-color);
        padding: 0 16px;
        margin: 0 0 16px;
    }
    .dashboard-side p {
        padding: 0 16px;
    }
    .dashboard-side .actionlist {
        padding: 0;
        margin: 16px;
    }
    .dashboard-side .actionlist li {
        line-height: 1.2;
        margin-bottom: 10px;
        padding-left: 18px;
    }
    #google-calendar-module {
        margin-bottom: 16px;
    }
    #google-calendar-module .calendar-event-list {
        list-style: none;
        padding: 0 16px 8px;
        margin: 0;
        display: flex;
        flex-direction: column;
        gap: 12px;
    }
    #google-calendar-module .calendar-event {
        display: flex;
        flex-direction: column;
        gap: 4px;
    }
    #google-calendar-module .calendar-event-title {
        font-weight: 600;
        text-decoration: none;
        color: inherit;
    }
    #google-calendar-module .calendar-event-title:focus,
    #google-calendar-module .calendar-event-title:hover {
        text-decoration: underline;
    }
    #google-calendar-module .calendar-event-time,
    #google-calendar-module .calendar-event-location {
        padding: 0;
        margin: 0;
        color: var(--body-quiet-color);
    }
    #google-calendar-module .calendar-empty,
    #google-calendar-module .calendar-link {
        padding: 0 16px 16px;
        margin: 0;
    }
    #google-calendar-module .calendar-link a {
        color: var(--body-quiet-color);
        text-decoration: none;
        font-weight: 600;
    }
    #google-calendar-module .calendar-link a:focus,
    #google-calendar-module .calendar-link a:hover {
        text-decoration: underline;
        color: var(--link-fg);
    }
    .dashboard-side .actionlist .recent-action-object {
        display: inline-flex;
        align-items: baseline;
        gap: 4px;
    }
    .dashboard-side .actionlist .recent-action-object .recent-action-pk {
        font-size: 0.85em;
        color: var(--body-quiet-color);
    }
    .dashboard-side .actionlist .recent-action-meta {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 12px;
        margin-top: 4px;
    }
    .dashboard-side .actionlist .recent-action-model {
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .dashboard-side .actionlist .recent-action-timestamp {
        flex: 0 0 auto;
        white-space: nowrap;
        font-variant-numeric: tabular-nums;
    }
    #release-manager-module {
        margin-bottom: 16px;
    }
    #release-manager-module .release-manager-task-list {
        list-style: none;
        margin: 0;
        padding: 0 16px 12px;
        display: flex;
        flex-direction: column;
        gap: 12px;
    }
    #release-manager-module .release-manager-module__empty {
        margin: 0;
        padding: 0 16px 16px;
        color: var(--body-quiet-color);
    }
    #release-manager-module .release-manager-task {
        background: var(--body-bg);
        border: 1px solid var(--hairline-color);
        border-radius: 10px;
        padding: 12px 14px;
        display: flex;
        flex-direction: column;
        gap: 6px;
        color: var(--body-fg);
        box-shadow: 0 6px 18px rgba(15, 23, 42, 0.05);
    }
    [data-theme="dark"] #release-manager-module .release-manager-task {
        background: rgba(15, 23, 42, 0.7);
        border-color: rgba(148, 163, 184, 0.35);
        box-shadow: none;
    }
    #release-manager-module .release-manager-task__title {
        font-weight: 600;
        font-size: 0.95rem;
        display: flex;
        align-items: baseline;
        gap: 6px;
    }
    #release-manager-module .release-manager-task__link {
        color: inherit;
        text-decoration: none;
    }
    #release-manager-module .release-manager-task__link:hover,
    #release-manager-module .release-manager-task__link:focus {
        text-decoration: underline;
        color: var(--link-fg);
    }
    #release-manager-module .release-manager-task__meta {
        margin: 0;
        font-size: 0.8rem;
        color: var(--body-quiet-color);
        display: flex;
        gap: 6px;
        flex-wrap: wrap;
    }
    #release-manager-module .release-manager-task__label {
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.06em;
    }
    #release-manager-module .release-manager-task__details {
        margin: 0;
        color: var(--body-quiet-color);
    }
    #release-manager-module .release-manager-task__actions {
        margin: 0;
        display: flex;
        flex-wrap: wrap;
        gap: 12px;
    }
    #release-manager-module .release-manager-task__action {
        color: var(--link-fg);
        font-weight: 600;
        text-decoration: none;
        word-break: break-word;
    }
    #release-manager-module .release-manager-task__action:hover,
    #release-manager-module .release-manager-task__action:focus {
        text-decoration: underline;
    }
    #release-manager-module .release-manager-task__action--secondary {
        color: var(--body-quiet-color);
    }
    #release-manager-module .release-manager-task__action--secondary:hover,
    #release-manager-module .release-manager-task__action--secondary:focus {
        color: var(--link-fg);
    }
    #release-manager-module .release-manager-module__footer {
        padding: 0 16px 16px;
        margin: 0;
    }
    #release-manager-module .release-manager-module__footer a {
        color: var(--body-quiet-color);
        font-weight: 600;
        text-decoration: none;
    }
    #release-manager-module .release-manager-module__footer a:hover,
    #release-manager-module .release-manager-module__footer a:focus {
        text-decoration: underline;
        color: var(--link-fg);
    }
    /* Override Django's dashboard defaults so the flex layout works */
    .dashboard #content {
        width: auto;
        box-sizing: border-box;
    }
    #content-main,
    #recent-boxes {
        float: none;
        width: auto;
    }
    .dashboard-main td.actions {
        text-align: right;
        white-space: nowrap;
    }
    .dashboard-main td.actions .actionlink {
        display: inline;
        margin-left: 0;
    }
    .dashboard-main .module table {
        width: 100%;
    }
    .dashboard-main .app-caption {
        width: 100%;
        box-sizing: border-box;
        padding: 6px 8px;
    }
    .app-caption-inner {
        display: flex;
        align-items: center;
        gap: 8px;
    }
    .app-caption-inner .section {
        flex: 1 1 auto;
    }
    .app-collapse-toggle {
        border: none;
        background: transparent;
        color: inherit;
        padding: 2px;
        margin-left: auto;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 28px;
        height: 28px;
        cursor: pointer;
    }
    .app-collapse-toggle:focus-visible {
        outline: 2px solid var(--button-bg, #0d6efd);
        outline-offset: 2px;
    }
    .app-collapse-toggle::before {
        content: '▾';
        font-size: 1rem;
        line-height: 1;
        transition: transform 120ms ease-in-out;
    }
    .module.is-collapsed .app-collapse-toggle::before {
        transform: rotate(90deg);
    }
    .dashboard-main .module.is-collapsed tbody {
        display: none;
    }
    .dashboard-main .lead-open-badge,
    .dashboard-main .node-count-badge {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        margin-left: 8px;
        padding: 0.125rem 0.5rem;
        min-width: 1.5rem;
        font-size: 0.75rem;
        font-weight: 600;
        line-height: 1;
        border-radius: 999px;
        background-color: var(--button-bg, #0d6efd);
        color: var(--button-fg, #fff);
    }
    .dashboard-main .rfid-release-stats {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        margin-left: 8px;
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--body-quiet-color);
    }
    .dashboard-main .rfid-release-badge,
    .dashboard-main .charger-availability-badge {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        margin-left: 8px;
        padding: 0.125rem 0.5rem;
        min-width: 1.5rem;
        font-size: 0.75rem;
        font-weight: 600;
        line-height: 1;
        border-radius: 999px;
        background-color: var(--button-bg, #0d6efd);
        color: var(--button-fg, #fff);
        border: none;
    }
    .dashboard-main .model-rule-status {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        margin-left: 8px;
        font-size: 0.75rem;
        font-weight: 600;
    }
    .dashboard-main .model-rule-status__icon {
        font-size: 0.85rem;
        line-height: 1;
    }
    .dashboard-main .model-rule-status--success {
        color: var(--success-fg, #1e7f47);
    }
    .dashboard-main .model-rule-status--error {
        color: var(--error-fg, #b42318);
    }
    .dashboard-main .rfid-release-separator {
        font-weight: 700;
        color: var(--body-quiet-color);
    }
    .dashboard-main .app-caption .section {
        display: block;
        width: 100%;
    }
    #viewhistory-mini-module {
        margin-top: 16px;
    }
    #viewhistory-mini-module .chart-wrapper {
        position: relative;
        padding: 0 16px 16px;
    }
    #viewhistory-mini-module canvas {
        display: block;
        width: 100%;
        height: 180px;
    }
    #viewhistory-mini-empty {
        padding: 0 16px;
        margin: 0;
        color: var(--body-quiet-color);
    }
    #viewhistory-mini-module .chart-link {
        padding: 0 16px 16px;
        margin: 0;
    }

    @media (max-width: 640px) {
        .dashboard {
            flex-direction: column;
        }

        .dashboard-main,
        .dashboard-side {
            min-width: 0;
        }

        .dashboard-main .module table {
            width: 100%;
            border-collapse: separate;
            border-spacing: 0;
        }

        .dashboard-main .module table thead {
            display: none;
        }

        .dashboard-main .module tbody {
            display: block;
        }

        .dashboard-main .module tbody tr {
            display: flex;
            flex-direction: column;
            gap: 12px;
            padding: 12px 16px;
            margin: 0 0 12px;
            border: 1px solid var(--hairline-color);
            border-radius: 12px;
            background: var(--body-bg);
        }

        .dashboard-main .module tbody tr:last-child {
            margin-bottom: 0;
        }

        .dashboard-main .module th[scope="row"] {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 0;
            margin: 0;
        }

        .dashboard-main .module th[scope="row"] .favorite-star {
            margin-right: 8px;
        }

        .dashboard-main .module td {
            display: flex;
            flex-direction: column;
            gap: 4px;
            padding: 0;
            margin: 0;
        }

        .dashboard-main .module td.actions {
            text-align: left;
        }

        .dashboard-main .module td[data-label]::before {
            content: attr(data-label);
            font-size: 0.75rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.08em;
            color: var(--body-quiet-color);
        }

        .dashboard-main .module td.change-link-cell {
            display: none;
        }

        .dashboard-main .module td.change-link-cell.change-link-cell--view-only {
            display: flex;
        }

        .dashboard-side {
            padding-left: 0;
            padding-right: 0;
        }
    }
  </style>
{% endblock %}

{% block coltype %}colM{% endblock %}

{% block bodyclass %}{{ block.super }} dashboard{% endblock %}

{% block content_title %}
{% admin_can_send_email as admin_email_configured %}
{% if user.is_superuser and not admin_email_configured %}
  {% url 'admin:teams_emailoutbox_add' as email_outbox_add_url %}
  <div class="admin-dashboard-warning" role="alert" aria-live="polite">
    <p class="admin-dashboard-warning__title">{% translate "Email delivery is not configured." %}</p>
    <p class="admin-dashboard-warning__body">
      {% blocktrans trimmed with link_start='<a href="'|add:email_outbox_add_url|add:'">'|safe link_end='</a>'|safe %}
        Configure Django email settings or {{ link_start }}add an Email Outbox{{ link_end }} to restore outbound email for this node.
      {% endblocktrans %}
    </p>
  </div>
{% endif %}
{% last_net_message as admin_last_net_message %}
<div id="admin-home-header">
  <h1>Home</h1>
  <div class="admin-home-net-message" role="status" aria-live="polite">
    <a class="admin-home-net-message__label admin-home-net-message__link" href="{% url 'admin:nodes_netmessage_send' %}">{% translate 'Net message' %}</a>
    <span class="admin-home-net-message__content{% if not admin_last_net_message.has_content %} admin-home-net-message__content--empty{% endif %}" title="{% if admin_last_net_message.has_content %}{{ admin_last_net_message.text }}{% else %}{% translate 'No net messages available' %}{% endif %}">{% if admin_last_net_message.has_content %}{{ admin_last_net_message.text }}{% else %}{% translate 'No net messages available' %}{% endif %}</span>
  </div>
  <div class="admin-home-actions">
    <a class="button" href="{% url 'admin:seed_data' %}">{% translate 'Seed Data' %}</a>
    <a class="button" href="{% url 'admin:user_data' %}">{% translate 'User Data' %}</a>
    <a class="button" href="{% url 'admin:system' %}">{% translate 'System Reports' %}</a>
    <a class="button" href="{% url 'admin:environment' %}">{% translate 'Environment' %}</a>
    <a class="button" href="{% url 'admin:config' %}">{% translate 'Django Config' %}</a>
    <a class="button" href="{% url 'admin:sigil_builder' %}">{% translate 'Sigil Builder' %}</a>
    {% if user.is_superuser %}
      <a class="button" href="{% url 'admin:run_command' %}">{% translate 'Run Command' %}</a>
    {% endif %}
    <a class="button" href="{% url 'admin:log_viewer' %}">{% translate 'Log Viewer' %}</a>
  </div>
</div>
{% endblock %}

{% block nav-breadcrumbs %}{% endblock %}
{% block nav-sidebar %}{% endblock %}

{% block content %}
<div class="dashboard" id="admin-dashboard">
  <div id="content-main" class="dashboard-main">
    {% include "admin/dashboard_app_list.html" with app_list=app_list %}
  </div>
<div class="dashboard-side" id="recent-boxes">
    {% user_google_calendar as google_calendar %}
    {% if google_calendar %}
    <div class="module" id="google-calendar-module">
        <h2>{{ google_calendar.title }}</h2>
        {% if google_calendar.events %}
        <ul class="calendar-event-list">
            {% for event in google_calendar.events %}
            <li class="calendar-event">
                {% if event.html_link %}
                <a class="calendar-event-title" href="{{ event.html_link }}" target="_blank" rel="noopener noreferrer">
                    {{ event.summary|default:_('Untitled event') }}
                </a>
                {% else %}
                <span class="calendar-event-title">{{ event.summary|default:_('Untitled event') }}</span>
                {% endif %}
                <p class="calendar-event-time">
                    {% if event.all_day %}
                        {{ event.start|localtime|date:"DATE_FORMAT" }}
                    {% else %}
                        {{ event.start|localtime|date:"SHORT_DATETIME_FORMAT" }}
                    {% endif %}
                </p>
                {% if event.location %}
                <p class="calendar-event-location">{{ event.location }}</p>
                {% endif %}
            </li>
            {% endfor %}
        </ul>
        {% else %}
        <p class="calendar-empty">{% translate 'No upcoming events' %}</p>
        {% endif %}
        {% if google_calendar.calendar_url %}
        <p class="calendar-link"><a href="{{ google_calendar.calendar_url }}" target="_blank" rel="noopener noreferrer">{% translate 'Open full calendar' %}</a></p>
        {% endif %}
    </div>
    {% endif %}
    <div class="module" id="viewhistory-mini-module">
        <h2>{% translate 'Public site traffic' %}</h2>
        <div class="chart-wrapper">
            <canvas id="viewhistory-mini-chart" role="img" aria-label="{% translate 'Mini chart of public visits' %}" height="160"></canvas>
            <p id="viewhistory-mini-empty" class="quiet" hidden>{% translate 'No visit data yet.' %}</p>
        </div>
        <p class="chart-link"><a id="viewhistory-mini-link" href="{% url 'admin:pages_viewhistory_traffic_graph' %}">{% translate 'Open full report' %}</a></p>
    </div>
    <div class="module" id="recent-actions-module">
        <h2>{% translate 'Recent actions' %}</h2>
        <h3>{% translate 'My actions' %}</h3>
            {% load log %}
            {% get_admin_log 10 as admin_log for_user user %}
            {% if not admin_log %}
            <p>{% translate 'None available' %}</p>
            {% else %}
            <ul class="actionlist">
            {% for entry in admin_log %}
            <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %} changelink{% endif %}{% if entry.is_deletion %} deletelink{% endif %}">
                <span class="visually-hidden">{% if entry.is_addition %}{% translate 'Added:' %}{% elif entry.is_change %}{% translate 'Changed:' %}{% elif entry.is_deletion %}{% translate 'Deleted:' %}{% endif %}</span>
                {% if entry.is_deletion or not entry.get_admin_url %}
                    <span class="recent-action-object">
                        {{ entry.object_repr }}
                        {% if entry.object_id %}
                            <span class="recent-action-pk">({{ entry.object_id }})</span>
                        {% endif %}
                    </span>
                {% else %}
                    <a class="recent-action-object" href="{{ entry.get_admin_url }}">
                        {{ entry.object_repr }}
                        {% if entry.object_id %}
                            <span class="recent-action-pk">({{ entry.object_id }})</span>
                        {% endif %}
                    </a>
                {% endif %}
                <div class="recent-action-meta mini quiet">
                    {% if entry.content_type %}
                        <span class="recent-action-model">{% filter capfirst %}{{ entry.content_type.name }}{% endfilter %}</span>
                    {% else %}
                        <span class="recent-action-model">{% translate 'Unknown content' %}</span>
                    {% endif %}
                    {% if entry.action_time %}
                        <time class="recent-action-timestamp" datetime="{{ entry.action_time|date:'c' }}">{{ entry.action_time|localtime|date:"SHORT_DATETIME_FORMAT" }}</time>
                    {% endif %}
                </div>
            </li>
            {% endfor %}
            </ul>
            {% endif %}
    </div>
</div>
</div>
{% endblock %}

{% block sidebar %}{% endblock %}

{% block extrahead %}
  {{ block.super }}
  <script>
    window.addEventListener('DOMContentLoaded', () => {
      const canvas = document.getElementById('viewhistory-mini-chart');
      const emptyLabel = document.getElementById('viewhistory-mini-empty');
      if (!canvas) return;

      const chartJsUrl = "{% static 'core/vendor/chart.umd.min.js' %}";

      const ensureChartJs = () => {
        if (window.Chart) {
          return Promise.resolve(window.Chart);
        }

        const waitForChart = (resolve) => {
          if (window.Chart) {
            resolve(window.Chart);
            return true;
          }
          return false;
        };

        return new Promise((resolve) => {
          const existing = document.querySelector('script[data-chartjs]');
          if (existing) {
            if (existing.dataset.chartjsState === 'error') {
              resolve(null);
              return;
            }

            if (waitForChart(resolve)) {
              return;
            }

            existing.addEventListener(
              'load',
              () => {
                existing.dataset.chartjsState = 'loaded';
                resolve(window.Chart || null);
              },
              { once: true },
            );
            existing.addEventListener(
              'error',
              () => {
                existing.dataset.chartjsState = 'error';
                resolve(null);
              },
              { once: true },
            );

            if (existing.readyState === 'complete') {
              waitForChart(resolve);
            }
            return;
          }

          const script = document.createElement('script');
          script.src = chartJsUrl;
          script.async = true;
          script.dataset.chartjs = 'true';
          script.dataset.chartjsState = 'loading';
          script.addEventListener(
            'load',
            () => {
              script.dataset.chartjsState = 'loaded';
              resolve(window.Chart || null);
            },
            { once: true },
          );
          script.addEventListener(
            'error',
            () => {
              script.dataset.chartjsState = 'error';
              resolve(null);
            },
            { once: true },
          );
          document.head.appendChild(script);
        });
      };

      const chartDataUrl = new URL(
        '{% url "admin:pages_viewhistory_traffic_data" %}',
        window.location,
      );
      chartDataUrl.searchParams.set('days', '7');

      const fetchData = () =>
        fetch(chartDataUrl.toString(), {
          headers: { Accept: 'application/json' },
        }).then((response) => (response.ok ? response.json() : Promise.reject()));

      ensureChartJs()
        .then((Chart) => {
          if (!Chart) {
            throw new Error('chartjs');
          }
          return fetchData().then((data) => ({ Chart, data }));
        })
        .then(({ Chart, data }) => {
          if (!data || !Array.isArray(data.datasets) || !data.datasets.length) {
            canvas.hidden = true;
            if (emptyLabel) {
              emptyLabel.hidden = false;
              emptyLabel.textContent = '{% translate "No visit data yet." %}';
            }
            return;
          }

          if (emptyLabel) {
            emptyLabel.hidden = true;
          }
          canvas.hidden = false;
          const context = canvas.getContext('2d');
          new Chart(context, {
            type: 'line',
            data: {
              labels: data.labels,
              datasets: data.datasets.map((dataset) => ({
                ...dataset,
                pointRadius: 0,
                pointHoverRadius: 3,
                borderWidth: 2,
              })),
            },
            options: {
              animation: false,
              responsive: true,
              maintainAspectRatio: false,
              plugins: {
                legend: { display: false },
                tooltip: {
                  mode: 'nearest',
                  intersect: false,
                },
              },
              elements: {
                line: { tension: 0.3 },
              },
              scales: {
                x: { display: false },
                y: { display: false, beginAtZero: true },
              },
            },
          });
        })
        .catch(() => {
          canvas.hidden = true;
          if (emptyLabel) {
            emptyLabel.hidden = false;
            emptyLabel.textContent = '{% translate "Unable to load visit data at this time." %}';
          }
        });
    });
  </script>
  <script>
    (function () {
      const storageKey = 'adminDashboardCollapsedSections';

      const loadState = () => {
        try {
          const raw = window.localStorage.getItem(storageKey);
          if (!raw) {
            return {};
          }
          const parsed = JSON.parse(raw);
          if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
            return parsed;
          }
        } catch (error) {
          /* ignore localStorage errors */
        }
        return {};
      };

      const saveState = (state) => {
        try {
          window.localStorage.setItem(storageKey, JSON.stringify(state));
        } catch (error) {
          /* ignore persistence errors */
        }
      };

      document.addEventListener('DOMContentLoaded', () => {
        const toggles = document.querySelectorAll('.app-collapse-toggle');
        if (!toggles.length) {
          return;
        }

        const collapsedState = loadState();

        toggles.forEach((button) => {
          const module = button.closest('.module[data-app-label]');
          const appLabel = button.dataset.appLabel;
          const targetId = button.getAttribute('aria-controls');
          const target = targetId ? document.getElementById(targetId) : null;

          if (!module || !target || !appLabel) {
            return;
          }

          const isCollapsed = collapsedState[appLabel] === true;
          module.classList.toggle('is-collapsed', isCollapsed);
          button.setAttribute('aria-expanded', String(!isCollapsed));
          target.hidden = isCollapsed;

          button.addEventListener('click', () => {
            const nowCollapsed = module.classList.toggle('is-collapsed');
            button.setAttribute('aria-expanded', String(!nowCollapsed));
            target.hidden = nowCollapsed;

            if (nowCollapsed) {
              collapsedState[appLabel] = true;
            } else {
              delete collapsedState[appLabel];
            }

            saveState(collapsedState);
          });
        });
      });
    })();
  </script>
{% endblock %}
