// NPM module imports
import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { MetroSpinner } from "react-spinners-kit";
// File imports
import { signOut, welcomePageComplete } from "../../store/actions/index";
import * as alertBarTypes from "../../components/AlertBar/alertBarTypes";
import firebase from "../../vendors/Firebase/firebase";
import { authError } from "../../vendors/Firebase/logs";
// Image imports
import logo from "../../assets/logos/tma-logo-white.png";
import downArrow from "../../assets/icons/down-arrow-white.svg";
// Component imports
import RectangularButton from "../../components/Buttons/RectangularButton/RectangularButton";
import AlertBar from "../../components/AlertBar/AlertBar";
// Style imports
import styles from "./Welcome.module.scss";
/**
* Renders the Welcome component.
* This component displays when a user needs to confirm their email.
* @extends {Component}
* @component
* @category Welcome
* @author Dan Levy <danlevy124@gmail.com>
*/
class Welcome extends Component {
/**
* Welcome component state
* @property {boolean} isLoading - Indicates if the component is in a loading state
* @property {boolean} isUserEmailVerified - Indicates if the user's email is verified
*/
state = {
isLoading: false,
isUserEmailVerified: false,
};
/**
* Indicates if the user's email was checked for verification at least once
*/
_wasEmailVerificationCheckedAlready = false;
/**
* Checks if the user's email is verified
*/
componentDidMount() {
this.checkIfUserEmailIsVerified();
}
/**
* Checks if the user's email is verified.
* Updates state depending on result.
* @function
*/
checkIfUserEmailIsVerified = () => {
// Sets loading to true in state
this.setState({ isLoading: true });
// Reloads the user and checks if the user's email is verified
const currentUser = firebase.auth().currentUser;
currentUser
.reload()
.then(() => {
if (currentUser.emailVerified) {
this.userEmailIsVerified();
} else {
this.userEmailNotVerified();
}
this._wasEmailVerificationCheckedAlready = true;
})
.catch(this.userEmailFetchError);
};
/**
* Updates state to indicate that the email is verified
* @function
*/
userEmailIsVerified = () => {
this.setState({ isLoading: false, isUserEmailVerified: true });
};
/**
* Updates state to indicate that the email is not verified
* Alerts the user that the email is not verified
* @function
*/
userEmailNotVerified = () => {
// Updates state
this.setState({
isLoading: false,
isUserEmailVerified: false,
});
// Alerts the user only if this is not the first check
if (this._wasEmailVerificationCheckedAlready) {
this.setState({
alert: {
type: alertBarTypes.WARNING,
heading: "Not Verified",
message: `Your email is not verified. If you can't find the verification email, please click "Resend Email."`,
},
});
}
};
/**
* Updates the state to indicate that the email is not verified.
* Alerts the user that there was an error.
* @function
* @param {object} error - The error received
*/
userEmailFetchError = (error) => {
authError(error.code, error.message, "[Welcome/userEmailFetchError]");
this.setState({
isLoading: false,
alert: {
type: alertBarTypes.ERROR,
heading: "Error",
message: error.message,
},
});
};
/**
* Tells Redux that this component is no longer needed (i.e. done)
* @function
*/
doneButtonClickedHandler = () => {
this.props.done();
};
/**
* Resends an email verification
* @function
*/
resendEmailVerificationButtonClickedHandler = () => {
// Sets loading to true in state
this.setState({ isLoading: true });
// Sends an email verification
firebase
.auth()
.currentUser.sendEmailVerification()
.then(this.emailWasSentHandler)
.catch(this.userEmailFetchError);
};
/**
* Updates state to indicate that a verification email was sent.
* Alerts the user that a verification email was sent.
* @function
*/
emailWasSentHandler = () => {
this.setState({
isLoading: false,
alert: {
type: alertBarTypes.INFO,
heading: "Email Sent",
message: "We have sent a new verification email",
},
});
};
/**
* Creates an alert bar if one was requested
* @function
* @returns {object} An alert bar (JSX)
*/
getAlertBar = () => {
return this.state.alert ? (
<AlertBar
type={this.state.alert.type}
heading={this.state.alert.heading}
message={this.state.alert.message}
done={() => this.setState({ alert: null })}
/>
) : null;
};
/**
* Gets the main component (loading spinner, success, or check email)
* @function
* @returns {object} The main component (JSX)
*/
getMainComponent = () => {
if (this.state.isLoading) {
return this.getSpinner();
} else if (this.state.isUserEmailVerified) {
return this.getSuccessComponent();
} else {
return this.getCheckEmailComponent();
}
};
/**
* Creates a spinner
* @function
* @returns {object} A spinner (JSX)
*/
getSpinner = () => {
return (
<div className={styles.welcomeMainSpinner}>
<MetroSpinner size={75} color="#F8F8F8" loading={true} />
</div>
);
};
/**
* Creates the success component
* @function
* @returns {object} A success component (JSX)
*/
getSuccessComponent = () => {
return (
<Fragment>
{/* Heading */}
<p className={styles.welcomeMainMessage}>
Your account has been created and a new experience awaits!
Click "Let's Go!" to add your first choir.
</p>
{/* Down arrow */}
<img
className={styles.welcomeMainDownArrow}
src={downArrow}
alt="Down Arrow"
/>
{/* Done Button */}
<div className={styles.welcomeMainButton}>
<RectangularButton
backgroundColor="orange"
type="button"
value=""
text="Let's Go!"
onClick={this.doneButtonClickedHandler}
/>
</div>
</Fragment>
);
};
/**
* Creates a check email component
* @function
* @returns {object} A check email component (JSX)
*/
getCheckEmailComponent = () => {
return (
<Fragment>
{/* Heading */}
<p className={styles.welcomeMainMessage}>
{`Please check your email (${
firebase.auth().currentUser.email
}) for a message from "The Music Assistant." Click the link to verify your email address and then come back here!`}
</p>
{/* Down arrow */}
<img
className={styles.welcomeMainDownArrow}
src={downArrow}
alt="Down Arrow"
/>
{/* Options */}
<div className={styles.welcomeMainButtons}>
<div className={styles.welcomeMainButton}>
<RectangularButton
backgroundColor="orange"
type="button"
value=""
text="I Verified My Email"
onClick={() => this.checkIfUserEmailIsVerified()}
/>
</div>
<div className={styles.welcomeMainButton}>
<RectangularButton
backgroundColor="blue"
type="button"
value=""
text="Resend Email"
onClick={
this.resendEmailVerificationButtonClickedHandler
}
/>
</div>
<div className={styles.welcomeMainButton}>
<RectangularButton
backgroundColor="red"
type="button"
value=""
text="Sign Out"
onClick={this.props.signOut}
/>
</div>
</div>
</Fragment>
);
};
/**
* Renders the Welcome component
* @returns {object} The JSX to render
*/
render() {
// Returns the JSX to render
return (
<div className={styles.welcome}>
{this.getAlertBar()}
{/* Page header */}
<div className={styles.welcomeHeader}>
<img
className={styles.welcomeHeaderLogo}
src={logo}
alt="Music Assistant Logo"
/>
<h1 className={styles.welcomeHeaderMessage}>
Welcome to <br /> The Music Assistant
</h1>
</div>
<div className={styles.welcomeMain}>
{this.getMainComponent()}
</div>
</div>
);
}
}
// Prop types for the Welcome component
Welcome.propTypes = {
/**
* Tells Redux that this component is no longer needed (i.e. done)
*/
done: PropTypes.func.isRequired,
/**
* Tells Redux to sign the user out
*/
signOut: PropTypes.func.isRequired,
};
/**
* Passes certain Redux actions to the Welcome component as props.
* This function is used only by the react-redux connect function.
* @memberof Welcome
* @param {function} dispatch - The react-redux dispatch function
* @returns {object} Redux actions used in the Welcome component
*/
const mapDispatchToProps = (dispatch) => {
return {
done: () => dispatch(welcomePageComplete()),
signOut: () => dispatch(signOut()),
};
};
export default connect(null, mapDispatchToProps)(Welcome);
Source