import { Form, useLocation, useNavigation, useSearchParams, useSubmit } from "react-router"; import { type TFunction } from "i18next"; import { useRef, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import ButtonPrimary from "~/components/ui/buttons/ButtonPrimary"; import ButtonTertiary from "~/components/ui/buttons/ButtonTertiary"; import { Input } from "~/components/ui/input"; import InputSelect from "~/components/ui/input/InputSelect"; import InputText from "~/components/ui/input/InputText"; import ConfirmModal, { RefConfirmModal } from "~/components/ui/modals/ConfirmModal"; import ErrorModal, { RefErrorModal } from "~/components/ui/modals/ErrorModal"; import SuccessModal, { RefSuccessModal } from "~/components/ui/modals/SuccessModal"; import SettingSection from "~/components/ui/sections/SettingSection"; import UploadDocuments from "~/components/ui/uploaders/UploadDocument"; import UploadImage from "~/components/ui/uploaders/UploadImage"; import { i18nConfig } from "~/locale/i18n"; import type { CurrentSessionSettings } from "~/routes/app.$tenant/settings/profile"; import { useRootData } from "~/utils/data/useRootData"; import { UserIcon } from "~/components/ui/icons/vendor"; type UserProfileMfaStatus = { enabled: boolean; pending: boolean; enabledAt: Date | string | null; pendingCreatedAt: Date | string | null; }; function getMfaStatusLabel(t: TFunction, mfaStatus?: UserProfileMfaStatus | null) { if (mfaStatus?.enabled) { return t("settings.profile.mfa.status.enabled"); } if (mfaStatus?.pending) { return t("settings.profile.mfa.status.pending"); } return t("settings.profile.mfa.status.notEnabled"); } function getLightOrDarkModeLabel(t: TFunction, value?: string | null) { if (value === "light" || value === "dark") { return t(`shared.${value}`); } return value || t("settings.profile.session.systemPreference"); } function getMfaStepUpLabel(t: TFunction, mfaStepUp?: CurrentSessionSettings["mfaStepUp"]) { if (mfaStepUp?.verified) { return t("settings.profile.session.mfaStepUpVerifiedWith", { method: mfaStepUp.method }); } if (mfaStepUp?.present) { return mfaStepUp.stale ? t("settings.profile.session.mfaStepUpStale") : t("settings.profile.session.mfaStepUpInvalid"); } return t("settings.profile.session.mfaStepUpNotPresent"); } export default function UserProfileSettings({ user, mfaStatus, otpauthUri, mfaError, recoveryCodes, currentSession, }: { user: { email: string; firstName: string; lastName: string; avatar: string | null; admin?: any | null; }; mfaStatus?: { enabled: boolean; pending: boolean; enabledAt: Date | string | null; pendingCreatedAt: Date | string | null; } | null; otpauthUri?: string; mfaError?: string; recoveryCodes?: string[]; currentSession?: CurrentSessionSettings; }) { const location = useLocation(); const [searchParams] = useSearchParams(); const { t, i18n } = useTranslation(); const navigation = useNavigation(); const submit = useSubmit(); const { csrf } = useRootData(); const errorModal = useRef(null); const successModal = useRef(null); const confirmModal = useRef(null); const inputFirstName = useRef(null); useEffect(() => { inputFirstName.current?.focus(); inputFirstName.current?.select(); }, []); const [avatar, setAvatar] = useState(user?.avatar ?? undefined); const [showUploadImage, setShowUploadImage] = useState(false); const [uploadingImage, setUploadingImage] = useState(false); function changedLocale(locale: string) { const form = new FormData(); form.set("action", "setLocale"); form.set("csrf", csrf ?? ""); searchParams.set("lng", locale); form.set("redirect", location.pathname + "?" + searchParams.toString()); form.set("lng", locale); submit(form, { method: "post", action: "/preferences", preventScrollReset: true }); } function deleteAccount() { if (user?.admin) { errorModal.current?.show(t("settings.profile.errors.cannotDeleteAdmin")); } else { confirmModal.current?.show(t("settings.danger.confirmDelete"), t("shared.confirm"), t("shared.cancel"), t("shared.warningCannotUndo"), ""); } } function confirmDelete(passwordCurrent: string | undefined) { const form = new FormData(); form.set("action", "deleteAccount"); form.set("csrf", csrf ?? ""); form.set("passwordCurrent", passwordCurrent ?? ""); submit(form, { method: "post" }); } function loadedImage(image: string | undefined) { setAvatar(image); setUploadingImage(true); } return (
{(() => { if (avatar) { return {t("shared.avatar")}; } else { return ( ); } })()}
{avatar ? ( loadedImage("")} type="button"> {t("shared.delete")} ) : ( )}
{/*Separator */}
{t("account.login.forgot")}{" "} {t("account.reset.button")}

} > {/*Security */}

{t("settings.profile.mfa.authenticatorApp")}

{getMfaStatusLabel(t, mfaStatus)}

{mfaError ? (

{mfaError}

) : null}
{otpauthUri ? (
{otpauthUri}
{t("settings.profile.mfa.confirmAuthenticator")}
) : null} {recoveryCodes?.length ? (

{t("settings.profile.mfa.saveRecoveryCodes")}

{t("settings.profile.mfa.recoveryCodesOneTime")}

    {recoveryCodes.map((code) => (
  • {code}
  • ))}