import { t, i18n } from '../../i18n.js' import { auth } from '../../services/auth.js' import { favoritesService } from '../../services/favorites.js' import { getCurrencySymbol, SUPPORTED_CURRENCIES } from '../../services/currency.js' class PageSettings extends HTMLElement { constructor() { super() this.isLoggedIn = false this.user = null this.uidVisible = false } async connectedCallback() { this.isLoggedIn = auth.isLoggedIn() if (!this.isLoggedIn) { window.location.hash = '#/' return } this.user = await auth.getUser() this.render() this.setupEventListeners() this._unsubs = [] this._unsubs.push(i18n.subscribe(() => { this.render() this.setupEventListeners() })) this._unsubs.push(auth.subscribe(() => { this.isLoggedIn = auth.isLoggedIn() if (!this.isLoggedIn) { window.location.hash = '#/' } })) } disconnectedCallback() { this._unsubs.forEach(fn => fn()) this._unsubs = [] } setupEventListeners() { // Theme toggle this.querySelectorAll('input[name="theme"]').forEach(input => { input.addEventListener('change', (e) => { this.setTheme(e.target.value) }) }) // Language select this.querySelector('#lang-select')?.addEventListener('change', async (e) => { i18n.setLocale(e.target.value) // Save to user profile if logged in if (this.isLoggedIn) { await auth.updatePreferences({ preferred_locale: e.target.value }) } }) // Currency select this.querySelector('#currency-select')?.addEventListener('change', async (e) => { await this.setCurrency(e.target.value) this.showToast(t('settings.currencyChanged')) }) // Clear favorites this.querySelector('#clear-favorites')?.addEventListener('click', async () => { if (confirm(t('settings.confirmClearFavorites'))) { const ids = favoritesService.getAll() for (const id of ids) { await favoritesService.toggle(id) } this.showToast(t('settings.favoritesCleared')) } }) // Clear search history this.querySelector('#clear-search')?.addEventListener('click', () => { if (confirm(t('settings.confirmClearSearch'))) { localStorage.removeItem('searchFilters') this.showToast(t('settings.searchCleared')) } }) // Delete all local data this.querySelector('#clear-all-data')?.addEventListener('click', async () => { if (confirm(t('settings.confirmDeleteAll'))) { await auth.clearAllData() window.location.hash = '#/' window.location.reload() } }) // Toggle UUID visibility this.querySelector('#toggle-uid-btn')?.addEventListener('click', () => { this.uidVisible = !this.uidVisible const display = this.querySelector('#user-id-display') const eyeIcon = this.querySelector('#toggle-uid-btn .icon-eye') const eyeOffIcon = this.querySelector('#toggle-uid-btn .icon-eye-off') if (display) { display.textContent = this.uidVisible ? auth.getStoredUuid() : '••••••••-••••-••••-••••-••••••••••••' } if (eyeIcon) eyeIcon.style.display = this.uidVisible ? 'none' : 'block' if (eyeOffIcon) eyeOffIcon.style.display = this.uidVisible ? 'block' : 'none' }) // Copy UUID this.querySelector('#copy-uid-btn')?.addEventListener('click', async () => { const uuid = auth.getStoredUuid() if (uuid) { await navigator.clipboard.writeText(uuid) this.showToast(t('auth.copy') + ' ✓') } }) // Logout this.querySelector('#logout-btn')?.addEventListener('click', () => { auth.logout() this.showToast(t('settings.loggedOut')) }) // Login this.querySelector('#login-btn')?.addEventListener('click', () => { document.querySelector('auth-modal')?.show() }) } setTheme(theme) { if (theme === 'system') { localStorage.removeItem('theme') const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches document.documentElement.dataset.theme = prefersDark ? 'dark' : 'light' } else { localStorage.setItem('theme', theme) document.documentElement.dataset.theme = theme } } getCurrentTheme() { return localStorage.getItem('theme') || 'system' } getCurrentCurrency() { return localStorage.getItem('kashilo_currency') || 'USD' } async setCurrency(currency) { localStorage.setItem('kashilo_currency', currency) window.dispatchEvent(new CustomEvent('currency-changed', { detail: { currency } })) // Save to user profile if logged in if (auth.isLoggedIn()) { await auth.updatePreferences({ preferred_currency: currency }) } } showToast(message) { const existing = document.querySelector('.settings-toast') existing?.remove() const toast = document.createElement('div') toast.className = 'settings-toast' toast.textContent = message document.body.appendChild(toast) requestAnimationFrame(() => toast.classList.add('visible')) setTimeout(() => { toast.classList.remove('visible') setTimeout(() => toast.remove(), 300) }, 2000) } render() { const currentTheme = this.getCurrentTheme() const currentLang = i18n.getLocale() const user = this.user this.innerHTML = /* html */`

${t('settings.appearance')}

${t('settings.account')}

${this.isLoggedIn ? /* html */`

${t('settings.userIdHint')}

${'•'.repeat(8)}-••••-••••-••••-${'•'.repeat(12)}
` : /* html */`

${t('settings.notLoggedIn')}

`}

${t('settings.data')}

${t('settings.favoritesHint')}

${t('settings.searchHistoryHint')}

${t('settings.deleteAllDataHint')}

${t('settings.about')}

kashilo.com v1.0.0

` } } customElements.define('page-settings', PageSettings) const style = document.createElement('style') style.textContent = /* css */` page-settings .settings-page { padding: var(--space-lg) 0; max-width: 600px; } page-settings .page-header { margin-bottom: var(--space-xl); } page-settings .page-header h1 { margin: 0; } page-settings .settings-sections { display: flex; flex-direction: column; gap: var(--space-xl); } page-settings .settings-section { background: var(--color-bg-secondary); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--space-lg); } page-settings .settings-section h2 { font-size: var(--font-size-lg); margin: 0 0 var(--space-lg); padding-bottom: var(--space-sm); border-bottom: 1px solid var(--color-border); } page-settings .setting-item { display: flex; justify-content: space-between; align-items: center; gap: var(--space-md); padding: var(--space-sm) 0; } page-settings .setting-item-column { flex-direction: column; align-items: stretch; } page-settings .setting-item + .setting-item { border-top: 1px solid var(--color-border); margin-top: var(--space-sm); padding-top: var(--space-md); } page-settings .setting-item > label { font-weight: var(--font-weight-medium); } page-settings .setting-hint { font-size: var(--font-size-sm); color: var(--color-text-muted); margin: var(--space-xs) 0 0; } page-settings .theme-options { display: flex; gap: var(--space-sm); } page-settings .theme-option { display: flex; align-items: center; gap: var(--space-xs); padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; font-size: var(--font-size-sm); transition: all var(--transition-fast); } page-settings .theme-option:has(input:checked) { border-color: var(--color-primary); background: var(--color-primary-light); } page-settings .theme-option input { display: none; } page-settings select { padding: var(--space-xs) var(--space-sm); border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); color: var(--color-text); font-size: var(--font-size-sm); } page-settings .user-id-row { display: flex; align-items: center; gap: var(--space-xs); flex-wrap: wrap; } page-settings .user-id-actions { display: flex; gap: var(--space-xs); } @media (max-width: 768px) { page-settings .user-id-row { flex-direction: column; align-items: stretch; } page-settings .user-id-actions { justify-content: flex-end; } } page-settings .user-id { flex: 1; min-width: 0; padding: var(--space-xs) var(--space-sm); background: var(--color-bg-tertiary); border-radius: var(--radius-sm); font-size: var(--font-size-sm); word-break: break-all; letter-spacing: 0.05em; } page-settings .btn-icon-sm { width: 32px; height: 32px; padding: 0; flex-shrink: 0; } page-settings .btn-ghost { background: transparent; border: none; color: var(--color-text-muted); cursor: pointer; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; transition: color var(--transition-fast), background var(--transition-fast); } page-settings .btn-ghost:hover { color: var(--color-text); background: var(--color-bg-secondary); } page-settings .btn-danger { color: var(--color-error, #dc2626); border-color: var(--color-error, #dc2626); } page-settings .btn-danger:hover { background: var(--color-error, #dc2626); color: white; } page-settings .about-links { display: flex; flex-wrap: wrap; gap: var(--space-md); margin-bottom: var(--space-md); } page-settings .about-links a { color: var(--color-text-secondary); text-decoration: none; } page-settings .about-links a:hover { color: var(--color-primary); } page-settings .version { font-size: var(--font-size-sm); color: var(--color-text-muted); margin: 0; } @media (max-width: 768px) { page-settings .setting-item { flex-direction: column; align-items: flex-start; } page-settings .theme-options { flex-wrap: wrap; } } /* Toast */ .settings-toast { position: fixed; bottom: var(--space-lg); left: 50%; transform: translateX(-50%) translateY(100px); padding: var(--space-sm) var(--space-lg); background: var(--color-bg-secondary); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); opacity: 0; transition: all 0.3s ease; z-index: 1000; } .settings-toast.visible { transform: translateX(-50%) translateY(0); opacity: 1; } ` document.head.appendChild(style)