Auto commit: 2026-03-13T01:53:04.187Z
This commit is contained in:
parent
3a45bf3328
commit
1fae2204d0
@ -3,21 +3,26 @@ import Header from './Header';
|
||||
import LoginPage from './LoginPage';
|
||||
import ProductList from './ProductList';
|
||||
import ProductDetail from './ProductDetail';
|
||||
import CartPage from './CartPage';
|
||||
import { CartProvider } from './CartContext';
|
||||
import { AuthProvider } from './AuthContext';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Router>
|
||||
<CartProvider>
|
||||
<Header />
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path="/" element={<ProductList />} />
|
||||
<Route path="/product/:id" element={<ProductDetail />} />
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
</Routes>
|
||||
</main>
|
||||
</CartProvider>
|
||||
<AuthProvider>
|
||||
<CartProvider>
|
||||
<Header />
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path="/" element={<ProductList />} />
|
||||
<Route path="/product/:id" element={<ProductDetail />} />
|
||||
<Route path="/cart" element={<CartPage />} />
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
</Routes>
|
||||
</main>
|
||||
</CartProvider>
|
||||
</AuthProvider>
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
|
||||
28
frontend/src/AuthContext.tsx
Normal file
28
frontend/src/AuthContext.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
||||
|
||||
interface AuthContextType {
|
||||
isAuthenticated: boolean;
|
||||
login: () => void;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||
|
||||
export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
|
||||
const login = () => setIsAuthenticated(true);
|
||||
const logout = () => setIsAuthenticated(false);
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) throw new Error('useAuth must be used within AuthProvider');
|
||||
return context;
|
||||
};
|
||||
33
frontend/src/CartPage.tsx
Normal file
33
frontend/src/CartPage.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { useCart } from './CartContext';
|
||||
|
||||
const CartPage: React.FC = () => {
|
||||
const { cart } = useCart();
|
||||
|
||||
const total = cart.reduce((sum, item) => sum + item.price, 0);
|
||||
|
||||
return (
|
||||
<div className="container mx-auto p-4">
|
||||
<h1 className="text-2xl font-bold mb-4">Your Shopping Cart</h1>
|
||||
{cart.length === 0 ? (
|
||||
<p>Your cart is empty.</p>
|
||||
) : (
|
||||
<div>
|
||||
<ul className="divide-y divide-gray-200">
|
||||
{cart.map((item, index) => (
|
||||
<li key={index} className="py-2 flex justify-between">
|
||||
<span>{item.name}</span>
|
||||
<span>${item.price.toFixed(2)}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="mt-4 pt-2 border-t border-gray-200 text-xl font-bold">
|
||||
Total: ${total.toFixed(2)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CartPage;
|
||||
@ -1,10 +1,22 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useAuth } from './AuthContext';
|
||||
|
||||
export default function Header() {
|
||||
const { isAuthenticated, logout } = useAuth();
|
||||
|
||||
return (
|
||||
<header className="bg-white shadow-sm p-4 flex justify-between items-center">
|
||||
<h1 className="text-xl font-bold">MyApp</h1>
|
||||
<h1 className="text-xl font-bold">
|
||||
<Link to="/">MyApp</Link>
|
||||
</h1>
|
||||
<nav>
|
||||
<button className="text-gray-600 hover:text-gray-900 mx-2">Products</button>
|
||||
<button className="text-blue-500 hover:text-blue-700 mx-2">Login</button>
|
||||
<Link to="/" className="text-gray-600 hover:text-gray-900 mx-2">Products</Link>
|
||||
<Link to="/cart" className="text-gray-600 hover:text-gray-900 mx-2">Cart</Link>
|
||||
{isAuthenticated ? (
|
||||
<button onClick={logout} className="text-red-500 hover:text-red-700 mx-2">Logout</button>
|
||||
) : (
|
||||
<Link to="/login" className="text-blue-500 hover:text-blue-700 mx-2">Login</Link>
|
||||
)}
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from './AuthContext';
|
||||
|
||||
export default function LoginPage() {
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const { login } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
console.log('Login attempt:', { username, password });
|
||||
// TODO: Implement actual JWT authentication logic here
|
||||
// Simulate login
|
||||
if (username === 'admin' && password === 'password') {
|
||||
login();
|
||||
navigate('/');
|
||||
} else {
|
||||
alert('Invalid credentials');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@ -45,4 +54,4 @@ export default function LoginPage() {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user