/** * @fileoverview Vote Buttons Component for Rantii * @author retoor * @description Upvote and downvote controls for rants and comments * @keywords vote, upvote, downvote, score, rating */ import { BaseComponent } from './base-component.js'; class VoteButtons extends BaseComponent { static get observedAttributes() { return ['score', 'vote-state', 'type', 'item-id', 'disabled']; } init() { this.render(); this.bindEvents(); } render() { const score = parseInt(this.getAttr('score') || '0', 10); const voteState = parseInt(this.getAttr('vote-state') || '0', 10); const disabled = this.hasAttr('disabled'); this.addClass('vote-buttons'); this.setHtml(` ${score} `); } bindEvents() { this.on(this, 'click', this.handleClick); } handleClick(e) { const btn = e.target.closest('.vote-btn'); if (!btn || btn.disabled) return; if (!this.isLoggedIn()) { this.getRouter()?.goToLogin(); return; } const currentState = parseInt(this.getAttr('vote-state') || '0', 10); let newVote; if (btn.classList.contains('upvote')) { newVote = currentState === 1 ? 0 : 1; } else if (btn.classList.contains('downvote')) { newVote = currentState === -1 ? 0 : -1; } if (newVote !== undefined) { this.emit('vote', { vote: newVote, type: this.getAttr('type'), itemId: this.getAttr('item-id') }); } } setScore(score) { this.setAttr('score', score.toString()); const scoreEl = this.$('.vote-score'); if (scoreEl) { scoreEl.textContent = score; } } setVoteState(state) { this.setAttr('vote-state', state.toString()); this.render(); } updateVote(score, voteState) { this.setAttr('score', score.toString()); this.setAttr('vote-state', voteState.toString()); this.render(); } disable() { this.setAttr('disabled', ''); this.render(); } enable() { this.removeAttribute('disabled'); this.render(); } onAttributeChanged(name, oldValue, newValue) { this.render(); } } customElements.define('vote-buttons', VoteButtons); export { VoteButtons };