on ee01fbf help sign in
bridge/src/views/Point.js
254 lines 7.0 kB history raw
1import React, { useCallback, useState } from 'react';
2import cn from 'classnames';
3import { Just } from 'folktale/maybe';
4import { Grid, Flex, Button } 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 } from 'components/Buttons';
14import Blinky from 'components/Blinky';
15import BarGraph from 'components/BarGraph';
16import Chip from 'components/Chip';
17import InviteSigilList from 'components/InviteSigilList';
19import * as need from 'lib/need';
20import useInvites from 'lib/useInvites';
21import { useSyncOwnedPoints } from 'lib/useSyncPoints';
22import useCurrentPermissions from 'lib/useCurrentPermissions';
23import { useLocalRouter } from 'lib/LocalRouter';
25import Inviter from 'views/Invite/Inviter';
27export default function Point() {
28 const { pop, push, names } = useLocalRouter();
29 const { pointCursor } = usePointCursor();
31 const { wallet } = useWallet();
32 const point = need.point(pointCursor);
34 const {
35 isParent,
36 isActiveOwner,
37 canManage,
38 canSpawn,
39 canVote,
40 } = useCurrentPermissions();
42 // fetch the invites for the current cursor
43 const invites = useInvites(point);
44 const {
45 availableInvites,
46 sentInvites,
47 acceptedInvites,
48 pendingPoints,
49 acceptedPoints,
50 } = invites;
52 const showInvites = !(
53 acceptedInvites.getOrElse(0) === 0 && sentInvites.getOrElse(0) === 0
54 );
56 const hasInvites = showInvites || availableInvites.getOrElse(0) !== 0;
58 const _totalInvites =
59 sentInvites.getOrElse(0) + availableInvites.getOrElse(0);
60 const _pendingInvites = pendingPoints.getOrElse([]).length;
62 const loadedInvites = Just.hasInstance(availableInvites);
63 //
64 // availableInvites.getOrElse(0) === 0
66 const goAdmin = useCallback(() => push(names.ADMIN), [push, names]);
68 const goSenate = useCallback(() => push(names.SENATE), [push, names]);
70 const goSigil = useCallback(() => push(names.SIGIL_GENERATOR), [push, names]);
72 const goCohort = useCallback(() => push(names.INVITE_COHORT), [push, names]);
74 const goUrbitOS = useCallback(() => push(names.URBIT_OS), [push, names]);
76 const goPartiesSetPoolSize = useCallback(
77 () => push(names.PARTY_SET_POOL_SIZE),
78 [push, names]
79 );
81 const goIssuePoint = useCallback(() => push(names.ISSUE_CHILD), [
82 names.ISSUE_CHILD,
83 push,
84 ]);
86 const isPlanet = azimuth.getPointSize(point) === azimuth.PointSize.Planet;
88 const [showInviteForm, setShowInviteForm] = useState(false);
90 const inviteButton = (() => {
91 if (azimuth.getPointSize(point) === azimuth.PointSize.Star) {
92 return (
93 <>
94 <Grid.Item
95 full
96 as={ForwardButton}
97 disabled={!isActiveOwner}
98 onClick={goPartiesSetPoolSize}>
99 Manage Invite Pools
100 </Grid.Item>
101 <Grid.Divider />
102 </>
103 );
104 }
106 return null;
107 })();
109 const senateButton = (() => {
110 if (azimuth.getPointSize(point) !== azimuth.PointSize.Galaxy) {
111 return null;
112 }
113 return (
114 <>
115 <Grid.Item
116 full
117 as={ForwardButton}
118 disabled={!canVote}
119 onClick={goSenate}>
120 Senate
121 </Grid.Item>
122 <Grid.Divider />
123 </>
124 );
125 })();
127 // sync the current cursor
128 useSyncOwnedPoints([point]);
130 const address = need.addressFromWallet(wallet);
132 return (
133 <View pop={pop} inset>
134 <Greeting point={point} />
135 <Passport
136 point={Just(point)}
137 address={Just(address)}
138 animationMode={'slide'}
139 />
140 <Grid gap={3}>
141 {isPlanet && hasInvites && (
142 <>
143 <Grid.Item cols={[1, 11]}>
144 Invite Group
145 <br />
146 </Grid.Item>
148 <Grid.Item
149 className={cn('t-right underline pointer-hover', {
150 gray4: sentInvites.getOrElse(0) === 0,
151 })}
152 onClick={goCohort}
153 cols={[11, 13]}>
154 View
155 </Grid.Item>
156 <Grid.Item full>
157 <Flex align="center">
158 <Flex.Item>
159 {acceptedInvites.getOrElse(0)} / {_totalInvites}
160 </Flex.Item>
161 {_pendingInvites > 0 && (
162 <Flex.Item as={Chip} className="bg-yellow1 yellow4">
163 {_pendingInvites} pending
164 </Flex.Item>
165 )}
166 </Flex>
167 </Grid.Item>
169 {showInvites && (
170 <>
171 <Grid.Item
172 full
173 as={BarGraph}
174 available={availableInvites}
175 sent={sentInvites}
176 accepted={acceptedInvites}
177 />
178 <Grid.Item
179 full
180 as={InviteSigilList}
181 pendingPoints={pendingPoints}
182 acceptedPoints={acceptedPoints}
183 />
184 </>
185 )}
186 {!showInvites && (
187 <>
188 <Grid.Item full className="b-gray4 b-dotted b1 self-center">
189 <div className="p4 pv8 t-center gray4">
190 Start your invite group by adding members
191 </div>
192 </Grid.Item>
193 </>
194 )}
195 {!showInviteForm && availableInvites.getOrElse(0) > 0 && (
196 <Grid.Item
197 full
198 solid
199 as={Button}
200 center
201 onClick={() => setShowInviteForm(true)}>
202 Add Members
203 </Grid.Item>
204 )}
205 {showInviteForm && <Inviter />}
206 <Grid.Item full className="mb2" />
207 </>
208 )}
209 {!loadedInvites && isPlanet && (
210 <Grid.Item className="mv2" full>
211 Invite Group <Blinky />
212 </Grid.Item>
213 )}
214 </Grid>
215 <Grid className="pt2">
216 {inviteButton}
217 <Grid.Item full as={ForwardButton} onClick={goSigil}>
218 Sigil
219 </Grid.Item>
220 <Grid.Divider />
221 <Grid.Item
222 full
223 as={ForwardButton}
224 disabled={!canManage}
225 onClick={goUrbitOS}>
226 Urbit OS
227 </Grid.Item>
228 <Grid.Divider />
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>
252 </View>
253 );