feat: navbar redesign

- rebuilt navbar and navbarlayout
- redesigned walletbalance and sync status widgets
- updated tests for navbar, walletbalance, sync status
- open the Market page after login

---

Reviewed-by: @localredhead
This commit is contained in:
Subir 2022-06-14 00:51:12 +05:30
parent 5ed0efd67e
commit 674b31d0c3
No known key found for this signature in database
GPG Key ID: 2D633D8047FD3FF0
21 changed files with 655 additions and 543 deletions

View File

@ -0,0 +1,10 @@
<svg width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M23.2723 9.41766H21.6216C21.3968 8.57814 21.0618 7.77205 20.6254 7.02036L21.7943 5.85154H21.7944C21.9301 5.71565 22.0066 5.53137 22.0066 5.33927C22.0066 5.14717 21.9301 4.96289 21.7944 4.82699L19.1683 2.20085C19.0324 2.06514 18.8481 1.98873 18.656 1.98873C18.4639 1.98873 18.2796 2.06514 18.1437 2.20085L16.9766 3.37055C16.2249 2.93414 15.4189 2.59926 14.5793 2.37437V0.724569C14.5793 0.532466 14.5029 0.348188 14.367 0.212295C14.2311 0.0764032 14.047 0 13.8547 0H10.1422C9.9499 0 9.76581 0.0764032 9.62992 0.212295C9.49402 0.348188 9.41762 0.532466 9.41762 0.724569V2.37525C8.5781 2.6001 7.77201 2.93503 7.02032 3.37144L5.8515 2.20262V2.20244C5.71561 2.06672 5.53133 1.99032 5.33923 1.99032C5.14712 1.99032 4.96284 2.06672 4.82695 2.20244L2.20081 4.82858C2.0651 4.96447 1.98869 5.14875 1.98869 5.34086C1.98869 5.53296 2.0651 5.71724 2.20081 5.85313L3.36963 7.02195H3.36981C2.93339 7.77364 2.59851 8.57968 2.37362 9.41925H0.724569C0.532466 9.41925 0.348188 9.49565 0.212295 9.63155C0.0764033 9.76726 0 9.95154 0 10.1438V13.8565V13.8564C0 14.0486 0.0764033 14.2327 0.212295 14.3686C0.348188 14.5045 0.532466 14.5809 0.724569 14.5809H2.37525C2.6001 15.4205 2.93503 16.2265 3.37144 16.9782L2.20262 18.1471H2.20244C2.06673 18.2829 1.99032 18.4672 1.99032 18.6593C1.99032 18.8514 2.06673 19.0357 2.20244 19.1716L4.82858 21.7977C4.96447 21.9335 5.14875 22.0099 5.34086 22.0099C5.53296 22.0099 5.71724 21.9335 5.85313 21.7977L7.02195 20.6289V20.6287C7.77364 21.0652 8.57968 21.4 9.41925 21.6249V23.2756C9.41925 23.4677 9.49565 23.652 9.63155 23.7879C9.76726 23.9238 9.95154 24 10.1438 24H13.8565H13.8564C14.0486 24 14.2327 23.9238 14.3686 23.7879C14.5045 23.652 14.5809 23.4677 14.5809 23.2756V21.6249C15.4205 21.4001 16.2265 21.0652 16.9782 20.6287L18.1471 21.7976V21.7977C18.2829 21.9335 18.4672 22.0099 18.6593 22.0099C18.8514 22.0099 19.0357 21.9335 19.1716 21.7977L21.7977 19.1716C21.9335 19.0357 22.0099 18.8514 22.0099 18.6593C22.0099 18.4672 21.9335 18.2829 21.7977 18.1471L20.6289 16.9782H20.6287C21.0652 16.2265 21.4 15.4205 21.6249 14.5809H23.2756C23.4677 14.5809 23.652 14.5045 23.7879 14.3686C23.9238 14.2327 24 14.0486 24 13.8564V10.1422C24 9.94936 23.9232 9.76472 23.7868 9.62866C23.6502 9.49277 23.4652 9.41691 23.2723 9.41764L23.2723 9.41766ZM22.5479 13.1304H21.0482C20.8812 13.1304 20.7193 13.1881 20.59 13.2937C20.4606 13.3993 20.3717 13.5464 20.3382 13.71C20.1219 14.7714 19.7027 15.7813 19.1041 16.6839C19.012 16.8233 18.9709 16.9901 18.9876 17.1562C19.0046 17.3223 19.0782 17.4774 19.1961 17.5955L20.2583 18.6579L18.6577 20.2585L17.5953 19.1963L17.5955 19.1961C17.4774 19.0781 17.3221 19.0044 17.156 18.9876C16.9899 18.9709 16.8231 19.012 16.6837 19.1041C15.781 19.7027 14.7714 20.1219 13.71 20.3384C13.5464 20.3718 13.3993 20.4606 13.2938 20.59C13.1881 20.7193 13.1304 20.8812 13.1304 21.0482V22.5479H10.8667V21.0482C10.8667 20.8812 10.809 20.7193 10.7033 20.59C10.5978 20.4606 10.4506 20.3718 10.2871 20.3384C9.2256 20.1219 8.21595 19.7028 7.31333 19.1041C7.17398 19.012 7.00716 18.9709 6.84106 18.9876C6.67495 19.0044 6.51962 19.0781 6.40155 19.1961L5.33919 20.2583L3.73852 18.6577L4.80074 17.5953L4.80092 17.5955C4.9188 17.4774 4.99248 17.3223 5.0094 17.1562C5.02614 16.9901 4.98502 16.8233 4.89297 16.6839C4.29431 15.7812 3.87518 14.7714 3.65886 13.71C3.62539 13.5464 3.53643 13.3993 3.40709 13.2937C3.27775 13.1881 3.11585 13.1304 2.94885 13.1304H1.44915V10.8667H2.94885C3.11585 10.8667 3.27775 10.809 3.40709 10.7033C3.53643 10.5978 3.62539 10.4506 3.65886 10.2871C3.87516 9.22559 4.29431 8.21576 4.89297 7.31314C4.98503 7.17379 5.02614 7.00697 5.0094 6.84087C4.99248 6.67478 4.91881 6.51961 4.80092 6.40154L3.7387 5.33918L5.33937 3.73851L6.40229 4.80087C6.52036 4.91894 6.67571 4.99261 6.8418 5.00935C7.00789 5.02609 7.1747 4.98497 7.31407 4.89292C8.21655 4.29426 9.22601 3.87513 10.2871 3.65862C10.4507 3.62515 10.5978 3.53638 10.7033 3.40704C10.809 3.2777 10.8667 3.11579 10.8667 2.94879V1.44909H13.1304V2.94879C13.1304 3.11579 13.1881 3.2777 13.2938 3.40704C13.3993 3.53638 13.5465 3.62515 13.71 3.65862C14.7715 3.8751 15.7811 4.29422 16.6838 4.89292C16.8231 4.98497 16.9899 5.02609 17.156 5.00935C17.3221 4.99261 17.4775 4.91894 17.5955 4.80087L18.6579 3.73865L20.2586 5.33932L19.1962 6.40224C19.0783 6.5203 19.0047 6.67548 18.9877 6.84157C18.971 7.00765 19.0121 7.17447 19.1042 7.31383C19.7028 8.21651 20.122 9.22629 20.3383 10.2878C20.3717 10.4513 20.4607 10.5985 20.59 10.704C20.7194 10.8097 20.8813 10.8674 21.0483 10.8674H22.548L22.5479 13.1304Z"
fill="white" />
<path d="M12.0009 6.40381C10.5172 6.40381 9.09405 6.9932 8.04497 8.04252C6.99569 9.09161 6.40625 10.5148 6.40625 11.9984C6.40625 13.4821 6.99564 14.9053 8.04497 15.9544C9.09405 17.0036 10.5172 17.5931 12.0009 17.5931C13.4846 17.5931 14.9077 17.0037 15.9568 15.9544C17.0061 14.9053 17.5955 13.4821 17.5955 11.9984C17.5937 10.5151 17.0037 9.09306 15.955 8.04434C14.9062 6.99562 13.4842 6.40562 12.0009 6.40381ZM12.0009 16.144C10.9014 16.144 9.84682 15.7072 9.06951 14.9297C8.29202 14.1524 7.85524 13.0978 7.85524 11.9983C7.85524 10.8989 8.29202 9.84428 9.06951 9.06698C9.84682 8.28949 10.9014 7.8527 12.0009 7.8527C13.1004 7.8527 14.1549 8.28948 14.9323 9.06698C15.7097 9.84428 16.1465 10.8989 16.1465 11.9983C16.1453 13.0975 15.7081 14.1513 14.9309 14.9285C14.1538 15.7056 13.1 16.1427 12.0008 16.144L12.0009 16.144Z"
fill="white" />
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,6 @@
<svg viewBox="0 0 23 35">
<path d="M6.67775 18.9037H16.3212V8.9873H23V34.6801H16.3212V24.1503H6.67775V34.6801H0V8.98833H6.67775V18.9037Z"
fill="white" />
<path d="M11.5226 6.74678C13.3858 6.74678 14.8963 5.23635 14.8963 3.37314C14.8963 1.50994 13.3858 -0.000488281 11.5226 -0.000488281C9.65941 -0.000488281 8.14899 1.50994 8.14899 3.37314C8.14899 5.23635 9.65941 6.74678 11.5226 6.74678Z"
fill="white" />
</svg>

After

Width:  |  Height:  |  Size: 424 B

View File

@ -0,0 +1,9 @@
<svg width="22"
height="24"
viewBox="0 0 22 24"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path opacity="0.7"
d="M10.5124 0C12.2143 0 13.6045 1.34011 13.6825 3.02105C16.6478 4.27504 18.6446 7.20048 18.6446 10.5121V14.6853C19.9739 14.7872 21.0248 15.8999 21.0248 17.2562V18.844C21.0248 19.6115 20.4016 20.2314 19.6354 20.2314H1.38944C0.621398 20.2314 0 19.6113 0 18.844V17.2562C0 15.9015 1.04954 14.7872 2.38017 14.6853V10.5121C2.38017 7.20205 4.3775 4.27606 7.34228 3.02152C7.42013 1.33999 8.81165 0 10.5124 0ZM19.0413 18.2479V17.2562C19.0413 16.9291 18.7728 16.6612 18.4455 16.6612C17.46 16.6612 16.6612 15.8623 16.6612 14.8767V10.5121C16.6612 7.8196 14.9152 5.46438 12.3916 4.65569L11.7025 4.43487V3.1702C11.7025 2.516 11.1694 1.98347 10.5124 1.98347C9.85622 1.98347 9.32231 2.51615 9.32231 3.1702V4.435L8.63344 4.65592C6.11029 5.4651 4.36364 7.82123 4.36364 10.5121V14.8767C4.36364 15.862 3.56355 16.6612 2.57934 16.6612C2.25168 16.6612 1.98347 16.9296 1.98347 17.2562V18.2479H19.0413ZM6.7438 20.2314H8.72727C8.72727 21.2173 9.5265 22.0165 10.5124 22.0165C11.4983 22.0165 12.2975 21.2173 12.2975 20.2314H14.281C14.281 22.3127 12.5937 24 10.5124 24C8.43106 24 6.7438 22.3127 6.7438 20.2314Z"
fill="white" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -20,7 +20,7 @@ import { SyncStatus } from ".";
import { SyncStatus as SyncStatusOptions } from "@constants/sync-status";
export default {
title: "molecules/Sync Status",
title: "atoms/Sync Status",
component: SyncStatus,
argTypes: {
status: {

View File

@ -14,7 +14,7 @@
// limitations under the License.
// =============================================================================
import { Box, createStyles, Group } from "@mantine/core";
import { Box, createStyles, Group, Stack, Text } from "@mantine/core";
import { BodyText } from "@atoms/Typography";
import { SyncStatus as SyncStatusOptions } from "@constants/sync-status";
@ -28,24 +28,37 @@ export function SyncStatus({
const { classes } = useStyles({ syncStatus: status });
return (
<Group className={classes.container} spacing="sm">
<Box component="span" className={classes.syncDot} />
<BodyText heavy className={classes.message}>
{status}
</BodyText>
</Group>
<Stack className={classes.container} spacing={2}>
<Group spacing={4}>
<Box component="span" className={classes.syncDot} />
<BodyText heavy className={classes.message}>
{status}
</BodyText>
</Group>
<Text className={classes.nodeName}>node.sethforprivacy.com</Text>
</Stack>
);
}
const useStyles = createStyles<string, { syncStatus: SyncStatusOptions }>(
(theme, { syncStatus }) => ({
container: {
backgroundColor: theme.colors.gray[1],
borderRadius: "0.5rem",
padding: "0.75rem 1rem",
background: "rgba(17, 17, 17, 0.15)",
borderRadius: theme.radius.md,
padding: `${theme.spacing.xs * 0.8}px ${theme.spacing.xs}px`,
},
message: {
color: theme.colors.white,
fontSize: "0.5rem",
fontWeight: 700,
opacity: 0.8,
textTransform: "uppercase",
},
nodeName: {
color: theme.colors.white,
fontSize: "0.75rem",
fontWeight: 600,
},
message: {},
notSynced: {},
syncDot: {
backgroundColor:
syncStatus === SyncStatusOptions.Full

View File

@ -3,15 +3,24 @@
exports[`atoms::Sync Status > renders the fully synced status 1`] = `
<DocumentFragment>
<div
class="mantine-Group-root mantine-33bl97"
class="mantine-Stack-root mantine-xkcyre"
>
<span
class="mantine-Group-child mantine-16wvh2m"
/>
<div
class="mantine-Text-root mantine-Group-child mantine-6ffw9j"
class="mantine-Group-root mantine-i39wlo"
>
Fully Synced
<span
class="mantine-Group-child mantine-16wvh2m"
/>
<div
class="mantine-Text-root mantine-Group-child mantine-1bxawp9"
>
Fully Synced
</div>
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
node.sethforprivacy.com
</div>
</div>
</DocumentFragment>
@ -20,15 +29,24 @@ exports[`atoms::Sync Status > renders the fully synced status 1`] = `
exports[`atoms::Sync Status > renders the not synced status by default 1`] = `
<DocumentFragment>
<div
class="mantine-Group-root mantine-33bl97"
class="mantine-Stack-root mantine-xkcyre"
>
<span
class="mantine-Group-child mantine-1mmj0t1"
/>
<div
class="mantine-Text-root mantine-Group-child mantine-6ffw9j"
class="mantine-Group-root mantine-i39wlo"
>
Not Synced
<span
class="mantine-Group-child mantine-1mmj0t1"
/>
<div
class="mantine-Text-root mantine-Group-child mantine-1bxawp9"
>
Not Synced
</div>
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
node.sethforprivacy.com
</div>
</div>
</DocumentFragment>
@ -37,15 +55,24 @@ exports[`atoms::Sync Status > renders the not synced status by default 1`] = `
exports[`atoms::Sync Status > renders the sync in progress status 1`] = `
<DocumentFragment>
<div
class="mantine-Group-root mantine-33bl97"
class="mantine-Stack-root mantine-xkcyre"
>
<span
class="mantine-Group-child mantine-6c6x3l"
/>
<div
class="mantine-Text-root mantine-Group-child mantine-6ffw9j"
class="mantine-Group-root mantine-i39wlo"
>
Syncing
<span
class="mantine-Group-child mantine-6c6x3l"
/>
<div
class="mantine-Text-root mantine-Group-child mantine-1bxawp9"
>
Syncing
</div>
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
node.sethforprivacy.com
</div>
</div>
</DocumentFragment>

View File

@ -14,150 +14,74 @@
// limitations under the License.
// =============================================================================
import { useState, useMemo } from "react";
import {
Collapse,
createStyles,
Group,
Stack,
Text,
UnstyledButton,
} from "@mantine/core";
import { ReactComponent as XMRLogo } from "@assets/xmr-logo-1.svg";
import { ReactComponent as ArrowDown } from "@assets/arrow-down.svg";
import { createStyles, Group, Skeleton, Stack, Text } from "@mantine/core";
import { useBalances } from "@hooks/haveno/useBalances";
import { useAccountInfo } from "@hooks/storage/useAccountInfo";
import { usePrice } from "@hooks/haveno/usePrice";
import { Currency } from "@atoms/Currency";
import { BodyText } from "@atoms/Typography";
export function WalletBalance() {
const [isOpen, setOpen] = useState(false);
const { classes } = useStyles({ isOpen });
const { classes } = useStyles();
const { data: balances, isLoading: isLoadingBalance } = useBalances();
const { data: accountInfo, isLoading: isLoadingAccountInfo } =
useAccountInfo();
const { data: price } = usePrice(accountInfo?.primaryFiat);
const totalBalance = useMemo(() => {
return balances?.balance || 0 + (balances?.reservedTradeBalance || 0);
}, [balances]);
const fiatBalance = useMemo(() => {
if (!totalBalance || !price || !accountInfo?.primaryFiat) {
return 0;
}
return totalBalance * price;
}, [totalBalance, price, accountInfo]);
return (
<UnstyledButton
aria-label="Show Balance"
className={classes.btnToggle}
onClick={() => setOpen(!isOpen)}
>
<Stack>
<Group spacing="sm">
<XMRLogo className={classes.xmrLogo} />
<Text className={classes.heading} weight={700}>
Available Balance
</Text>
</Group>
{isLoadingAccountInfo || isLoadingBalance ? (
<Stack>
<BodyText size="xs">Loading...</BodyText>
</Stack>
) : (
<>
<Stack spacing={4}>
<Group>
<Text className={classes.xmr}>
<Currency value={Number(balances?.balance || 0)} />
</Text>
<ArrowDown className={classes.toggleIcon} />
</Group>
<Text className={classes.fiat}>
(
<Currency
currencyCode={accountInfo?.primaryFiat}
value={fiatBalance}
/>
)
</Text>
</Stack>
<Collapse in={isOpen}>
<Stack>
<Stack spacing={4}>
<Text className={classes.balanceLabel}>Total</Text>
<Text className={classes.balanceValue}>
<Currency value={totalBalance} />
</Text>
</Stack>
<Stack spacing={4}>
<Text className={classes.balanceLabel}>Reserved</Text>
<Text className={classes.balanceValue}>
<Currency value={balances?.reservedTradeBalance || 0} />
</Text>
</Stack>
<Stack spacing={4}>
<Text className={classes.balanceLabel}>Locked</Text>
<Text className={classes.balanceValue}>
<Currency value={balances?.lockedBalance || 0} />
</Text>
</Stack>
</Stack>
</Collapse>
</>
)}
<Group className={classes.container} spacing="sm" position="apart">
<Stack spacing={2}>
<Text className={classes.heading}>Available Balance</Text>
<BalanceValue
isLoading={isLoadingBalance}
value={balances?.availableBalance || 0}
/>
</Stack>
</UnstyledButton>
<Stack spacing={2}>
<Text className={classes.heading}>Locked Funds</Text>
<BalanceValue
isLoading={isLoadingBalance}
value={balances?.lockedBalance || 0}
/>
</Stack>
<Stack spacing={2}>
<Text className={classes.heading}>Reserved Funds</Text>
<BalanceValue
isLoading={isLoadingBalance}
value={balances?.reservedBalance || 0}
/>
</Stack>
</Group>
);
}
const useStyles = createStyles<string, { isOpen: boolean }>(
(theme, params) => ({
btnToggle: {
border: `solid 1px ${theme.colors.gray[4]}`,
borderRadius: theme.radius.md,
padding: theme.spacing.md,
interface BalanceValueProps {
isLoading: boolean;
value: number;
}
"&:hover": {
borderColor: theme.colors.gray[5],
},
},
xmrLogo: {
width: 20,
},
toggleIcon: {
transform: `rotate(${params.isOpen ? 180 : 0}deg)`,
transition: "transform 0.2s",
width: 8,
},
heading: {
fontSize: "0.5rem",
fontWeight: 700,
textTransform: "uppercase",
},
xmr: {
fontSize: "0.75rem",
fontWeight: 600,
},
fiat: {
color: theme.colors.gray[6],
fontSize: "0.625rem",
fontWeight: 500,
},
balanceLabel: {
color: theme.colors.gray[6],
fontSize: "0.625rem",
fontWeight: 700,
textTransform: "uppercase",
},
balanceValue: {
color: theme.colors.gray[8],
fontSize: "0.625rem",
fontWeight: 600,
},
})
);
function BalanceValue({ isLoading, value }: BalanceValueProps) {
const { classes } = useStyles();
if (isLoading) {
return <Skeleton height={12} my={3} sx={{ opacity: 0.15 }} />;
}
return (
<Text className={classes.balanceValue}>
<Currency value={value} />
</Text>
);
}
const useStyles = createStyles((theme) => ({
container: {
background: "rgba(17, 17, 17, 0.15)",
borderRadius: theme.radius.md,
padding: `${theme.spacing.xs * 0.8}px ${theme.spacing.xs}px`,
},
heading: {
color: theme.colors.white,
fontSize: "0.5rem",
fontWeight: 700,
opacity: 0.8,
textTransform: "uppercase",
},
balanceValue: {
color: theme.colors.white,
fontSize: "0.75rem",
fontWeight: 600,
},
}));

View File

@ -2,290 +2,102 @@
exports[`molecules::WalletBalance > renders after loading data 1`] = `
<DocumentFragment>
<button
aria-label="Show Balance"
class="mantine-UnstyledButton-root mantine-3om9so"
type="button"
<div
class="mantine-Group-root mantine-cvr2kw"
>
<div
class="mantine-Stack-root mantine-lfk3cq"
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Group-root mantine-1lumg83"
class="mantine-Text-root mantine-1l9p15c"
>
<svg
class="mantine-Group-child mantine-oilh7i"
fill="none"
height="1em"
viewBox="0 0 20 20"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#clip0_3508_17165)"
>
<path
d="M10.0026 0C4.4815 0 -0.00311409 4.48323 0.0039145 9.9987C0.00529892 11.1022 0.18128 12.1636 0.51157 13.1565H3.5034V4.74512L10.0026 11.2436L16.5015 4.74512V13.1567H19.494C19.8247 12.1639 19.9998 11.1024 20.0018 9.99885C20.0112 4.47764 15.5243 0.00133103 10.0026 0.00133103V0Z"
fill="#111111"
/>
<path
d="M8.50535 12.7375L5.66905 9.90137V15.1943H3.50057L1.45435 15.1946C3.20952 18.0739 6.38154 20 9.99999 20C13.6184 20 16.7906 18.0735 18.5461 15.1942H14.3303V9.90137L11.4938 12.7375L9.99967 14.2315L8.50545 12.7375H8.50535Z"
fill="#111111"
/>
</g>
<defs>
<clippath
id="clip0_3508_17165"
>
<rect
fill="white"
height="20"
width="20"
/>
</clippath>
</defs>
</svg>
<div
class="mantine-Text-root mantine-Group-child mantine-1iw7oli"
>
Available Balance
</div>
Available Balance
</div>
<div
class="mantine-Stack-root mantine-1kb6t4k"
class="mantine-Text-root mantine-1azyhhz"
>
<div
class="mantine-Group-root mantine-6y1794"
>
<div
class="mantine-Text-root mantine-Group-child mantine-q5labh"
>
15.00
</div>
<svg
class="mantine-Group-child mantine-qg5oag"
fill="none"
height="1em"
viewBox="0 0 7 4"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M2.91916 3.69319C3.23963 4.04927 3.76166 4.04657 4.07971 3.69319L6.82329 0.644746C7.14377 0.288661 7.01636 0 6.53811 0H0.460749C-0.0172283 0 -0.14248 0.291357 0.17557 0.644746L2.91916 3.69319Z"
fill="#111111"
fill-rule="evenodd"
/>
</svg>
</div>
<div
class="mantine-Text-root mantine-1pfxwhx"
>
(USD 4,500.00)
</div>
</div>
<div
aria-hidden="true"
class="mantine-1avyp1d"
style="box-sizing: border-box; display: none; height: 0px; overflow: hidden;"
>
<div
style="opacity: 0; transition: opacity 200ms ease;"
>
<div
class="mantine-Stack-root mantine-lfk3cq"
>
<div
class="mantine-Stack-root mantine-1kb6t4k"
>
<div
class="mantine-Text-root mantine-kaqdcf"
>
Total
</div>
<div
class="mantine-Text-root mantine-14d5cdm"
>
15.00
</div>
</div>
<div
class="mantine-Stack-root mantine-1kb6t4k"
>
<div
class="mantine-Text-root mantine-kaqdcf"
>
Reserved
</div>
<div
class="mantine-Text-root mantine-14d5cdm"
>
14.00
</div>
</div>
<div
class="mantine-Stack-root mantine-1kb6t4k"
>
<div
class="mantine-Text-root mantine-kaqdcf"
>
Locked
</div>
<div
class="mantine-Text-root mantine-14d5cdm"
>
12.00
</div>
</div>
</div>
</div>
0.00
</div>
</div>
</button>
<div
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Text-root mantine-1l9p15c"
>
Locked Funds
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
12.00
</div>
</div>
<div
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Text-root mantine-1l9p15c"
>
Reserved Funds
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
0.00
</div>
</div>
</div>
</DocumentFragment>
`;
exports[`molecules::WalletBalance > renders loading state 1`] = `
<DocumentFragment>
<button
aria-label="Show Balance"
class="mantine-UnstyledButton-root mantine-3om9so"
type="button"
<div
class="mantine-Group-root mantine-cvr2kw"
>
<div
class="mantine-Stack-root mantine-lfk3cq"
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Group-root mantine-1lumg83"
class="mantine-Text-root mantine-1l9p15c"
>
<svg
class="mantine-Group-child mantine-oilh7i"
fill="none"
height="1em"
viewBox="0 0 20 20"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#clip0_3508_17165)"
>
<path
d="M10.0026 0C4.4815 0 -0.00311409 4.48323 0.0039145 9.9987C0.00529892 11.1022 0.18128 12.1636 0.51157 13.1565H3.5034V4.74512L10.0026 11.2436L16.5015 4.74512V13.1567H19.494C19.8247 12.1639 19.9998 11.1024 20.0018 9.99885C20.0112 4.47764 15.5243 0.00133103 10.0026 0.00133103V0Z"
fill="#111111"
/>
<path
d="M8.50535 12.7375L5.66905 9.90137V15.1943H3.50057L1.45435 15.1946C3.20952 18.0739 6.38154 20 9.99999 20C13.6184 20 16.7906 18.0735 18.5461 15.1942H14.3303V9.90137L11.4938 12.7375L9.99967 14.2315L8.50545 12.7375H8.50535Z"
fill="#111111"
/>
</g>
<defs>
<clippath
id="clip0_3508_17165"
>
<rect
fill="white"
height="20"
width="20"
/>
</clippath>
</defs>
</svg>
<div
class="mantine-Text-root mantine-Group-child mantine-1iw7oli"
>
Available Balance
</div>
Available Balance
</div>
<div
class="mantine-Stack-root mantine-1kb6t4k"
class="mantine-Text-root mantine-1azyhhz"
>
<div
class="mantine-Group-root mantine-6y1794"
>
<div
class="mantine-Text-root mantine-Group-child mantine-q5labh"
>
15.00
</div>
<svg
class="mantine-Group-child mantine-qg5oag"
fill="none"
height="1em"
viewBox="0 0 7 4"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M2.91916 3.69319C3.23963 4.04927 3.76166 4.04657 4.07971 3.69319L6.82329 0.644746C7.14377 0.288661 7.01636 0 6.53811 0H0.460749C-0.0172283 0 -0.14248 0.291357 0.17557 0.644746L2.91916 3.69319Z"
fill="#111111"
fill-rule="evenodd"
/>
</svg>
</div>
<div
class="mantine-Text-root mantine-1pfxwhx"
>
(USD 4,500.00)
</div>
</div>
<div
aria-hidden="true"
class="mantine-1avyp1d"
style="box-sizing: border-box; display: none; height: 0px; overflow: hidden;"
>
<div
style="opacity: 0; transition: opacity 200ms ease;"
>
<div
class="mantine-Stack-root mantine-lfk3cq"
>
<div
class="mantine-Stack-root mantine-1kb6t4k"
>
<div
class="mantine-Text-root mantine-kaqdcf"
>
Total
</div>
<div
class="mantine-Text-root mantine-14d5cdm"
>
15.00
</div>
</div>
<div
class="mantine-Stack-root mantine-1kb6t4k"
>
<div
class="mantine-Text-root mantine-kaqdcf"
>
Reserved
</div>
<div
class="mantine-Text-root mantine-14d5cdm"
>
14.00
</div>
</div>
<div
class="mantine-Stack-root mantine-1kb6t4k"
>
<div
class="mantine-Text-root mantine-kaqdcf"
>
Locked
</div>
<div
class="mantine-Text-root mantine-14d5cdm"
>
12.00
</div>
</div>
</div>
</div>
0.00
</div>
</div>
</button>
<div
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Text-root mantine-1l9p15c"
>
Locked Funds
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
12.00
</div>
</div>
<div
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Text-root mantine-1l9p15c"
>
Reserved Funds
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
0.00
</div>
</div>
</div>
</DocumentFragment>
`;

View File

@ -16,17 +16,17 @@
import { Stack } from "@mantine/core";
import type { ComponentStory, ComponentMeta } from "@storybook/react";
import { Sidebar } from ".";
import { Navbar } from ".";
export default {
title: "organisms/Sidebar",
component: Sidebar,
} as ComponentMeta<typeof Sidebar>;
title: "organisms/Navbar",
component: Navbar,
} as ComponentMeta<typeof Navbar>;
const Template: ComponentStory<typeof Sidebar> = () => {
const Template: ComponentStory<typeof Navbar> = () => {
return (
<Stack>
<Sidebar />
<Navbar />
</Stack>
);
};

View File

@ -16,11 +16,11 @@
import { beforeAll, describe, expect, it, vi } from "vitest";
import { render } from "@testing-library/react";
import { Sidebar } from ".";
import { Navbar } from ".";
import { AppProviders } from "@atoms/AppProviders";
import { SyncStatus } from "@constants/sync-status";
describe("molecules::Sidebar", () => {
describe("molecules::Navbar", () => {
beforeAll(() => {
vi.mock("@hooks/haveno/useSyncStatus", () => ({
useSyncStatus: () => ({
@ -34,7 +34,7 @@ describe("molecules::Sidebar", () => {
it("renders without exploding", () => {
const { asFragment } = render(
<AppProviders>
<Sidebar />
<Navbar />
</AppProviders>
);
expect(asFragment()).toMatchSnapshot();

View File

@ -0,0 +1,118 @@
// =============================================================================
// Copyright 2022 Haveno
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
import { createStyles, Group } from "@mantine/core";
import { NavLink } from "./_NavLink";
import { WalletBalance } from "@molecules/WalletBalance";
import { ReactComponent as Logo } from "@assets/logo-white.svg";
import { ReactComponent as CogIcon } from "@assets/cog.svg";
import { ReactComponent as NotificationIcon } from "@assets/notification.svg";
import { useSyncStatus } from "@hooks/haveno/useSyncStatus";
import { SyncStatus } from "@atoms/SyncStatus";
import { ROUTES } from "@constants/routes";
export function Navbar() {
const { classes } = useStyles();
const { data: syncStatus } = useSyncStatus();
return (
<Group align="center" className={classes.container} position="apart">
<Group spacing="xl">
<Logo className={classes.logo} />
<NavLink
label="Dashboard"
to={ROUTES.Home}
activeRoutes={[ROUTES.Home]}
/>
<NavLink
label="Market"
to={ROUTES.Markets}
activeRoutes={[ROUTES.Markets]}
/>
<NavLink
label="My Offers"
to={ROUTES.MyOffers}
activeRoutes={[ROUTES.MyOffers]}
/>
<NavLink
label="My Trades"
to={ROUTES.MyTrades}
activeRoutes={[ROUTES.MyTrades]}
/>
<NavLink
label="Wallet"
to={ROUTES.MyWallet}
activeRoutes={[ROUTES.MyWallet]}
/>
</Group>
<Group spacing="xl">
<Group spacing="md">
<SyncStatus status={syncStatus} />
<WalletBalance />
</Group>
<Group spacing="md">
<NavLink
Component={<CogIcon className={classes.iconButton} />}
to={ROUTES.NodeSettings}
activeRoutes={[
ROUTES.PaymentAccounts,
ROUTES.AddPaymentAccount,
ROUTES.NodeSettings,
ROUTES.Backup,
ROUTES.Wallet,
ROUTES.Security,
]}
/>
<NavLink
Component={<NotificationIcon className={classes.iconButton} />}
to={ROUTES.Notifications}
activeRoutes={[ROUTES.Notifications]}
/>
</Group>
</Group>
</Group>
);
}
const useStyles = createStyles((theme) => ({
container: {
background: theme.colors.blue[6],
height: "4rem",
position: "relative",
padding: "0 2rem",
},
logo: {
height: "2rem !important",
marginRight: "1rem",
width: "2rem !important",
},
iconButton: {
height: "1.5rem !important",
width: "1.5rem !important",
},
nav: {
border: 0,
padding: 0,
paddingLeft: theme.spacing.md,
},
syncStatusContainer: {
margin: theme.spacing.lg,
},
walletBalance: {
marginRight: theme.spacing.lg,
marginTop: theme.spacing.lg,
},
}));

View File

@ -0,0 +1,87 @@
// =============================================================================
// Copyright 2022 Haveno
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
import { Text, createStyles } from "@mantine/core";
import { useMemo } from "react";
import { Link, matchPath, useLocation } from "react-router-dom";
interface NavLinkProps {
activeRoutes: Array<string>;
label?: string;
to: string;
Component?: JSX.Element;
}
export function NavLink(props: NavLinkProps) {
const { Component, activeRoutes, to, label } = props;
const location = useLocation();
const isActive = useMemo(() => {
let matched = false;
activeRoutes.forEach((route) => {
if (matchPath(route, location.pathname)) {
matched = true;
}
});
return matched;
}, [activeRoutes, location]);
const { classes } = useStyles({ isActive });
return (
<Link to={to} className={classes.navLink}>
{Component}
{label && (
<Text className={classes.text} color="white" size="xs">
{label}
</Text>
)}
</Link>
);
}
const useStyles = createStyles<string, { isActive: boolean }>(
(theme, { isActive }) => ({
navLink: {
alignItems: "center",
display: "flex",
height: 64,
opacity: isActive ? 1 : 0.7,
position: "relative",
textDecoration: "none",
transition: "opacity 0.2s",
"&:after": {
background: isActive ? "white" : "none",
bottom: 0,
content: '" "',
height: 3,
left: 0,
position: "absolute",
right: 0,
},
"&:hover": {
opacity: 1,
},
},
text: {
color: theme.colors.gray[0],
fontSize: "0.75rem",
fontWeight: 600,
},
})
);

View File

@ -0,0 +1,193 @@
// Vitest Snapshot v1
exports[`molecules::Navbar > renders without exploding 1`] = `
<DocumentFragment>
<div
class="mantine-Group-root mantine-9hzenx"
>
<div
class="mantine-Group-root mantine-Group-child mantine-j57jgu"
>
<svg
class="mantine-Group-child mantine-1rtqz1s"
height="1em"
viewBox="0 0 23 35"
width="1em"
>
<path
d="M6.67775 18.9037H16.3212V8.9873H23V34.6801H16.3212V24.1503H6.67775V34.6801H0V8.98833H6.67775V18.9037Z"
fill="white"
/>
<path
d="M11.5226 6.74678C13.3858 6.74678 14.8963 5.23635 14.8963 3.37314C14.8963 1.50994 13.3858 -0.000488281 11.5226 -0.000488281C9.65941 -0.000488281 8.14899 1.50994 8.14899 3.37314C8.14899 5.23635 9.65941 6.74678 11.5226 6.74678Z"
fill="white"
/>
</svg>
<a
class="mantine-vyomv2"
href="#/"
>
<div
class="mantine-Text-root mantine-dnz1r0"
>
Dashboard
</div>
</a>
<a
class="mantine-12wpkdi"
href="#/markets"
>
<div
class="mantine-Text-root mantine-dnz1r0"
>
Market
</div>
</a>
<a
class="mantine-12wpkdi"
href="#/my-offers"
>
<div
class="mantine-Text-root mantine-dnz1r0"
>
My Offers
</div>
</a>
<a
class="mantine-12wpkdi"
href="#/my-trades"
>
<div
class="mantine-Text-root mantine-dnz1r0"
>
My Trades
</div>
</a>
<a
class="mantine-12wpkdi"
href="#/my-wallet"
>
<div
class="mantine-Text-root mantine-dnz1r0"
>
Wallet
</div>
</a>
</div>
<div
class="mantine-Group-root mantine-Group-child mantine-j57jgu"
>
<div
class="mantine-Group-root mantine-Group-child mantine-zah578"
>
<div
class="mantine-Stack-root mantine-xkcyre"
>
<div
class="mantine-Group-root mantine-i39wlo"
>
<span
class="mantine-Group-child mantine-1mmj0t1"
/>
<div
class="mantine-Text-root mantine-Group-child mantine-1bxawp9"
>
Not Synced
</div>
</div>
<div
class="mantine-Text-root mantine-1azyhhz"
>
node.sethforprivacy.com
</div>
</div>
<div
class="mantine-Group-root mantine-cvr2kw"
>
<div
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Text-root mantine-1l9p15c"
>
Available Balance
</div>
<div
class="mantine-Skeleton-root mantine-Skeleton-visible mantine-1c7n6se"
/>
</div>
<div
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Text-root mantine-1l9p15c"
>
Locked Funds
</div>
<div
class="mantine-Skeleton-root mantine-Skeleton-visible mantine-1c7n6se"
/>
</div>
<div
class="mantine-Stack-root mantine-Group-child mantine-1vgxq13"
>
<div
class="mantine-Text-root mantine-1l9p15c"
>
Reserved Funds
</div>
<div
class="mantine-Skeleton-root mantine-Skeleton-visible mantine-1c7n6se"
/>
</div>
</div>
</div>
<div
class="mantine-Group-root mantine-Group-child mantine-zah578"
>
<a
class="mantine-12wpkdi"
href="#/account/node-settings"
>
<svg
class="mantine-1r5q4ov"
fill="none"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M23.2723 9.41766H21.6216C21.3968 8.57814 21.0618 7.77205 20.6254 7.02036L21.7943 5.85154H21.7944C21.9301 5.71565 22.0066 5.53137 22.0066 5.33927C22.0066 5.14717 21.9301 4.96289 21.7944 4.82699L19.1683 2.20085C19.0324 2.06514 18.8481 1.98873 18.656 1.98873C18.4639 1.98873 18.2796 2.06514 18.1437 2.20085L16.9766 3.37055C16.2249 2.93414 15.4189 2.59926 14.5793 2.37437V0.724569C14.5793 0.532466 14.5029 0.348188 14.367 0.212295C14.2311 0.0764032 14.047 0 13.8547 0H10.1422C9.9499 0 9.76581 0.0764032 9.62992 0.212295C9.49402 0.348188 9.41762 0.532466 9.41762 0.724569V2.37525C8.5781 2.6001 7.77201 2.93503 7.02032 3.37144L5.8515 2.20262V2.20244C5.71561 2.06672 5.53133 1.99032 5.33923 1.99032C5.14712 1.99032 4.96284 2.06672 4.82695 2.20244L2.20081 4.82858C2.0651 4.96447 1.98869 5.14875 1.98869 5.34086C1.98869 5.53296 2.0651 5.71724 2.20081 5.85313L3.36963 7.02195H3.36981C2.93339 7.77364 2.59851 8.57968 2.37362 9.41925H0.724569C0.532466 9.41925 0.348188 9.49565 0.212295 9.63155C0.0764033 9.76726 0 9.95154 0 10.1438V13.8565V13.8564C0 14.0486 0.0764033 14.2327 0.212295 14.3686C0.348188 14.5045 0.532466 14.5809 0.724569 14.5809H2.37525C2.6001 15.4205 2.93503 16.2265 3.37144 16.9782L2.20262 18.1471H2.20244C2.06673 18.2829 1.99032 18.4672 1.99032 18.6593C1.99032 18.8514 2.06673 19.0357 2.20244 19.1716L4.82858 21.7977C4.96447 21.9335 5.14875 22.0099 5.34086 22.0099C5.53296 22.0099 5.71724 21.9335 5.85313 21.7977L7.02195 20.6289V20.6287C7.77364 21.0652 8.57968 21.4 9.41925 21.6249V23.2756C9.41925 23.4677 9.49565 23.652 9.63155 23.7879C9.76726 23.9238 9.95154 24 10.1438 24H13.8565H13.8564C14.0486 24 14.2327 23.9238 14.3686 23.7879C14.5045 23.652 14.5809 23.4677 14.5809 23.2756V21.6249C15.4205 21.4001 16.2265 21.0652 16.9782 20.6287L18.1471 21.7976V21.7977C18.2829 21.9335 18.4672 22.0099 18.6593 22.0099C18.8514 22.0099 19.0357 21.9335 19.1716 21.7977L21.7977 19.1716C21.9335 19.0357 22.0099 18.8514 22.0099 18.6593C22.0099 18.4672 21.9335 18.2829 21.7977 18.1471L20.6289 16.9782H20.6287C21.0652 16.2265 21.4 15.4205 21.6249 14.5809H23.2756C23.4677 14.5809 23.652 14.5045 23.7879 14.3686C23.9238 14.2327 24 14.0486 24 13.8564V10.1422C24 9.94936 23.9232 9.76472 23.7868 9.62866C23.6502 9.49277 23.4652 9.41691 23.2723 9.41764L23.2723 9.41766ZM22.5479 13.1304H21.0482C20.8812 13.1304 20.7193 13.1881 20.59 13.2937C20.4606 13.3993 20.3717 13.5464 20.3382 13.71C20.1219 14.7714 19.7027 15.7813 19.1041 16.6839C19.012 16.8233 18.9709 16.9901 18.9876 17.1562C19.0046 17.3223 19.0782 17.4774 19.1961 17.5955L20.2583 18.6579L18.6577 20.2585L17.5953 19.1963L17.5955 19.1961C17.4774 19.0781 17.3221 19.0044 17.156 18.9876C16.9899 18.9709 16.8231 19.012 16.6837 19.1041C15.781 19.7027 14.7714 20.1219 13.71 20.3384C13.5464 20.3718 13.3993 20.4606 13.2938 20.59C13.1881 20.7193 13.1304 20.8812 13.1304 21.0482V22.5479H10.8667V21.0482C10.8667 20.8812 10.809 20.7193 10.7033 20.59C10.5978 20.4606 10.4506 20.3718 10.2871 20.3384C9.2256 20.1219 8.21595 19.7028 7.31333 19.1041C7.17398 19.012 7.00716 18.9709 6.84106 18.9876C6.67495 19.0044 6.51962 19.0781 6.40155 19.1961L5.33919 20.2583L3.73852 18.6577L4.80074 17.5953L4.80092 17.5955C4.9188 17.4774 4.99248 17.3223 5.0094 17.1562C5.02614 16.9901 4.98502 16.8233 4.89297 16.6839C4.29431 15.7812 3.87518 14.7714 3.65886 13.71C3.62539 13.5464 3.53643 13.3993 3.40709 13.2937C3.27775 13.1881 3.11585 13.1304 2.94885 13.1304H1.44915V10.8667H2.94885C3.11585 10.8667 3.27775 10.809 3.40709 10.7033C3.53643 10.5978 3.62539 10.4506 3.65886 10.2871C3.87516 9.22559 4.29431 8.21576 4.89297 7.31314C4.98503 7.17379 5.02614 7.00697 5.0094 6.84087C4.99248 6.67478 4.91881 6.51961 4.80092 6.40154L3.7387 5.33918L5.33937 3.73851L6.40229 4.80087C6.52036 4.91894 6.67571 4.99261 6.8418 5.00935C7.00789 5.02609 7.1747 4.98497 7.31407 4.89292C8.21655 4.29426 9.22601 3.87513 10.2871 3.65862C10.4507 3.62515 10.5978 3.53638 10.7033 3.40704C10.809 3.2777 10.8667 3.11579 10.8667 2.94879V1.44909H13.1304V2.94879C13.1304 3.11579 13.1881 3.2777 13.2938 3.40704C13.3993 3.53638 13.5465 3.62515 13.71 3.65862C14.7715 3.8751 15.7811 4.29422 16.6838 4.89292C16.8231 4.98497 16.9899 5.02609 17.156 5.00935C17.3221 4.99261 17.4775 4.91894 17.5955 4.80087L18.6579 3.73865L20.2586 5.33932L19.1962 6.40224C19.0783 6.5203 19.0047 6.67548 18.9877 6.84157C18.971 7.00765 19.0121 7.17447 19.1042 7.31383C19.7028 8.21651 20.122 9.22629 20.3383 10.2878C20.3717 10.4513 20.4607 10.5985 20.59 10.704C20.7194 10.8097 20.8813 10.8674 21.0483 10.8674H22.548L22.5479 13.1304Z"
fill="white"
/>
<path
d="M12.0009 6.40381C10.5172 6.40381 9.09405 6.9932 8.04497 8.04252C6.99569 9.09161 6.40625 10.5148 6.40625 11.9984C6.40625 13.4821 6.99564 14.9053 8.04497 15.9544C9.09405 17.0036 10.5172 17.5931 12.0009 17.5931C13.4846 17.5931 14.9077 17.0037 15.9568 15.9544C17.0061 14.9053 17.5955 13.4821 17.5955 11.9984C17.5937 10.5151 17.0037 9.09306 15.955 8.04434C14.9062 6.99562 13.4842 6.40562 12.0009 6.40381ZM12.0009 16.144C10.9014 16.144 9.84682 15.7072 9.06951 14.9297C8.29202 14.1524 7.85524 13.0978 7.85524 11.9983C7.85524 10.8989 8.29202 9.84428 9.06951 9.06698C9.84682 8.28949 10.9014 7.8527 12.0009 7.8527C13.1004 7.8527 14.1549 8.28948 14.9323 9.06698C15.7097 9.84428 16.1465 10.8989 16.1465 11.9983C16.1453 13.0975 15.7081 14.1513 14.9309 14.9285C14.1538 15.7056 13.1 16.1427 12.0008 16.144L12.0009 16.144Z"
fill="white"
/>
</svg>
</a>
<a
class="mantine-12wpkdi"
href="#/notifications"
>
<svg
class="mantine-1r5q4ov"
fill="none"
height="1em"
viewBox="0 0 22 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.5124 0C12.2143 0 13.6045 1.34011 13.6825 3.02105C16.6478 4.27504 18.6446 7.20048 18.6446 10.5121V14.6853C19.9739 14.7872 21.0248 15.8999 21.0248 17.2562V18.844C21.0248 19.6115 20.4016 20.2314 19.6354 20.2314H1.38944C0.621398 20.2314 0 19.6113 0 18.844V17.2562C0 15.9015 1.04954 14.7872 2.38017 14.6853V10.5121C2.38017 7.20205 4.3775 4.27606 7.34228 3.02152C7.42013 1.33999 8.81165 0 10.5124 0ZM19.0413 18.2479V17.2562C19.0413 16.9291 18.7728 16.6612 18.4455 16.6612C17.46 16.6612 16.6612 15.8623 16.6612 14.8767V10.5121C16.6612 7.8196 14.9152 5.46438 12.3916 4.65569L11.7025 4.43487V3.1702C11.7025 2.516 11.1694 1.98347 10.5124 1.98347C9.85622 1.98347 9.32231 2.51615 9.32231 3.1702V4.435L8.63344 4.65592C6.11029 5.4651 4.36364 7.82123 4.36364 10.5121V14.8767C4.36364 15.862 3.56355 16.6612 2.57934 16.6612C2.25168 16.6612 1.98347 16.9296 1.98347 17.2562V18.2479H19.0413ZM6.7438 20.2314H8.72727C8.72727 21.2173 9.5265 22.0165 10.5124 22.0165C11.4983 22.0165 12.2975 21.2173 12.2975 20.2314H14.281C14.281 22.3127 12.5937 24 10.5124 24C8.43106 24 6.7438 22.3127 6.7438 20.2314Z"
fill="white"
opacity="0.7"
/>
</svg>
</a>
</div>
</div>
</div>
</DocumentFragment>
`;

View File

@ -14,4 +14,4 @@
// limitations under the License.
// =============================================================================
export * from "./Sidebar";
export * from "./Navbar";

View File

@ -1,75 +0,0 @@
// =============================================================================
// Copyright 2022 Haveno
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
import { Box, createStyles, Navbar, Stack } from "@mantine/core";
import { NAV_LINKS, WIDTH } from "./_constants";
import { NavLink } from "./_NavLink";
import { WalletBalance } from "@molecules/WalletBalance";
import { ReactComponent as Logo } from "@assets/logo-icon.svg";
import { SyncStatus } from "@atoms/SyncStatus";
import { useSyncStatus } from "@hooks/haveno/useSyncStatus";
export function Sidebar() {
const { classes } = useStyles();
const { data: syncStatus } = useSyncStatus();
return (
<Stack className={classes.container} justify="space-between">
<Navbar className={classes.nav} width={{ base: WIDTH - 1 }}>
<Navbar.Section>
<Box component={Logo} className={classes.logo} />
</Navbar.Section>
{NAV_LINKS.map((link) => (
<Navbar.Section key={link.label}>
<NavLink {...link} />
</Navbar.Section>
))}
<Navbar.Section>
<Box className={classes.walletBalance}>
<WalletBalance />
</Box>
</Navbar.Section>
</Navbar>
<Box className={classes.syncStatusContainer}>
<SyncStatus status={syncStatus} />
</Box>
</Stack>
);
}
const useStyles = createStyles((theme) => ({
container: {
borderRight: `solid 1px ${theme.colors.gray[1]}`,
position: "relative",
width: WIDTH,
},
logo: {
height: "2rem",
padding: `${theme.spacing.lg}px ${theme.spacing.lg}px`,
},
nav: {
border: 0,
padding: 0,
paddingLeft: theme.spacing.md,
},
syncStatusContainer: {
margin: theme.spacing.lg,
},
walletBalance: {
marginRight: theme.spacing.lg,
marginTop: theme.spacing.lg,
},
}));

View File

@ -14,36 +14,22 @@
// limitations under the License.
// =============================================================================
import type { FC } from "react";
import { Group, createStyles, Box } from "@mantine/core";
import { NavbarLayout } from "@templates/NavbarLayout";
import { AccountSidebar } from "@organisms/AccountSidebar";
interface AccountContentProps {
children: JSX.Element | Array<JSX.Element>;
}
function AccountContent({ children }: AccountContentProps) {
export const AccountLayout: FC = ({ children }) => {
const { classes } = useStyles();
return (
<Group className={classes.container} spacing={0}>
<AccountSidebar />
<Box className={classes.contentArea}>{children}</Box>
</Group>
);
}
interface AccountLayoutProps {
children: JSX.Element | Array<JSX.Element>;
}
export function AccountLayout({ children }: AccountLayoutProps) {
return (
<NavbarLayout>
<AccountContent>{children}</AccountContent>
<Group className={classes.container} spacing={0}>
<AccountSidebar />
<Box className={classes.contentArea}>{children}</Box>
</Group>
</NavbarLayout>
);
}
};
const useStyles = createStyles((theme) => ({
container: {

View File

@ -16,8 +16,8 @@
import type { FC } from "react";
import type { DefaultProps } from "@mantine/core";
import { Box, createStyles, Group } from "@mantine/core";
import { Sidebar } from "@organisms/Sidebar";
import { Box, createStyles, Stack } from "@mantine/core";
import { Navbar } from "@organisms/Navbar";
export const NavbarLayout: FC<DefaultProps> = ({
children,
@ -31,17 +31,17 @@ export const NavbarLayout: FC<DefaultProps> = ({
});
return (
<Group className={cx(classes.container, className)} spacing={0} {...rest}>
<Sidebar />
<Stack className={cx(classes.container, className)} spacing={0} {...rest}>
<Navbar />
<Box className={classes.contentArea}>{children}</Box>
</Group>
</Stack>
);
};
const useStyles = createStyles((theme) => ({
container: {
flex: 1,
alignItems: "stretch",
flex: 1,
},
contentArea: {
background: theme.colors.gray[0],

View File

@ -18,11 +18,14 @@ export const ROUTES = {
Home: "",
HomeAlias: "/",
Login: "/login",
Markets: "/markets",
MyOffers: "/my-offers",
MyTrades: "/my-trades",
Welcome: "/onboarding/welcome",
CreateAccount: "/onboarding/create-account",
RestoreBackup: "/onboarding/restore-backup",
MyWallet: "/my-wallet",
Markets: "/markets",
Notifications: "/notifications",
// Account routes
PaymentAccounts: "/account/payment-accounts",

View File

@ -85,8 +85,7 @@ describe("pages::Login", () => {
unmount();
});
// TODO: update behavior to redirect to the Market page
it("navigates to Payment Accounts page after successful login", async () => {
it("navigates to Market page after successful login", async () => {
const PASSWORD = "Haveno!2022";
loginSpy.mockImplementation(({ password }, { onSuccess, onError }) => {
if (password === PASSWORD) {
@ -105,7 +104,7 @@ describe("pages::Login", () => {
await user.type(screen.getByLabelText("Password"), PASSWORD);
fireEvent.submit(screen.getByRole("button", { name: "Login" }));
expect(navSpy).to.toHaveBeenCalledTimes(1);
expect(navSpy).toHaveBeenCalledWith(ROUTES.PaymentAccounts, {
expect(navSpy).toHaveBeenCalledWith(ROUTES.Markets, {
replace: true,
});
unmount();

View File

@ -41,7 +41,7 @@ export function Login() {
const handleSubmit = (values: FormValues) => {
login(values, {
onSuccess: () => {
navigate(ROUTES.PaymentAccounts, { replace: true });
navigate(ROUTES.Markets, { replace: true });
},
onError: (err) => {
showNotification({