- using nanoevents as event emitter

- bug: createResumeModal opens twice
This commit is contained in:
Amruth Pillai
2020-07-06 14:47:05 +05:30
parent 6d3e5823fc
commit dbb005d26c
11 changed files with 1183 additions and 784 deletions
+7 -1
View File
@@ -1,5 +1,11 @@
{ {
"files.associations": { "files.associations": {
"*.js": "javascriptreact" "*.js": "javascriptreact"
} },
"[javascriptreact]": {
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"editor.formatOnSave": true
} }
+1112 -713
View File
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -18,7 +18,7 @@
"classnames": "^2.2.6", "classnames": "^2.2.6",
"firebase": "^7.15.5", "firebase": "^7.15.5",
"formik": "^2.1.4", "formik": "^2.1.4",
"gatsby": "^2.23.12", "gatsby": "^2.23.20",
"gatsby-image": "^2.4.12", "gatsby-image": "^2.4.12",
"gatsby-plugin-create-client-paths": "^2.3.9", "gatsby-plugin-create-client-paths": "^2.3.9",
"gatsby-plugin-firebase": "^0.2.0-beta.4", "gatsby-plugin-firebase": "^0.2.0-beta.4",
@@ -32,9 +32,10 @@
"gatsby-transformer-sharp": "^2.5.10", "gatsby-transformer-sharp": "^2.5.10",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"moment": "^2.27.0", "moment": "^2.27.0",
"react": "^16.12.0", "nanoevents": "^5.1.8",
"react": "^16.13.1",
"react-beautiful-dnd": "^13.0.0", "react-beautiful-dnd": "^13.0.0",
"react-dom": "^16.12.0", "react-dom": "^16.13.1",
"react-firebase-hooks": "^2.2.0", "react-firebase-hooks": "^2.2.0",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-icons": "^3.10.0", "react-icons": "^3.10.0",
+2 -4
View File
@@ -4,11 +4,9 @@ import ModalContext from "../../contexts/ModalContext";
import styles from "./CreateResume.module.css"; import styles from "./CreateResume.module.css";
const CreateResume = () => { const CreateResume = () => {
const { createResumeModal } = useContext(ModalContext); const { emitter, events } = useContext(ModalContext);
const handleClick = () => { const handleClick = () => emitter.emit(events.CREATE_RESUME_MODAL);
createResumeModal.setOpen(true);
};
return ( return (
<div className={styles.resume}> <div className={styles.resume}>
+2 -3
View File
@@ -10,7 +10,7 @@ import styles from "./ResumePreview.module.css";
const ResumePreview = ({ resume }) => { const ResumePreview = ({ resume }) => {
const [anchorEl, setAnchorEl] = useState(null); const [anchorEl, setAnchorEl] = useState(null);
const { createResumeModal } = useContext(ModalContext); const { emitter, events } = useContext(ModalContext);
const { deleteResume } = useContext(DatabaseContext); const { deleteResume } = useContext(DatabaseContext);
const handleOpen = () => navigate(`/app/builder/${resume.id}`); const handleOpen = () => navigate(`/app/builder/${resume.id}`);
@@ -20,8 +20,7 @@ const ResumePreview = ({ resume }) => {
}; };
const handleRename = () => { const handleRename = () => {
createResumeModal.setOpen(true); emitter.emit(events.CREATE_RESUME_MODAL, resume);
createResumeModal.setData(resume);
setAnchorEl(null); setAnchorEl(null);
}; };
+6 -10
View File
@@ -1,18 +1,18 @@
import { navigate } from "gatsby";
import React, { useContext } from "react"; import React, { useContext } from "react";
import { FaGithub } from "react-icons/fa"; import { FaGithub } from "react-icons/fa";
import ThemeContext from "../../contexts/ThemeContext";
import ModalContext from "../../contexts/ModalContext"; import ModalContext from "../../contexts/ModalContext";
import ThemeContext from "../../contexts/ThemeContext";
import UserContext from "../../contexts/UserContext"; import UserContext from "../../contexts/UserContext";
import Button from "../shared/Button"; import Button from "../shared/Button";
import Logo from "../shared/Logo"; import Logo from "../shared/Logo";
import { navigate } from "gatsby";
const Hero = () => { const Hero = () => {
const { emitter, events } = useContext(ModalContext);
const { user, loading } = useContext(UserContext); const { user, loading } = useContext(UserContext);
const { toggleDarkMode } = useContext(ThemeContext); const { toggleDarkMode } = useContext(ThemeContext);
const { authModal } = useContext(ModalContext);
const handleLogin = () => authModal.setOpen(true); const handleLogin = () => emitter.emit(events.AUTH_MODAL);
const handleGotoApp = () => navigate("/app/dashboard"); const handleGotoApp = () => navigate("/app/dashboard");
@@ -31,14 +31,10 @@ const Hero = () => {
<Button <Button
title="Go to App" title="Go to App"
onClick={handleGotoApp} onClick={handleGotoApp}
isLoading={loading || authModal.isOpen} isLoading={loading}
/> />
) : ( ) : (
<Button <Button title="Login" onClick={handleLogin} isLoading={loading} />
title="Login"
onClick={handleLogin}
isLoading={loading || authModal.isOpen}
/>
)} )}
<Button <Button
outline outline
+10 -28
View File
@@ -1,38 +1,20 @@
import React, { createContext, useState } from "react"; import { createNanoEvents } from "nanoevents";
import React, { createContext } from "react";
const defaultState = { const events = {
authModal: { AUTH_MODAL: "auth_modal",
isOpen: false, CREATE_RESUME_MODAL: "create_resume_modal",
setOpen: () => {},
},
createResumeModal: {
isOpen: false,
setOpen: () => {},
data: null,
setData: () => {},
},
}; };
const emitter = createNanoEvents();
const defaultState = { events, emitter };
const ModalContext = createContext(defaultState); const ModalContext = createContext(defaultState);
const ModalProvider = ({ children }) => { const ModalProvider = ({ children }) => {
const [authOpen, setAuthOpen] = useState(false);
const [createResumeOpen, setCreateResumeOpen] = useState(false);
const [createResumeData, setCreateResumeData] = useState(null);
return ( return (
<ModalContext.Provider <ModalContext.Provider value={defaultState}>
value={{
authModal: { isOpen: authOpen, setOpen: setAuthOpen },
createResumeModal: {
isOpen: createResumeOpen,
setOpen: setCreateResumeOpen,
data: createResumeData,
setData: setCreateResumeData,
},
}}
>
{children} {children}
</ModalContext.Provider> </ModalContext.Provider>
); );
+14 -6
View File
@@ -1,15 +1,23 @@
import React, { useState, useContext, Fragment } from "react"; import { navigate } from "gatsby";
import BaseModal from "./BaseModal"; import React, { Fragment, useContext, useEffect, useState } from "react";
import Button from "../components/shared/Button"; import Button from "../components/shared/Button";
import ModalContext from "../contexts/ModalContext"; import ModalContext from "../contexts/ModalContext";
import UserContext from "../contexts/UserContext"; import UserContext from "../contexts/UserContext";
import { navigate } from "gatsby"; import BaseModal from "./BaseModal";
const AuthModal = () => { const AuthModal = () => {
const [open, setOpen] = useState(false);
const [isLoading, setLoading] = useState(false); const [isLoading, setLoading] = useState(false);
const { authModal } = useContext(ModalContext);
const { emitter, events } = useContext(ModalContext);
const { user, loginWithGoogle, logout } = useContext(UserContext); const { user, loginWithGoogle, logout } = useContext(UserContext);
useEffect(() => {
const unbind = emitter.on(events.AUTH_MODAL, () => setOpen(true));
return () => unbind();
}, [emitter, events]);
const handleSignInWithGoogle = async () => { const handleSignInWithGoogle = async () => {
setLoading(true); setLoading(true);
await loginWithGoogle(); await loginWithGoogle();
@@ -18,7 +26,7 @@ const AuthModal = () => {
const handleGotoApp = () => { const handleGotoApp = () => {
navigate("/app/dashboard"); navigate("/app/dashboard");
authModal.setOpen(false); setOpen(false);
}; };
const getTitle = () => const getTitle = () =>
@@ -46,7 +54,7 @@ const AuthModal = () => {
return ( return (
<BaseModal <BaseModal
state={authModal} state={[open, setOpen]}
title={getTitle()} title={getTitle()}
action={user ? loggedInAction : loggedOutAction} action={user ? loggedInAction : loggedOutAction}
> >
+7 -8
View File
@@ -1,21 +1,20 @@
import React, { forwardRef, useImperativeHandle } from "react";
import { isFunction } from "lodash";
import Modal from "@material-ui/core/Modal";
import Backdrop from "@material-ui/core/Backdrop"; import Backdrop from "@material-ui/core/Backdrop";
import Fade from "@material-ui/core/Fade"; import Fade from "@material-ui/core/Fade";
import Modal from "@material-ui/core/Modal";
import { isFunction } from "lodash";
import React, { forwardRef, useImperativeHandle } from "react";
import { MdClose } from "react-icons/md"; import { MdClose } from "react-icons/md";
import styles from "./BaseModal.module.css";
import Button from "../components/shared/Button"; import Button from "../components/shared/Button";
import styles from "./BaseModal.module.css";
const BaseModal = forwardRef( const BaseModal = forwardRef(
({ title, state, children, action, onDestroy }, ref) => { ({ title, state, children, action, onDestroy }, ref) => {
const { isOpen, setOpen, setData } = state; const [open, setOpen] = state;
const handleClose = () => { const handleClose = () => {
setOpen(false); setOpen(false);
setTimeout(() => { setTimeout(() => {
isFunction(setData) && setData(null);
isFunction(onDestroy) && onDestroy(); isFunction(onDestroy) && onDestroy();
}, 250); }, 250);
}; };
@@ -24,13 +23,13 @@ const BaseModal = forwardRef(
return ( return (
<Modal <Modal
open={isOpen} open={open}
closeAfterTransition closeAfterTransition
onClose={handleClose} onClose={handleClose}
className={styles.root} className={styles.root}
BackdropComponent={Backdrop} BackdropComponent={Backdrop}
> >
<Fade in={isOpen}> <Fade in={open}>
<div className={styles.modal}> <div className={styles.modal}>
<div className={styles.title}> <div className={styles.title}>
<h2>{title}</h2> <h2>{title}</h2>
+17 -3
View File
@@ -14,12 +14,25 @@ const CreateResumeSchema = Yup.object().shape({
.required("This is a required field."), .required("This is a required field."),
}); });
const CreateResumeModal = ({ data }) => { const CreateResumeModal = () => {
const modalRef = useRef(null); const modalRef = useRef(null);
const [data, setData] = useState(null);
const [open, setOpen] = useState(false);
const [isEditMode, setEditMode] = useState(false); const [isEditMode, setEditMode] = useState(false);
const { createResumeModal } = useContext(ModalContext);
const { emitter, events } = useContext(ModalContext);
const { createResume, updateResume } = useContext(DatabaseContext); const { createResume, updateResume } = useContext(DatabaseContext);
useEffect(() => {
const unbind = emitter.on(events.CREATE_RESUME_MODAL, (data) => {
setOpen(true);
setData(data);
});
return () => unbind();
}, [emitter, events]);
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
name: "", name: "",
@@ -47,12 +60,13 @@ const CreateResumeModal = ({ data }) => {
const onDestroy = () => { const onDestroy = () => {
formik.resetForm(); formik.resetForm();
setEditMode(false); setEditMode(false);
setData(null);
}; };
return ( return (
<BaseModal <BaseModal
ref={modalRef} ref={modalRef}
state={createResumeModal} state={[open, setOpen]}
title={getModalText(isEditMode, "Resume")} title={getModalText(isEditMode, "Resume")}
action={submitAction} action={submitAction}
onDestroy={onDestroy} onDestroy={onDestroy}
+2 -5
View File
@@ -1,15 +1,12 @@
import React, { Fragment, useContext } from "react"; import React, { Fragment } from "react";
import ModalContext from "../contexts/ModalContext";
import AuthModal from "./AuthModal"; import AuthModal from "./AuthModal";
import CreateResumeModal from "./CreateResumeModal"; import CreateResumeModal from "./CreateResumeModal";
const ModalRegistrar = () => { const ModalRegistrar = () => {
const { createResumeModal } = useContext(ModalContext);
return ( return (
<Fragment> <Fragment>
<AuthModal /> <AuthModal />
<CreateResumeModal data={createResumeModal.data} /> <CreateResumeModal />
</Fragment> </Fragment>
); );
}; };