@@ -0,0 +1,70 @@
1+import cn from 'classnames';
2+import { Box, Icon, Row } from '@tlon/indigo-react';
3+import { RollerTransaction } from '@urbit/roller-api';
4+import { format, fromUnixTime } from 'date-fns';
5+import { titleize } from 'form/formatters';
6+import {
7+ TRANSACTION_STATUS_ICONS,
8+ TRANSACTION_TYPE_ICONS,
9+ TRANSACTION_TYPE_TITLES,
10+} from 'lib/constants';
11+import { abbreviateAddress } from 'lib/utils/address';
12+import { useMemo } from 'react';
13+import { useRollerStore } from 'store/roller';
14+
15+export const TransactionRow = ({
16+ type,
17+ hash,
18+ status,
19+ time,
20+}: RollerTransaction) => {
21+ const { nextRoll } = useRollerStore();
22+
23+ const label = useMemo(() => {
24+ return TRANSACTION_TYPE_TITLES[type] || type;
25+ }, [type]);
26+
27+ const icon = useMemo(() => {
28+ return <Icon icon={TRANSACTION_TYPE_ICONS[type] || 'Bug'} />;
29+ }, [type]);
30+
31+ const shortHash = useMemo(() => {
32+ return abbreviateAddress(hash);
33+ }, [hash]);
34+
35+ const shortDate = useMemo(() => {
36+ if (!time) {
37+ return null;
38+ }
39+ const d = fromUnixTime(time / 1000);
40+ console.log(d.toLocaleTimeString());
41+ return format(d, 'MMMM dd');
42+ }, [time]);
43+
44+ const statusBadge = useMemo(() => {
45+ return (
46+ <div className={cn(['badge', status])}>
47+ <span>
48+ <Icon icon={TRANSACTION_STATUS_ICONS[status] || 'Bug'} />
49+ </span>
50+ <span>{status === 'pending' ? nextRoll : titleize(status)}</span>
51+ </div>
52+ );
53+ }, [status, nextRoll]);
54+
55+ return (
56+ <Box className="transaction-row">
57+ <Box className="icon">{icon}</Box>
58+ <Box className="info">
59+ <Row className="title-row">
60+ <Box className="title">{label}</Box>
61+ <Box className="status">{statusBadge}</Box>
62+ </Row>
63+ <Row className="info-row">
64+ <Box className="hash">{shortHash}</Box>
65+ <Box className="date">{shortDate}</Box>
66+ </Row>
67+ </Box>
68+ </Box>
69+ );
70+};