Skip to content

Commit

Permalink
Implement list card functionality and sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyfurion committed Dec 7, 2021
1 parent 598ca46 commit 06b79a7
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 112 deletions.
11 changes: 3 additions & 8 deletions client/src/components/AppBanner.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useContext, useState } from 'react';
import { Link } from 'react-router-dom'
import { Link } from 'react-router-dom';
import AuthContext from '../auth';
import { GlobalStoreContext } from '../store'
import AppBar from '@mui/material/AppBar';
Expand All @@ -17,13 +17,8 @@ export default function AppBanner() {
const [anchorEl, setAnchorEl] = useState(null);
const isMenuOpen = Boolean(anchorEl);

const handleProfileMenuOpen = (event) => {
setAnchorEl(event.currentTarget);
};

const handleMenuClose = () => {
setAnchorEl(null);
};
const handleProfileMenuOpen = (event) => { setAnchorEl(event.currentTarget); };
const handleMenuClose = () => { setAnchorEl(null); };

const handleLogout = () => {
handleMenuClose();
Expand Down
81 changes: 57 additions & 24 deletions client/src/components/ListCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import DeleteIcon from '@mui/icons-material/Delete';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ThumbDownIcon from '@mui/icons-material/ThumbDown';
import ThumbDownOutlinedIcon from '@mui/icons-material/ThumbDownOutlined';
import ThumbUpIcon from '@mui/icons-material/ThumbUp';
import ThumbUpOutlinedIcon from '@mui/icons-material/ThumbUpOutlined';

/**
This is a card in our list of top 5 lists. It lets select
Expand Down Expand Up @@ -38,6 +40,10 @@ function ListCard(props) {
event.target.value = "";
}
}
function handleRate(event, type) {
event.stopPropagation();
store.rate(listInfo._id, type);
}

async function handleDeleteList(event, id) {
event.stopPropagation();
Expand All @@ -47,28 +53,54 @@ function ListCard(props) {
let text = "", likes = "", dislikes = "", views = "", comment = "";
if (listInfo.published) {
text = <b>Published: <span style={{ color: "green" }}>{listInfo.publishedDate}</span></b>
likes =
<IconButton
aria-label='like'
sx={{
"grid-area": "1 / 1 / 2 / 2",
justifyContent: "left",
padding: 0
}}
>
<ThumbUpIcon /><b style={{ marginLeft: "10px" }}>{listInfo.likes.length}</b>
</IconButton>;
dislikes =
likes = listInfo.likes.includes(auth.user.email) ?
<IconButton
aria-label='like'
sx={{
gridArea: "1 / 1 / 2 / 2",
justifyContent: "left",
padding: 0
}}
onClick={(event) => handleRate(event, "like")}
>
<ThumbUpIcon /><b style={{ marginLeft: "10px" }}>{listInfo.likes.length}</b>
</IconButton>
:
<IconButton
aria-label='like'
sx={{
gridArea: "1 / 1 / 2 / 2",
justifyContent: "left",
padding: 0
}}
onClick={(event) => handleRate(event, "like")}
>
<ThumbUpOutlinedIcon /><b style={{ marginLeft: "10px" }}>{listInfo.likes.length}</b>
</IconButton>
dislikes = listInfo.dislikes.includes(auth.user.email) ?
<IconButton
aria-label='dislike'
sx={{
"grid-area": "1 / 2 / 2 / 3",
gridArea: "1 / 2 / 2 / 3",
justifyContent: "left",
padding: 0
}}
onClick={(event) => handleRate(event, "dislike")}
>
<ThumbDownIcon /><b style={{ marginLeft: "10px" }}>{listInfo.dislikes.length}</b>
</IconButton>;
</IconButton>
:
<IconButton
aria-label='dislike'
sx={{
gridArea: "1 / 2 / 2 / 3",
justifyContent: "left",
padding: 0
}}
onClick={(event) => handleRate(event, "dislike")}
>
<ThumbDownOutlinedIcon /><b style={{ marginLeft: "10px" }}>{listInfo.dislikes.length}</b>
</IconButton>
views = <b style={{ gridArea: "2 / 1 / 3 / 3" }}>Views: <span style={{ color: "darkred" }}>{listInfo.views}</span></b>;
comment =
<input
Expand Down Expand Up @@ -126,12 +158,12 @@ function ListCard(props) {
<IconButton
onClick={(event) => { handleDeleteList(event, listInfo._id) }}
aria-label= 'delete'
sx={{ "grid-area": "1 / 3 / 2 / 4" }}
sx={{ gridArea: "1 / 3 / 2 / 4" }}
>
<DeleteIcon />
</IconButton>
{views}
<ExpandMoreIcon sx={{ "grid-area": "2 / 3 / 3 / 4" }} />
<ExpandMoreIcon sx={{ gridArea: "2 / 3 / 3 / 4" }} />
</Box>
</ListItem>

Expand Down Expand Up @@ -162,15 +194,15 @@ function ListCard(props) {
"grid-row-gap": "0px",
width: "100%"
}}>
<div style={{ "grid-area": "1 / 1 / 2 / 2" }}>
<div style={{ gridArea: "1 / 1 / 2 / 2" }}>
<b style={{ fontSize: "20pt" }}>{listInfo.name}</b><br />
By: {listInfo.ownerName}
</div>
<Stack sx={{
color: "#d4af37",
backgroundColor: "#2c2f70",
width: "97%",
"grid-area": "2 / 1 / 3 / 2",
gridArea: "2 / 1 / 3 / 2",
borderRadius: "10px",
fontSize: "24pt",
fontWeight: "bold"
Expand All @@ -184,32 +216,32 @@ function ListCard(props) {
<div style={{
display: "flex",
alignItems: "center",
"grid-area": "3 / 1 / 4 / 2"
gridArea: "3 / 1 / 4 / 2"
}}>
{text}
</div>
<div style={{
display: "flex",
alignItems: "center",
"grid-area": "1 / 3 / 2 / 4"
gridArea: "1 / 3 / 2 / 4"
}}>
{likes}
</div>
<div style={{
display: "flex",
alignItems: "center",
"grid-area": "1 / 4 / 2 / 5"
gridArea: "1 / 4 / 2 / 5"
}}>
{dislikes}
</div>
<IconButton
onClick={(event) => { handleDeleteList(event, listInfo._id) }}
aria-label= 'delete'
sx={{ "grid-area": "1 / 5 / 2 / 6" }}
sx={{ gridArea: "1 / 5 / 2 / 6" }}
>
<DeleteIcon />
</IconButton>
<Box sx={{ "grid-area": "2 / 2 / 3 / 6" }}>
<Box sx={{ gridArea: "2 / 2 / 3 / 6" }}>
<Stack sx={{
height: "210px",
overflowY: "scroll"
Expand All @@ -225,10 +257,11 @@ function ListCard(props) {
<div style={{
display: "flex",
alignItems: "center",
"grid-area": "3 / 3 / 4 / 4"
gridArea: "3 / 3 / 4 / 4"
}}>
{views}
</div>
<ExpandLessIcon sx={{ gridArea: "3 / 5 / 4 / 6" }} />
</Box>
</ListItem>
}
Expand Down
67 changes: 64 additions & 3 deletions client/src/components/Toolbar.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,50 @@
import { useContext } from 'react';
import { useState, useContext } from 'react';
import { GlobalStoreContext } from '../store/index.js';
import { Box, IconButton } from '@mui/material';
import AuthContext from '../auth';
import { Box, IconButton, Menu, MenuItem } from '@mui/material';
import HomeIcon from '@mui/icons-material/Home';
import GroupIcon from '@mui/icons-material/Groups';
import PersonIcon from '@mui/icons-material/Person';
import FunctionsIcon from '@mui/icons-material/Functions';
import SortIcon from '@mui/icons-material/Sort';

function Toolbar() {
const { auth } = useContext(AuthContext);
const { store } = useContext(GlobalStoreContext);
const [anchorEl, setAnchorEl] = useState(null);
const isMenuOpen = Boolean(anchorEl);

function handleChangeView(view) { store.setView(view); }
function handleSort(type) { store.sortBy(type); }
function handleSearch(event) {
if (event.code === "Enter") {
if (event.target.value === "") {
store.loadListData();
} else {
let filter = {};
switch (store.view) {
case "home":
filter = { ownerEmail: auth.user.email, name: { $regex: '^' + event.target.value, $options: 'i' } }
break;
case "all":
filter = { published: true, name: { $regex: '^' + event.target.value + '$', $options: 'i' } }
break;
case "user":
filter = { published: true, ownerName: { $regex: '^' + event.target.value + '$', $options: 'i' } }
break;
case "community":
filter = { ownerEmail: "community", name: { $regex: '^' + event.target.value + '$', $options: 'i' } }
break;
default:
return;
}
store.loadListData(filter);
}
}
}

const handleMenuOpen = (event) => { setAnchorEl(event.currentTarget); }
const handleMenuClose = () => { setAnchorEl(null); }

return (
<div id="list-selector-heading">
Expand Down Expand Up @@ -43,7 +77,12 @@ function Toolbar() {
>
<FunctionsIcon />
</IconButton>
<input type="text" id="search-bar" disabled={store.currentList ? true : false} />
<input
type="text"
id="search-bar"
disabled={store.currentList ? true : false}
onKeyPress={handleSearch}
/>
</Box>
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
<IconButton
Expand All @@ -52,11 +91,33 @@ function Toolbar() {
aria-haspopup="true"
sx={{ color: 'black' }}
disabled={store.currentList ? true : false}
onClick={handleMenuOpen}
>
<p id="sort-by-text">SORT BY</p>
<SortIcon />
</IconButton>
</Box>
<Menu
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
id="sort-menu"
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={isMenuOpen}
onClose={handleMenuClose}
>
<MenuItem onClick={() => handleSort("new")}>Publish Date (Newest)</MenuItem>
<MenuItem onClick={() => handleSort("old")}>Publish Date (Oldest)</MenuItem>
<MenuItem onClick={() => handleSort("views")}>Views</MenuItem>
<MenuItem onClick={() => handleSort("likes")}>Likes</MenuItem>
<MenuItem onClick={() => handleSort("dislikes")}>Dislikes</MenuItem>
</Menu>
</div>
)
}
Expand Down
11 changes: 9 additions & 2 deletions client/src/components/WorkspaceScreen.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext, useEffect } from 'react';
import { useContext } from 'react';
import Top5Item from './Top5Item.js';
import { GlobalStoreContext } from '../store/index.js';
/**
Expand All @@ -21,7 +21,14 @@ function WorkspaceScreen() {
store.closeCurrentList();
}
function handlePublish() {
store.publishCurrentList();
if (new Set(newItems).size !== newItems.length) { return; }
for (const item of newItems) {
if (item === "" || !/[a-z0-9]/i.test(item.charAt(0))) { return; }
}
let id = store.currentList._id;
store.changeListName(id, newName);
store.changeListItems(id, newItems);
store.publishList(id);
store.closeCurrentList();
}

Expand Down
Loading

0 comments on commit 06b79a7

Please sign in to comment.