🎨 Complete Tailwind CSS conversion - Redesigned post detail page with modern gradient backgrounds - Updated profile page with consistent design language - Converted from Bootstrap to Tailwind CSS throughout ✨ New Features & Improvements - Enhanced community post management system - Added admin panel with analytics dashboard - Improved post creation and editing workflows - Interactive GPS map integration with Leaflet.js - Photo gallery with modal view and hover effects - Adventure statistics and metadata display - Like system and community engagement features 🔧 Technical Improvements - Fixed template syntax errors and CSRF token issues - Updated database models and relationships - Enhanced media file management - Improved responsive design patterns - Added proper error handling and validation 📱 Mobile-First Design - Responsive grid layouts - Touch-friendly interactions - Optimized for all screen sizes - Modern card-based UI components 🏍️ Adventure Platform Features - GPS track visualization and statistics - Photo uploads with thumbnail generation - GPX file downloads for registered users - Community comments and discussions - Post approval workflow for admins - Difficulty rating system with star indicators
522 lines
26 KiB
HTML
522 lines
26 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ post.title }} - Moto Adventure{% endblock %}
|
|
|
|
{% block head %}
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
<style>
|
|
.map-container {
|
|
height: 400px;
|
|
border-radius: 1rem;
|
|
overflow: hidden;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="min-h-screen bg-gradient-to-br from-blue-900 via-purple-900 to-teal-900 pt-16">
|
|
<!-- Hero Section -->
|
|
<div class="relative overflow-hidden py-16">
|
|
{% set cover_image = post.images.filter_by(is_cover=True).first() %}
|
|
{% if cover_image %}
|
|
<div class="absolute inset-0">
|
|
<img src="{{ cover_image.get_url() }}" alt="{{ post.title }}"
|
|
class="w-full h-full object-cover opacity-30">
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Status Badge -->
|
|
{% if current_user.is_authenticated and (current_user.id == post.author_id or current_user.is_admin) %}
|
|
<div class="absolute top-4 right-4 z-10">
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium
|
|
{{ 'bg-green-100 text-green-800' if post.published else 'bg-yellow-100 text-yellow-800' }}">
|
|
{% if post.published %}
|
|
<i class="fas fa-check-circle mr-1"></i> Published
|
|
{% else %}
|
|
<i class="fas fa-clock mr-1"></i> Pending Review
|
|
{% endif %}
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
|
<!-- Difficulty Badge -->
|
|
<div class="inline-flex items-center px-4 py-2 rounded-full bg-white/10 backdrop-blur-sm border border-white/20 text-white mb-6">
|
|
{% for i in range(post.difficulty) %}
|
|
<i class="fas fa-star text-yellow-400 mr-1"></i>
|
|
{% endfor %}
|
|
<span class="ml-2 font-semibold">{{ post.get_difficulty_label() }}</span>
|
|
</div>
|
|
|
|
<h1 class="text-4xl md:text-6xl font-bold text-white mb-4">{{ post.title }}</h1>
|
|
{% if post.subtitle %}
|
|
<p class="text-xl text-blue-100 max-w-3xl mx-auto">{{ post.subtitle }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-12">
|
|
<!-- Post Meta Information -->
|
|
<div class="bg-white/10 backdrop-blur-sm rounded-2xl p-6 border border-white/20 mb-8 -mt-8 relative z-10">
|
|
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
|
<div class="flex items-center space-x-4">
|
|
<div class="w-12 h-12 bg-gradient-to-r from-orange-500 to-red-600 rounded-full flex items-center justify-center text-white font-bold text-lg">
|
|
{{ post.author.nickname[0].upper() }}
|
|
</div>
|
|
<div>
|
|
<h3 class="text-white font-semibold text-lg">{{ post.author.nickname }}</h3>
|
|
<p class="text-blue-200 text-sm">
|
|
<i class="fas fa-calendar-alt mr-1"></i>
|
|
Published on {{ post.created_at.strftime('%B %d, %Y') }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-3">
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full bg-pink-500/20 text-pink-200 text-sm">
|
|
<i class="fas fa-heart mr-1"></i> {{ post.get_like_count() }} likes
|
|
</span>
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full bg-blue-500/20 text-blue-200 text-sm">
|
|
<i class="fas fa-comments mr-1"></i> {{ post.comments.count() }} comments
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 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="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>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="prose prose-lg max-w-none text-gray-700">
|
|
{{ post.content | safe | nl2br }}
|
|
</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>
|
|
{% endif %}
|
|
|
|
<!-- Comments Section -->
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
|
|
<div class="bg-gradient-to-r from-purple-600 to-pink-600 p-6">
|
|
<div class="flex items-center text-white">
|
|
<i class="fas fa-comment-dots text-2xl mr-3"></i>
|
|
<div>
|
|
<h2 class="text-2xl font-bold">Community Discussion</h2>
|
|
<p class="text-purple-100">Share your thoughts and experiences ({{ comments|length }})</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6">
|
|
{% if current_user.is_authenticated %}
|
|
<form method="POST" action="{{ url_for('community.add_comment', id=post.id) }}" class="mb-6">
|
|
{{ form.hidden_tag() }}
|
|
<div class="mb-4">
|
|
{{ form.content.label(class="block text-sm font-medium text-gray-700 mb-2") }}
|
|
{{ form.content(class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent", rows="4", placeholder="Share your thoughts about this adventure...") }}
|
|
</div>
|
|
<button type="submit" class="inline-flex items-center px-4 py-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-lg hover:from-blue-700 hover:to-purple-700 transition-all duration-200">
|
|
<i class="fas fa-paper-plane mr-2"></i> Post Comment
|
|
</button>
|
|
</form>
|
|
{% else %}
|
|
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
|
|
<div class="flex items-center">
|
|
<i class="fas fa-info-circle text-blue-600 mr-3"></i>
|
|
<div>
|
|
<p class="text-blue-800">
|
|
<a href="{{ url_for('auth.login') }}" class="font-semibold hover:underline">Login</a> or
|
|
<a href="{{ url_for('auth.register') }}" class="font-semibold hover:underline">create an account</a>
|
|
to join the discussion.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="space-y-4">
|
|
{% for comment in comments %}
|
|
<div class="bg-gray-50 rounded-lg p-4 border-l-4 border-blue-500">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h4 class="font-semibold text-gray-900">{{ comment.author.nickname }}</h4>
|
|
<span class="text-sm text-gray-500">
|
|
{{ comment.created_at.strftime('%B %d, %Y at %I:%M %p') }}
|
|
</span>
|
|
</div>
|
|
<p class="text-gray-700">{{ comment.content }}</p>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{% if comments|length == 0 %}
|
|
<div class="text-center py-8 text-gray-500">
|
|
<i class="fas fa-comment-slash text-4xl mb-4 opacity-50"></i>
|
|
<h5 class="text-lg font-semibold mb-2">No comments yet</h5>
|
|
<p>Be the first to share your thoughts about this adventure!</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="space-y-8">
|
|
<!-- GPS Map and Route Information -->
|
|
{% if post.gpx_files.count() > 0 %}
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
|
|
<div class="bg-gradient-to-r from-orange-600 to-red-600 p-6">
|
|
<div class="flex items-center text-white">
|
|
<i class="fas fa-route text-2xl mr-3"></i>
|
|
<div>
|
|
<h2 class="text-xl font-bold">Route Map</h2>
|
|
<p class="text-orange-100">GPS track and statistics</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6">
|
|
<div id="map" class="map-container mb-6 shadow-lg"></div>
|
|
|
|
<!-- Route Statistics -->
|
|
<div class="grid grid-cols-2 gap-4 mb-6">
|
|
<div class="text-center p-4 bg-gradient-to-br from-blue-50 to-blue-100 rounded-lg">
|
|
<div class="text-2xl font-bold text-blue-600" id="distance">-</div>
|
|
<div class="text-sm text-gray-600">Distance (km)</div>
|
|
</div>
|
|
<div class="text-center p-4 bg-gradient-to-br from-green-50 to-green-100 rounded-lg">
|
|
<div class="text-2xl font-bold text-green-600" id="elevation-gain">-</div>
|
|
<div class="text-sm text-gray-600">Elevation (m)</div>
|
|
</div>
|
|
<div class="text-center p-4 bg-gradient-to-br from-purple-50 to-purple-100 rounded-lg">
|
|
<div class="text-2xl font-bold text-purple-600" id="max-elevation">-</div>
|
|
<div class="text-sm text-gray-600">Max Elevation (m)</div>
|
|
</div>
|
|
<div class="text-center p-4 bg-gradient-to-br from-orange-50 to-orange-100 rounded-lg">
|
|
<div class="text-2xl font-bold text-orange-600" id="waypoints">-</div>
|
|
<div class="text-sm text-gray-600">Track Points</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="space-y-3">
|
|
{% for gpx_file in post.gpx_files %}
|
|
{% if current_user.is_authenticated %}
|
|
<a href="{{ gpx_file.get_url() }}" download="{{ gpx_file.original_name }}"
|
|
class="block w-full text-center px-4 py-2 bg-gradient-to-r from-green-600 to-emerald-600 text-white font-semibold rounded-lg hover:from-green-700 hover:to-emerald-700 transition-all duration-200 transform hover:scale-105">
|
|
<i class="fas fa-download mr-2"></i>
|
|
Download GPX ({{ "%.1f"|format(gpx_file.size / 1024) }} KB)
|
|
</a>
|
|
{% else %}
|
|
<a href="{{ url_for('auth.login') }}"
|
|
class="block w-full text-center px-4 py-2 bg-gray-400 text-white font-semibold rounded-lg hover:bg-gray-500 transition-all duration-200">
|
|
<i class="fas fa-lock mr-2"></i>
|
|
Login to Download GPX
|
|
</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if current_user.is_authenticated %}
|
|
<button onclick="toggleLike({{ post.id }})"
|
|
class="w-full px-4 py-2 bg-gradient-to-r from-pink-600 to-red-600 text-white font-semibold rounded-lg hover:from-pink-700 hover:to-red-700 transition-all duration-200 transform hover:scale-105">
|
|
<i class="fas fa-heart mr-2"></i>
|
|
<span id="like-text">Like this Adventure</span>
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Adventure Info -->
|
|
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
|
|
<div class="bg-gradient-to-r from-indigo-600 to-blue-600 p-6">
|
|
<div class="flex items-center text-white">
|
|
<i class="fas fa-info-circle text-2xl mr-3"></i>
|
|
<div>
|
|
<h2 class="text-xl font-bold">Adventure Info</h2>
|
|
<p class="text-indigo-100">Trip details</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="space-y-4">
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-gray-600">Difficulty</span>
|
|
<div class="flex items-center">
|
|
{% for i in range(post.difficulty) %}
|
|
<i class="fas fa-star text-yellow-500"></i>
|
|
{% endfor %}
|
|
{% for i in range(5 - post.difficulty) %}
|
|
<i class="far fa-star text-gray-300"></i>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-gray-600">Published</span>
|
|
<span class="text-gray-900">{{ post.created_at.strftime('%B %d, %Y') }}</span>
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-gray-600">Author</span>
|
|
<span class="text-gray-900">{{ post.author.nickname }}</span>
|
|
</div>
|
|
{% if post.images.count() > 0 %}
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-gray-600">Photos</span>
|
|
<span class="text-gray-900">{{ post.images.count() }}</span>
|
|
</div>
|
|
{% endif %}
|
|
{% if post.gpx_files.count() > 0 %}
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-gray-600">GPS Files</span>
|
|
<span class="text-gray-900">{{ post.gpx_files.count() }}</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Image Modal -->
|
|
<div id="imageModal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden">
|
|
<div class="relative max-w-4xl max-h-full p-4">
|
|
<button onclick="closeImageModal()" class="absolute top-2 right-2 text-white text-2xl z-10 bg-black bg-opacity-50 w-10 h-10 rounded-full flex items-center justify-center hover:bg-opacity-75">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
<img id="modalImage" src="" alt="" class="max-w-full max-h-full rounded-lg">
|
|
<div id="modalCaption" class="text-white text-center mt-4 text-lg"></div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
<script>
|
|
let map;
|
|
|
|
// Initialize map if GPX files exist
|
|
{% if post.gpx_files.count() > 0 %}
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialize map
|
|
map = L.map('map').setView([45.9432, 24.9668], 10); // Romania center as default
|
|
|
|
// Add tile layer
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
attribution: '© OpenStreetMap contributors'
|
|
}).addTo(map);
|
|
|
|
// Load and display GPX files
|
|
{% for gpx_file in post.gpx_files %}
|
|
loadGPXFile('{{ gpx_file.get_url() }}');
|
|
{% endfor %}
|
|
});
|
|
|
|
function loadGPXFile(gpxUrl) {
|
|
fetch(gpxUrl)
|
|
.then(response => response.text())
|
|
.then(gpxContent => {
|
|
const parser = new DOMParser();
|
|
const gpxDoc = parser.parseFromString(gpxContent, 'application/xml');
|
|
|
|
// Parse track points
|
|
const trackPoints = [];
|
|
const trkpts = gpxDoc.getElementsByTagName('trkpt');
|
|
let totalDistance = 0;
|
|
let elevationGain = 0;
|
|
let maxElevation = 0;
|
|
let previousPoint = null;
|
|
|
|
for (let i = 0; i < trkpts.length; i++) {
|
|
const lat = parseFloat(trkpts[i].getAttribute('lat'));
|
|
const lon = parseFloat(trkpts[i].getAttribute('lon'));
|
|
const eleElement = trkpts[i].getElementsByTagName('ele')[0];
|
|
const elevation = eleElement ? parseFloat(eleElement.textContent) : 0;
|
|
|
|
trackPoints.push([lat, lon]);
|
|
|
|
if (elevation > maxElevation) {
|
|
maxElevation = elevation;
|
|
}
|
|
|
|
if (previousPoint) {
|
|
// Calculate distance
|
|
const distance = calculateDistance(previousPoint.lat, previousPoint.lon, lat, lon);
|
|
totalDistance += distance;
|
|
|
|
// Calculate elevation gain
|
|
if (elevation > previousPoint.elevation) {
|
|
elevationGain += (elevation - previousPoint.elevation);
|
|
}
|
|
}
|
|
|
|
previousPoint = { lat: lat, lon: lon, elevation: elevation };
|
|
}
|
|
|
|
// Add track to map
|
|
if (trackPoints.length > 0) {
|
|
const polyline = L.polyline(trackPoints, {
|
|
color: '#e74c3c',
|
|
weight: 4,
|
|
opacity: 0.8
|
|
}).addTo(map);
|
|
|
|
// Fit map to track
|
|
map.fitBounds(polyline.getBounds(), { padding: [20, 20] });
|
|
|
|
// Add start and end markers
|
|
const startIcon = L.divIcon({
|
|
html: '<div class="w-6 h-6 bg-green-500 rounded-full border-2 border-white flex items-center justify-center text-white text-xs font-bold">S</div>',
|
|
className: 'custom-div-icon',
|
|
iconSize: [24, 24],
|
|
iconAnchor: [12, 12]
|
|
});
|
|
|
|
const endIcon = L.divIcon({
|
|
html: '<div class="w-6 h-6 bg-red-500 rounded-full border-2 border-white flex items-center justify-center text-white text-xs font-bold">E</div>',
|
|
className: 'custom-div-icon',
|
|
iconSize: [24, 24],
|
|
iconAnchor: [12, 12]
|
|
});
|
|
|
|
L.marker(trackPoints[0], { icon: startIcon })
|
|
.bindPopup('Start Point')
|
|
.addTo(map);
|
|
|
|
L.marker(trackPoints[trackPoints.length - 1], { icon: endIcon })
|
|
.bindPopup('End Point')
|
|
.addTo(map);
|
|
}
|
|
|
|
// Update statistics
|
|
document.getElementById('distance').textContent = totalDistance.toFixed(1);
|
|
document.getElementById('elevation-gain').textContent = Math.round(elevationGain);
|
|
document.getElementById('max-elevation').textContent = Math.round(maxElevation);
|
|
document.getElementById('waypoints').textContent = trackPoints.length;
|
|
})
|
|
.catch(error => {
|
|
console.error('Error loading GPX file:', error);
|
|
});
|
|
}
|
|
|
|
function calculateDistance(lat1, lon1, lat2, lon2) {
|
|
const R = 6371; // Earth's radius in km
|
|
const dLat = (lat2 - lat1) * Math.PI / 180;
|
|
const dLon = (lon2 - lon1) * Math.PI / 180;
|
|
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
|
|
Math.sin(dLon/2) * Math.sin(dLon/2);
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
|
return R * c;
|
|
}
|
|
{% endif %}
|
|
|
|
// Image modal functionality
|
|
function openImageModal(imageSrc, imageTitle) {
|
|
document.getElementById('modalImage').src = imageSrc;
|
|
document.getElementById('modalCaption').textContent = imageTitle;
|
|
document.getElementById('imageModal').classList.remove('hidden');
|
|
}
|
|
|
|
function closeImageModal() {
|
|
document.getElementById('imageModal').classList.add('hidden');
|
|
}
|
|
|
|
// Close modal on click outside
|
|
document.getElementById('imageModal').addEventListener('click', function(e) {
|
|
if (e.target === this) {
|
|
closeImageModal();
|
|
}
|
|
});
|
|
|
|
// Close modal on escape key
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Escape') {
|
|
closeImageModal();
|
|
}
|
|
});
|
|
|
|
// Like functionality
|
|
function toggleLike(postId) {
|
|
fetch(`/community/post/${postId}/like`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRFToken': '{{ csrf_token() }}'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
const likeBtn = document.querySelector('button[onclick*="toggleLike"]');
|
|
const likeText = document.getElementById('like-text');
|
|
|
|
if (data.liked) {
|
|
likeBtn.classList.remove('from-pink-600', 'to-red-600', 'hover:from-pink-700', 'hover:to-red-700');
|
|
likeBtn.classList.add('from-red-600', 'to-pink-600', 'hover:from-red-700', 'hover:to-pink-700');
|
|
likeText.textContent = 'Liked!';
|
|
} else {
|
|
likeBtn.classList.remove('from-red-600', 'to-pink-600', 'hover:from-red-700', 'hover:to-pink-700');
|
|
likeBtn.classList.add('from-pink-600', 'to-red-600', 'hover:from-pink-700', 'hover:to-red-700');
|
|
likeText.textContent = 'Like this Adventure';
|
|
}
|
|
|
|
// Update like count in meta section
|
|
const likeCountSpan = document.querySelector('.bg-pink-500\\/20');
|
|
if (likeCountSpan) {
|
|
likeCountSpan.innerHTML = `<i class="fas fa-heart mr-1"></i> ${data.count} likes`;
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Please log in to like posts');
|
|
});
|
|
}
|
|
</script>
|
|
{% endblock %}
|