Initial commit: Diario Conversazioni Olimpic Nastri

- Django 5.2 + PostgreSQL + Gunicorn
- Conversazioni, Obiettivi, Documenti PDF, Persone
- Commenti e aggiornamenti con modifica/eliminazione
- Agenda, ricerca live, giorni rimanenti scadenze
- Bootstrap 5 + HTMX + toast notifications
- Deploy: Nginx + Gunicorn + SSL
This commit is contained in:
automationkriz
2026-04-05 14:48:22 +00:00
commit d296353dcb
48 changed files with 3538 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
{% 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 '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>
{% 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>
{% 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>
{% 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>
{% 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 %}