Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor historical data detail page #134

Merged
merged 1 commit into from
Oct 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/components/common/modal/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@
background-color: #fff;
border-radius: 5px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
left: 50%;
max-height: 90%;
/* min-width: 700px; */
max-width: 90%;
overflow: auto;
padding: 20px;
position: fixed;

/* transform makes text blurry, so deprecated it */
/* left: 50%;
top: 50%;
transform: translate(-50%, -50%);
transform: translate(-50%, -50%); */
z-index: 999;
}

Expand Down
30 changes: 30 additions & 0 deletions src/components/common/modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";

import "./index.css";
import { useWindowSize } from "../../../utils/hook";

const App = (props: {
visible: boolean;
Expand All @@ -9,6 +10,33 @@ const App = (props: {
}) => {
const [isModalOpen, setIsModalOpen] = useState(props.visible);

const [offsetTop, setOffsetTop] = useState(0);
const [offsetLeft, setOffsetLeft] = useState(0);

const usize = useWindowSize();

useEffect(() => setTopAndLeft(usize), [usize]);
useEffect(() => setTopAndLeft(usize), [isModalOpen]);

function setTopAndLeft(winSize: { width?: number; height?: number }) {
const width = winSize.width ?? 800;
const height = winSize.height ?? 800;

// get modal by className

const modal = document.querySelector(".modal");
if (modal) {
const modalWidth = modal.clientWidth;
const modalHeight = modal.clientHeight;

const top = (height - modalHeight) / 2;
const left = (width - modalWidth) / 2;

setOffsetTop(top);
setOffsetLeft(left);
}
}

useEffect(() => {
setIsModalOpen(props.visible);
}, [props.visible]);
Expand All @@ -35,6 +63,8 @@ const App = (props: {
onClick={(e) => e.stopPropagation()}
style={{
backgroundColor: "#f5f5f5",
top: offsetTop,
left: offsetLeft,
}}
>
{props.children}
Expand Down
7 changes: 7 additions & 0 deletions src/components/historical-data/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,10 @@
right: 0;
color: gray;
}

.historical-data-detail-row {
display: inline-block;
height: 40px;
font-size: 17px;
line-height: 40px;
}
113 changes: 97 additions & 16 deletions src/components/historical-data/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import { timestampToDate } from "../../utils/date";
import {
currencyWrapper,
prettyNumberToLocaleString,
prettyPriceNumberToLocaleString,
} from "../../utils/currency";
import Modal from "../common/modal";
import { downloadCoinLogos } from "../../middlelayers/data";
import { appCacheDir as getAppCacheDir } from "@tauri-apps/api/path";
import { convertFileSrc } from "@tauri-apps/api/tauri";
import { useWindowSize } from "../../utils/hook";

type RankData = {
id: number;
Expand All @@ -42,6 +44,8 @@ const App = ({
const [isModalOpen, setIsModalOpen] = useState(false);
const [appCacheDir, setAppCacheDir] = useState("");

const wsize = useWindowSize();

const [pageNum, setPageNum] = useState(1);
const pageSize = 10;

Expand Down Expand Up @@ -266,18 +270,51 @@ const App = ({
const filePath = `${appCacheDir}assets/coins/${d.symbol.toLowerCase()}.png`;
const apiPath = convertFileSrc(filePath);
return (
<div key={d.id}>
<img
src={apiPath}
alt={d.symbol}
style={{ width: 20, height: 20 }}
/>
<div>{d.rank}</div>
<div>{d.symbol}</div>
<div>{d.amount}</div>
<div>{d.value}</div>
<div>{d.price}</div>
</div>
<tr key={d.id}>
<td>
<p className="historical-data-detail-row">{d.rank}</p>
</td>
<td
style={{
textAlign: "start",
}}
>
<img
src={apiPath}
alt={d.symbol}
style={{ width: 20, height: 20, marginRight: 5 }}
/>
<p className="historical-data-detail-row">{d.symbol}</p>
</td>
<td
style={{
textAlign: "end",
}}
>
<p className="historical-data-detail-row">
{currency.symbol + prettyPriceNumberToLocaleString(currencyWrapper(currency)(d.price))}
</p>
</td>
<td
style={{
textAlign: "end",
}}
>
<p className="historical-data-detail-row">{d.amount}</p>
</td>
<td
style={{
textAlign: "end",
}}
>
<p className="historical-data-detail-row">
{currency.symbol +
prettyNumberToLocaleString(
currencyWrapper(currency)(d.value)
)}
</p>
</td>
</tr>
);
})
.value();
Expand All @@ -297,12 +334,56 @@ const App = ({
id="detail-view"
style={{
display: rankData.length > 0 ? "inline-block" : "none",
marginRight: 10,
verticalAlign: "top",
width: (wsize.width ?? 800) * 0.7,
}}
>
{/* <Table data={rankData} columns={rankColumns} /> */}
{detailPage(rankData)}
<table>
<thead>
<tr>
<th
style={{
width: 50,
}}
>
#
</th>
<th
style={{
width: '30%',
minWidth: 180,
textAlign: "start",
}}
>
Name
</th>
<th
style={{
width: '20%',
textAlign: "end",
}}
>
Price
</th>
<th
style={{
width: '25%',
textAlign: "end",
}}
>
Amount
</th>
<th
style={{
width: '20%',
textAlign: "end",
}}
>
Value
</th>
</tr>
</thead>
<tbody>{detailPage(rankData)}</tbody>
</table>
</div>
</Modal>
<div
Expand Down
34 changes: 34 additions & 0 deletions src/utils/currency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,37 @@ export function prettyNumberToLocaleString(value: number) {
maximumFractionDigits: 2,
})
}

// pretty to show price, if price >= 1, keep 3 digits after decimal point
export function prettyPriceNumberToLocaleString(value: number) {
if (value >= 1) {
return prettyNumberToLocaleString(value)
}

// find last 0, and keep 3 digits after last 0
const str = safeNumberToString(value)
// +2 because of "0." at begin
let last0 = 2
for (let i = 0; i < str.length; i++) {
if (str[i] === ".") {
continue
}
if (str[i] !== "0") {
last0 = i
break
}
}
return str.substring(0, last0 + 4)
}

// safe transfer number to string without scientific notation
function safeNumberToString(inputNumber: number) {
const inum = parseFloat('' + inputNumber)
let eformat = inum.toExponential()
const tmpArray = eformat.match(/\d(?:\.(\d*))?e([+-]\d+)/)
if (!tmpArray) {
return inputNumber + ''
}
let number = inputNumber.toFixed(Math.max(0, (tmpArray[1] || '').length - parseInt(tmpArray[2])))
return number
}
Loading