diff --git a/public/locales/en.json b/public/locales/en.json index 17be5ff..a8cee1e 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -187,6 +187,24 @@ "errorWalletLimitDescription": "You currently cannot add any more wallets." }, + "dashboard": { + "siteTitle": "Dashboard", + + "walletOverviewCardTitle": "Wallets", + "walletOverviewTotalBalance": "Total balance", + "walletOverviewNames": "Names", + "walletOverviewNamesCount": "{{count}} name", + "walletOverviewNamesCount_plural": "{{count}} names", + "walletOverviewSeeMore": "See all {{count}}...", + "walletOverviewAddWallets": "Add wallets...", + + "transactionsCardTitle": "Transactions", + + "blockValueCardTitle": "Block Value", + + "blockDifficultyCardTitle": "Block Difficulty" + }, + "credits": { "title": "Credits", "madeBy": "Made by <1>{{authorName}}", diff --git a/src/layout/AppLayout.less b/src/layout/AppLayout.less index 5e60b05..485ae1d 100644 --- a/src/layout/AppLayout.less +++ b/src/layout/AppLayout.less @@ -56,6 +56,7 @@ .ant-tag { margin-left: 0.5em; + margin-right: 0; } } diff --git a/src/layout/AppRouter.tsx b/src/layout/AppRouter.tsx index 742bc96..84701c5 100644 --- a/src/layout/AppRouter.tsx +++ b/src/layout/AppRouter.tsx @@ -1,7 +1,7 @@ import React from "react"; import { Switch, Route } from "react-router-dom"; -import { DashboardPage } from "../pages/DashboardPage"; +import { DashboardPage } from "../pages/dashboard/DashboardPage"; import { WalletsPage } from "../pages/wallets/WalletsPage"; import { SettingsPage } from "../pages/settings/SettingsPage"; diff --git a/src/pages/DashboardPage.tsx b/src/pages/DashboardPage.tsx deleted file mode 100644 index c6dfa7e..0000000 --- a/src/pages/DashboardPage.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from "react"; -import { Button, message } from "antd"; - -import { useDispatch, useSelector, shallowEqual } from "react-redux"; -import { RootState } from "../store"; - -import { syncWallets } from "../krist/wallets/Wallet"; - -import { PageLayout } from "../layout/PageLayout"; -import { AuthorisedAction } from "../components/auth/AuthorisedAction"; - -export function DashboardPage(): JSX.Element { - const { isAuthed, hasMasterPassword } - = useSelector((s: RootState) => s.walletManager, shallowEqual); - const { wallets } = useSelector((s: RootState) => s.wallets, shallowEqual); - const dispatch = useDispatch(); - - return {/* TODO */} -

Is authed: {isAuthed ? "yes" : "no"}

-

Has master password: {hasMasterPassword ? "yes" : "no"}

- - - -

- - - -

- - message.success("Something authed happened!")}> - - -
; -} diff --git a/src/pages/dashboard/BlockDifficultyCard.tsx b/src/pages/dashboard/BlockDifficultyCard.tsx new file mode 100644 index 0000000..552ac73 --- /dev/null +++ b/src/pages/dashboard/BlockDifficultyCard.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Card } from "antd"; + +import { useTranslation } from "react-i18next"; + +export function BlockDifficultyCard(): JSX.Element { + const { t } = useTranslation(); + + return + + ; +} diff --git a/src/pages/dashboard/BlockValueCard.tsx b/src/pages/dashboard/BlockValueCard.tsx new file mode 100644 index 0000000..1556906 --- /dev/null +++ b/src/pages/dashboard/BlockValueCard.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Card } from "antd"; + +import { useTranslation } from "react-i18next"; + +export function BlockValueCard(): JSX.Element { + const { t } = useTranslation(); + + return + + ; +} diff --git a/src/pages/dashboard/DashboardPage.less b/src/pages/dashboard/DashboardPage.less new file mode 100644 index 0000000..d88e5dd --- /dev/null +++ b/src/pages/dashboard/DashboardPage.less @@ -0,0 +1,119 @@ +@import (reference) "../../App.less"; + +.dashboard-page { + .dashboard-main-row { + margin-bottom: @margin-md; + align-items: stretch; + + & > .ant-col > .ant-card { + height: 100%; + + border: none; + border-radius: @kw-big-card-border-radius; + + .ant-card-head { + border-bottom: 0; + margin-bottom: 0; + + border-radius: @kw-big-card-border-radius @kw-big-card-border-radius 0 0; + + .ant-card-head-title { + padding-bottom: 0; + } + } + + .ant-card-body { + padding-top: @padding-sm; + } + } + } + + .dashboard-statistic { + &-title { + color: @kw-text-secondary; + display: block; + } + + &-value { + font-size: @heading-3-size; + } + } + + .dashboard-card-wallets { + .dashboard-wallets-top-row { + margin-bottom: @margin-sm; + } + + .dashboard-wallets-balance { + .krist-value { + color: @kw-green; + + .anticon svg, .krist-currency-long { + color: fade(@kw-green, 75%); + } + + &.empty { + color: @text-color; + + .anticon svg, .krist-currency-long { + color: fade(@text-color, 75%); + } + } + } + } + + .dashboard-wallet-preview { + padding: @padding-sm @padding-md; + margin-bottom: @margin-xs; + + background: @kw-dark; + border-radius: @kw-big-card-border-radius; + + height: 60px; + justify-content: center; + + line-height: 1.5; + + .wallet-left { + flex: 1; + height: 100%; + + display: flex; + flex-direction: column; + justify-content: center; + + .wallet-label { + font-weight: bold; + } + } + + .wallet-right { + flex: 0; + font-size: @font-size-lg; + + display: flex; + justify-content: center; + align-items: center; + } + + &:last-child { + margin-bottom: 0; + } + } + } + + .dashboard-more a { + display: block; + width: 100%; + + margin-bottom: -@padding-sm; + + color: @text-color-secondary; + font-size: 90%; + text-align: center; + + &:hover { + color: lighten(@text-color-secondary, 10%); + } + } +} diff --git a/src/pages/dashboard/DashboardPage.tsx b/src/pages/dashboard/DashboardPage.tsx new file mode 100644 index 0000000..6a3f9e9 --- /dev/null +++ b/src/pages/dashboard/DashboardPage.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { Row, Col } from "antd"; + +import { PageLayout } from "../../layout/PageLayout"; + +import { WalletOverviewCard } from "./WalletOverviewCard"; +import { TransactionsCard } from "./TransactionsCard"; +import { BlockValueCard } from "./BlockValueCard"; +import { BlockDifficultyCard } from "./BlockDifficultyCard"; + +import "./DashboardPage.less"; + +export function DashboardPage(): JSX.Element { + return + + + + + + + + + + ; +} diff --git a/src/pages/dashboard/Statistic.tsx b/src/pages/dashboard/Statistic.tsx new file mode 100644 index 0000000..5a89ee3 --- /dev/null +++ b/src/pages/dashboard/Statistic.tsx @@ -0,0 +1,18 @@ +import React from "react"; + +import { useTranslation } from "react-i18next"; + +interface Props { + title?: string; + titleKey?: string; + value?: React.ReactNode; +} + +export function Statistic({ title, titleKey, value }: Props): JSX.Element { + const { t } = useTranslation(); + + return
+ {titleKey ? t(titleKey) : title} + {value} +
; +} diff --git a/src/pages/dashboard/TransactionsCard.tsx b/src/pages/dashboard/TransactionsCard.tsx new file mode 100644 index 0000000..879a9ef --- /dev/null +++ b/src/pages/dashboard/TransactionsCard.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Card } from "antd"; + +import { useTranslation } from "react-i18next"; + +export function TransactionsCard(): JSX.Element { + const { t } = useTranslation(); + + return + + ; +} diff --git a/src/pages/dashboard/WalletOverviewCard.tsx b/src/pages/dashboard/WalletOverviewCard.tsx new file mode 100644 index 0000000..2a9b173 --- /dev/null +++ b/src/pages/dashboard/WalletOverviewCard.tsx @@ -0,0 +1,73 @@ +import React from "react"; +import { Card, Row, Col, Typography } from "antd"; + +import { useSelector, shallowEqual } from "react-redux"; +import { RootState } from "../../store"; +import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; + +import { Wallet } from "../../krist/wallets/Wallet"; + +import { KristValue } from "../../components/KristValue"; +import { Statistic } from "./Statistic"; + +import { keyedNullSort } from "../../utils"; + +export function WalletPreview({ wallet }: { wallet: Wallet }): JSX.Element { + return + + {wallet.label && {wallet.label}} + {wallet.address} + + + + + + ; +} + +export function WalletOverviewCard(): JSX.Element { + const { wallets } = useSelector((s: RootState) => s.wallets, shallowEqual); + const { t } = useTranslation(); + + const clonedWallets = [...Object.values(wallets)]; + + const balance = clonedWallets.filter(w => w.balance !== undefined) + .reduce((acc, w) => acc + w.balance!, 0); + const names = clonedWallets.filter(w => w.names !== undefined) + .reduce((acc, w) => acc + w.names!, 0); + + const topWallets = [...clonedWallets]; + const sort = keyedNullSort("balance", undefined); + topWallets.sort((a: Wallet, b: Wallet) => sort(a, b, "descend")); + topWallets.reverse(); + const top4Wallets = topWallets.slice(0, 4); + + return + + + 0 ? "" : "empty"} />} + /> + + + + + + + + {top4Wallets.map(w => )} + + + + {clonedWallets.length > 0 + ? t("dashboard.walletOverviewSeeMore", { count: clonedWallets.length }) + : t("dashboard.walletOverviewAddWallets")} + + + ; +} diff --git a/src/style/theme.less b/src/style/theme.less index 559961c..b24677b 100644 --- a/src/style/theme.less +++ b/src/style/theme.less @@ -94,6 +94,9 @@ } @table-header-icon-color: @text-color-secondary; +@card-background: mix(@kw-dark, @kw-slighter, 75%); +@kw-big-card-border-radius: 4px; + // general theme // --- @kw-sidebar-bg: @kw-darker;