Source: pages/userProfile.js

import React from 'react';
import Person from '../components/user_profile/person';
import Information from '../components/user_profile/information';
import Amplify, { Auth, API, graphqlOperation, I18n, Storage } from "aws-amplify";
import * as queries from '../graphql/queries';
import * as customQueries from '../customGraphql/queries';
import * as mutations from '../graphql/mutations';
import { getUser, isLoggedIn, getLanguage } from '../services/auth';
import dict from "../components/dictionary/dictionary"
import { Layout, Skeleton, Menu, Icon, message, Button } from 'antd';
import PhotoUploader from '../components/user_profile/photoUploader';
import ResumeUploader from '../components/user_profile/resumeUploader';
import { Link, navigate } from "gatsby";
import BasicInfoForm from "../components/user_profile/basicInfoForm";
import AddEduForm from "../components/form/addEducation";
import AddExpForm from "../components/form/addExperience";
import UpdateAddressForm from "../components/form/updateAddress";
import CreateAddressForm from "../components/form/createAddress";
import { async } from 'q';
import "../style/userProfile.css";


// Some components from the ant-design
const { Header, Footer, Sider, Content } = Layout;
const SubMenu = Menu.SubMenu;

// The profile page of a user
/**
 * The class Profile will render the page of the user profile.
 * It will render the edit profile buttons if the user is viewing his own profile
 * It will not render the edit profile buttons if the user is viewing others profile
 */
class Profile extends React.Component {

    /**
     * the constructor will initilize the state of user profile
     * @param {object} props
     */
    constructor(props) {
        super(props);
        this.state = {
            lan: getLanguage() ? getLanguage() : 'es',      // if the language is not chose, the default will be english
            userID: this.props.userID,                      // the userID will be passed from the query params
            loading: true,                                  // true when fetching data
            collapsed: false,                               // hide the sidebar
            education: [],                                  // education of the user
            experiences: [],
            address: [],                                // experince of the user
            allowEdit: this.props.userID === getUser().sub  // check if the user is viewing his own profile
        }
    }
    // hide the sidebar
    /**
     * hide the sidebar
     */
    onCollapse = (collapsed) => {
        console.log(collapsed);
        this.setState({ collapsed });
    }
    /**
     * fetch user information from dynamodb
     */
    fetchUserInfo = async () => {
        try {
            const user = await API.graphql(graphqlOperation(queries.getEmployee, { id: this.state.userID }));
            this.setState({
                user: user.data.getEmployee,
            })
            console.log(user.data.getEmployee);
        } catch (err) {
            console.log("From userProfile.js - error in getting the user's information", err);
        }
    }
    /** 
     * fetch user's address 
     */
    fetchAddress = async () => {
        try {
            const userAdd = await API.graphql(graphqlOperation(queries.getAddress, { id: this.state.userID }));
            this.setState({
                address: userAdd
            });
        } catch (err) {
            console.log("From userProfile.js - error in getting the user's address", err);
        }
    }
    /**
     * using custom query to fetch user's applied jobs
     */
    fetchAppliedJob = async () => {
        try {
            const testing = await API.graphql(graphqlOperation(customQueries.getAppliedJobEmployee, { id: this.state.userID }));
            const temp = testing.data.getEmployee.appliedJob.items;
            const transformJob = temp.map(item => {
                const jobID = item.Job.id
                const { datePosted, deadline, jobTitle } = item.Job
                const job = {
                    jobID: jobID,
                    jobTitle: jobTitle,
                    datePosted: datePosted,
                    deadline: deadline,
                    status: item.status,
                    dateApplied: item.dateApplied
                }
                return job;
            })
            this.setState({
                jobs: transformJob
            })
        } catch (err) {
            console.log("custom queries failed", err);
        }
    }
    /**
     * fetch user's education information
     */
    fetchEducation = async () => {
        try {
            const educationResults = await API.graphql(graphqlOperation(customQueries.getEducationEmployee, { id: this.state.userID }));
            const temp = educationResults.data.getEmployee.education.items;
            this.setState({ education: temp });
        } catch (err) {
            console.log("couldn't get education: ", err);
        }
    }
    /**
     * fetch user's experiences
     */
    fetchExperience = async () => {
        try {
            const experienceResults = await API.graphql(graphqlOperation(customQueries.getExperienceEmployee, { id: this.state.userID }));
            const temp = experienceResults.data.getEmployee.experience.items;
            this.setState({ experiences: temp });
        } catch (err) {
            console.log("couldn't get experience: ", err);
        }
    }
    /** 
     * fetch user photo from AWS Storage
     */
    fetchPhoto = async () => {
        if (this.state.user.pic === 'yes') {
            Storage.get('profilePic', {
                level: 'protected',
                identityId: this.state.user.identityID// the identityId of that user
            })
                .then(result => {
                    console.log(result);
                    let user = this.state.user;
                    user.pic = result;
                    console.log("state is", this.state);
                    this.setState({ user: user });
                })
                .catch(err => console.log(err));
        }
    }

    // where all the data fetching happen
    /**
     * where all the data fetching happen
     */
    componentDidMount = async () => {
        // fetch the user info
        await this.fetchUserInfo();

        // fetch user's address
        await this.fetchAddress();

        // fetch the employee's applied jobs
        await this.fetchAppliedJob();

        // fetch the employee's education
        await this.fetchEducation();

        // fetch the employee's experiences
        await this.fetchExperience();

        // fetch photo
        await this.fetchPhoto();

        this.setState({
            loading: false
        })
    }
    // TODO function for uploading resume
    onChange(info) {
        if (info.file.status !== 'uploading') {
            console.log(info.file, info.fileList);
        }
        if (info.file.status === 'done') {
            message.success(`${info.file.name} file uploaded successfully`);
        } else if (info.file.status === 'error') {
            message.error(`${info.file.name} file upload failed.`);
        }
    }

    /**
     * delete the education information of the user
     */
    deleteEducation = async (key, e) => {
        // call API to delete education
        try {
            const delEdu = await API.graphql(graphqlOperation(mutations.deleteEducation, { input: { id: key } }));
            console.log("this item was deleted: ", delEdu);
            message.success(`Education deleted`);
        } catch (err) {
            console.log("error - ", err);
            message.error(`Couldn't delete education`);
        }
        let edu = [...this.state.education];
        let deleteIndex = edu.findIndex((item) => item.id === key);
        let willDelete = false;
        edu.forEach(item => {
            if (item.id === key) {
                willDelete = true;
            }
        })
        if (willDelete) {
            edu.splice(deleteIndex, 1);
            this.setState({ education: edu });
        }
    }
    /**
    * delete the user's experience information 
    */
    deleteExperience = async (key, e) => {
        // call API to delete
        try {
            const delExp = await API.graphql(graphqlOperation(mutations.deleteExperience, { input: { id: key } }));
            console.log("this item was deleted: ", delExp);
            message.success(`Experience deleted`);
        } catch (err) {
            console.log("error - ", err);
            message.error(`Couldn't delete experience`);
        }
        // remove it from the page
        let exp = [...this.state.experiences];
        let deleteIndex = exp.findIndex((item) => item.id === key);
        let willDelete = false;
        exp.forEach(item => {
            if (item.id === key) {
                willDelete = true;
            }
        })
        if (willDelete) {
            exp.splice(deleteIndex, 1);
            this.setState({ experiences: exp });
        }
    }
    /**
     * delete the user's address
     */
    deleteAddress = async () => {
        try {
            const delAdd = await API.graphql(graphqlOperation(mutations.deleteAddress, { input: { id: this.state.userID } }));
            console.log("User address was deleted.");
            message.success(`Address deleted`);
            window.location.reload();
        } catch (err) {
            console.log("From userProfile.js - could not delete address", err);
            message.error(`Couldn't delete address`);
        }
    }
    /**
     * begin to render
     */
    render() {
        // setup the dictionary
        I18n.putVocabularies(dict);
        I18n.setLanguage(this.state.lan);
        // if the fetching is not done
        /**
         * make the information is fetched before rendering
         */
        if (this.state.loading) {
            return (
                <Skeleton active />
            );
        }
        return (
            <div>
                <Layout style={{ minHeight: '100vh' }}>
                    <Sider
                        collapsible
                        collapsed={this.state.collapsed}
                        onCollapse={this.onCollapse}
                        width={300}
                    >
                        <Person user={this.state.user} />
                        {/**
                    * render those edit button when user is viewing his own profile page
                    */}
                        {(getUser().sub === this.state.userID) ? (
                            <Menu theme="dark" defaultSelectedKeys={['1']} mode="inline">
                                <SubMenu
                                    key="sub1"
                                    title={<span><Icon type="form" /><span>{I18n.get('Edit Profile')}</span></span>}
                                >
                                    <Menu.Item key="3">
                                        <BasicInfoForm userInfo={this.state.user} />
                                        {/* {I18n.get('Modify Basic Info')} */}
                                    </Menu.Item>

                                    {this.state.address.data.getAddress ?
                                        <Menu.Item key="5">
                                            <UpdateAddressForm />
                                        </Menu.Item> :
                                        <Menu.Item key="4">
                                            <CreateAddressForm />
                                        </Menu.Item>}

                                    {this.state.address.data.getAddress ?
                                        <Menu.Item key="6">
                                            <Button className="modify-info-button" ghost onClick={this.deleteAddress}>
                                                <Icon type="delete" theme="twoTone" twoToneColor="#52c41a" />Delete Address</Button>
                                        </Menu.Item> : null}

                                    <Menu.Item key="7">
                                        <AddEduForm />
                                    </Menu.Item>

                                    <Menu.Item key="8">
                                        <AddExpForm />
                                    </Menu.Item>
                                </SubMenu>

                                <Menu.Item key="2">
                                    <PhotoUploader />

                                    {/* <span>{I18n.get('Change Profile Picture')}</span> */}
                                </Menu.Item>

                                <Menu.Item key="9">
                                    <ResumeUploader onChange={this.onChange} />
                                </Menu.Item>
                            </Menu>) : null
                        }
                    </Sider>
                    <Content>
                        <Information
                            user={this.state.user}
                            address={this.state.address}
                            jobs={this.state.jobs}
                            education={this.state.education}
                            experiences={this.state.experiences}
                            allowEdit={this.state.allowEdit}
                            deleteEdu={this.deleteEducation}
                            deleteExp={this.deleteExperience}
                        />
                    </Content>
                </Layout>
                <Footer style={{ textAlign: 'center' }}>
                    {I18n.get('JobFirst')} ©2019 {I18n.get('Created by JobFirst Group')}
                </Footer>
            </div>
        );
    }
}

export default Profile;