//=========================================== // THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template //=========================================== import { yupResolver } from "@hookform/resolvers/yup"; import { KnownErrors } from "@hexclave/shared/dist/known-errors"; import { strictEmailSchema, yupObject } from "@hexclave/shared/dist/schema-fields"; import { runAsynchronously } from "@hexclave/shared/dist/utils/promises"; import { ActionCell, Badge, Button, Input, Table, TableBody, TableCell, TableRow, Typography } from "@hexclave/ui"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import * as yup from "yup"; import { FormWarningText } from "../../../components/elements/form-warning"; import { useUser } from "../../../lib/hooks"; import { useTranslation } from "../../../lib/translations"; export function EmailsSection(props?: { mockMode?: boolean, }) { const { t } = useTranslation(); const user = useUser({ or: props?.mockMode ? 'return-null' : 'redirect' }); // In mock mode, show a placeholder message if (props?.mockMode && !user) { return (
{t("Emails")}
{t("Email management is not available in demo mode.")}
); } if (!user) { return null; // This shouldn't happen in non-mock mode due to redirect } const contactChannels = user.useContactChannels(); const [addingEmail, setAddingEmail] = useState(contactChannels.length === 0); const [addingEmailLoading, setAddingEmailLoading] = useState(false); const [addedEmail, setAddedEmail] = useState(null); // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const isLastEmailUsedForAuth = contactChannels.filter(x => x.usedForAuth && x.type === 'email').length === 1; useEffect(() => { if (addedEmail) { runAsynchronously(async () => { const cc = contactChannels.find(x => x.value === addedEmail); if (cc && !cc.isVerified) { await cc.sendVerificationEmail(); } setAddedEmail(null); }); } }, [contactChannels, addedEmail]); const emailSchema = yupObject({ email: strictEmailSchema(t('Please enter a valid email address')) .notOneOf(contactChannels.map(x => x.value), t('Email already exists')) .defined() .nonEmpty(t('Email is required')), }); const { register, handleSubmit, formState: { errors }, reset } = useForm({ resolver: yupResolver(emailSchema) }); const onSubmit = async (data: yup.InferType) => { setAddingEmailLoading(true); try { await user.createContactChannel({ type: 'email', value: data.email, usedForAuth: false }); setAddedEmail(data.email); } finally { setAddingEmailLoading(false); } setAddingEmail(false); reset(); }; return (
{t("Emails")} {addingEmail ? (
{ e.preventDefault(); runAsynchronously(handleSubmit(onSubmit)); }} className='flex flex-col' >
{errors.email && } ) : (
)}
{contactChannels.length > 0 ? (
{/*eslint-disable-next-line @typescript-eslint/no-unnecessary-condition*/} {contactChannels.filter(x => x.type === 'email') .sort((a, b) => { if (a.isPrimary !== b.isPrimary) return a.isPrimary ? -1 : 1; if (a.isVerified !== b.isVerified) return a.isVerified ? -1 : 1; return 0; }) .map(x => (
{x.value}
{x.isPrimary ? {t("Primary")} : null} {!x.isVerified ? {t("Unverified")} : null} {x.usedForAuth ? {t("Used for sign-in")} : null}
{ await x.sendVerificationEmail(); }, }] : []), ...(!x.isPrimary && x.isVerified ? [{ item: t("Set as primary"), onClick: async () => { await x.update({ isPrimary: true }); }, }] : !x.isPrimary ? [{ item: t("Set as primary"), onClick: async () => {}, disabled: true, disabledTooltip: t("Please verify your email first"), }] : []), ...(!x.usedForAuth && x.isVerified ? [{ item: t("Use for sign-in"), onClick: async () => { try { await x.update({ usedForAuth: true }); } catch (e) { if (KnownErrors.ContactChannelAlreadyUsedForAuthBySomeoneElse.isInstance(e)) { alert(t("This email is already used for sign-in by another user.")); } } } }] : []), ...(x.usedForAuth && !isLastEmailUsedForAuth ? [{ item: t("Stop using for sign-in"), onClick: async () => { await x.update({ usedForAuth: false }); }, }] : x.usedForAuth ? [{ item: t("Stop using for sign-in"), onClick: async () => {}, disabled: true, disabledTooltip: t("You can not remove your last sign-in email"), }] : []), // Determine if this email can be removed ...(!isLastEmailUsedForAuth || !x.usedForAuth ? [{ item: t("Remove"), onClick: async () => { await x.delete(); }, danger: true, }] : [{ item: t("Remove"), onClick: async () => {}, disabled: true, disabledTooltip: t("You can not remove your last sign-in email"), }]), ]}/>
))}
) : null}
); }