on c19b2a8 help sign in
bridge/src/views/Point.js
268 lines 7.5 kB history raw
1import React, { useCallback, useState } from 'react';
2import cn from 'classnames';
3import { Just } from 'folktale/maybe';
4import { Grid, Flex } from 'indigo-react';
5import { azimuth } from 'azimuth-js';
7import { usePointCursor } from 'store/pointCursor';
8import { useWallet } from 'store/wallet';
10import View from 'components/View';
11import Greeting from 'components/Greeting';
12import Passport from 'components/Passport';
13import { ForwardButton, BootUrbitOSButton } from 'components/Buttons';
14import CopyButton from 'components/CopyButton';
15import { matchBlinky } from 'components/Blinky';
16import DownloadSigilButton from 'components/DownloadSigilButton';
17import BarGraph from 'components/BarGraph';
18import Chip from 'components/Chip';
19import InviteSigilList from 'components/InviteSigilList';
21import * as need from 'lib/need';
22import useInvites from 'lib/useInvites';
23import { useSyncOwnedPoints } from 'lib/useSyncPoints';
24import useCurrentPermissions from 'lib/useCurrentPermissions';
25import { useLocalRouter } from 'lib/LocalRouter';
26import useKeyfileGenerator from 'lib/useKeyfileGenerator';
28import InviteCohort from 'views/Invite/Cohort';
30export default function Point() {
31 const { pop, push, names } = useLocalRouter();
32 const { pointCursor } = usePointCursor();
34 const { wallet } = useWallet();
35 const point = need.point(pointCursor);
37 const { code, notice } = useKeyfileGenerator();
39 const {
40 isParent,
41 isActiveOwner,
42 canManage,
43 canSpawn,
44 canVote,
45 } = useCurrentPermissions();
47 // fetch the invites for the current cursor
48 const invites = useInvites(point);
49 const {
50 availableInvites,
51 sentInvites,
52 acceptedInvites,
53 pendingPoints,
54 acceptedPoints,
55 } = invites;
57 const showInvites = !(
58 acceptedInvites.getOrElse(0) === 0 && sentInvites.getOrElse(0) === 0
59 );
61 const hasInvites = showInvites || availableInvites.getOrElse(0) !== 0;
63 const _totalInvites =
64 sentInvites.getOrElse(0) + availableInvites.getOrElse(0);
65 const _pendingInvites = pendingPoints.getOrElse([]).length;
66 //
67 // availableInvites.getOrElse(0) === 0
69 const goAdmin = useCallback(() => push(names.ADMIN), [push, names]);
71 const goSenate = useCallback(() => push(names.SENATE), [push, names]);
73 const goInvite = useCallback(() => push(names.INVITE), [push, names]);
75 const goParty = useCallback(() => push(names.PARTY), [push, names]);
77 const goPartiesSetPoolSize = useCallback(
78 () => push(names.PARTY_SET_POOL_SIZE),
79 [push, names]
80 );
82 const goIssuePoint = useCallback(() => push(names.ISSUE_CHILD), [
83 names.ISSUE_CHILD,
84 push,
85 ]);
87 const isPlanet = azimuth.getPointSize(point) === azimuth.PointSize.Planet;
89 const [showInviteForm, setShowInviteForm] = useState(false);
91 const inviteButton = (() => {
92 switch (azimuth.getPointSize(point)) {
93 case azimuth.PointSize.Planet:
94 const availableInvitesText = matchBlinky(availableInvites);
95 return (
96 <>
97 <Grid.Item
98 full
99 as={ForwardButton}
100 disabled={!isActiveOwner}
101 onClick={goInvite}>
102 Invite <sup>{availableInvitesText}</sup>
103 </Grid.Item>
104 <Grid.Divider />
105 </>
106 );
107 //
108 case azimuth.PointSize.Star:
109 return (
110 <>
111 <Grid.Item
112 full
113 as={ForwardButton}
114 disabled={!isActiveOwner}
115 onClick={goPartiesSetPoolSize}>
116 Manage Invite Pools
117 </Grid.Item>
118 <Grid.Divider />
119 </>
120 );
121 //
122 default:
123 return null;
124 }
125 })();
127 const senateButton = (() => {
128 if (azimuth.getPointSize(point) !== azimuth.PointSize.Galaxy) {
129 return null;
130 }
131 return (
132 <>
133 <Grid.Item
134 full
135 as={ForwardButton}
136 disabled={!canVote}
137 onClick={goSenate}>
138 Senate
139 </Grid.Item>
140 <Grid.Divider />
141 </>
142 );
143 })();
145 // sync the current cursor
146 useSyncOwnedPoints([point]);
148 const address = need.addressFromWallet(wallet);
150 return (
151 <View pop={pop} inset>
152 <Greeting point={point} />
153 <Passport
154 point={Just(point)}
155 address={Just(address)}
156 animationMode={'slide'}
157 />
158 <Grid gap={3}>
159 {isPlanet && hasInvites && (
160 <>
161 <Grid.Item cols={[1, 11]}>
162 Invite Group
163 <br />
164 </Grid.Item>
166 <Grid.Item
167 className={cn('t-right underline', {
168 gray4: sentInvites.getOrElse(0) === 0,
169 })}
170 onClick={goParty}
171 cols={[11, 13]}>
172 View
173 </Grid.Item>
174 <Grid.Item full>
175 <Flex align="center">
176 <Flex.Item>
177 {acceptedInvites.getOrElse(0) + _pendingInvites} /{' '}
178 {_totalInvites}
179 </Flex.Item>
180 {_pendingInvites > 0 && (
181 <Flex.Item as={Chip} color="yellow">
182 {_pendingInvites} pending
183 </Flex.Item>
184 )}
185 </Flex>
186 </Grid.Item>
188 {showInvites && (
189 <>
190 <Grid.Item
191 full
192 as={BarGraph}
193 available={availableInvites}
194 sent={sentInvites}
195 accepted={acceptedInvites}
196 />
197 <Grid.Item
198 full
199 as={InviteSigilList}
200 pendingPoints={pendingPoints}
201 acceptedPoints={acceptedPoints}
202 />
203 </>
204 )}
205 {!showInvites && (
206 <>
207 <Grid.Item full className="b-gray4 b-dotted b1 self-center">
208 <div className="p4 pv8 t-center gray4">
209 Start your invite group by adding members
210 </div>
211 </Grid.Item>
212 </>
213 )}
214 {!showInviteForm && availableInvites.getOrElse(0) > 0 && (
215 <Grid.Item
216 full
217 solid
218 as={ForwardButton}
219 onClick={() => setShowInviteForm(true)}>
220 Add Members
221 </Grid.Item>
222 )}
223 {showInviteForm && <InviteCohort />}
224 </>
225 )}
226 </Grid>
227 <Grid className="pt2">
228 {inviteButton}
229 <Grid.Item
230 full
231 as={ForwardButton}
232 disabled={!canManage}
233 onClick={goAdmin}>
234 Admin
235 </Grid.Item>
236 <Grid.Divider />
238 {isParent && (
239 <>
240 <Grid.Item
241 full
242 as={ForwardButton}
243 disabled={!canSpawn}
244 onClick={goIssuePoint}>
245 Issue Point
246 </Grid.Item>
247 <Grid.Divider />
248 </>
249 )}
250 {senateButton}
251 <Grid.Item full as={BootUrbitOSButton} />
252 <Grid.Divider />
253 <Grid.Item
254 full
255 as={ForwardButton}
256 accessory={code && <CopyButton text={code} />}
257 detail={code || notice}
258 disabled={!code}
259 detailClassName="mono">
260 Login Code
261 </Grid.Item>
262 <Grid.Divider />
263 <Grid.Item full as={DownloadSigilButton} point={point} />
264 <Grid.Divider />
265 </Grid>
266 </View>
267 );