-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathApp.tsx
More file actions
132 lines (125 loc) · 5.32 KB
/
App.tsx
File metadata and controls
132 lines (125 loc) · 5.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route, Navigate, Link } from "react-router-dom";
import { CartProvider, useCart } from "./contexts/CartContext";
import { UserProvider, useUser } from "./contexts/UserContext";
import Navbar from "./components/Navbar";
import Home from "./pages/Home";
import Products from "./pages/Products";
import LoginForm from "./components/LoginForm";
import NotFound from "./pages/NotFound";
import Scenarios from "./pages/Scenarios";
import Profile from "./pages/Profile";
import Checkout from "./pages/Checkout";
import OrderHistory from "./pages/OrderHistory";
import React from 'react';
const queryClient = new QueryClient();
const AppContent = () => {
return (
<div className="min-h-screen bg-background">
<Navbar />
<main>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products" element={<Products />} />
<Route path="/scenarios" element={<Scenarios />} />
<Route path="/login" element={
<RedirectIfLoggedIn>
<LoginForm />
</RedirectIfLoggedIn>
} />
<Route path="/cart" element={<ShoppingCartPage />} />
<Route path="/checkout" element={
<RequireAuth>
<Checkout />
</RequireAuth>
} />
<Route path="/profile" element={
<RequireAuth>
<Profile />
</RequireAuth>
} />
<Route path="/orders" element={
<RequireAuth>
<OrderHistory />
</RequireAuth>
} />
<Route path="*" element={<NotFound />} />
</Routes>
</main>
<footer className="w-full text-center py-4 text-gray-500 text-sm border-t bg-white mt-8">
© 2025 BrowserStack. All rights reserved.
</footer>
</div>
);
};
export const RequireAuth = ({ children }: { children: React.ReactNode }) => {
const { user } = useUser();
return user ? <>{children}</> : <Navigate to="/login" replace />;
};
export const RedirectIfLoggedIn = ({ children }: { children: React.ReactNode }) => {
const { user } = useUser();
return user ? <Navigate to="/profile" replace /> : <>{children}</>;
};
const ShoppingCartPage = () => {
const { cart, removeFromCart, clearCart, addToCart, decrementFromCart } = useCart();
const { user } = useUser();
return (
<div className="min-h-screen flex flex-col items-center justify-center py-8">
<h1 className="text-2xl font-bold mb-4">Shopping Cart</h1>
{cart.items.length === 0 ? (
<p className="text-gray-500">Your cart is empty.</p>
) : (
<div className="w-full max-w-3xl space-y-4 p-3">
{cart.items.map(item => (
<div key={item.id} id='cart-item' className="flex flex-col md:flex-row items-center justify-between bg-white rounded-lg shadow p-4 gap-4">
<div className="flex items-center gap-4 w-full md:w-2/3">
<img src={item.image} alt={item.name} className="w-24 h-24 object-cover rounded" />
<div className="flex-1">
<div className="font-semibold text-lg">{item.name}</div>
{item.category && (
<span className="inline-block bg-blue-100 text-blue-700 text-xs font-semibold px-2 py-1 rounded-full mb-1">{item.category}</span>
)}
{item.rating && (
<div className="text-xs text-gray-500">Rating: {item.rating.rate} ({item.rating.count} reviews)</div>
)}
<div className="text-blue-600 font-bold text-lg">${item.price} x {item.quantity}</div>
<div className="flex items-center gap-2 mt-2">
<button className="px-2 py-1 bg-gray-200 rounded" onClick={() => decrementFromCart(item.id)}>-</button>
<span className="px-2" id="item-quantity">{item.quantity}</span>
<button className="px-2 py-1 bg-gray-200 rounded" onClick={() => addToCart(item, 1)}>+</button>
</div>
</div>
</div>
<button className="text-red-500 hover:underline self-start" onClick={() => removeFromCart(item.id)}>Remove</button>
</div>
))}
<button id="clear-cart-btn" className="mt-4 px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600" onClick={clearCart}>Clear Cart</button>
{user ? (
<>
<Link to="/checkout" id="checkout-btn" className="mt-6 px-6 py-3 bg-green-600 text-white rounded hover:bg-green-700 w-full text-lg font-bold text-center block">Checkout</Link>
</>
) : (
<div className="mt-6 px-6 py-3 bg-yellow-100 text-yellow-800 rounded w-full text-center text-lg font-semibold">
Please <Link to="/profile" className="underline text-blue-600">login</Link> to checkout.
</div>
)}
</div>
)}
</div>
);
};
const App = () => (
<UserProvider>
<CartProvider>
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<BrowserRouter basename={import.meta.env.BASE_URL}>
<AppContent />
</BrowserRouter>
</TooltipProvider>
</QueryClientProvider>
</CartProvider>
</UserProvider>
);
export default App;