Files
ShooterHub/templates/index.html
2026-03-19 16:42:37 +01:00

175 lines
8.7 KiB
HTML

{% 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 %}
<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>
{% endif %}
</div>
<div class="nav-right">
{# 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">&#9660;</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>
{% 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;">&#128100;</span>{% endif %}
<span>{{ current_user.display_name or current_user.email.split('@')[0] }}</span>
<span class="caret">&#9660;</span>
</button>
<div class="nav-dd-menu">
<a href="{{ url_for('auth.profile') }}">&#128100;&ensp;{{ _('Profile') }}</a>
<hr>
<form method="post" action="{{ url_for('auth.logout') }}">
<button type="submit">&#8594;&ensp;{{ _('Logout') }}</button>
</form>
</div>
</div>
{% else %}
<a href="{{ url_for('auth.login') }}" style="color:#c8cfe0;font-size:0.9rem;text-decoration:none;">{{ _('Login') }}</a>
<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;">
{{ _('Join free') }}
</a>
{% endif %}
</div>
</nav>
<script>
function toggleDropdown(e) {
e.stopPropagation();
document.getElementById('userDropdown').classList.toggle('open');
}
function toggleLangDropdown(e) {
e.stopPropagation();
document.getElementById('langDropdown').classList.toggle('open');
}
document.addEventListener('click', function() {
var d = document.getElementById('userDropdown');
if (d) d.classList.remove('open');
var l = document.getElementById('langDropdown');
if (l) l.classList.remove('open');
});
</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;">
{{ _('New Analysis') }}
</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;">
{{ _('Log a Session') }}
</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;">
{{ _('Get started — free') }}
</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;">
{{ _('Try without account') }}
</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>
<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>
</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>
<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>
</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>
<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>
</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;">
{{ _('Latest sessions') }}
</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;">
{{ _('No public sessions yet. Be the first to share one!') }}
</p>
{% endif %}
</div>
</section>
{% endblock %}