- implement lists

- implement generic sections
- implement list actions
- implement error handlers
This commit is contained in:
Amruth Pillai
2020-07-08 05:01:50 +05:30
parent d7e86ddf29
commit bee6a40e9f
38 changed files with 762 additions and 177 deletions

View File

@ -1,103 +0,0 @@
import { useFormik } from "formik";
import React, { useContext, useEffect, useRef, useState } from "react";
import * as Yup from "yup";
import Button from "../components/shared/Button";
import Input from "../components/shared/Input";
import DatabaseContext from "../contexts/DatabaseContext";
import ModalContext from "../contexts/ModalContext";
import { getModalText } from "../utils";
import BaseModal from "./BaseModal";
const CreateResumeSchema = Yup.object().shape({
name: Yup.string()
.min(5, "Please enter at least 5 characters.")
.required("This is a required field."),
});
const CreateResumeModal = () => {
const modalRef = useRef(null);
const [data, setData] = useState(null);
const [open, setOpen] = useState(false);
const [isEditMode, setEditMode] = useState(false);
const { emitter, events } = useContext(ModalContext);
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({
initialValues: {
name: "",
},
validationSchema: CreateResumeSchema,
onSubmit: (newData) => {
if (isEditMode) {
if (data !== newData) {
updateResume(newData);
}
} else {
createResume(newData);
}
modalRef.current.handleClose();
},
});
useEffect(() => {
data && formik.setValues(data) && setEditMode(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data]);
const submitAction = (
<Button
type="submit"
title={getModalText(isEditMode, "Resume")}
onClick={() => formik.handleSubmit()}
/>
);
const onDestroy = () => {
formik.resetForm();
setEditMode(false);
setData(null);
};
return (
<BaseModal
ref={modalRef}
state={[open, setOpen]}
title={getModalText(isEditMode, "Resume")}
action={submitAction}
onDestroy={onDestroy}
>
<form className="mb-8">
<Input
type="text"
label="Name"
name="name"
placeholder="Full Stack Web Developer"
onChange={formik.handleChange}
value={formik.values.name}
error={formik.errors.name}
/>
</form>
<p>
You are going to be creating a new resume from scratch, but first, let's
give it a name. This can be the name of the role you want to apply for,
or if you're making a resume for a friend, you could call it Alex's
Resume.
</p>
</BaseModal>
);
};
export default CreateResumeModal;

108
src/modals/DataModal.js Normal file
View File

@ -0,0 +1,108 @@
import { isEmpty, isFunction } from "lodash";
import React, { useContext, useEffect, useRef, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import Button from "../components/shared/Button";
import ModalContext from "../contexts/ModalContext";
import ResumeContext from "../contexts/ResumeContext";
import { getModalText } from "../utils";
import BaseModal from "./BaseModal";
const DataModal = ({
name,
path,
event,
title,
formik,
onEdit,
onCreate,
children,
}) => {
const modalRef = useRef(null);
const [data, setData] = useState(null);
const [open, setOpen] = useState(false);
const [isEditMode, setEditMode] = useState(false);
const { emitter } = useContext(ModalContext);
const { dispatch } = useContext(ResumeContext);
useEffect(() => {
const unbind = emitter.on(event, (data) => {
setOpen(true);
setData(data);
});
return () => unbind();
}, [emitter, event]);
useEffect(() => {
data && formik.setValues(data) && setEditMode(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data]);
const onSubmit = async (newData) => {
if (isEmpty(await formik.validateForm(newData))) {
if (isEditMode) {
if (data !== newData) {
isFunction(onEdit)
? onEdit(newData)
: dispatch({
type: "on_edit_item",
payload: {
path,
value: newData,
},
});
}
} else {
newData.id = uuidv4();
isFunction(onCreate)
? onCreate(newData)
: dispatch({
type: "on_add_item",
payload: {
path,
value: newData,
},
});
}
modalRef.current.handleClose();
}
};
const getTitle = isEmpty(title)
? getModalText(isEditMode, name)
: isEditMode
? title.edit
: title.create;
const submitAction = (
<Button
type="submit"
title={getTitle}
onClick={() => onSubmit(formik.values)}
/>
);
const onDestroy = () => {
formik.resetForm();
setEditMode(false);
setData(null);
};
return (
<BaseModal
ref={modalRef}
action={submitAction}
onDestroy={onDestroy}
state={[open, setOpen]}
title={getTitle}
>
{children}
</BaseModal>
);
};
export default DataModal;

View File

@ -1,12 +1,14 @@
import React, { Fragment } from "react";
import AuthModal from "./AuthModal";
import CreateResumeModal from "./CreateResumeModal";
import ResumeModal from "./ResumeModal";
import SocialModal from "./sections/SocialModal";
const ModalRegistrar = () => {
return (
<Fragment>
<AuthModal />
<CreateResumeModal />
<ResumeModal />
<SocialModal />
</Fragment>
);
};

64
src/modals/ResumeModal.js Normal file
View File

@ -0,0 +1,64 @@
import { useFormik } from "formik";
import React, { useContext } from "react";
import * as Yup from "yup";
import Input from "../components/shared/Input";
import DatabaseContext from "../contexts/DatabaseContext";
import ModalContext from "../contexts/ModalContext";
import DataModal from "./DataModal";
const initialValues = {
name: "",
};
const validationSchema = Yup.object().shape({
name: Yup.string()
.min(5, "Please enter at least 5 characters.")
.required("This is a required field."),
});
const ResumeModal = () => {
const { events } = useContext(ModalContext);
const { createResume, updateResume } = useContext(DatabaseContext);
const formik = useFormik({
initialValues,
validationSchema,
});
const getFieldProps = (name) => ({
...formik.getFieldProps(name),
error: formik.errors[name],
});
return (
<DataModal
name="Resume"
formik={formik}
title={{
create: "Create Resume",
edit: "Edit Resume",
}}
onEdit={updateResume}
onCreate={createResume}
event={events.CREATE_RESUME_MODAL}
>
<Input
type="text"
name="name"
label="Name"
className="mb-8"
placeholder="Full Stack Web Developer"
{...getFieldProps("name")}
/>
<p>
You are going to be creating a new resume from scratch, but first, let's
give it a name. This can be the name of the role you want to apply for,
or if you're making a resume for a friend, you could call it Alex's
Resume.
</p>
</DataModal>
);
};
export default ResumeModal;

View File

@ -0,0 +1,77 @@
import { useFormik } from "formik";
import React, { useContext } from "react";
import * as Yup from "yup";
import Input from "../../components/shared/Input";
import ModalContext from "../../contexts/ModalContext";
import DataModal from "../DataModal";
const initialValues = {
url: "https://",
network: "",
username: "",
};
const validationSchema = Yup.object().shape({
network: Yup.string()
.min(5, "Please enter at least 5 characters.")
.required("This is a required field."),
username: Yup.string().required("This is a required field."),
url: Yup.string()
.min(5, "Please enter at least 5 characters.")
.required("This is a required field.")
.url("Must be a valid URL"),
});
const SocialModal = () => {
const { events } = useContext(ModalContext);
const formik = useFormik({
initialValues,
validationSchema,
validateOnBlur: true,
});
const getFieldProps = (name) => ({
...formik.getFieldProps(name),
touched: formik.touched[name],
error: formik.errors[name],
});
return (
<DataModal
formik={formik}
path="social.items"
name="Social Network"
event={events.SOCIAL_MODAL}
>
<div className="grid grid-cols-2 gap-8">
<Input
type="text"
name="network"
label="Network"
placeholder="Twitter"
{...getFieldProps("network")}
/>
<Input
type="text"
name="username"
label="Username"
placeholder="KingOKings"
{...getFieldProps("username")}
/>
<Input
type="text"
name="url"
label="URL"
className="col-span-2"
placeholder="https://twitter.com/KingOKings"
{...getFieldProps("url")}
/>
</div>
</DataModal>
);
};
export default SocialModal;