on d760cbf help sign in
bridge/src/components/Passport.js
101 lines 3.2 kB history raw
1import React from 'react';
2import cn from 'classnames';
3import { Just, Nothing } from 'folktale/maybe';
4import * as ob from 'urbit-ob';
5import { Grid, Flex, Text } from 'indigo-react';
6import { times } from 'lodash';
8import usePointBirthday from 'lib/usePointBirthday';
9import { formatDots } from 'lib/dateFormat';
11import Blinky, { LOADING_CHARACTER, INTERSTITIAL_CHARACTER } from './Blinky';
12import MaybeSigil from './MaybeSigil';
14const buildDate = char =>
15 [4, 2, 2].map(t => times(t, () => char).join('')).join('.');
16const DATE_A = buildDate(LOADING_CHARACTER);
17const DATE_B = buildDate(INTERSTITIAL_CHARACTER);
19const TICKET_CHAR_LENGTH = 30;
20const TICKET = times(TICKET_CHAR_LENGTH, i =>
21 i % 2 === 0 ? LOADING_CHARACTER : INTERSTITIAL_CHARACTER
22).join('');
23const PENDING_TICKET = TICKET;
24const VALID_TICKET = `${TICKET} ◆`;
26const VISIBLE_ADDRESS_CHAR_COUNT = 20;
27const EMPTY_ADDRESS = times(VISIBLE_ADDRESS_CHAR_COUNT, () => '<').join('');
28const ADDRESS_BUFFER_CHARS = times(40, () => '<').join('');
30/**
31 * point is Maybe<number>
32 * ticket is null | boolean
33 * address is null | Maybe<string>
34 */
35export default function Passport({
36 point,
37 className,
38 ticket = null,
39 address = Nothing(),
40 mini = false,
41}) {
42 const birthday = usePointBirthday(point.getOrElse(null));
43 const visualBirthday = birthday.matchWith({
44 Nothing: () => <Blinky a={DATE_A} b={DATE_B} delayed />,
45 Just: p => formatDots(p.value),
46 });
48 const name = point.matchWith({
49 Nothing: () => Nothing(),
50 Just: p => Just(ob.patp(p.value)),
51 });
52 const visualName = name.matchWith({
53 Nothing: () => '...',
54 Just: p => p.value,
55 });
57 const showTicket = ticket !== null;
58 const isValidTiket = !!ticket;
59 const visibleTicket = isValidTiket ? VALID_TICKET : PENDING_TICKET;
60 const visibleAddress = `${address.matchWith({
61 Nothing: () => EMPTY_ADDRESS,
62 Just: p => p.value.slice(0, VISIBLE_ADDRESS_CHAR_COUNT),
63 })}${ADDRESS_BUFFER_CHARS}`;
65 return (
66 <Grid gap={4} className={cn('bg-black r8 p7', className)}>
67 <Grid.Item cols={[1, 4]} className="bg-green">
68 <MaybeSigil patp={name} size={64} margin={0} />
69 </Grid.Item>
70 <Grid.Item as={Flex} cols={[4, 13]} col justify="between">
71 <Flex.Item className="mono white f5">{visualName}</Flex.Item>
72 <Flex.Item as={Flex} col>
73 <Flex.Item as={Text} className="mono f6 f5-ns gray4 uppercase">
74 Birth Time
75 </Flex.Item>
76 <Flex.Item as={Text} className="mono f6 f5-ns gray4 ">
77 {visualBirthday}
78 </Flex.Item>
79 </Flex.Item>
80 </Grid.Item>
81 {!mini && showTicket && (
82 <Grid.Item full className="mv3" as={Flex} col>
83 <Flex.Item as={Text} className="mono f6 f5-ns gray4 uppercase">
84 Master Ticket
85 </Flex.Item>
86 <Flex.Item
87 as={Text}
88 className={cn('mono f6 f5-ns wrap', {
89 gray4: !isValidTiket,
90 green3: isValidTiket,
91 })}>
92 {visibleTicket}
93 </Flex.Item>
94 <Flex.Item as={Text} className="mono f6 f5-ns gray4 wrap">
95 {visibleAddress}
96 </Flex.Item>
97 </Grid.Item>
98 )}
99 </Grid>
100 );