Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 27 additions & 9 deletions frontend/src/components/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// frontend/src/components/Login.jsx
import { Link, useNavigate } from 'react-router-dom';
import '../styles/auth.css';
import { useForm } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { loginUser } from '../redux/actions/authActions'; // Updated import
import { useEffect } from 'react';
import { loginUser } from '../redux/actions/authActions';
import { useEffect, useState } from 'react';
import { resetAuthState } from '../redux/reducers/authSlice';
import ThemeToggler from './ThemeToggler'; // Import the new component

const Login = () => {
const navigate = useNavigate();
Expand All @@ -26,31 +26,49 @@ const Login = () => {
}
}, [isAuthenticated, navigate]);

// Reset loading state when component mounts
useEffect(() => {
dispatch(resetAuthState());
}, [dispatch]);

return (
<div className="auth-container">
<ThemeToggler />
<form className="auth-form" onSubmit={handleSubmit(submitHandler)}>
<div className="auth-header">
{error && <h2 style={{ fontSize: '1rem', color: 'red' }}>{error}</h2>}
<h2>Welcome Back</h2>
<div className="auth-logo">
<svg className="logo-icon-svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12.48 3.52a1 1 0 0 0-1 1v2.92a1 1 0 0 0 .52.88l5.44 3.14a1 1 0 0 0 1.5-.87V7.52a1 1 0 0 0-.52-.88l-5.44-3.14a1 1 0 0 0-.5 0zM5.08 7.52a1 1 0 0 0-.52.88v2.92a1 1 0 0 0 .52.88l5.44 3.14a1 1 0 0 0 1.5-.87V11.4a1 1 0 0 0-.52-.88L6.58 7.52a1 1 0 0 0-1.5 0zM12 14.5l-5.44 3.14a1 1 0 0 0-.52.88v2.92a1 1 0 0 0 1.5.87l5.44-3.14a1 1 0 0 0 .52-.88v-2.92a1 1 0 0 0-1.5-.87z" /> </svg>
<span>Atomic</span>
</div>
<h2>Welcome back</h2>
<p>Welcome back! Please enter your details.</p>
</div>
{error && <p className="auth-error">{error}</p>}
<div className="form-group">
<label htmlFor="email">Email</label>
<input {...register('email')} type="email" id="email" placeholder="Enter your email" />
<input
{...register('email')}
type="email"
id="email"
placeholder="Enter your email"
required
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input {...register('password')} type="password" id="password" placeholder="Enter your password" />
<input
{...register('password')}
type="password"
id="password"
placeholder="Password"
required
/>
</div>
{/* <a href="#" className="forgot-password">Forgot password</a> */}
<button type="submit" className="auth-button" disabled={loading}>
{loading ? 'Logging in...' : 'Login'}
</button>
<p className="auth-switch">
Don't have an account? <Link to="/register">Register</Link>
Don't have an account? <Link to="/register">Sign up</Link>
</p>
</form>
</div>
Expand Down
64 changes: 39 additions & 25 deletions frontend/src/components/Register.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// frontend/src/components/Register.jsx
import "../styles/auth.css";
import { Link, useNavigate } from "react-router-dom";
import "../styles/auth.css";
import { useForm } from "react-hook-form";
import { useDispatch, useSelector } from "react-redux";
import { registerUser } from "../redux/actions/authActions"; // Updated import
import { registerUser } from "../redux/actions/authActions";
import { useEffect } from "react";
import { resetAuthState } from "../redux/reducers/authSlice";
import ThemeToggler from './ThemeToggler';

const Register = () => {
const navigate = useNavigate();
Expand All @@ -31,43 +31,56 @@ const Register = () => {
}
}, [isAuthenticated, navigate]);

// Reset loading state when component mounts
useEffect(() => {
dispatch(resetAuthState());
}, [dispatch]);

return (
<div className="auth-container">
<ThemeToggler />
<form className="auth-form" onSubmit={handleSubmit(submitHandler)}>
<div className="auth-header">
{error && <h2 style={{ fontSize: '1rem', color: 'red' }}>{error}</h2>}
<h2>Create Account</h2>
<div className="auth-logo">
<svg className="logo-icon-svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path d="M12.48 3.52a1 1 0 0 0-1 1v2.92a1 1 0 0 0 .52.88l5.44 3.14a1 1 0 0 0 1.5-.87V7.52a1 1 0 0 0-.52-.88l-5.44-3.14a1 1 0 0 0-.5 0zM5.08 7.52a1 1 0 0 0-.52.88v2.92a1 1 0 0 0 .52.88l5.44 3.14a1 1 0 0 0 1.5-.87V11.4a1 1 0 0 0-.52-.88L6.58 7.52a1 1 0 0 0-1.5 0zM12 14.5l-5.44 3.14a1 1 0 0 0-.52.88v2.92a1 1 0 0 0 1.5.87l5.44-3.14a1 1 0 0 0 .52-.88v-2.92a1 1 0 0 0-1.5-.87z" /> </svg>
<span>Atomic</span>
</div>
<h2>Create an account</h2>
<p>Start your journey with us.</p>
</div>
<div className="form-group">
<label htmlFor="firstName">First Name</label>
<input
{...register("firstName")}
type="text"
id="firstName"
placeholder="Enter your first name"
/>
</div>
<div className="form-group">
<label htmlFor="lastName">Last Name</label>
<input
{...register("lastName")}
type="text"
id="lastName"
placeholder="Enter your last name"
/>
{error && <p className="auth-error">{error}</p>}

{/* UPDATED PART: Wrap name fields in a form-row div */}
<div className="form-row">
<div className="form-group">
<label htmlFor="firstName">First Name</label>
<input
{...register("firstName")}
type="text"
id="firstName"
placeholder="First Name"
required
/>
</div>
<div className="form-group">
<label htmlFor="lastName">Last Name</label>
<input
{...register("lastName")}
type="text"
id="lastName"
placeholder="Last Name"
required
/>
</div>
</div>

<div className="form-group">
<label htmlFor="email">Email</label>
<input
{...register("email")}
type="email"
id="email"
placeholder="Enter your email"
required
/>
</div>
<div className="form-group">
Expand All @@ -76,11 +89,12 @@ const Register = () => {
{...register("password")}
type="password"
id="password"
placeholder="Enter your password"
placeholder="Password"
required
/>
</div>
<button type="submit" className="auth-button" disabled={loading}>
{loading ? 'Registering...' : 'Register'}
{loading ? 'Creating account...' : 'Create account'}
</button>
<p className="auth-switch">
Already have an account? <Link to="/login">Login</Link>
Expand Down
38 changes: 38 additions & 0 deletions frontend/src/components/ThemeToggler.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { useState, useEffect } from 'react';

const ThemeToggler = () => {
const [theme, setTheme] = useState(localStorage.getItem('theme') || 'light');

useEffect(() => {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
}, [theme]);

const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};

return (
<button onClick={toggleTheme} className="theme-toggle-button" aria-label="Toggle theme">
<div className="theme-toggle-icon-container">
<svg className={`theme-icon sun-icon ${theme === 'light' ? 'active' : ''}`} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
<svg className={`theme-icon moon-icon ${theme === 'dark' ? 'active' : ''}`} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
</div>
<span className="theme-toggle-text">{theme === 'light' ? 'Light Theme' : 'Dark Theme'}</span>
</button>
);
};

export default ThemeToggler;
Loading