@@ -101,7 +101,7 @@ export default function InviteEmail() {
101 const { syncInvites, getInvites } = usePointCache();
101 const { syncInvites, getInvites } = usePointCache();
102 const { pointCursor } = usePointCursor();
102 const { pointCursor } = usePointCursor();
103 const point = need.point(pointCursor);
103 const point = need.point(pointCursor);
104− const { getHasRecieved, syncHasReceivedForEmail, sendMail } = useMailer();
104+ const { getHasReceived, syncHasReceivedForEmail, sendMail } = useMailer();
106 const { availableInvites } = getInvites(point);
106 const { availableInvites } = getInvites(point);
107 const maxInvitesToSend = availableInvites.matchWith({
107 const maxInvitesToSend = availableInvites.matchWith({
@@ -142,14 +142,14 @@ export default function InviteEmail() {
143 inputConfigs.map(config => {
143 inputConfigs.map(config => {
144 config.disabled = !canInput;
144 config.disabled = !canInput;
145− const hasReceivedError = getHasRecieved(config.name).matchWith({
145+ const hasReceivedError = getHasReceived(config.name).matchWith({
146 Nothing: () => null, // loading
146 Nothing: () => null, // loading
147 Just: p => p.value && HAS_RECEIVED_TEXT,
147 Just: p => p.value && HAS_RECEIVED_TEXT,
149 config.error = hasReceivedError || errors[config.name];
149 config.error = hasReceivedError || errors[config.name];
150 return config;
150 return config;
152− [inputConfigs, errors, canInput, getHasRecieved]
152+ [inputConfigs, errors, canInput, getHasReceived]
155 // construct the state of the set of inputs we're rendering below
155 // construct the state of the set of inputs we're rendering below
@@ -187,6 +187,27 @@ export default function InviteEmail() {
187 throw new Error('Internal Error: Missing Contracts/Web3/Wallet');
187 throw new Error('Internal Error: Missing Contracts/Web3/Wallet');
190+ //TODO want to do this on-input, but that gets weird. see #188
193+ inputs.map(async input => {
194+ const email = input.data;
195+ const hasReceived = getHasReceived(email).matchWith({
196+ Nothing: () => false, // loading
202+ [input.name]: `${email} has already received an invite.`,
207+ if (errorCount > 0) {
208+ throw new Error(`Some of these already have a point!`);
190 const nonce = await _web3.eth.getTransactionCount(_wallet.address);
211 const nonce = await _web3.eth.getTransactionCount(_wallet.address);
191 const chainId = await _web3.eth.net.getId();
212 const chainId = await _web3.eth.net.getId();
192 const planets = await azimuth.delegatedSending.getPlanetsToSend(
213 const planets = await azimuth.delegatedSending.getPlanetsToSend(
@@ -207,7 +228,6 @@ export default function InviteEmail() {
211 clearInvites();
231 clearInvites();
212 // NB(shrugs) - must be processed in serial because main thread, etc
232 // NB(shrugs) - must be processed in serial because main thread, etc
213 for (let i = 0; i < inputs.length; i++) {
233 for (let i = 0; i < inputs.length; i++) {
@@ -318,12 +338,18 @@ export default function InviteEmail() {
341+ const success = await sendMail(
321− await sendMail(invite.email, invite.ticket, invite.rawTx);
343+ invite.ticket,
346+ if (!success) throw new Error('Failed to send mail');
322 } catch (error) {
347 } catch (error) {
323 console.error(error);
348 console.error(error);
324 errorCount++;
349 errorCount++;
350+ //TODO make sure this actually gets displayed
325 addError({
351 addError({
326− [input.name]: `Mailing Failure for ${invite.email}`,
352+ [input.name]: `Mailing Failure for ${invite.email}, please send them this code manually: ${invite.ticket}`,