73 lines
2.5 KiB
TypeScript
Executable File
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>
|
|
);
|
|
}
|