Files
redefined-designs/frontend/src/App.tsx
T
bermudalamb 9ab689e624
SonarQube Analysis / sonarqube (pull_request) Failing after 59s
Tests / backend-unit (pull_request) Successful in 34s
Tests / backend-integration (pull_request) Failing after 1m33s
Tests / frontend-e2e (pull_request) Failing after 1m5s
feat: add customer cart with expiry, shipping addresses with USPS validation, and multi-item PayPal checkout
2026-08-14 14:02:25 -05:00

73 lines
2.5 KiB
TypeScript
Executable File

import { useEffect, useState, useCallback } from 'react';
import { Layout, Typography, Switch, Row, Col, Spin, Button, theme, Badge } from 'antd';
import { ShoppingCartOutlined } from '@ant-design/icons';
import { Link } from 'react-router-dom';
import { Item, fetchItems } from './api';
import ItemCard from './components/ItemCard';
import { useThemeMode } from './theme/ThemeContext';
import { useCustomerAuth } from './customer/CustomerAuthContext';
import { useCart } from './cart/CartContext';
const { Header, Content, Footer } = Layout;
const { Title } = Typography;
export default function App() {
const [items, setItems] = useState<Item[]>([]);
const { mode, toggle } = useThemeMode();
const { customer } = useCustomerAuth();
const { items: cartItems } = useCart();
const { token } = theme.useToken();
const load = useCallback(() => {
fetchItems().then(setItems);
}, []);
useEffect(() => { load(); }, [load]);
return (
<Layout style={{ minHeight: '100vh' }}>
<Header
className="site-header"
style={{
background: token.colorBgContainer,
borderBottom: `1px solid ${token.colorBorderSecondary}`
}}
>
<Title level={3} className="site-header-title" style={{ color: token.colorText }}>
Redefined Designs
</Title>
<div className="site-header-actions">
<Switch checked={mode === 'dark'} onChange={toggle} checkedChildren="Dark" unCheckedChildren="Light" />
<Link to="/cart">
<Badge count={cartItems.length} size="small">
<Button icon={<ShoppingCartOutlined />} />
</Badge>
</Link>
{customer ? (
<Link to="/account"><Button>My Account</Button></Link>
) : (
<>
<Link to="/login"><Button>Log in</Button></Link>
<Link to="/register"><Button type="primary">Sign up</Button></Link>
</>
)}
</div>
</Header>
<Content style={{ padding: 24 }}>
{!items.length ? <Spin /> : (
<Row gutter={[20, 20]}>
{items.map(item => (
<Col key={item.id} xs={24} sm={12} md={8} lg={6}>
<ItemCard item={item} onChanged={load} />
</Col>
))}
</Row>
)}
</Content>
<Footer style={{ textAlign: 'center', background: token.colorBgContainer }}>
<Link to="/privacy">Privacy Policy</Link>
</Footer>
</Layout>
);
}