@@ -1,7 +1,10 @@
1−import React, { useCallback } from 'react';
2−import { Just } from 'folktale/maybe';
1+import React, { useCallback, useState } from 'react';
2+import { Just, Nothing } from 'folktale/maybe';
33import { Grid } from 'indigo-react';
44import { azimuth } from 'azimuth-js';
5+import cn from 'classnames';
6+import { take } from 'lodash';
7+import ob from 'urbit-ob';
58
69import { usePointCursor } from 'store/pointCursor';
710import { useWallet } from 'store/wallet';
@@ -13,6 +16,8 @@ import { ForwardButton, BootUrbitOSButton } from 'components/Buttons';
1316import CopyButton from 'components/CopyButton';
1417import { matchBlinky } from 'components/Blinky';
1518import DownloadSigilButton from 'components/DownloadSigilButton';
19+import BarGraph from 'components/BarGraph';
20+import MaybeSigil from 'components/MaybeSigil';
1621
1722import * as need from 'lib/need';
1823import useInvites from 'lib/useInvites';
@@ -21,6 +26,46 @@ import useCurrentPermissions from 'lib/useCurrentPermissions';
2126import { useLocalRouter } from 'lib/LocalRouter';
2227import useKeyfileGenerator from 'lib/useKeyfileGenerator';
2328
29+import InviteCohort from 'views/Invite/Cohort';
30+
31+const InviteSigilList = ({ className, pendingPoints, acceptedPoints }) => {
32+ const _acceptedPoints = take(
33+ acceptedPoints.getOrElse([]).map(x => Just(ob.patp(x))),
34+ 6
35+ );
36+
37+ const _pendingPoints = take(
38+ pendingPoints.getOrElse([]).map(x => Just(ob.patp(x))),
39+ 6 - _acceptedPoints.length
40+ );
41+
42+ const empty = [
43+ ...Array(
44+ Math.max(6 - _acceptedPoints.length - _pendingPoints.length, 0)
45+ ).keys(),
46+ ].map(() => Nothing());
47+
48+ const renderSigil = (points, colors, klassName) => {
49+ return (
50+ <>
51+ {points.map((point, idx) => (
52+ <div className={cn(klassName, 'h9 w9')}>
53+ <MaybeSigil patp={point} size={50} colors={colors} />
54+ </div>
55+ ))}
56+ </>
57+ );
58+ };
59+
60+ return (
61+ <div className={cn('flex justify-between', className)}>
62+ {renderSigil(_acceptedPoints, ['#000000', '#FFFFFF'])}
63+ {renderSigil(_pendingPoints, ['#ee892b', '#FFFFFF'])}
64+ {renderSigil(empty, [], 'b1 b-black')}
65+ </div>
66+ );
67+};
68+
2469export default function Point() {
2570 const { pop, push, names } = useLocalRouter();
2671 const { pointCursor } = usePointCursor();
@@ -38,7 +83,22 @@ export default function Point() {
3883 } = useCurrentPermissions();
3984
4085 // fetch the invites for the current cursor
41− const { availableInvites } = useInvites(point);
86+ const invites = useInvites(point);
87+ const {
88+ availableInvites,
89+ sentInvites,
90+ acceptedInvites,
91+ pendingPoints,
92+ acceptedPoints,
93+ } = invites;
94+
95+ const showInvites = !(
96+ acceptedInvites.getOrElse(0) === 0 && sentInvites.getOrElse(0) === 0
97+ );
98+
99+ const hasInvites = showInvites || availableInvites.getOrElse(0) !== 0;
100+ //&&
101+ // availableInvites.getOrElse(0) === 0
42102
43103 const goAdmin = useCallback(() => push(names.ADMIN), [push, names]);
44104
@@ -54,6 +114,10 @@ export default function Point() {
54114 push,
55115 ]);
56116
117+ const isPlanet = azimuth.getPointSize(point) === azimuth.PointSize.Planet;
118+
119+ const [showInviteForm, setShowInviteForm] = useState(false);
120+
57121 const inviteButton = (() => {
58122 switch (azimuth.getPointSize(point)) {
59123 case azimuth.PointSize.Planet:
@@ -103,6 +167,52 @@ export default function Point() {
103167 address={Just(address)}
104168 animationMode={'slide'}
105169 />
170+ <Grid gap={3}>
171+ {isPlanet && hasInvites && (
172+ <>
173+ <Grid.Item full>
174+ Invite Group
175+ <br />
176+ </Grid.Item>
177+ {showInvites && (
178+ <>
179+ <Grid.Item
180+ full
181+ as={BarGraph}
182+ available={availableInvites}
183+ sent={sentInvites}
184+ accepted={acceptedInvites}
185+ />
186+ <Grid.Item
187+ full
188+ as={InviteSigilList}
189+ pendingPoints={pendingPoints}
190+ acceptedPoints={acceptedPoints}
191+ />
192+ </>
193+ )}
194+ {!showInvites && (
195+ <>
196+ <Grid.Item full className="b-gray4 b-dotted b1 self-center">
197+ <div className="p4 pv8 t-center gray4">
198+ Start your invite group by adding members
199+ </div>
200+ </Grid.Item>
201+ </>
202+ )}
203+ {!showInviteForm && availableInvites.getOrElse(0) > 0 && (
204+ <Grid.Item
205+ full
206+ solid
207+ as={ForwardButton}
208+ onClick={() => setShowInviteForm(true)}>
209+ Add Members
210+ </Grid.Item>
211+ )}
212+ {showInviteForm && <InviteCohort />}
213+ </>
214+ )}
215+ </Grid>
106216 <Grid className="pt2">
107217 {inviteButton}
108218 <Grid.Item