/**
* @fileoverview Comment Form Component for Rantii
* @author retoor <retoor@molodetz.nl>
* @description Form for posting new comments
* @keywords comment, form, post, reply, input
*/
import { BaseComponent } from './base-component.js';
class CommentForm extends BaseComponent {
static get observedAttributes() {
return ['rant-id'];
}
init() {
this.isSubmitting = false;
this.render();
this.bindEvents();
this.loadDraft();
}
render() {
const rantId = this.getAttr('rant-id');
const isLoggedIn = this.isLoggedIn();
this.addClass('comment-form');
if (!isLoggedIn) {
this.setHtml(`
<div class="comment-form-auth">
<p>Sign in to comment</p>
<button class="btn btn-primary login-btn">Sign In</button>
</div>
`);
return;
}
this.setHtml(`
<form class="comment-form-inner">
<div class="form-group">
<textarea
class="comment-input"
placeholder="Write a comment..."
rows="3"
maxlength="5000"
${this.isSubmitting ? 'disabled' : ''}></textarea>
</div>
<div class="form-actions">
<span class="char-count">0 / 5000</span>
<button type="submit"
class="btn btn-primary submit-btn"
${this.isSubmitting ? 'disabled' : ''}>
${this.isSubmitting ? '<loading-spinner size="small"></loading-spinner>' : 'Post'}
</button>
</div>
</form>
`);
}
bindEvents() {
this.on(this, 'click', this.handleClick);
this.on(this, 'submit', this.handleSubmit);
this.on(this, 'input', this.handleInput);
}
handleClick(e) {
const loginBtn = e.target.closest('.login-btn');
if (loginBtn) {
this.getRouter()?.goToLogin();
}
}
async handleSubmit(e) {
e.preventDefault();
if (this.isSubmitting) return;
const textarea = this.$('.comment-input');
if (!textarea) return;
const text = textarea.value.trim();
if (!text) return;
const rantId = this.getAttr('rant-id');
if (!rantId) return;
this.isSubmitting = true;
this.render();
try {
const result = await this.getApi()?.postComment(rantId, text);
if (result?.success) {
this.clearDraft();
this.emit('comment-posted', { rantId, comment: result.comment });
this.isSubmitting = false;
this.render();
} else {
this.getApp()?.toast?.error(result?.error || 'Failed to post comment');
this.isSubmitting = false;
this.render();
}
} catch (error) {
this.getApp()?.toast?.error('Failed to post comment');
this.isSubmitting = false;
this.render();
}
}
handleInput(e) {
if (e.target.classList.contains('comment-input')) {
const textarea = e.target;
const count = textarea.value.length;
const countEl = this.$('.char-count');
if (countEl) {
countEl.textContent = `${count} / 5000`;
}
this.saveDraft(textarea.value);
}
}
loadDraft() {
const rantId = this.getAttr('rant-id');
if (rantId) {
const draft = this.getStorage()?.getDraftComment(rantId);
if (draft) {
const textarea = this.$('.comment-input');
if (textarea) {
textarea.value = draft;
const countEl = this.$('.char-count');
if (countEl) {
countEl.textContent = `${draft.length} / 5000`;
}
}
}
}
}
saveDraft(text) {
const rantId = this.getAttr('rant-id');
if (rantId) {
this.getStorage()?.setDraftComment(rantId, text);
}
}
clearDraft() {
const rantId = this.getAttr('rant-id');
if (rantId) {
this.getStorage()?.clearDraftComment(rantId);
}
}
reset() {
const textarea = this.$('.comment-input');
if (textarea) {
textarea.value = '';
}
const countEl = this.$('.char-count');
if (countEl) {
countEl.textContent = '0 / 5000';
}
this.clearDraft();
}
focus() {
const textarea = this.$('.comment-input');
if (textarea) {
textarea.focus();
}
}
onAttributeChanged(name, oldValue, newValue) {
if (name === 'rant-id') {
this.loadDraft();
}
}
}
customElements.define('comment-form', CommentForm);
export { CommentForm };