mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-15 17:21:35 +10:00
- fix issue with firebase-hooks
- implement custom useAuthState
This commit is contained in:
@ -1,11 +1,11 @@
|
||||
import cx from "classnames";
|
||||
import React, { useContext } from "react";
|
||||
import { MdPerson, MdSync } from "react-icons/md";
|
||||
import { MdPerson, MdSync, MdSyncDisabled } from "react-icons/md";
|
||||
import DatabaseContext from "../../../contexts/DatabaseContext";
|
||||
import styles from "./RightNavbar.module.css";
|
||||
|
||||
const RightNavbar = () => {
|
||||
const { isUpdating } = useContext(DatabaseContext);
|
||||
const { isOffline, isUpdating } = useContext(DatabaseContext);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
@ -16,7 +16,13 @@ const RightNavbar = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<MdSync size="24px" className={cx("mt-auto", { spin: isUpdating })} />
|
||||
<div className="text-4xl mt-auto">
|
||||
{isOffline ? (
|
||||
<MdSyncDisabled className="text-red-600" />
|
||||
) : (
|
||||
<MdSync className={cx({ spin: isUpdating })} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,23 +1,34 @@
|
||||
import firebase from "gatsby-plugin-firebase";
|
||||
import { debounce } from "lodash";
|
||||
import React, { createContext, useContext, useState } from "react";
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import UserContext from "./UserContext";
|
||||
|
||||
const defaultState = {
|
||||
isOffline: false,
|
||||
isUpdating: false,
|
||||
getResume: async () => {},
|
||||
getResumes: async () => {},
|
||||
createResume: () => {},
|
||||
updateResume: async () => {},
|
||||
debouncedUpdate: async () => {},
|
||||
deleteResume: () => {},
|
||||
};
|
||||
|
||||
const DatabaseContext = createContext(defaultState);
|
||||
|
||||
const DatabaseProvider = ({ children }) => {
|
||||
const [isOffline, setOffline] = useState(false);
|
||||
const [isUpdating, setUpdating] = useState(false);
|
||||
const { user } = useContext(UserContext);
|
||||
|
||||
useEffect(() => {
|
||||
const connectedRef = firebase.database().ref(".info/connected");
|
||||
connectedRef.on("value", (snapshot) => {
|
||||
snapshot.val() === true ? setOffline(false) : setOffline(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const getResume = async (id) => {
|
||||
const snapshot = await firebase
|
||||
.database()
|
||||
@ -30,11 +41,25 @@ const DatabaseProvider = ({ children }) => {
|
||||
const id = uuidv4();
|
||||
const createdAt = firebase.database.ServerValue.TIMESTAMP;
|
||||
|
||||
let firstName = "",
|
||||
lastName = "",
|
||||
photograph = "";
|
||||
|
||||
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,
|
||||
},
|
||||
...resume,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
@ -66,10 +91,12 @@ const DatabaseProvider = ({ children }) => {
|
||||
return (
|
||||
<DatabaseContext.Provider
|
||||
value={{
|
||||
isOffline,
|
||||
isUpdating,
|
||||
getResume,
|
||||
createResume,
|
||||
updateResume: debouncedUpdate,
|
||||
updateResume,
|
||||
debouncedUpdate,
|
||||
deleteResume,
|
||||
}}
|
||||
>
|
||||
|
||||
@ -5,7 +5,7 @@ import DatabaseContext from "./DatabaseContext";
|
||||
const ResumeContext = createContext({});
|
||||
|
||||
const ResumeProvider = ({ children }) => {
|
||||
const { updateResume } = useContext(DatabaseContext);
|
||||
const { debouncedUpdate } = useContext(DatabaseContext);
|
||||
|
||||
const [state, dispatch] = useReducer((state, { type, payload }) => {
|
||||
let newState;
|
||||
@ -13,7 +13,7 @@ const ResumeProvider = ({ children }) => {
|
||||
switch (type) {
|
||||
case "on_input":
|
||||
newState = set({ ...state }, payload.path, payload.value);
|
||||
updateResume(newState);
|
||||
debouncedUpdate(newState);
|
||||
return newState;
|
||||
case "set_data":
|
||||
return payload;
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
import firebase from "gatsby-plugin-firebase";
|
||||
import { pick } from "lodash";
|
||||
import React, { createContext, useEffect, useState } from "react";
|
||||
import { useAuthState } from "react-firebase-hooks/auth";
|
||||
import { toast } from "react-toastify";
|
||||
import useAuthState from "../hooks/useAuthState";
|
||||
|
||||
const defaultUser = {
|
||||
uid: null,
|
||||
displayName: null,
|
||||
email: null,
|
||||
photoURL: null,
|
||||
isAnonymous: false,
|
||||
};
|
||||
|
||||
const defaultState = {
|
||||
@ -20,7 +21,7 @@ const defaultState = {
|
||||
const UserContext = createContext(defaultState);
|
||||
|
||||
const UserProvider = ({ children }) => {
|
||||
const [firebaseUser, loading] = useAuthState(firebase.auth());
|
||||
const [firebaseUser, loading] = useAuthState(firebase);
|
||||
const [user, setUser] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
54
src/hooks/useAuthState.js
Normal file
54
src/hooks/useAuthState.js
Normal file
@ -0,0 +1,54 @@
|
||||
import { useEffect, useReducer, useState } from "react";
|
||||
|
||||
export default function useAuthState(firebase) {
|
||||
const [auth, setAuth] = useState(undefined);
|
||||
|
||||
const [state, dispatch] = useReducer(
|
||||
(state, action) => {
|
||||
switch (action.type) {
|
||||
case "auth_state_changed":
|
||||
return {
|
||||
...state,
|
||||
user: action.user,
|
||||
loading: false,
|
||||
};
|
||||
case "error":
|
||||
return {
|
||||
...state,
|
||||
error: action.error,
|
||||
loading: false,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
},
|
||||
{
|
||||
user: undefined,
|
||||
loading: true,
|
||||
error: undefined,
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setAuth(firebase.auth());
|
||||
}, [firebase]);
|
||||
|
||||
useEffect(() => {
|
||||
if (auth === undefined) return;
|
||||
|
||||
const unsubscribe = auth.onAuthStateChanged(
|
||||
(user) => {
|
||||
dispatch({ type: "auth_state_changed", user });
|
||||
},
|
||||
(error) => {
|
||||
dispatch({ type: "error", error });
|
||||
}
|
||||
);
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [auth]);
|
||||
|
||||
return [state.user, state.loading, state.error];
|
||||
}
|
||||
@ -38,8 +38,15 @@ const CreateResumeModal = () => {
|
||||
name: "",
|
||||
},
|
||||
validationSchema: CreateResumeSchema,
|
||||
onSubmit: (data) => {
|
||||
isEditMode ? updateResume(data) : createResume(data);
|
||||
onSubmit: (newData) => {
|
||||
if (isEditMode) {
|
||||
if (data !== newData) {
|
||||
updateResume(newData);
|
||||
}
|
||||
} else {
|
||||
createResume(newData);
|
||||
}
|
||||
|
||||
modalRef.current.handleClose();
|
||||
},
|
||||
});
|
||||
|
||||
@ -1,15 +1,28 @@
|
||||
import firebase from "gatsby-plugin-firebase";
|
||||
import React from "react";
|
||||
import { useListVals } from "react-firebase-hooks/database";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import CreateResume from "../../components/dashboard/CreateResume";
|
||||
import ResumePreview from "../../components/dashboard/ResumePreview";
|
||||
import TopNavbar from "../../components/dashboard/TopNavbar";
|
||||
import LoadingScreen from "../../components/router/LoadingScreen";
|
||||
|
||||
const Dashboard = ({ user }) => {
|
||||
const [resumes, loading] = useListVals(
|
||||
firebase.database().ref(`users/${user.uid}/resumes`)
|
||||
);
|
||||
const [resumes, setResumes] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
firebase
|
||||
.database()
|
||||
.ref(`users/${user.uid}/resumes`)
|
||||
.on("value", (snapshot) => {
|
||||
if (snapshot.val()) {
|
||||
const resumes = [];
|
||||
const data = snapshot.val();
|
||||
Object.keys(data).forEach((key) => resumes.push(data[key]));
|
||||
setResumes(resumes);
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
}, [user]);
|
||||
|
||||
if (loading) {
|
||||
return <LoadingScreen message="Connecting to database..." />;
|
||||
|
||||
Reference in New Issue
Block a user