import { html, LitElement, TemplateResult } from "lit"; import { customElement, query, state } from "lit/decorators.js"; import { UserMeResponse } from "../core/ApiSchemas"; import "./components/Difficulties"; import "./components/PatternButton"; import { discordLogin, getApiBase, getUserMe, logOut } from "./jwt"; import { translateText } from "./Utils"; @customElement("account-modal") export class AccountModal extends LitElement { @query("o-modal") private modalEl!: HTMLElement & { open: () => void; close: () => void; }; @state() private email: string = ""; private loggedInEmail: string | null = null; private loggedInDiscord: string | null = null; constructor() { super(); } createRenderRoot() { return this; } render() { return html` ${this.renderInner()} `; } private renderInner() { if (this.loggedInDiscord) { return this.renderLoggedInDiscord(); } else if (this.loggedInEmail) { return this.renderLoggedInEmail(); } else { return this.renderLoginOptions(); } } private renderLoggedInDiscord() { return html`

Logged in with Discord as ${this.loggedInDiscord}

${this.logoutButton()}
`; } private renderLoggedInEmail(): TemplateResult { return html`

Logged in as ${this.loggedInEmail}

${this.logoutButton()}
`; } private logoutButton(): TemplateResult { return html` `; } private renderLoginOptions() { return html`

Choose your login method

or
`; } private handleEmailInput(e: Event) { const target = e.target as HTMLInputElement; this.email = target.value; } private async handleSubmit() { if (!this.email) { alert("Please enter an email address"); return; } try { const apiBase = getApiBase(); const response = await fetch(`${apiBase}/magic-link`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ redirectDomain: window.location.origin, email: this.email, }), }); if (response.ok) { alert( translateText("account_modal.recovery_email_sent", { email: this.email, }), ); this.close(); } else { console.error( "Failed to send recovery email:", response.status, response.statusText, ); alert("Failed to send recovery email. Please try again."); } } catch (error) { console.error("Error sending recovery email:", error); alert("Error sending recovery email. Please try again."); } } private handleDiscordLogin() { discordLogin(); } public async open() { const userMe = await getUserMe(); if (userMe) { this.loggedInEmail = userMe.user.email ?? null; this.loggedInDiscord = userMe.user.discord?.global_name ?? null; } this.modalEl?.open(); this.requestUpdate(); } public close() { this.modalEl?.close(); } private async handleLogout() { await logOut(); this.close(); // Refresh the page after logout to update the UI state window.location.reload(); } } @customElement("account-button") export class AccountButton extends LitElement { @state() private loggedInEmail: string | null = null; @state() private loggedInDiscord: string | null = null; private isVisible = true; @query("account-modal") private recoveryModal: AccountModal; constructor() { super(); document.addEventListener("userMeResponse", (event: Event) => { const customEvent = event as CustomEvent; if (customEvent.detail) { const userMeResponse = customEvent.detail as UserMeResponse; if (userMeResponse.user.email) { this.loggedInEmail = userMeResponse.user.email; this.requestUpdate(); } else if (userMeResponse.user.discord) { this.loggedInDiscord = userMeResponse.user.discord.id; this.requestUpdate(); } } else { // Clear the logged in states when user logs out this.loggedInEmail = null; this.loggedInDiscord = null; this.requestUpdate(); } }); } createRenderRoot() { return this; } render() { if (!this.isVisible) { return html``; } let buttonTitle = ""; if (this.loggedInEmail) { buttonTitle = translateText("account_modal.logged_in_as", { email: this.loggedInEmail, }); } else if (this.loggedInDiscord) { buttonTitle = translateText("account_modal.logged_in_with_discord"); } return html`
`; } private renderIcon() { if (this.loggedInDiscord) { return html`Discord`; } else if (this.loggedInEmail) { return html`Email`; } return html`Logged Out`; } private open() { this.recoveryModal?.open(); } public close() { this.isVisible = false; this.recoveryModal?.close(); this.requestUpdate(); } }