diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 882e9f6..0000000 --- a/.eslintignore +++ /dev/null @@ -1,6 +0,0 @@ -# .js -# .jsx -# *.js -# *.jsx -# src/*js -# src/*jsx \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 26b1ca9..e23112c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,7 +15,7 @@ module.exports = { // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs // e.g. "@typescript-eslint/explicit-function-return-type": "off", "react/prop-types": 0, - "eslint-disable-next-line": 0, + "@typescript-eslint/no-explicit-any": 0, }, plugins: ["react"], settings: { diff --git a/start.bat b/VSCode.bat similarity index 100% rename from start.bat rename to VSCode.bat diff --git a/package.json b/package.json index 2749c42..758b260 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@babel/preset-env": "^7.12.13", "@babel/preset-react": "^7.12.13", "@tailwindcss/postcss7-compat": "^2.1.0", + "@types/react-redux": "^7.1.16", "@types/styled-components": "^5.1.9", "@typescript-eslint/eslint-plugin": "^4.25.0", "@typescript-eslint/parser": "^4.25.0", diff --git a/start server_dev.bat b/server.bat similarity index 100% rename from start server_dev.bat rename to server.bat diff --git a/src/components/Auth/Login.jsx b/src/components/Auth/Login.jsx index ab8c6af..f102271 100644 --- a/src/components/Auth/Login.jsx +++ b/src/components/Auth/Login.jsx @@ -7,7 +7,7 @@ import styled from "styled-components/macro"; import * as Yup from "yup"; // import background from "../../assets/pexels-bg.jpg"; -const Login = (props) => { +const Login = () => { const dispatch = useDispatch(); const [validationSchema] = useState( Yup.object().shape({ diff --git a/src/components/Chat/Chat.jsx b/src/components/Chat/Chat.jsx index 0b991cd..bbef438 100644 --- a/src/components/Chat/Chat.jsx +++ b/src/components/Chat/Chat.jsx @@ -1,4 +1,4 @@ -import Sidebar from "components/Chat/ChatSidebar/ChatSidebar"; +import ChatSidebar from "components/Chat/ChatSidebar/ChatSidebar"; import { selectChannelName, selectChannelUUID } from "features/channelsSlice"; import { fetchMessagesByChannel } from "features/messagesSlice"; import { fetchTextChannels } from "features/channelsSlice"; @@ -27,7 +27,7 @@ const Chat = () => { return ( - + diff --git a/src/components/Chat/ChatSidebar/ChatSidebar.jsx b/src/components/Chat/ChatSidebar/ChatSidebar.jsx index a733d99..458b4e8 100644 --- a/src/components/Chat/ChatSidebar/ChatSidebar.jsx +++ b/src/components/Chat/ChatSidebar/ChatSidebar.jsx @@ -1,8 +1,8 @@ import React from "react"; import styled from "styled-components/macro"; import ExpandMoreRoundedIcon from "@material-ui/icons/ExpandMoreRounded"; -import SidebarContent from "./ChatSidebarContent"; -import SidebarProfile from "./ChatSidebarProfile"; +import ChatSidebarContent from "./ChatSidebarContent"; +import ChatSidebarProfile from "./ChatSidebarProfile"; const Sidebar = () => { return ( @@ -12,10 +12,10 @@ const Sidebar = () => { - + - + ); diff --git a/src/components/Chat/ChatSidebar/ChatSidebarContent.jsx b/src/components/Chat/ChatSidebar/ChatSidebarContent.jsx index a4bc984..21ef0d2 100644 --- a/src/components/Chat/ChatSidebar/ChatSidebarContent.jsx +++ b/src/components/Chat/ChatSidebar/ChatSidebarContent.jsx @@ -1,16 +1,17 @@ import AddRoundedIcon from "@material-ui/icons/AddRounded"; import ExpandMoreRoundedIcon from "@material-ui/icons/ExpandMoreRounded"; -import { createChannel, selectTextChannels } from "features/channelsSlice"; -import React, { useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import styled from "styled-components/macro"; -import SidebarChannel from "./ChatSidebarChannel"; +import TextInput from "components/common/Form/TextInput"; import Modal from "components/common/Modal/Modal"; import VariantButton from "components/common/VariantButton"; import { variant } from "constants/variant"; +import { createChannel, selectTextChannels } from "features/channelsSlice"; +import { selectUser } from "features/userSlice"; import { Form, Formik } from "formik"; -import TextInput from "components/common/Form/TextInput"; +import React, { useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import styled from "styled-components/macro"; import * as Yup from "yup"; +import SidebarChannel from "./ChatSidebarChannel"; const textChannelContext = { type: "TEXT", @@ -25,8 +26,11 @@ const voiceChannelContext = { const SidebarContent = () => { const dispatch = useDispatch(); const channels = useSelector(selectTextChannels); + const user = useSelector(selectUser); const [showModal, setShowModal] = useState(false); const [modalContext, setModalContext] = useState({}); + const [textChannelsCollapse, setTextChannelsCollapse] = useState(false); + const [voiceChannelsCollapse, setVoiceChannelsCollapse] = useState(true); const [validationSchema] = useState( Yup.object().shape({ @@ -66,34 +70,50 @@ const SidebarContent = () => { - + setTextChannelsCollapse((value) => !value)} + />

Text channels

- { - handleAddChannel("TEXT"); - }} - /> + {user && user.role === "admin" && ( + { + handleAddChannel("TEXT"); + }} + /> + )}
- - {channels && - channels.length > 0 && - channels.map(({ UUID, name }) => ( - - ))} - + {!textChannelsCollapse && ( + + {channels && + channels.length > 0 && + channels.map(({ UUID, name }) => ( + + ))} + + )} - + setVoiceChannelsCollapse((value) => !value)} + />

Voice channels

- { - handleAddChannel("VOICE"); - }} - /> + {user && user.role === "admin" && ( + { + handleAddChannel("VOICE"); + }} + /> + )}
+ {!voiceChannelsCollapse && Voice [WIP]} { - + diff --git a/src/components/Layout.jsx b/src/components/Layout.jsx index ad965a5..eb1c68b 100644 --- a/src/components/Layout.jsx +++ b/src/components/Layout.jsx @@ -14,6 +14,9 @@ const Layout = () => { + + Hello KC + diff --git a/src/components/Message/Message.jsx b/src/components/Message/Message.tsx similarity index 55% rename from src/components/Message/Message.jsx rename to src/components/Message/Message.tsx index fda3936..96f7b86 100644 --- a/src/components/Message/Message.jsx +++ b/src/components/Message/Message.tsx @@ -1,22 +1,44 @@ import React, { useEffect } from "react"; import styled from "styled-components/macro"; import { Avatar } from "@material-ui/core"; +import { selectUser } from "features/userSlice"; +import { useSelector } from "react-redux"; -const Message = ({ message }) => { +interface IMessageProps { + message: any; +} + +interface IMessageContainer { + isUserMessage: boolean; +} + +const Message: React.FC = ({ message }) => { const date = new Date(message.createdAt).toLocaleString(); - const user = message.user; + const { UUID } = useSelector(selectUser); + + const isUserMessage = () => { + return UUID === message.user.UUID; + }; return ( - {user && ( - + {!!message.user && ( + - {user.name} + + {message.user.name} + {date} - {message.body} + + {message.body} + )} @@ -24,27 +46,25 @@ const Message = ({ message }) => { ); }; -export default Message; - const MessageListItem = styled.div` display: flex; - padding-right: 3rem; color: ${({ theme }) => theme.textPrimary}; `; -const MessageContainer = styled.div` +const MessageContainer = styled.div` display: flex; width: 100%; - margin: 1rem 0; + margin: 0.5rem 0; + ${({ isUserMessage }) => isUserMessage && "flex-direction: row-reverse"}; `; -const MessageBodyContent = styled.div` +const MessageBodyContent = styled.div` display: flex; height: 100%; width: 100%; padding: 0.5rem 1rem; border-radius: 0.375rem; - background: #444; + background: ${({ isUserMessage }) => (isUserMessage ? "#57595C" : "#444")}; font-size: 0.875rem; box-shadow: 0 0 4px ${({ theme }) => theme.borderPrimary}; `; @@ -54,7 +74,7 @@ const MessageWrapper = styled.div` flex-direction: column; min-width: 360px; max-width: 75%; - margin-left: 1rem; + margin: 0 1rem; `; const MessageHeader = styled.div` @@ -74,3 +94,5 @@ const MessageTimestamp = styled.div` font-size: 0.625rem; font-size: x-small; `; + +export default Message; diff --git a/src/components/common/Form/TextInput.jsx b/src/components/common/Form/TextInput.jsx index 0affa2c..f190f5f 100644 --- a/src/components/common/Form/TextInput.jsx +++ b/src/components/common/Form/TextInput.jsx @@ -19,6 +19,6 @@ const InputWrapper = tw.div`flex flex-wrap flex-col w-full`; const Info = tw.div`flex justify-between my-2`; const Label = tw.label`text-white`; const Error = tw.span`text-sm text-red-600 text-right mx-2`; -const Input = tw(Field)`border-2 rounded px-4 py-1 outline-none bg-gray-900`; +const Input = tw(Field)`rounded px-4 py-1 outline-none bg-primary-1 text-white`; export default TextInput; diff --git a/src/components/common/Modal/ModalBody.tsx b/src/components/common/Modal/ModalBody.tsx index 5eee292..e7713c0 100644 --- a/src/components/common/Modal/ModalBody.tsx +++ b/src/components/common/Modal/ModalBody.tsx @@ -15,6 +15,6 @@ const ModalBody: React.FC = ({ children, ...props }) => { ) } -const Body = tw.div`flex p-4` +const Body = tw.div`flex px-4 py-6` export default ModalBody diff --git a/src/components/common/Modal/ModalDialog.tsx b/src/components/common/Modal/ModalDialog.tsx index 237b42e..43ab098 100644 --- a/src/components/common/Modal/ModalDialog.tsx +++ b/src/components/common/Modal/ModalDialog.tsx @@ -1,47 +1,51 @@ -import React from 'react' -import tw from 'tailwind-styled-components'; -import PropTypes from 'prop-types'; -import { IModalProps } from './Modal'; -import styled from 'styled-components'; -import { ITheme } from 'interfaces/theme.interface'; +import React from "react"; +import PropTypes from "prop-types"; +import { IModalProps } from "./Modal"; +import styled from "styled-components"; +import { ITheme } from "interfaces/theme.interface"; const propTypes = { children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.element), - PropTypes.element + PropTypes.element, ]), show: PropTypes.bool.isRequired, onHide: PropTypes.func.isRequired, -} +}; const defaultProps = { show: false, onHide: () => { - console.log("Hide modal") + console.log("Hide modal"); }, -} +}; -const ModalDialog: React.FC = ({ children, show, onHide, ...props }) => { +const ModalDialog: React.FC = ({ + children, + show, + onHide, + ...props +}) => { return ( - - {children} - + {children} - ) -} + ); +}; -ModalDialog.displayName = 'ModalDialog'; +ModalDialog.displayName = "ModalDialog"; ModalDialog.propTypes = propTypes; ModalDialog.defaultProps = defaultProps; -const Dialog = tw.div`flex-center w-full my-8`; -const DialogContent = styled.div` +const Dialog = styled.div` max-width: 480px; width: 100%; - background: ${({ theme }: ITheme ) => theme.backgroundPrimary}; +`; + +const DialogContent = styled.div` + background: ${({ theme }: ITheme) => theme.backgroundPrimary}; color: white; border-radius: 8px; `; -export default ModalDialog +export default ModalDialog; diff --git a/src/components/common/Modal/ModalFooter.tsx b/src/components/common/Modal/ModalFooter.tsx index f98d858..8c181f8 100644 --- a/src/components/common/Modal/ModalFooter.tsx +++ b/src/components/common/Modal/ModalFooter.tsx @@ -15,6 +15,6 @@ const ModalFooter: React.FC = ({ children }) => { ) } -const Footer = tw.div`flex justify-end border-t border-gray-600 p-4` +const Footer = tw.div`flex justify-end border-t border-primary-1 p-4` export default ModalFooter diff --git a/src/components/common/Modal/ModalHeader.tsx b/src/components/common/Modal/ModalHeader.tsx index c22029e..cc26569 100644 --- a/src/components/common/Modal/ModalHeader.tsx +++ b/src/components/common/Modal/ModalHeader.tsx @@ -5,6 +5,6 @@ const ModalHeader: React.FC<{title: string}> = ({ title }) => { return
{title}
; }; -const Header = tw.div`flex border-b border-gray-600 p-4` +const Header = tw.div`flex border-b border-primary-1 p-4` export default ModalHeader; diff --git a/src/index.css b/src/index.css index 2b3248e..047653f 100644 --- a/src/index.css +++ b/src/index.css @@ -22,6 +22,14 @@ code { monospace; } +input:-webkit-autofill, +input:-webkit-autofill:hover, +input:-webkit-autofill:focus, +input:-webkit-autofill:active { + background-color: white; + transition: background-color 5000s ease-in-out 0s; +} + a, h1, h2, @@ -38,6 +46,24 @@ path { transform 100ms linear; } +::-webkit-scrollbar { + width: 12px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: #444; + border-radius: 12px; + box-shadow: inset 0 0 2px #151515; +} + +::-webkit-scrollbar-thumb:hover { + background: #404040; +} + .text-ellipsis--2 { text-overflow: ellipsis; overflow: hidden; diff --git a/tailwind.config.js b/tailwind.config.js index 88af5d4..ed5d94c 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,3 +1,6 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const colors = require("tailwindcss/colors"); + module.exports = { purge: [ "./src/**/*.html", @@ -6,6 +9,15 @@ module.exports = { ], darkMode: false, // or 'media' or 'class' theme: { + colors: { + ...colors, + primary: { + 1: "#2c2c2c", + }, + accent: { + 1: "#ffaa32", + }, + }, extend: { fontSize: { xxl: "12rem", diff --git a/yarn.lock b/yarn.lock index bc06bc1..3cf17ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2230,7 +2230,7 @@ dependencies: "@types/node" "*" -"@types/hoist-non-react-statics@*": +"@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" integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== @@ -2357,6 +2357,16 @@ dependencies: "@types/react" "*" +"@types/react-redux@^7.1.16": + version "7.1.16" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.16.tgz#0fbd04c2500c12105494c83d4a3e45c084e3cb21" + integrity sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react-transition-group@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d"