class QuoteApp { constructor() { this.quotes = []; this.author = "Денис Шулепов"; this.serverUrl = window.location.origin; this.init(); } init() { this.bindEvents(); this.loadQuotes(); } async loadQuotes() { try { const response = await fetch(`${this.serverUrl}/api/quotes`); if (response.ok) { this.quotes = await response.json(); this.renderQuotes(); } else { throw new Error("Ошибка загрузки цитат"); } } catch (error) { console.error("Ошибка при загрузке цитат:", error); this.showError("Не удалось загрузить цитаты с сервера"); this.showEmptyState(); } } bindEvents() { // События удалены - только автоматическая публикация } showEmptyState() { const quotesFeed = document.getElementById("quotesFeed"); quotesFeed.innerHTML = `

Добро пожаловать в гейский цитатник!

Ожидаем первую автоматическую публикацию цитаты...

`; } renderQuotes() { const quotesFeed = document.getElementById("quotesFeed"); if (this.quotes.length === 0) { this.showEmptyState(); return; } quotesFeed.innerHTML = this.quotes .map((quote) => this.createQuoteCard(quote)) .join(""); this.bindQuoteActions(); } createQuoteCard(quote) { const date = new Date(quote.date).toLocaleDateString("ru-RU", { day: "numeric", month: "long", year: "numeric", hour: "2-digit", minute: "2-digit", }); return `
${this.escapeHtml(
                      quote.author
                    )}
${this.escapeHtml( quote.author )}
${date}
${this.escapeHtml(quote.text)}
`; } bindQuoteActions() { // Дополнительные обработчики для карточек цитат } async generateNewQuote() { const loading = document.getElementById("loading"); loading.style.display = "block"; try { const response = await fetch(`${this.serverUrl}/api/quotes`, { method: "POST", }); if (response.ok) { const newQuote = await response.json(); this.quotes.unshift(newQuote); this.renderQuotes(); this.showSuccess("Новая цитата создана!"); } else { throw new Error("Ошибка сервера"); } } catch (error) { console.error("Ошибка при генерации цитаты:", error); this.showError( "Не удалось сгенерировать цитату. Проверьте подключение к серверу." ); } finally { loading.style.display = "none"; } } async deleteQuote(id) { if (confirm("Вы уверены, что хотите удалить эту цитату?")) { try { const response = await fetch(`${this.serverUrl}/api/quotes/${id}`, { method: "DELETE", }); if (response.ok) { this.quotes = this.quotes.filter((q) => q.id !== id); this.renderQuotes(); this.showSuccess("Цитата удалена!"); } else { throw new Error("Ошибка сервера"); } } catch (error) { console.error("Ошибка при удалении цитаты:", error); this.showError("Не удалось удалить цитату"); } } } copyQuote(id) { const quote = this.quotes.find((q) => q.id === id); if (quote) { const text = `"${quote.text}"\n— ${quote.author}`; if (navigator.clipboard) { navigator.clipboard .writeText(text) .then(() => { this.showSuccess("Цитата скопирована в буфер обмена!"); }) .catch(() => { this.fallbackCopyToClipboard(text); }); } else { this.fallbackCopyToClipboard(text); } } } fallbackCopyToClipboard(text) { const textArea = document.createElement("textarea"); textArea.value = text; textArea.style.position = "fixed"; textArea.style.left = "-999999px"; textArea.style.top = "-999999px"; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { document.execCommand("copy"); this.showSuccess("Цитата скопирована в буфер обмена!"); } catch (err) { console.error("Не удалось скопировать текст:", err); this.showError("Не удалось скопировать цитату"); } document.body.removeChild(textArea); } showError(message) { this.showNotification(message, "error"); } showSuccess(message) { this.showNotification(message, "success"); } showNotification(message, type = "info") { const notification = document.createElement("div"); notification.className = `notification notification-${type}`; notification.textContent = message; notification.style.cssText = ` position: fixed; top: 20px; right: 20px; background: ${ type === "error" ? "#e74c3c" : type === "success" ? "#27ae60" : "#ff6b9d" }; color: white; padding: 15px 20px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); z-index: 1000; max-width: 300px; font-size: 14px; animation: slideIn 0.3s ease-out; `; document.body.appendChild(notification); setTimeout(() => { notification.style.animation = "slideOut 0.3s ease-out"; setTimeout(() => { document.body.removeChild(notification); }, 300); }, 3000); } escapeHtml(text) { const div = document.createElement("div"); div.textContent = text; return div.innerHTML; } } // Добавляем стили для анимаций уведомлений const style = document.createElement("style"); style.textContent = ` @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slideOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(100%); opacity: 0; } } `; document.head.appendChild(style); // Инициализация приложения const app = new QuoteApp();