SQL CODE BUGS FIXES
Login Auth now implemented Persistance login page AI app.jsx formating
This commit is contained in:
@@ -1,37 +1,34 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
|
||||
import Navbar from './components/Navbar';
|
||||
import Home from './pages/Home';
|
||||
import Settings from './pages/Settings';
|
||||
import Selling from './pages/Selling';
|
||||
import Transactions from './pages/Transactions';
|
||||
import Favorites from './pages/Favorites';
|
||||
import ProductDetail from './pages/ProductDetail';
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Routes,
|
||||
Route,
|
||||
Navigate,
|
||||
} from "react-router-dom";
|
||||
import Navbar from "./components/Navbar";
|
||||
import Home from "./pages/Home";
|
||||
import Settings from "./pages/Settings";
|
||||
import Selling from "./pages/Selling";
|
||||
import Transactions from "./pages/Transactions";
|
||||
import Favorites from "./pages/Favorites";
|
||||
import ProductDetail from "./pages/ProductDetail";
|
||||
|
||||
function App() {
|
||||
// Authentication state
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
const [user, setUser] = useState(null);
|
||||
|
||||
// Authentication state - initialize from localStorage if available
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(() => {
|
||||
return localStorage.getItem("isAuthenticated") === "true";
|
||||
});
|
||||
const [user, setUser] = useState(() => {
|
||||
const savedUser = localStorage.getItem("user");
|
||||
return savedUser ? JSON.parse(savedUser) : null;
|
||||
});
|
||||
|
||||
// UI state for login/signup form
|
||||
const [isSignUp, setIsSignUp] = useState(false);
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
ucid: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
password: '',
|
||||
});
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [showImage, setShowImage] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
const [error, setError] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
// Fake users database
|
||||
const fakeUsers = [
|
||||
{ email: 'john1@ucalgary.ca', password: 'password123', name: 'John Doe' },
|
||||
{ email: 'jane@ucalgary.ca', password: 'password456', name: 'Jane Smith' }
|
||||
];
|
||||
|
||||
// Auto-hide image on smaller screens
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
@@ -41,105 +38,127 @@ function App() {
|
||||
setShowImage(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Initial check
|
||||
handleResize();
|
||||
|
||||
|
||||
// Listen for window resize
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
// Cleanup
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
const { id, value } = e.target;
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[id]: value
|
||||
}));
|
||||
|
||||
// Clear any error when user starts typing again
|
||||
if (error) setError('');
|
||||
};
|
||||
|
||||
const handleLogin = (e) => {
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
setIsLoading(true);
|
||||
setError("");
|
||||
|
||||
// Get form data directly from the form
|
||||
const formData = new FormData(e.target);
|
||||
const formValues = Object.fromEntries(formData.entries());
|
||||
|
||||
// Validate email and password
|
||||
if (!formData.email || !formData.password) {
|
||||
setError('Email and password are required');
|
||||
if (!formValues.email || !formValues.password) {
|
||||
setError("Email and password are required");
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSignUp) {
|
||||
// Handle Sign Up
|
||||
console.log('Sign Up Form Data:', formData);
|
||||
|
||||
// Simulate saving new user to database
|
||||
const newUser = {
|
||||
name: formData.name,
|
||||
email: formData.email,
|
||||
ucid: formData.ucid,
|
||||
phone: formData.phone
|
||||
};
|
||||
|
||||
// Set authenticated user
|
||||
setUser(newUser);
|
||||
setIsAuthenticated(true);
|
||||
|
||||
console.log('New user registered:', newUser);
|
||||
} else {
|
||||
// Handle Login
|
||||
console.log('Login Attempt:', { email: formData.email, password: formData.password });
|
||||
|
||||
// Check against fake user database
|
||||
const foundUser = fakeUsers.find(
|
||||
user => user.email === formData.email && user.password === formData.password
|
||||
);
|
||||
|
||||
if (foundUser) {
|
||||
|
||||
try {
|
||||
if (isSignUp) {
|
||||
// Handle Sign Up
|
||||
console.log("Sign Up Form Data:", formValues);
|
||||
|
||||
// You could add API endpoint for registration here
|
||||
// For now, we'll just simulate a successful registration
|
||||
const newUser = {
|
||||
name: formValues.name,
|
||||
email: formValues.email,
|
||||
ucid: formValues.ucid,
|
||||
phone: formValues.phone,
|
||||
};
|
||||
|
||||
// Set authenticated user
|
||||
setUser({
|
||||
name: foundUser.name,
|
||||
email: foundUser.email
|
||||
});
|
||||
setUser(newUser);
|
||||
setIsAuthenticated(true);
|
||||
console.log('Login successful for:', foundUser.name);
|
||||
|
||||
// Save to localStorage to persist across refreshes
|
||||
localStorage.setItem("isAuthenticated", "true");
|
||||
localStorage.setItem("user", JSON.stringify(newUser));
|
||||
|
||||
console.log("New user registered:", newUser);
|
||||
} else {
|
||||
setError('Invalid email or password');
|
||||
console.log('Login failed: Invalid credentials');
|
||||
// Handle Login with API
|
||||
console.log("Login Attempt:", {
|
||||
email: formValues.email,
|
||||
password: formValues.password,
|
||||
});
|
||||
|
||||
// Make API call to localhost:3030/find_user
|
||||
const response = await fetch("http://localhost:3030/find_user", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: formValues.email,
|
||||
password: formValues.password,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
|
||||
const userData = await response.json();
|
||||
|
||||
if (userData && userData.found) {
|
||||
// Create user object
|
||||
const userObj = {
|
||||
name: userData.name || userData.email,
|
||||
email: userData.email,
|
||||
// Add any other user data returned from the API
|
||||
};
|
||||
|
||||
// Set authenticated user with data from API
|
||||
setUser(userObj);
|
||||
setIsAuthenticated(true);
|
||||
|
||||
// Save to localStorage to persist across refreshes
|
||||
localStorage.setItem("isAuthenticated", "true");
|
||||
localStorage.setItem("user", JSON.stringify(userObj));
|
||||
|
||||
console.log("Login successful for:", userData.email);
|
||||
} else {
|
||||
// Show error message for invalid credentials
|
||||
setError("Invalid email or password");
|
||||
console.log("Login failed: Invalid credentials");
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Authentication error:", err);
|
||||
setError("Authentication failed. Please try again later.");
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleLogout = () => {
|
||||
// Clear authentication state
|
||||
setIsAuthenticated(false);
|
||||
setUser(null);
|
||||
console.log('User logged out');
|
||||
|
||||
// Reset form data
|
||||
setFormData({
|
||||
name: '',
|
||||
ucid: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
// Clear localStorage
|
||||
localStorage.removeItem("isAuthenticated");
|
||||
localStorage.removeItem("user");
|
||||
|
||||
console.log("User logged out");
|
||||
};
|
||||
|
||||
const toggleAuthMode = () => {
|
||||
setIsSignUp(!isSignUp);
|
||||
setError(''); // Clear errors when switching modes
|
||||
|
||||
// Reset form data when switching modes
|
||||
setFormData({
|
||||
name: '',
|
||||
ucid: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
password: '',
|
||||
});
|
||||
setError(""); // Clear errors when switching modes
|
||||
};
|
||||
|
||||
// Login component
|
||||
@@ -148,9 +167,9 @@ function App() {
|
||||
{/* Image Section - Automatically hidden on mobile */}
|
||||
{showImage && (
|
||||
<div className="w-1/2 relative">
|
||||
<img
|
||||
src="../market.png"
|
||||
alt="auth illustration"
|
||||
<img
|
||||
src="../market.png"
|
||||
alt="auth illustration"
|
||||
className="w-full h-full object-cover opacity-75"
|
||||
/>
|
||||
<div className="absolute inset-0"></div>
|
||||
@@ -158,14 +177,18 @@ function App() {
|
||||
)}
|
||||
|
||||
{/* Auth Form Section */}
|
||||
<div className={`${showImage ? 'w-1/2' : 'w-full'} bg-white p-8 flex items-center justify-center`}>
|
||||
<div
|
||||
className={`${
|
||||
showImage ? "w-1/2" : "w-full"
|
||||
} bg-white p-8 flex items-center justify-center`}
|
||||
>
|
||||
<div className="w-full max-w-md">
|
||||
<div className="mb-8 text-center">
|
||||
<h2 className="text-2xl font-bold text-gray-800">
|
||||
{isSignUp ? 'Create Account' : 'Welcome Back'}
|
||||
{isSignUp ? "Create Account" : "Welcome Back"}
|
||||
</h2>
|
||||
<p className="mt-2 text-gray-600">
|
||||
{isSignUp ? 'Set up your new account' : 'Sign in to your account'}
|
||||
{isSignUp ? "Set up your new account" : "Sign in to your account"}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -175,19 +198,21 @@ function App() {
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleLogin} className="space-y-4">
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{/* Name field - only for signup */}
|
||||
{isSignUp && (
|
||||
<div>
|
||||
<label htmlFor="name" className="block mb-1 text-sm font-medium text-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block mb-1 text-sm font-medium text-gray-800"
|
||||
>
|
||||
Full Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
value={formData.name}
|
||||
onChange={handleInputChange}
|
||||
name="name"
|
||||
placeholder="Enter your name"
|
||||
className="w-full px-4 py-2 border border-gray-300 bg-white text-gray-800 focus:outline-none focus:border-green-500 focus:ring-1 focus:ring-green-500"
|
||||
required={isSignUp}
|
||||
@@ -197,14 +222,16 @@ function App() {
|
||||
|
||||
{isSignUp && (
|
||||
<div>
|
||||
<label htmlFor="ucid" className="block mb-1 text-sm font-medium text-gray-800">
|
||||
<label
|
||||
htmlFor="ucid"
|
||||
className="block mb-1 text-sm font-medium text-gray-800"
|
||||
>
|
||||
UCID
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="ucid"
|
||||
value={formData.ucid}
|
||||
onChange={handleInputChange}
|
||||
name="ucid"
|
||||
placeholder="1234567"
|
||||
className="w-full px-4 py-2 border border-gray-300 bg-white text-gray-800 focus:outline-none focus:border-green-500 focus:ring-1 focus:ring-green-500"
|
||||
required={isSignUp}
|
||||
@@ -213,30 +240,34 @@ function App() {
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label htmlFor="email" className="block mb-1 text-sm font-medium text-gray-800">
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block mb-1 text-sm font-medium text-gray-800"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
value={formData.email}
|
||||
onChange={handleInputChange}
|
||||
name="email"
|
||||
placeholder="your.email@ucalgary.ca"
|
||||
className="w-full px-4 py-2 border border-gray-300 bg-white text-gray-800 focus:outline-none focus:border-green-500 focus:ring-1 focus:ring-green-500"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
{isSignUp && (
|
||||
<div>
|
||||
<label htmlFor="phone" className="block mb-1 text-sm font-medium text-gray-800">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="block mb-1 text-sm font-medium text-gray-800"
|
||||
>
|
||||
Phone Number
|
||||
</label>
|
||||
<input
|
||||
type="tel"
|
||||
id="phone"
|
||||
value={formData.phone}
|
||||
onChange={handleInputChange}
|
||||
name="phone"
|
||||
placeholder="+1(123)456 7890"
|
||||
className="w-full px-4 py-2 border border-gray-300 bg-white text-gray-800 focus:outline-none focus:border-green-500 focus:ring-1 focus:ring-green-500"
|
||||
required={isSignUp}
|
||||
@@ -245,48 +276,52 @@ function App() {
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label htmlFor="password" className="block mb-1 text-sm font-medium text-gray-800">
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="block mb-1 text-sm font-medium text-gray-800"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
id="password"
|
||||
value={formData.password}
|
||||
onChange={handleInputChange}
|
||||
placeholder={isSignUp ? "Create a secure password" : "Enter your password"}
|
||||
className="w-full px-4 py-2 border border-gray-300 bg-white text-gray-800 focus:outline-none focus:border-green-500 focus:ring-1 focus:ring-green-500"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="absolute inset-y-0 right-0 pr-3 flex items-center text-sm text-gray-500 hover:text-green-500"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
>
|
||||
{showPassword ? 'Hide' : 'Show'}
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
placeholder={
|
||||
isSignUp
|
||||
? "Create a secure password"
|
||||
: "Enter your password"
|
||||
}
|
||||
className="w-full px-4 py-2 border border-gray-300 bg-white text-gray-800 focus:outline-none focus:border-green-500 focus:ring-1 focus:ring-green-500"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full px-6 py-2 text-base font-medium text-white bg-green-500 hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-offset-2 transition-colors"
|
||||
disabled={isLoading}
|
||||
className="w-full px-6 py-2 text-base font-medium text-white bg-green-500 hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-offset-2 transition-colors disabled:bg-green-300"
|
||||
>
|
||||
{isSignUp ? 'Create Account' : 'Sign In'}
|
||||
{isLoading
|
||||
? "Please wait..."
|
||||
: isSignUp
|
||||
? "Create Account"
|
||||
: "Sign In"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center text-sm text-gray-500">
|
||||
<p>
|
||||
{isSignUp ? 'Already have an account?' : "Don't have an account?"}
|
||||
{' '}
|
||||
<button
|
||||
{isSignUp
|
||||
? "Already have an account?"
|
||||
: "Don't have an account?"}{" "}
|
||||
<button
|
||||
onClick={toggleAuthMode}
|
||||
type="button"
|
||||
className="text-green-500 font-medium hover:text-green-700"
|
||||
>
|
||||
{isSignUp ? 'Sign in' : 'Sign up'}
|
||||
{isSignUp ? "Sign in" : "Sign up"}
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
@@ -301,7 +336,7 @@ function App() {
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to="/login" />;
|
||||
}
|
||||
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
@@ -309,90 +344,91 @@ function App() {
|
||||
<Router>
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
{/* Only show navbar when authenticated */}
|
||||
{isAuthenticated && <Navbar onLogout={handleLogout} userName={user?.name} />}
|
||||
|
||||
{isAuthenticated && (
|
||||
<Navbar onLogout={handleLogout} userName={user?.name} />
|
||||
)}
|
||||
|
||||
<Routes>
|
||||
{/* Public routes */}
|
||||
<Route
|
||||
path="/login"
|
||||
element={
|
||||
isAuthenticated ?
|
||||
<Navigate to="/" /> :
|
||||
<LoginComponent />
|
||||
}
|
||||
<Route
|
||||
path="/login"
|
||||
element={isAuthenticated ? <Navigate to="/" /> : <LoginComponent />}
|
||||
/>
|
||||
|
||||
|
||||
{/* Protected routes */}
|
||||
<Route
|
||||
path="/"
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<div className="container mx-auto px-4 py-6">
|
||||
<Home />
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/product/:id"
|
||||
|
||||
<Route
|
||||
path="/product/:id"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<ProductDetail />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/settings"
|
||||
|
||||
<Route
|
||||
path="/settings"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<div className="container mx-auto px-4 py-6">
|
||||
<Settings />
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/selling"
|
||||
|
||||
<Route
|
||||
path="/selling"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<div className="container mx-auto px-4 py-6">
|
||||
<Selling />
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/transactions"
|
||||
|
||||
<Route
|
||||
path="/transactions"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<div className="container mx-auto px-4 py-6">
|
||||
<Transactions />
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/favorites"
|
||||
|
||||
<Route
|
||||
path="/favorites"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<div className="container mx-auto px-4 py-6">
|
||||
<Favorites />
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
{/* Redirect to login for any unmatched routes */}
|
||||
<Route path="*" element={<Navigate to={isAuthenticated ? "/" : "/login"} />} />
|
||||
<Route
|
||||
path="*"
|
||||
element={<Navigate to={isAuthenticated ? "/" : "/login"} />}
|
||||
/>
|
||||
</Routes>
|
||||
</div>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
|
||||
Reference in New Issue
Block a user