Skip to content

Commit

Permalink
finilized auth styling
Browse files Browse the repository at this point in the history
  • Loading branch information
rachaelch3n committed Dec 7, 2024
1 parent e600e66 commit 0b8030d
Show file tree
Hide file tree
Showing 8 changed files with 442 additions and 123 deletions.
95 changes: 67 additions & 28 deletions app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,86 @@
'use client';

import { useState } from 'react';
import { useRouter } from 'next/navigation';
// import { useRouter } from 'next/navigation';
import TextInput from '@/components/TextInput';
import { StyledButton, StyledForm } from '@/components/TextInput/styles';
import COLORS from '@/styles/colors';
import { H2, P3 } from '@/styles/text';
import { useAuth } from '../../../utils/AuthProvider';

export default function Login() {
const { signIn } = useAuth(); // Use `signIn` function from AuthProvider
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const router = useRouter();
const [showPassword, setShowPassword] = useState(false);
const [invalidEmailError, setInvalidEmailError] = useState('');
const [invalidPasswordError, setInvalidPasswordError] = useState('');

const isFormValid = email && password;

// const { push } = useRouter();
const handleLogin = async () => {
// Define handleLogin
try {
await signIn(email, password);
router.push('/'); // Redirect to the home page on success
} catch (error) {
if (error instanceof Error) {
console.error('Login Error:', error.message);
const { error } = await signIn(email, password);
// push('/');

if (error) {
// Match error messages from Supabase
if (error.message.includes('Invalid login credentials')) {
setInvalidEmailError('Invalid email address');
setInvalidPasswordError('Invalid password');
}
return;
}

// Clear errors on success
setInvalidEmailError('');
setInvalidPasswordError('');
} catch (err) {
console.error('Login Error:', err);
setInvalidEmailError('An unexpected error occurred. Please try again.');
}
};

return (
<>
<input
name="email"
onChange={e => setEmail(e.target.value)}
value={email}
placeholder="Email"
/>
{/* Email input*/}
<input
type="password"
name="password"
onChange={e => setPassword(e.target.value)}
value={password}
placeholder="Password"
/>
<button type="button" onClick={handleLogin}>
Sign in
</button>{' '}
{/* Sign in button */}
</>
<StyledForm onSubmit={handleLogin}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
<H2 style={{ color: COLORS.shrub }}>Log In</H2>
<div>
<TextInput
id="email-input"
type="email"
label="Email"
onChange={setEmail}
value={email}
error={!!invalidEmailError}
/>
{/* Email input*/}
<P3 $color={COLORS.errorRed}>{invalidEmailError}</P3>
</div>
<div>
<TextInput
id="password-input"
label="Password"
type="password"
onChange={setPassword}
value={password}
isVisible={showPassword}
toggleVisibility={() => setShowPassword(!showPassword)}
error={!!invalidPasswordError}
/>
<P3 $color={COLORS.errorRed}>{invalidPasswordError}</P3>
{/* Password input*/}
</div>
<StyledButton
type="button"
onClick={handleLogin}
disabled={!isFormValid}
>
Log in
</StyledButton>{' '}
{/* Sign in button */}
</div>
</StyledForm>
);
}
235 changes: 155 additions & 80 deletions app/(auth)/signup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,122 +2,197 @@

import { useState } from 'react';
import PasswordComplexity from '@/components/PasswordComplexity';
import PasswordInput from '@/components/PasswordInput';
import TextInput from '@/components/TextInput';
import { StyledButton, StyledForm } from '@/components/TextInput/styles';
import COLORS from '@/styles/colors';
import { H2, P3 } from '@/styles/text';
import { useAuth } from '@/utils/AuthProvider';

export default function SignUp() {
const { signUp } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>('');
const [passwordError, setPasswordError] = useState('');
const [passwordComplexityError, setPasswordComplexityError] = useState<
string | null
>(null);
const [passwordComplexity, setPasswordComplexity] = useState<boolean>(false);
const [samePasswordCheck, setSamePasswordCheck] = useState('');
const [mismatchError, setMismatchError] = useState('');
const [isPasswordComplexityMet, setIsPasswordComplexityMet] =
useState<boolean>(false);
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [checkEmailExistsError] = useState('');
const [checkValidEmailError, setCheckValidEmailError] = useState('');
const [isSubmitted, setIsSubmitted] = useState(false);
const [isEmailValid, setIsEmailValid] = useState(true);

const isFormValid = email && password && confirmPassword;

const isValidEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};

const handleEmailChange = async (newEmail: string) => {
setEmail(newEmail);

// Validate email format
if (!isValidEmail(newEmail)) {
setIsEmailValid(false);
setCheckValidEmailError('Please enter a valid email address');
} else {
setIsEmailValid(true);
setCheckValidEmailError('');
}
// Check if the email already exists
};

// Handles input to password
const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newPassword = e.target.value;
const handlePasswordChange = (newPassword: string) => {
setPassword(newPassword);
validatePasswords(newPassword, confirmPassword);
validatePasswordComplexity(newPassword);

if (!newPassword || !confirmPassword) {
setMismatchError('');
setSamePasswordCheck('');
return;
}

// Set mismatch error if passwords do not match
if (newPassword !== confirmPassword) {
setMismatchError('✗ Passwords do not match');
setSamePasswordCheck('');
} else {
setMismatchError('');
setSamePasswordCheck('✓ Passwords match');
}

validateIsPasswordComplexityMet(newPassword);
};

// Handles input to confirm password
const handleConfirmPasswordChange = (
e: React.ChangeEvent<HTMLInputElement>,
) => {
const newConfirmPassword = e.target.value;
const handleConfirmPasswordChange = (newConfirmPassword: string) => {
setConfirmPassword(newConfirmPassword);
validatePasswords(password, newConfirmPassword);
};

// Checks if passwords match and sets error
const validatePasswords = (
password: string | null,
confirmPassword: string | null,
) => {
if (password !== confirmPassword) {
setPasswordError('Passwords do not match.');
// Clear mismatch error if either field is empty
if (!password || !newConfirmPassword) {
setMismatchError('');
setSamePasswordCheck('');
return;
}

// Set mismatch error if passwords do not match
if (password !== newConfirmPassword) {
setMismatchError('✗ Passwords do not match');
setSamePasswordCheck('');
} else {
setPasswordError(''); // Clear error when passwords match
setMismatchError('');
setSamePasswordCheck('✓ Passwords match');
}
};

// Set password complexity error if requirements are not met
const validatePasswordComplexity = (password: string | null) => {
const validateIsPasswordComplexityMet = (password: string | null) => {
const hasLowerCase = /[a-z]/.test(password || '');
const hasNumber = /\d/.test(password || '');
const longEnough = (password || '').length >= 8;

if (password && hasLowerCase && hasNumber && longEnough) {
setPasswordComplexity(true);
setPasswordComplexityError(null); // Clear error if all conditions are met
} else if (password) {
setPasswordComplexity(false);
setPasswordComplexityError('Password must meet complexity requirements');
setIsPasswordComplexityMet(true);
} else {
setPasswordComplexity(false);
setPasswordComplexityError(null); // Clear error if password is empty
setIsPasswordComplexityMet(false);
}
};

const handleSignUp = async () => {
if (password) {
setIsSubmitted(true);

if (!isValidEmail(email)) {
setCheckValidEmailError('Please enter a valid email address');
} else {
setCheckValidEmailError(''); // Clear email format error if valid
}

try {
await signUp(email, password);
} catch (error) {
console.error('Sign up failed:', error);
alert('There was an error during sign up. Please try again.');
}
};

return (
<>
<input
name="email"
onChange={e => setEmail(e.target.value)}
value={email}
placeholder="Email"
/>
{/* Email input*/}
<PasswordInput
value={password}
onChange={handlePasswordChange}
placeholder="Password"
isVisible={showPassword}
toggleVisibility={() => setShowPassword(!showPassword)}
name="password"
/>
{/* Password input with toggle visibility */}
<PasswordInput
value={confirmPassword}
onChange={handleConfirmPasswordChange}
placeholder="Confirm Password"
isVisible={showConfirmPassword}
toggleVisibility={() => setShowConfirmPassword(!showConfirmPassword)}
name="confirmPassword"
/>
{/* Confirm password input with toggle visibility */}
<button
type="button"
onClick={handleSignUp}
disabled={!email || !!passwordError || !!passwordComplexityError}
>
Sign up
</button>{' '}
{/* Sign up button */}
{confirmPassword && passwordError && (
<p style={{ color: 'red' }}>{passwordError}</p>
)}
{/* Conditional password validation error message */}
<PasswordComplexity
password={password || ''} // Set default value if password is null
/>
{/* Password complexity requirements */}
{password && !passwordComplexity && passwordComplexityError && (
<p style={{ color: 'red' }}>{passwordComplexityError}</p>
)}
{/* Password complexity error message */}
</>
<StyledForm onSubmit={handleSignUp}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
<H2 style={{ color: COLORS.shrub }}>Sign Up</H2>
<div>
<TextInput
id="email-input"
label="Email"
type="email"
onChange={handleEmailChange}
value={email}
error={!!checkEmailExistsError || (!isEmailValid && isSubmitted)}
/>
{/* Email input*/}
{checkEmailExistsError && (
<P3 style={{ color: COLORS.errorRed }}>{checkEmailExistsError}</P3>
)}
{!isEmailValid && isSubmitted && (
<P3 style={{ color: COLORS.errorRed }}>{checkValidEmailError}</P3>
)}
</div>
<div>
<TextInput
id="password-input"
type="password"
value={password || ''}
onChange={handlePasswordChange}
isVisible={showPassword}
toggleVisibility={() => setShowPassword(!showPassword)}
label="Password"
error={isSubmitted && !isPasswordComplexityMet}
/>
{/* Password input*/}

<PasswordComplexity
password={password} // Set default value if password is null
/>

{/* Password complexity requirements */}
</div>
<div>
{password && (
<TextInput
id="confirm-password-input"
type="password"
value={confirmPassword || ''}
onChange={handleConfirmPasswordChange}
isVisible={showConfirmPassword}
toggleVisibility={() =>
setShowConfirmPassword(!showConfirmPassword)
}
label="Confirm Password"
error={isSubmitted && !samePasswordCheck}
/>
)}
{/* Confirm password input with toggle visibility */}

{samePasswordCheck && (
<P3 style={{ color: '#0D8817' }}>{samePasswordCheck}</P3>
)}

{isSubmitted && !samePasswordCheck && (
<P3 style={{ color: COLORS.errorRed }}>{mismatchError}</P3>
)}
{/* Conditional password validation error message */}
</div>
<StyledButton
type="button"
onClick={handleSignUp}
disabled={!isFormValid}
>
<P3 style={{ color: '#FFF' }}>Sign up</P3>
</StyledButton>{' '}
{/* Sign up button */}
</div>
</StyledForm>
);
}
Loading

0 comments on commit 0b8030d

Please sign in to comment.