Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions public/static/locales/en/bulkCodes.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@
"importMethodText": {
"title": "Import File",
"subtitle": "Use this method if one of the following criteria match your use case:",
"details": ["I want to provide the Recipient's name or Email for each code.", "I want Plant-for-the-Planet to automatically email the recipients once it has been generated (optional).", "I want to issue codes for different tree counts."]
"details": [
"I want to provide the Recipient's name or Email for each code.",
"I want Plant-for-the-Planet to automatically email the recipients once it has been generated (optional).",
"I want to issue codes for different tree counts."
]
},
"genericMethodText": {
"title": "Create Generic Codes",
"subtitle": "Use this method if the following criteria matches your use case:",
"details": ["All codes will have the same value.", "I want to generate a number of code for arbitrary recipients.", "Names and Emails cannot be associated with the code."]
"details": [
"All codes will have the same value.",
"I want to generate a number of code for arbitrary recipients.",
"Names and Emails cannot be associated with the code."
]
},
"projectName": "Project Name",
"costPerUnit": "Cost per Unit",
Expand All @@ -31,6 +39,7 @@
"occasion": "Occasion",
"total": "Total",
"chargeConsentText": "By clicking Issue Codes, you agree that above amount will be charged to your account.",
"invalidEmailWarningText": "Please make sure that that recipient_email is a valid email. Using dummy or invalid emails will lead to account suspension in accordance with Platform terms and conditions.",
"projectRequired": "No project is selected.",
"unitsPerCodeRequired": "Each code should contain at least 1 unit.",
"codeQuantityRequired": "You need to create at least 1 code.",
Expand Down Expand Up @@ -61,7 +70,7 @@
"unitsNotProvided": "Units are missing/invalid for some recipients.",
"notifyNotPossible": "Email and name are missing for some recipients that are to be notified.",
"instructionRowError": "An error occurred on the 1st row. Please check if you have deleted the instructions, or if there is additional data.",
"invalidEmails": "The emails provided are invalid on the following rows: ",
"invalidEmails": "recipient_email contains dummy/invalid emails on the following rows: {{rowList}}. Please remove invalid emails or add valid emails.",
"generalError": "Something went wrong. Please try after a while."
},
"successUploadCSV": {
Expand All @@ -75,4 +84,4 @@
"planet_cash_payment_failure": "The transaction failed. {{reason}}",
"planet_cash_invalid_project": "You cannot make a donation to the selected project."
}
}
}
14 changes: 13 additions & 1 deletion src/features/user/BulkCodes/components/BulkGiftTotal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ interface BulkGiftTotalProps {
currency?: string;
units?: number;
unit?: string;
isImport?: boolean;
}

const BulkGiftTotal = ({
amount = 0,
currency,
units = 0,
unit = 'tree',
isImport = false,
}: BulkGiftTotalProps): ReactElement | null => {
const { t, ready, i18n } = useTranslation(['common', 'bulkCodes']);

Expand All @@ -43,7 +45,17 @@ const BulkGiftTotal = ({
currency as string,
amount
)} for ${units} ${getUnit(unit, units)}`}
helperText={t('bulkCodes:chargeConsentText')}
helperText={
<>
{t('bulkCodes:chargeConsentText')}
{isImport && (
<>
<br />
{t('bulkCodes:invalidEmailWarningText')}
</>
)}
</>
}
// TODOO translation and pluralization
></TextField>
);
Expand Down
12 changes: 6 additions & 6 deletions src/features/user/BulkCodes/components/RecipientsUploadForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '../BulkCodesTypes';

import styles from '../BulkCodes.module.scss';
import { isEmailValid } from '../../../../utils/isEmailValid';

const { Trans, useTranslation } = i18next;

Expand Down Expand Up @@ -126,19 +127,18 @@ const RecipientsUploadForm = ({
const invalidEmailIndexes: number[] = [];
recipients.forEach((recipient, index) => {
const { recipient_email } = recipient;
const emailRegex =
/^([a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)$/i;
if (!emailRegex.test(recipient_email) && recipient_email.length !== 0)
if (!isEmailValid(recipient_email) && recipient_email.length !== 0) {
invalidEmailIndexes.push(index + 1);
}
});

if (invalidEmailIndexes.length > 0) {
setParseError({
type: 'invalidEmails',
message: ready
? `${t(
'bulkCodes:errorUploadCSV.invalidEmails'
)} ${invalidEmailIndexes.join(', ')}`
? t('bulkCodes:errorUploadCSV.invalidEmails', {
rowList: invalidEmailIndexes.join(', '),
})
: '',
});
return false;
Expand Down
1 change: 1 addition & 0 deletions src/features/user/BulkCodes/forms/IssueCodesForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ const IssueCodesForm = ({}: IssueCodesFormProps): ReactElement | null => {
currency={planetCashAccount?.currency}
units={getTotalUnits()}
unit={project?.unit}
isImport={bulkMethod === 'import'}
/>
</div>

Expand Down
22 changes: 22 additions & 0 deletions src/utils/isEmailValid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const INVALID_DOMAIN_LIST = ['dummy.de', 'example.com', 'company.de'];

const generateInvalidEmailRegex = (): string => {
const startingPattern =
'^[a-zA-Z0-9_.+-]+@(?:(?:[a-zA-Z0-9-]+.)?[a-zA-Z]+.)?(';
const domainList = INVALID_DOMAIN_LIST.join('|');
const endingPattern = ')$';
return `${startingPattern}${domainList}${endingPattern}`;
};

const INVALID_DOMAIN_REGEX = new RegExp(generateInvalidEmailRegex(), 'i');
const EMAIL_FORMAT_REGEX =
/^([a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)$/i;

/**
* Validates provided email address for standard email format, and against excluded/invalid domains
* @param {string} email - Email address to be validated
* @returns boolean
*/
export const isEmailValid = (email: string): boolean => {
return EMAIL_FORMAT_REGEX.test(email) && !INVALID_DOMAIN_REGEX.test(email);
};