diff --git a/frontend/src/components/ui/FormField.tsx b/frontend/src/components/ui/FormField.tsx
index 70c2346..1fc6b45 100644
--- a/frontend/src/components/ui/FormField.tsx
+++ b/frontend/src/components/ui/FormField.tsx
@@ -1,44 +1,43 @@
import type { UseFormRegisterReturn } from "react-hook-form";
interface FormFieldProps {
- label: string;
- type?: string;
- placeholder?: string;
- registration: UseFormRegisterReturn;
- error?: string;
- handleFocus?: () => void;
- "data-testid"?: string;
+ label: string;
+ type?: string;
+ placeholder?: string;
+ registration: UseFormRegisterReturn;
+ error?: string;
+ handleFocus?: () => void;
+ "data-testid"?: string;
}
export default function FormField({
- label,
- type = "text",
- placeholder,
- registration,
- error,
- handleFocus,
- "data-testid": testId,
+ label,
+ type = "text",
+ placeholder,
+ registration,
+ error,
+ handleFocus,
+ "data-testid": testId,
}: FormFieldProps) {
- return (
-
-
-
- {error &&
{error}
}
-
- );
+ return (
+
+
+
+ {error &&
{error}
}
+
+ );
}
diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx
index 2f4b32e..9aca27f 100644
--- a/frontend/src/pages/Login.tsx
+++ b/frontend/src/pages/Login.tsx
@@ -16,135 +16,134 @@ import { useAuth } from "../hooks/useAuth";
import { CryptoUtils } from "../utils/crypto";
const loginSchema = z.object({
- email: z.email("Please enter a valid email"),
- password: z.string().min(1, "Password is required"),
+ email: z.email("Please enter a valid email"),
+ password: z.string().min(1, "Password is required"),
});
type LoginInputs = z.infer;
export default function Login() {
- const navigate = useNavigate();
- const location = useLocation();
- const [isLoading, setIsLoading] = useState(false);
- const [apiError, setApiError] = useState(null);
- const { setAuthStore } = useAuth();
- const [showWelcome, setShowWelcome] = useState(!!location.state?.firstTime);
- const [saajanMessage, setSaajanMessage] = useState(
- "I was wondering when you'd return.",
- );
- const nextRoute = location.state?.redirectUrl || ROUTES.DRAWER;
+ const navigate = useNavigate();
+ const location = useLocation();
+ const [isLoading, setIsLoading] = useState(false);
+ const [apiError, setApiError] = useState(null);
+ const { setAuthStore } = useAuth();
+ const [showWelcome, setShowWelcome] = useState(!!location.state?.firstTime);
+ const [saajanMessage, setSaajanMessage] = useState(
+ "I was wondering when you'd return.",
+ );
+ const nextRoute = location.state?.redirectUrl || ROUTES.DRAWER;
- const {
- register,
- handleSubmit,
- formState: { errors },
- } = useForm({
- resolver: zodResolver(loginSchema),
- });
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: zodResolver(loginSchema),
+ });
- const onSubmit = async (data: LoginInputs) => {
- setIsLoading(true);
- setApiError(null);
- try {
- // client side key derivation for e2e encryption
- const { masterKey, authHash } = await CryptoUtils.deriveKeyBundle(
- data.password,
- data.email,
- );
+ const onSubmit = async (data: LoginInputs) => {
+ setIsLoading(true);
+ setApiError(null);
+ try {
+ // client side key derivation for e2e encryption
+ const { masterKey, authHash } = await CryptoUtils.deriveKeyBundle(
+ data.password,
+ data.email,
+ );
- // send just the authHash as the password to the server
- const { data: authData } = await publicApi.post(endpoints.LOGIN, {
- email: data.email,
- password: authHash,
- });
+ // send just the authHash as the password to the server
+ const { data: authData } = await publicApi.post(endpoints.LOGIN, {
+ email: data.email,
+ password: authHash,
+ });
- const { data: userData } = await api.get(endpoints.ME, {
- headers: { Authorization: `Bearer ${authData.access}` },
- });
+ const { data: userData } = await api.get(endpoints.ME, {
+ headers: { Authorization: `Bearer ${authData.access}` },
+ });
- await setAuthStore(authData.access, userData, masterKey);
+ await setAuthStore(authData.access, userData, masterKey);
- navigate(nextRoute, { replace: true, state: location.state });
- } catch (err) {
- let message =
- "Sorry, we're experiencing technical issues.\nPlease try again later.";
- if (axios.isAxiosError(err) && err.response?.status !== 500) {
- message = err.response?.data?.detail || err.response?.data?.message;
- }
- setApiError(message);
- } finally {
- setIsLoading(false);
- }
- };
-
- return (
-
- {!showWelcome &&
}
- {showWelcome &&
}
-
+
+ );
}
diff --git a/frontend/src/pages/Register.tsx b/frontend/src/pages/Register.tsx
index b28403a..aa711dd 100644
--- a/frontend/src/pages/Register.tsx
+++ b/frontend/src/pages/Register.tsx
@@ -14,158 +14,170 @@ import { ROUTES } from "../config/routes";
import { CryptoUtils } from "../utils/crypto";
const registerSchema = z
- .object({
- full_name: z.string().min(2, "Name must be at least 2 characters"),
- email: z.email("Please enter a valid email"),
- password: z.string().min(8, "Password must be at least 8 characters"),
- confirm_password: z.string(),
- })
- .refine((data) => data.password === data.confirm_password, {
- message: "Passwords don't match",
- path: ["confirm_password"],
- });
+ .object({
+ full_name: z.string().min(2, "Name must be at least 2 characters"),
+ email: z.email("Please enter a valid email"),
+ password: z.string().min(8, "Password must be at least 8 characters"),
+ confirm_password: z.string(),
+ })
+ .refine((data) => data.password === data.confirm_password, {
+ message: "Passwords don't match",
+ path: ["confirm_password"],
+ });
type RegisterInputs = z.infer;
export default function Register() {
- const navigate = useNavigate();
- const [isLoading, setIsLoading] = useState(false);
- const [apiError, setApiError] = useState(null);
- const [saajanMessage, setSaajanMessage] = useState(
- "I didn't think I'd be here either.\nAnd yet, here we are.",
- );
+ const navigate = useNavigate();
+ const [isLoading, setIsLoading] = useState(false);
+ const [apiError, setApiError] = useState(null);
+ const [saajanMessage, setSaajanMessage] = useState(
+ "I didn't think I'd be here either.\nAnd yet, here we are.",
+ );
- const {
- register,
- handleSubmit,
- formState: { errors },
- } = useForm({
- resolver: zodResolver(registerSchema),
- });
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: zodResolver(registerSchema),
+ });
- const onSubmit = async (data: RegisterInputs) => {
- setSaajanMessage("Good. I'll remember that.");
- setIsLoading(true);
- setApiError(null);
- try {
- // we generate the key bundle here to get the authHash (password) to be haSHed and stored in the db.
- const { authHash } = await CryptoUtils.deriveKeyBundle(
- data.password,
- data.email,
- );
+ const onSubmit = async (data: RegisterInputs) => {
+ setSaajanMessage("Good. I'll remember that.");
+ setIsLoading(true);
+ setApiError(null);
+ try {
+ // we generate the key bundle here to get the authHash (password) to be haSHed and stored in the db.
+ const { authHash } = await CryptoUtils.deriveKeyBundle(
+ data.password,
+ data.email,
+ );
- await publicApi.post(endpoints.REGISTER, {
- full_name: data.full_name,
- email: data.email,
- password: authHash,
- });
- navigate(ROUTES.VERIFY_EMAIL, { replace: true });
- } catch (err) {
- let message = "Registration failed. Please try again.";
- if (axios.isAxiosError(err)) {
- message = err.response?.data?.message || message;
- }
- setApiError(message);
- } finally {
- setIsLoading(false);
- }
- };
+ await publicApi.post(endpoints.REGISTER, {
+ full_name: data.full_name,
+ email: data.email,
+ password: authHash,
+ });
+ navigate(ROUTES.VERIFY_EMAIL, { replace: true });
+ } catch (err) {
+ let message = "Registration failed. Please try again.";
+ if (axios.isAxiosError(err)) {
+ message = err.response?.data?.message || message;
+ }
+ setApiError(message);
+ } finally {
+ setIsLoading(false);
+ }
+ };
- return (
-
-
-
-
+ );
}