diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 9e26dfe..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/compass/app/auth/forgot_password/page.tsx b/compass/app/auth/forgot_password/page.tsx index 5a57226..ed607b2 100644 --- a/compass/app/auth/forgot_password/page.tsx +++ b/compass/app/auth/forgot_password/page.tsx @@ -1,71 +1,65 @@ -"use client" +// pages/forgot-password.tsx +"use client"; + +import React, { useState, useEffect } from 'react'; +import Input from '@/components/Input'; import Button from '@/components/Button'; -import Input from '@/components/Input' import InlineLink from '@/components/InlineLink'; import Paper from '@/components/auth/Paper'; -import { useState, useEffect } from 'react'; +import ErrorBanner from '@/components/auth/ErrorBanner'; -function isValidEmail(email: string) { - //check email validation +function isValidEmail(email: string): string | null { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (email.trim() === '') { - //check if input is empty return 'Email cannot be empty'; } else if (!emailRegex.test(email)) { - //check for incorrect email format return 'Invalid email format'; } - else{ - //return message for no error in input - return 'If your email exists in the database, you should receive a password reset in your inbox.' - } - + return null; // No error } -export default function Page() { +export default function ForgotPasswordPage() { + const [confirmEmail, setConfirmEmail] = useState(""); + const [emailError, setEmailError] = useState<string | null>(null); const [isButtonDisabled, setIsButtonDisabled] = useState(true); - const [confirmEmail, setconfirmEmail] = useState(''); - const [emailError, setEmailError] = useState(''); useEffect(() => { - //when email string inputted it is checked in isValidEmail const error = isValidEmail(confirmEmail); - setEmailError(error); - //button is disabled if any error is detected - setIsButtonDisabled(error !== null && !error.includes('exists in the database')); + setEmailError(error); // set the error message based on validation + setIsButtonDisabled(!!error); // disable button if there is an error }, [confirmEmail]); return ( <> <Paper> <form - className="mb-0 m-auto mt-6 space-y-4 rounded-lg p-4 shadow-lg sm:p-6 lg:p-8 bg-white max-w-xl"> - <h1 className="font-bold text-xl text-purple-800">Forgot password</h1> - <div className="mb-4"> - <Input type='email' - title="Enter your email address" - placeholder="janedoe@gmail.com" - //setting a placeholder in the email input box - value={confirmEmail} - onChange={(e) => { - setconfirmEmail(e.target.value); - }}/> - {emailError && ( - <p className={`mt-2 ${emailError.includes('exists in the database') ? 'text-green-500' : 'text-red-500'}`}> - {emailError} - </p> - //if email does not meet certain criteria, then issue an error - )} + onSubmit={(e) => { + e.preventDefault(); + // submit form logic here. since it's a "forgot password" form, + // typically you would send a reset password link to the email provided. + console.log('Form submitted with email:', confirmEmail); + }} + className="mb-0 m-auto mt-6 space-y-4 rounded-lg p-4 shadow-lg sm:p-6 lg:p-8 bg-white max-w-xl" + > + <h1 className="font-bold text-xl text-purple-800">Forgot Password</h1> + <div className="mb-6"> + <Input + type='email' + valid={emailError !== null} + title="Enter your email address" + placeholder="janedoe@gmail.com" + value={confirmEmail} + onChange={(e) => setConfirmEmail(e.target.value)} + /> </div> + {emailError && <ErrorBanner heading={emailError} />} <div className="flex flex-col items-left space-y-4"> - <InlineLink href= "/auth/login"> {/* link back to login page */} + <InlineLink href="/auth/login"> Back to Sign In </InlineLink> <Button type="submit" disabled={isButtonDisabled}> Send </Button> - </div> </form> <p className="text-center mt-6 text-gray-500 text-xs"> @@ -74,5 +68,4 @@ export default function Page() { </Paper> </> ); -}; - +} diff --git a/compass/app/auth/login/page.tsx b/compass/app/auth/login/page.tsx index 0284517..0439972 100644 --- a/compass/app/auth/login/page.tsx +++ b/compass/app/auth/login/page.tsx @@ -6,13 +6,15 @@ import Input from '@/components/Input' import InlineLink from '@/components/InlineLink'; import Paper from '@/components/auth/Paper'; import Image from 'next/image'; -import { ChangeEvent, useState } from "react"; +import { useState } from "react"; import PasswordInput from '@/components/auth/PasswordInput'; +import ErrorBanner from '@/components/auth/ErrorBanner'; export default function Page() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); - const [error, setError] = useState(""); + const [emailError, setEmailError] = useState(""); + const [passwordError, setPasswordError] = useState(""); const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => { setEmail(event.currentTarget.value); @@ -26,17 +28,17 @@ export default function Page() { // Priority: Incorrect combo > Missing email > Missing password if (password.trim().length === 0) { - setError("Please enter your password.") + setEmailError("Please enter your password.") event.preventDefault(); } // This shouldn't happen, <input type="email"> already provides validation, but just in case. if (email.trim().length === 0) { - setError("Please enter your email.") + setPasswordError("Please enter your email.") event.preventDefault(); } // Placeholder for incorrect email + password combo. if (email === "incorrect@gmail.com" && password) { - setError("Incorrect password.") + setPasswordError("Incorrect password.") event.preventDefault(); } } @@ -44,7 +46,9 @@ export default function Page() { return ( <> <Paper> - <form className="mb-0 m-auto mt-6 space-y-4 rounded-lg p-4 shadow-lg sm:p-6 lg:p-8 bg-white max-w-xl"> + <form onSubmit={(e) => { + e.preventDefault(); + }} className="mb-0 m-auto mt-6 space-y-4 rounded-lg p-4 shadow-lg sm:p-6 lg:p-8 bg-white max-w-xl"> <Image src="/logo.png" alt='Compass Center logo.' @@ -54,13 +58,17 @@ export default function Page() { <h1 className='font-bold text-xl text-purple-800'>Login</h1> - <div className="mb-4"> - <Input type='email' title="Email" placeholder="janedoe@gmail.com" onChange={handleEmailChange} required /> + <div className="mb-6"> + <Input type='email' valid={emailError !== null} title="Email" placeholder="janedoe@gmail.com" onChange={handleEmailChange} required /> + </div> + {emailError && <ErrorBanner heading={emailError} />} <div className="mb-6"> - <PasswordInput title="Password" onChange={handlePasswordChange} required /> + <PasswordInput title="Password" valid={passwordError !== null} onChange={handlePasswordChange} required /> + </div> + {passwordError && <ErrorBanner heading={passwordError} />} <div className="flex flex-col items-left space-y-4"> <InlineLink href="/auth/forgot_password"> @@ -69,9 +77,6 @@ export default function Page() { <Button onClick={handleClick}> Login </Button> - <div className="text-center text-red-600" hidden={!error}> - <p>{error}</p> - </div> </div> </form> diff --git a/compass/app/auth/new_password/page.tsx b/compass/app/auth/new_password/page.tsx index ba9ebde..361b422 100644 --- a/compass/app/auth/new_password/page.tsx +++ b/compass/app/auth/new_password/page.tsx @@ -1,13 +1,11 @@ // pages/index.tsx "use client"; import { useState, useEffect } from 'react'; - -import Input from '@/components/Input'; - import Button from '@/components/Button'; import Paper from '@/components/auth/Paper'; import PasswordInput from '@/components/auth/PasswordInput'; +import ErrorBanner from '@/components/auth/ErrorBanner'; function isStrongPassword(password: string): boolean { @@ -45,7 +43,6 @@ export default function Page() { </div> <div className="mb-4"> <PasswordInput - type="password" title="Enter New Password" value={newPassword} valid={!isButtonDisabled || isStrongPassword(newPassword)} @@ -54,15 +51,9 @@ export default function Page() { }} /> </div> - {isStrongPassword(newPassword) || newPassword === '' ? null : <div role="alert" className="rounded border-s-4 border-red-500 bg-red-50 p-4"> - <strong className="block text-sm font-semibold text-red-800"> Password is not strong enough. </strong> - <p className="mt-2 text-xs font-thin text-red-700"> - Tip: Use a mix of letters, numbers, and symbols for a strong password. Aim for at least 8 characters! - </p> - </div>} + {isStrongPassword(newPassword) || newPassword === '' ? null : <ErrorBanner heading="Password is not strong enough." description="Tip: Use a mix of letters, numbers, and symbols for a strong password. Aim for at least 8 characters!" />} <div className="mb-6"> <PasswordInput - type="password" title="Confirm Password" value={confirmPassword} valid={!isButtonDisabled || (newPassword === confirmPassword && confirmPassword !== '')} @@ -71,12 +62,7 @@ export default function Page() { }} /> </div> - {newPassword === confirmPassword || confirmPassword === '' ? null : <div role="alert" className="rounded border-s-4 border-red-500 bg-red-50 p-4"> - <strong className="block text-sm font-semibold text-red-800"> Passwords do not match. </strong> - <p className="mt-2 text-xs font-thin text-red-700"> - Please make sure both passwords are the exact same! - </p> - </div>} + {newPassword === confirmPassword || confirmPassword === '' ? null : <ErrorBanner heading="Passwords do not match." description="Please make sure both passwords are the exact same!"/>} <div className="flex flex-col items-left space-y-4"> <Button type="submit" disabled={isButtonDisabled} > Send diff --git a/compass/app/page.tsx b/compass/app/page.tsx index ee3a07a..dba820a 100644 --- a/compass/app/page.tsx +++ b/compass/app/page.tsx @@ -59,7 +59,7 @@ export default function Page() { /> <h1 className='font-bold text-xl text-purple-800'>Login</h1> <div className="mb-4"> - <Input type='email' title="Email" placeholder="janedoe@gmail.com" icon={'EmailInputIcon'} onChange={handleEmailChange} /> + <Input type='email' title="Email" placeholder="janedoe@gmail.com" onChange={handleEmailChange} /> </div> <div className="mb-6"> <Input type='password' title="Password" onChange={handlePasswordChange} /> diff --git a/compass/components/auth/ErrorBanner.tsx b/compass/components/auth/ErrorBanner.tsx new file mode 100644 index 0000000..c7dfea3 --- /dev/null +++ b/compass/components/auth/ErrorBanner.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +interface ErrorBannerProps { + heading: string; + description?: string | null; +} + +const ErrorBanner: React.FC<ErrorBannerProps> = ({ heading, description = null }) => { + return ( + <div role="alert" className="rounded border-s-4 border-red-500 bg-red-50 p-4"> + <strong className="block text-sm font-semibold text-red-800">{heading}</strong> + {description && <p className="mt-2 text-xs font-thin text-red-700"> + {description} + </p>} + </div> + ); +}; + +export default ErrorBanner;