@@ -9,22 +9,16 @@ import { usePointCache } from 'store/pointCache';
99import { useWallet } from 'store/wallet';
1010
1111import View from 'components/View';
12−import Tabs from 'components/Tabs';
13−import BarGraph from 'components/BarGraph';
1412import MaybeSigil from 'components/MaybeSigil';
1513import { matchBlinky } from 'components/Blinky';
16−import Chip from 'components/Chip';
1714
1815import { useLocalRouter } from 'lib/LocalRouter';
1916import useInvites from 'lib/useInvites';
2017import * as need from 'lib/need';
2118import * as wg from 'lib/walletgen';
2219
23−import Inviter from 'views/Invite/Inviter';
24−
2520import { ReactComponent as SearchIcon } from 'assets/search.svg';
2621import CopyButton from 'components/copiable/CopyButton';
27−import { useSyncDetails } from 'lib/useSyncPoints';
2822import { useNetwork } from 'store/network';
2923import L2BackHeader from 'components/L2/Headers/L2BackHeader';
3024import Window from 'components/L2/Window/Window';
@@ -33,7 +27,6 @@ import { Icon, Row, StatelessTextInput } from '@tlon/indigo-react';
3327import BodyPane from 'components/L2/Window/BodyPane';
3428import { useRollerStore } from 'store/roller';
3529import useRoller from 'lib/useRoller';
36−import { convertToInt } from 'lib/convertToInt';
3730import FeeDropdown from 'components/L2/Dropdowns/FeeDropdown';
3831import LoadingOverlay from 'components/L2/LoadingOverlay';
3932import { generateUrl } from 'lib/utils/invite';
@@ -41,6 +34,7 @@ import CopiableWithTooltip from 'components/copiable/CopiableWithTooltip';
4134import Paginator from 'components/L2/Paginator';
4235
4336import './Cohort.scss';
37+import useInviter from 'lib/useInviter';
4438
4539const INVITES_PER_PAGE = 7;
4640const DEFAULT_NUM_INVITES = 5;
@@ -298,69 +292,57 @@ export default function InviteCohort() {
298292 currentL2,
299293 pendingTransactions,
300294 invites,
301− setInvites,
302295 } = useRollerStore();
303− const { generateInviteCodes } = useRoller();
296+ const { generateInvites } = useInviter();
297+ const { generateInviteCodes, getPendingTransactions } = useRoller();
304298
305299 const { pointCursor } = usePointCursor();
306300 const point = need.point(pointCursor);
307301
308− const _point = convertToInt(need.point(pointCursor), 10);
309302 const [page, setPage] = useState(0);
310303
311− const invitesToDisplay = invites.slice(
304+ const { pendingPoints } = useInvites(point);
305+
306+ const displayedInvites = currentL2 ? invites : pendingPoints.getOrElse([]);
307+
308+ const invitesToDisplay = displayedInvites.slice(
312309 page * INVITES_PER_PAGE,
313310 (page + 1) * INVITES_PER_PAGE
314311 );
315312
316− const {
317− acceptedInvites,
318− acceptedPoints,
319− pendingPoints,
320− availableInvites,
321− sentInvites,
322− } = useInvites(point);
323−
324313 const hasPending = Boolean(pendingTransactions.length);
325− const hasInvites = Boolean(invites.length);
314+ const hasInvites = Boolean(displayedInvites.length);
326315
327316 const [numInvites, setNumInvites] = useState(DEFAULT_NUM_INVITES);
328317 const [showInviteForm, setShowInviteForm] = useState(false);
329− const [tab, setTab] = useState(NAMES.ALL);
330318 const [loading, setLoading] = useState(false);
331319 const [error, setError] = useState(null);
332320
333− const _acceptedPoints = acceptedPoints.getOrElse([]);
334− const _pendingPoints = pendingPoints.getOrElse([]);
335− const _pendingInvites = _pendingPoints.length;
336− const _acceptedInvites = _acceptedPoints.length;
337− const _totalInvites = availableInvites
338− .map(a => sentInvites.getOrElse(0) + a)
339− .getOrElse(0);
340−
341− const [selectedInvite, _setSelectedInvite] = useState();
342−
343− useSyncDetails([..._acceptedPoints, ..._pendingPoints]);
344−
345− const setSelectedInvite = useCallback(
346− p => _setSelectedInvite(old => (old === p ? null : p)),
347− []
348− );
349−
350− const generateInvites = useCallback(async () => {
321+ const createInvites = useCallback(async () => {
351322 setLoading(true);
352323 try {
353− const invites = await generateInviteCodes(numInvites);
354− console.log('INVITES', invites)
355− // TODO: store these invites somewhere. How do I recover the invites for future use?
356− setInvites(invites);
324+ if (currentL2) {
325+ const invites = await generateInviteCodes(numInvites);
326+ console.log('INVITES', invites);
327+ getPendingTransactions(point);
328+ } else {
329+ const invites = await generateInvites(numInvites);
330+ console.log('INVITES', invites);
331+ }
357332 setShowInviteForm(false);
358333 } catch (error) {
359334 setError(error);
360335 } finally {
361336 setLoading(false);
362337 }
363− }, [generateInviteCodes, numInvites, setInvites]);
338+ }, [
339+ generateInviteCodes,
340+ numInvites,
341+ getPendingTransactions,
342+ point,
343+ generateInvites,
344+ currentL2,
345+ ]);
364346
365347 const getContent = () => {
366348 if (hasInvites) {
@@ -416,8 +398,8 @@ export default function InviteCohort() {
416398 const header = (
417399 <h5>
418400 You have
419− <span className="number-emphasis"> {invites.length} </span>
420− Planet Code{invites.length > 1 ? 's' : ''}
401+ <span className="number-emphasis"> {displayedInvites.length} </span>
402+ Planet Code{displayedInvites.length === 1 ? '' : 's'}
421403 </h5>
422404 );
423405
@@ -470,7 +452,7 @@ export default function InviteCohort() {
470452 className="generate-codes"
471453 center
472454 solid
473− onClick={generateInvites}>
455+ onClick={createInvites}>
474456 Generate Planet Codes ({numInvites})
475457 </Button>
476458 </div>
@@ -479,140 +461,57 @@ export default function InviteCohort() {
479461 <LoadingOverlay loading={loading} />
480462 </View>
481463 );
482− } else if (currentL2) {
483− return (
484− <View
485− pop={pop}
486− inset
487− className="cohort"
488− hideBack
489− header={<L2BackHeader />}>
490− <Window>
491− <HeaderPane>
492− {!hasInvites ? (
493− header
494− ) : (
495− <Row className="has-invites-header">
496− {header}
497− <div className="download-csv" onClick={() => null}>
498− <Icon icon="Download" />
499− <div>CSV</div>
500− </div>
501− </Row>
502− )}
503− </HeaderPane>
504− <BodyPane>
505− <div className={`content ${!hasInvites ? 'center' : ''}`}>
506− {getContent()}
507− </div>
508− {!hasPending && !hasInvites && (
509− <Button
510− as={'button'}
511− className="generate-button"
512− center
513− solid
514− onClick={() => setShowInviteForm(true)}>
515− Generate Codes
516− </Button>
517− )}
518− {hasInvites && (
519− <Paginator
520− page={page}
521− numPerPage={INVITES_PER_PAGE}
522− numElements={invites.length}
523− goPrevious={() => setPage(page - 1)}
524− goNext={() => setPage(page + 1)}
525− />
526− )}
527− </BodyPane>
528− </Window>
529− {(hasInvites || hasPending) && (
530− <Button
531− onClick={() => setShowInviteForm(true)}
532− className="add-more"
533− accessory={<Icon icon="ChevronEast" />}>
534− Add More
535− </Button>
536− )}
537− </View>
538− );
539464 }
540465
541466 return (
542− <View pop={pop} inset className="cohort" hideBack>
543− <Grid gap={3}>
544− <Grid.Item full>Invite Group</Grid.Item>
545− <Grid.Item full>
546− <Flex align="center">
547− <Flex.Item>
548− {_acceptedInvites} / {_totalInvites}
549− </Flex.Item>
550− {_pendingInvites !== 0 && (
551− <Flex.Item as={Chip} className="bg-yellow4 white">
552− {_pendingInvites} pending
553− </Flex.Item>
554− )}
555− </Flex>
556− </Grid.Item>
557− <Grid.Item
558− full
559− as={BarGraph}
560− available={availableInvites}
561− sent={sentInvites}
562− accepted={acceptedInvites}
563− />
564− {availableInvites.getOrElse(0) !== 0 && !showInviteForm && (
565− <Grid.Item
566− full
567− solid
568− center
569− as={Button}
570− onClick={() => setShowInviteForm(true)}>
571− Add Members
572− </Grid.Item>
573− )}
574− {showInviteForm && <Inviter />}
575−
576− {true && (
577− <Grid.Item
578− full
579− center
580− as={Tabs}
581− views={VIEWS}
582− options={OPTIONS}
583− currentTab={tab}
584− onTabChange={setTab}
585− acceptedPoints={_acceptedPoints}
586− pendingPoints={_pendingPoints}
587− onlyPending={tab === NAMES.PENDING}
588− onSelectInvite={setSelectedInvite}
589− />
590− )}
591− {selectedInvite && (
592− <Grid.Item
593− full
594− center
595− as={CohortMemberExpanded}
596− pending
597− point={selectedInvite}
598− onBack={() => setSelectedInvite(null)}
599− />
600− )}
601− </Grid>
467+ <View pop={pop} inset className="cohort" hideBack header={<L2BackHeader />}>
468+ <Window>
469+ <HeaderPane>
470+ {!hasInvites ? (
471+ header
472+ ) : (
473+ <Row className="has-invites-header">
474+ {header}
475+ <div className="download-csv" onClick={() => null}>
476+ <Icon icon="Download" />
477+ <div>CSV</div>
478+ </div>
479+ </Row>
480+ )}
481+ </HeaderPane>
482+ <BodyPane>
483+ <div className={`content ${!hasInvites ? 'center' : ''}`}>
484+ {getContent()}
485+ </div>
486+ {!hasPending && !hasInvites && (
487+ <Button
488+ as={'button'}
489+ className="generate-button"
490+ center
491+ solid
492+ onClick={() => setShowInviteForm(true)}>
493+ Generate Codes
494+ </Button>
495+ )}
496+ {hasInvites && (
497+ <Paginator
498+ page={page}
499+ numPerPage={INVITES_PER_PAGE}
500+ numElements={displayedInvites.length}
501+ goPrevious={() => setPage(page - 1)}
502+ goNext={() => setPage(page + 1)}
503+ />
504+ )}
505+ </BodyPane>
506+ </Window>
507+ {(hasInvites || hasPending) && (
508+ <Button
509+ onClick={() => setShowInviteForm(true)}
510+ className="add-more"
511+ accessory={<Icon icon="ChevronEast" />}>
512+ Add More
513+ </Button>
514+ )}
602515 </View>
603516 );
604517}
605−const NAMES = {
606− ALL: 'ALL',
607− PENDING: 'PENDING',
608−};
609−
610−const VIEWS = {
611− [NAMES.PENDING]: CohortList,
612− [NAMES.ALL]: CohortList,
613−};
614−
615−const OPTIONS = [
616− { text: 'All', value: NAMES.ALL },
617− { text: 'Pending', value: NAMES.PENDING },
618−];