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 LoginPage from './LoginPage';
|
||||||
import ProductList from './ProductList';
|
import ProductList from './ProductList';
|
||||||
import ProductDetail from './ProductDetail';
|
import ProductDetail from './ProductDetail';
|
||||||
|
import CartPage from './CartPage';
|
||||||
import { CartProvider } from './CartContext';
|
import { CartProvider } from './CartContext';
|
||||||
|
import { AuthProvider } from './AuthContext';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<CartProvider>
|
<AuthProvider>
|
||||||
<Header />
|
<CartProvider>
|
||||||
<main>
|
<Header />
|
||||||
<Routes>
|
<main>
|
||||||
<Route path="/" element={<ProductList />} />
|
<Routes>
|
||||||
<Route path="/product/:id" element={<ProductDetail />} />
|
<Route path="/" element={<ProductList />} />
|
||||||
<Route path="/login" element={<LoginPage />} />
|
<Route path="/product/:id" element={<ProductDetail />} />
|
||||||
</Routes>
|
<Route path="/cart" element={<CartPage />} />
|
||||||
</main>
|
<Route path="/login" element={<LoginPage />} />
|
||||||
</CartProvider>
|
</Routes>
|
||||||
|
</main>
|
||||||
|
</CartProvider>
|
||||||
|
</AuthProvider>
|
||||||
</Router>
|
</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() {
|
export default function Header() {
|
||||||
|
const { isAuthenticated, logout } = useAuth();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="bg-white shadow-sm p-4 flex justify-between items-center">
|
<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>
|
<nav>
|
||||||
<button className="text-gray-600 hover:text-gray-900 mx-2">Products</button>
|
<Link to="/" className="text-gray-600 hover:text-gray-900 mx-2">Products</Link>
|
||||||
<button className="text-blue-500 hover:text-blue-700 mx-2">Login</button>
|
<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>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,13 +1,22 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { useAuth } from './AuthContext';
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
|
const { login } = useAuth();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log('Login attempt:', { username, password });
|
// Simulate login
|
||||||
// TODO: Implement actual JWT authentication logic here
|
if (username === 'admin' && password === 'password') {
|
||||||
|
login();
|
||||||
|
navigate('/');
|
||||||
|
} else {
|
||||||
|
alert('Invalid credentials');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -45,4 +54,4 @@ export default function LoginPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user