Add .gitignore Removed node_modules from previous commit Fix task modes Fix task modes Fix task modes Remove node_modules Update basic task modal Add notes functionality Improve UI Setup views Add scopes Fix projects layout Restructure Fix rest of the UI issues Cleanup old views Add .env to .gitignore
101 lines
3 KiB
TypeScript
101 lines
3 KiB
TypeScript
// src/Login.tsx
|
|
|
|
import React, { useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
const Login: React.FC = () => {
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [error, setError] = useState<string | null>(null);
|
|
const navigate = useNavigate();
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
try {
|
|
const response = await fetch('/login', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ email, password }),
|
|
credentials: 'include'
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
console.log('Login successful:', data);
|
|
navigate('/tasks?type=today&order_by=due_date%3Aasc');
|
|
} else {
|
|
setError(data.errors[0] || 'Login failed. Please try again.');
|
|
}
|
|
} catch (err) {
|
|
setError('An error occurred. Please try again.');
|
|
console.error('Error during login:', err);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="bg-gray-100 flex items-center justify-center min-h-screen px-4">
|
|
<div className="bg-white p-8 rounded-lg shadow-md w-full max-w-sm">
|
|
<h2 className="text-2xl font-bold mb-6 text-center text-gray-700">
|
|
Login
|
|
</h2>
|
|
{error && (
|
|
<div className="mb-4 text-center text-red-500">
|
|
{error}
|
|
</div>
|
|
)}
|
|
<form onSubmit={handleSubmit}>
|
|
<div className="mb-4">
|
|
<label
|
|
htmlFor="email"
|
|
className="block text-gray-600 mb-1"
|
|
>
|
|
Email
|
|
</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
name="email"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
className="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="mb-4">
|
|
<label
|
|
htmlFor="password"
|
|
className="block text-gray-600 mb-1"
|
|
>
|
|
Password
|
|
</label>
|
|
<input
|
|
type="password"
|
|
id="password"
|
|
name="password"
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
className="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
required
|
|
/>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
className="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition-colors"
|
|
>
|
|
Login
|
|
</button>
|
|
</form>
|
|
<div className="mt-6 text-center">
|
|
<a href="#" className="text-blue-500 hover:underline">
|
|
Forgot Password?
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Login;
|