Question

How can I add Newsletter in PWA Magento2 ?

Was it helpful?

Solution

This code is to add newsletter in the footer, the code is based on venia concept package. change as per your need.

Here you have to create REST Api module for newsletter in Magento, there is free module available you can use that https://github.com/regento/magento2-newsletter-api

Import Newsletter in Footer: src/components/Footer/footer.js

import Newsletter from '../Newsletter';

// Add below code in render() Method
<div className={classes.newsletter}>
    <Newsletter />
</div>

Create Newsletter Component, src/components/Newsletter/index.js

export { default as Newsletter } from './newsletter';
export { default } from './container';

src/components/Newsletter/newsletter.js

import React, { Component } from 'react';
import { func, shape, string } from 'prop-types';
import defaultClasses from './newsletter.css';
import classify from 'src/classify';

import Field from '../Field';
import Button from '../Button';
import { Form } from 'informed';
import TextInput from '../TextInput';
import Icon from '../Icon';
import MailIcon from 'react-feather/dist/icons/mail';
import combine from 'src/util/combineValidators';
import { validateEmail, isRequired } from 'src/util/formValidators';

class Newsletter extends Component {
    static propTypes = {
        classes: shape({
            actions: string,
            error: string,
            lead: string,
            root: string,
            form: string,
            subscribe: string,
            signUp: string,
            signUpTitle: string,
            signUpText: string,
            inputField: string,
            signUpPolicy: string,
            successMessage: string,
            inProgressMessage: string,
            errorMessage: string
        }),
        createAccountError: shape({
            message: string
        }),
        initialValues: shape({
            email: string,
            firstName: string,
            lastName: string
        })
    };

    static defaultProps = {
        initialValues: {}
    };

    get errorMessage() {
        const { createAccountError } = this.props;

        if (createAccountError) {
            const errorIsEmpty = Object.keys(createAccountError).length === 0;
            if (!errorIsEmpty) {
                return 'An error occurred. Please try again.';
            }
        }
    }

    get initialValues() {
        const { initialValues } = this.props;
        const { email, firstName, lastName, ...rest } = initialValues;

        return {
            customer: { email, firstname: firstName, lastname: lastName },
            ...rest
        };
    }

    handleFormSubmit = async ({ email }) => {
        this.props.signUpForNewsletter({ email });
    };

    render() {
        const { errorMessage, initialValues, props } = this;
        const { classes, isError, isInProgress, isSuccess } = props;
        const mail = <Icon src={MailIcon} size={16} />;

        if (isInProgress) {
            return (
                <div className={classes.root}>
                    <p className={classes.inProgressMessage}>
                        Sending your request...
                    </p>
                </div>
            );
        }

        if (isError) {
            return (
                <div className={classes.root}>
                    <p className={classes.errorMessage}>
                        Looks like you have already signed up, Thanks!
                    </p>
                </div>
            );
        }

        if (isSuccess) {
            return (
                <div className={classes.root}>
                    <p className={classes.successMessage}>
                        Thanks for signing up for our newsletter
                    </p>
                    <small className={classes.signUpPolicy}>
                        emails are subject to our
                        <a href="/privacy-policy"> Privacy Policy</a>
                    </small>
                </div>
            );
        }

        return (
            <div className={classes.root}>
                <h2 className={classes.signUpTitle}>Let's keep in touch</h2>
                <p className={classes.signUpText}>
                    <span>
                        Stay up-to-date with our newest products and best deals
                    </span>
                </p>
                <div className={classes.inputField}>
                    <Form
                        className={classes.form}
                        initialValues={initialValues}
                        onSubmit={this.handleFormSubmit}
                    >
                        <Field label="Email" required={true}>
                            <TextInput
                                field="email"
                                autoComplete="email"
                                validate={combine([isRequired, validateEmail])}
                                validateOnBlur
                                placeholder="Email"
                                label="Email"
                                before={mail}
                            />
                        </Field>
                        <div className={classes.error}>{errorMessage}</div>
                        <div className={classes.actions}>
                            <Button type="submit" priority="high">
                                {'Submit'}
                            </Button>
                        </div>
                    </Form>
                </div>
                <small className={classes.signUpPolicy}>
                    emails are subject to our
                    <a href="/privacy-policy"> Privacy Policy</a>
                </small>
            </div>
        );
    }
}

export default classify(defaultClasses)(Newsletter);

src/components/Newsletter/container.js

import { connect } from 'src/drivers';
import Newsletter from './newsletter';
import { signUpForNewsletter } from 'src/actions/newsletter';

const mapStateToProps = ({ newsletter }) => {
    const { isInProgress, isError, isSuccess } = newsletter;

    return {
        isInProgress,
        isError,
        isSuccess
    };
};

const mapDispatchToProps = {
    signUpForNewsletter
};

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Newsletter);

src/actions/newsletter/actions.js

import { createActions } from 'redux-actions';

const prefix = 'NEWSLETTER';

const actionMap = {
    SIGN_UP_FOR_NEWSLETTER: {
        REQUEST: null,
        RECEIVE: null
    },
    NEWSLETTER_ERROR: {
        REQUEST: null,
        RECEIVE: null
    }
};

export default createActions(actionMap, { prefix });

src/actions/newsletter/asyncActions.js

import { RestApi } from '@magento/peregrine';
import actions from './actions';

const { request } = RestApi.Magento2;

export const signUpForNewsletter = ({ email }) =>
    async function thunk(...args) {
        const [dispatch] = args;

        dispatch(actions.signUpForNewsletter.request(email));

        const body = {
            email: email
        };
        const response = await request('rest/V1/newsletter/subscribe', {
            method: 'POST',
            body: JSON.stringify(body)
        });

        console.log('newsletter action response', response);
        if (response.success == true) {
            await dispatch(actions.signUpForNewsletter.receive(response));
        }

        if (response.success == false) {
            await dispatch(actions.newsletterError.receive(response));
        }
    };

src/actions/newsletter/index.js

export { default } from './actions';
export * from './asyncActions';

src/reducers/index.js

import newsletter from './newsletter';

// Add in combineReducers
export default combineReducers({
    newsletter
});

src/reducers/newsletter.js

import { handleActions } from 'redux-actions';    
import actions from '../actions/newsletter';    
export const name = 'newsletter';

const initialState = {
    isInProgress: false,
    isError: false,
    isSuccess: false
};

const reducerMap = {
    [actions.signUpForNewsletter.request]: state => {
        return {
            ...state,
            isInProgress: true,
            isError: false
        };
    },
    [actions.signUpForNewsletter.receive]: state => {
        return {
            ...state,
            isInProgress: false,
            isSuccess: true
        };
    },
    [actions.newsletterError.receive]: state => {
        return {
            ...state,
            isInProgress: false,
            isError: true
        };
    }
};

export default handleActions(reducerMap, initialState);

src/components/Newsletter/newsletter.css

Add your CSS in this file

And it works, Hope this help.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top