import { state, property } from "lit/decorators.js"; import { msg, str, localized } from "@lit/localize"; import LiteElement, { html } from "../utils/LiteElement"; import type { AuthState } from "../utils/AuthService"; import { DASHBOARD_ROUTE } from "../routes"; @localized() export class AcceptInvite extends LiteElement { @property({ type: Object }) authState?: AuthState; @property({ type: String }) token?: string; @property({ type: String }) email?: string; @state() serverError?: string; @state() private inviteInfo: { inviterEmail: string; inviterName: string; orgName: string; } = { inviterEmail: "", inviterName: "", orgName: "", }; connectedCallback(): void { if (this.token && this.email) { super.connectedCallback(); } else { throw new Error("Missing email or token"); } } private get isLoggedIn(): boolean { return Boolean( this.authState && this.email && this.authState.username === this.email ); } firstUpdated() { if (this.isLoggedIn) { this.getInviteInfo(); } else { this.notify({ message: msg("Log in to continue."), variant: "success", icon: "check2-circle", duration: 10000, }); this.navTo( `/log-in?redirectUrl=${encodeURIComponent( `${window.location.pathname}${window.location.search}` )}` ); } } render() { let serverError; if (this.serverError) { serverError = html`
${this.serverError}
`; } const hasInviteInfo = Boolean(this.inviteInfo.inviterEmail); const placeholder = html` `; if (serverError && !hasInviteInfo) { return serverError; } return html`
${serverError}
${msg("Invited by ")} ${this.inviteInfo.inviterName || this.inviteInfo.inviterEmail || placeholder}

${msg( html`You've been invited to join ${hasInviteInfo ? this.inviteInfo.orgName || msg("Browsertrix Cloud") : placeholder}` )}

${msg("Accept invitation")} ${msg("Decline")}
`; } private async getInviteInfo() { if (!this.authState) return; try { const data = await this.apiFetch( `/users/me/invite/${this.token}`, this.authState ); this.inviteInfo = { inviterEmail: data.inviterEmail, inviterName: data.inviterName, orgName: data.orgName, }; } catch { this.serverError = msg("This invitation is not valid"); } } private async onAccept() { if (!this.authState || !this.isLoggedIn) { // TODO handle error this.serverError = msg("Something unexpected went wrong"); return; } try { await this.apiFetch(`/orgs/invite-accept/${this.token}`, this.authState, { method: "POST", }); this.notify({ message: msg(str`You've joined ${this.inviteInfo.orgName}.`), variant: "success", icon: "check2-circle", }); this.navTo(DASHBOARD_ROUTE); } catch (err: any) { if (err.isApiError && err.message === "Invalid Invite Code") { this.serverError = msg("This invitation is not valid"); } else { this.serverError = msg("Something unexpected went wrong"); } } } private onDecline() { this.notify({ message: msg(str`You've declined to join ${this.inviteInfo.orgName}.`), variant: "info", icon: "info-circle", }); this.navTo(DASHBOARD_ROUTE); } }