Files
Poll-system/app/internal/templates/posts.html
2025-08-29 16:49:13 -06:00

340 lines
9.9 KiB
HTML

{{ define "content" }}
<div class="min-h-screen bg-gray-100">
<!-- Header -->
<div class="max-w-2xl mx-auto">
<!-- Create Post Form -->
<div class="bg-white border-b border-gray-200 p-6">
<form
action="/posts"
method="POST"
enctype="multipart/form-data"
class="space-y-4"
>
<div class="flex items-start space-x-4">
<div class="flex-shrink-0">
<div
class="w-10 h-10 bg-blue-500 flex items-center justify-center text-white font-semibold"
>
You
</div>
</div>
<div class="flex-1">
<textarea
id="content"
name="content"
placeholder="What's on your mind?"
class="w-full px-0 py-2 text-gray-900 placeholder-gray-500 border-0 resize-none focus:outline-none focus:ring-0"
rows="3"
required
></textarea>
</div>
</div>
<div
class="flex items-center justify-between pt-4 border-t border-gray-100"
>
<div class="flex items-center">
<label
for="image"
class="cursor-pointer flex items-center space-x-2 text-blue-500 hover:text-blue-600"
>
<svg
class="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
></path>
</svg>
<span class="text-sm font-medium">Photo</span>
</label>
<input
id="image"
type="file"
name="image"
accept="image/*"
class="hidden"
/>
</div>
<button
type="submit"
class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 text-sm font-semibold transition-colors disabled:opacity-50"
>
Post
</button>
</div>
<!-- Image preview -->
<div id="imagePreview" class="hidden">
<img
id="previewImg"
class="w-full h-64 object-cover border"
alt="Preview"
/>
<button
type="button"
id="removeImage"
class="mt-2 text-red-500 text-sm hover:text-red-600"
>
Remove image
</button>
</div>
</form>
</div>
<!-- Posts Feed -->
<div class="space-y-0">
{{range .Posts}}
<article class="bg-white border-b border-gray-200">
<!-- Post Header -->
<div class="flex items-center px-6 py-4">
<div class="flex-shrink-0">
<div
class="w-10 h-10 bg-blue-500 flex items-center justify-center text-white font-semibold"
>
{{slice .AuthorName 0 1}}
</div>
</div>
<div class="ml-4">
<p class="text-sm font-semibold text-gray-900">{{.AuthorName}}</p>
<p class="text-xs text-gray-500">
{{.CreatedAt.Format "Jan 2, 2006"}}
</p>
</div>
</div>
<!-- Post Image -->
{{if .ImageURL}}
<div class="w-full">
<img
src="{{.ImageURL}}"
alt="Post image"
class="w-full max-h-96 object-cover"
onerror="this.parentElement.style.display='none'"
/>
</div>
{{end}}
<!-- Post Content -->
{{if .Content}}
<div class="px-6 pt-2 pb-4">
<p class="text-gray-900 leading-relaxed">
<span class="font-semibold">{{.AuthorName}}</span> {{.Content}}
</p>
</div>
{{end}}
</article>
{{else}}
<div class="bg-white p-12 text-center">
<div class="max-w-sm mx-auto">
<svg
class="w-16 h-16 mx-auto text-gray-300 mb-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
></path>
</svg>
<h3 class="text-lg font-medium text-gray-900 mb-2">No posts yet</h3>
<p class="text-gray-500">
Be the first to share something with the community!
</p>
</div>
</div>
{{end}}
</div>
</div>
</div>
<style>
/* Custom styles for Instagram-like feel */
.reaction-btn.active {
color: #3b82f6 !important;
}
.reaction-btn.active svg {
fill: currentColor;
}
.reaction-btn.dislike-active {
color: #ef4444 !important;
}
/* Smooth transitions */
.reaction-btn {
transition: all 0.2s ease-in-out;
}
.reaction-btn:hover {
transform: scale(1.05);
}
/* Focus styles */
button:focus {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
input:focus,
textarea:focus {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function () {
const fileInput = document.getElementById("image");
const imagePreview = document.getElementById("imagePreview");
const previewImg = document.getElementById("previewImg");
const removeImageBtn = document.getElementById("removeImage");
const form = document.querySelector("form");
// Image upload preview
if (fileInput) {
fileInput.addEventListener("change", function (e) {
const file = e.target.files[0];
if (file) {
console.log(
"Selected file:",
file.name,
"Size:",
file.size,
"Type:",
file.type
);
// Validate file size (10MB max)
if (file.size > 10 * 1024 * 1024) {
alert("File is too large. Maximum size is 10MB.");
this.value = "";
return;
}
// Validate file type
const allowedTypes = [
"image/jpeg",
"image/jpg",
"image/png",
"image/gif",
"image/webp",
];
if (!allowedTypes.includes(file.type)) {
alert("Invalid file type. Please select a valid image file.");
this.value = "";
return;
}
// Show preview
const reader = new FileReader();
reader.onload = function (e) {
previewImg.src = e.target.result;
imagePreview.classList.remove("hidden");
};
reader.readAsDataURL(file);
}
});
}
// Remove image preview
if (removeImageBtn) {
removeImageBtn.addEventListener("click", function () {
fileInput.value = "";
imagePreview.classList.add("hidden");
previewImg.src = "";
});
}
// Reaction buttons
const reactionBtns = document.querySelectorAll(".reaction-btn");
reactionBtns.forEach(function (btn) {
btn.addEventListener("click", function (e) {
e.preventDefault();
const postId = this.dataset.postId;
const reaction = this.dataset.reaction;
// Toggle active state
if (reaction === "like") {
this.classList.toggle("active");
// Remove dislike active state from sibling
const dislikeBtn = this.parentElement.querySelector(
'[data-reaction="dislike"]'
);
dislikeBtn.classList.remove("dislike-active");
} else {
this.classList.toggle("dislike-active");
// Remove like active state from sibling
const likeBtn = this.parentElement.querySelector(
'[data-reaction="like"]'
);
likeBtn.classList.remove("active");
}
// Update count (mock implementation)
const countSpan = this.querySelector("span");
const currentCount = parseInt(countSpan.textContent);
const isActive =
this.classList.contains("active") ||
this.classList.contains("dislike-active");
countSpan.textContent = isActive
? currentCount + 1
: Math.max(0, currentCount - 1);
console.log(`${reaction} clicked for post ${postId}`);
// Here you would typically send an AJAX request to update the backend
// fetch(`/posts/${postId}/react`, {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ reaction: reaction })
// });
});
});
// Form submission
if (form) {
form.addEventListener("submit", function (e) {
const content = document.getElementById("content").value.trim();
const hasImage = fileInput.files.length > 0;
if (!content && !hasImage) {
e.preventDefault();
alert("Please add some content or an image to your post.");
return;
}
console.log("Form being submitted...");
});
}
// Auto-resize textarea
const textarea = document.getElementById("content");
if (textarea) {
textarea.addEventListener("input", function () {
this.style.height = "auto";
this.style.height = this.scrollHeight + "px";
});
}
// Smooth scroll to top when clicking header
const header = document.querySelector("h1");
if (header) {
header.addEventListener("click", function () {
window.scrollTo({ top: 0, behavior: "smooth" });
});
}
});
</script>
{{ end }}