an / templates /board.html
Docfile's picture
Upload 23 files
75ba54e verified
{% extends 'base.html' %}
{% block title %}/{{ board.slug }}/ - {{ board.name }}{% endblock %}
{% block content %}
<div class="mb-6 px-4 pt-4">
<h1 class="text-2xl font-bold text-gray-900 tracking-tight">/{{ board.slug }}/ - {{ board.name }}</h1>
<p class="text-gray-500 text-sm mt-1">{{ board.description }}</p>
</div>
<!-- Threads List -->
<div class="space-y-4 px-2 pb-24">
{% for thread in threads %}
<div class="bg-white p-4 rounded-xl border border-gray-100 shadow-sm" id="post-{{ thread.id }}">
<div class="flex gap-4">
<!-- Thumbnails -->
{% if thread.files %}
<div class="flex-shrink-0 flex flex-col gap-2">
{% for file in thread.files[:1] %} <!-- Show only first file as thumbnail -->
{% if file.filename.endswith(('.mp4', '.webm')) %}
<video controls class="w-24 h-24 sm:w-32 sm:h-32 object-cover rounded-lg bg-black">
<source src="{{ url_for('static', filename='uploads/' + file.filename) }}" type="video/{{ file.filename.split('.')[-1] }}">
</video>
{% else %}
<img
src="{{ url_for('static', filename='uploads/' + file.filename) }}"
data-thumb="{{ url_for('static', filename='uploads/' + file.filename) }}"
data-full="{{ url_for('static', filename='uploads/' + file.filename) }}"
alt="Post image"
class="post-image w-24 h-24 sm:w-32 sm:h-32 object-cover rounded-lg cursor-pointer hover:opacity-90 transition-opacity bg-gray-100"
>
{% endif %}
{% endfor %}
{% if thread.files|length > 1 %}
<span class="text-xs text-gray-500 text-center">+ {{ thread.files|length - 1 }} autres</span>
{% endif %}
</div>
{% endif %}
<div class="flex-grow min-w-0"> <!-- min-w-0 for truncation -->
<div class="flex items-center text-xs text-gray-500 mb-2 space-x-2">
<span class="font-bold text-gray-900">{{ thread.nickname }}</span>
<span>{{ thread.created_at.strftime('%d/%m %H:%M') }}</span>
<a href="{{ url_for('thread', thread_id=thread.id) }}" class="text-blue-500 hover:underline">N° {{ thread.id }}</a>
</div>
<div class="text-gray-800 text-base leading-relaxed break-words line-clamp-4 mb-3">
{{ thread.content|default('', true)|truncate(300)|format_post(post_context) }}
</div>
<div class="flex items-center justify-between">
<a href="{{ url_for('thread', thread_id=thread.id) }}" class="text-sm font-medium text-blue-600 hover:text-blue-800 bg-blue-50 px-3 py-1 rounded-full">
Voir le fil
{% if thread.replies|length > 0 %}
<span class="ml-1 text-blue-800">({{ thread.replies|length }})</span>
{% endif %}
</a>
<button class="text-green-600 hover:text-green-800 p-2 rounded-full hover:bg-green-50" onclick="sharePost('{{ thread.id }}', '{{ url_for('thread', thread_id=thread.id, _external=True) }}')" title="Partager">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" />
</svg>
</button>
</div>
<!-- Latest replies preview (Desktop only maybe? Or simplified) -->
{% set recent_replies = thread.replies[-2:] %}
{% if recent_replies %}
<div class="mt-4 space-y-2 border-l-2 border-gray-100 pl-3">
{% for reply in recent_replies %}
<div class="text-sm text-gray-600">
<span class="text-xs text-gray-400">>> {{ reply.created_at.strftime('%H:%M') }}</span>
<span class="line-clamp-1">{{ reply.content|truncate(100) }}</span>
</div>
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
{% else %}
<div class="text-center text-gray-400 py-12 bg-white rounded-xl border border-gray-100 border-dashed">
<p>C'est calme ici. Lancez une conversation.</p>
</div>
{% endfor %}
</div>
<!-- Floating Action Button -->
<button id="fab-button" onclick="togglePostForm()" class="fixed bottom-6 right-6 bg-blue-600 hover:bg-blue-700 text-white rounded-full p-4 shadow-lg transition-transform hover:scale-105 active:scale-95 z-40 flex items-center justify-center w-14 h-14">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
</button>
<!-- Hidden Modal Form -->
<div id="post-form-container" class="hidden fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-gray-900 bg-opacity-40 backdrop-blur-sm p-0 sm:p-4">
<!-- Overlay click to close -->
<div class="absolute inset-0" onclick="togglePostForm()"></div>
<div class="bg-white w-full max-w-lg rounded-t-2xl sm:rounded-2xl shadow-2xl transform transition-all relative z-10 flex flex-col max-h-[90vh]">
<div class="flex justify-between items-center p-4 border-b border-gray-100">
<h3 class="text-lg font-bold text-gray-900">Nouveau fil</h3>
<button onclick="togglePostForm()" class="text-gray-400 hover:text-gray-600 p-2 rounded-full hover:bg-gray-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="p-6 overflow-y-auto">
<form method="POST" enctype="multipart/form-data" class="space-y-5">
{{ form.hidden_tag() }}
<div class="hidden">
{{ form.honeypot() }}
</div>
<div id="nickname-field">
<label class="block text-gray-700 text-sm font-semibold mb-2" for="nickname">Pseudo</label>
{{ form.nickname(class="w-full bg-gray-50 text-gray-900 border border-gray-200 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent", placeholder="Pseudo (Optionnel)") }}
</div>
<div>
<label class="block text-gray-700 text-sm font-semibold mb-2" for="content">Message</label>
{{ form.content(class="w-full bg-gray-50 text-gray-900 border border-gray-200 rounded-lg py-3 px-4 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent h-40 resize-none text-base", placeholder="Écrivez quelque chose...") }}
{% for error in form.content.errors %}
<p class="text-red-500 text-xs mt-1">{{ error }}</p>
{% endfor %}
</div>
<div>
<label class="block text-gray-700 text-sm font-semibold mb-2" for="files">Images ou Vidéos</label>
<div class="flex items-center justify-center w-full">
<label for="files" class="flex flex-col items-center justify-center w-full h-32 border-2 border-gray-200 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100">
<div class="flex flex-col items-center justify-center pt-5 pb-6">
<svg class="w-8 h-8 mb-4 text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"/>
</svg>
<p class="text-sm text-gray-500"><span class="font-semibold">Cliquez pour uploader</span></p>
</div>
{{ form.files(class="hidden", multiple=True, accept="image/*,video/*", onchange="previewFiles(this, 'preview-board')") }}
</label>
</div>
<div id="preview-board" class="flex flex-wrap gap-2 mt-2"></div>
{% for error in form.files.errors %}
<p class="text-red-500 text-xs mt-1">{{ error }}</p>
{% endfor %}
</div>
<div class="pt-2">
{{ form.submit(class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-lg cursor-pointer shadow-md active:scale-95 transition-transform") }}
</div>
</form>
</div>
</div>
</div>
{% endblock %}