@@ -49,6 +49,7 @@ import Paginator from 'components/L2/Paginator';
49import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
49import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
51import './Cohort.scss';
51import './Cohort.scss';
52+import Modal from 'components/L2/Modal';
53interface L1Invite {
54interface L1Invite {
54 ticket: string;
55 ticket: string;
@@ -89,6 +90,8 @@ export default function InviteCohort() {
90 const [showInviteForm, setShowInviteForm] = useState(false);
91 const [showInviteForm, setShowInviteForm] = useState(false);
91 const [loading, setLoading] = useState(false);
92 const [loading, setLoading] = useState(false);
93+ const [showCsvModal, setShowCsvModal] = useState(false);
94+ const [csvElement, setCsvElement] = useState<HTMLAnchorElement | null>();
92 const [error, setError] = useState('');
95 const [error, setError] = useState('');
93 const [l1Invite, setL1Invite] = useState<L1Invite | null>(null);
96 const [l1Invite, setL1Invite] = useState<L1Invite | null>(null);
94 const [page, setPage] = useState(0);
97 const [page, setPage] = useState(0);
@@ -215,9 +218,10 @@ export default function InviteCohort() {
218− const downloadCsv = useCallback(() => {
221+ const generateCsv = useCallback(() => {
219− const generateAndDownload = async () => {
222+ const generateCsvElement = async () => {
220 setLoading(true);
223 setLoading(true);
224+ setShowCsvModal(true);
221 const invites = await getInvites();
225 const invites = await getInvites();
222 if (invites) {
226 if (invites) {
223 const csv = invites.reduce(
227 const csv = invites.reduce(
@@ -225,26 +229,35 @@ export default function InviteCohort() {
225 (csvData += generateCsvLine(ind, ticket, planet)),
229 (csvData += generateCsvLine(ind, ticket, planet)),
226 'Number,Planet,Invite URL,Point,Ticket\n'
230 'Number,Planet,Invite URL,Point,Ticket\n'
232+ document.getElementById('csv')?.remove();
228 const hiddenElement = document.createElement('a');
233 const hiddenElement = document.createElement('a');
229 hiddenElement.href = `data:text/csv;charset=utf-8,${encodeURIComponent(
234 hiddenElement.href = `data:text/csv;charset=utf-8,${encodeURIComponent(
232 hiddenElement.target = '_blank';
237 hiddenElement.target = '_blank';
238+ hiddenElement.id = 'csv';
234 //provide the name for the CSV file to be downloaded
240 //provide the name for the CSV file to be downloaded
235 hiddenElement.download = generateCsvName(
241 hiddenElement.download = generateCsvName(
236 DEFAULT_CSV_NAME,
242 DEFAULT_CSV_NAME,
237 point.patp?.slice(1) || 'bridge'
243 point.patp?.slice(1) || 'bridge'
239− hiddenElement.click();
245+ setCsvElement(hiddenElement);
241 setError('There was an error creating the CSV');
247 setError('There was an error creating the CSV');
243 setLoading(false);
249 setLoading(false);
244 setInviteGeneratingNum(0);
250 setInviteGeneratingNum(0);
246− generateAndDownload();
252+ generateCsvElement();
247− }, [getInvites, setError, setLoading, setInviteGeneratingNum, point]);
257+ setInviteGeneratingNum,
249 const goNextPage = useCallback(() => {
262 const goNextPage = useCallback(() => {
250 setPage(page + 1);
263 setPage(page + 1);
@@ -425,7 +438,7 @@ export default function InviteCohort() {
425 const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
438 const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
426 const showAddMoreButton =
439 const showAddMoreButton =
427 (hasInvites || hasPending) && point.canSpawn && point.l2Quota > 0;
440 (hasInvites || hasPending) && point.canSpawn && point.l2Quota > 0;
428− const generatingCodesText = `Generating invite code ${inviteGeneratingNum} of ${invitePoints.length}...`;
441+ const generatingCodesText = `Generating ${inviteGeneratingNum} of ${invitePoints.length} codes...`;
@@ -441,7 +454,7 @@ export default function InviteCohort() {
442 <Row className="has-invites-header">
455 <Row className="has-invites-header">
444− <Row className="download-csv" onClick={downloadCsv}>
457+ <Row className="download-csv" onClick={generateCsv}>
445 <Icon icon="Download" />
458 <Icon icon="Download" />
446 <Box>CSV</Box>
459 <Box>CSV</Box>
@@ -486,7 +499,36 @@ export default function InviteCohort() {
486 <strong>{` ${ddmmmYYYY(nextQuotaTime)}`}</strong>.
499 <strong>{` ${ddmmmYYYY(nextQuotaTime)}`}</strong>.
488 ) : null}
501 ) : null}
502+ <Modal show={showCsvModal} hide={() => setShowCsvModal(false)} hideClose>
503+ <Box className="download-csv-modal">
505+ <Box>Download CSV</Box>
489− <LoadingOverlay loading={loading} text={generatingCodesText} />
506+ {loading && <Box>{generatingCodesText}</Box>}
508+ <Row className="download-buttons">
511+ className="ph4 close-button"
513+ onClick={() => setShowCsvModal(false)}>
518+ className="ph4 download-button"
521+ onClick={() => csvElement?.click()}>
527+ <Box className="csv-loading">
528+ <LoadingSpinner background="#BCDCFF" foreground="#219DFF" />