//=========================================== // 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 { getPasswordError } from '@hexclave/shared/dist/helpers/password'; import { passwordSchema as schemaFieldsPasswordSchema, yupObject, yupString } from "@hexclave/shared/dist/schema-fields"; import { runAsynchronously, runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises"; import { Button, Input, Label, PasswordInput, Typography } from "@hexclave/ui"; import { useState } from "react"; import { useForm } from "react-hook-form"; import * as yup from "yup"; import { useStackApp } from '../../..'; import { FormWarningText } from "../../../components/elements/form-warning"; import { useUser } from "../../../lib/hooks"; import { useTranslation } from "../../../lib/translations"; import { Section } from "../section"; export function PasswordSection(props?: { mockMode?: boolean, }) { const { t } = useTranslation(); const user = useUser({ or: props?.mockMode ? 'return-null' : "throw" }); // In mock mode, show a placeholder message if (props?.mockMode && !user) { return (
{t("Password management is not available in demo mode.")}
); } if (!user) { return null; // This shouldn't happen in non-mock mode due to throw } const contactChannels = user.useContactChannels(); const [changingPassword, setChangingPassword] = useState(false); const [loading, setLoading] = useState(false); const project = useStackApp().useProject(); const passwordSchema = yupObject({ oldPassword: user.hasPassword ? schemaFieldsPasswordSchema.defined().nonEmpty(t('Please enter your old password')) : yupString(), newPassword: schemaFieldsPasswordSchema.defined().nonEmpty(t('Please enter your password')).test({ name: 'is-valid-password', test: (value, ctx) => { const error = getPasswordError(value); if (error) { return ctx.createError({ message: error.message }); } else { return true; } } }), newPasswordRepeat: yupString().nullable().oneOf([yup.ref('newPassword'), "", null], t('Passwords do not match')).defined().nonEmpty(t('Please repeat your password')) }); const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = useForm({ resolver: yupResolver(passwordSchema) }); // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const hasValidEmail = contactChannels.filter(x => x.type === 'email' && x.usedForAuth).length > 0; const onSubmit = async (data: yup.InferType) => { setLoading(true); try { const { oldPassword, newPassword } = data; const error = user.hasPassword ? await user.updatePassword({ oldPassword: oldPassword!, newPassword }) : await user.setPassword({ password: newPassword! }); if (error) { setError('oldPassword', { type: 'manual', message: t('Incorrect password') }); } else { reset(); setChangingPassword(false); } } finally { setLoading(false); } }; const registerPassword = register('newPassword'); const registerPasswordRepeat = register('newPasswordRepeat'); if (!project.config.credentialEnabled) { return null; } return (
{!changingPassword ? ( hasValidEmail ? ( ) : ( {t("To set a password, please add a sign-in email.")} ) ) : (
runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))} noValidate > {user.hasPassword && ( <> )} { clearErrors('newPassword'); clearErrors('newPasswordRepeat'); runAsynchronously(registerPassword.onChange(e)); }} /> { clearErrors('newPassword'); clearErrors('newPasswordRepeat'); runAsynchronously(registerPasswordRepeat.onChange(e)); }} />
)}
); }