mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-19 11:12:00 +10:00
- implement lists
- implement generic sections - implement list actions - implement error handlers
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
import firebase from "gatsby-plugin-firebase";
|
||||
import { debounce } from "lodash";
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import UserContext from "./UserContext";
|
||||
|
||||
const defaultState = {
|
||||
@ -38,27 +37,22 @@ const DatabaseProvider = ({ children }) => {
|
||||
};
|
||||
|
||||
const createResume = (resume) => {
|
||||
const id = uuidv4();
|
||||
const { id } = resume;
|
||||
const createdAt = firebase.database.ServerValue.TIMESTAMP;
|
||||
|
||||
let firstName = "",
|
||||
lastName = "",
|
||||
photograph = "";
|
||||
let firstName, lastName;
|
||||
|
||||
if (!user.isAnonymous) {
|
||||
[firstName, lastName] = user.displayName.split(" ");
|
||||
photograph = user.photoURL;
|
||||
}
|
||||
|
||||
firebase
|
||||
.database()
|
||||
.ref(`users/${user.uid}/resumes/${id}`)
|
||||
.set({
|
||||
id,
|
||||
profile: {
|
||||
firstName,
|
||||
lastName,
|
||||
photograph,
|
||||
firstName: firstName || "",
|
||||
lastName: lastName || "",
|
||||
},
|
||||
...resume,
|
||||
createdAt,
|
||||
|
||||
@ -4,6 +4,7 @@ import React, { createContext } from "react";
|
||||
const events = {
|
||||
AUTH_MODAL: "auth_modal",
|
||||
CREATE_RESUME_MODAL: "create_resume_modal",
|
||||
SOCIAL_MODAL: "social_modal",
|
||||
};
|
||||
|
||||
const emitter = createNanoEvents();
|
||||
|
||||
@ -1,26 +1,88 @@
|
||||
import { set } from "lodash";
|
||||
import React, { createContext, useContext, useReducer } from "react";
|
||||
import arrayMove from "array-move";
|
||||
import { clone, findIndex, get, setWith } from "lodash";
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useReducer,
|
||||
} from "react";
|
||||
import DatabaseContext from "./DatabaseContext";
|
||||
|
||||
const ResumeContext = createContext({});
|
||||
const initialState = {};
|
||||
|
||||
const ResumeContext = createContext(initialState);
|
||||
|
||||
const ResumeProvider = ({ children }) => {
|
||||
const { debouncedUpdate } = useContext(DatabaseContext);
|
||||
|
||||
const [state, dispatch] = useReducer((state, { type, payload }) => {
|
||||
let newState;
|
||||
const memoizedReducer = useCallback(
|
||||
(state, { type, payload }) => {
|
||||
let newState, index, items;
|
||||
|
||||
switch (type) {
|
||||
case "on_input":
|
||||
newState = set({ ...state }, payload.path, payload.value);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
case "set_data":
|
||||
return payload;
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
}, {});
|
||||
switch (type) {
|
||||
case "on_add_item":
|
||||
items = get(state, payload.path, []);
|
||||
newState = setWith(
|
||||
clone(state),
|
||||
payload.path,
|
||||
[...items, payload.value],
|
||||
clone
|
||||
);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
|
||||
case "on_edit_item":
|
||||
items = get(state, payload.path);
|
||||
index = findIndex(items, ["id", payload.value.id]);
|
||||
newState = setWith(
|
||||
clone(state),
|
||||
`${payload.path}[${index}]`,
|
||||
payload.value,
|
||||
clone
|
||||
);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
|
||||
case "on_delete_item":
|
||||
items = get(state, payload.path);
|
||||
index = findIndex(items, ["id", payload.value.id]);
|
||||
items.splice(index, 1);
|
||||
newState = setWith(clone(state), payload.path, items, clone);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
|
||||
case "on_move_item_up":
|
||||
items = get(state, payload.path);
|
||||
index = findIndex(items, ["id", payload.value.id]);
|
||||
items = arrayMove(items, index, index - 1);
|
||||
newState = setWith(clone(state), payload.path, items, clone);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
|
||||
case "on_move_item_down":
|
||||
items = get(state, payload.path);
|
||||
index = findIndex(items, ["id", payload.value.id]);
|
||||
items = arrayMove(items, index, index + 1);
|
||||
newState = setWith(clone(state), payload.path, items, clone);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
|
||||
case "on_input":
|
||||
newState = setWith(clone(state), payload.path, payload.value, clone);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
|
||||
case "set_data":
|
||||
return payload;
|
||||
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
},
|
||||
[debouncedUpdate]
|
||||
);
|
||||
|
||||
const [state, dispatch] = useReducer(memoizedReducer, initialState);
|
||||
|
||||
return (
|
||||
<ResumeContext.Provider value={{ state, dispatch }}>
|
||||
|
||||
85
src/contexts/StorageContext.js
Normal file
85
src/contexts/StorageContext.js
Normal file
@ -0,0 +1,85 @@
|
||||
import firebase from "gatsby-plugin-firebase";
|
||||
import React, { createContext, useContext, useRef } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import { isFileImage } from "../utils";
|
||||
import ResumeContext from "./ResumeContext";
|
||||
import UserContext from "./UserContext";
|
||||
|
||||
const defaultState = {
|
||||
uploadPhotograph: async () => {},
|
||||
};
|
||||
|
||||
const StorageContext = createContext(defaultState);
|
||||
|
||||
const StorageProvider = ({ children }) => {
|
||||
const toastId = useRef(null);
|
||||
|
||||
const { user } = useContext(UserContext);
|
||||
const { state, dispatch } = useContext(ResumeContext);
|
||||
|
||||
const uploadPhotograph = async (file) => {
|
||||
if (!isFileImage(file)) {
|
||||
toast.error(
|
||||
"You tried to upload a file that was not an image. That won't look good on your resume. Please try again."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const uploadTask = firebase
|
||||
.storage()
|
||||
.ref(`/users/${user.uid}/photographs/${state.id}`)
|
||||
.put(file);
|
||||
|
||||
let progress = 0;
|
||||
toastId.current = toast("Firing up engines...", {
|
||||
progress,
|
||||
});
|
||||
|
||||
uploadTask.on(
|
||||
"state_changed",
|
||||
(snapshot) => {
|
||||
progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
|
||||
toast.update(toastId.current, {
|
||||
render: "Uploading...",
|
||||
progress,
|
||||
hideProgressBar: false,
|
||||
});
|
||||
},
|
||||
(error) => toast.error(error),
|
||||
async () => {
|
||||
const downloadURL = await uploadTask.snapshot.ref.getDownloadURL();
|
||||
dispatch({
|
||||
type: "on_input",
|
||||
payload: {
|
||||
path: "profile.photograph",
|
||||
value: downloadURL,
|
||||
},
|
||||
});
|
||||
|
||||
toast.update(toastId.current, {
|
||||
render:
|
||||
"Your photograph was uploaded successfully... and you look great!",
|
||||
progress,
|
||||
autoClose: 5000,
|
||||
hideProgressBar: true,
|
||||
});
|
||||
|
||||
toastId.current = null;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<StorageContext.Provider
|
||||
value={{
|
||||
uploadPhotograph,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</StorageContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default StorageContext;
|
||||
|
||||
export { StorageProvider };
|
||||
@ -6,13 +6,13 @@ import useAuthState from "../hooks/useAuthState";
|
||||
|
||||
const defaultUser = {
|
||||
uid: null,
|
||||
displayName: null,
|
||||
email: null,
|
||||
photoURL: null,
|
||||
displayName: null,
|
||||
isAnonymous: false,
|
||||
};
|
||||
|
||||
const defaultState = {
|
||||
loading: false,
|
||||
user: defaultUser,
|
||||
logout: async () => {},
|
||||
loginWithGoogle: async () => {},
|
||||
@ -32,8 +32,8 @@ const UserProvider = ({ children }) => {
|
||||
useEffect(() => {
|
||||
if (firebaseUser) {
|
||||
const user = pick(firebaseUser, Object.keys(defaultUser));
|
||||
setUser(user);
|
||||
localStorage.setItem("user", JSON.stringify(user));
|
||||
setUser(user);
|
||||
|
||||
const addUserToDatabase = async () => {
|
||||
const userRef = firebase.database().ref(`users/${user.uid}`);
|
||||
|
||||
Reference in New Issue
Block a user