|
|
|
|
@@ -139,87 +139,148 @@
|
|
|
|
|
|
|
|
|
|
<!-- Comments -->
|
|
|
|
|
{% if page.comments_enabled %}
|
|
|
|
|
<section class="mt-16 pt-12 border-t border-zinc-200 dark:border-zinc-800">
|
|
|
|
|
<h2 class="font-display font-bold text-3xl mb-8">Comments</h2>
|
|
|
|
|
<section class="mt-20 pt-16 border-t border-zinc-200 dark:border-zinc-800">
|
|
|
|
|
<div class="flex items-baseline justify-between mb-10">
|
|
|
|
|
<h2 class="font-display font-bold text-4xl tracking-tight">Comments</h2>
|
|
|
|
|
<span class="font-mono text-sm text-zinc-500 uppercase tracking-widest">{{ approved_comments|length }} response{{ approved_comments|length|pluralize }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{% if approved_comments %}
|
|
|
|
|
<div class="space-y-8 mb-12">
|
|
|
|
|
<div class="space-y-12 mb-16">
|
|
|
|
|
{% for comment in approved_comments %}
|
|
|
|
|
<article id="comment-{{ comment.id }}" class="bg-brand-surfaceLight dark:bg-brand-surfaceDark border border-zinc-200 dark:border-zinc-800 p-6">
|
|
|
|
|
<div class="flex items-center gap-3 mb-3">
|
|
|
|
|
<div class="w-8 h-8 bg-gradient-to-tr from-brand-cyan to-brand-pink shrink-0"></div>
|
|
|
|
|
<div>
|
|
|
|
|
<div class="font-display font-bold text-sm">{{ comment.author_name }}</div>
|
|
|
|
|
<div class="font-mono text-xs text-zinc-500">{{ comment.created_at|date:"M j, Y" }}</div>
|
|
|
|
|
<div class="group">
|
|
|
|
|
<!-- Top-level Comment -->
|
|
|
|
|
<article id="comment-{{ comment.id }}" class="relative bg-brand-surfaceLight dark:bg-brand-surfaceDark border border-zinc-200 dark:border-zinc-800 p-6 sm:p-8 hover:border-brand-pink/30 transition-colors">
|
|
|
|
|
<div class="flex items-start gap-4 mb-4">
|
|
|
|
|
<div class="w-10 h-10 bg-gradient-to-tr from-brand-cyan to-brand-pink shrink-0 rounded-sm shadow-solid-dark/10 dark:shadow-solid-light/5"></div>
|
|
|
|
|
<div class="flex-1 min-w-0">
|
|
|
|
|
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1">
|
|
|
|
|
<span class="font-display font-bold text-base text-zinc-900 dark:text-zinc-100">{{ comment.author_name }}</span>
|
|
|
|
|
<time datetime="{{ comment.created_at|date:'c' }}" class="font-mono text-xs text-zinc-500 uppercase tracking-wider">{{ comment.created_at|date:"M j, Y" }}</time>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="mt-3 prose prose-sm dark:prose-invert max-w-none text-zinc-700 dark:text-zinc-300 leading-relaxed">
|
|
|
|
|
{{ comment.body|linebreaks }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<p class="text-zinc-700 dark:text-zinc-300 text-sm leading-relaxed">{{ comment.body }}</p>
|
|
|
|
|
{% for reply in comment.replies.all %}
|
|
|
|
|
<article id="comment-{{ reply.id }}" class="mt-6 ml-8 bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 p-4">
|
|
|
|
|
<div class="flex items-center gap-3 mb-2">
|
|
|
|
|
<div class="w-6 h-6 bg-gradient-to-tr from-brand-pink to-brand-cyan shrink-0"></div>
|
|
|
|
|
<div>
|
|
|
|
|
<div class="font-display font-bold text-sm">{{ reply.author_name }}</div>
|
|
|
|
|
<div class="font-mono text-xs text-zinc-500">{{ reply.created_at|date:"M j, Y" }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<p class="text-zinc-700 dark:text-zinc-300 text-sm leading-relaxed">{{ reply.body }}</p>
|
|
|
|
|
</article>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
<form method="post" action="{% url 'comment_post' %}" class="mt-4 pt-4 border-t border-zinc-100 dark:border-zinc-800">
|
|
|
|
|
|
|
|
|
|
<details class="group/details mt-6">
|
|
|
|
|
<summary class="list-none cursor-pointer flex items-center gap-2 font-mono text-xs font-bold uppercase tracking-widest text-zinc-500 hover:text-brand-pink transition-colors [&::-webkit-details-marker]:hidden">
|
|
|
|
|
<svg class="w-4 h-4 transition-transform group-open/details:-translate-y-0.5 group-open/details:translate-x-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6" />
|
|
|
|
|
</svg>
|
|
|
|
|
<span class="group-open/details:hidden">Reply</span>
|
|
|
|
|
<span class="hidden group-open/details:inline text-brand-pink">Cancel Reply</span>
|
|
|
|
|
</summary>
|
|
|
|
|
|
|
|
|
|
<!-- Inline Reply Form -->
|
|
|
|
|
<div class="mt-8 pt-8 border-t border-zinc-100 dark:border-zinc-800 animate-in fade-in slide-in-from-top-2 duration-300">
|
|
|
|
|
<h4 class="font-display font-bold text-sm mb-4 uppercase tracking-wider">Reply to {{ comment.author_name }}</h4>
|
|
|
|
|
<form method="post" action="{% url 'comment_post' %}" class="space-y-4">
|
|
|
|
|
{% csrf_token %}
|
|
|
|
|
<input type="hidden" name="article_id" value="{{ page.id }}" />
|
|
|
|
|
<input type="hidden" name="parent_id" value="{{ comment.id }}" />
|
|
|
|
|
<div class="flex gap-3 mb-3">
|
|
|
|
|
<input type="text" name="author_name" required placeholder="Your name"
|
|
|
|
|
class="flex-1 bg-transparent border border-zinc-300 dark:border-zinc-700 px-3 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors" />
|
|
|
|
|
<input type="email" name="author_email" required placeholder="your@email.com"
|
|
|
|
|
class="flex-1 bg-transparent border border-zinc-300 dark:border-zinc-700 px-3 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors" />
|
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
|
|
|
<input type="text" name="author_name" required placeholder="Name *"
|
|
|
|
|
class="bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:ring-1 focus:ring-brand-pink transition-all" />
|
|
|
|
|
<input type="email" name="author_email" required placeholder="Email *"
|
|
|
|
|
class="bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:ring-1 focus:ring-brand-pink transition-all" />
|
|
|
|
|
</div>
|
|
|
|
|
<textarea name="body" required placeholder="Your reply..." rows="3"
|
|
|
|
|
class="w-full bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:ring-1 focus:ring-brand-pink transition-all resize-none"></textarea>
|
|
|
|
|
<input type="text" name="honeypot" hidden />
|
|
|
|
|
<div class="flex justify-end gap-3">
|
|
|
|
|
<button type="submit" data-testid="post-reply-btn" class="px-6 py-2 bg-brand-pink text-white font-display font-bold text-sm shadow-solid-dark hover:-translate-y-0.5 hover:shadow-solid-dark/80 transition-all active:translate-y-0">Post Reply</button>
|
|
|
|
|
</div>
|
|
|
|
|
<textarea name="body" required placeholder="Write a reply..." rows="2"
|
|
|
|
|
class="w-full bg-transparent border border-zinc-300 dark:border-zinc-700 px-3 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors mb-3 resize-none"></textarea>
|
|
|
|
|
<input type="text" name="honeypot" hidden /> <button type="submit" class="px-4 py-2 bg-zinc-200 dark:bg-zinc-800 font-display font-bold text-sm hover:bg-brand-pink hover:text-white transition-colors">Reply</button>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</details>
|
|
|
|
|
</article>
|
|
|
|
|
|
|
|
|
|
<!-- Nested Replies -->
|
|
|
|
|
{% if comment.replies.all %}
|
|
|
|
|
<div class="relative ml-6 sm:ml-12 mt-4 space-y-4 pl-6 sm:pl-8 border-l-2 border-zinc-100 dark:border-zinc-800">
|
|
|
|
|
{% for reply in comment.replies.all %}
|
|
|
|
|
<article id="comment-{{ reply.id }}" class="bg-zinc-50/50 dark:bg-zinc-900/30 border border-zinc-100 dark:border-zinc-800 p-5 sm:p-6">
|
|
|
|
|
<div class="flex items-start gap-3 mb-3">
|
|
|
|
|
<div class="w-8 h-8 bg-gradient-to-tr from-brand-pink to-brand-cyan shrink-0 rounded-sm"></div>
|
|
|
|
|
<div class="flex-1 min-w-0">
|
|
|
|
|
<div class="flex flex-wrap items-baseline gap-x-2">
|
|
|
|
|
<span class="font-display font-bold text-sm text-zinc-900 dark:text-zinc-100">{{ reply.author_name }}</span>
|
|
|
|
|
<time datetime="{{ reply.created_at|date:'c' }}" class="font-mono text-[10px] text-zinc-400 uppercase tracking-wider">{{ reply.created_at|date:"M j, Y" }}</time>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="mt-2 prose prose-sm dark:prose-invert max-w-none text-zinc-600 dark:text-zinc-400 leading-relaxed text-sm">
|
|
|
|
|
{{ reply.body|linebreaks }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</article>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
{% else %}
|
|
|
|
|
<p class="font-mono text-sm text-zinc-500 mb-12">No comments yet. Be the first to comment.</p>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
{% else %}
|
|
|
|
|
<div class="bg-zinc-50 dark:bg-zinc-900/50 border-2 border-dashed border-zinc-200 dark:border-zinc-800 p-12 text-center mb-16">
|
|
|
|
|
<p class="font-mono text-sm text-zinc-500 uppercase tracking-widest">No comments yet. Be the first to join the conversation.</p>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
|
|
<!-- New Comment Form Section -->
|
|
|
|
|
<div class="relative bg-zinc-900 text-white dark:bg-white dark:text-zinc-900 p-8 sm:p-12 shadow-solid-pink">
|
|
|
|
|
<div class="max-w-2xl">
|
|
|
|
|
<h3 class="font-display font-bold text-3xl mb-2">Join the conversation</h3>
|
|
|
|
|
<p class="font-mono text-sm text-zinc-400 dark:text-zinc-500 mb-10 uppercase tracking-widest">Add your fresh comment below</p>
|
|
|
|
|
|
|
|
|
|
{% if comment_form and comment_form.errors %}
|
|
|
|
|
<div aria-label="Comment form errors" class="mb-6 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 font-mono text-sm text-red-600 dark:text-red-400">
|
|
|
|
|
{{ comment_form.non_field_errors }}
|
|
|
|
|
{% for field in comment_form %}{{ field.errors }}{% endfor %}
|
|
|
|
|
<div aria-label="Comment form errors" class="mb-8 p-4 bg-red-500/10 border border-red-500/20 font-mono text-sm text-red-400">
|
|
|
|
|
<div class="font-bold mb-2 uppercase tracking-widest text-xs">There were some errors:</div>
|
|
|
|
|
<ul class="list-disc list-inside">
|
|
|
|
|
{% if comment_form.non_field_errors %}
|
|
|
|
|
{% for error in comment_form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% for field in comment_form %}
|
|
|
|
|
{% if field.errors %}
|
|
|
|
|
{% for error in field.errors %}<li>{{ field.label }}: {{ error }}</li>{% endfor %}
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
|
|
<div class="bg-brand-surfaceLight dark:bg-brand-surfaceDark border border-zinc-200 dark:border-zinc-800 p-6">
|
|
|
|
|
<h3 class="font-display font-bold text-xl mb-6">Post a Comment</h3>
|
|
|
|
|
<form method="post" action="{% url 'comment_post' %}" data-comment-form class="space-y-4">
|
|
|
|
|
<form method="post" action="{% url 'comment_post' %}" data-comment-form class="space-y-6">
|
|
|
|
|
{% csrf_token %}
|
|
|
|
|
<input type="hidden" name="article_id" value="{{ page.id }}" />
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block font-mono text-xs text-zinc-500 mb-1 uppercase tracking-wider">Name *</label>
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
|
|
<div class="space-y-2">
|
|
|
|
|
<label class="block font-mono text-[10px] uppercase tracking-[0.2em] opacity-60">Full Name</label>
|
|
|
|
|
<input type="text" name="author_name" value="{% if comment_form %}{{ comment_form.author_name.value|default:'' }}{% endif %}" required
|
|
|
|
|
class="w-full bg-transparent border border-zinc-300 dark:border-zinc-700 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors" />
|
|
|
|
|
class="w-full bg-white/5 dark:bg-black/5 border-b-2 border-white/20 dark:border-black/20 px-0 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors" />
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block font-mono text-xs text-zinc-500 mb-1 uppercase tracking-wider">Email *</label>
|
|
|
|
|
<div class="space-y-2">
|
|
|
|
|
<label class="block font-mono text-[10px] uppercase tracking-[0.2em] opacity-60">Email Address</label>
|
|
|
|
|
<input type="email" name="author_email" value="{% if comment_form %}{{ comment_form.author_email.value|default:'' }}{% endif %}" required
|
|
|
|
|
class="w-full bg-transparent border border-zinc-300 dark:border-zinc-700 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors" />
|
|
|
|
|
class="w-full bg-white/5 dark:bg-black/5 border-b-2 border-white/20 dark:border-black/20 px-0 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block font-mono text-xs text-zinc-500 mb-1 uppercase tracking-wider">Comment *</label>
|
|
|
|
|
<div class="space-y-2">
|
|
|
|
|
<label class="block font-mono text-[10px] uppercase tracking-[0.2em] opacity-60">Your Thoughts</label>
|
|
|
|
|
<textarea name="body" required rows="5"
|
|
|
|
|
class="w-full bg-transparent border border-zinc-300 dark:border-zinc-700 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors resize-none">{% if comment_form %}{{ comment_form.body.value|default:'' }}{% endif %}</textarea>
|
|
|
|
|
class="w-full bg-white/5 dark:bg-black/5 border-b-2 border-white/20 dark:border-black/20 px-0 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink transition-colors resize-none">{% if comment_form %}{{ comment_form.body.value|default:'' }}{% endif %}</textarea>
|
|
|
|
|
</div>
|
|
|
|
|
<input type="text" name="honeypot" hidden />
|
|
|
|
|
<button type="submit" class="px-6 py-3 bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark font-display font-bold hover:-translate-y-1 hover:shadow-solid-dark dark:hover:shadow-solid-light transition-all">Post comment</button>
|
|
|
|
|
<div class="pt-4">
|
|
|
|
|
<button type="submit" class="group relative inline-flex items-center gap-3 px-8 py-4 bg-brand-pink text-white font-display font-bold uppercase tracking-widest text-sm hover:-translate-y-1 transition-all active:translate-y-0">
|
|
|
|
|
<span>Post comment</span>
|
|
|
|
|
<svg class="w-4 h-4 transition-transform group-hover:translate-x-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|