diff --git a/web/package.json b/web/package.json index 8cc1a0b..3c04490 100644 --- a/web/package.json +++ b/web/package.json @@ -52,6 +52,7 @@ "posthog-js": "1.234.1", "punycode": "2.3.1", "react-expanding-textarea": "2.3.6", + "react-hook-form": "7.65.0", "react-hot-toast": "2.2.0", "react-icons": "5.5.0", "react-international-phone": "4.2.6", diff --git a/web/pages/settings.tsx b/web/pages/settings.tsx index 750c04a..62975d1 100644 --- a/web/pages/settings.tsx +++ b/web/pages/settings.tsx @@ -1,14 +1,18 @@ +import {useState} from 'react' import {PrivateUser} from 'common/src/user' +import {useForm} from 'react-hook-form' +import {Input} from 'web/components/widgets/input' +import {Col} from 'web/components/layout/col' +import toast from 'react-hot-toast' import {NoSEO} from 'web/components/NoSEO' import {UncontrolledTabs} from 'web/components/layout/tabs' import {PageBase} from 'web/components/page-base' import {Title} from 'web/components/widgets/title' import {useRedirectIfSignedOut} from "web/hooks/use-redirect-if-signed-out"; -import toast from "react-hot-toast"; import {deleteAccount} from "web/lib/util/delete"; import router from "next/router"; import {Button} from "web/components/buttons/button"; -import {getAuth, sendEmailVerification, sendPasswordResetEmail} from 'firebase/auth'; +import {getAuth, sendEmailVerification, sendPasswordResetEmail, updateEmail} from 'firebase/auth'; import {auth} from "web/lib/firebase/users"; import {NotificationSettings} from "web/components/notifications"; import ThemeIcon from "web/components/theme-icon"; @@ -41,6 +45,10 @@ const LoadedGeneralSettings = (props: { privateUser: PrivateUser, }) => { const {privateUser} = props + + const [isChangingEmail, setIsChangingEmail] = useState(false) + const {register, handleSubmit, formState: {errors}, reset} = useForm<{ newEmail: string }>() + const user = auth.currentUser if (!user) return null @@ -85,6 +93,32 @@ const LoadedGeneralSettings = (props: { }) } + const changeUserEmail = async (newEmail: string) => { + if (!user) return + + try { + await updateEmail(user, newEmail) + toast.success('Email updated successfully') + setIsChangingEmail(false) + reset() + // Force a reload to update the UI with the new email + // window.location.reload() + } catch (error: any) { + console.error('Error updating email:', error) + toast.error(error.message || 'Failed to update email') + } + } + + const onSubmitEmailChange = (data: { newEmail: string }) => { + if (!user) return + if (data.newEmail === user.email) { + toast.error('New email is the same as current email') + return + } + changeUserEmail(data.newEmail) + } + + const sendVerificationEmail = async () => { if (!privateUser?.email) { toast.error('No email found on your account.') @@ -112,19 +146,62 @@ const LoadedGeneralSettings = (props: {

Theme

Account

-
Credentials
- +
Email
-
Verification
-
Dangerous
+ {!isChangingEmail ? ( + + ) : ( +
+ + + {errors.newEmail && ( + {errors.newEmail.message} + )} + +
+ + +
+
+ )} + +
Password
+ + +
Danger Zone
diff --git a/yarn.lock b/yarn.lock index b816aa0..7b76699 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10405,6 +10405,11 @@ react-fast-compare@^3.0.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== +react-hook-form@7.65.0: + version "7.65.0" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.65.0.tgz#6139dac77ed1081d0178b6830dc6f5ff6ff86361" + integrity sha512-xtOzDz063WcXvGWaHgLNrNzlsdFgtUWcb32E6WFaGTd7kPZG3EeDusjdZfUsPwKCKVXy1ZlntifaHZ4l8pAsmw== + react-hot-toast@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.2.0.tgz#ab6f4caed4214b9534f94bb8cfaaf21b051e62b9"