Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 2x 14x 14x 2x 7x 7x 7x 7x 7x | import { Stack } from "@mui/material";
import GiveText from "@shared/Text/GiveText";
import { CoinsIcon } from "@phosphor-icons/react";
import { ReactNode } from "react";
import { useCustomThemeV2 } from "@theme/hooks/useCustomThemeV2";
import { ReconciliationHubView } from "../types";
import { formatHubAmount, formatHubAmountCompact } from "../format";
import SectionHeading from "./SectionHeading";
interface Props {
data?: ReconciliationHubView;
}
/** A grey sub-panel on the right side of the cash-position card. */
const DistributionKey = ({
label,
value,
}: {
label: string;
value: ReactNode;
}) => (
<Stack
justifyContent="center"
gap="4px"
sx={(theme) => ({
flex: "1 1 0",
minWidth: 0,
alignSelf: "stretch",
padding: "24px 20px",
borderRadius: "12px",
overflow: "hidden",
background: theme.palette.primitive?.transparent?.["darken-2"] ?? "rgba(0,0,0,0.02)",
})}
>
<GiveText variant="bodyS" color="secondary" noWrap>
{label}
</GiveText>
<GiveText variant="h3" noWrap>
{value}
</GiveText>
</Stack>
);
/**
* Cash Position: a single composite card. The left half shows the FBO
* Available Balance with a coins badge; the right half holds two grey
* distribution panels — Merchant Liabilities and the Buffer
* (FBO Available − Merchant Liabilities) — all as-of period end.
*/
const HubCashPosition = ({ data }: Props) => {
const { isLargeView } = useCustomThemeV2();
// On smaller screens these FBO / liabilities / buffer figures reach the
// billions and would ellipsize inside the fixed-width panels — compact them
// to `M`/`B` (confirmed with design); keep full precision on large screens.
const fmt = isLargeView ? formatHubAmount : formatHubAmountCompact;
return (
<Stack gap="12px" data-testid="hub-cash-position">
<SectionHeading variant="h6">Cash Position</SectionHeading>
<Stack
direction="row"
flexWrap="wrap"
alignItems="flex-end"
gap="12px"
sx={(theme) => ({
position: "relative",
minHeight: { xs: "auto", md: "224px" },
padding: "24px 20px",
// On mobile the content stacks from the top, so reserve room for the
// top-left coins badge; on desktop the tall card + bottom alignment
// already clears it.
paddingTop: { xs: "88px", md: "24px" },
borderRadius: "8px",
border: `1px solid ${theme.palette.border?.primary ?? "#E5E5E3"}`,
background: theme.palette.surface?.primary ?? theme.palette.background?.paper,
})}
>
{/* Coins badge, top-left */}
<Stack
alignItems="center"
justifyContent="center"
sx={(theme) => ({
position: "absolute",
top: "23px",
left: "19px",
padding: "13px",
borderRadius: "50%",
color: theme.palette.icon?.["icon-primary"] ?? theme.palette.text.primary,
background: theme.palette.surface?.secondary ?? "#F5F5F3",
})}
>
<CoinsIcon size={30} />
</Stack>
{/* Left: FBO Available Balance */}
<Stack
justifyContent="center"
gap="4px"
sx={{ flex: "1 1 280px", minWidth: "240px", minHeight: "97px" }}
>
<GiveText variant="bodyM" color="secondary">
FBO Available Balance (USD)
</GiveText>
<GiveText variant="h2">{fmt(data?.fboAvailable)}</GiveText>
</Stack>
{/* Right: distribution panels */}
<Stack
direction="row"
alignItems="stretch"
gap="12px"
sx={{ flex: "1 1 280px", minWidth: "240px", minHeight: "97px" }}
>
<DistributionKey
label="Merchant Liabilities (USD)"
value={fmt(data?.merchantLiabilities)}
/>
<DistributionKey
label="Buffer = FBO − Liabilities (USD)"
value={fmt(data?.buffer)}
/>
</Stack>
</Stack>
</Stack>
);
};
export default HubCashPosition;
|