diff --git a/backend/package.json b/backend/package.json index 3ea559419..345610de2 100644 --- a/backend/package.json +++ b/backend/package.json @@ -16,6 +16,7 @@ "license": "MIT", "dependencies": { "@sentry/node": "^5.29.2", + "@types/lodash": "^4.17.5", "@types/pino": "^6.3.4", "bcryptjs": "^2.4.3", "cookie-parser": "^1.4.5", diff --git a/frontend/src/components/NotificationsPopOver/index.js b/frontend/src/components/NotificationsPopOver/index.js index e6acc68f0..6ab793d1a 100644 --- a/frontend/src/components/NotificationsPopOver/index.js +++ b/frontend/src/components/NotificationsPopOver/index.js @@ -1,5 +1,4 @@ import React, { useState, useRef, useEffect, useContext } from "react"; - import { useHistory } from "react-router-dom"; import { format } from "date-fns"; import openSocket from "../../services/socket-io"; @@ -38,6 +37,9 @@ const useStyles = makeStyles(theme => ({ noShadow: { boxShadow: "none !important", }, + iconButton: { + color: theme.palette.text.primary, + }, })); const NotificationsPopOver = () => { @@ -192,7 +194,7 @@ const NotificationsPopOver = () => { onClick={handleClick} ref={anchorEl} aria-label="Open Notifications" - color="inherit" + className={classes.iconButton} > @@ -231,4 +233,4 @@ const NotificationsPopOver = () => { ); }; -export default NotificationsPopOver; \ No newline at end of file +export default NotificationsPopOver; diff --git a/frontend/src/components/TicketsManager/index.js b/frontend/src/components/TicketsManager/index.js index 68883226a..8e199f487 100644 --- a/frontend/src/components/TicketsManager/index.js +++ b/frontend/src/components/TicketsManager/index.js @@ -1,5 +1,4 @@ import React, { useContext, useEffect, useRef, useState } from "react"; - import { makeStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; import SearchIcon from "@material-ui/icons/Search"; @@ -9,14 +8,11 @@ import Tab from "@material-ui/core/Tab"; import Badge from "@material-ui/core/Badge"; import MoveToInboxIcon from "@material-ui/icons/MoveToInbox"; import CheckBoxIcon from "@material-ui/icons/CheckBox"; - import FormControlLabel from "@material-ui/core/FormControlLabel"; import Switch from "@material-ui/core/Switch"; - import NewTicketModal from "../NewTicketModal"; import TicketsList from "../TicketsList"; import TabPanel from "../TabPanel"; - import { i18n } from "../../translate/i18n"; import { AuthContext } from "../../context/Auth/AuthContext"; import { Can } from "../Can"; @@ -32,54 +28,50 @@ const useStyles = makeStyles((theme) => ({ overflow: "hidden", borderTopRightRadius: 0, borderBottomRightRadius: 0, + backgroundColor: theme.palette.background.default, + color: theme.palette.text.primary, }, - tabsHeader: { flex: "none", - backgroundColor: "#eee", + backgroundColor: theme.palette.background.paper, }, - settingsIcon: { alignSelf: "center", marginLeft: "auto", padding: 8, }, - tab: { minWidth: 120, width: 120, }, - ticketOptionsBox: { display: "flex", justifyContent: "space-between", alignItems: "center", - background: "#fafafa", + background: theme.palette.background.paper, padding: theme.spacing(1), }, - serachInputWrapper: { flex: 1, - background: "#fff", + background: theme.palette.background.default, display: "flex", borderRadius: 40, padding: 4, marginRight: theme.spacing(1), }, - searchIcon: { color: "grey", marginLeft: 6, marginRight: 6, alignSelf: "center", }, - searchInput: { flex: 1, border: "none", borderRadius: 30, + color: theme.palette.text.primary, + backgroundColor: theme.palette.background.default, }, - badge: { right: "-10px", }, @@ -93,7 +85,6 @@ const useStyles = makeStyles((theme) => ({ const TicketsManager = () => { const classes = useStyles(); - const [searchParam, setSearchParam] = useState(""); const [tab, setTab] = useState("open"); const [tabOpen, setTabOpen] = useState("open"); @@ -101,10 +92,8 @@ const TicketsManager = () => { const [showAllTickets, setShowAllTickets] = useState(false); const searchInputRef = useRef(); const { user } = useContext(AuthContext); - const [openCount, setOpenCount] = useState(0); const [pendingCount, setPendingCount] = useState(0); - const userQueueIds = user.queues.map((q) => q.id); const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []); diff --git a/frontend/src/context/DarkMode/index.js b/frontend/src/context/DarkMode/index.js new file mode 100644 index 000000000..98be1f38a --- /dev/null +++ b/frontend/src/context/DarkMode/index.js @@ -0,0 +1,40 @@ +import React, { createContext, useState, useContext, useMemo } from "react"; +import PropTypes from "prop-types"; +import { createMuiTheme, ThemeProvider as MUIThemeProvider } from "@material-ui/core/styles"; +import { CssBaseline } from "@material-ui/core"; + +const ThemeContext = createContext(); + +export const ThemeProvider = ({ children }) => { + const [darkMode, setDarkMode] = useState(false); + + const toggleTheme = () => { + setDarkMode((prevMode) => !prevMode); + }; + + const theme = useMemo( + () => + createMuiTheme({ + palette: { + type: darkMode ? "dark" : "light", + }, + }), + [darkMode] + ); + + const contextValue = useMemo(() => ({ darkMode, toggleTheme }), [darkMode]); + + return ( + + + + {children} + + + ); +}; +ThemeProvider.propTypes = { + children: PropTypes.node.isRequired, +}; + +export const useThemeContext = () => useContext(ThemeContext); diff --git a/frontend/src/layout/index.js b/frontend/src/layout/index.js index 589b1331b..65b7aa846 100644 --- a/frontend/src/layout/index.js +++ b/frontend/src/layout/index.js @@ -1,6 +1,5 @@ import React, { useState, useContext, useEffect } from "react"; import clsx from "clsx"; - import { makeStyles, Drawer, @@ -12,11 +11,12 @@ import { MenuItem, IconButton, Menu, + Switch, } from "@material-ui/core"; - import MenuIcon from "@material-ui/icons/Menu"; import ChevronLeftIcon from "@material-ui/icons/ChevronLeft"; import AccountCircle from "@material-ui/icons/AccountCircle"; +import Brightness4Icon from "@material-ui/icons/Brightness4"; import MainListItems from "./MainListItems"; import NotificationsPopOver from "../components/NotificationsPopOver"; @@ -24,6 +24,7 @@ import UserModal from "../components/UserModal"; import { AuthContext } from "../context/Auth/AuthContext"; import BackdropLoading from "../components/BackdropLoading"; import { i18n } from "../translate/i18n"; +import { useThemeContext } from "../context/DarkMode"; const drawerWidth = 240; @@ -35,7 +36,6 @@ const useStyles = makeStyles((theme) => ({ height: "calc(100vh - 56px)", }, }, - toolbar: { paddingRight: 24, // keep right padding when drawer closed }, @@ -52,6 +52,7 @@ const useStyles = makeStyles((theme) => ({ easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.leavingScreen, }), + backgroundColor: theme.palette.background.default, }, appBarShift: { marginLeft: drawerWidth, @@ -63,12 +64,14 @@ const useStyles = makeStyles((theme) => ({ }, menuButton: { marginRight: 36, + color: theme.palette.text.primary, }, menuButtonHidden: { display: "none", }, title: { flexGrow: 1, + color: theme.palette.text.primary, }, drawerPaper: { position: "relative", @@ -78,6 +81,7 @@ const useStyles = makeStyles((theme) => ({ easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.enteringScreen, }), + backgroundColor: theme.palette.background.paper, }, drawerPaperClose: { overflowX: "hidden", @@ -107,6 +111,19 @@ const useStyles = makeStyles((theme) => ({ overflow: "auto", flexDirection: "column", }, + switch: { + transform: "scale(0.8)", + }, + iconButton: { + color: theme.palette.text.primary, + }, + themeSwitchContainer: { + display: "flex", + alignItems: "center", + }, + themeIcon: { + color: theme.palette.text.primary, + }, })); const LoggedInLayout = ({ children }) => { @@ -118,6 +135,7 @@ const LoggedInLayout = ({ children }) => { const [drawerOpen, setDrawerOpen] = useState(false); const [drawerVariant, setDrawerVariant] = useState("permanent"); const { user } = useContext(AuthContext); + const { darkMode, toggleTheme } = useThemeContext(); useEffect(() => { if (document.body.offsetWidth > 600) { @@ -195,12 +213,10 @@ const LoggedInLayout = ({ children }) => { setDrawerOpen(!drawerOpen)} className={clsx( @@ -213,13 +229,25 @@ const LoggedInLayout = ({ children }) => { WhaTicket - {user.id && } + +
+ + +
+ + {user.id && ( + + )}
{ aria-controls="menu-appbar" aria-haspopup="true" onClick={handleMenu} - color="inherit" + className={classes.iconButton} > @@ -258,7 +286,6 @@ const LoggedInLayout = ({ children }) => {
- {children ? children : null}
diff --git a/frontend/src/pages/Tickets/index.js b/frontend/src/pages/Tickets/index.js index 80eb90949..578f48b0b 100644 --- a/frontend/src/pages/Tickets/index.js +++ b/frontend/src/pages/Tickets/index.js @@ -17,12 +17,14 @@ const useStyles = makeStyles((theme) => ({ // padding: theme.spacing(4), height: `calc(100% - 48px)`, overflowY: "hidden", + backgroundColor: theme.palette.background.default, }, chatPapper: { // backgroundColor: "red", display: "flex", height: "100%", + backgroundColor: theme.palette.background.paper, }, contactsWrapper: { @@ -46,7 +48,7 @@ const useStyles = makeStyles((theme) => ({ flexDirection: "column", }, welcomeMsg: { - backgroundColor: "#eee", + backgroundColor: theme.palette.background.paper, display: "flex", justifyContent: "space-evenly", alignItems: "center", diff --git a/frontend/src/routes/index.js b/frontend/src/routes/index.js index f303380ac..5ed8db483 100644 --- a/frontend/src/routes/index.js +++ b/frontend/src/routes/index.js @@ -15,44 +15,32 @@ import QuickAnswers from "../pages/QuickAnswers/"; import Queues from "../pages/Queues/"; import { AuthProvider } from "../context/Auth/AuthContext"; import { WhatsAppsProvider } from "../context/WhatsApp/WhatsAppsContext"; +import { ThemeProvider } from "../context/DarkMode"; import Route from "./Route"; const Routes = () => { return ( - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + );