- Modello Tag con nome e colore, M2M su Conversazione - Modello Appuntamento con luogo, note, partecipanti, link a Conversazione - @menzioni nei commenti e aggiornamenti: @username → link al profilo - Autocomplete JS per @menzioni nelle textarea - Auto-data conversazioni (default=now) - CRUD completo appuntamenti con permessi autore - Appuntamenti in agenda, dashboard, dettaglio conversazione - Crea riunione direttamente da una conversazione (pre-compila titolo e partecipanti) - Admin: Tag, Appuntamento registrati
189 lines
9.5 KiB
HTML
189 lines
9.5 KiB
HTML
{% extends "diario/base.html" %}
|
||
{% load custom_filters %}
|
||
{% block title %}Agenda – Olimpic Nastri{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="row justify-content-center">
|
||
<div class="col-lg-9">
|
||
|
||
<div class="d-flex justify-content-between align-items-center mb-4 fade-in">
|
||
<div>
|
||
<p class="section-title mb-0">Agenda</p>
|
||
<small class="text-muted">Panoramica di scadenze e appuntamenti</small>
|
||
</div>
|
||
<div class="d-flex gap-2">
|
||
<a href="{% url 'appuntamento_nuovo' %}" class="btn btn-sm btn-outline-warning">
|
||
<i class="bi bi-plus-lg me-1"></i>Appuntamento
|
||
</a>
|
||
<a href="{% url 'obiettivo_nuovo' %}" class="btn btn-sm btn-outline-primary">
|
||
<i class="bi bi-plus-lg me-1"></i>Obiettivo
|
||
</a>
|
||
<a href="{% url 'conversazione_nuova' %}" class="btn btn-sm btn-primary">
|
||
<i class="bi bi-plus-lg me-1"></i>Conversazione
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── Prossimi eventi ── -->
|
||
<div class="card mb-4 fade-in">
|
||
<div class="card-header-accent d-flex align-items-center">
|
||
<i class="bi bi-arrow-right-circle me-2"></i>
|
||
<span>Prossimi eventi</span>
|
||
<span class="badge bg-primary bg-opacity-10 text-primary ms-2">{{ eventi_futuri|length }}</span>
|
||
</div>
|
||
<div class="p-0">
|
||
{% for ev in eventi_futuri %}
|
||
<div class="d-flex align-items-center gap-3 px-4 py-3 {% if not forloop.last %}border-bottom{% endif %} agenda-row">
|
||
<!-- Data -->
|
||
<div class="agenda-date text-center flex-shrink-0">
|
||
<div class="agenda-day">{{ ev.data|date:"d" }}</div>
|
||
<div class="agenda-month">{{ ev.data|date:"M" }}</div>
|
||
</div>
|
||
|
||
<!-- Icona tipo -->
|
||
{% if ev.tipo == 'scadenza' %}
|
||
<div class="agenda-icon agenda-icon-scadenza">
|
||
<i class="bi bi-bullseye"></i>
|
||
</div>
|
||
{% elif ev.tipo == 'appuntamento' %}
|
||
<div class="agenda-icon agenda-icon-appuntamento">
|
||
<i class="bi bi-calendar-check"></i>
|
||
</div>
|
||
{% else %}
|
||
<div class="agenda-icon agenda-icon-conv">
|
||
<i class="bi bi-chat-quote"></i>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- Dettaglio -->
|
||
<div class="flex-grow-1">
|
||
{% if ev.tipo == 'scadenza' %}
|
||
<a href="{% url 'obiettivo_dettaglio' ev.obj.pk %}" class="text-decoration-none text-dark fw-semibold d-block">
|
||
{{ ev.obj.titolo }}
|
||
</a>
|
||
<div class="d-flex align-items-center gap-2 mt-1">
|
||
<span class="badge-stato stato-{{ ev.obj.stato }}">{{ ev.obj.get_stato_display }}</span>
|
||
<span class="pill-tipo pill-{{ ev.obj.tipo }}">{{ ev.obj.get_tipo_display }}</span>
|
||
{% with days=ev.obj.giorni_rimanenti %}
|
||
{% if days == 0 %}
|
||
<span class="countdown countdown-urgent">Oggi!</span>
|
||
{% elif days == 1 %}
|
||
<span class="countdown countdown-urgent">Domani</span>
|
||
{% elif days <= 7 %}
|
||
<span class="countdown countdown-soon">{{ days }} giorni</span>
|
||
{% else %}
|
||
<span class="countdown countdown-ok">{{ days }} giorni</span>
|
||
{% endif %}
|
||
{% endwith %}
|
||
</div>
|
||
{% elif ev.tipo == 'appuntamento' %}
|
||
<a href="{% url 'appuntamento_dettaglio' ev.obj.pk %}" class="text-decoration-none text-dark fw-semibold d-block">
|
||
<i class="bi bi-calendar-check me-1 text-warning"></i>{{ ev.obj.titolo }}
|
||
</a>
|
||
<div class="d-flex align-items-center gap-2 mt-1">
|
||
<small class="text-muted"><i class="bi bi-clock me-1"></i>{{ ev.obj.data_ora|date:"H:i" }}</small>
|
||
{% if ev.obj.luogo %}<small class="text-muted"><i class="bi bi-geo-alt me-1"></i>{{ ev.obj.luogo }}</small>{% endif %}
|
||
</div>
|
||
{% else %}
|
||
<a href="{% url 'conversazione_dettaglio' ev.obj.pk %}" class="text-decoration-none text-dark fw-semibold d-block">
|
||
{{ ev.obj.titolo }}
|
||
</a>
|
||
<div class="d-flex align-items-center gap-2 mt-1">
|
||
<small class="text-muted">
|
||
<i class="bi bi-clock me-1"></i>{{ ev.obj.data|date:"H:i" }}
|
||
</small>
|
||
<small class="text-muted">
|
||
{{ ev.obj.registrato_da.get_full_name|default:ev.obj.registrato_da.username }}
|
||
</small>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- Progress (se scadenza) -->
|
||
{% if ev.tipo == 'scadenza' %}
|
||
<div class="d-none d-md-block" style="width:80px;">
|
||
<div class="progress" style="height:6px; border-radius:3px;">
|
||
<div class="progress-bar" role="progressbar"
|
||
style="width:{{ ev.obj.avanzamento }}%; background:var(--accent);">
|
||
</div>
|
||
</div>
|
||
<small class="text-muted d-block text-center mt-1" style="font-size:.7rem;">{{ ev.obj.avanzamento }}%</small>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% empty %}
|
||
<div class="empty-state py-4">
|
||
<i class="bi bi-calendar-check"></i>
|
||
<p>Nessun evento programmato. Tutto in ordine!</p>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── Eventi passati ── -->
|
||
<div class="card fade-in">
|
||
<div class="card-header-accent d-flex align-items-center" style="background:#f8f9fa; color:#64748b; border-bottom-color:#e2e8f0;">
|
||
<i class="bi bi-clock-history me-2"></i>
|
||
<span>Ultimi 30 giorni</span>
|
||
<span class="badge bg-secondary bg-opacity-10 text-secondary ms-2">{{ eventi_passati|length }}</span>
|
||
</div>
|
||
<div class="p-0">
|
||
{% for ev in eventi_passati %}
|
||
<div class="d-flex align-items-center gap-3 px-4 py-3 {% if not forloop.last %}border-bottom{% endif %} agenda-row {% if ev.scaduto %}agenda-row-scaduto{% endif %}">
|
||
<!-- Data -->
|
||
<div class="agenda-date text-center flex-shrink-0 {% if ev.scaduto %}text-danger{% endif %}">
|
||
<div class="agenda-day">{{ ev.data|date:"d" }}</div>
|
||
<div class="agenda-month">{{ ev.data|date:"M" }}</div>
|
||
</div>
|
||
|
||
<!-- Icona -->
|
||
{% if ev.tipo == 'scadenza' %}
|
||
<div class="agenda-icon {% if ev.scaduto %}agenda-icon-danger{% else %}agenda-icon-scadenza{% endif %}">
|
||
<i class="bi {% if ev.scaduto %}bi-exclamation-triangle{% else %}bi-bullseye{% endif %}"></i>
|
||
</div>
|
||
{% elif ev.tipo == 'appuntamento' %}
|
||
<div class="agenda-icon agenda-icon-appuntamento" style="opacity:.6;">
|
||
<i class="bi bi-calendar-check"></i>
|
||
</div>
|
||
{% else %}
|
||
<div class="agenda-icon agenda-icon-conv" style="opacity:.6;">
|
||
<i class="bi bi-chat-quote"></i>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- Dettaglio -->
|
||
<div class="flex-grow-1">
|
||
{% if ev.tipo == 'scadenza' %}
|
||
<a href="{% url 'obiettivo_dettaglio' ev.obj.pk %}" class="text-decoration-none {% if ev.scaduto %}text-danger{% else %}text-dark{% endif %} fw-semibold d-block">
|
||
{{ ev.obj.titolo }}
|
||
{% if ev.scaduto %}<small class="text-danger fw-normal">(scaduto)</small>{% endif %}
|
||
</a>
|
||
<div class="d-flex align-items-center gap-2 mt-1">
|
||
<span class="badge-stato stato-{{ ev.obj.stato }}">{{ ev.obj.get_stato_display }}</span>
|
||
</div>
|
||
{% elif ev.tipo == 'appuntamento' %}
|
||
<a href="{% url 'appuntamento_dettaglio' ev.obj.pk %}" class="text-decoration-none text-muted fw-semibold d-block">
|
||
<i class="bi bi-calendar-check me-1"></i>{{ ev.obj.titolo }}
|
||
</a>
|
||
<small class="text-muted">{{ ev.obj.data_ora|date:"H:i" }}{% if ev.obj.luogo %} · {{ ev.obj.luogo }}{% endif %}</small>
|
||
{% else %}
|
||
<a href="{% url 'conversazione_dettaglio' ev.obj.pk %}" class="text-decoration-none text-muted fw-semibold d-block">
|
||
{{ ev.obj.titolo }}
|
||
</a>
|
||
<small class="text-muted">{{ ev.obj.registrato_da.get_full_name|default:ev.obj.registrato_da.username }}</small>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% empty %}
|
||
<div class="empty-state py-4">
|
||
<i class="bi bi-clock-history"></i>
|
||
<p>Nessun evento negli ultimi 30 giorni.</p>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|