@@ -1,16 +1,11 @@
1import { useCallback, useState } from 'react';
1import { useCallback, useState } from 'react';
2import { Button } from 'indigo-react';
2import { Button } from 'indigo-react';
3−import { Icon, Row, Box, LoadingSpinner } from '@tlon/indigo-react';
3+import { Icon, Row, Box, LoadingSpinner, Text, H3 } from '@tlon/indigo-react';
5import { useRollerStore } from 'store/rollerStore';
5import { useRollerStore } from 'store/rollerStore';
6import { useLocalRouter } from 'lib/LocalRouter';
6import { useLocalRouter } from 'lib/LocalRouter';
9− generateUrlAbbreviation,
7+import { generateUrl, generateUrlAbbreviation } from 'lib/utils/invite';
12−} from 'lib/utils/invite';
13−import { INVITES_PER_PAGE, DEFAULT_CSV_NAME } from 'lib/constants';
8+import { INVITES_PER_PAGE } from 'lib/constants';
14import { useTimerStore } from 'store/timerStore';
9import { useTimerStore } from 'store/timerStore';
15import { Invite } from 'lib/types/Invite';
10import { Invite } from 'lib/types/Invite';
16import { ddmmmYYYY } from 'lib/utils/date';
11import { ddmmmYYYY } from 'lib/utils/date';
@@ -24,8 +19,8 @@ import CopiableWithTooltip from 'components/copiable/CopiableWithTooltip';
24import Paginator from 'components/L2/Paginator';
19import Paginator from 'components/L2/Paginator';
26import './Cohort.scss';
21import './Cohort.scss';
27−import Modal from 'components/L2/Modal';
28−import { useInvites, useInviteStore } from './useInvites';
22+import { useInviteStore } from './useInvites';
23+import { CSVModal } from './CSVModal';
30export default function InviteCohort() {
25export default function InviteCohort() {
31 const { names, pop, push } = useLocalRouter();
26 const { names, pop, push } = useLocalRouter();
@@ -33,15 +28,11 @@ export default function InviteCohort() {
34 const { nextRoll } = useTimerStore();
29 const { nextRoll } = useTimerStore();
36− const { invites, generatingNum } = useInviteStore();
31+ const { invites, loading } = useInviteStore();
37− const { getInvites } = useInvites();
38 const currentL2 = Boolean(point.isL2Spawn);
32 const currentL2 = Boolean(point.isL2Spawn);
40− const [loading, setLoading] = useState(false);
41 const [showCsvModal, setShowCsvModal] = useState(false);
34 const [showCsvModal, setShowCsvModal] = useState(false);
42− const [csvElement, setCsvElement] = useState<HTMLAnchorElement | null>();
43 // TODO: do we need to read this error? currently unused
35 // TODO: do we need to read this error? currently unused
44− const [error, setError] = useState('');
45 const [page, setPage] = useState(0);
36 const [page, setPage] = useState(0);
47 const invitePoints = invites[point.value];
38 const invitePoints = invites[point.value];
@@ -54,40 +45,6 @@ export default function InviteCohort() {
54 const hasPending = Boolean(pendingTransactions.length);
45 const hasPending = Boolean(pendingTransactions.length);
55 const hasInvites = Boolean(invitePoints.length);
46 const hasInvites = Boolean(invitePoints.length);
57− const generateCsv = useCallback(() => {
58− const generateCsvElement = async () => {
60− setShowCsvModal(true);
61− const invites = await getInvites();
63− const csv = invites.reduce(
64− (csvData, { ticket, planet }, ind) =>
65− (csvData += generateCsvLine(ind, ticket, planet)),
66− 'Number,Planet,Invite URL,Point,Ticket\n'
68− document.getElementById('csv')?.remove();
69− const hiddenElement = document.createElement('a');
70− hiddenElement.href = `data:text/csv;charset=utf-8,${encodeURIComponent(
73− hiddenElement.target = '_blank';
74− hiddenElement.id = 'csv';
76− //provide the name for the CSV file to be downloaded
77− hiddenElement.download = generateCsvName(
79− point.patp?.slice(1) || 'bridge'
81− setCsvElement(hiddenElement);
83− setError('There was an error creating the CSV');
86− useInviteStore.setState({ generatingNum: 0 });
88− generateCsvElement();
89− }, [getInvites, setError, setLoading, setShowCsvModal, point]);
91 const goNextPage = useCallback(() => {
48 const goNextPage = useCallback(() => {
92 setPage(page + 1);
49 setPage(page + 1);
93 }, [page]);
50 }, [page]);
@@ -155,18 +112,28 @@ export default function InviteCohort() {
158− const header = (
115+ const header = () => {
118+ <Row alignItems="center">
119+ <LoadingSpinner dark />
120+ <H3 ml={2}>Checking and Updating Invites...</H3>
160− You have
127+ You have
161− <span className="number-emphasis"> {invitePoints.length} </span>
128+ <span className="number-emphasis"> {invitePoints.length} </span>
162− Invite Code{invitePoints.length === 1 ? '' : 's'}
129+ Invite Code{invitePoints.length === 1 ? '' : 's'}
166 const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
134 const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
167 const showAddMoreButton =
135 const showAddMoreButton =
168 (hasInvites || hasPending) && point.canSpawn && point.l2Quota > 0;
136 (hasInvites || hasPending) && point.canSpawn && point.l2Quota > 0;
169− const generatingCodesText = `Generating ${generatingNum} of ${invitePoints.length} codes...`;
@@ -178,11 +145,13 @@ export default function InviteCohort() {
179 <HeaderPane>
146 <HeaderPane>
180 {!hasInvites ? (
147 {!hasInvites ? (
183 <Row className="has-invites-header">
150 <Row className="has-invites-header">
184− {header}
151+ {header()}
185− <Row className="download-csv" onClick={generateCsv}>
153+ className="download-csv"
154+ onClick={() => setShowCsvModal(true)}>
186 <Icon icon="Download" />
155 <Icon icon="Download" />
187 <Box>CSV</Box>
156 <Box>CSV</Box>
@@ -230,40 +199,12 @@ export default function InviteCohort() {
230 <strong>{` ${ddmmmYYYY(nextQuotaTime)}`}</strong>.
199 <strong>{` ${ddmmmYYYY(nextQuotaTime)}`}</strong>.
232 ) : null}
201 ) : null}
233− <Modal show={showCsvModal} hide={() => setShowCsvModal(false)} hideClose>
205+ hide={() => setShowCsvModal(false)}
234− <Box className="download-csv-modal">
206+ hideClose
236− <Box>Download CSV</Box>
237− {loading && <Box>{generatingCodesText}</Box>}
239− <Row className="download-buttons">
244− className="ph4 close-button"
246− onClick={() => setShowCsvModal(false)}>
253− className="ph4 download-button"
256− onClick={() => csvElement?.click()}>
262− <Box className="csv-loading">
263− <LoadingSpinner background="#BCDCFF" foreground="#219DFF" />