diff --git a/package.json b/package.json index 04a696d..35aaf05 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "react-dom": "^17.0.1", "react-firebase-hooks": "^2.2.0", "react-redux": "^7.2.0", - "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", + "react-spinkit": "^3.0.0", "styled-components": "^5.2.1" }, "scripts": { @@ -40,7 +40,7 @@ "@types/react": "^17.0.2", "@types/react-dom": "^17.0.1", "@types/react-redux": "^7.1.16", - "@types/react-router-dom": "^5.1.7", + "@types/react-spinkit": "^3.0.6", "@types/styled-components": "^5.1.7", "typescript": "^4.2.2" } diff --git a/public/favicon.ico b/public/favicon.ico index 354202a..fc91800 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html index 1dbdca6..91b2804 100644 --- a/public/index.html +++ b/public/index.html @@ -5,39 +5,13 @@ - - - + + - - React Redux App + Slack Clone
- diff --git a/public/logo192.png b/public/logo192.png deleted file mode 100644 index 3362410..0000000 Binary files a/public/logo192.png and /dev/null differ diff --git a/public/logo512.png b/public/logo512.png deleted file mode 100644 index b351622..0000000 Binary files a/public/logo512.png and /dev/null differ diff --git a/public/manifest.json b/public/manifest.json index 080d6c7..f8d68ff 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,21 +1,11 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "Slack Clone", + "name": "Slack clone", "icons": [ { "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" } ], "start_url": ".", diff --git a/src/components/Chat.tsx b/src/components/Chat.tsx new file mode 100644 index 0000000..c3e9d05 --- /dev/null +++ b/src/components/Chat.tsx @@ -0,0 +1,128 @@ +import InfoOutlinedIcon from "@material-ui/icons/InfoOutlined"; +import StarBorderOutlinedIcon from "@material-ui/icons/StarBorderOutlined"; +import React, { useEffect, useRef } from "react"; +import { useCollection, useDocument } from "react-firebase-hooks/firestore"; +import { useSelector } from "react-redux"; +import styled from "styled-components"; +import { selectRoomId } from "../features/roomSlice"; +import { db } from "../firebase"; +import { MessageContent } from "../types"; +import { ChatInput } from "./ChatInput"; +import { Message } from "./Message"; + +export const Chat: React.FC = () => { + const chatRef = useRef(null); + + const roomId = useSelector(selectRoomId); + + const [roomDetails] = useDocument( + roomId && db.collection("rooms").doc(roomId) + ); + + const [roomMessages, loading] = useCollection( + roomId && + db + .collection("rooms") + .doc(roomId) + .collection("messages") + .orderBy("timestamp", "asc") + ); + + useEffect(() => { + chatRef?.current?.scrollIntoView({ + behavior: "smooth", + }); + }, [roomId, loading]); + + return ( + + {roomDetails && roomMessages && ( + <> + + +

+ #{roomDetails?.data().name} + +

+
+ +

+ Details +

+
+
+ + {roomMessages?.docs.map((doc: MessageContent) => { + const { message, timestamp, user, userImg } = doc.data(); + + return ( + + ); + })} + + + + + )} +
+ ); +}; + +const ChatContainer = styled.div` + flex: 0.7; + flex-grow: 1; + overflow-y: scroll; + margin-top: 70px; +`; + +const ChatHeader = styled.div` + display: flex; + justify-content: space-between; + padding: 20px; + border-bottom: 1px solid lightgray; +`; + +const ChatHeaderLeft = styled.div` + display: flex; + align-items: center; + + > h4 { + display: flex; + text-transform: lowercase; + margin-right: 1px; + } + + > h4 > svg { + margin-left: 10px; + font-style: 18px; + } +`; + +const ChatHeaderRight = styled.div` + > p { + display: flex; + align-items: center; + font-size: 14px; + } + + > p > svg { + margin-right: 5px; + font-size: 16px; + } +`; + +const ChatMessages = styled.div``; + +const ChatBottom = styled.div` + padding-bottom: 200px; +`; diff --git a/src/components/ChatInput.tsx b/src/components/ChatInput.tsx new file mode 100644 index 0000000..ef77566 --- /dev/null +++ b/src/components/ChatInput.tsx @@ -0,0 +1,86 @@ +import { Button } from "@material-ui/core"; +import React, { useRef } from "react"; +import { auth, db } from "../firebase"; +import styled from "styled-components"; +import firebase from "firebase/app"; +import { useAuthState } from "react-firebase-hooks/auth"; + +interface ChatInputProps { + chatRef: React.RefObject; + channelId: string | null; + channelName: string; +} + +export const ChatInput: React.FC = ({ + chatRef, + channelId, + channelName, +}) => { + const inputRef = useRef(null); + + const [user] = useAuthState(auth); + + const sendMessage = (e: React.MouseEvent) => { + e.preventDefault(); + + if (!channelId || !inputRef.current) { + return; + } + + if (inputRef.current.value === "") { + return; + } + + db.collection("rooms").doc(channelId).collection("messages").add({ + message: inputRef.current.value, + timestamp: firebase.firestore.FieldValue.serverTimestamp(), + user: user?.displayName, + userImg: user?.photoURL, + }); + + chatRef.current?.scrollIntoView({ + behavior: "smooth", + }); + + inputRef.current.value = ""; + }; + + return ( + +
+ + +
+
+ ); +}; + +const ChatInputCointainer = styled.div` + border-radius: 20px; + + > form { + position: relative; + display: flex; + justify-content: center; + } + + > form > input { + position: fixed; + bottom: 30px; + width: 60%; + border: 1px solid gray; + border-radius: 3px; + padding: 20px; + outline: none; + } + + > form > button { + display: none !important; + } +`; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 03860da..d9284ba 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -3,13 +3,21 @@ import AccessTimeIcon from "@material-ui/icons/AccessTime"; import HelpOutlinedIcon from "@material-ui/icons/HelpOutline"; import SearchIcon from "@material-ui/icons/Search"; import React from "react"; +import { useAuthState } from "react-firebase-hooks/auth"; +import { auth } from "../firebase"; import styled from "styled-components"; export const Header: React.FC = () => { + const [user] = useAuthState(auth); + return ( - + auth.signOut()} + src={user?.photoURL} + alt={user?.displayName} + /> diff --git a/src/components/Message.tsx b/src/components/Message.tsx new file mode 100644 index 0000000..7da83e3 --- /dev/null +++ b/src/components/Message.tsx @@ -0,0 +1,51 @@ +import React from "react"; +import styled from "styled-components"; + +interface MessageProps { + message: string; + timestamp: any; + user: string; + userImg: string | null; +} + +export const Message: React.FC = ({ + message, + timestamp, + user, + userImg, +}) => { + return ( + + profile + +

+ {user} + {new Date(timestamp?.toDate()).toUTCString()} +

+

{message}

+
+
+ ); +}; + +const MessageContainer = styled.div` + display: flex; + align-items: center; + padding: 20px; + + > img { + height: 50px; + border-radius: 8px; + } +`; + +const MessageInfo = styled.div` + padding-left: 10px; + + > h4 > span { + color: gray; + font-weight: 300; + margin-left: 4px; + font-size: 10px; + } +`; diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index b3fb33f..0168623 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -14,9 +14,11 @@ import styled from "styled-components"; import { SidebarOption } from "./SidebarOption"; import { StatusBadge } from "./StatusBadge"; import { useCollection } from "react-firebase-hooks/firestore"; -import { db } from "../firebase"; +import { auth, db } from "../firebase"; +import { useAuthState } from "react-firebase-hooks/auth"; export const Sidebar: React.FC = () => { + const [user] = useAuthState(auth); const [channels] = useCollection(db.collection("rooms")); return ( @@ -28,7 +30,7 @@ export const Sidebar: React.FC = () => { - Martin Velkov + {user?.displayName} diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 90bcd39..16fea74 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -1,22 +1,42 @@ import React from "react"; -import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; +import { useAuthState } from "react-firebase-hooks/auth"; import styled from "styled-components"; +import { Chat } from "../components/Chat"; import { Header } from "../components/Header"; import { Sidebar } from "../components/Sidebar"; +import { auth } from "../firebase"; +import Login from "./Login"; +import Spinner from "react-spinkit"; const App: React.FC = () => { + const [user, loading] = useAuthState(auth); + + if (loading) { + return ( + + + loading + + + + + ); + } + return ( - - <> -
- - - - - - - - + <> + {!user ? ( + + ) : ( + <> +
+ + + + + + )} + ); }; @@ -26,3 +46,25 @@ const AppBody = styled.div` display: flex; height: 100vh; `; + +const AppLoading = styled.div` + display: grid; + place-items: center; + height: 100vh; + width: 100%; +`; + +const AppLoadingContents = styled.div` + text-align: center; + padding-bottom: 100px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + > img { + height: 100px; + padding: 20px; + margin-bottom: 40px; + } +`; diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx new file mode 100644 index 0000000..69c4aa2 --- /dev/null +++ b/src/pages/Login.tsx @@ -0,0 +1,51 @@ +import { Button } from "@material-ui/core"; +import React from "react"; +import styled from "styled-components"; +import { auth, provider } from "../firebase"; + +const Login: React.FC = () => { + const signIn = (e: React.MouseEvent) => { + e.preventDefault(); + + auth.signInWithPopup(provider).catch((err) => alert(err.message)); + }; + + return ( + + + logo +

Sign in now

+ +
+
+ ); +}; + +export default Login; + +const LoginContainer = styled.div` + background: #f8f8f8; + height: 100vh; + display: grid; + place-items: center; +`; + +const LoginInnerContainer = styled.div` + padding: 100px; + text-align: center; + background: white; + border-radius: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); + + > img { + object-fit: contain; + height: 100px; + } + + > button { + margin-top: 50px; + text-transform: inherit; + background: #0a8d48; + color: white; + } +`; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..48ecbfa --- /dev/null +++ b/src/types.ts @@ -0,0 +1,9 @@ +export type MessageContent = { + data(): { + message: string; + timestamp: any; + user: string; + userImg: string | null; + }; + id: string; +}; diff --git a/yarn.lock b/yarn.lock index daa9b2b..eea4d54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1111,7 +1111,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== @@ -2075,11 +2075,6 @@ dependencies: "@types/node" "*" -"@types/history@*": - version "4.7.8" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" - integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== - "@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" @@ -2184,21 +2179,11 @@ hoist-non-react-statics "^3.3.0" redux "^4.0.0" -"@types/react-router-dom@^5.1.7": - version "5.1.7" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.7.tgz#a126d9ea76079ffbbdb0d9225073eb5797ab7271" - integrity sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg== - dependencies: - "@types/history" "*" - "@types/react" "*" - "@types/react-router" "*" - -"@types/react-router@*": - version "5.1.12" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.12.tgz#0f300e09468e7aed86e18241c90238c18c377e51" - integrity sha512-0bhXQwHYfMeJlCh7mGhc0VJTRm0Gk+Z8T00aiP4702mDUuLs9SMhnd2DitpjWFjdOecx2UXtICK14H9iMnziGA== +"@types/react-spinkit@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/react-spinkit/-/react-spinkit-3.0.6.tgz#ed707c705afd8006f54a5cc70deacc4b3557d75b" + integrity sha512-iGgzwQcwU93PSue8U5eYwXEf2yF7ji1vraqB1op6ZuSRvdYg/keFP+7pEuIt454XSQgc/aI4XyLZfO1TdoT0Bw== dependencies: - "@types/history" "*" "@types/react" "*" "@types/react-transition-group@^4.2.0": @@ -3714,6 +3699,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@^2.2.3: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -6015,18 +6005,6 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== - dependencies: - "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -6036,7 +6014,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -6760,11 +6738,6 @@ is-wsl@^2.1.1, is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -7638,6 +7611,11 @@ loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: emojis-list "^3.0.0" json5 "^1.0.1" +loaders.css@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/loaders.css/-/loaders.css-0.1.2.tgz#3a9fb43726c73334a38142af9d0629019b658743" + integrity sha1-Op+0NybHMzSjgUKvnQYpAZtlh0M= + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -7721,7 +7699,7 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== -loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: +loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -7917,14 +7895,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== - dependencies: - "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" - mini-css-extract-plugin@0.11.3: version "0.11.3" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz#15b0910a7f32e62ffde4a7430cfefbd700724ea6" @@ -8689,13 +8659,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" @@ -9561,7 +9524,7 @@ prompts@2.4.0, prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -9805,7 +9768,7 @@ react-firebase-hooks@^2.2.0: resolved "https://registry.yarnpkg.com/react-firebase-hooks/-/react-firebase-hooks-2.2.0.tgz#a2cea46d3da94619e8a316b85173638698ef7d2b" integrity sha512-bwBaCYa8M+bpTqD0masAPGDTzxiTkGbyxv363hyR+NeNH1HbezPll6G7aMIGl+7OOYRPzfdmpkk72zc3VgXfEw== -react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -9831,35 +9794,6 @@ react-refresh@^0.8.3: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== -react-router-dom@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" - integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA== - dependencies: - "@babel/runtime" "^7.1.2" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.2.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - -react-router@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" - integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw== - dependencies: - "@babel/runtime" "^7.1.2" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - react-scripts@4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345" @@ -9926,6 +9860,16 @@ react-scripts@4.0.3: optionalDependencies: fsevents "^2.1.3" +react-spinkit@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/react-spinkit/-/react-spinkit-3.0.0.tgz#31fdaf4e18177766c57d1b1f3330290f8492a85a" + integrity sha1-Mf2vThgXd2bFfRsfMzApD4SSqFo= + dependencies: + classnames "^2.2.3" + loaders.css "^0.1.2" + object-assign "^4.1.0" + prop-types "^15.5.8" + react-transition-group@^4.4.0: version "4.4.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" @@ -10244,11 +10188,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - resolve-url-loader@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz#235e2c28e22e3e432ba7a5d4e305c59a58edfc08" @@ -11355,12 +11294,7 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tiny-invariant@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" - integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== - -tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3: +tiny-warning@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== @@ -11797,11 +11731,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"