Skip to content

Commit c709d8c

Browse files
basic TeaLevel component implementation
1 parent e9c38ef commit c709d8c

File tree

4 files changed

+98
-2
lines changed

4 files changed

+98
-2
lines changed

ui/src/App.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import './App.css';
3-
import { Container, Form } from 'react-bootstrap';
3+
import { Col, Container, Form, Row } from 'react-bootstrap';
44
import { connect } from 'react-redux';
55

66
import NotificationsArea from './components/NotificationsArea.js';
@@ -11,6 +11,7 @@ import SystemStatusArea from './components/SystemStatusArea.js';
1111
import CurrentOperationInfoArea from './components/CurrentOperationInfoArea.js';
1212
import HoldToPour from './components/HoldToPour.js';
1313
import PowerLevel from './components/PowerLevel.js';
14+
import TeaLevel from './components/TeaLevel.js';
1415

1516
function App({ isConnected }) {
1617
return (
@@ -26,7 +27,14 @@ function App({ isConnected }) {
2627
<PourTimeField />
2728
<CurrentOperationInfoArea />
2829
<SystemControls />
29-
<HoldToPour />
30+
<Row>
31+
<Col>
32+
<HoldToPour />
33+
</Col>
34+
<Col>
35+
<TeaLevel />
36+
</Col>
37+
</Row>
3038
</>
3139
) : null}
3240
</Form>

ui/src/components/TeaLevel.css

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
.tea-glass {
2+
height: 100%;
3+
position: relative;
4+
display: flex;
5+
justify-content: center;
6+
align-items: center;
7+
user-select: none;
8+
}
9+
10+
.tea-container {
11+
position: relative;
12+
height: 100%;
13+
max-width: 100%;
14+
width: fit-content;
15+
display: flex;
16+
}
17+
18+
.cup-image {
19+
max-height: 30vh;
20+
max-width: 100%;
21+
object-fit: contain;
22+
position: relative;
23+
z-index: 1;
24+
cursor: pointer;
25+
}
26+
27+
.tea-level {
28+
position: absolute;
29+
left: 0px;
30+
right: 0px;
31+
height: 3px;
32+
background-color: #76b7b2;
33+
z-index: 2;
34+
}
35+
36+
.est-tea-level {
37+
position: absolute;
38+
left: 0px;
39+
right: 0px;
40+
height: 3px;
41+
border-bottom: 3px dashed red;
42+
z-index: 3;
43+
}

ui/src/components/TeaLevel.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React, { useState } from 'react';
2+
import './TeaLevel.css';
3+
import cup from './cup.jpg';
4+
5+
const bottomLevel = 20; // where the tea starts (0%)
6+
const maxLevel = 80; // where the tea ends (100%)
7+
8+
function toRealLevel(level) {
9+
const H = maxLevel - bottomLevel;
10+
return (level / 100 * H) + bottomLevel;
11+
}
12+
13+
function toPercentage(realLevel) {
14+
const H = maxLevel - bottomLevel;
15+
return (realLevel - bottomLevel) / H * 100;
16+
}
17+
18+
function TeaLevel({ initialLevel=null }) {
19+
const estimatedLevel = 50;
20+
const [currentLevel, setCurrentLevel] = useState(initialLevel || 70);
21+
22+
const handleCupClick = (e) => {
23+
const { top, height } = e.target.getBoundingClientRect();
24+
const clickY = e.clientY;
25+
const clickedPosition = top - clickY + height;
26+
const clickedPercentage = (clickedPosition / height) * 100;
27+
const newLevel = toPercentage(clickedPercentage);
28+
// limit the new level to the range [0, 100]
29+
setCurrentLevel( Math.min(Math.max(newLevel, 0), 100) );
30+
};
31+
32+
return (
33+
<div className="tea-glass">
34+
<div className="tea-container">
35+
<img src={cup} alt="Cup" className="cup-image" draggable="false"
36+
onClick={handleCupClick}
37+
/>
38+
<div className="tea-level" style={{ bottom: `${toRealLevel(currentLevel)}%` }}></div>
39+
<div className="est-tea-level" style={{ bottom: `${toRealLevel(estimatedLevel)}%` }}></div>
40+
</div>
41+
</div>
42+
);
43+
}
44+
45+
export default TeaLevel;

ui/src/components/cup.jpg

191 KB
Loading

0 commit comments

Comments
 (0)