/** * @fileoverview Post Form Component for Rantii * @author retoor * @description Form for creating new rants * @keywords post, form, create, rant, new */ import { BaseComponent } from './base-component.js'; class PostForm extends BaseComponent { init() { this.isSubmitting = false; this.render(); this.bindEvents(); this.loadDraft(); } render() { const isLoggedIn = this.isLoggedIn(); this.addClass('post-form'); if (!isLoggedIn) { this.setHtml(`

Sign in to post

`); return; } this.setHtml(`

Create Rant

0 / 5000
`); } 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'); const closeBtn = e.target.closest('.close-btn'); if (loginBtn) { this.getRouter()?.goToLogin(); return; } if (closeBtn) { this.emit('close'); } } async handleSubmit(e) { e.preventDefault(); if (this.isSubmitting) return; const textarea = this.$('.post-input'); const tagsInput = this.$('.tags-input'); if (!textarea) return; const text = textarea.value.trim(); if (!text) { this.getApp()?.toast?.error('Please enter some text'); return; } const tags = tagsInput ? tagsInput.value.trim() : ''; this.isSubmitting = true; this.render(); try { const result = await this.getApi()?.postRant(text, tags); if (result?.success) { this.clearDraft(); this.emit('post-created', { rantId: result.rantId }); this.getApp()?.toast?.success('Rant posted successfully'); this.isSubmitting = false; this.render(); this.getRouter()?.goToRant(result.rantId); } else { this.getApp()?.toast?.error(result?.error || 'Failed to post'); this.isSubmitting = false; this.render(); } } catch (error) { this.getApp()?.toast?.error('Failed to post'); this.isSubmitting = false; this.render(); } } handleInput(e) { if (e.target.classList.contains('post-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 draft = this.getStorage()?.getDraftRant(); if (draft) { const textarea = this.$('.post-input'); if (textarea) { textarea.value = draft; const countEl = this.$('.char-count'); if (countEl) { countEl.textContent = `${draft.length} / 5000`; } } } } saveDraft(text) { this.getStorage()?.setDraftRant(text); } clearDraft() { this.getStorage()?.clearDraftRant(); } reset() { const textarea = this.$('.post-input'); if (textarea) { textarea.value = ''; } const tagsInput = this.$('.tags-input'); if (tagsInput) { tagsInput.value = ''; } const countEl = this.$('.char-count'); if (countEl) { countEl.textContent = '0 / 5000'; } this.clearDraft(); } focus() { const textarea = this.$('.post-input'); if (textarea) { textarea.focus(); } } } customElements.define('post-form', PostForm); class PostModal extends BaseComponent { init() { this.keydownHandler = (e) => this.handleKeydown(e); this.render(); this.bindEvents(); } render() { this.addClass('modal', 'post-modal'); this.setHtml(` `); requestAnimationFrame(() => this.addClass('modal-visible')); } bindEvents() { this.on(this, 'click', this.handleClick); this.on(this, 'close', this.close); this.on(this, 'post-created', this.close); document.addEventListener('keydown', this.keydownHandler); } handleClick(e) { if (e.target.classList.contains('modal-backdrop')) { this.close(); } } handleKeydown(e) { if (e.key === 'Escape') { this.close(); } } close() { document.removeEventListener('keydown', this.keydownHandler); this.removeClass('modal-visible'); setTimeout(() => this.remove(), 300); } open() { document.body.appendChild(this); const form = this.$('post-form'); if (form) { form.focus(); } } } customElements.define('post-modal', PostModal); export { PostForm, PostModal };