no separate login/register page, use modal throughout

This commit is contained in:
jackiettran
2025-10-10 15:26:07 -04:00
parent 0a9b875a9d
commit 462dbf6b7a
12 changed files with 125 additions and 296 deletions

View File

@@ -4,6 +4,7 @@ import { useAuth } from '../contexts/AuthContext';
import { itemAPI } from '../services/api';
import { Item } from '../types';
import ItemCard from '../components/ItemCard';
import AuthButton from '../components/AuthButton';
const Home: React.FC = () => {
const { user } = useAuth();
@@ -48,9 +49,9 @@ const Home: React.FC = () => {
List Your Items
</Link>
) : (
<Link to="/register" className="btn btn-outline-light">
<AuthButton mode="signup" className="btn btn-outline-light">
Start Earning
</Link>
</AuthButton>
)}
</div>
</div>
@@ -292,9 +293,9 @@ const Home: React.FC = () => {
List an Item
</Link>
) : (
<Link to="/register" className="btn btn-outline-light btn-lg">
<AuthButton mode="signup" className="btn btn-outline-light btn-lg">
Sign Up Free
</Link>
</AuthButton>
)}
</div>
</div>

View File

@@ -4,6 +4,7 @@ import { useAuth } from '../contexts/AuthContext';
import { itemRequestAPI } from '../services/api';
import { ItemRequest, ItemRequestResponse } from '../types';
import RequestResponseModal from '../components/RequestResponseModal';
import AuthButton from '../components/AuthButton';
const ItemRequestDetail: React.FC = () => {
const { id } = useParams<{ id: string }>();
@@ -330,9 +331,9 @@ const ItemRequestDetail: React.FC = () => {
</div>
) : !user ? (
<div className="text-center">
<Link to="/login" className="btn btn-outline-primary">
<AuthButton mode="login" className="btn btn-outline-primary">
Log in to Respond
</Link>
</AuthButton>
</div>
) : null}

View File

@@ -4,6 +4,7 @@ import { useAuth } from '../contexts/AuthContext';
import { itemRequestAPI } from '../services/api';
import { ItemRequest } from '../types';
import ItemRequestCard from '../components/ItemRequestCard';
import AuthButton from '../components/AuthButton';
const ItemRequests: React.FC = () => {
const { user } = useAuth();
@@ -200,7 +201,7 @@ const ItemRequests: React.FC = () => {
<div className="mt-4">
<div className="alert alert-info" role="alert">
<i className="bi bi-info-circle me-2"></i>
<Link to="/login" className="alert-link">Log in</Link> to create your own item requests or respond to existing ones.
<AuthButton mode="login" className="alert-link" asLink>Log in</AuthButton> to create your own item requests or respond to existing ones.
</div>
</div>
)}

View File

@@ -1,89 +0,0 @@
import React, { useState } from 'react';
import { Link, useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import PasswordInput from '../components/PasswordInput';
const Login: React.FC = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const { login } = useAuth();
const navigate = useNavigate();
const location = useLocation();
const from = location.state?.from?.pathname || '/';
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
setLoading(true);
try {
await login(email, password);
navigate(from, { replace: true });
} catch (err: any) {
setError(err.response?.data?.error || 'Failed to login');
} finally {
setLoading(false);
}
};
return (
<div className="container mt-5">
<div className="row justify-content-center">
<div className="col-md-6 col-lg-5">
<div className="card shadow">
<div className="card-body p-4">
<h2 className="text-center mb-4">Login</h2>
{error && (
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label htmlFor="email" className="form-label">
Email
</label>
<input
type="email"
className="form-control"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<PasswordInput
id="password"
label="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<button
type="submit"
className="btn btn-primary w-100"
disabled={loading}
>
{loading ? 'Logging in...' : 'Login'}
</button>
</form>
<div className="text-center mt-3">
<p className="mb-0">
Don't have an account?{' '}
<Link to="/register" state={{ from: location.state?.from }} className="text-decoration-none">
Sign up
</Link>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default Login;

View File

@@ -1,13 +1,12 @@
import React, { useState, useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import { itemRequestAPI } from '../services/api';
import { ItemRequest, ItemRequestResponse } from '../types';
import ConfirmationModal from '../components/ConfirmationModal';
const MyRequests: React.FC = () => {
const { user } = useAuth();
const navigate = useNavigate();
const { user, openAuthModal } = useAuth();
const [requests, setRequests] = useState<ItemRequest[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
@@ -20,9 +19,9 @@ const MyRequests: React.FC = () => {
if (user) {
fetchMyRequests();
} else {
navigate('/login');
openAuthModal('login');
}
}, [user, navigate]);
}, [user, openAuthModal]);
const fetchMyRequests = async () => {
try {

View File

@@ -1,161 +0,0 @@
import React, { useState } from 'react';
import { Link, useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import PasswordInput from '../components/PasswordInput';
const Register: React.FC = () => {
const [formData, setFormData] = useState({
username: '',
email: '',
password: '',
firstName: '',
lastName: '',
phone: ''
});
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const { register } = useAuth();
const navigate = useNavigate();
const location = useLocation();
const from = location.state?.from?.pathname || '/';
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
setLoading(true);
try {
await register(formData);
navigate(from, { replace: true });
} catch (err: any) {
setError(err.response?.data?.error || 'Failed to create account');
} finally {
setLoading(false);
}
};
return (
<div className="container mt-5">
<div className="row justify-content-center">
<div className="col-md-6 col-lg-5">
<div className="card shadow">
<div className="card-body p-4">
<h2 className="text-center mb-4">Create Account</h2>
{error && (
<div className="alert alert-danger" role="alert">
{error}
</div>
)}
<form onSubmit={handleSubmit}>
<div className="row">
<div className="col-md-6 mb-3">
<label htmlFor="firstName" className="form-label">
First Name
</label>
<input
type="text"
className="form-control"
id="firstName"
name="firstName"
value={formData.firstName}
onChange={handleChange}
required
/>
</div>
<div className="col-md-6 mb-3">
<label htmlFor="lastName" className="form-label">
Last Name
</label>
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
value={formData.lastName}
onChange={handleChange}
required
/>
</div>
</div>
<div className="mb-3">
<label htmlFor="username" className="form-label">
Username
</label>
<input
type="text"
className="form-control"
id="username"
name="username"
value={formData.username}
onChange={handleChange}
required
/>
</div>
<div className="mb-3">
<label htmlFor="email" className="form-label">
Email
</label>
<input
type="email"
className="form-control"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
required
/>
</div>
<div className="mb-3">
<label htmlFor="phone" className="form-label">
Phone (optional)
</label>
<input
type="tel"
className="form-control"
id="phone"
name="phone"
value={formData.phone}
onChange={handleChange}
/>
</div>
<PasswordInput
id="password"
name="password"
label="Password"
value={formData.password}
onChange={handleChange}
required
/>
<button
type="submit"
className="btn btn-primary w-100"
disabled={loading}
>
{loading ? 'Creating Account...' : 'Sign Up'}
</button>
</form>
<div className="text-center mt-3">
<p className="mb-0">
Already have an account?{' '}
<Link to="/login" className="text-decoration-none">
Login
</Link>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default Register;