import { html, nothing } from 'lit'; import { LightElement } from '../lib/base.js'; export class ProfilePage extends LightElement { static get properties() { return { _open: { state: true }, _me: { state: true }, _displayName: { state: true }, _savingName: { state: true }, _nameMsg: { state: true }, _pwCurrent: { state: true }, _pwNew: { state: true }, _pwConfirm: { state: true }, _savingPw: { state: true }, _pwMsg: { state: true }, }; } constructor() { super(); this._open = false; this._me = null; this._displayName = ''; this._savingName = false; this._nameMsg = null; this._pwCurrent = ''; this._pwNew = ''; this._pwConfirm = ''; this._savingPw = false; this._pwMsg = null; } connectedCallback() { super.connectedCallback(); window.addEventListener('llm-page-change', (e) => { this._open = e.detail.page === 'profile'; this.style.display = this._open ? 'flex' : 'none'; if (this._open) this._load(); }); } async _load() { try { const res = await fetch('/api/auth/me'); if (res.ok) { this._me = await res.json(); this._displayName = this._me.display_name ?? ''; } } catch { /* ignore */ } } async _saveName() { if (this._savingName) return; this._savingName = true; this._nameMsg = null; try { const res = await fetch('/api/auth/profile', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ display_name: this._displayName.trim() || null }), }); if (!res.ok) throw new Error(await res.text()); this._nameMsg = { type: 'ok', text: 'Saved.' }; await this._load(); } catch (e) { this._nameMsg = { type: 'err', text: e.message }; } finally { this._savingName = false; } } async _savePassword() { if (this._savingPw) return; this._pwMsg = null; if (this._pwNew.length < 4) { this._pwMsg = { type: 'err', text: 'Password must be at least 4 characters.' }; return; } if (this._pwNew !== this._pwConfirm) { this._pwMsg = { type: 'err', text: 'Passwords do not match.' }; return; } this._savingPw = true; try { const res = await fetch('/api/auth/change-password', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ current_password: this._pwCurrent || null, new_password: this._pwNew, }), }); if (!res.ok) throw new Error(await res.text()); this._pwMsg = { type: 'ok', text: 'Password changed.' }; this._pwCurrent = ''; this._pwNew = ''; this._pwConfirm = ''; } catch (e) { this._pwMsg = { type: 'err', text: e.message }; } finally { this._savingPw = false; } } render() { if (!this._open) return nothing; const me = this._me; return html`

Profile

${me ? html`
Account
` : nothing}
Display name
this._displayName = e.target.value} />
${this._nameMsg ? html`
${this._nameMsg.text}
` : nothing}
Change password
${me?.role_id === 'admin' || me?.encrypted ? html`
this._pwCurrent = e.target.value} />
` : nothing}
this._pwNew = e.target.value} />
this._pwConfirm = e.target.value} />
${this._pwMsg ? html`
${this._pwMsg.text}
` : nothing}
`; } }