summaryrefslogtreecommitdiff
path: root/templates
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-05-06 14:34:01 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-05-06 14:34:01 -0700
commita3df69ff5218cee132a6def9d860cd0276cc0cd4 (patch)
tree2d8bf71b98a606b2f1194ce608c23a8e17d8cb6c /templates
parente708bec6cd76c2686de4158dde4d04f72a3c300d (diff)
Add year review and inline diary ratings
Diffstat (limited to 'templates')
-rw-r--r--templates/_film_card.html14
-rw-r--r--templates/detail.html80
-rw-r--r--templates/stats.html9
-rw-r--r--templates/year_review.html175
4 files changed, 256 insertions, 22 deletions
diff --git a/templates/_film_card.html b/templates/_film_card.html
index 9fcd89b..7147a1e 100644
--- a/templates/_film_card.html
+++ b/templates/_film_card.html
@@ -21,7 +21,19 @@
{% endif %}
</p>
</div>
- {% if film.stars %}
+ {% if film.shelf == 'diary' %}
+ <div class="star-control" role="group" aria-label="Rate film" data-film-id="{{ film.id }}" data-current-stars="{{ film.stars }}">
+ {% for value in range(1, 4) %}
+ <button
+ type="button"
+ class="star-button {% if film.stars >= value %}is-active{% endif %}"
+ data-stars="{{ value }}"
+ aria-label="{{ value }} star{% if value > 1 %}s{% endif %}"
+ aria-pressed="{% if film.stars >= value %}true{% else %}false{% endif %}"
+ >✦</button>
+ {% endfor %}
+ </div>
+ {% elif film.stars %}
<span class="rating">{% for _ in range(film.stars) %}✦{% endfor %}</span>
{% endif %}
</div>
diff --git a/templates/detail.html b/templates/detail.html
index b937c6b..df3f96a 100644
--- a/templates/detail.html
+++ b/templates/detail.html
@@ -12,6 +12,20 @@
<span>{{ film.title[:1] }}</span>
{% endif %}
</div>
+ <div class="detail-aside-meta">
+ <div>
+ <span class="summary-label">Shelf</span>
+ <strong>{{ film.shelf|title }}</strong>
+ </div>
+ <div>
+ <span class="summary-label">Watched</span>
+ <strong>{% if film.date_watched %}{{ film.date_watched }}{% else %}Not set{% endif %}</strong>
+ </div>
+ <div>
+ <span class="summary-label">Stars</span>
+ <strong>{% if film.stars %}{% for _ in range(film.stars) %}✦{% endfor %}{% else %}Unstarred{% endif %}</strong>
+ </div>
+ </div>
</aside>
<section class="detail-body">
@@ -31,29 +45,57 @@
{% endif %}
</p>
- <div class="detail-meta">
- {% if film.stars %}<span class="rating">{% for _ in range(film.stars) %}✦{% endfor %}</span>{% endif %}
- {% if film.date_watched %}<span>{{ film.date_watched }}</span>{% endif %}
- {% if film.runtime %}<span>{{ film.runtime }} min</span>{% endif %}
- {% if film.rewatch %}<span>Rewatch{% if film.rewatch_count %} #{{ film.rewatch_count }}{% endif %}</span>{% endif %}
- {% if film.country %}<span>{{ film.country }}</span>{% endif %}
- {% if film.language %}<span>{{ film.language }}</span>{% endif %}
- </div>
+ <section class="detail-grid">
+ <article class="detail-panel">
+ <p class="eyebrow">Watch log</p>
+ <div class="detail-meta">
+ {% if film.date_watched %}<span>{{ film.date_watched }}</span>{% endif %}
+ {% if film.runtime %}<span>{{ film.runtime }} min</span>{% endif %}
+ {% if film.rewatch %}<span>Rewatch{% if film.rewatch_count %} #{{ film.rewatch_count }}{% endif %}</span>{% endif %}
+ {% if film.watched_with %}<span>With {{ film.watched_with }}</span>{% endif %}
+ {% if film.context %}<span>{{ film.context }}</span>{% endif %}
+ {% if film.how_found %}<span>{{ film.how_found }}</span>{% endif %}
+ </div>
+ </article>
- {% if film.context or film.how_found or film.watched_with %}
- <div class="tag-row detail-tags">
- {% if film.context %}<span>{{ film.context }}</span>{% endif %}
- {% if film.how_found %}<span>{{ film.how_found }}</span>{% endif %}
- {% if film.watched_with %}<span>With {{ film.watched_with }}</span>{% endif %}
- </div>
- {% endif %}
+ <article class="detail-panel">
+ <p class="eyebrow">Production</p>
+ <div class="detail-meta">
+ {% if film.country %}<span>{{ film.country }}</span>{% endif %}
+ {% if film.language %}<span>{{ film.language }}</span>{% endif %}
+ {% if film.year %}<span>{{ film.year }}</span>{% endif %}
+ {% if film.tmdb_id %}<span>TMDB {{ film.tmdb_id }}</span>{% endif %}
+ </div>
+ </article>
+ </section>
- {% if film.notes %}
- <div class="notes-body">
- {{ film.notes }}
- </div>
+ {% if tmdb_context %}
+ <section class="detail-panel">
+ <p class="eyebrow">Summary</p>
+ {% if tmdb_context.tagline %}
+ <p class="detail-tagline">{{ tmdb_context.tagline }}</p>
+ {% endif %}
+ {% if tmdb_context.overview %}
+ <p class="detail-overview">{{ tmdb_context.overview }}</p>
+ {% endif %}
+ {% if tmdb_context.cast %}
+ <div class="detail-cast">
+ <span class="summary-label">Cast</span>
+ <p>{{ tmdb_context.cast|join(", ") }}</p>
+ </div>
+ {% endif %}
+ </section>
{% endif %}
+ <section class="detail-panel">
+ <p class="eyebrow">Notes</p>
+ {% if film.notes %}
+ <div class="notes-body">{{ film.notes }}</div>
+ {% else %}
+ <p class="muted">No notes saved.</p>
+ {% endif %}
+ </section>
+
<div class="detail-actions">
<a class="secondary-button" href="/films/{{ film.id }}/edit">Edit</a>
{% if film.shelf == 'queue' %}
diff --git a/templates/stats.html b/templates/stats.html
index 7b54634..2983418 100644
--- a/templates/stats.html
+++ b/templates/stats.html
@@ -4,8 +4,13 @@
{% block content %}
<section class="page-heading">
- <p class="eyebrow">Stats</p>
- <h1>Watching patterns</h1>
+ <div class="page-heading-row">
+ <div>
+ <p class="eyebrow">Stats</p>
+ <h1>Watching patterns</h1>
+ </div>
+ <a class="button-link" href="/stats/year-in-review">Year in review</a>
+ </div>
</section>
<section class="stats-layout">
diff --git a/templates/year_review.html b/templates/year_review.html
new file mode 100644
index 0000000..5339c34
--- /dev/null
+++ b/templates/year_review.html
@@ -0,0 +1,175 @@
+{% extends "base.html" %}
+
+{% block title %}{{ selected_year }} Year in Review · Lumière{% endblock %}
+
+{% block content %}
+ <section class="review-hero">
+ <div>
+ <p class="eyebrow">Year in Review</p>
+ <h1>{{ selected_year }}</h1>
+ <p class="review-intro">A snapshot of the films you logged that year.</p>
+ </div>
+
+ <form class="year-picker" method="get" action="/stats/year-in-review">
+ <label for="year">Year</label>
+ <select id="year" name="year" onchange="this.form.submit()">
+ {% for option in available_years %}
+ <option value="{{ option }}" {% if option == selected_year %}selected{% endif %}>{{ option }}</option>
+ {% endfor %}
+ </select>
+ </form>
+ </section>
+
+ {% if total_watched == 0 %}
+ <section class="empty-state">
+ <p class="eyebrow">No entries</p>
+ <h2>No diary films for this year</h2>
+ <p>Pick another year or add more diary entries.</p>
+ </section>
+ {% else %}
+ <section class="review-metrics">
+ <article class="summary-card">
+ <span class="summary-label">Films watched</span>
+ <strong>{{ total_watched }}</strong>
+ </article>
+ <article class="summary-card">
+ <span class="summary-label">Average stars</span>
+ <strong>{{ "%.1f"|format(average_stars) }}</strong>
+ </article>
+ <article class="summary-card">
+ <span class="summary-label">Rewatch rate</span>
+ <strong>{{ (rewatch_rate.rate * 100)|round(0) }}%</strong>
+ </article>
+ <article class="summary-card">
+ <span class="summary-label">Top director</span>
+ <strong>{% if top_director %}{{ top_director.director }}{% else %}—{% endif %}</strong>
+ </article>
+ <article class="summary-card">
+ <span class="summary-label">Top month</span>
+ <strong>{% if top_month %}{{ top_month.month }}{% else %}—{% endif %}</strong>
+ </article>
+ </section>
+
+ <section class="review-grid">
+ <article class="review-panel review-panel-wide">
+ <p class="eyebrow">Monthly activity</p>
+ <div class="year-bars">
+ {% set max_month = films_per_month | map(attribute='count') | max if films_per_month else 1 %}
+ {% for item in films_per_month %}
+ <div class="year-bar-row">
+ <span>{{ item.month[:3] }}</span>
+ <div class="year-bar-track">
+ <div class="year-bar-fill" style="width: {{ (item.count / max_month * 100) if max_month else 0 }}%"></div>
+ </div>
+ <strong>{{ item.count }}</strong>
+ </div>
+ {% endfor %}
+ </div>
+ </article>
+
+ <article class="review-panel">
+ <p class="eyebrow">Stars</p>
+ <div class="stats-bars">
+ {% set max_stars = star_distribution | map(attribute='count') | max if star_distribution else 1 %}
+ {% for item in star_distribution %}
+ <div class="stats-bar-row">
+ <span>{{ item.stars }} star</span>
+ <div class="stats-bar-track"><div class="stats-bar-fill" style="width: {{ (item.count / max_stars * 100) if max_stars else 0 }}%"></div></div>
+ <strong>{{ item.count }}</strong>
+ </div>
+ {% endfor %}
+ </div>
+ </article>
+
+ <article class="review-panel">
+ <p class="eyebrow">Companions</p>
+ <ol class="stats-list">
+ {% for item in watched_with_breakdown %}
+ <li><span>{{ item.watched_with }}</span><strong>{{ item.count }}</strong></li>
+ {% endfor %}
+ </ol>
+ </article>
+ </section>
+
+ <section class="review-panel">
+ <p class="eyebrow">Highlights</p>
+ <div class="highlight-grid">
+ {% if highlight_films.highest_rated %}
+ {% for film in highlight_films.highest_rated %}
+ <article class="highlight-card">
+ <a class="poster-frame" href="/films/{{ film.id }}">
+ {% if film.poster_url %}
+ <img src="{{ film.poster_url }}" alt="{{ film.title }} poster">
+ {% else %}
+ <span>{{ film.title[:1] }}</span>
+ {% endif %}
+ </a>
+ <div>
+ <h2><a href="/films/{{ film.id }}">{{ film.title }}</a></h2>
+ <p class="muted">{{ film.director or "Unknown director" }}</p>
+ <p class="highlight-meta">
+ {% if film.date_watched %}{{ film.date_watched }}{% endif %}
+ {% if film.stars %} · {% for _ in range(film.stars) %}✦{% endfor %}{% endif %}
+ </p>
+ {% if film.notes_excerpt %}
+ <p class="notes-preview">{{ film.notes_excerpt }}</p>
+ {% endif %}
+ </div>
+ </article>
+ {% endfor %}
+ {% endif %}
+
+ {% if highlight_films.first_watch %}
+ <article class="highlight-card">
+ <a class="poster-frame" href="/films/{{ highlight_films.first_watch.id }}">
+ {% if highlight_films.first_watch.poster_url %}
+ <img src="{{ highlight_films.first_watch.poster_url }}" alt="{{ highlight_films.first_watch.title }} poster">
+ {% else %}
+ <span>{{ highlight_films.first_watch.title[:1] }}</span>
+ {% endif %}
+ </a>
+ <div>
+ <p class="summary-label">First watch</p>
+ <h2><a href="/films/{{ highlight_films.first_watch.id }}">{{ highlight_films.first_watch.title }}</a></h2>
+ <p class="muted">{{ highlight_films.first_watch.date_watched }}</p>
+ </div>
+ </article>
+ {% endif %}
+
+ {% if highlight_films.last_watch %}
+ <article class="highlight-card">
+ <a class="poster-frame" href="/films/{{ highlight_films.last_watch.id }}">
+ {% if highlight_films.last_watch.poster_url %}
+ <img src="{{ highlight_films.last_watch.poster_url }}" alt="{{ highlight_films.last_watch.title }} poster">
+ {% else %}
+ <span>{{ highlight_films.last_watch.title[:1] }}</span>
+ {% endif %}
+ </a>
+ <div>
+ <p class="summary-label">Last watch</p>
+ <h2><a href="/films/{{ highlight_films.last_watch.id }}">{{ highlight_films.last_watch.title }}</a></h2>
+ <p class="muted">{{ highlight_films.last_watch.date_watched }}</p>
+ </div>
+ </article>
+ {% endif %}
+
+ {% if highlight_films.most_rewatched %}
+ <article class="highlight-card">
+ <a class="poster-frame" href="/films/{{ highlight_films.most_rewatched.id }}">
+ {% if highlight_films.most_rewatched.poster_url %}
+ <img src="{{ highlight_films.most_rewatched.poster_url }}" alt="{{ highlight_films.most_rewatched.title }} poster">
+ {% else %}
+ <span>{{ highlight_films.most_rewatched.title[:1] }}</span>
+ {% endif %}
+ </a>
+ <div>
+ <p class="summary-label">Most rewatched</p>
+ <h2><a href="/films/{{ highlight_films.most_rewatched.id }}">{{ highlight_films.most_rewatched.title }}</a></h2>
+ <p class="muted">{{ highlight_films.most_rewatched.rewatch_count }} rewatches</p>
+ </div>
+ </article>
+ {% endif %}
+ </div>
+ </section>
+ {% endif %}
+{% endblock %}