@@ -49,6 +49,7 @@ import Paginator from 'components/L2/Paginator';
4949import InlineEthereumTransaction from 'components/InlineEthereumTransaction';
5050
5151import './Cohort.scss';
52+import Modal from 'components/L2/Modal';
5253
5354interface L1Invite {
5455 ticket: string;
@@ -89,6 +90,8 @@ export default function InviteCohort() {
8990 );
9091 const [showInviteForm, setShowInviteForm] = useState(false);
9192 const [loading, setLoading] = useState(false);
93+ const [showCsvModal, setShowCsvModal] = useState(false);
94+ const [csvElement, setCsvElement] = useState<HTMLAnchorElement | null>();
9295 const [error, setError] = useState('');
9396 const [l1Invite, setL1Invite] = useState<L1Invite | null>(null);
9497 const [page, setPage] = useState(0);
@@ -215,9 +218,10 @@ export default function InviteCohort() {
215218 point,
216219 ]);
217220
218− const downloadCsv = useCallback(() => {
219− const generateAndDownload = async () => {
221+ const generateCsv = useCallback(() => {
222+ const generateCsvElement = async () => {
220223 setLoading(true);
224+ setShowCsvModal(true);
221225 const invites = await getInvites();
222226 if (invites) {
223227 const csv = invites.reduce(
@@ -225,26 +229,35 @@ export default function InviteCohort() {
225229 (csvData += generateCsvLine(ind, ticket, planet)),
226230 'Number,Planet,Invite URL,Point,Ticket\n'
227231 );
232+ document.getElementById('csv')?.remove();
228233 const hiddenElement = document.createElement('a');
229234 hiddenElement.href = `data:text/csv;charset=utf-8,${encodeURIComponent(
230235 csv
231236 )}`;
232237 hiddenElement.target = '_blank';
238+ hiddenElement.id = 'csv';
233239
234240 //provide the name for the CSV file to be downloaded
235241 hiddenElement.download = generateCsvName(
236242 DEFAULT_CSV_NAME,
237243 point.patp?.slice(1) || 'bridge'
238244 );
239− hiddenElement.click();
245+ setCsvElement(hiddenElement);
240246 } else {
241247 setError('There was an error creating the CSV');
242248 }
243249 setLoading(false);
244250 setInviteGeneratingNum(0);
245251 };
246− generateAndDownload();
247− }, [getInvites, setError, setLoading, setInviteGeneratingNum, point]);
252+ generateCsvElement();
253+ }, [
254+ getInvites,
255+ setError,
256+ setLoading,
257+ setInviteGeneratingNum,
258+ setShowCsvModal,
259+ point,
260+ ]);
248261
249262 const goNextPage = useCallback(() => {
250263 setPage(page + 1);
@@ -425,7 +438,7 @@ export default function InviteCohort() {
425438 const showGenerateButton = !hasPending && !hasInvites && point.canSpawn;
426439 const showAddMoreButton =
427440 (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...`;
429442
430443 return (
431444 <View
@@ -441,7 +454,7 @@ export default function InviteCohort() {
441454 ) : (
442455 <Row className="has-invites-header">
443456 {header}
444− <Row className="download-csv" onClick={downloadCsv}>
457+ <Row className="download-csv" onClick={generateCsv}>
445458 <Icon icon="Download" />
446459 <Box>CSV</Box>
447460 </Row>
@@ -486,7 +499,36 @@ export default function InviteCohort() {
486499 <strong>{` ${ddmmmYYYY(nextQuotaTime)}`}</strong>.
487500 </Box>
488501 ) : null}
489− <LoadingOverlay loading={loading} text={generatingCodesText} />
502+ <Modal show={showCsvModal} hide={() => setShowCsvModal(false)} hideClose>
503+ <Box className="download-csv-modal">
504+ <Box>
505+ <Box>Download CSV</Box>
506+ {loading && <Box>{generatingCodesText}</Box>}
507+ </Box>
508+ <Row className="download-buttons">
509+ <Button
510+ center
511+ className="ph4 close-button"
512+ solid
513+ onClick={() => setShowCsvModal(false)}>
514+ Close
515+ </Button>
516+ <Button
517+ center
518+ className="ph4 download-button"
519+ disabled={loading}
520+ solid
521+ onClick={() => csvElement?.click()}>
522+ Download CSV
523+ </Button>
524+ </Row>
525+ </Box>
526+ {loading && (
527+ <Box className="csv-loading">
528+ <LoadingSpinner background="#BCDCFF" foreground="#219DFF" />
529+ </Box>
530+ )}
531+ </Modal>
490532 </View>
491533 );
492534}