feat: Redesign post detail page as blog-style adventure story

Major UI/UX improvements for better storytelling:

Story Layout:
- Convert adventure story into blog-style sequential sections
- Extract keywords from **bold** text and display as highlight tags
- Show sections with keywords → text → images flow
- Create continuous narrative experience with section separators

Photo Gallery Enhancement:
- Move photo gallery to compact sidebar widget
- Reduce gallery size to focus attention on story
- Show 2x2 grid with hover effects and cover indicators
- Add 'click to view gallery' hint for better UX

Features:
- Parse content sections separated by double newlines
- Extract **keyword** patterns as section highlights
- Distribute section images across story sections
- Maintain image modal functionality
- Clean, readable typography with proper spacing
- Visual hierarchy that guides reader through adventure

This creates a much more engaging blog-post experience where the story takes center stage and images support the narrative rather than competing for attention.
This commit is contained in:
ske087
2025-07-24 17:52:01 +03:00
parent 8691a6cd2d
commit d5c8ec1dc2

View File

@@ -85,59 +85,96 @@
<!-- Main Content Grid -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Main Content -->
<div class="lg:col-span-2 space-y-8">
<!-- Adventure Story -->
<div class="lg:col-span-2">
<!-- Adventure Story Blog Post -->
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
<div class="bg-gradient-to-r from-blue-600 to-purple-600 p-6">
<div class="flex items-center text-white">
<i class="fas fa-book-open text-2xl mr-3"></i>
<div>
<h2 class="text-2xl font-bold">Adventure Story</h2>
<p class="text-blue-100">Discover the journey through the author's words</p>
<p class="text-blue-100">Follow the journey step by step</p>
</div>
</div>
</div>
<div class="p-6">
<div class="prose prose-lg max-w-none text-gray-700">
{{ post.content | safe | nl2br }}
<div class="p-8">
<div class="prose prose-lg max-w-none">
{% set content_sections = post.content.split('\n\n') %}
{% set section_images = post.images.filter_by(is_cover=False).all() %}
{% set images_per_section = (section_images|length / (content_sections|length))|round|int if content_sections|length > 0 else 0 %}
{% for section in content_sections %}
{% if section.strip() %}
<div class="mb-8 pb-6 {% if not loop.last %}border-b border-gray-200{% endif %}">
{% set section_text = section.strip() %}
<!-- Extract keywords from **bold** text -->
{% set keywords = [] %}
{% set clean_text = section_text %}
<!-- Simple keyword extraction for **word** patterns -->
{% if '**' in section_text %}
{% set parts = section_text.split('**') %}
{% set clean_parts = [] %}
{% for i in range(parts|length) %}
{% if i % 2 == 1 %}
{% set _ = keywords.append(parts[i]) %}
{% set _ = clean_parts.append(parts[i]) %}
{% else %}
{% set _ = clean_parts.append(parts[i]) %}
{% endif %}
{% endfor %}
{% set clean_text = clean_parts|join('') %}
{% endif %}
<!-- Section Keywords -->
{% if keywords %}
<div class="mb-4">
{% for keyword in keywords %}
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gradient-to-r from-amber-500 to-orange-500 text-white mr-2 mb-2">
<i class="fas fa-tag mr-1 text-xs"></i>
{{ keyword }}
</span>
{% endfor %}
</div>
{% endif %}
<!-- Section Text -->
<div class="text-gray-700 leading-relaxed mb-6 text-lg">
{{ clean_text | safe | nl2br }}
</div>
<!-- Section Images -->
{% if section_images %}
{% set start_idx = loop.index0 * images_per_section %}
{% set end_idx = start_idx + images_per_section %}
{% set current_section_images = section_images[start_idx:end_idx] %}
{% if current_section_images %}
<div class="grid grid-cols-1 {% if current_section_images|length > 1 %}md:grid-cols-2{% endif %} gap-4 mb-6">
{% for image in current_section_images %}
<div class="relative rounded-xl overflow-hidden cursor-pointer group transition-all duration-300 hover:shadow-lg"
onclick="openImageModal('{{ image.get_url() }}', '{{ image.description or image.original_name }}')">
<img src="{{ image.get_url() }}" alt="{{ image.description or image.original_name }}"
class="w-full h-64 object-cover transition-transform duration-300 group-hover:scale-105">
<div class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
{% if image.description %}
<div class="absolute bottom-0 left-0 right-0 p-3 text-white text-sm opacity-0 group-hover:opacity-100 transition-opacity duration-300">
{{ image.description }}
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
{% endif %}
</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
<!-- Photo Gallery -->
{% if post.images.count() > 0 %}
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
<div class="bg-gradient-to-r from-green-600 to-teal-600 p-6">
<div class="flex items-center text-white">
<i class="fas fa-camera-retro text-2xl mr-3"></i>
<div>
<h2 class="text-2xl font-bold">Photo Gallery</h2>
<p class="text-green-100">Visual highlights from this adventure</p>
</div>
</div>
</div>
<div class="p-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
{% for image in post.images %}
<div class="relative rounded-lg overflow-hidden cursor-pointer group transition-transform duration-300 hover:scale-105"
onclick="openImageModal('{{ image.get_url() }}', '{{ image.description or image.original_name }}')">
<img src="{{ image.get_url() }}" alt="{{ image.description or image.original_name }}"
class="w-full h-64 object-cover">
{% if image.description %}
<div class="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
<p class="text-white p-4 text-sm">{{ image.description }}</p>
</div>
{% endif %}
{% if image.is_cover %}
<div class="absolute top-2 left-2">
<span class="inline-flex items-center px-2 py-1 rounded bg-yellow-500 text-white text-xs font-semibold">
<i class="fas fa-star mr-1"></i> Cover
</span>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endif %}
@@ -319,6 +356,45 @@
</div>
</div>
</div>
<!-- Photo Gallery (Compact) -->
{% if post.images.count() > 0 %}
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
<div class="bg-gradient-to-r from-green-600 to-teal-600 p-4">
<div class="flex items-center text-white">
<i class="fas fa-camera-retro text-xl mr-2"></i>
<div>
<h2 class="text-lg font-bold">Photo Gallery</h2>
<p class="text-green-100 text-sm">{{ post.images.count() }} photos</p>
</div>
</div>
</div>
<div class="p-4">
<div class="grid grid-cols-2 gap-2">
{% for image in post.images %}
<div class="relative rounded-lg overflow-hidden cursor-pointer group"
onclick="openImageModal('{{ image.get_url() }}', '{{ image.description or image.original_name }}')">
<img src="{{ image.get_url() }}" alt="{{ image.description or image.original_name }}"
class="w-full h-20 object-cover transition-transform duration-300 group-hover:scale-110">
{% if image.is_cover %}
<div class="absolute top-1 left-1">
<span class="inline-flex items-center px-1 py-0.5 rounded text-xs font-semibold bg-yellow-500 text-white">
<i class="fas fa-star"></i>
</span>
</div>
{% endif %}
<div class="absolute inset-0 bg-black/30 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
</div>
{% endfor %}
</div>
{% if post.images.count() > 4 %}
<div class="mt-3 text-center">
<span class="text-sm text-gray-500">Click any photo to view gallery</span>
</div>
{% endif %}
</div>
</div>
{% endif %}
</div>
</div>
</div>