Initial commit
All checks were successful
Docker Build and Publish / build-and-push (push) Successful in 2m17s

This commit is contained in:
2026-01-11 18:55:03 -05:00
commit 493ea4688c
45 changed files with 7107 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
import React, { useState, useContext } from 'react';
import { AuthContext } from '../../contexts/AuthContext';
import { useNavigate, Link } from 'react-router-dom';
import GoCLayout from '../Layout/GoCLayout';
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const { login, loading } = useContext(AuthContext);
const navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
setError('');
try {
await login(email, password);
navigate('/');
} catch (err) {
setError('Failed to log in. Please check your credentials.');
}
};
return (
<GoCLayout>
<div className="flex items-center justify-center p-4">
<div className="bg-white p-8 rounded-lg shadow-md w-full max-w-md border border-gray-200">
<h2 className="text-2xl font-bold mb-6 text-center text-gray-800">Sign In</h2>
{error && <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="email">
Email
</label>
<input
type="email"
id="email"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div className="mb-6">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="password">
Password
</label>
<input
type="password"
id="password"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<div className="flex items-center justify-between flex-col gap-4">
<button
className="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full transition duration-300"
type="submit"
disabled={loading}
>
{loading ? 'Logging in...' : 'Sign In'}
</button>
<Link to="/register" className="text-blue-600 hover:text-blue-800 text-sm">
Don't have an account? Register here
</Link>
</div>
</form>
</div>
</div>
</GoCLayout>
);
};
export default Login;

View File

@@ -0,0 +1,127 @@
import React, { useState, useContext } from 'react';
import { AuthContext } from '../../contexts/AuthContext';
import { useNavigate, Link } from 'react-router-dom';
import { pb } from '../../lib/pocketbase';
import GoCLayout from '../Layout/GoCLayout';
const Register = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [passwordConfirm, setPasswordConfirm] = useState('');
const [error, setError] = useState('');
const { login } = useContext(AuthContext);
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setError('');
if (password !== passwordConfirm) {
return setError('Passwords do not match');
}
setLoading(true);
try {
// Create user
const data = {
"username": `user_${Math.random().toString(36).slice(2, 12)}`, // Generate random username if required or let PB handle it if not
"email": email,
"emailVisibility": true,
"password": password,
"passwordConfirm": passwordConfirm,
"name": name
};
await pb.collection('users').create(data);
// Log in immediately after creation
await login(email, password);
navigate('/');
} catch (err) {
console.error("Registration error:", err);
setError('Failed to create account. Please try again.');
} finally {
setLoading(false);
}
};
return (
<GoCLayout>
<div className="flex items-center justify-center p-4">
<div className="bg-white p-8 rounded-lg shadow-md w-full max-w-md border border-gray-200">
<h2 className="text-2xl font-bold mb-6 text-center text-gray-800">Create Account</h2>
{error && <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="name">
Name
</label>
<input
type="text"
id="name"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="email">
Email
</label>
<input
type="email"
id="email"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="password">
Password
</label>
<input
type="password"
id="password"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<div className="mb-6">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="passwordConfirm">
Confirm Password
</label>
<input
type="password"
id="passwordConfirm"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:ring-2 focus:ring-blue-500"
value={passwordConfirm}
onChange={(e) => setPasswordConfirm(e.target.value)}
required
/>
</div>
<div className="flex items-center justify-between flex-col gap-4">
<button
className="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full transition duration-300"
type="submit"
disabled={loading}
>
{loading ? 'Creating Account...' : 'Register'}
</button>
<Link to="/" className="text-blue-600 hover:text-blue-800 text-sm">
Already have an account? Sign In
</Link>
</div>
</form>
</div>
</div>
</GoCLayout>
);
};
export default Register;