2026-03-17 17:20:54 +01:00
{% extends "base.html" %}
{% block title %}The Shooter's Network — Track, analyze, share{% endblock %}
{% block body %}
< nav class = "nav" >
< a href = "/" class = "nav-brand" > The Shooter's Network< / a >
< div class = "nav-links" >
{% if current_user.is_authenticated %}
2026-03-19 16:42:37 +01:00
< a href = "{{ url_for('analyze') }}" > {{ _('New Analysis') }}< / a >
< a href = "{{ url_for('equipment.index') }}" > {{ _('Equipment') }}< / a >
< a href = "{{ url_for('sessions.index') }}" > {{ _('Sessions') }}< / a >
< a href = "{{ url_for('dashboard.index') }}" > {{ _('Dashboard') }}< / a >
2026-03-17 17:20:54 +01:00
{% endif %}
< / div >
< div class = "nav-right" >
2026-03-19 16:42:37 +01:00
{# Language switcher #}
< div class = "nav-dropdown" id = "langDropdown" >
< button class = "nav-user-btn" onclick = "toggleLangDropdown(event)" style = "padding:.2rem .55rem;gap:.35rem;font-size:1.1rem;" >
{% if current_lang == 'fr' %}🇫🇷{% elif current_lang == 'de' %}🇩🇪{% else %}🇬🇧{% endif %}< span class = "caret" > ▼ < / span >
< / button >
< div class = "nav-dd-menu" style = "min-width:130px;" >
< a href = "{{ url_for('set_lang', lang='en') }}" > 🇬🇧 English< / a >
< a href = "{{ url_for('set_lang', lang='fr') }}" > 🇫🇷 Français< / a >
< a href = "{{ url_for('set_lang', lang='de') }}" > 🇩🇪 Deutsch< / a >
< / div >
< / div >
2026-03-17 17:20:54 +01:00
{% if current_user.is_authenticated %}
< div class = "nav-dropdown" id = "userDropdown" >
< button class = "nav-user-btn" onclick = "toggleDropdown(event)" >
{% set av = current_user.effective_avatar_url %}
{% if av %}< img src = "{{ av }}" class = "nav-avatar" alt = "" >
{% else %}< span style = "font-size:1.1rem;line-height:1;" > 👤 < / span > {% endif %}
< span > {{ current_user.display_name or current_user.email.split('@')[0] }}< / span >
< span class = "caret" > ▼ < / span >
< / button >
< div class = "nav-dd-menu" >
2026-03-19 16:42:37 +01:00
< a href = "{{ url_for('auth.profile') }}" > 👤   {{ _('Profile') }}< / a >
2026-03-17 17:20:54 +01:00
< hr >
< form method = "post" action = "{{ url_for('auth.logout') }}" >
2026-03-19 16:42:37 +01:00
< button type = "submit" > →   {{ _('Logout') }}< / button >
2026-03-17 17:20:54 +01:00
< / form >
< / div >
< / div >
{% else %}
2026-03-19 16:42:37 +01:00
< a href = "{{ url_for('auth.login') }}" style = "color:#c8cfe0;font-size:0.9rem;text-decoration:none;" > {{ _('Login') }}< / a >
2026-03-17 17:20:54 +01:00
< a href = "{{ url_for('auth.register') }}"
style="background:#1f77b4;color:#fff;padding:0.35rem 0.9rem;border-radius:4px;font-size:0.88rem;text-decoration:none;">
2026-03-19 16:42:37 +01:00
{{ _('Join free') }}
2026-03-17 17:20:54 +01:00
< / a >
{% endif %}
< / div >
< / nav >
< script >
function toggleDropdown(e) {
e.stopPropagation();
document.getElementById('userDropdown').classList.toggle('open');
}
2026-03-19 16:42:37 +01:00
function toggleLangDropdown(e) {
e.stopPropagation();
document.getElementById('langDropdown').classList.toggle('open');
}
2026-03-17 17:20:54 +01:00
document.addEventListener('click', function() {
var d = document.getElementById('userDropdown');
if (d) d.classList.remove('open');
2026-03-19 16:42:37 +01:00
var l = document.getElementById('langDropdown');
if (l) l.classList.remove('open');
2026-03-17 17:20:54 +01:00
});
< / script >
<!-- ── Hero ── -->
< section style = "background:#1a1a2e;color:#fff;padding:4rem 1.5rem;text-align:center;" >
< h1 style = "font-size:2.4rem;font-weight:800;color:#fff;margin-bottom:0.75rem;letter-spacing:-0.02em;" >
The Shooter's Network
< / h1 >
< p style = "font-size:1.15rem;color:#a0aec0;max-width:560px;margin:0 auto 2rem;" >
Analyze your ballistic data, track every session, manage your equipment,
and share your performance with the community.
< / p >
< div style = "display:flex;gap:1rem;justify-content:center;flex-wrap:wrap;" >
{% if current_user.is_authenticated %}
< a href = "{{ url_for('analyze') }}"
style="background:#1f77b4;color:#fff;padding:0.75rem 1.75rem;border-radius:6px;font-size:1rem;font-weight:600;text-decoration:none;">
2026-03-19 16:42:37 +01:00
{{ _('New Analysis') }}
2026-03-17 17:20:54 +01:00
< / a >
< a href = "{{ url_for('sessions.new') }}"
style="background:transparent;color:#fff;padding:0.75rem 1.75rem;border-radius:6px;font-size:1rem;font-weight:600;text-decoration:none;border:1px solid #4a5568;">
2026-03-19 16:42:37 +01:00
{{ _('Log a Session') }}
2026-03-17 17:20:54 +01:00
< / a >
{% else %}
< a href = "{{ url_for('auth.register') }}"
style="background:#1f77b4;color:#fff;padding:0.75rem 1.75rem;border-radius:6px;font-size:1rem;font-weight:600;text-decoration:none;">
2026-03-19 16:42:37 +01:00
{{ _('Get started — free') }}
2026-03-17 17:20:54 +01:00
< / a >
< a href = "{{ url_for('analyze') }}"
style="background:transparent;color:#fff;padding:0.75rem 1.75rem;border-radius:6px;font-size:1rem;font-weight:600;text-decoration:none;border:1px solid #4a5568;">
2026-03-19 16:42:37 +01:00
{{ _('Try without account') }}
2026-03-17 17:20:54 +01:00
< / a >
{% endif %}
< / div >
< / section >
<!-- ── Features ── -->
< section style = "background:#f8f9fb;padding:2.5rem 1.5rem;" >
< div style = "max-width:900px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1.25rem;" >
< div style = "background:#fff;padding:1.5rem;border-radius:8px;box-shadow:0 1px 4px rgba(0,0,0,.07);" >
< div style = "font-size:1.6rem;margin-bottom:0.5rem;" > 📊< / div >
2026-03-19 16:42:37 +01:00
< h3 style = "margin:0 0 .35rem;color:#1a1a2e;font-size:1rem;" > {{ _('Ballistic Analysis') }}< / h3 >
< p style = "color:#666;font-size:0.88rem;margin:0;" > {{ _('Upload CSV files from your chronograph and get instant shot-group statistics, velocity charts, and PDF reports.') }}< / p >
2026-03-17 17:20:54 +01:00
< / div >
< div style = "background:#fff;padding:1.5rem;border-radius:8px;box-shadow:0 1px 4px rgba(0,0,0,.07);" >
< div style = "font-size:1.6rem;margin-bottom:0.5rem;" > 🎯< / div >
2026-03-19 16:42:37 +01:00
< h3 style = "margin:0 0 .35rem;color:#1a1a2e;font-size:1rem;" > {{ _('Session Tracking') }}< / h3 >
< p style = "color:#666;font-size:0.88rem;margin:0;" > {{ _('Log every range visit with location, weather, rifle, ammo, and distance. All your data in one place.') }}< / p >
2026-03-17 17:20:54 +01:00
< / div >
< div style = "background:#fff;padding:1.5rem;border-radius:8px;box-shadow:0 1px 4px rgba(0,0,0,.07);" >
< div style = "font-size:1.6rem;margin-bottom:0.5rem;" > 🤝< / div >
2026-03-19 16:42:37 +01:00
< h3 style = "margin:0 0 .35rem;color:#1a1a2e;font-size:1rem;" > {{ _('Community Feed') }}< / h3 >
< p style = "color:#666;font-size:0.88rem;margin:0;" > {{ _('Share your public sessions and see what other shooters are achieving on the range.') }}< / p >
2026-03-17 17:20:54 +01:00
< / div >
< / div >
< / section >
<!-- ── Flash messages ── -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
< div style = "max-width:960px;margin:1rem auto;padding:0 1.5rem;" >
{% for category, message in messages %}
< div class = "flash {{ category }}" > {{ message }}< / div >
{% endfor %}
< / div >
{% endif %}
{% endwith %}
<!-- ── Public sessions feed ── -->
< section style = "padding:2.5rem 1.5rem 3rem;" >
< div style = "max-width:960px;margin:0 auto;" >
< h2 style = "font-size:1.3rem;color:#1a1a2e;margin-bottom:1.25rem;border-bottom:2px solid #e0e0e0;padding-bottom:.4rem;" >
2026-03-19 16:42:37 +01:00
{{ _('Latest sessions') }}
2026-03-17 17:20:54 +01:00
< / h2 >
{% if public_sessions %}
< div style = "display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1.1rem;" >
{% for s in public_sessions %}
< a href = "{{ url_for('sessions.detail', session_id=s.id) }}"
style="display:block;background:#fff;border:1px solid #e8e8e8;border-radius:8px;padding:1.1rem 1.25rem;text-decoration:none;color:inherit;">
< div style = "display:flex;align-items:center;gap:0.55rem;margin-bottom:0.65rem;" >
{% if s.user.avatar_url %}
< img src = "{{ s.user.avatar_url }}" style = "width:26px;height:26px;border-radius:50%;object-fit:cover;" alt = "" >
{% else %}
< div style = "width:26px;height:26px;border-radius:50%;background:#e0e4f0;display:flex;align-items:center;justify-content:center;font-size:0.72rem;color:#666;font-weight:700;" >
{{ (s.user.display_name or s.user.email)[0].upper() }}
< / div >
{% endif %}
< span style = "font-size:0.83rem;color:#666;" > {{ s.user.display_name or s.user.email.split('@')[0] }}< / span >
< / div >
< div style = "font-weight:600;color:#1a1a2e;margin-bottom:0.35rem;font-size:0.95rem;" > {{ s.label }}< / div >
< div style = "font-size:0.81rem;color:#888;display:flex;flex-wrap:wrap;gap:.3rem .65rem;" >
< span > {{ s.session_date.strftime('%d %b %Y') }}< / span >
{% if s.location_name %}< span > 📍 {{ s.location_name }}< / span > {% endif %}
{% if s.distance_m %}< span > {{ s.distance_m }} m< / span > {% endif %}
{% if s.weather_cond %}< span > {{ s.weather_cond.replace('_', ' ').title() }}< / span > {% endif %}
{% if s.weather_temp_c is not none %}< span > {{ s.weather_temp_c }}°C< / span > {% endif %}
< / div >
< / a >
{% endfor %}
< / div >
{% else %}
< p style = "color:#aaa;text-align:center;padding:3rem 0;" >
2026-03-19 16:42:37 +01:00
{{ _('No public sessions yet. Be the first to share one!') }}
2026-03-17 17:20:54 +01:00
< / p >
{% endif %}
< / div >
< / section >
{% endblock %}