Compare commits
No commits in common. "heiclone-main" and "master" have entirely different histories.
heiclone-m
...
master
|
|
@ -1 +0,0 @@
|
||||||
[{"name":"Maitotuotteet","subgroups":["Lehmänmaito","Vuohenmaito","Cheddar","Mozzarella"]},{"name":"Kukat","subgroups":["Leikkokukat","Rairuohot","Vehnä"]},{"name":"Lihatuotteet","subgroups":["Kana","Lammas","Possu","Kebabeläin"]}]
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"webpack-dev-server": "^3.10.3"
|
"webpack-dev-server": "^3.10.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"antd": "^4.10.1",
|
"antd": "^4.1.3",
|
||||||
"mobx": "^5.15.4",
|
"mobx": "^5.15.4",
|
||||||
"mobx-react": "^6.2.2",
|
"mobx-react": "^6.2.2",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
|
|
|
||||||
160
src/index.tsx
|
|
@ -1,160 +1,38 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as ReactDOM from 'react-dom';
|
import * as ReactDOM from 'react-dom';
|
||||||
import { observable, action, configure } from 'mobx';
|
import {observable} from 'mobx';
|
||||||
import { observer } from 'mobx-react';
|
import {observer} from 'mobx-react';
|
||||||
|
|
||||||
import "antd/es/layout/style";
|
|
||||||
import Layout from "antd/es/layout";
|
|
||||||
|
|
||||||
import "antd/es/menu/style";
|
|
||||||
import Menu from "antd/es/menu";
|
|
||||||
|
|
||||||
import "antd/es/card/style";
|
|
||||||
import Card from "antd/es/card";
|
|
||||||
|
|
||||||
import "antd/es/grid/style";
|
|
||||||
import { Row, Col } from "antd/es/grid";
|
|
||||||
|
|
||||||
import "antd/es/input/style";
|
|
||||||
import Input from "antd/es/input";
|
|
||||||
|
|
||||||
import { ShoppingCartOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
import * as productGroups from "../data/productGroups.json";
|
|
||||||
|
|
||||||
|
|
||||||
configure({ enforceActions: 'always' });
|
|
||||||
|
|
||||||
|
|
||||||
interface ProductGroup {
|
|
||||||
name: String,
|
|
||||||
subgroups: String[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const PRODUCTGROUPS: ProductGroup[] = productGroups; // from GET productgroups
|
|
||||||
|
|
||||||
class AppState {
|
class AppState {
|
||||||
@observable productCardsOnDisplay: Array<ProductCard>;
|
@observable timer = 0;
|
||||||
|
|
||||||
@action
|
|
||||||
setProductCardsOnDisplay(cards: Array<ProductCard>) {
|
|
||||||
this.productCardsOnDisplay = cards;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchProductCards() {
|
|
||||||
try {
|
|
||||||
const res = await fetch("http://localhost:8000/productCards");
|
|
||||||
const cards = await res.json();
|
|
||||||
this.setProductCardsOnDisplay(cards)
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.setProductCardsOnDisplay([]);
|
setInterval(() => {
|
||||||
this.fetchProductCards();
|
this.timer += 1;
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
interface ProductCard {
|
resetTimer() {
|
||||||
name: string,
|
this.timer = 0;
|
||||||
thumbnail: string,
|
}
|
||||||
display_price: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class MainView extends React.Component<{ appState: AppState }, {}> {
|
class TimerView extends React.Component<{appState: AppState}, {}> {
|
||||||
productRows(products: ProductCard[]) {
|
|
||||||
const cardWidth = 180;
|
|
||||||
let ret: Array<JSX.Element> = [];
|
|
||||||
|
|
||||||
// TODO: there's probably thousand better ways than the initial copy paste rinse and repeat model below to form some rows .. PRs are welcomed
|
|
||||||
|
|
||||||
for (let index = 0; index < products.length; index += 4) {
|
|
||||||
let cols: Array<JSX.Element> = [
|
|
||||||
<Col offset={1}>
|
|
||||||
<Card hoverable style={{ width: cardWidth }} cover={<img alt="example" src={products[index].thumbnail} />}>
|
|
||||||
<Card.Meta title={products[index].name} description={products[index].display_price} />
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
];
|
|
||||||
if (index + 1 < products.length) {
|
|
||||||
cols.push(
|
|
||||||
<Col >
|
|
||||||
<Card hoverable style={{ width: cardWidth }} cover={<img alt="example" src={products[index + 1].thumbnail} />}>
|
|
||||||
<Card.Meta title={products[index + 1].name} description={products[index + 1].display_price} />
|
|
||||||
</Card>
|
|
||||||
</Col>);
|
|
||||||
}
|
|
||||||
if (index + 2 < products.length) {
|
|
||||||
cols.push(
|
|
||||||
<Col>
|
|
||||||
<Card hoverable style={{ width: cardWidth }} cover={<img alt="example" src={products[index + 2].thumbnail} />}>
|
|
||||||
<Card.Meta title={products[index + 2].name} description={products[index + 2].display_price} />
|
|
||||||
</Card>
|
|
||||||
</Col>);
|
|
||||||
}
|
|
||||||
if (index + 3 < products.length) {
|
|
||||||
cols.push(
|
|
||||||
<Col>
|
|
||||||
<Card hoverable style={{ width: cardWidth }} cover={<img alt="example" src={products[index + 3].thumbnail} />}>
|
|
||||||
<Card.Meta title={products[index + 3].name} description={products[index + 3].display_price} />
|
|
||||||
</Card>
|
|
||||||
</Col>);
|
|
||||||
}
|
|
||||||
ret.push(
|
|
||||||
<Row justify="start" gutter={[{ xs: 8, sm: 16, md: 24, lg: 32 }, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
|
||||||
{cols}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<div>
|
||||||
<Layout.Header style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
<button onClick={this.onReset}>
|
||||||
|
Seconds passed: {this.props.appState.timer}
|
||||||
<img src="/static/logo.png" alt="logo" style={{ height: "inherit" }}></img>
|
</button>
|
||||||
|
</div>
|
||||||
<Menu mode="horizontal" theme="dark">
|
|
||||||
{PRODUCTGROUPS.map((group, groupindex) =>
|
|
||||||
<Menu.SubMenu key={groupindex} title={group.name}>
|
|
||||||
{group.subgroups.map((subgroup, subgroupindex) =>
|
|
||||||
<Menu.Item key={subgroupindex}>{subgroup}</Menu.Item>
|
|
||||||
)}
|
|
||||||
</Menu.SubMenu>
|
|
||||||
)}
|
|
||||||
<Menu.SubMenu title="Muuta tietoa">
|
|
||||||
<Menu.Item>Yhteystiedot</Menu.Item>
|
|
||||||
<Menu.Item>Aukioloajat</Menu.Item>
|
|
||||||
</Menu.SubMenu>
|
|
||||||
</Menu>
|
|
||||||
<Input.Search style={{ maxWidth: "20rem" }} />
|
|
||||||
</Layout.Header>
|
|
||||||
<Layout>
|
|
||||||
<Layout.Content>
|
|
||||||
{this.productRows(this.props.appState.productCardsOnDisplay)}
|
|
||||||
</Layout.Content>
|
|
||||||
|
|
||||||
<Layout.Sider theme="light">
|
|
||||||
<ShoppingCartOutlined style={{ fontSize: "6rem", width: "100%" }} />
|
|
||||||
</Layout.Sider>
|
|
||||||
</Layout>
|
|
||||||
<Layout.Footer>
|
|
||||||
<h4>Foobar</h4>
|
|
||||||
</Layout.Footer>
|
|
||||||
</Layout>
|
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onReset = () => {
|
||||||
|
this.props.appState.resetTimer();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const appState = new AppState();
|
const appState = new AppState();
|
||||||
|
ReactDOM.render(<TimerView appState={appState} />, document.getElementById('root'));
|
||||||
ReactDOM.render(<MainView appState={appState} />, document.getElementById('root'));
|
|
||||||
|
|
|
||||||
BIN
static/logo.png
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 6.6 MiB |
|
Before Width: | Height: | Size: 6.6 MiB |
|
Before Width: | Height: | Size: 6.5 MiB |
|
Before Width: | Height: | Size: 7.4 MiB |
|
Before Width: | Height: | Size: 6.6 MiB |
|
Before Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 14 KiB |