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
3 changes: 2 additions & 1 deletion public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@
"verifyEmailHeader":"Please confirm your email.",
"verifyEmailText":"To secure your account, we need to verify your email. Please check your inbox or spam/junk folder for a confirmation email and then continue to login.",
"verifyEmailInfo":"If you didn’t receive an email please try logging in again and we’ll send you another email.",
"continueToLogin":"Continue to Login"
"continueToLogin":"Continue to Login",
"plantedBy":"Planted by"
}
8 changes: 8 additions & 0 deletions public/static/locales/en/redeem.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"myPlantedTreesByOrg": "My {{count}} tree will be planted by {{tpoName}}",
"myPlantedTreesByOrg_plural": "My {{count}} trees will be planted by {{tpoName}}",
"congratulations":"Congratulations!",
"addToMyTrees":"Add to my trees",
"validateCode":"Validate Code",
"enterRedeemCode": "Please enter a code to redeem"
}
244 changes: 233 additions & 11 deletions src/features/user/UserProfile/components/RedeemModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,130 @@ import Backdrop from '@material-ui/core/Backdrop';
import Fade from '@material-ui/core/Fade';
import MaterialTextField from '../../../common/InputTypes/MaterialTextField';
import i18next from '../../../../../i18n';
import { postAuthenticatedRequest } from '../../../../utils/apiRequests/api';
import { useForm } from 'react-hook-form';
import { useAuth0 } from '@auth0/auth0-react';
import Close from '../../../../../public/assets/images/icons/headerIcons/close';
import ShareOptions from '../../../donations/components/ShareOptions';
import Snackbar from '@material-ui/core/Snackbar';
import MuiAlert, { AlertProps } from '@material-ui/lab/Alert';
import tenantConfig from '../../../../../tenant.config';


const {useTranslation} = i18next;
const { useTranslation } = i18next;
export default function RedeemModal({
redeemModalOpen,
handleRedeemModalClose,
}: any) {
const {t} = useTranslation(['me', 'common'])
const { t } = useTranslation(['me', 'common', 'donate','redeem']);

const config = tenantConfig();

const {
isLoading,
isAuthenticated,
getAccessTokenSilently
} = useAuth0();

const imageRef = React.createRef();
const sendRef = () => imageRef;

const [errorMessage, setErrorMessage] = React.useState()
const [codeValidated, setCodeValidated] = React.useState(false)
const [isUploadingData, setIsUploadingData] = React.useState(false);
const [validCodeData, setValidCodeData] = React.useState();
const [codeRedeemed, setCodeRedeemed] = React.useState(false);
const [code, setCode] = React.useState();
const [textCopiedsnackbarOpen, setTextCopiedSnackbarOpen] = React.useState(
false,
);
const handleTextCopiedSnackbarOpen = () => {
setTextCopiedSnackbarOpen(true);
};

const handleTextCopiedSnackbarClose = (
event?: React.SyntheticEvent,
reason?: string,
) => {
if (reason === 'clickaway') {
return;
}
setTextCopiedSnackbarOpen(false);
};

function Alert(props: AlertProps) {
return <MuiAlert elevation={6} variant="filled" {...props} />;
}

const {
register,
handleSubmit,
errors,
getValues
} = useForm({ mode: 'onBlur' });

async function validateCode(data: any) {
setIsUploadingData(true)
const submitData = {
type: 'gift',
code: data.code
}
if (!isLoading && isAuthenticated) {
let token = await getAccessTokenSilently();
let userLang = localStorage.getItem('language') || 'en';
postAuthenticatedRequest(`/api/v1.3/${userLang}/validateCode`, submitData, token).then((res) => {
if (res.code === 401) {
setErrorMessage(res.message);
setIsUploadingData(false)
}
else if (res.status === 'error') {
setErrorMessage(res.errorText);
setIsUploadingData(false)
}
else if (res.status === 'success') {
setCode(data.code)
setCodeValidated(true);
setValidCodeData(res)
setIsUploadingData(false)
}
})
}
}

async function redeemCode() {
setIsUploadingData(true)
const submitData = {
type: 'gift',
code: code
}
if (!isLoading && isAuthenticated) {
let token = await getAccessTokenSilently();
let userLang = localStorage.getItem('language') || 'en';
postAuthenticatedRequest(`/api/v1.3/${userLang}/convertCode`, submitData, token).then((res) => {
console.log('Result', res);
if (res.code === 401) {
setErrorMessage(res.message);
setIsUploadingData(false)
}
else if (res.response.status === 'error') {
setErrorMessage(res.errorText);
setIsUploadingData(false)
}
else if (res.response.status === 'success') {
setCodeRedeemed(true);
setIsUploadingData(false);
setCodeValidated(false);
}
})
}
}

const closeRedeem = () => {
setCodeValidated(false);
setCodeRedeemed(false);
handleRedeemModalClose()
}

return (
<Modal
className={styles.modalContainer}
Expand All @@ -27,15 +143,121 @@ export default function RedeemModal({
}}
>
<Fade in={redeemModalOpen}>
<div className={styles.modal}>
<h4>
<b> {t('me:redeem')} </b>
</h4>
<div className={styles.inputField}>
<MaterialTextField placeholder="pp.eco/XADSA-DS-AS" label="" variant="outlined" />
</div>
<div className={styles.continueButton}>{t('common:continue')}</div>
</div>

{codeRedeemed && validCodeData ? (
<>
<div className={styles.modalFinal}>
<div className={styles.header}>
<div onClick={() => closeRedeem()} className={styles.headerCloseIcon}>
<Close />
</div>
<div className={styles.headerTitle}>
{t('redeem:congratulations')}
</div>
</div>

<div className={styles.thankyouImageContainer}>
<div className={styles.thankyouImage}>
<div className={styles.thankyouImageHeader}>
<p dangerouslySetInnerHTML={{ __html: t('donate:thankyouHeaderText') }} />
</div>
<div className={styles.donationCount}>
{t('redeem:myPlantedTreesByOrg', { count: validCodeData.treeCount,tpoName:validCodeData.tpos[0].tpoName })}
<p className={styles.donationTenant}>
{t('donate:plantTreesAtURL', { url: config.tenantURL })}
</p>
</div>
</div>
</div>

{/* hidden div for image download */}
<div style={{ width: '0px', height: '0px', overflow: 'hidden' }}>
<div className={styles.tempThankYouImage} ref={imageRef}>
<div className={styles.tempthankyouImageHeader}>
<p dangerouslySetInnerHTML={{ __html: t('donate:thankyouHeaderText') }} />
</div>
<p className={styles.tempDonationCount}>
{t('redeem:myPlantedTreesByOrg', { count: validCodeData.treeCount,tpoName:validCodeData.tpos[0].tpoName })}
</p>
<p className={styles.tempDonationTenant}>
{t('donate:plantTreesAtURL', { url: config.tenantURL })}
</p>
</div>
</div>

<div className={styles.shareOptions}>
<ShareOptions
treeCount={validCodeData.treeCount}
sendRef={sendRef}
handleTextCopiedSnackbarOpen={handleTextCopiedSnackbarOpen}
/>
</div>

<Snackbar
open={textCopiedsnackbarOpen}
autoHideDuration={4000}
onClose={handleTextCopiedSnackbarClose}
>
<Alert onClose={handleTextCopiedSnackbarClose} severity="success">
{t('donate:copiedToClipboard')}
</Alert>
</Snackbar>

</div>
</>
) : (
<div className={styles.modal}>
{codeValidated && validCodeData ? (
<>
<div className={styles.codeTreeCount}>
{validCodeData.treeCount}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format this number once this branch and #526 is merged!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a reminder for myself at #549

<span>{t('common:trees')}</span>
</div>

<div className={styles.plantedBy}>
<span>{t('common:plantedBy')}</span>
<p>{validCodeData.tpos[0].tpoName}</p>
</div>

<div onClick={handleSubmit(redeemCode)} className={styles.continueButton}>
{isUploadingData ? (
<div className={styles.spinner}></div>
) : (t('redeem:addToMyTrees'))}
</div>
</>
) : (
<>
<h4>
{t('me:redeem')}
</h4>

<div className={styles.inputField}>
<MaterialTextField inputRef={register({
required: {
value: true,
message: t('redeem:enterRedeemCode'),
}
})} name={'code'} placeholder="XAD-1SA-5F1-A" label="" variant="outlined" />

</div>
{errors.code && (
<span className={styles.formErrors}>{errors.code.message}</span>
)}

{errorMessage && (
<span className={styles.formErrors}>{errorMessage}</span>
)}
<div onClick={handleSubmit(validateCode)} className={styles.continueButton}>
{isUploadingData ? (
<div className={styles.spinner}></div>
) : (t('redeem:validateCode'))}
</div>
</>
)}

</div>
)}

</Fade>
</Modal>
);
Expand Down
Loading