@@ -6,7 +6,6 @@ import { Grid, Flex, Input, IconButton, HelpText, Text } from 'indigo-react';
6import { uniq } from 'lodash';
6import { uniq } from 'lodash';
8import * as need from 'lib/need';
8import * as need from 'lib/need';
9−import { hasReceived, sendMail } from 'lib/inviteMail';
10import * as wg from 'lib/walletgen';
9import * as wg from 'lib/walletgen';
12// for transaction generation and signing
11// for transaction generation and signing
@@ -35,6 +34,7 @@ import { usePointCache } from 'store/pointCache';
35import { useWallet } from 'store/wallet';
34import { useWallet } from 'store/wallet';
36import useSetState from 'lib/useSetState';
35import useSetState from 'lib/useSetState';
37import pluralize from 'lib/pluralize';
36import pluralize from 'lib/pluralize';
37+import useMailer from 'lib/useMailer';
39const kStubMailer = process.env.REACT_APP_STUB_MAILER === 'true';
39const kStubMailer = process.env.REACT_APP_STUB_MAILER === 'true';
@@ -89,10 +89,10 @@ const buildAccessoryFor = (dones, errors) => name => (
92−// TODO: refactor transactions + mailer into hooks
92+// TODO: how to handle dependency loop between inputConfigs and hasReceived?
93+// TODO: test with tank, successful txs
93// TODO: put accessory inside of input
94// TODO: put accessory inside of input
94−// TODO: implement hasReceived cache with useHasReceived
95−export default function NewInviteEmail() {
95+export default function InviteEmail() {
96 // TODO: resumption after error?
96 // TODO: resumption after error?
97 const { pop } = useLocalRouter();
97 const { pop } = useLocalRouter();
98 const { contracts, web3, networkType } = useNetwork();
98 const { contracts, web3, networkType } = useNetwork();
@@ -115,10 +115,10 @@ export default function NewInviteEmail() {
115 buildInputConfig
115 buildInputConfig
118− const [hovered, setHovered] = useSetState({});
118+ const [hovered, setHovered] = useSetState();
119− const [invites, addInvite, clearInvites] = useSetState({});
119+ const [invites, addInvite, clearInvites] = useSetState();
120− const [receipts, addReceipt, clearReceipts] = useSetState({});
120+ const [receipts, addReceipt, clearReceipts] = useSetState();
121− const [errors, addError, clearError] = useSetState({});
121+ const [errors, addError, clearError] = useSetState();
123 const [status, setStatus] = useState(STATUS.INPUT);
123 const [status, setStatus] = useState(STATUS.INPUT);
124 const [needFunds, setNeedFunds] = useState(null);
124 const [needFunds, setNeedFunds] = useState(null);
@@ -136,13 +136,16 @@ export default function NewInviteEmail() {
137 inputConfigs.map(config => {
137 inputConfigs.map(config => {
138 config.disabled = !canInput;
138 config.disabled = !canInput;
139− console.log(config.name, errors[config.name]);
140 config.error = errors[config.name];
139 config.error = errors[config.name];
141 return config;
140 return config;
143 [inputConfigs, errors, canInput]
142 [inputConfigs, errors, canInput]
145 const { inputs, pass } = useForm(dynamicConfigs);
144 const { inputs, pass } = useForm(dynamicConfigs);
145+ const emails = useMemo(() => inputs.map(i => i.data).filter(d => !!d), [
148+ const { getHasRecieved, sendMail } = useMailer(emails);
147 const canAddInvite = canInput && inputs.length < maxInvitesToSend;
150 const canAddInvite = canInput && inputs.length < maxInvitesToSend;
148 const allPass = pass && !generalError;
151 const allPass = pass && !generalError;
@@ -379,13 +382,12 @@ export default function NewInviteEmail() {
379 }, [canGenerate, canSend, onClickGenerate, onClickSend]);
382 }, [canGenerate, canSend, onClickGenerate, onClickSend]);
381 useEffect(() => {
384 useEffect(() => {
382− const emails = inputs.map(i => i.data).filter(d => !!d);
383 if (uniq(emails).length !== emails.length) {
385 if (uniq(emails).length !== emails.length) {
384 setGeneralError(new Error(`Duplicate email.`));
386 setGeneralError(new Error(`Duplicate email.`));
386 setGeneralError(null);
388 setGeneralError(null);
388− }, [inputs]);
390+ }, [emails]);
391 <Grid gap={12}>
393 <Grid gap={12}>