diff --git a/src/Components/AchievementDescriptionCard.js b/src/Components/AchievementDescriptionCard.js index ad01fc46506825aef6570d3c342bdac2d088d8f2..aa00c2aa87be6c84bf26d03323d57165735d99fb 100644 --- a/src/Components/AchievementDescriptionCard.js +++ b/src/Components/AchievementDescriptionCard.js @@ -7,11 +7,11 @@ import RequirementDialog from './RequirementsDialog.js'; export default function AchievementDescriptionCard(props) { return ( <Paper elevation={3}> - <Grid container direction="row" justify="space-around" alignItems="center"> + <Grid container direction="row" justify="space-between" alignItems="center"> <Grid item xs={3}> <AchievementImg src={props.src}/> </Grid> - <Grid item xs={7}> + <Grid item xs={7} style={{textAlign : "center"}}> <AchievementTitle>{props.title}</AchievementTitle> <AchievementDescription>{props.description}</AchievementDescription> <RequirementDialog diff --git a/src/Components/Activities/getRecipientHref.js b/src/Components/Activities/getRecipientHref.js index 0239307756716ee989bd0be908bb425a94af1a26..95f6cf507396d204751420bf1270faebbe0745f2 100644 --- a/src/Components/Activities/getRecipientHref.js +++ b/src/Components/Activities/getRecipientHref.js @@ -1,5 +1,10 @@ export function getRecipientHref (notification) { if (notification.trackable_type === 'CuratorAssignment') { - return `/recurso/${notification.recipient.id}` + if (notification.recipient !== null) { + return `/recurso/${notification.recipient.id}` + } + else { + return null + } } } diff --git a/src/Components/BadgeCard.js b/src/Components/BadgeCard.js new file mode 100644 index 0000000000000000000000000000000000000000..627493510cb303803a1f119eb74ebfc0ef2f0b82 --- /dev/null +++ b/src/Components/BadgeCard.js @@ -0,0 +1,106 @@ +/*Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana + +This file is part of Plataforma Integrada MEC. + +Plataforma Integrada MEC is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Plataforma Integrada MEC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import clsx from 'clsx'; +import Card from '@material-ui/core/Card'; +import CardHeader from '@material-ui/core/CardHeader'; +import CardContent from '@material-ui/core/CardContent'; +import CardActions from '@material-ui/core/CardActions'; +import Collapse from '@material-ui/core/Collapse'; +import Avatar from '@material-ui/core/Avatar'; +import IconButton from '@material-ui/core/IconButton'; +import Typography from '@material-ui/core/Typography'; +import { red } from '@material-ui/core/colors'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import Button from '@material-ui/core/Button' + +const useStyles = makeStyles((theme) => ({ + root: { + maxWidth: 345, + }, + media: { + height: 0, + paddingTop: '56.25%', // 16:9 + }, + expand: { + transform: 'rotate(0deg)', + marginLeft: 'auto', + transition: theme.transitions.create('transform', { + duration: theme.transitions.duration.shortest, + }), + }, + expandOpen: { + transform: 'rotate(180deg)', + }, + avatar: { + backgroundColor: red[500], + }, +})); + +export default function BadgeCard(props) { + console.log(props); + const classes = useStyles(); + const [expanded, setExpanded] = React.useState(false); + + const handleExpandClick = () => { + setExpanded(!expanded); + }; + + return ( + <Card className={classes.root}> + <CardHeader + avatar={ + <Avatar src={props.avatar} /> + } + title={props.title} + subheader={props.time} + action={ + <IconButton + className={clsx(classes.expand, { + [classes.expandOpen]: expanded, + })} + onClick={handleExpandClick} + aria-expanded={expanded} + aria-label="show more" + > + <ExpandMoreIcon /> + </IconButton> + } + /> + <Collapse in={expanded} timeout="auto" unmountOnExit> + <CardContent> + <Typography variant="h6" color="textPrimary" component="p"> + Descrição + </Typography> + <Typography variant="body2" color="textSecondary" component="p"> + {props.description} + </Typography> + </CardContent> + <CardActions disableSpacing> + <Button + variant="contained" + color="primary" + > + Usar + </Button> + </CardActions> + </Collapse> + </Card> + ); +} \ No newline at end of file diff --git a/src/Components/BadgesModal.js b/src/Components/BadgesModal.js new file mode 100644 index 0000000000000000000000000000000000000000..e42706bb37173c83c0ecd9c6072ebbcb658ca2b8 --- /dev/null +++ b/src/Components/BadgesModal.js @@ -0,0 +1,206 @@ +/*Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana + +This file is part of Plataforma Integrada MEC. + +Plataforma Integrada MEC is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Plataforma Integrada MEC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import Dialog from '@material-ui/core/Dialog'; +import AppBar from '@material-ui/core/AppBar'; +import Toolbar from '@material-ui/core/Toolbar'; +import IconButton from '@material-ui/core/IconButton'; +import Typography from '@material-ui/core/Typography'; +import CloseIcon from '@material-ui/icons/Close'; +import Slide from '@material-ui/core/Slide'; +import Grid from '@material-ui/core/Grid'; +import Accordion from '@material-ui/core/Accordion'; +import AccordionSummary from '@material-ui/core/AccordionSummary'; +import AccordionDetails from '@material-ui/core/AccordionDetails'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; + +import BadgeCard from './BadgeCard'; + +const useStyles = makeStyles((theme) => ({ + appBar: { + position: 'relative', + }, + title: { + marginLeft: theme.spacing(2), + flex: 1, + }, + root: { + width: '100%', + }, +})); + +const Transition = React.forwardRef(function Transition(props, ref) { + return <Slide direction="up" ref={ref} {...props} />; +}); + +export default function FullScreenDialog(props) { + const classes = useStyles(); + const myBadgets = [ + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://futhead.cursecdn.com/static/img/17/items/badges/6000255.png" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://futhead.cursecdn.com/static/img/17/items/badges/6000255.png" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://futhead.cursecdn.com/static/img/17/items/badges/6000255.png" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://futhead.cursecdn.com/static/img/17/items/badges/6000255.png" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://futhead.cursecdn.com/static/img/17/items/badges/6000255.png" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://futhead.cursecdn.com/static/img/17/items/badges/6000255.png" + } + ] + + const myAvatares = [ + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://styles.redditmedia.com/t5_tpk2m/styles/profileIcon_snoo5272646d-0efc-4e69-a737-47637e80bb66-headshot.png?width=256&height=256&crop=256:256,smart&s=4f7a7996efd782f55ec9f10b23545043cd61d3b4" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://styles.redditmedia.com/t5_tpk2m/styles/profileIcon_snoo5272646d-0efc-4e69-a737-47637e80bb66-headshot.png?width=256&height=256&crop=256:256,smart&s=4f7a7996efd782f55ec9f10b23545043cd61d3b4" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://styles.redditmedia.com/t5_tpk2m/styles/profileIcon_snoo5272646d-0efc-4e69-a737-47637e80bb66-headshot.png?width=256&height=256&crop=256:256,smart&s=4f7a7996efd782f55ec9f10b23545043cd61d3b4" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://styles.redditmedia.com/t5_tpk2m/styles/profileIcon_snoo5272646d-0efc-4e69-a737-47637e80bb66-headshot.png?width=256&height=256&crop=256:256,smart&s=4f7a7996efd782f55ec9f10b23545043cd61d3b4" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://styles.redditmedia.com/t5_tpk2m/styles/profileIcon_snoo5272646d-0efc-4e69-a737-47637e80bb66-headshot.png?width=256&height=256&crop=256:256,smart&s=4f7a7996efd782f55ec9f10b23545043cd61d3b4" + }, + { + title: "Shrimp and Chorizo Paella", + time: "September 14, 2016", + description: "This impressive paella is a perfect party dish and a fun meal to cook together with your guests.Add 1 cup of frozen peas along with the mussels, if you like.", + avatar: "https://styles.redditmedia.com/t5_tpk2m/styles/profileIcon_snoo5272646d-0efc-4e69-a737-47637e80bb66-headshot.png?width=256&height=256&crop=256:256,smart&s=4f7a7996efd782f55ec9f10b23545043cd61d3b4" + } + ] + + // + + return ( + <div> + <Dialog fullScreen open={props.open} onClose={props.handleClose} TransitionComponent={Transition}> + <AppBar className={classes.appBar}> + <Toolbar> + <IconButton edge="start" color="inherit" onClick={props.handleClose} aria-label="close"> + <CloseIcon /> + </IconButton> + <Typography variant="h6" className={classes.title}> + Seus Badges + </Typography> + </Toolbar> + </AppBar> + + <Accordion> + <AccordionSummary + expandIcon={<ExpandMoreIcon />} + aria-controls="panel1a-content" + id="panel1a-header" + > + <Typography variant="h6">Badgets</Typography> + </AccordionSummary> + <AccordionDetails> + <Grid container direction="row" alignItems="center" justify="center" spacing={4} xs={12}> + { + myBadgets.map((badge, index) => { + return ( + <Grid item alignContent="center" key={index}> + <BadgeCard + title={badge.title} + time={badge.time} + description={badge.description} + avatar={badge.avatar} + /> + </Grid> + ) + }) + } + </Grid> + </AccordionDetails> + </Accordion> + + <Accordion> + <AccordionSummary + expandIcon={<ExpandMoreIcon />} + aria-controls="panel1a-content" + id="panel1a-header" + > + <Typography variant="h6">Avatares</Typography> + </AccordionSummary> + <AccordionDetails> + <Grid container direction="row" alignItems="center" justify="center" spacing={4} xs={12}> + { + myAvatares.map((badge, index) => { + return ( + <Grid item alignContent="center" key={index}> + <BadgeCard + title={badge.title} + time={badge.time} + description={badge.description} + avatar={badge.avatar} + /> + </Grid> + ) + }) + } + </Grid> + </AccordionDetails> + </Accordion> + </Dialog> + </div> + ); +} diff --git a/src/Components/LevelDescriptionCard.js b/src/Components/LevelDescriptionCard.js index 7c55a81f33b75bcdb375ee02c1919df2ab4a3b24..cf846394cb1f0425887a3904443fd96c8125acc9 100644 --- a/src/Components/LevelDescriptionCard.js +++ b/src/Components/LevelDescriptionCard.js @@ -1,36 +1,75 @@ -import React from 'react'; +import React from 'react' + +import Button from '@material-ui/core/Button' +import BookmarkIcon from '@material-ui/icons/Bookmark' +import { Grid } from '@material-ui/core' import styled from 'styled-components' import ShinyProgressBar from './ShinyProgressBar.js' -import { Grid } from '@material-ui/core' +import BadgesModal from './BadgesModal' export default function LevelDescriptionCard(props) { - return ( - <LevelDescDiv> - <Grid container direction="row" justify="space-between" alignItems="center"> - <Grid item xs={6} md={4}> - <CurrentLevelNumber> - Nível {props.level} - </CurrentLevelNumber> - <CurrentLevelXP> - XP {props.xp} - </CurrentLevelXP> - </Grid> - <Grid item xs={6} md={4} alignContent='flex-end'> - <CurrentCoins> - {props.coins} COINS - </CurrentCoins> - <NextLevelXP> - {props.xp_to_next_lvl} XP PARA O NÍVEL {props.level+1} - </NextLevelXP> - </Grid> - <ShinyProgressBar percentage={props.bar_size} /> - </Grid> - </LevelDescDiv> - ); + const [open, setOpen] = React.useState(false); + + const handleClickOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + + + return ( + <LevelDescDiv> + <BadgesModal handleClose={handleClose} open={open}/> + <ButtonDiv> + <Button + variant="contained" + color="primary" + endIcon={<BookmarkIcon />} + onClick={handleClickOpen} + > + Badges + </Button> + </ButtonDiv> + + <Grid container alignItems="center"> + <Grid container justify="flex-start" alignItems="center" direction="row" xs={12} md={6}> + <Grid item> + <GreyCircle /> + </Grid> + <Grid item> + <CurrentLevelNumber> + Nível {props.level} + </CurrentLevelNumber> + <CurrentCoins> + {props.coins} COINS + </CurrentCoins> + <CurrentLevelXP> + XP {props.xp} + </CurrentLevelXP> + </Grid> + </Grid> + + <Grid container justify="flex-end" align-items="center" > + <NextLevelXP> + {props.xp_to_next_lvl} XP PARA O NÍVEL {props.level + 1} + </NextLevelXP> + <ShinyProgressBar percentage={props.bar_size} /> + </Grid> + </Grid> + </LevelDescDiv> + ); } +const ButtonDiv = styled.div` + position: absolute; + top: 20px; + right: 20px; +` + const NextLevelXP = styled.p` text-align: right; font-size: large; @@ -47,6 +86,16 @@ const CurrentCoins = styled.p` margin-right: 30px; ` +const GreyCircle = styled.div` + background-color: #d4d4d4; + height: 125px; + width: 125px; + border-radius: 50%; +` + +const CurrentLevelInfo = styled.div` + background-color: red; +` const CurrentLevelNumber = styled.h1` font-weight: 500; font-size: 40px; @@ -64,4 +113,5 @@ const CurrentLevelXP = styled.h2` const LevelDescDiv = styled.div` margin: 20px; padding: 20px; + position: relative; ` diff --git a/src/Components/MenuBar.js b/src/Components/MenuBar.js index dd911f2b4f04d9f33403cb8eda7f1d0a0d30f408..a15d3d70bbccebd6f17316e013604efcf8bf44cf 100644 --- a/src/Components/MenuBar.js +++ b/src/Components/MenuBar.js @@ -117,10 +117,11 @@ export default function MenuBar(props){ const minhaArea = [ { name: "Perfil e Atividades", href: "/perfil", value : '0'}, - { name: "Recursos Publicados", href: "/perfil", value : '1'}, - { name: "Favoritos", href: "/perfil", value : '2'}, - { name: "Coleções", href: "/perfil", value : '3'}, - { name: "Rede", href: "/perfil", value : '4'}, + { name: "Status e Conquistas", href: "/perfil", value : '1'}, + { name: "Recursos Publicados", href: "/perfil", value : '2'}, + { name: "Favoritos", href: "/perfil", value : '3'}, + { name: "Coleções", href: "/perfil", value : '4'}, + { name: "Rede", href: "/perfil", value : '5'}, { name: "Configurações", href: "/editarperfil"}, ] @@ -133,11 +134,11 @@ export default function MenuBar(props){ <a href="http://educacaoconectada.mec.gov.br/" rel="noopener noreferrer" target="_blank" > <ButtonStyled >Educação Conectada</ButtonStyled> </a> - {/*<Link to="/loja"> + <Link to="/loja"> <ButtonStyled>Lojinha</ButtonStyled> - </Link>*/} + </Link> <ButtonStyled onClick={props.openSearchBar} ><IconSearchStyled />Buscar</ButtonStyled> - + </Left> <Right> { diff --git a/src/Components/MobileDrawerMenu.js b/src/Components/MobileDrawerMenu.js index 01ca7521d766886607235c6691c6e188c7085f7a..88ac0a581999656a7717fe5cd3a4be2a470c491a 100644 --- a/src/Components/MobileDrawerMenu.js +++ b/src/Components/MobileDrawerMenu.js @@ -39,12 +39,14 @@ import SettingsIcon from '@material-ui/icons/Settings'; import {apiDomain} from '../env.js' import {deleteRequest} from './HelperFunctions/getAxiosConfig' import SearchIcon from '@material-ui/icons/Search'; +import ShoppingBasketIcon from '@material-ui/icons/ShoppingBasket'; export default function MobileDrawerMenu (props) { const {state, dispatch} = useContext(Store) const menuSobre = [ { name : "Página Inicial", href : "/", icon : <HomeIcon/>}, + { name : "Lojinha", href : "/loja", icon : <ShoppingBasketIcon/>}, { name : "Sobre a Plataforma", href : "sobre", icon : <InfoIcon/>}, { name : "Contato", href : "contato", icon : <MailOutlineIcon/>}, { name : "Central de Ajuda", href : "ajuda", icon : <HelpOutlineIcon/>}, diff --git a/src/Components/Notifications.js b/src/Components/Notifications.js index 09b1f99b4caf1e4fffd7dafe130713af08bfe87c..ce6888a07c8c2c9705b66e78c1684baad0a4529b 100644 --- a/src/Components/Notifications.js +++ b/src/Components/Notifications.js @@ -89,9 +89,9 @@ export default function Notification (props) { } - useEffect(() => { - getRequest('/feed?offset=0&limit=30', handleAxiosSuccess, handleAxiosError) - }, []) + /*}// useEffect(() => { + // getRequest('/feed?offset=0&limit=30', handleAxiosSuccess, handleAxiosError) + // }, [])*/ function handleClick(event) { @@ -125,14 +125,14 @@ export default function Notification (props) { notifications.map( (notification) => <ActivityListItem onMenuBar={true} - avatar = {notification.owner.avatar ? apiDomain + notification.owner.avatar : null} + avatar = { notification.owner ? (notification.owner.avatar ? apiDomain + notification.owner.avatar : null) : null} activity = {notification.activity} actionType = {notification.trackable_type} objectType = {notification.recipient_type} createdAt = {notification.created_at} - ownerName = {notification.owner.name} - ownerHref = {'/usuario-publico/' + notification.owner.id} - recipientName = {notification.recipient.name} + ownerName = { notification.owner ? notification.owner.name : null} + ownerHref = {notification.owner ? '/usuario-publico/' + notification.owner.id : null} + recipientName = {notification.recipient ? notification.recipient.name : null} recipientHref = {getRecipientHref(notification)} /> ) diff --git a/src/Components/ShinyProgressBar.js b/src/Components/ShinyProgressBar.js index f2d1cc03c8c2df869499dd72d3dda7078fe2f7de..56dfb67ee409464e3e8417e947140a1600f0afc2 100644 --- a/src/Components/ShinyProgressBar.js +++ b/src/Components/ShinyProgressBar.js @@ -8,7 +8,7 @@ import styled from 'styled-components' export default function ShinyProgressBar(props) { return ( <ProgressBar> - <ShinyFiller percentage={props.percentage}/> + <ShinyFiller percentage={props.percentage}/> </ProgressBar> ); } @@ -31,8 +31,6 @@ const ProgressBar = styled.div` height: 30px; width: 100%; border-radius: 50px; - margin-left:20px; - margin-right:20px; ` const StyledFiller = styled.div` @@ -52,4 +50,4 @@ const StyledShine = styled.div` border-radius: 50px; transition: width 1s ease-in; z-index: +1; -` \ No newline at end of file +` diff --git a/src/Components/StoreGuide.js b/src/Components/StoreGuide.js index f3f22b5695349341eaab3a7bb80bd3c0a7875749..ecc65434dfda5504420dea7203116ec71befe162 100644 --- a/src/Components/StoreGuide.js +++ b/src/Components/StoreGuide.js @@ -15,14 +15,17 @@ GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ -import React from 'react'; +import React, {useState, useContext} from 'react'; import styled from 'styled-components'; import Grid from '@material-ui/core/Grid'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; +import { Typography } from '@material-ui/core'; const StoreTitle = styled.h1` margin-top: 0; + margin-bottom : 10px; + font-size : 45px; ` const StoreTopic = styled.h2` @@ -38,7 +41,7 @@ export default function ItemStoreContainer (props) { return ( <Grid item xs={10} sm={7}> <Card> - <CardContent> + <CardContent style={{color : "#666"}}> <StoreTitle> Lojinha </StoreTitle> diff --git a/src/Components/TabPanels/TabPanelStatusEConquistas.js b/src/Components/TabPanels/TabPanelStatusEConquistas.js index d9e0c20762cb1387ee0ab460f27fe5aeffd2dc07..984f6498ff2db7cd25e14dca005018871d442728 100644 --- a/src/Components/TabPanels/TabPanelStatusEConquistas.js +++ b/src/Components/TabPanels/TabPanelStatusEConquistas.js @@ -1,112 +1,430 @@ -/*Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre -Departamento de Informatica - Universidade Federal do Parana - -This file is part of Plataforma Integrada MEC. - -Plataforma Integrada MEC is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Plataforma Integrada MEC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ - - -import React, {useContext, useState, useEffect} from 'react' +import React, { useContext, useState, useEffect } from 'react' import { Store } from '../../Store.js' import styled from 'styled-components' import Paper from '@material-ui/core/Paper'; -import {ContainerDivStyled} from './StyledComponents.js' -import axios from 'axios' -import {apiUrl} from '../../env'; +import { ContainerDivStyled } from './StyledComponents.js' +import LoadingSpinner from '../LoadingSpinner.js' import LevelDescriptionCard from '../LevelDescriptionCard.js' import AchievementDescriptionCard from '../AchievementDescriptionCard.js' import { Grid } from '@material-ui/core' +import ShinyProgressBar from '../ShinyProgressBar.js' +import {getRequest} from '../HelperFunctions/getAxiosConfig.js' +export default function TabPanelStatusEConquistas(props) { + const {state} = useContext(Store) + + useEffect(() => { + const url = `/completed_achievements/` + getRequest(url, (data) => { + console.log(data) + }, (error) => { + console.log(error); + }); + }, []) + + const currUserLevel = state.currentUser.level + const currUserTotalXP = state.currentUser.experience + state.currentUser.level_xp + const currUserPoints = state.currentUser.points + + const [achievements, setAchievements] = useState([ + { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [ + { + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 5, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 5 + }, + ] + + }, + { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 5 + }, + ] + }, + { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + + ] + }, + { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, + { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, + { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, { + title: "Doctor Strange", + imgsrc: "https://www.filmstories.co.uk/wp-content/uploads/2020/01/doctor-strange-850x600.jpg", + description: "Hey, its doctor strange here!", + requirements: [{ + name: "Curtidor!", + description: "Curtir 5 coleções", + steps : 5, + currStep : 3, + }, + { + name: "Divulgador!", + description: "Divulgar 5 coleções", + steps : 5, + currStep : 2 + }, + ] + }, + ]); -export default function TabPanelStatusEConquistas (props) { - // eslint-disable-next-line - const [achievements, setAchievements] = useState([]); - // eslint-disable-next-line - const [level, setLevel] = useState(0); - // eslint-disable-next-line - const [xp, setXP] = useState(0); - // eslint-disable-next-line - const [coins, setCoins] = useState(0); - // eslint-disable-next-line - const [barSize, setBarSize] = useState(0); - // eslint-disable-next-line - const [xpToNextLevel, setXpToNextLevel] = useState(0); - const { state } = useContext(Store) - - useEffect(() => { - axios.all( - ['xp_to_next_lvl', 'percent_to_next_level', 'points', 'xp', 'get_level', - 'completed_achievements'].map((r) => { - return axios.get(apiUrl + '/' + r + '?id=' + state.currentUser.id); - })).then(axios.spread((xp_to_next_lvl, percent_to_next_level, points, - xp, level, completed_achievements) => { - this.setXpToNextLevel(xp_to_next_lvl); - this.setBarSize(100-percent_to_next_level); - this.setCoins(points); - this.setXP(xp); - this.setLevel(level); - this.setAchievements(completed_achievements); - })); - }, []) return ( - <div> - <ContainerDivStyled> - <Paper elevation={3}> - <LevelDescriptionCard - xp_to_next_lvl={xpToNextLevel} - bar_size={barSize} - coins={coins} - xp={xp} - level={level} - /> - </Paper> - </ContainerDivStyled> - <AchievementsContainer> - <AchievementsSectionTitle> - Conquistas - </AchievementsSectionTitle> - <AchievementsList> - <Grid container direction="row" justify="space-around" alignItems="center"> - {achievements.map( - (a) => { return ( - <Grid item xs={12} md={5}> - <AchievementDescriptionCard - name={a.title} - description={a.description} - src={a.imgsrc} - requirements={a.requirements} - /> - - </Grid> + <React.Fragment> + <WhiteContainer> + <Grid container direction="column" style={{padding : "15px"}}> + + <Grid item> + <div style={{display : "flex", flexDirection : "row", paddingLeft : "15px" }}> + <GreyCircle/> + + <div style={{display : "flex", flexDirection : "column" }}> + <CurrentLevelNumber> + Nível {currUserLevel} + </CurrentLevelNumber> + + <CurrentLevelXP> + XP TOTAL {currUserTotalXP} + </CurrentLevelXP> + </div> + </div> + </Grid> + + <Grid item> + <NextLevelXP> + ???? XP PARA O NÍVEL {currUserLevel + 1} + </NextLevelXP> + <ShinyProgressBar percentage={69} /> + </Grid> + + </Grid> + </WhiteContainer> + <AchievementsContainer> + <AchievementsList> + <AchievementsSectionTitle> + Conquistas + </AchievementsSectionTitle> + <StyledGrid container direction="row" justify="center" alignItems="center" spacing={4} xs={12}> + {achievements.map( + (achievement, index) => { + return ( + <Grid item key={index}> + <AchievementDescriptionCard + name={achievement.title} + description={achievement.description} + src={achievement.imgsrc} + requirements={achievement.requirements} + /> + </Grid> + ) + } )} - )} - </Grid> - </AchievementsList> + </StyledGrid> + </AchievementsList> </AchievementsContainer> - </div> + </React.Fragment> ); } +const StyledGrid = styled(Grid)` + margin : auto !important; +` + const AchievementsSectionTitle = styled.h1` font-weight: 400; + @media screen and (max-width : 502px) { + text-align : center; + } ` const AchievementsContainer = styled.div` max-width : 1140px; - margin-left : auto; - margin-right : auto; margin-bottom: 30px; margin-top: 70px; + margin-left : auto; + margin-right : auto; ` const AchievementsList = styled.div` + display: flex; + flex-direction: column + flex: 1; + justify-content: center; + alignItems: center; +` + +const NextLevelXP = styled.p` + text-align : right; + font-size: 15px; + font-weight: 500; + color: #666; + margin-right: 10px; +` + +const CurrentLevelXP = styled.h2` + margin-top : 0; + font-size : 20px; + font-weight : 500; + color : #00bcd4; +` + +const CurrentLevelNumber = styled.h1` + margin-bottom : 20px; + font-weight: 500; + font-size: 40px; + color: #666; +` + +const GreyCircle = styled.div` + margin-right : 20px; + align-self : center; + background-color: #d4d4d4; + height: 125px; + width: 125px; + border-radius: 50%; +` + +const WhiteContainer = styled.div` + padding-top : 1em; + display : flex; + margin-left : auto; + margin-right : auto; + background-color : #fff; + box-shadow : 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24); + margin-bottom : 30px; + @media screen and (min-width: 1200px) { + width : 1170px; + } + @media screen and (min-width: 992px) and (max-width : 1199px){ + width : 970px; + } + @media screen and (min-width: 768px) and (max-width : 991px) { + width : 750px; + } + @media screen and (max-width: 768px) { + width : auto; + } ` diff --git a/src/Pages/ItemStore.js b/src/Pages/ItemStore.js index 45c3649d1a69a5535dcaee82960343f373527745..8ac7f1d61a508aacde78f0365ce752624b4c6d40 100644 --- a/src/Pages/ItemStore.js +++ b/src/Pages/ItemStore.js @@ -15,15 +15,22 @@ GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ -import React, {useState, useEffect} from 'react'; +import React, { useState, useContext, useEffect } from 'react'; import styled from 'styled-components'; import axios from 'axios'; import Grid from '@material-ui/core/Grid'; +import Card from '@material-ui/core/Card'; +import CardActions from '@material-ui/core/CardActions'; +import CardContent from '@material-ui/core/CardContent'; import Container from '@material-ui/core/Container'; -import UserCardGamified from '../Components/UserCardGamified.js'; +import CircularProgress from '@material-ui/core/CircularProgress'; +import {getRequest} from '../Components/HelperFunctions/getAxiosConfig.js' import StoreGuide from '../Components/StoreGuide.js'; import ItemCarousel from '../Components/ItemCarousel.js'; -import {apiUrl} from '../env'; +import ContactCard from '../Components/ContactCard.js'; +import { apiUrl } from '../env'; +import { Store } from '../Store'; +import { apiDomain } from '../env'; const SectionTitle = styled.h3` font-weight: 100; @@ -41,61 +48,90 @@ const StoreSection = styled.div` margin-bottom: 20px; ` -export default function ItemStoreContainer (props) { - const [avatar_frames, setAvatarFrames] = useState([]); - const [card_frames, setCardFrames] = useState([]); - const [cover_frames, setCoverFrames] = useState([]); - const [badges, setBadges] = useState([]); - - useEffect(() => { - axios.all( - ['avatar_frame', 'card_frame', 'cover_frame', 'badge'].map((r) => { - return axios.get(`${apiUrl}/user_items/index?item_type=${r}&unlock_rule=purchase`); - })).then(axios.spread((avatar, card, cover, badge) => { - setAvatarFrames(avatar); - setCardFrames(card); - setCoverFrames(cover); - setBadges(badge); - })); - }, []) - - return ( - <Container style={{paddingTop : "2em", backgroundColor : "#f4f4f4", width: '100%'}}> - <Grid container - direction="row" - justify="space-around" - alignItems="stretch" - style={{ - marginTop: '2em', - marginBottom: '2em', - }} - > - <UserCardGamified/> - <StoreGuide/> - </Grid> - <StoreSection> - <SectionTitle>Bordas de avatar</SectionTitle> - <StoreDivider/> - <ItemCarousel items={avatar_frames}/> - </StoreSection> - - <StoreSection> - <SectionTitle>Insígnias</SectionTitle> - <StoreDivider/> - <ItemCarousel items={badges}/> - </StoreSection> - - <StoreSection> - <SectionTitle>Bordas de card</SectionTitle> - <StoreDivider/> - <ItemCarousel items={card_frames}/> - </StoreSection> - - <StoreSection> - <SectionTitle>Bordas de capa de perfil</SectionTitle> - <StoreDivider/> - <ItemCarousel items={cover_frames}/> - </StoreSection> - </Container> - ) +export default function ItemStoreContainer(props) { + const { state, dispatch } = useContext(Store); + console.log(state); + + const [avatar_frames, setAvatarFrames] = useState([]); + const [card_frames, setCardFrames] = useState([]); + const [cover_frames, setCoverFrames] = useState([]); + const [badges, setBadges] = useState([]); + + const [currUser, setCurrUser] = useState({}); + const [isLoading, setIsLoading] = useState(true); + + // useEffect(() => { + // axios.all( + // ['avatar_frame', 'card_frame', 'cover_frame', 'badge'].map((r) => { + // return axios.get(apiUrl+'/' + 'user_items/index?item_type='+r+'&unlock_rule=purchase'); + // })).then(axios.spread((avatar, card, cover, badge) => { + // setAvatarFrames(avatar); + // setCardFrames(card); + // setCoverFrames(cover); + // setBadges(badge); + // })); + // }, []) + + useEffect(() => { + // axios.get((`${apiUrl}/users/` + state.currentUser.id)) + // .then((response) => { + // setCurrUser(response.data); + // setIsLoading(false); + // }, + // (error) => { + // console.log(error); + // setIsLoading(false); + // } + // ) + getRequest("/items", (data) => { + console.log(data) + setBadges(data.filter(item => item.item_type === "badge")) + }, (error) => { + console.log(error); + }); + }, []) + + + return ( + <Container maxWidth="false" style={{ marginBottom: "-20px", paddingTop: "2em", backgroundColor: "#f4f4f4", paddingBottom : "30px !important"}}> + <Grid container + direction="row" + justify="space-around" + alignItems="center" + style={{ + marginTop: '2em', + marginBottom: '2em', + }} + > + { + isLoading ? <CircularProgress /> : + <ContactCard + name={currUser.name} + avatar={currUser.avatar ? apiDomain + currUser.avatar : null} + cover={currUser.cover ? apiDomain + currUser.cover : null} + numCollections={currUser.collections_count} + numLearningObjects={currUser.learning_objects_count} + follow_count={currUser.follows_count} + //followed={currUser.followed || null} + //followerID={currUser.follower.id} + href={'/usuario-publico/' + currUser.id} + /> + } + <StoreGuide /> + </Grid> + + <StoreSection> + <SectionTitle>Insígnias</SectionTitle> + <StoreDivider /> + <ItemCarousel items={badges} /> + </StoreSection> + + <StoreSection> + <SectionTitle>Bordas de perfil</SectionTitle> + <StoreDivider /> + <ItemCarousel items={card_frames} /> + </StoreSection> + + </Container> + ) } diff --git a/src/Pages/UserPage.js b/src/Pages/UserPage.js index 6882eb50f7ef17bb2f96af0732efd52f33371e4a..6a4903aa7d87f3b7763dceb4737123bb22211694 100644 --- a/src/Pages/UserPage.js +++ b/src/Pages/UserPage.js @@ -28,6 +28,7 @@ import TabPanelFavoritos from "../Components/TabPanels/UserPageTabs/PanelFavorit import TabPanelColecoes from "../Components/TabPanels/UserPageTabs/PanelColecoes.js"; import TabPanelRede from "../Components/TabPanels/UserPageTabs/PanelRede.js"; import TabPanelCuradoria from "../Components/TabPanels/UserPageTabs/PanelCuradoria.js"; +import TabPanelStatusEConquistas from "../Components/TabPanels/TabPanelStatusEConquistas.js"; import Grid from "@material-ui/core/Grid"; import { HeaderContainer, @@ -58,6 +59,7 @@ export default function UserPage(props) { const [tabValue, setTabValue] = useState(Number(props.location.state) || 0); const [tabs, setTabs] = useState([ "Atividades", + "Status e Conquistas", "Meus Recursos", "Favoritos", "Coleções", @@ -79,6 +81,7 @@ export default function UserPage(props) { if (data.role_ids.includes(4)) { setTabs([ "Atividades", + "Status e Conquistas", "Meus Recursos", "Favoritos", "Coleções", @@ -223,11 +226,12 @@ export default function UserPage(props) { </Grid> <Grid item xs={12}> {tabValue === 0 && <TabPanelAtividades id={id} />} - {tabValue === 1 && <TabPanelMeusRecursos id={id} />} - {tabValue === 2 && <TabPanelFavoritos id={id} />} - {tabValue === 3 && <TabPanelColecoes id={id} />} - {tabValue === 4 && <TabPanelRede id={id} />} - {tabValue === 5 && <TabPanelCuradoria id={id} />} + {tabValue === 1 && <TabPanelStatusEConquistas id={id} />} + {tabValue === 2 && <TabPanelMeusRecursos id={id} />} + {tabValue === 3 && <TabPanelFavoritos id={id} />} + {tabValue === 4 && <TabPanelColecoes id={id} />} + {tabValue === 5 && <TabPanelRede id={id} />} + {tabValue === 6 && <TabPanelCuradoria id={id} />} </Grid> </Grid> </BackgroundDiv> diff --git a/src/env.js b/src/env.js index c13c03e40d90e114c527b17dd43088c759948fcb..62dc6d39c743d4ada8ce203b0dd6e7b7f47860e4 100644 --- a/src/env.js +++ b/src/env.js @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with Plataforma Integrada MEC. If not, see <http://www.gnu.org/licenses/>.*/ -var apiDomain = 'https://api.portalmec.c3sl.ufpr.br', +var apiDomain = 'https://api.portalmechomologa.c3sl.ufpr.br', apiVersion = 'v1', apiUrl = apiDomain + '/' + apiVersion;