diff --git a/apps/web/i18next-scanner.config.js b/apps/web/i18next-scanner.config.js index 4bca73307..04cb299b9 100644 --- a/apps/web/i18next-scanner.config.js +++ b/apps/web/i18next-scanner.config.js @@ -1,9 +1,8 @@ const typescriptTransform = require("i18next-scanner-typescript"); module.exports = { - input: ["src/**/*.{ts,tsx}", "!src/utils/auth.ts"], + input: ["src/**/*.{ts,tsx}", "!src/auth.ts"], options: { - keySeparator: ".", nsSeparator: false, defaultNs: "app", defaultValue: "__STRING_NOT_TRANSLATED__", diff --git a/apps/web/public/locales/en/app.json b/apps/web/public/locales/en/app.json index d1f96b92a..5c178849c 100644 --- a/apps/web/public/locales/en/app.json +++ b/apps/web/public/locales/en/app.json @@ -279,5 +279,15 @@ "subscribe": "Subscribe", "cancelAnytime": "Cancel anytime from your billing page.", "unsubscribeToastTitle": "You have disabled notifications", - "unsubscribeToastDescription": "You will no longer receive notifications for this poll" + "unsubscribeToastDescription": "You will no longer receive notifications for this poll", + "emailChangeSuccess": "Email changed successfully", + "emailChangeSuccessDescription": "Your email has been updated", + "emailChangeFailed": "Email change failed", + "emailChangeInvalidToken": "The verification link is invalid or has expired. Please try again.", + "emailChangeError": "An error occurred while changing your email", + "emailChangeRequestSent": "Verify your new email address", + "emailChangeRequestSentDescription": "To complete the change, please check your email for a verification link.", + "profileEmailAddress": "Email Address", + "profileEmailAddressDescription": "Your email address is used to log in to your account", + "emailAlreadyInUse": "Email already in use. Please try a different one or delete the existing account." } diff --git a/apps/web/src/app/[locale]/(admin)/settings/profile/profile-email-address.tsx b/apps/web/src/app/[locale]/(admin)/settings/profile/profile-email-address.tsx new file mode 100644 index 000000000..43ff53b8c --- /dev/null +++ b/apps/web/src/app/[locale]/(admin)/settings/profile/profile-email-address.tsx @@ -0,0 +1,154 @@ +import { usePostHog } from "@rallly/posthog/client"; +import { Alert, AlertDescription, AlertTitle } from "@rallly/ui/alert"; +import { Button } from "@rallly/ui/button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@rallly/ui/form"; +import { useToast } from "@rallly/ui/hooks/use-toast"; +import { Input } from "@rallly/ui/input"; +import Cookies from "js-cookie"; +import { InfoIcon } from "lucide-react"; +import React from "react"; +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; + +import { Trans } from "@/components/trans"; +import { useUser } from "@/components/user-provider"; +import { trpc } from "@/trpc/client"; + +export const ProfileEmailAddress = () => { + const { user, refresh } = useUser(); + const requestEmailChange = trpc.user.requestEmailChange.useMutation(); + const posthog = usePostHog(); + const form = useForm<{ + name: string; + email: string; + }>({ + defaultValues: { + name: user.isGuest ? "" : user.name, + email: user.email ?? "", + }, + }); + const { t } = useTranslation("app"); + const { toast } = useToast(); + + const [didRequestEmailChange, setDidRequestEmailChange] = + React.useState(false); + + React.useEffect(() => { + const success = Cookies.get("email-change-success"); + const error = Cookies.get("email-change-error"); + + if (success) { + posthog.capture("email change completed"); + toast({ + title: t("emailChangeSuccess", { + defaultValue: "Email changed successfully", + }), + description: t("emailChangeSuccessDescription", { + defaultValue: "Your email has been updated", + }), + }); + } + + if (error) { + posthog.capture("email change failed", { error }); + toast({ + variant: "destructive", + title: t("emailChangeFailed", { + defaultValue: "Email change failed", + }), + description: + error === "invalidToken" + ? t("emailChangeInvalidToken", { + defaultValue: + "The verification link is invalid or has expired. Please try again.", + }) + : t("emailChangeError", { + defaultValue: "An error occurred while changing your email", + }), + }); + } + }, [posthog, refresh, t, toast]); + + const { handleSubmit, formState, reset } = form; + return ( +