techtalk/templates/index.html

221 lines
9.7 KiB
HTML
Raw Normal View History

2024-09-20 17:13:37 +02:00
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<div class="container">
<h1 class="mb-4">TechTalks</h1>
<!-- Sorting options -->
<div class="mb-3">
<label for="sort-select" class="form-label">Sort by:</label>
<select id="sort-select" class="form-select">
<option value="newest">Newest</option>
<option value="oldest">Oldest</option>
<option value="most_liked">Most Liked</option>
<option value="most_commented">Most Commented</option>
</select>
</div>
<!-- Posts container -->
<div id="posts-container">
{% for post in posts %}
<div class="card mb-3" id="post-{{ post.id }}">
<div class="card-body">
<div class="d-flex align-items-center mb-2">
{% if post.author %}
{% if post.author.profile_picture %}
<img src="{{ url_for('static', filename='uploads/' + post.author.profile_picture) }}" class="rounded-circle me-2" alt="Profile Picture" style="width: 30px; height: 30px; object-fit: cover;">
{% else %}
<div class="rounded-circle me-2 d-flex justify-content-center align-items-center bg-primary" style="width: 30px; height: 30px;">
<span class="text-white" style="font-size: 0.8rem;">{{ post.author.username[0].upper() }}</span>
</div>
{% endif %}
<small class="text-muted">
<a href="{{ url_for('profile', username=post.author.username) }}" class="text-decoration-none">{{ post.author.username }}</a>
</small>
{% else %}
<small class="text-muted">{{ post.anonymous_username }}</small>
{% endif %}
<span class="ms-auto text-muted">{{ post.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</span>
</div>
<p class="card-text">{{ post.content|safe }}</p>
{% if post.image_url %}
<img src="{{ url_for('static', filename='uploads/' + post.image_url) }}" class="img-fluid mb-2 post-image" alt="Post image" data-bs-toggle="modal" data-bs-target="#imageModal{{ post.id }}">
{% endif %}
<div class="d-flex flex-wrap justify-content-between align-items-center">
<div class="btn-group mb-2">
<button class="btn btn-outline-primary btn-sm like-btn" data-post-id="{{ post.id }}">
<i class="bi bi-heart-fill"></i> Like (<span class="like-count">{{ post.likes|length }}</span>)
</button>
<button class="btn btn-outline-secondary btn-sm comment-btn" data-post-id="{{ post.id }}">
<i class="bi bi-chat-fill"></i> Comment ({{ post.comments|length }})
</button>
</div>
<div class="btn-group mb-2">
<a href="{{ url_for('post_detail', post_id=post.id) }}" class="btn btn-outline-info btn-sm" target="_blank">
<i class="bi bi-box-arrow-up-right"></i> Open in new tab
</a>
<button class="btn btn-outline-info btn-sm copy-link-btn" data-post-url="{{ url_for('post_detail', post_id=post.id, _external=True, _scheme='https') }}">
<i class="bi bi-link-45deg"></i> Copy Link
</button>
{% if current_user.is_authenticated and current_user.id == post.author.id %}
<a href="{{ url_for('edit_post', post_id=post.id) }}" class="btn btn-outline-warning btn-sm">
<i class="bi bi-pencil-fill"></i> Edit
</a>
{% endif %}
</div>
</div>
</div>
<div class="comment-section" id="comment-section-{{ post.id }}" style="display: none;">
<div class="card-body pt-0">
<h6 class="mb-3">Comments:</h6>
<ul class="list-unstyled mb-3">
{% for comment in post.comments %}
{% include 'comment.html' %}
{% endfor %}
</ul>
<form class="comment-form" data-post-id="{{ post.id }}">
<div class="input-group">
<input type="text" class="form-control" placeholder="Add a comment" name="content" required>
<button class="btn btn-outline-secondary" type="submit">Send</button>
</div>
</form>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
{% block scripts %}
{{ super() }}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Sorting functionality
const sortSelect = document.getElementById('sort-select');
const postsContainer = document.getElementById('posts-container');
sortSelect.addEventListener('change', function() {
const sortOption = this.value;
fetch(`/sort_posts?sort=${sortOption}`)
.then(response => response.text())
.then(html => {
postsContainer.innerHTML = html;
// Reinitialize any event listeners for the new content
initializePostInteractions();
})
.catch(error => console.error('Error:', error));
});
function initializePostInteractions() {
// Re-initialize like buttons
document.querySelectorAll('.like-btn').forEach(button => {
button.addEventListener('click', handleLike);
});
// Re-initialize comment buttons
document.querySelectorAll('.comment-btn').forEach(button => {
button.addEventListener('click', handleComment);
});
// Re-initialize copy link buttons
document.querySelectorAll('.copy-link-btn').forEach(button => {
button.addEventListener('click', handleCopyLink);
});
// Re-initialize comment forms
document.querySelectorAll('.comment-form').forEach(form => {
form.addEventListener('submit', handleCommentSubmit);
});
// Initialize comment like buttons
document.querySelectorAll('.like-comment-btn').forEach(button => {
button.addEventListener('click', handleCommentLike);
});
}
function handleLike(event) {
// Implement like functionality
var postId = this.dataset.postId;
fetch('/like/' + postId, { method: 'POST' })
.then(response => response.json())
.then(data => {
this.querySelector('.like-count').textContent = data.likes;
});
}
function handleComment(event) {
var postId = this.dataset.postId;
var commentSection = document.getElementById('comment-section-' + postId);
if (commentSection.style.display === 'none' || commentSection.style.display === '') {
commentSection.style.display = 'block';
} else {
commentSection.style.display = 'none';
}
}
function handleCommentLike(event) {
event.preventDefault();
var commentId = this.dataset.commentId;
fetch('/like_comment/' + commentId, { method: 'POST' })
.then(response => response.json())
.then(data => {
this.querySelector('.comment-like-count').textContent = data.likes;
});
}
function handleCommentSubmit(event) {
event.preventDefault();
var postId = this.dataset.postId;
var content = this.querySelector('input[name="content"]').value;
fetch('/comment/' + postId, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'content=' + encodeURIComponent(content)
})
.then(response => response.json())
.then(data => {
if (data.success) {
var commentList = document.querySelector('#comment-section-' + postId + ' ul');
var newComment = document.createElement('li');
newComment.innerHTML = '<strong>' + (data.username !== 'Anonymous' ? '<a href="/profile/' + data.username + '">' + data.username + '</a>' : '<span class="text-white">Anonymous</span>') + ':</strong> ' + data.content +
'<button class="btn btn-sm btn-outline-primary like-comment-btn" data-comment-id="' + data.comment_id + '">' +
'<i class="bi bi-heart-fill"></i> (<span class="comment-like-count">0</span>)</button>';
commentList.appendChild(newComment);
this.querySelector('input[name="content"]').value = '';
newComment.querySelector('.like-comment-btn').addEventListener('click', handleCommentLike);
}
});
}
function handleCopyLink(event) {
var postUrl = this.dataset.postUrl;
navigator.clipboard.writeText(postUrl).then(function() {
alert('Link copied to clipboard!');
}, function(err) {
console.error('Could not copy text: ', err);
});
}
// Initialize interactions for the initial page load
initializePostInteractions();
});
</script>
{% endblock %}
{% block styles %}
{{ super() }}
<style>
.comment-section {
border-top: 1px solid rgba(0,0,0,.125);
}
.comment-section .card-body {
padding-top: 1rem;
}
</style>
{% endblock %}