Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion frontend/src/app/(auth)/forgot-password/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useState } from "react";
import { useMemo, useState } from "react";

import Link from "next/link";

Expand All @@ -10,6 +10,7 @@ import LinkText from "@/components/link-text";
import TextInputField from "@/components/text-input-field";
import ActionButton from "@/features/button/components/action";
import LinkButton from "@/features/button/components/link";
import useCheckMobile from "@/lib/hooks/use-check-mobile";
import { useFormErrors } from "@/lib/hooks/use-form-errors";
import { MESSAGES } from "@/lib/messages";
import { clientPost } from "@/lib/utils/api/client-fetch";
Expand All @@ -19,10 +20,20 @@ import { ApiErrorResponse } from "@/lib/utils/api/fetch-wrapper";
export default function Page() {
const [email, setEmail] = useState("");
const [emailSent, setEmailSent] = useState(false);
const isMobile = useCheckMobile();

// TOASTS AND ERROR STATES
const { errors, handleError, clearAllErrors } = useFormErrors();

// CHECK FIELDS
const invalidForm = useMemo(() => {
return !email || !email.trim()
? "Please enter an email address."
: Object.keys(errors).length
? MESSAGES.FORM_HAS_ERRORS
: undefined;
}, [email, errors]);
Comment thread
jzgom067 marked this conversation as resolved.

const handleEmailChange = (value: string) => {
handleError("email", "");
handleError("api", "");
Expand Down Expand Up @@ -90,7 +101,9 @@ export default function Page() {
<ActionButton
buttonStyle="primary"
label="Send Link"
tooltip={invalidForm}
onClick={handleSubmit}
disabled={!isMobile && !!invalidForm}
loadOnSuccess
/>
</div>
Expand Down
15 changes: 14 additions & 1 deletion frontend/src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useState } from "react";
import { useMemo, useState } from "react";

import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
Expand All @@ -10,6 +10,7 @@ import AuthPageLayout from "@/components/layout/auth-page";
import LinkText from "@/components/link-text";
import TextInputField from "@/components/text-input-field";
import ActionButton from "@/features/button/components/action";
import useCheckMobile from "@/lib/hooks/use-check-mobile";
import { useFormErrors } from "@/lib/hooks/use-form-errors";
import { MESSAGES } from "@/lib/messages";
import { clientPost } from "@/lib/utils/api/client-fetch";
Expand All @@ -22,13 +23,23 @@ export default function Page() {
const [password, setPassword] = useState("");
const [rememberMe, setRememberMe] = useState(false);
const router = useRouter();
const isMobile = useCheckMobile();

const searchParams = useSearchParams();
const callbackUrl = getSafeRedirectUrl(searchParams.get("callbackUrl"));

// TOASTS AND ERROR STATES
const { errors, handleError, clearAllErrors } = useFormErrors();

// CHECK FIELDS
const invalidForm = useMemo(() => {
return !email || !email.trim() || !password
? MESSAGES.FORM_NOT_FILLED
: Object.keys(errors).length
? MESSAGES.FORM_HAS_ERRORS
: undefined;
}, [email, password, errors]);

const handleEmailChange = (value: string) => {
handleError("email", "");
handleError("api", "");
Expand Down Expand Up @@ -122,7 +133,9 @@ export default function Page() {
<ActionButton
buttonStyle="primary"
label="Login"
tooltip={invalidForm}
onClick={handleSubmit}
disabled={!isMobile && !!invalidForm}
loadOnSuccess
/>
</div>
Expand Down
33 changes: 29 additions & 4 deletions frontend/src/app/(auth)/register/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useEffect, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";

import Link from "next/link";
import { useRouter } from "next/navigation";
Expand All @@ -10,6 +10,7 @@ import LinkText from "@/components/link-text";
import TextInputField from "@/components/text-input-field";
import PasswordValidation from "@/features/auth/components/password-validation";
import ActionButton from "@/features/button/components/action";
import useCheckMobile from "@/lib/hooks/use-check-mobile";
import { useFormErrors } from "@/lib/hooks/use-form-errors";
import { MESSAGES } from "@/lib/messages";
import { clientPost } from "@/lib/utils/api/client-fetch";
Expand All @@ -23,20 +24,42 @@ export default function Page() {
const [passwordCriteria, setPasswordCriteria] = useState({});
const [showPasswordCriteria, setShowPasswordCriteria] = useState(false);
const router = useRouter();
const isMobile = useCheckMobile();

// TOASTS AND ERROR STATES
const { errors, handleError, clearAllErrors } = useFormErrors();

function passwordIsStrong() {
const passwordIsStrong = useCallback(() => {
return Object.values(passwordCriteria).every((value) => value === true);
}
}, [passwordCriteria]);

// CHECK FIELDS
const invalidForm = useMemo(() => {
return !email || !email.trim() || !password
? MESSAGES.FORM_NOT_FILLED
: !passwordIsStrong()
? MESSAGES.ERROR_PASSWORD_WEAK
: !confirmPassword
? MESSAGES.FORM_NOT_FILLED
: password !== confirmPassword
? MESSAGES.ERROR_PASSWORD_MISMATCH
: Object.keys(errors).length
? MESSAGES.FORM_HAS_ERRORS
: undefined;
}, [email, password, confirmPassword, passwordIsStrong, errors]);
Comment thread
jzgom067 marked this conversation as resolved.

const handleEmailChange = (value: string) => {
handleError("email", "");
handleError("api", "");
setEmail(value);
};

const handlePasswordChange = (value: string) => {
handleError("password", "");
handleError("api", "");
setPassword(value);
};

const handleConfirmPasswordChange = (value: string) => {
handleError("confirmPassword", "");
handleError("api", "");
Expand Down Expand Up @@ -116,7 +139,7 @@ export default function Page() {
label="Password*"
value={password}
onChange={(value) => {
setPassword(value);
handlePasswordChange(value);
}}
onFocus={() => setShowPasswordCriteria(true)}
onBlur={() => {
Expand Down Expand Up @@ -147,7 +170,9 @@ export default function Page() {
<ActionButton
buttonStyle="primary"
label="Register"
tooltip={invalidForm}
onClick={handleSubmit}
disabled={!isMobile && !!invalidForm}
loadOnSuccess
/>
</div>
Expand Down
33 changes: 29 additions & 4 deletions frontend/src/app/(auth)/reset-password/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"use client";

import { useEffect, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";

import { notFound, useRouter, useSearchParams } from "next/navigation";

import AuthPageLayout from "@/components/layout/auth-page";
import TextInputField from "@/components/text-input-field";
import PasswordValidation from "@/features/auth/components/password-validation";
import ActionButton from "@/features/button/components/action";
import useCheckMobile from "@/lib/hooks/use-check-mobile";
import { useFormErrors } from "@/lib/hooks/use-form-errors";
import { MESSAGES } from "@/lib/messages";
import { clientPost } from "@/lib/utils/api/client-fetch";
Expand All @@ -20,20 +21,42 @@ export default function Page() {
const [passwordCriteria, setPasswordCriteria] = useState({});
const [showPasswordCriteria, setShowPasswordCriteria] = useState(false);
const router = useRouter();
const isMobile = useCheckMobile();

const searchParams = useSearchParams();
const pwdResetToken = searchParams.get("token");
if (!pwdResetToken) {
notFound(); // If no token is provided, show 404 page
}

function passwordIsStrong() {
const passwordIsStrong = useCallback(() => {
return Object.values(passwordCriteria).every((value) => value === true);
}
}, [passwordCriteria]);

// TOASTS AND ERROR STATES
const { errors, handleError, clearAllErrors } = useFormErrors();

// CHECK FIELDS
const invalidForm = useMemo(() => {
return !newPassword
? MESSAGES.FORM_NOT_FILLED
: !passwordIsStrong()
? MESSAGES.ERROR_PASSWORD_WEAK
: !confirmPassword
? MESSAGES.FORM_NOT_FILLED
: newPassword !== confirmPassword
? MESSAGES.ERROR_PASSWORD_MISMATCH
: Object.keys(errors).length
? MESSAGES.FORM_HAS_ERRORS
: undefined;
}, [newPassword, passwordIsStrong, confirmPassword, errors]);

const handleNewPasswordChange = (value: string) => {
handleError("password", "");
handleError("api", "");
setNewPassword(value);
};

const handleConfirmPasswordChange = (value: string) => {
handleError("confirmPassword", "");
handleError("api", "");
Expand Down Expand Up @@ -93,7 +116,7 @@ export default function Page() {
label="New Password*"
value={newPassword}
onChange={(value) => {
setNewPassword(value);
handleNewPasswordChange(value);
}}
onFocus={() => setShowPasswordCriteria(true)}
onBlur={() => {
Expand Down Expand Up @@ -125,7 +148,9 @@ export default function Page() {
<ActionButton
buttonStyle="primary"
label="Change Password"
tooltip={invalidForm}
onClick={handleSubmit}
disabled={!isMobile && !!invalidForm}
loadOnSuccess
/>
</div>
Expand Down
Loading
Loading