Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notifications socketio #57

Draft
wants to merge 11 commits into
base: dev
Choose a base branch
from
65 changes: 51 additions & 14 deletions client/src/App.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react";
import { MuiThemeProvider } from "@material-ui/core";
import { BrowserRouter, Route, Redirect } from "react-router-dom";
import socketIoClient from "socket.io-client";

import { theme } from "./themes/theme";

Expand All @@ -14,35 +15,71 @@ import Messages from "./pages/Messages";
import Settings from "./pages/Settings";
import ContestSubmissions from "./pages/ContestSubmissions";

import { AuthContext } from "./components/UserContext";
import { AuthContext, NotificationContext } from "./components/UserContext";

import "./App.css";

function App() {
const existingTokens = JSON.parse(localStorage.getItem("tokens"));
const [authTokens, setAuthTokens] = useState(existingTokens);
const [userNotifications, setUserNotifications] = useState({
openNotification: false,
});
const ENDPOINT = "/";
let socketNotify;

const setTokens = (data) => {
localStorage.setItem("tokens", JSON.stringify(data));
setAuthTokens(data);
};

useEffect(() => {
//connect to default socket
socketNotify = socketIoClient(ENDPOINT);
if (authTokens) {
socketNotify.emit("login", authTokens.user);
}
socketNotify.on("send-user-notifications", (fetchNotification) => {
setUserNotifications({
...userNotifications,
...fetchNotification,
});
});
return () => {
socketNotify.emit("disconnect");
socketNotify.off();
socketNotify.close();
};
}, []);

return (
<MuiThemeProvider theme={theme}>
<AuthContext.Provider value={{ authTokens, setAuthTokens: setTokens }}>
<BrowserRouter>
<Route path='/' component={Header} />
<Route exact path='/' render={(props) => <Redirect to='/login' />} />
<Route path='/register' component={Register} />
<Route path='/login' component={Login} />
<Route path='/profile' component={Profile} />
<Route exact path='/contest' component={Contest} />
<Route exact path='/contest/:id' component={ContestSubmissions} />
<Route path='/submit/:id' component={Submission} />
<Route path='/settings' component={Settings} />
<Route path='/submission' component={Submission} />
<Route path='/messages' component={Messages} />
</BrowserRouter>
<NotificationContext.Provider
value={{ userNotifications, setUserNotifications }}
>
<BrowserRouter>
<Route path='/' component={Header} />
<Route
exact
path='/'
render={(props) => <Redirect to='/login' />}
/>
<Route path='/register' component={Register} />
<Route path='/login' component={Login} />
<Route path='/profile' component={Profile} />
<Route path='/contest' component={Contest} />
<Route path='/submission' component={Submission} />
<Route
path='/messages'
component={Messages}
socketNotify={socketNotify}
/>
<Route exact path='/contest/:id' component={ContestSubmissions} />
<Route path='/submit/:id' component={Submission} />
<Route path='/settings' component={Settings} />
</BrowserRouter>
</NotificationContext.Provider>
</AuthContext.Provider>
</MuiThemeProvider>
);
Expand Down
105 changes: 63 additions & 42 deletions client/src/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
Grid,
} from "@material-ui/core";

import { useAuth } from "./UserContext";
import { useAuth, useNotification } from "./UserContext";

const useStyles = makeStyles({
bar: {
Expand Down Expand Up @@ -38,59 +38,80 @@ const useStyles = makeStyles({
textDecoration: "none",
color: "white",
},
links: {
tabs: {
textDecoration: "none",
color: "white",
marginTop: "60px",
marginBottom: "60px",
marginLeft: "30px",
padding: "5px",
margin: "60px 15px 45px 0px",
},
auth: {
visibility: "hidden",
},
});

function Header(props) {
const { authTokens } = useAuth();
const { userNotifications, setUserNotifications } = useNotification();
const path = window.location.pathname;
const classes = useStyles();

const showNotifications = () => {
setUserNotifications({
...userNotifications,
openNotification: !userNotifications.openNotification,
});
};
return (
<AppBar position='static' className={classes.bar}>
<Toolbar>
<Grid container>
<Grid item xs={3}>
<a className={classes.link} href='/'>
<Typography variant='h6' className={classes.title}>
TATTOO ART
</Typography>
</a>
</Grid>
<Grid item xs={3}></Grid>
<Grid item xs={3}>
<a className={classes.link} href='/messages'>
<Typography variant='subtitle1' className={classes.links}>
<>
<AppBar position='static' className={classes.bar}>
<Toolbar>
<Grid container spacing={2}>
<Grid item xs={3}>
<a className={classes.link} href='/'>
<Typography variant='h6' className={classes.title}>
TATTOO ART
</Typography>
</a>
</Grid>

<Grid
item
xs={6}
container
direction='row-reverse'
spacing={2}
className={authTokens ? "" : classes.auth}
>
<a className={classes.tabs} href='/messages'>
Messages
</Typography>
</a>
</Grid>
<Grid item xs={3}>
<Button
variant='outlined'
className={classes.button}
href={
authTokens
? "/contest"
</a>
<a href='#' className={classes.tabs} onClick={showNotifications}>
Notifications
</a>
</Grid>
<Grid item xs={3}>
<Button
variant='outlined'
className={classes.button}
href={
authTokens
? "/contest"
: path === "/login"
? "/register"
: "/login"
}
>
{authTokens
? "CREATE CONTEST"
: path === "/login"
? "/register"
: "/login"
}
>
{authTokens
? "CREATE CONTEST"
: path === "/login"
? "SIGN UP"
: "SIGN IN"}
</Button>
? "SIGN UP"
: "SIGN IN"}
</Button>
</Grid>
</Grid>
</Grid>
</Toolbar>
</AppBar>
</Toolbar>
</AppBar>
</>
);
}

Expand Down
98 changes: 98 additions & 0 deletions client/src/components/Notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { useState, useEffect } from "react";
import {
Paper,
List,
ListItem,
makeStyles,
Typography,
Button,
Box,
} from "@material-ui/core";

import { useAuth, useNotification } from "./UserContext";

const Notifications = (props) => {
let { socketNotify } = props;
//const [socketNotify]=useState(props)
const classes = useStyles();
const { authTokens } = useAuth();
const { userNotifications, setUserNotifications } = useNotification();
const [newList, setNewList] = useState([]);
const [oldList, setOldList] = useState([]);

useEffect(() => {
setNewList(userNotifications.new_notifications);
setOldList(userNotifications.old_notifications);
}, [userNotifications]);

useEffect(() => {
return () => {
if (
userNotifications.new_notifications.length !== newList.length &&
(newList.length > 0 || oldList.length > 0)
) {
fetch("/api/notifications/read", {
method: "PUT",
headers: {
"Content-Type": "application/json",
"x-auth-token": authTokens.token,
},
body: JSON.stringify({
upd_new_notifications: [...newList],
upd_old_notifications: [...oldList],
}),
})
.then((response) => response.json())
.then((result) => {
console.log(result);
});
}
};
}, [newList, oldList]);

const markNotificationRead = (index) => {
let moveToOldList = newList[index];
let updNewList = [...newList];
updNewList.splice(index, 1);
setNewList([...updNewList]);
setOldList([...oldList, moveToOldList]);
};
return (
<Paper elevation={10} className={classes.root}>
<Typography variant='h6'>New Notifications</Typography>
<List>
{newList.map((notification, index) => (
<Box className={classes.listItem} key={index}>
<ListItem>{notification.text}</ListItem>
<Button onClick={() => markNotificationRead(index)}>
Mark Read
</Button>
</Box>
))}
</List>
<Typography variant='h6'>Past Notifications</Typography>
<List>
{oldList.map((notification, index) => (
<ListItem key={index}>{notification.text}</ListItem>
))}
</List>
</Paper>
);
};

export default Notifications;

const useStyles = makeStyles({
root: {
width: "40%",
direction: "ltr",
zIndex: "100",
position: "absolute",
right: "0px",
top: "80px",
},
list: {},
listItem: {
display: "flex",
},
});
9 changes: 7 additions & 2 deletions client/src/components/UserContext.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { createContext, useContext } from 'react';
import { createContext, useContext } from "react";

export const AuthContext = createContext();
export const NotificationContext = createContext();

export function useAuth() {
return useContext(AuthContext);
}
}

export function useNotification() {
return useContext(NotificationContext);
}
Loading