diff --git a/package-lock.json b/package-lock.json index 9981744652217d6fb750aea73a717b279797a75b..4bb79c1033c8b7700f8106f383d38a57a45c7f06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2338,9 +2338,9 @@ "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==" }, "@hapi/hoek": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.0.tgz", - "integrity": "sha512-7XYT10CZfPsH7j9F1Jmg1+d0ezOux2oM2GfArAzLwWe4mE2Dr3hVjsAL6+TFY49RRJlCdJDMw3nJsLFroTc8Kw==" + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==" }, "@hapi/joi": { "version": "15.1.1", @@ -12977,6 +12977,15 @@ "camelcase": "^5.0.0" } }, + "react-input-mask": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-input-mask/-/react-input-mask-2.0.4.tgz", + "integrity": "sha512-1hwzMr/aO9tXfiroiVCx5EtKohKwLk/NT8QlJXHQ4N+yJJFyUuMT+zfTpLBwX/lK3PkuMlievIffncpMZ3HGRQ==", + "requires": { + "invariant": "^2.2.4", + "warning": "^4.0.2" + } + }, "react-is": { "version": "16.8.6", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", @@ -15273,6 +15282,14 @@ "makeerror": "1.0.x" } }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", diff --git a/package.json b/package.json index 6786c2893aa0962597f90ef982a379bfcae57109..b3585858fce7291fa34862e8a8b72256c430dbff 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "react-google-login": "^5.0.7", "react-grid-system": "^4.4.11", "react-icons": "^3.8.0", + "react-input-mask": "^2.0.4", "react-recaptcha": "^2.3.10", "react-responsive-carousel": "^3.1.51", "react-router-dom": "^5.1.2", diff --git a/src/App.js b/src/App.js index 07386a15b5cee65fe64c5f8c33e32ee477299071..16edfcb0a2fa9f5e41f14d4eee1c2a74a7d8fe1a 100644 --- a/src/App.js +++ b/src/App.js @@ -32,6 +32,9 @@ import TabResoursePub from './Pages/TabsHelp/TabResoursePub'; import TabResourseFind from './Pages/TabsHelp/TabResourseFind'; import TabNetPart from './Pages/TabsHelp/TabNetPart'; import TabManageAc from './Pages/TabsHelp/TabManageAc'; +import PasswordRecoveryPage from './Pages/PasswordRecoveryPage.js' +import Teste from './Pages/Teste'; +import PageProfessor from './Pages/PageProfessor.js' import ResourcePage from './Pages/ResourcePage'; import {BrowserRouter, Switch, Route} from 'react-router-dom'; import { Store } from './Store' @@ -39,6 +42,8 @@ import TermsPage from './Pages/TermsPage.js' import PublicationPermissionsPage from './Pages/PublicationPermissionsPage.js' import TabPlataformaMEC from './Pages/TabsHelp/TabPlataformaMEC'; +import Contact from './Pages/Contact.js' +import EditProfilePage from './Pages/EditProfilePage.js' export default function App(){ // eslint-disable-next-line @@ -74,12 +79,13 @@ export default function App(){ <BrowserRouter> <Header /> <div style={{backgroundImage: "linear-gradient(to right,#ff7f00,#e81f4f,#673ab7,#00bcd4)", height:"5px"}}></div> + <link href="https://fonts.googleapis.com/css?family=Kalam|Pompiere|Roboto&display=swap" rel="stylesheet"/> <Switch> <Route path="/" exact={true} component={Home}/> <Route path="/busca" component={Search} /> - <Route path="/perfil-atualizacoes" component={UserPage} /> + <Route path="/perfil" component={UserPage} /> + <Route path="/editarperfil" component={EditProfilePage} /> <Route path="/recurso" component={ResourcePage}/> - <Route path="/termos-publicar-recurso" component={TermsPage}/> <Route path="/permission" component={PublicationPermissionsPage}/> {/*<Route path="termos-de-uso#publicacoes-de-usuario" component={}*/} @@ -93,7 +99,8 @@ export default function App(){ <Route path="/participando-da-rede" component={TabNetPart}/> <Route path="/gerenciando-conta" component={TabManageAc}/> <Route path="/plataforma-mec" component={TabPlataformaMEC}/> - + <Route path="/recuperar-senha" component={PasswordRecoveryPage}/> + <Route path='/professor' component={PageProfessor}/> </Switch> <EcFooter/> <GNUAGPLfooter/> diff --git a/src/Components/AreasSubPages.js b/src/Components/AreasSubPages.js index bbd12897bf3de1689c3f32f1ae4b7048e81defb6..074fd927a6a295f87908e5fb8304b152fff42655 100644 --- a/src/Components/AreasSubPages.js +++ b/src/Components/AreasSubPages.js @@ -29,14 +29,17 @@ import { Carousel } from 'react-responsive-carousel'; import recursos from "../img/ilustra_recursos_digitais.png"; import materiais from "../img/ilustra_materiais.png"; import colecoes from "../img/ilustra_colecoes.png"; +import Grid from '@material-ui/core/Grid'; + const areaStyle={ paddingTop: "5px", fontSize: "16px", textAlign:"left", backgroundColor: "inherit", - width: "700px", + width: "1000px", + margin: "auto", padding: "20px", - minHeight: "150px" + minHeight: "190px" } class ReqResources extends Component{ @@ -156,11 +159,19 @@ class SubPages extends Component{ <React.Fragment> <div style={{backgroundColor: "#ff7f00"}}> <Container style={areaStyle}> - <img src={recursos} alt="aba recursos" height="100" style={{float: "left"}}/> - <p>Nesta área, você tem acesso a Recursos Educacionais Digitais, isto é, - a vÃdeos, animações e a outros recursos destinados à educação. São Recursos - de portais parceiros do MEC e de professores que, como você, atuam na - Educação Básica!</p> + <Grid container style={{display:"flex"}} spacing={5}> + <Grid item xs={3} > + <img src={recursos} alt="aba recursos" height="155" style={{float: "right"}}/> + </Grid> + <Grid item xs={9}> + <p style={{textAlign: "justify", color:"#fff"}}> + Nesta área, você tem acesso a Recursos Educacionais Digitais, isto é, + a vÃdeos, animações e a outros recursos destinados à educação. São Recursos + de portais parceiros do MEC e de professores que, como você, atuam na + Educação Básica! + </p> + </Grid> + </Grid> </Container> </div> <Container style={{padding:"20px"}}> @@ -180,7 +191,8 @@ class SubPages extends Component{ <React.Fragment> <div style={{backgroundColor: "#e81f4f"}}> <Container style={areaStyle}> - <img src={materiais} alt="aba materiais" height="100" style={{float: "left"}}/> + + <img src={materiais} alt="aba materiais" height="165" style={{float: "right"}}/> <p>Nesta área, você acessa livremente materiais completos de formação, como cursos já oferecidos pelo MEC e seus parceiros. São conteúdos elaborados por equipes multidisciplinares e de autoria de pesquisadores diff --git a/src/Components/Checkbox.js b/src/Components/Checkbox.js index 9e497b4cc68267ba337fb8d3c89b72fbcf22ecf5..3e0be625c424542d75bd13680417450a409f410d 100644 --- a/src/Components/Checkbox.js +++ b/src/Components/Checkbox.js @@ -25,10 +25,9 @@ const StyledFormControlLabel = styled(FormControlLabel)` .label { font-size : 12px !important; } -` - -const StyledCheckbox = styled(Checkbox)` - color : #00bcd4 !important; + .MuiCheckbox-colorSecondary.Mui-checked { + color : #00bcd4 !important; + } ` export default function LabeledCheckbox(props) { @@ -36,8 +35,7 @@ export default function LabeledCheckbox(props) { return ( <StyledFormControlLabel control={ - <StyledCheckbox - disabled = {props.disabledCheckbox} + <Checkbox value = {props.checked} onChange = {props.handleChange} /> diff --git a/src/Components/ColaborarModal.js b/src/Components/ColaborarModal.js index 29d6dc499501ed400765614c4c1d7d310b5f761c..395f305fab1546d612c17c80df513fb5f1eda9cd 100644 --- a/src/Components/ColaborarModal.js +++ b/src/Components/ColaborarModal.js @@ -1,4 +1,4 @@ -import React, {useContext} from 'react'; +import React, {useContext, useState} from 'react'; import Modal from '@material-ui/core/Modal'; import Fade from '@material-ui/core/Fade'; import styled from 'styled-components' @@ -9,7 +9,7 @@ import CloseIcon from '@material-ui/icons/Close'; import LabeledCheckbox from "../Components/Checkbox.js" const StyledDivContainer = styled.div` - background-color : rgb(255,255,255);; + background-color : rgb(255,255,255); border-radius : 4px; border-shadow : #000; color : rgb(102,102,102); @@ -25,7 +25,7 @@ const StyledDivHeader = styled.div` text-align : center; display : flex; justify-content : space-between; - padding : 10px 58px 0 58px; + padding : 10px 26px 0 26px; color : #666; font-size : 40px; font-weight : 400; @@ -34,7 +34,7 @@ const StyledDivHeader = styled.div` ` const StyledDivDialogContent = styled.div` - padding : 20px 30px; + padding : 20px 0; ` const StyledButtonsDiv = styled.div` @@ -45,6 +45,7 @@ const StyledButtonsDiv = styled.div` const StyledButton = styled(Button)` background-color : #00acc1 !important; + width : 45% ` const StyledH2 = styled.h2` @@ -77,6 +78,8 @@ const Styledspan = styled.span` export default function ColaborarModal (props) { const {state, dispatch} = useContext(Store) + const [checkbox, controlCheckbox] = useState(false) + const handleCheckbox = () => controlCheckbox(!checkbox) return ( <StyledModal @@ -95,6 +98,7 @@ export default function ColaborarModal (props) { <Fade in={props.open}> <StyledDivContainer> <StyledDivHeader> + <span style={{width:"32px"}}/> <StyledH2> Você é professor(a), da educação básica, e gostaria de colaborar com a Plataforma? </StyledH2> @@ -111,7 +115,7 @@ export default function ColaborarModal (props) { }} > <div style={{maxWidth:"350px", marginRight:"0", marginLeft:"auto", color:"#666"}}> - <p style={{textAlign:"start", fontSize:"15px", margin:"0 0 10"}}> + <p style={{textAlign:"justify", fontSize:"15px", margin:"0 0 10"}}> Ao ser identificado como professor(a), você poderá <span style={{color:"#00bcd4"}}> publicar e compartilhar recursos educacionais digitais </span> na plataforma com toda a comunidade escolar do paÃs. @@ -126,7 +130,7 @@ export default function ColaborarModal (props) { </StyledButtonsDiv> </div> <div style={{display:"flex", alignItems:"flex-start"}}> - <LabeledCheckbox label={<Styledspan>Não perguntar novamente</Styledspan>} /> + <LabeledCheckbox label={<Styledspan>Não perguntar novamente!</Styledspan>} checked={checkbox} handleChange={handleCheckbox}/> </div> </StyledDivContentInformation> </StyledDivDialogContent> diff --git a/src/Components/ComponentAlterarAvatar.js b/src/Components/ComponentAlterarAvatar.js new file mode 100644 index 0000000000000000000000000000000000000000..5ce25f28809d22e7b70eb8be1f9a3a29d9a2d9b7 --- /dev/null +++ b/src/Components/ComponentAlterarAvatar.js @@ -0,0 +1,229 @@ +/*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,Component} from 'react'; +import { Button } from '@material-ui/core'; +import Modal from '@material-ui/core/Modal'; +import Backdrop from '@material-ui/core/Backdrop'; +import Zoom from '@material-ui/core/Fade'; +import styled from 'styled-components' +import {Store} from '../Store.js' +import axios from 'axios' +import {apiUrl} from '../env'; +import CloseIcon from '@material-ui/icons/Close'; +import Profile from '../img/default_profile0.png' + +const ChangeAvatarDiv = styled.div` + color : rgba(255,255,255,.7); + background-color:rgba(0,0,0,.5); + position: absolute; + bottom: 0; + width: inherit; + text-align: center; + font-size: 18px; + padding-bottom: 5px; + font-weight: 400; + height: 30%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +` + + +const ModalDiv = styled.div` + background-color : #fff; + border-radius : 4px; + min-width : 560px; + color : #666; + display: flex; + flex-direction : column; +` + +const StyledButtonConfirmar = styled(Button)` + background-color : #00acc1 !important; + color: #fff !important; + display: inline-block !important; + position: relative !important; + cursor: pointer !important; + min-height: 36px !important; + min-width: 88px !important; + line-height: 36px !important; + vertical-align: middle !important; + align-items: center !important; + text-align: center !important; + border-radius: 4px !important; + box-sizing: border-box !important; + user-select: none !important; + border: 0 !important; + padding: 0 6px !important; + margin: 6px 8px !important; + background: transparent !important; + background-color: transparent !important; + color: currentColor !important; + white-space: nowrap !important; + text-transform: uppercase !important; + font-weight: 500 !important; + font-size: 14px !important; + font-style: inherit !important; + font-variant: inherit !important; + font-family: inherit !important; + text-decoration: none !important; + overflow: hidden !important; +` + +const ButtonCancelar = styled(Button)` + outline : none !important; + display: inline-block !important; + position: relative !important; + cursor: pointer !important; + min-height: 36px !important; + min-width: 88px !important; + line-height: 36px !important; + vertical-align: middle !important; + align-items: center !important; + text-align: center !important; + border-radius: 3px !important; + box-sizing: border-box !important; + user-select: none !important; + border: 0 !important; + padding: 0 6px !important; + margin: 6px 8px !important; + background:transparent !important; + color: currentColor !important; + white-space: nowrap !important; + text-transform: uppercase !important; + font-weight: 500 !important; + font-size: 14px !important; + font-style: inherit !important; + font-variant: inherit !important; + font-family: inherit !important; + text-decoration: none !important; + overflow: hidden !important; +` + +const ButtonsDiv = styled.div` + display : flex; + justify-content:flex-end; +` + +const AvatarCircleDiv = styled.div` + margin-bottom : 0; + border-radius : 50%; + height : 150px; + width : 150px; + position : relative; + overflow: hidden; +` + +const DivFlowHolder =styled.div` + align-self : auto; +` + +const DivAlterarFoto = styled.div` + display : flex; + margin-bottom : 30px; + flex-direction : row; + align-items : center; + justify-content :center; +` + +const DialogDiv = styled.div` + padding : 20px 30px; + overflow : visible !important; +` + +const HeaderDiv = styled.div` + display : flex; + flex-direction : row; + align-items : center; + align-content : center; + justify-content : center; + max-width : 100%; +` +const StyledH2 = styled.h2` + font-size : 26px; + font-weight : lighter; + margin-top : 20px; + margin-bottom : 10px; + font-family: inherit; + line-height: 1.1; + color: inherit; +` +const StyledCloseModalButton = styled(Button)` + display : inline-block; + position : relative; + float : right !important; + margin-right : -8px !important; + background : transparent !important; + min-width: 0 !important; + width : 40px; + border-radius : 50%; + padding : 8px; + height : 40px; + margin : 0 6px; +` + +export default function ComponentAlterarAvatar (props) { + return ( + <ModalDiv style={{maxWidth:"500px", maxHeight:"500px"}}> + <HeaderDiv> + <span style={{width:"32px"}}/> + <StyledH2>Editar Foto</StyledH2> + <StyledCloseModalButton onClick={props.handleClose}> + <CloseIcon/> + </StyledCloseModalButton> + </HeaderDiv> + <DialogDiv> + <div style={{marginTop:"0"}}> + <form> + <DivAlterarFoto> + <DivFlowHolder> + <AvatarCircleDiv> + { + props.userAvatar == '' || props.userAvatar == null ? + ( + + <img src={Profile} alt={'user avatar'} style={{height:"inherit", width:"inherit", objectFit:"cover"}}/> + ): + ( + <img src={this.props.userAvatar} alt={'user avatar'} style={{height:"inherit", width:"inherit", objectFit:"cover"}}/> + ) + } + <input accept="image/*" id="icon-button-file" + type="file" + onChange={(e) => props.handleFile(e.target.files) } + style={{display:"none"}}/> + <label for="icon-button-file" style={{width:"inherit"}}> + <ChangeAvatarDiv > + <span>Alterar</span> + </ChangeAvatarDiv> + </label> + </AvatarCircleDiv> + </DivFlowHolder> + </DivAlterarFoto> + <ButtonsDiv> + <ButtonCancelar onClick={props.handleClose}><span>Cancelar</span></ButtonCancelar><StyledButtonConfirmar><span>Salvar Alterações</span></StyledButtonConfirmar> + </ButtonsDiv> + </form> + </div> + </DialogDiv> + </ModalDiv> + ) + +} diff --git a/src/Components/FormInput.js b/src/Components/FormInput.js index 60b74706cbad2b228901e0c14c63f8b491f8d5c3..1b1a64aac071528700c2bc26c3dc3b19da5a472c 100644 --- a/src/Components/FormInput.js +++ b/src/Components/FormInput.js @@ -42,7 +42,7 @@ const useStyles = makeStyles(theme => ({ maxWidth: '100%', fontSize : '15px', fontWeight : 'lighter', - color : 'inherit', + color : '#00bcd4', width : '100%', }, })); @@ -52,7 +52,6 @@ export default function FormInput(props) { return ( - <StyledTextField id="standard-basic" label={props.placeholder} @@ -67,9 +66,14 @@ export default function FormInput(props) { error = {props.error} rowsMax = {props.rowsMax} InputProps={{className: classes.input}} + required = {props.required} + error = {props.error} + helperText ={props.help} style={{width:"100%"}} - multiline = {props.multi} + mask={props.mask} + multiline={props.multi} + rows={props.rows} + rowsMax={props.rowMax} /> - ); } diff --git a/src/Components/FormValidationFunction.js b/src/Components/FormValidationFunction.js new file mode 100644 index 0000000000000000000000000000000000000000..c7a8407c5de125cbe34c97d559d6614296e5bfe9 --- /dev/null +++ b/src/Components/FormValidationFunction.js @@ -0,0 +1,45 @@ +import React from 'react' + +//fieldName : form field name +//userInput : user input for a given field +//confirmation : optional password confirmation argument +export default function ValidateUserInput (fieldName, userInput, confirmation) { + let flag = false + + switch(fieldName) { + case('username'): + if (userInput.length < 1) { + flag = true + } + break; + case('email'): + if(userInput.length < 7 || !(userInput.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i))) { + flag = true + } + break; + case('password'): + if (userInput.length < 8) { + flag = true + } + break; + case('confirmation'): + if (userInput !== confirmation) { + flag = true + } + break; + case('message'): + if(userInput.length === 0) { + flag = true + } + break; + case('aboutMe'): + if(userInput.length > 160) { + flag = true + } + break; + default: + break; + } + + return flag +} diff --git a/src/Components/Header.js b/src/Components/Header.js index 623b91e17f4f2d69f68badcef2e427b4aaeec4d8..c7821b5a43e2b539b9cad953105cfc43a45ec879 100644 --- a/src/Components/Header.js +++ b/src/Components/Header.js @@ -25,16 +25,32 @@ import SignUpModal from './SignUpModal' import LoginModal from './LoginModal' import { Store } from '../Store'; import ColaborarModal from './ColaborarModal.js' - +import Snackbar from '@material-ui/core/Snackbar'; +import MuiAlert from '@material-ui/lab/Alert'; //const StyledButton = styled(Button)` // background : #ffa54c !important; // boxShadow :none; //` +function Alert(props) { + return <MuiAlert elevation={6} variant="filled" {...props} />; +} + + export default function Header(props){ const { state, dispatch } = useContext(Store) const [signUpOpen, setSignUp] = useState(false) const [loginOpen, setLogin] = useState(false) + const [successfulLoginOpen, handleSuccessfulLogin] = useState(false) + const [modalColaborar, setModalColaborar] = useState(false) + + const toggleSnackbar = (event, reason) => { + if (reason === 'clickaway') { + return; + } + + handleSuccessfulLogin(false); + } const handleSignUp = () => { setSignUp(!signUpOpen) @@ -54,13 +70,18 @@ export default function Header(props){ return( <> <AcessibilityBar/> + <Snackbar open={successfulLoginOpen} autoHideDuration={1000} onClose={toggleSnackbar} + anchorOrigin = {{ vertical:'top', horizontal:'middle' }} + > + <Alert severity="success" style={{backgroundColor:"#00acc1"}}>Você está conectado(a)!</Alert> + </Snackbar> <MenuBar openSearchBar={handleClickSearch} openSignUp = {handleSignUp} openLogin = {handleLogin}/> { state.searchOpen && <SearchBar/> } <SignUpModal open={signUpOpen} handleClose={handleSignUp} openLogin={handleLogin}/> - <LoginModal open={loginOpen} handleClose={handleLogin} openSignUp={handleSignUp}/> - {/*<ColaborarModal open={state.modalColaborarPlataformaOpen} handleClose={handleKyloren} />*/} + <LoginModal open={loginOpen} handleClose={handleLogin} openSignUp={handleSignUp} openSnackbar = {() => {handleSuccessfulLogin(true)}}/> + <ColaborarModal open={modalColaborar} handleClose={() => {setModalColaborar(!modalColaborar)}} /> </> ) diff --git a/src/Components/IllegalContentModal.js b/src/Components/IllegalContentModal.js index f623587ac501efc859c5edc5b87d42b6c714ac34..7b2060f5d40fec1594801d148248e21257dcfea9 100644 --- a/src/Components/IllegalContentModal.js +++ b/src/Components/IllegalContentModal.js @@ -112,7 +112,7 @@ export default function IllegalContentModal (props) { <Fade in={props.open}> <StyledDivContainer > <StyledDivContent> - <StyledH2>{state.loginInfo.username}!</StyledH2> + <StyledH2>{state.currentUser.username}!</StyledH2> <div> <StyledParagraph>Seu recurso não está de acordo com os termos</StyledParagraph> </div> diff --git a/src/Components/LoadingSpinner.js b/src/Components/LoadingSpinner.js new file mode 100644 index 0000000000000000000000000000000000000000..ffeec90992457ab00d31c18dff77e14ba0d40b61 --- /dev/null +++ b/src/Components/LoadingSpinner.js @@ -0,0 +1,11 @@ +import React from 'react'; +import LoadingGif from '../img/loading_busca.gif' + + const LoadingSpinner = (props) => ( + <div style={{display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center"}}> + <img src={LoadingGif} /> + <span style={{textTransform:"uppercase"}}>{props.text}</span> + </div> + ); + + export default LoadingSpinner; diff --git a/src/Components/LoginContainer.js b/src/Components/LoginContainer.js index c148704c53c34f48bec95f21d711922e16c79820..ccdc075a1565fb8a139d21a0c8ffe1f951555fc1 100644 --- a/src/Components/LoginContainer.js +++ b/src/Components/LoginContainer.js @@ -24,6 +24,7 @@ import styled from 'styled-components' import {device} from './device.js' import LabeledCheckbox from './Checkbox.js' import FormInput from "./FormInput.js" +import GoogleLogo from "../img/logo_google.svg" //arrumar isso const responseGoogle = (response) => { @@ -35,9 +36,9 @@ class LoginContainer extends Component { super(props); this.state = { - email : "", - senha : "", - checkboxChecked : true + email : localStorage.getItem("@portalmec/email") || "", + senha : localStorage.getItem("@portalmec/senha") ||"", + checkboxChecked : false }; this.handleChecked = this.handleChecked.bind(this) } @@ -54,8 +55,9 @@ class LoginContainer extends Component { onSubmit = (e) => { e.preventDefault(); + const login = this.state - this.props.handleLoginInfo(this.state); + this.props.handleLoginInfo(login); this.setState({ email: "", @@ -64,8 +66,11 @@ class LoginContainer extends Component { } handleChecked = (e) => { + const value = !this.state.checkboxChecked + console.log(this.state.checkboxChecked) + console.log(value) this.setState({ - checkboxChecked : !this.state.checkboxChecked + checkboxChecked :value }) } @@ -73,15 +78,16 @@ class LoginContainer extends Component { return ( <ContainerStyled > <DialogHeaderStyled> + <span style={{width:"32px"}}/> <H2Styled> Entrar - <StyledCloseModalButton onClick={this.props.handleClose}> - <CloseIcon/> - </StyledCloseModalButton> </H2Styled> + <StyledCloseModalButton onClick={this.props.handleClose}> + <CloseIcon/> + </StyledCloseModalButton> </DialogHeaderStyled> - <div style={{paddingTop: "20px"}}> - <div style={{marginTop:"0"}}> + <DialogContentDiv> + <SocialConnectDiv> <StyledGoogleLoginButton clientId="658977310896-knrl3gka66fldh83dao2rhgbblmd4un9.apps.googleusercontent.com" @@ -89,50 +95,54 @@ class LoginContainer extends Component { onFailure={responseGoogle} cookiePolicy={'single_host_origin'} > - <span style={{textTransform:"none", fontSize:"13px"}}>Usando o Google</span> + <span style={{textTransform:"none", fontSize:"13px", color : "#666"}}>Usando o Google</span> </StyledGoogleLoginButton> - </div> - </div> - - <H3Styled> - <RightSideStrikedH3/> - <span style={{verticalAlign:"middle"}}>ou</span> - <LeftSideStrikedH3/> - </H3Styled> - - <form ref="form" onSubmit={this.onSubmit}> - <FormInput - inputType={"text"} - name={"email"} - value={this.state.email} - placeholder={"E-mail *"} - handleChange={e => this.handleChange(e)} - /> - <br/> - <FormInput - inputType={"password"} - name={"senha"} - value={this.state.senha} - placeholder={"Senha *"} - handleChange={e => this.handleChange(e)} - /> - <br/> - - <RememberRecover> - <LabeledCheckbox label={<StyledSpan>Lembrar-me</StyledSpan>} onchange={this.handleChecked}/> - <span style={{paddingTop:"15px"}}>Esqueceu a senha?<a href="recuperar-senha" style={{textAlign: "right", color:"#4cd0e1"}}>Clique aqui!</a></span> - </RememberRecover> - - <ConfirmContainerStyled> - <StyledLoginButton onClick={e => this.onSubmit(e)} variant="contained"> - <span style={{borderRadius:"3px", boxSizing:"border-box", fontFamily:"Roboto, sans serif", fontWeight:"500", color:"#fff"}}>ENTRAR</span> - </StyledLoginButton> - </ConfirmContainerStyled> - </form> - - <DialogFooterStyled> - <span style={{textAlign:"center", fontSize: "14px", color:"rgb(102, 102, 102)"}}>Ainda não tem cadastro? <StyledAnchor href="" onClick={e => this.switchModal(e)}>CADASTRE-SE</StyledAnchor></span> - </DialogFooterStyled> + </SocialConnectDiv> + + <H3Div> + <H3Styled> + <RightSideStrikedH3/> + <span style={{verticalAlign:"middle"}}>ou</span> + <LeftSideStrikedH3/> + </H3Styled> + </H3Div> + + <form ref="form" onSubmit={this.onSubmit}> + <FormInput + inputType={"text"} + name={"email"} + value={this.state.email} + placeholder={"E-mail"} + handleChange={e => this.handleChange(e)} + required={true} + /> + <br/> + <FormInput + inputType={"password"} + name={"senha"} + value={this.state.senha} + placeholder={"Senha"} + handleChange={e => this.handleChange(e)} + required={true} + /> + <br/> + + <RememberRecover> + <LabeledCheckbox label={<StyledLabel><StyledSpan>Lembrar-me</StyledSpan></StyledLabel>} handleChange={this.handleChecked} /> + <UserForgotTheirPasswordSpan>Esqueceu a senha? <a href="recuperar-senha" style={{textAlign: "right", color:"#4cd0e1"}}>Clique aqui!</a></UserForgotTheirPasswordSpan> + </RememberRecover> + + <ConfirmContainerStyled> + <StyledLoginButton type="submit" variant="contained"> + <span style={{borderRadius:"3px", boxSizing:"border-box", fontFamily:"Roboto, sans serif", fontWeight:"500", color:"#fff"}}>ENTRAR</span> + </StyledLoginButton> + </ConfirmContainerStyled> + </form> + + <DialogFooterStyled> + <span style={{textAlign:"center", fontSize: "14px", color:"rgb(102, 102, 102)"}}>Ainda não tem cadastro? <StyledAnchor href="" onClick={e => this.switchModal(e)}>CADASTRE-SE</StyledAnchor></span> + </DialogFooterStyled> + </DialogContentDiv> </ContainerStyled> ) } @@ -144,24 +154,68 @@ const ContainerStyled = styled.div` box-sizing : border-box; background-color : white; max-width : none; + display : flex; + flex-direction : column; + min-width : 440px; + min-height : 550px; align : center; - padding-left : 25px; - padding-right:25px; - padding-bottom:10px; + padding : 10px; border-radius: 4px; + line-height : 20px; + font-size : 14px; @media ${device.mobileM} { width : 100%; height : 100%; } ` -const DialogHeaderStyled = styled.div` +export const DialogHeaderStyled = styled.div` text-align : center; - display : inline-flex; + display : flex; + flex-direction : row; justify-content : space-between; padding : 10px 26px 0 26px; height : 64px; ` +const H2Styled = styled.h2` + align-self : center; + color : #666; + font-size : 26px; + font-weight : 100; + font-family: 'Roboto', sans serif, 'Helvetica Neue', Helvetica, Arial, sans-serif !important; + justify-content: space-between; + text-align: center; + letter-spacing: .005em; +` + +export const StyledCloseModalButton = styled(Button)` + display : inline-block; + position : relative; + float : right !important; + margin-right : -8px !important; + background : transparent !important; + min-width: 0 !important; + width : 40px; +` +export const DialogContentDiv = styled.div` + padding : 20px 30px; + overflow : visible !important; +` + +export const SocialConnectDiv = styled.div` + margin-top : 0; + display : flex; + flex-direction : row; +` +export const StyledGoogleLoginButton = styled(GoogleLogin)` + background-color : #fff !important; + color : #666 !important; + border : 1px solid rgb(66, 133, 244); + box-shadow: 0 0 0 1px #4285f4 !important; + :hover { + background-color: #f4f4f4 !important; + } +` const DialogFooterStyled = styled.div` box-sizing : border-box; @@ -174,17 +228,6 @@ const DialogFooterStyled = styled.div` line-height : 1.42857143 ` -const H2Styled = styled.h2` - align-self : center; - color : #666; - font-size : 26px; - font-weight : 100; - font-family: 'Roboto', sans serif, 'Helvetica Neue', Helvetica, Arial, sans-serif !important; - justify-content: space-between; - padding: 10px 26px 0 26px; - text-align: center; - letter-spacing: .005em; -` const RightSideStrikedH3 = styled.div` display : inline-block; @@ -203,13 +246,10 @@ const LeftSideStrikedH3 = styled.div` margin-left : 5px; width : 45%; ` -const StyledGoogleLoginButton = styled(GoogleLogin)` - background-color: fff; - border : 1px solid rgb(66, 133, 244); - box-shadow: 0 0 0 1px #4285f4 !important; - :hover { - background-color: #f4f4f4 !important; - } + +export const H3Div = styled.div` + margin-top : 0; + margin-bottom : 10px; ` const H3Styled = styled.h3` @@ -224,24 +264,14 @@ const StyledAnchor = styled.a` color : #00bcd4; text-decoration : none; ` -const StyledCloseModalButton = styled(Button)` - display : inline-block; - position : relative; - float : right !important; - margin-right : -8px; - background : transparent; - min-width: 0 !important; - width : 40px; -` const ConfirmContainerStyled = styled.div` display : flex; margin-top : 10px; align-items : center; justify-content : center; - box-sizing : border-box; ` const StyledLoginButton = styled(Button)` - background-color: #00bcd4 !important; + background-color : #00bcd4 !important; box-shadow : none !important; outline: none !important; border : 0 !important; @@ -259,15 +289,32 @@ const StyledLoginButton = styled(Button)` } ` + const RememberRecover = styled.div` display : flex; justify-content : space-between; font-size: 12px; font-weight : 400; - margin-bottom: 16px; ` + +const StyledLabel = styled.div` + box-sizing : border-box; + position : relative; + vertical-align : middle !important; + color : #666; + +` + +const UserForgotTheirPasswordSpan = styled.span` + margin-top : 1em; + font-size : 12px; + font-weight : 400; + text-align : right; + color : #666; +` + const StyledSpan = styled.span` - font-size: 12px; - font-weight: 400; - padding-top: 2px; + font-size : 12px; + font-weight : 400; + padding-top : 2px; ` diff --git a/src/Components/LoginContainerFunction.js b/src/Components/LoginContainerFunction.js new file mode 100644 index 0000000000000000000000000000000000000000..38150d43eede273208f5ea3da943ef994654b83f --- /dev/null +++ b/src/Components/LoginContainerFunction.js @@ -0,0 +1,345 @@ +/*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, {useState} from "react"; +import GoogleLogin from 'react-google-login' +import { Button } from '@material-ui/core'; +//import FacebookLogin from 'react-facebook-login'; +import CloseIcon from '@material-ui/icons/Close'; +import styled from 'styled-components' +import {device} from './device.js' +import LabeledCheckbox from './Checkbox.js' +import FormInput from "./FormInput.js" +import GoogleLogo from "../img/logo_google.svg" +import ValidateUserInput from '../Components/FormValidationFunction.js' + +export default function LoginContainer (props) { + const [formEmail, setEmail] = useState( + { + key : false, + value : localStorage.getItem("@portalmec/email") || "", + } + ) + + const [formSenha, setSenha] = useState( + { + key : false, + value : localStorage.getItem("@portalmec/senha") ||"" + } + ) + + const [checkboxControl, setCheckbox] = useState(false) + + const switchModal = (e) => { + e.preventDefault() + props.handleClose() + props.openSignUp() + } + + const handleChange = (e, type) => { + const userInput = e.target.value + const flag = ValidateUserInput(type, userInput) + + if(type === 'email') { + setEmail({...formEmail, + key : flag, + value : userInput + }) + console.log(formEmail) + } + else if(type === 'password') { + setSenha({...formSenha, + key : flag, + value : userInput + }) + console.log(formSenha) + } + } + + const limpaCamposForm = () => { + setEmail({...formEmail, + key : false, + value : '' + }); + + setSenha({...formSenha, + key : false, + value : '' + }) + } + + const onSubmit = (e) => { + e.preventDefault() + const login = {email : formEmail.value, senha : formSenha.value, checkbox : checkboxControl} + + if (!(formEmail.key || formSenha.key)) { + props.handleLoginInfo(login) + limpaCamposForm() + } + + } + + //arrumar isso + const responseGoogle = (response) => { + console.log(response); + } + + return ( + <div> + <ContainerStyled > + <DialogHeaderStyled> + <span style={{width:"32px"}}/> + <H2Styled> Entrar + </H2Styled> + <StyledCloseModalButton onClick={props.handleClose}> + <CloseIcon/> + </StyledCloseModalButton> + </DialogHeaderStyled> + + <DialogContentDiv> + <SocialConnectDiv> + <StyledGoogleLoginButton + clientId="658977310896-knrl3gka66fldh83dao2rhgbblmd4un9.apps.googleusercontent.com" + onSuccess={responseGoogle} + onFailure={responseGoogle} + cookiePolicy={'single_host_origin'} + > + <span style={{textTransform:"none", fontSize:"13px", color : "#666"}}>Usando o Google</span> + </StyledGoogleLoginButton> + </SocialConnectDiv> + + <H3Div> + <H3Styled> + <RightSideStrikedH3/> + <span style={{verticalAlign:"middle"}}>ou</span> + <LeftSideStrikedH3/> + </H3Styled> + </H3Div> + + <form onSubmit={e => onSubmit(e)}> + <FormInput + inputType={"text"} + name={"email"} + value={formEmail.value} + placeholder={"E-mail"} + handleChange={e => handleChange(e, 'email')} + required={true} + error = {formEmail.key} + help = {formEmail.key ? ( formEmail.value.length == 0 ? "Faltou preencher seu e-mail." : <span>Insira um endereço de e-mail válido.<br/>Por exemplo: seunome@gmail.com, seunome@hotmail.com</span>) : ""} + /> + <br/> + <FormInput + inputType={"password"} + name={"senha"} + value={formSenha.value} + placeholder={"Senha"} + handleChange={e => handleChange(e, 'password')} + required={true} + error = {formSenha.key} + help = {formSenha.key ? (formSenha.value.length == 0 ? "Faltou digitar sua senha." : "A senha precisa ter no mÃnimo 8 caracteres.") : ""} + /> + <br/> + + <RememberRecover> + <LabeledCheckbox label={<StyledLabel><StyledSpan>Lembrar-me</StyledSpan></StyledLabel>} handleChange={() => setCheckbox(!checkboxControl)}/> + <UserForgotTheirPasswordSpan>Esqueceu a senha? <a href="recuperar-senha" style={{textAlign: "right", color:"#4cd0e1"}}>Clique aqui!</a></UserForgotTheirPasswordSpan> + </RememberRecover> + + <ConfirmContainerStyled> + <StyledLoginButton type="submit" variant="contained"> + <span style={{borderRadius:"3px", boxSizing:"border-box", fontFamily:"Roboto, sans serif", fontWeight:"500", color:"#fff"}}>ENTRAR</span> + </StyledLoginButton> + </ConfirmContainerStyled> + </form> + + <DialogFooterStyled> + <span style={{textAlign:"center", fontSize: "14px", color:"rgb(102, 102, 102)"}}>Ainda não tem cadastro? <StyledAnchor href="" onClick={e => switchModal(e)}>CADASTRE-SE</StyledAnchor></span> + </DialogFooterStyled> + </DialogContentDiv> + </ContainerStyled> + </div> + ) +} + + + const ContainerStyled = styled.div` + box-sizing : border-box; + background-color : white; + max-width : none; + display : flex; + flex-direction : column; + min-width : 440px; + + align : center; + padding : 10px; + border-radius: 4px; + line-height : 20px; + font-size : 14px; + @media ${device.mobileM} { + width : 100%; + height : 100%; + } + ` + + export const DialogHeaderStyled = styled.div` + text-align : center; + display : flex; + flex-direction : row; + justify-content : space-between; + padding : 10px 26px 0 26px; + height : 64px; + ` + const H2Styled = styled.h2` + align-self : center; + color : #666; + font-size : 26px; + font-weight : 100; + font-family: 'Roboto', sans serif, 'Helvetica Neue', Helvetica, Arial, sans-serif !important; + justify-content: space-between; + text-align: center; + letter-spacing: .005em; + ` + + export const StyledCloseModalButton = styled(Button)` + display : inline-block; + position : relative; + float : right !important; + margin-right : -8px !important; + background : transparent !important; + min-width: 0 !important; + width : 40px; + ` + export const DialogContentDiv = styled.div` + padding : 20px 30px; + overflow : visible !important; + ` + + export const SocialConnectDiv = styled.div` + margin-top : 0; + display : flex; + flex-direction : row; + ` + export const StyledGoogleLoginButton = styled(GoogleLogin)` + background-color : #fff !important; + color : #666 !important; + border : 1px solid rgb(66, 133, 244); + box-shadow: 0 0 0 1px #4285f4 !important; + :hover { + background-color: #f4f4f4 !important; + } + ` + + const DialogFooterStyled = styled.div` + box-sizing : border-box; + font-family : 'Roboto', sans serif; + margin : 20px -20px; + padding-top : 20px; + border-top : 1px #e5e5e5 solid; + justify-content : center; + text-align : center; + line-height : 1.42857143 + ` + + +export const RightSideStrikedH3 = styled.div` + display : inline-block; + border-bottom: 1px dotted #666; + vertical-align : middle; + font-weight : 500; + margin-right : 5px; + width : 45%; + ` + + export const LeftSideStrikedH3 = styled.div` + display : inline-block; + border-bottom: 1px dotted #666; + vertical-align : middle; + font-weight : 500; + margin-left : 5px; + width : 45%; + ` + + export const H3Div = styled.div` + margin-top : 0; + margin-bottom : 10px; + ` + + const H3Styled = styled.h3` + overflow : hidden; + text-align : center; + font-size : 14px; + color : #666; + margin : 10px 0; + ` + + const StyledAnchor = styled.a` + color : #00bcd4; + text-decoration : none; + ` + const ConfirmContainerStyled = styled.div` + display : flex; + margin-top : 10px; + align-items : center; + justify-content : center; + ` + const StyledLoginButton = styled(Button)` + background-color : #00bcd4 !important; + box-shadow : none !important; + outline: none !important; + border : 0 !important; + overflow : hidden !important; + width : 35% !important; + display : inline-block !important; + font-family : 'Roboto', sans serif !important; + font-size: 14px !important; + height : 36px !important; + align-items : center !important; + border-radius: 3px !important; + align-self : 50% !important; + :hover { + background-color : #00acc1 !important; + } + ` + + + const RememberRecover = styled.div` + display : flex; + justify-content : space-between; + font-size: 12px; + font-weight : 400; + ` + + const StyledLabel = styled.div` + box-sizing : border-box; + position : relative; + vertical-align : middle !important; + color : #666; + ` + + const UserForgotTheirPasswordSpan = styled.span` + margin-top : 1em; + font-size : 12px; + font-weight : 400; + text-align : right; + color : #666; + ` + + const StyledSpan = styled.span` + font-size : 12px; + font-weight : 400; + padding-top : 2px; + ` diff --git a/src/Components/LoginModal.js b/src/Components/LoginModal.js index 1652dc66f76984373b739f1a4ea692a3ef389ca7..df1be6a4871c4de3a0042884f643567171f34294 100644 --- a/src/Components/LoginModal.js +++ b/src/Components/LoginModal.js @@ -16,16 +16,18 @@ 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} from 'react'; +import React, {useContext, useState} from 'react'; import { Button } from '@material-ui/core'; import Modal from '@material-ui/core/Modal'; import Backdrop from '@material-ui/core/Backdrop'; -import Fade from '@material-ui/core/Fade'; +import Zoom from '@material-ui/core/Fade'; import styled from 'styled-components' -import LoginContainer from './LoginContainer' +import LoginContainer from './LoginContainerFunction.js' import {Store} from '../Store.js' import axios from 'axios' import {apiUrl} from '../env'; +import Snackbar from '@material-ui/core/Snackbar'; +import MuiAlert from '@material-ui/lab/Alert'; const StyledLogin = styled(Modal)` margin : 0 !important; @@ -38,9 +40,22 @@ const StyledLogin = styled(Modal)` border-radius : 4px; ` +export function Alert(props) { + return <MuiAlert elevation={6} variant="filled" {...props} />; +} export default function LoginModal (props){ - const {state, dispatch} = useContext(Store) + const {state, dispatch} = useContext(Store) + + const [snackbarOpened, handleSnackbar] = useState(false) + + const handleCloseSnackbar = (event, reason) => { + if (reason === 'clickaway') { + return; + } + + handleSnackbar(false); + } const handleLoginInfo = (login) => { axios.post(`${apiUrl}/auth/sign_in`, @@ -53,22 +68,41 @@ export default function LoginModal (props){ type: "USER_LOGGED_IN", userLoggedIn: !state.userIsLoggedIn, login: { - username : login.username, - email : login.email, + id : response.data.id, + username : response.data.data.name, + email : response.data.data.email, accessToken : response.headers['access-token'], - client : response.headers.client + clientToken : response.headers.client, + userAvatar : response.data.data.avatar_file_name, + userCover : response.data.data.cover_file_name } } ) props.handleClose(); + props.openSnackbar(); + sessionStorage.setItem('@portalmec/accessToken', response.headers['access-token']) + sessionStorage.setItem('@portalmec/clientToken', response.headers.client,) + sessionStorage.setItem('@portalmec/id', response.data.data.id) + sessionStorage.setItem('@portalmec/username', response.data.data.name) + sessionStorage.setItem('@portalmec/uid', response.data.data.uid) + if (login.checkboxChecked) { + localStorage.setItem('@portalmec/email', login.email) + localStorage.setItem('@portalmec/senha', login.senha) //MUDAR ISSO ASAP + } }, (error) => { - console.log(':()') + {handleSnackbar(true)} } ) } return ( + <> + <Snackbar open={snackbarOpened} autoHideDuration={1000} onClose={handleCloseSnackbar} + anchorOrigin = {{ vertical:'top', horizontal:'right' }} + > + <Alert severity="error">Ocorreu um erro ao se conectar!</Alert> + </Snackbar> <StyledLogin aria-labelledby="transition-modal-title" aria-describedby="transition-modal-description" @@ -82,12 +116,13 @@ export default function LoginModal (props){ timeout: 500, }} > - <Fade in={props.open}> + <Zoom in={props.open} style={{ transitionDelay :"0.2ms"}}> <LoginContainer handleClose={props.handleClose} openSignUp={props.openSignUp} handleLoginInfo={handleLoginInfo} /> - </Fade> + </Zoom> </StyledLogin> + </> ) } diff --git a/src/Components/MenuBar.js b/src/Components/MenuBar.js index fdece9ab7ffd114385dde14e0e26769c9aa89f18..f3632a4c38bbb33a5b3c8ba134f94160a6b17724 100644 --- a/src/Components/MenuBar.js +++ b/src/Components/MenuBar.js @@ -29,7 +29,7 @@ import styled from 'styled-components' import { Store } from '../Store'; import CloudUploadIcon from '@material-ui/icons/CloudUpload'; import Notifications from "./Notifications.js" -import CustomizedMenus from './MenuList' +import MenuList from './MenuList' const ContainerStyled = styled(Container)` *{ text-decoration: none } @@ -51,6 +51,7 @@ const ButtonPublicarRecurso = styled(Button)` border : 1px transparent solid; background-color : #ff7f00 !important; align-content : center; + font-weight : 500 !important; text-transform: capitalize !important; font-stretch : expanded; max-width: 200 !important; @@ -81,6 +82,7 @@ const Left = styled.span ` ` const ButtonPubRecursoStyled = styled(Button)` + font-weight : 500 !important; border : 1.5px #666 solid !important; color: #666; box-shadow: none; @@ -107,13 +109,12 @@ export default function MenuBar(props){ ] const minhaArea = [ - { name: "Perfil e Atividades", href: "/perfil/atualizacoes"}, - { name: "Recursos Publicados", href: "/perfil/recursos-publicados"}, - { name: "Favoritos", href: "/perfil/favoritos"}, - { name: "Coleções", href: "/perfil/colecoes"}, - { name: "Rede", href: "/perfil/rede"}, - { name: "Configurações", href: "/perfil/cofiguracoes/editarperfil"}, - { name: "Sair", href:"/"} + { 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: "Configurações", href: "/editarperfil"}, ] return( @@ -137,7 +138,7 @@ export default function MenuBar(props){ <Link to="/termos-publicar-recurso"> <ButtonPublicarRecurso> <CloudUploadIcon style={{color:"white", marginLeft : "0"}}/> - <span style={{color : "#fff", textAlign: "center", alignSelf : "center", fontWeight:"100"}} > + <span style={{color : "#fff", textAlign: "center", alignSelf : "center", fontWeight:"500"}} > PUBLICAR RECURSO </span> @@ -149,7 +150,7 @@ export default function MenuBar(props){ <Notifications/> </div> - <CustomizedMenus items={minhaArea}/> + <MenuList items={minhaArea}/> </> ] diff --git a/src/Components/MenuList.js b/src/Components/MenuList.js index 5652912f35b10d55da9dc1ba178d80394267e8ae..d3f2a6eaf7a67cc1441e3403da0c06578d1a9c55 100644 --- a/src/Components/MenuList.js +++ b/src/Components/MenuList.js @@ -42,7 +42,7 @@ const OverrideButton = styled(Button)` text-transform : none !important; ` -export default function CustomizedMenus(props) { +export default function MenuList(props) { const [anchorEl, setAnchorEl] = React.useState(null); const { state, dispatch } = useContext(Store) @@ -55,6 +55,7 @@ export default function CustomizedMenus(props) { }; const handleLogout = () => { + localStorage.removeItem('@portalmec/username'); dispatch( { type: 'USER_LOGGED_OUT', userLoggedOut: !state.userIsLoggedIn, @@ -77,7 +78,16 @@ export default function CustomizedMenus(props) { onMouseEnter={handleClick} > - <img src={Profile} alt={''} style={{maxWidth:"50px", maxHeight:"50px", borderRadius:"25px"}}/> + { + state.currentUser.userAvatar == '' || state.currentUser.userAvatar == null ? + ( + + <img src={Profile} alt={''} style={{maxWidth:"50px", maxHeight:"50px", borderRadius:"25px"}}/> + ): + ( + <img src={state.currentUser.userAvatar} alt={''}/> + ) + } <span style={{fontFamily:"inherit", fontWeight:"400", color:"#666"}}>Minha Ãrea </span> <KeyboardArrowDownIcon/> </OverrideButton> @@ -98,10 +108,13 @@ export default function CustomizedMenus(props) { { props.items.map((item)=> - <Link key={item.name} to={item.href} style={{textDecoration:"none"}} ><MenuItem style= {{fontSize:"14px", padding:"5px 20px", color:"#666"}}>{item.name}</MenuItem></Link> - ) + <Link to={{ + pathname : item.href, + state : item.value + }} style={{textDecoration:"none"}} ><MenuItem style= {{fontSize:"14px", padding:"5px 20px", color:"#666"}}>{item.name}</MenuItem></Link> + ) } - <Button onClick={handleLogout} style={{layout:"row", layoutAlign:"space-between-center"}}> <MenuItem>Sair<ExitToAppIcon style={{align:"right"}}/></MenuItem></Button> + <StyledButtonSair onClick={handleLogout}> <StyledMenuItem disableGutters={true}>Sair<StyledExitToAppIcon/></StyledMenuItem></StyledButtonSair> </Menu> @@ -109,6 +122,37 @@ export default function CustomizedMenus(props) { ); } +const StyledButtonSair = styled(Button)` + height : 31px; + width : 177px; + layout : row; + + .listItem { + width : 100% !important; + display : flex !important; + justify-content: space-between !important; + font-size : 14px !important; + color : #a5a5a5 !important; + padding : 5px 20px !important; + } +` + +const StyledExitToAppIcon = styled(ExitToAppIcon) ` + fontSize : 24px; + color : rgb(162,165,165); + align : right; + display : flex; + justify-content : flex-end; +` +const StyledMenuItem = styled(MenuItem)` + display : flex !important; + justify-content: space-between !important; + width : 100% !important; + font-size : 14px !important; + color : #a5a5a5 !important; + padding : 5px 20px !important; +` + //import React from 'react'; //import Button from '@material-ui/core/Button'; //import ClickAwayListener from '@material-ui/core/ClickAwayListener'; diff --git a/src/Components/ModalAlterarAvatar.js b/src/Components/ModalAlterarAvatar.js new file mode 100644 index 0000000000000000000000000000000000000000..8bd1c57e9a0010946d3bf1f40e51bbdd9cfe3ccc --- /dev/null +++ b/src/Components/ModalAlterarAvatar.js @@ -0,0 +1,88 @@ +/*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} from 'react'; +import { Button } from '@material-ui/core'; +import Modal from '@material-ui/core/Modal'; +import Backdrop from '@material-ui/core/Backdrop'; +import Fade from '@material-ui/core/Fade'; +import styled from 'styled-components' +import {Store} from '../Store.js' +import axios from 'axios' +import {apiUrl} from '../env'; +import CloseIcon from '@material-ui/icons/Close'; +import Profile from '../img/default_profile0.png' +import ComponentAlterarAvatar from './ComponentAlterarAvatar.js' + +const StyledModal = styled(Modal)` + display : flex; + align-items: center; + justify-content : center; + text-align : center; + padding : 10px !important; +` + +export default function ModarAlterarAvatar (props){ + const {state, dispatch} = useContext(Store) + const [avatarFile, setFile] = useState('') + const handleLoginInfo = (login) => { + axios.post(`${apiUrl}`, + { + } + ).then( (response) => { + dispatch ({ + + }, (error) => { + + } + ) + }) + } + + const handleFile = (selectorFiles : FileList) => { + console.log(selectorFiles) + {/*setFile()*/} + } + + return ( + + <StyledModal + aria-labelledby="transition-modal-title" + aria-describedby="transition-modal-description" + open={props.open} + animation={true} + centered={true} + onClose={props.handleClose} + closeAfterTransition + BackdropComponent={Backdrop} + BackdropProps={{ + timeout: 500, + }} + > + <Fade in={props.open} style={{ transitionDelay :"0.4ms"}}> + + <ComponentAlterarAvatar + userAvatar={state.currentUser.userAvatar} + handleFile={handleFile} + handleClose={props.handleClose} + /> + </Fade> + </StyledModal> + + ) +} diff --git a/src/Components/PageProfessorComponents/ModalConfirmarProfessor.js b/src/Components/PageProfessorComponents/ModalConfirmarProfessor.js new file mode 100644 index 0000000000000000000000000000000000000000..05d49f3bbc1ef2f412cb6109dc3bd51ceaa3040a --- /dev/null +++ b/src/Components/PageProfessorComponents/ModalConfirmarProfessor.js @@ -0,0 +1,155 @@ +/*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} from 'react'; +import { Button } from '@material-ui/core'; +import Modal from '@material-ui/core/Modal'; +import Backdrop from '@material-ui/core/Backdrop'; +import Fade from '@material-ui/core/Fade'; +import styled from 'styled-components' +import axios from 'axios' +import {apiUrl} from '../../env'; +import CloseIcon from '@material-ui/icons/Close'; + +const StyledModal = styled(Modal)` + display : flex; + align-items: center; + justify-content : center; + text-align : center; + padding : 10px !important; +` + +export default function ModalConfirmarProfessor (props){ + return ( + + <StyledModal + aria-labelledby="transition-modal-title" + aria-describedby="transition-modal-description" + open={props.open} + animation={true} + centered={true} + onClose={props.handleClose} + closeAfterTransition + BackdropComponent={Backdrop} + BackdropProps={{ + timeout: 500, + }} + > + <Fade in={props.open} style={{ transitionDelay :"0.4ms"}}> + <> + <ConfirmarProfessorComponent> + <HeaderDiv> + <span style={{width:"32px"}}/> + <h2>Confirme os Dados</h2> + <Button style={{marginRight:"-8px", color:"000"}} onClick={props.handleClose}> + <CloseIcon style={{color:"#666", cursor:"pointer", verticalAlign:"middle"}}/> + </Button> + </HeaderDiv> + + <DialogContentDiv> + <ContainerCentralized> + <p><strong>MunicÃpio - UF:</strong> {props.info.school_uf.name} - {props.info.school_city} </p> + <p><strong>Escola:</strong> {props.info.school_name}</p> + <p><strong>Telefone da Escola:</strong> {props.info.school_phone}</p> + <p><strong>Seu CPF:</strong> {props.info.teacher_cpf}</p> + <ButtonsDiv> + <ConfirmButton onClick ={props.confirmar}>CONFIRMAR</ConfirmButton> + <CancelButton onClick = {props.cancelar}>CANCELAR</CancelButton> + </ButtonsDiv> + </ContainerCentralized> + </DialogContentDiv> + </ConfirmarProfessorComponent> + </> + </Fade> + </StyledModal> + + ) +} + +const CancelButton = styled(Button)` + width : 140px !important; + color :#666 !important; + font-family : Roboto,sans-serif !important; + font-size : 14px !important; + font-weight : 500 !important; + height : 36px !important; + border-radius : 3px !important; + padding-left : 16px !important; + padding-right : 16px !important; + outline : none !important; + margin : 6px 8px !important; + display : inline-block !important; +` + +const ConfirmButton = styled(Button)` + width : 140px !important; + background-color : #00bcd4 !important; + color : #fff !important; + font-family : Roboto,sans-serif !important; + font-size : 14px !important; + font-weight : 500 !important; + height : 36px !important; + border-radius : 3px !important; + padding-left : 32px !important; + padding-right : 32px !important; + outline : none !important; + margin : 6px 8px !important; + display : inline-block !important; +` + +const ButtonsDiv = styled.div` + margin-top : 10px; + display : flex; + justify-content : center; +` + + +const ContainerCentralized = styled.div` + margin-top : 0; + padding-left : 20px; + padding-right : 30px; + + p { + font-size : 15px; + margin : 0 0 10px; + } +` + +const DialogContentDiv = styled.div` + padding : 20px 30px; + overflow : visible !important; +` + +const HeaderDiv = styled.div` + text-align : center; + display : flex; + justify-content : space-between; + padding : 10px 26px 0 26px; + + h2 { + font-size : 26px; + font-weight : lighter; + } +` + +const ConfirmarProfessorComponent = styled.div` + min-width : 600px; + border-radius : 4px; + background-color : #fff; + color : #666; +` diff --git a/src/Components/PageProfessorComponents/PartOne.js b/src/Components/PageProfessorComponents/PartOne.js new file mode 100644 index 0000000000000000000000000000000000000000..6fe3e70cb933c64da77e923804f69fe375fbc580 --- /dev/null +++ b/src/Components/PageProfessorComponents/PartOne.js @@ -0,0 +1,291 @@ +import React, {useState, useEffect} from 'react' +import styled from 'styled-components' +import Stepper from '../Stepper.js' +import FormControl from '@material-ui/core/FormControl'; +import MenuItem from '@material-ui/core/MenuItem'; +import Select from '@material-ui/core/Select'; +import InputLabel from '@material-ui/core/InputLabel'; +import {Button} from '@material-ui/core' +import {RightSideStrikedH3, LeftSideStrikedH3} from '../LoginContainerFunction.js' +import Divider from '@material-ui/core/Divider'; +import {ButtonCancelar} from './PartTwo.js' +import axios from 'axios' +import FormInput from '../FormInput.js' + +export function sortDict (dict) { + const newDict = dict.sort((a, b) => (a.name) > (b.name) ? 1 : -1) + return newDict + +} + +const extractUFInfo = (ufs, name) => { + var id = '' + var abbreviation = '' + for (const obj of ufs) { + if (obj.name === name) { + id = obj.id + abbreviation = obj.abbreviation + } + } + return {id : id, abbreviation : abbreviation} +} + +export default function PartOne (props) { + //stores initial get response (list of states, sorted alphabetically) + const [ufList, setStates] = useState([]) + const handleSetStates = (states) => {setStates(states)} + + //stores list of cities sorted alphabetically + const [municipioList, setMunicipioList] = useState([]) + const handleSetMunicipioList = (municipios) => setMunicipioList(municipios) + + //stores a single user selected state + const [uf, setUF] = useState( + { + algumFoiEscolhido : false, + name : '', + abbreviation : '' + } + ) + + //stores a single user selected city + const [municipio, setMunicipio] = useState( + { + algumFoiEscolhido : false, + name : '' + } + ) + + const [codigoINEP, setCodigoINEP] = useState( + { + codigoInvalido : false, + value : '' + } + ) + + const handleCodigoINEP = (event) => { + const code = event.target.value + + setCodigoINEP({...codigoINEP, + codigoInvalido : false, + value : code + }) + } + + const validateINEP = () => { + const code = codigoINEP.value + + axios.get(('https://www.simcaq.c3sl.ufpr.br/api/v1/portal_mec_inep?filter=school_cod:' + code) + ).then( (response) => { + handleSubmit() + }, (error) => { + setCodigoINEP({...codigoINEP, + codigoInvalido : true, + value : '' + }) + } + ) + } + + const handleSubmit = () => { + console.log('handle submit : ', uf.abbreviation, uf.name, municipio.name, codigoINEP.value) + props.handleBuscar(uf.abbreviation, uf.name, municipio.name, codigoINEP.value) + } + + //on render component, call simcaq api and update ufList + useEffect ( () => { + axios.get(('https://simcaq.c3sl.ufpr.br/api/v1/state') + ).then( (response) => { + console.log(sortDict(response.data.result)) + handleSetStates(sortDict(response.data.result)) + }, + (error) => console.log('erro acessando api do simcaq (estados)')) + }, []) + + const handleChooseUF = (event) => { + const ufName = event.target.value + const {id, abbreviation} = extractUFInfo(ufList, ufName) + console.log(id, abbreviation) + + setUF({...uf, + algumFoiEscolhido : true, + name : ufName, + abbreviation : abbreviation + } + ) + + axios.get(('https://simcaq.c3sl.ufpr.br/api/v1/city?filter=state:' + id) + ).then( (response) => { + handleSetMunicipioList(sortDict(response.data.result)) + }, (error) => console.log('erro acessando api do simcaq (cidades)') + ) + } + + const handleChooseCity = (event) => { + const cityName = event.target.value + console.log(cityName) + setMunicipio({...municipio, + algumFoiEscolhido : true, + name : cityName + } + ) + } + + return ( + <> + {/*/////////////////////////////PRIMEIRA PARTE/////////////////////////////*/} + <Content> + <h4>Vamos localizar o seu cadastro:</h4> + <Stepper items={props.stepper}/> + <form style={{textAlign:"start"}}> + <p>Localize pelo menos uma escola em que você tenha atuado até maio de 2017:</p> + <FormControl required style={{width:"100%"}}> + <InputLabel>Procure sua UF</InputLabel> + <Select + labelId="demo-simple-select-label" + id="demo-simple-select" + value={uf.name} + onChange={handleChooseUF} + > + { + ufList.map( (ufs)=> + <MenuItem key={ufs.name} value={ufs.name}>{ufs.name}</MenuItem> + ) + } + </Select> + </FormControl> + <FormControl required style={{width:"100%"}}> + <InputLabel>Busque o seu municÃpio</InputLabel> + <Select + labelId="demo-simple-select-label" + id="demo-simple-select" + value={municipio.name} + onChange={handleChooseCity} + > + { + municipioList.map( (cidades)=> + <MenuItem key={cidades.name} value={cidades.name}>{cidades.name}</MenuItem> + ) + } + </Select> + </FormControl> + <div style={{display:"flex", justifyContent:"center",paddingTop:"10px", paddingBottom:"10px"}}> + <ButtonConfirmar + onClick={ ( (uf.algumFoiEscolhido && municipio.algumFoiEscolhido) ? handleSubmit : '')} + > + BUSCAR</ButtonConfirmar> + </div> + </form> + </Content> + + <div style={{display:"flex", justifyContent:"center", alignItems:"center"}}> + <LeftSideStrikedH3/><StrikeSpan>ou</StrikeSpan><RightSideStrikedH3/> + </div> + + {/*/////////////////////////////SEGUNDA PARTE/////////////////////////////*/} + <Content> + <form> + <p>Localize pelo código INEP da escola:</p> + <FormControl required style={{width:"100%"}}> + <FormInput + inputType={'text'} + name={'Código INEP'} + value={codigoINEP.value} + handleChange = {handleCodigoINEP} + placeholder={'Código INEP'} + required={true} + error={codigoINEP.codigoInvalido} + help={codigoINEP.codigoInvalido ? <span style={{color:'red'}}>código INEP inválido</span> : ''} + > + </FormInput> + </FormControl> + <div style={{display:"flex", justifyContent:"center",paddingTop:"10px", paddingBottom:"10px"}}> + <ButtonConfirmar + onClick={validateINEP} + > + BUSCAR</ButtonConfirmar> + </div> + </form> + </Content> + <Divider/> + <ButtonsArea> + <ButtonCancelar onClick={props.handleCancelar}>CANCELAR VERIFICAÇÃO</ButtonCancelar> + </ButtonsArea> + </> + ) +} + +export const ButtonsArea = styled.div` + display : flex; + justify-content : center; + padding-top : 10px; + padding-bottom : 10px; +` + +const StrikeSpan = styled.span` + vertical-align : middle; + font-family : Roboto; + font-style : normal; + font-weight : 500; + line-height : 22px; + font-size : 15px; + letter-spacing : .01em; +` + +export const Content = styled.div` + margin-top : 16px; + margin-bottom : 16px; + margin-right : 10%; + margin-left : 10%; + + h4 { + text-align : center; + magin-bottom : 20px; + font-family: Roboto; + font-style : normal; + font-weight : 300; + line-height : 36px; + font-size : 26px; + margin-top : 20px; + } + + p { + font-family : Roboto; + font-style : normal; + font-weight : 400; + line-height : 21px; + font-size : 15px; + } +` +export const ButtonConfirmar = styled(Button)` + background-color : #00bcd4 !important; + color : #fff !important; + font-family : 'Roboto',sans-serif !important; + font-size : 14px !important; + font-weight : bolder !important; + padding-left : 16px !important; + padding-right : 16px !important; + outline : none !important; + margin : 6px 8px !important; + white-space : nowrap !important; + text-transform : uppercase !important; + font-weight : bold !important; + font-size : 14px !important; + font-style : inherit !important; + font-variant : inherit !important; + font-family : inherit !important; + text-decoration : none !important; + overflow : hidden !important; + display : inline-block !important; + position : relative !important; + cursor : pointer !important; + min-height : 36px !important; + min-width : 88px !important; + line-height : 36px !important; + vertical-align : middle !important; + align-items : center !important; + text-align : center !important; + border-radius : 3px !important; + box-sizing : border-box !important; + border : 0 !important; +` diff --git a/src/Components/PageProfessorComponents/PartThree.js b/src/Components/PageProfessorComponents/PartThree.js new file mode 100644 index 0000000000000000000000000000000000000000..2ee7c262ad0e85e3ba1a3c6221cf5241bde4b207 --- /dev/null +++ b/src/Components/PageProfessorComponents/PartThree.js @@ -0,0 +1,109 @@ +import React, {useState} from 'react' +import {Content, ButtonsArea} from './PartOne.js' +import {ButtonCancelar, ButtonGrey} from './PartTwo.js' +import FormControl from '@material-ui/core/FormControl'; +import InputLabel from '@material-ui/core/InputLabel'; +import Stepper from '../Stepper.js' +import FormInput from '../FormInput.js' +import styled from 'styled-components' +import {Button} from '@material-ui/core' + +export default function PartThree (props) { + const [phoneNumber, setPhoneNumber] = useState( + { + flagInvalid : false, + number : '' + } + ) + const handleChangePhoneNumber = (event) => { + const input = event.target.value.replace(/\D/,'') + setPhoneNumber({...phoneNumber, + flagInvalid : (input.length < 9 ? true : false), + number : (input.length > 9 ? phoneNumber.number : input), + }) + } + + const [cpf, setCpf] = useState( { + flagInvalid : false, + number : '' + }) + const handleChangeCpf = (event) => { + const input = event.target.value.replace(/\D/,'') + setCpf({...cpf, + flagInvalid : (input.length < 11 ? true : false), + number : (input.length > 11 ? cpf.number : input), + }) + } + + const handleSubmit = () => { + const submit_phone = phoneNumber.number + const submit_cpf = cpf.number + + props.handleSubmit(submit_phone, submit_cpf) + } + + return ( + <> + {console.log(props)} + <Content> + <h4>Vamos localizar o seu cadastro:</h4> + <Stepper items={props.stepper}/> + <form style={{textAlign:"start"}}> + <span>CENTRO EDUC INF MEU PEDACINHO DE CHAO</span> + <FormControl required style={{width:"100%"}}> + <p>Inserir o telefone da escola:</p> + <FormInput + inputType={'text'} + pattern="[0-9]" + name={'DDD e Número'} + placeholder={'DDD e Número'} + value={phoneNumber.number} + handleChange={handleChangePhoneNumber} + error={phoneNumber.flagInvalid} + > + </FormInput> + </FormControl> + <FormControl required style={{width:"100%"}}> + <p>Inserir o seu CPF</p> + <FormInput + inputType={'text'} + name={'11 dÃgitos'} + placeholder={'11 dÃgitos'} + value={cpf.number} + handleChange={handleChangeCpf} + mask={'999.999.999-99'} + error={cpf.flagInvalid} + > + </FormInput> + </FormControl> + <div style={{display:"flex", justifyContent:"space-evenly",paddingTop:"10px", paddingBottom:"10px"}}> + <div style={{display:"flex", justifyContent:"center"}}> + <ButtonConfirmar onClick={( (cpf.flagInvalid || phoneNumber.flagInvalid) ? () => {console.log('cpf.flagInvalid: ', cpf.flagInvalid, 'phoneNumber.flagInvalid: ', phoneNumber.flagInvalid)} : handleSubmit)}>BUSCAR</ButtonConfirmar> + </div> + <div style={{display:"flex", justifyContent:"center"}}> + <ButtonGrey onClick={() => props.goBack(false, true, false)}>VOLTAR</ButtonGrey> + <ButtonCancelar onClick={props.handleCancelar}>CANCELAR</ButtonCancelar> + </div> + </div> + </form> + </Content> + </> + ) +} + +const ButtonConfirmar = styled(Button)` + background-color : #00bcd4 !important; + color : #fff !important; + box-shadow : none !important; + font-family : 'Roboto',sans-serif !important; + font-size : 14px !important; + font-weight : bold !important; + height : 36px !important; + border-radius : 3px !important; + padding-left : 16px !important; + padding-right : 16px !important; + vertical-align : middle !important; + text-align : center !important; + align-items : center !important; + +` diff --git a/src/Components/PageProfessorComponents/PartTwo.js b/src/Components/PageProfessorComponents/PartTwo.js new file mode 100644 index 0000000000000000000000000000000000000000..a4e68d4a6de2ad449ab9cfd9e999b321cd546379 --- /dev/null +++ b/src/Components/PageProfessorComponents/PartTwo.js @@ -0,0 +1,101 @@ +import React, {useState, useEffect} from 'react' +import {Content, ButtonsArea} from './PartOne.js' +import Divider from '@material-ui/core/Divider'; +import Stepper from '../Stepper.js' +import CustomizedTables from '../Table.js' +import styled from 'styled-components' +import {Button} from '@material-ui/core' +import axios from 'axios' +import {simcaqAPIurl} from '../../env' +import {sortDict} from './PartOne.js' + +export default function PartTwo (props) { + const [schoolList, setSchoolList] = useState([]) + + useEffect ( () => { + const code = (props.info.inep_code || '') + const uf = (props.info.school_uf.abbreviation || '') + const municipio = (props.info.school_city || '') + //console.log(code, uf, municipio) + + //if user searched by inep code + if (code !== '') { + axios.get((`${simcaqAPIurl}/portal_mec_inep?filter=school_cod:` + code) + ).then ((response) => { + setSchoolList(sortDict(response.data.result)) + }, (error) => console.log('erro ao dar get na escola por inep code') + )} + else if (uf !== '' && municipio !== '') { + axios.get((`${simcaqAPIurl}/school?search=state_name:"` + uf + '",city_name:"' + municipio + '"&filter=year:2017') + ).then((response)=> { + //console.log(response.data.result) + setSchoolList(sortDict(response.data.result)) + }, (error) => console.log('erro ao dar get na escola por uf e municipio', code, uf, municipio) + )} + }, []) + + const onClickTable = (city_name, id, name, state_name) => { + props.handleBuscar(city_name, id, name, state_name) + } + + return ( + <> + {console.log(props)} + <Content> + <h4>Vamos localizar o seu cadastro:</h4> + <Stepper items={props.stepper}/> + </Content> + <Content> + <InputContainer> + <p>Selecione a sua escola:</p> + + <CustomizedTables + columns={['Codigo INEP', 'Escola', 'UF', 'Cidade']} + rows={schoolList} onClickTable={onClickTable} + /> + + </InputContainer> + </Content> + <Divider/> + <ButtonsArea> + <ButtonGrey onClick={() => props.goBack(true, false, false)}>VOLTAR</ButtonGrey> + <ButtonCancelar onClick={props.handleCancelar}>CANCELAR VERIFICAÇÃO</ButtonCancelar> + </ButtonsArea> + </> + ) +} + +export const ButtonCancelar = styled(Button)` + color: #666 !important; + font-family: 'Roboto',sans-serif !important; + font-size: 14px !important; + font-weight: bold !important; + height: 36px !important; + border-radius: 3px !important; + padding-left: 16px !important; + padding-right: 16px !important; +` + +export const ButtonGrey = styled(Button)` + background-color : #fff !important; + border : 1.5px #666 solid !important; + color : #666 !important; + box-shadow : none !important; + font-family : 'Roboto',sans-serif !important; + font-size : 14px !important; + font-weight : bold !important; + height : 36px !important; + border-radius : 3px !important; + padding-left : 16px !important; + padding-right : 16px !important; + vertical-align : middle !important; + text-align : center !important; + align-items : center !important; + +` + +const InputContainer = styled.div` + max-width : 970px; + display : block; + flex : auto; +` diff --git a/src/Components/PageProfessorComponents/SuccessfulRequest.js b/src/Components/PageProfessorComponents/SuccessfulRequest.js new file mode 100644 index 0000000000000000000000000000000000000000..0e478b74df1a357b5b1c7949717f92e4069f2550 --- /dev/null +++ b/src/Components/PageProfessorComponents/SuccessfulRequest.js @@ -0,0 +1,56 @@ +import React from 'react' +import styled from 'styled-components' +import {ButtonConfirmar} from './PartOne.js' +import Comentarios from '../../img/comentarios.png' + +export default function SuccessfulRequest (props) { + const h4Text = 'Obrigado por fazer parte dessa rede!' + const pText = 'Em breve você poderá publicar os seus próprios reursos educacionais digitais. O MEC analisará as suas informações junto a escola e você será avisada(o) aqui na plataforma e em seu email: ' + + return ( + <div style={{maxWidth:"575px", padding : "0 36px"}}> + <div style={{display : "flex", flexDirection : "column"}}> + <StyledH4>{h4Text}</StyledH4> + <TextDiv> + <p>{pText} <b>{props.email}</b>.</p> + </TextDiv> + <div style={{display : 'flex', flexDirection : 'row', justifyContent : "center"}}> + <ButtonConfirmar>VOLTAR À PAGINA INICIAL</ButtonConfirmar> + </div> + <ImageDiv/> + </div> + </div> + ) +} + +const ImageDiv = styled.div` + height : 500px; + background-image : url(${Comentarios}); + background-repeat : no-repeat; + background-position : center center; +` + +const TextDiv = styled.div` + display : flex; + flex-direction : row; + + p { + text-align : justify; + font-family: Roboto; + font-style : normal; + font-weight : 400; + line-height : 21px; + font-size : 15px; + margin : 0 0 10px; + } +` + +const StyledH4 = styled.h4` + font-family : Roboto; + font-style : normal; + font-weight : 300; + line-height : 36px; + font-size : 26px; + margin-top : 20px; + margin-bottom : 20px; +` diff --git a/src/Components/PasswordRecoveryComponents/Default.js b/src/Components/PasswordRecoveryComponents/Default.js new file mode 100644 index 0000000000000000000000000000000000000000..3be9952501e3e693998d27ce08743a220939a286 --- /dev/null +++ b/src/Components/PasswordRecoveryComponents/Default.js @@ -0,0 +1,25 @@ +import React from 'react' +import {CompletarCadastroButton} from '../TabPanels/TabPanelSolicitarContaProfessor.js' +import FormInput from "../FormInput.js" + +export default function Default (props) { + return ( + <div style={{overflow:"hidden", display:"inline-block"}}> + <h2 style={{fontSize:"32px", fontWeight:"200", marginBottom:"20px"}}>Vamos encontrar a sua conta</h2> + <form onSubmit={(e) => props.onSubmit(e)}> + <FormInput + inputType={"text"} + name={"email"} + value={props.value} + placeholder={"E-mail"} + handleChange={e => props.handleChange(e)} + required={true} + error = {props.error} + /> + <div style={{display:"flex", justifyContent:"center"}}> + <CompletarCadastroButton onClick={(e) => props.onSubmit(e, props.value)}>BUSCAR</CompletarCadastroButton> + </div> + </form> + </div> + ) +} diff --git a/src/Components/PasswordRecoveryComponents/Error.js b/src/Components/PasswordRecoveryComponents/Error.js new file mode 100644 index 0000000000000000000000000000000000000000..ba9fc189ebc8c0a07becf8312fa43d5bd70547b6 --- /dev/null +++ b/src/Components/PasswordRecoveryComponents/Error.js @@ -0,0 +1,27 @@ +import React from 'react' +import {CompletarCadastroButton} from '../TabPanels/TabPanelSolicitarContaProfessor.js' +import FormInput from "../FormInput.js" + +export default function Default (props) { + return ( + <div style={{overflow:"hidden", display:"inline-block"}}> + <h2 style={{fontSize:"32px", fontWeight:"200", marginBottom:"20px"}}>Ops! Não encontramos essa conta</h2> + <p>{props.email}</p> + <p>Verifique se o e-mail foi digitado corretamente ou se você utilizou algum outro e-mail.</p> + <form onSubmit={(e) => props.onSubmit(e)}> + <FormInput + inputType={"text"} + name={"email"} + value={props.value} + placeholder={"E-mail"} + handleChange={e => props.handleChange(e)} + required={true} + error = {props.error} + /> + <div style={{display:"flex", justifyContent:"center"}}> + <CompletarCadastroButton onClick={(e) => props.onSubmit(e, props.value)}>BUSCAR</CompletarCadastroButton> + </div> + </form> + </div> + ) +} diff --git a/src/Components/PasswordRecoveryComponents/Success.js b/src/Components/PasswordRecoveryComponents/Success.js new file mode 100644 index 0000000000000000000000000000000000000000..558f0bf48615a2ec12c076cd66ba870d3552397e --- /dev/null +++ b/src/Components/PasswordRecoveryComponents/Success.js @@ -0,0 +1,14 @@ +import React from 'react' +import {CompletarCadastroButton} from '../TabPanels/TabPanelSolicitarContaProfessor.js' +import FormInput from "../FormInput.js" + +export default function Default (props) { + return ( + <div style={{overflow:"hidden", display:"inline-block", fontSize:"14px", textAlign:"start"}}> + <h2 style={{fontSize:"32px", fontWeight:"200", marginBottom:"20px"}}>Feito! Confira seu e-mail</h2> + <p> Enviamos um link para <span style={{color:"#00bcd4"}}>{props.email}</span> que permite alterar sua senha. </p> + <p style={{marginBottom:"30px"}}> Caso não chegue em sua caixa de entrada, dê uma olhada em outras pastas, como lixo eletrônico ou spam. </p> + <p> Não é o seu e-mail? <span style={{color:"#00bcd4", cursor:"pointer"}} onClick={() => {props.changeSwitch('default')}}> Tente Novamente.</span></p> + </div> + ) +} diff --git a/src/Components/PublicationPermissionsContent.js b/src/Components/PublicationPermissionsContent.js index c40d49d7e16a0f6235b198be07fccb60ec6133e4..3b62deef23b511ad971908294c360ad7f4ffe887 100644 --- a/src/Components/PublicationPermissionsContent.js +++ b/src/Components/PublicationPermissionsContent.js @@ -31,7 +31,7 @@ export default function PublicationPermissionsContent (props) { <p>Ao prosseguir você concede a permissão de publicação do seu recurso ao nosso portal e se compromete a não infringir as polÃticas de conteúdos, estando então, a partir desse momento passÃvel de responsabilização pelo conteúdo a ser integrado a nossa rede. Para tanto atente-se as pontuações abaixo e verifique se o seu recurso está de acordo, antecipadamente, com as nossas condições. É recomendável a leitura das polÃticas de conteúdo estabelecidas - (<a href="termos-de-uso#publicacoes-de-usuario"><strong>PolÃticas de Conteúdo</strong></a>) + (<a href="/termos" style={{color:"initial"}}><strong>PolÃticas de Conteúdo</strong></a>) </p> <Typography variant="h5" style={{fontWeight:"300", color:"rgb(102, 102, 102)", fontSize:"22px"}}> Para que o recurso seja publicado na plataforma é preciso que ele esteja de acordo com as diretrizes abaixo, a presença de quaisquer dos itens a seguir diff --git a/src/Components/SignUpContainer.js b/src/Components/SignUpContainer.js index f87f002efb76eb4ee4313705ab6f9e81003b4b9b..9d01f58daf46303a7b3967d3eb8adc5d2e7e9ec0 100644 --- a/src/Components/SignUpContainer.js +++ b/src/Components/SignUpContainer.js @@ -24,7 +24,7 @@ import CloseIcon from '@material-ui/icons/Close'; import styled from 'styled-components' import {device} from './device.js' import FormInput from "./FormInput.js" - +import {StyledCloseModalButton, DialogContentDiv, DialogHeaderStyled, SocialConnectDiv, StyledGoogleLoginButton, H3Div} from './LoginContainer.js' const responseGoogle = (response) => { console.log(response); } @@ -40,14 +40,36 @@ var callback = function () { console.log('Done!!!!'); }; +function validateUserInfo (name, email, password) { + const errors = [] + + if(name.lenght === 0 ) { + errors.push({name : "name", msg : "Faltou preencher seu nome completo."}) + } + if(email.length === 0) { + errors.push({name : "email", msg : "Faltou preencher seu e-mail."}) + } + else if ( (email.split("").filter(x => x === "@").length !== 1) || (email.indexOf(".") === -1) ){ + errors.push({name : "email", msg : "Insira um endereço de email válido."}) + errors.push({name : "email", msg : "Por exemplo: seunome@gmail.com, seunome@hotmail.com"}) + } + if(password.length === 0) { + errors.push({ name : "password", msg : "Faltou definir uma senha."}) + } + + return errors +} + class SignUpContainer extends Component { constructor (props) { super(props); this.state = { - nomeCompleto: "", + name: "", email: "", - senha: "" + password: "", + + errors : [] }; }; @@ -59,85 +81,102 @@ class SignUpContainer extends Component { handleChange = e => { this.setState({[e.target.name]: e.target.value}) + }; onSubmit = (e) => { //on submit we should prevent the page from refreshing e.preventDefault(); //though this is arguable - - //pass user info to Store.js and clear all text fields - this.props.handleLoginInfo(this.state) - this.setState({ - nomeCompleto: "", - email: "", - senha: "" - }) + const { name, email, password } = this.state; + const errors = validateUserInfo(name, email, password) + console.log(this.state) + if ( errors.length < 1) { + //pass user info to Store.js and clear all text fields + this.props.handleLoginInfo(this.state) + this.setState({ + name: "", + email: "", + password: "" + }) + } + else { + this.setState({errors}) + } } render () { + const { errors } = this.state; return ( <ContainerStyled > <DialogHeaderStyled> + <span style={{width:"32px"}}/> <H2Styled> Cadastrar-se - <StyledCloseModalButton onClick={this.props.handleClose} > - <CloseIcon /> - </StyledCloseModalButton> </H2Styled> + <StyledCloseModalButton onClick={this.props.handleClose} > + <CloseIcon /> + </StyledCloseModalButton> </DialogHeaderStyled> - <div style={{paddingTop: "20px"}}> - <div style={{marginTop:"0"}}> + <DialogContentDiv> + <SocialConnectDiv> <StyledGoogleLoginButton clientId="658977310896-knrl3gka66fldh83dao2rhgbblmd4un9.apps.googleusercontent.com" - onSuccess={responseGoogle} onFailure={responseGoogle} cookiePolicy={'single_host_origin'} > <span style={{textTransform:"none", fontSize:"13px"}}>Usando o Google</span> </StyledGoogleLoginButton> - </div> - </div> + </SocialConnectDiv> - <H3Styled> - <RightSideStrikedH3/> - <span style={{verticalAlign:"middle"}}>ou</span> - <LeftSideStrikedH3/> - </H3Styled> + <H3Div> + <H3Styled> + <RightSideStrikedH3/> + <span style={{verticalAlign:"middle"}}>ou</span> + <LeftSideStrikedH3/> + </H3Styled> + </H3Div> <form ref="form" onSubmit={this.onSubmit}> + {errors.map(error => ( + <p key={error.name}>Error: {error.msg}</p> + ))} <FormInput inputType={"text"} - name={"nomeCompleto"} - value={this.state.nomeCompleto} - placeholder={"Nome Completo *"} + name={"name"} + value={this.state.name} + placeholder={"Nome Completo"} handleChange={e => this.handleChange(e)} + required={true} /> <br/> <FormInput inputType={"text"} name={"email"} value={this.state.email} - placeholder={"E-mail *"} + placeholder={"E-mail"} handleChange={e => this.handleChange(e)} + required={true} /> <br/> <FormInput inputType={"password"} - name={"senha"} - value={this.state.senha} - placeholder={"Senha *"} + name={"password"} + value={this.state.password} + placeholder={"Senha"} handleChange={e => this.handleChange(e)} + required={true} /> <br/> - <StyledRecaptcha + <Recaptcha sitekey="6LcyFr8UAAAAAOd0Po6rmZC1D_nYik8nLCAkNKsc" + size="normal" render="explicit" onloadCallback={callback} /> <ConfirmContainerStyled> - <StyledSignUpButton onClick={e => this.onSubmit(e)} variant="contained"> + <StyledSignUpButton type="submit" variant="contained"> <span style={{paddingLeft:"16px", paddingRight:"16px", borderRadius:"3px", boxSizing:"border-box", fontFamily:"Roboto, sans serif", fontWeight:"500", color:"#fff"}} @@ -156,6 +195,7 @@ class SignUpContainer extends Component { <DialogFooterStyled> <span style={{textAlign:"center", fontSize: "14px"}}>Já possui cadastro? <StyledAnchor href="" onClick={e => this.switchModal(e)}>ENTRAR</StyledAnchor></span> </DialogFooterStyled> + </DialogContentDiv> </ContainerStyled> ) } @@ -168,24 +208,19 @@ const ContainerStyled = styled.div` background-color : white; max-width : none; align : center; - padding-left : 25px; - padding-right:25px; - padding-bottom:10px; - border-radius: 4px; + display : flex; + flex-direction : column; + min-width : 450px; + + max-height : none; + position : relative; + padding : 10px; @media ${device.mobileM} { width : 100%; height : 100%; } ` -const DialogHeaderStyled = styled.div` - text-align : center; - display : inline-flex; - justify-content : space-between; - padding : 10px 26px 0 26px; - height : 64px; -` - const DialogFooterStyled = styled.div` box-sizing : border-box; font-family : 'Roboto', sans serif; @@ -197,15 +232,6 @@ const DialogFooterStyled = styled.div` line-height : 1.42857143 ` -const StyledGoogleLoginButton = styled(GoogleLogin)` - background-color: fff; - border : 1px solid rgb(66, 133, 244); - box-shadow: 0 0 0 1px #4285f4 !important; - :hover { - background-color: #f4f4f4 !important; - } -` - const TermosDeUsoStyled = styled.div` font-family: 'Roboto', sans serif, 'Helvetica Neue', Helvetica, Arial, sans-serif; color : #666; @@ -223,7 +249,6 @@ const H2Styled = styled.h2` font-weight : lighter; justify-content: space-between; font-family: 'Roboto', sans serif, 'Helvetica Neue', Helvetica, Arial, sans-serif !important; - padding: 10px 26px 0 26px; text-align: center; letter-spacing: .005em; ` @@ -257,15 +282,15 @@ const StyledAnchor = styled.a` color : #00bcd4; text-decoration : none; ` -const StyledCloseModalButton = styled(Button)` - display : inline-block; - position : relative; - float : right !important; - margin-right : -8px; - background : transparent; - min-width: 0 !important; - width : 40px; -` +//const StyledCloseModalButton = styled(Button)` +// display : inline-block; +// position : relative; +// float : right !important; +// margin-right : -8px; +// background : transparent; +// min-width: 0 !important; +// width : 40px; +//` const ConfirmContainerStyled = styled.div` display : flex; @@ -273,6 +298,7 @@ const ConfirmContainerStyled = styled.div` align-items : center; justify-content : center; box-sizing : border-box; + font-size : 13px; ` const StyledSignUpButton = styled(Button)` diff --git a/src/Components/SignUpContainerFunction.js b/src/Components/SignUpContainerFunction.js new file mode 100644 index 0000000000000000000000000000000000000000..44e3df95450417562ead91717e0abd5a7134d65c --- /dev/null +++ b/src/Components/SignUpContainerFunction.js @@ -0,0 +1,337 @@ +/*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, {useState} from "react"; +import GoogleLogin from 'react-google-login' +import { Button } from '@material-ui/core'; +//import FacebookLogin from 'react-facebook-login'; +import CloseIcon from '@material-ui/icons/Close'; +import styled from 'styled-components' +import {device} from './device.js' +import FormInput from "./FormInput.js" +import {StyledCloseModalButton, DialogContentDiv, DialogHeaderStyled, SocialConnectDiv, StyledGoogleLoginButton, H3Div} from './LoginContainer.js' +import ValidateUserInput from '../Components/FormValidationFunction.js' + +var Recaptcha = require('react-recaptcha') + +var callback = function () { + console.log('Done!!!!'); +}; + +export default function SignUpContainer (props) { + const [formNome, setNome] = useState( + { + key : false, + value : "", + } + ) + + const [formEmail, setEmail] = useState( + { + key : false, + value : "", + } + ) + + const [formSenha, setSenha] = useState( + { + key : false, + value : "" + } + ) + + const handleChange = (e, type) => { + const userInput = e.target.value + const flag = ValidateUserInput(type, userInput) + + if (type === 'username') { + setNome({...formNome, + key : flag, + value : userInput + }) + console.log(formNome) + } + else if(type === 'email') { + setEmail({...formEmail, + key : flag, + value : userInput + }) + console.log(formEmail) + } + else if(type === 'password') { + setSenha({...formSenha, + key : flag, + value : userInput + }) + console.log(formSenha) + } + } + + const limpaCamposForm = () => { + setNome({...formNome, + key : false, + value : '' + }) + + setEmail({...formEmail, + key : false, + value : '' + }); + + setSenha({...formSenha, + key : false, + value : '' + }) + } + + const responseGoogle = (response) => { + console.log(response); + } + + const switchModal = (e) => { + e.preventDefault() + props.handleClose() + props.openLogin() + }; + + const onSubmit = (e) => { + e.preventDefault(); + const newLogin = {name : formNome.value, email : formEmail.value, password : formSenha.value} + + if (!(formNome.key || formEmail.key || formSenha.key)) { + props.handleLoginInfo(newLogin) + limpaCamposForm() + } + } + + return ( + <ContainerStyled > + <DialogHeaderStyled> + <span style={{width:"32px"}}/> + <H2Styled> Cadastrar-se + </H2Styled> + <StyledCloseModalButton onClick={props.handleClose} > + <CloseIcon /> + </StyledCloseModalButton> + </DialogHeaderStyled> + + <DialogContentDiv> + <SocialConnectDiv> + <StyledGoogleLoginButton + clientId="658977310896-knrl3gka66fldh83dao2rhgbblmd4un9.apps.googleusercontent.com" + onSuccess={responseGoogle} + onFailure={responseGoogle} + cookiePolicy={'single_host_origin'} + > + <span style={{textTransform:"none", fontSize:"13px"}}>Usando o Google</span> + </StyledGoogleLoginButton> + </SocialConnectDiv> + + <H3Div> + <H3Styled> + <RightSideStrikedH3/> + <span style={{verticalAlign:"middle"}}>ou</span> + <LeftSideStrikedH3/> + </H3Styled> + </H3Div> + + <form onSubmit={onSubmit}> + <FormInput + inputType={"text"} + name={"name"} + value={formNome.value} + placeholder={"Nome Completo"} + handleChange={e => handleChange(e, 'username')} + required={true} + error={formNome.key} + /> + <br/> + <FormInput + inputType={"text"} + name={"email"} + value={formEmail.value} + placeholder={"E-mail"} + handleChange={e => handleChange(e, 'email')} + required={true} + error={formEmail.key} + help = {formEmail.key ? (formEmail.value.length == 0 ? "Faltou preencher seu e-mail." : <span>Insira um endereço de e-mail válido.<br/>Por exemplo: seunome@gmail.com, seunome@hotmail.com</span>) : ""} + /> + <br/> + <FormInput + inputType={"password"} + name={"password"} + value={formSenha.value} + placeholder={"Senha"} + handleChange={e => handleChange(e, 'password')} + required={true} + error={formSenha.key} + help = {formSenha.key ? (formSenha.value.length == 0 ? "Faltou digitar sua senha." : "A senha precisa ter no mÃnimo 8 caracteres.") : ""} + /> + <br/> + <Recaptcha + sitekey="6LcyFr8UAAAAAOd0Po6rmZC1D_nYik8nLCAkNKsc" + size="normal" + render="explicit" + onloadCallback={callback} + /> + <ConfirmContainerStyled> + <StyledSignUpButton type="submit" variant="contained"> + <span + style={{paddingLeft:"16px", paddingRight:"16px", borderRadius:"3px", boxSizing:"border-box", + fontFamily:"Roboto, sans serif", fontWeight:"500", color:"#fff"}} + > + CADASTRAR + </span> + </StyledSignUpButton> + </ConfirmContainerStyled> + </form> + + <TermosDeUsoStyled> + <p>Ao se cadastrar, você está aceitando os Termos de Uso e de PolÃtica + de Privacidade. <a href="./">Ler Termos</a>.</p> + </TermosDeUsoStyled> + + <DialogFooterStyled> + <span style={{textAlign:"center", fontSize: "14px"}}>Já possui cadastro? <StyledAnchor href="" onClick={e => switchModal(e)}>ENTRAR</StyledAnchor></span> + </DialogFooterStyled> + </DialogContentDiv> + </ContainerStyled> + ) +} + +const ContainerStyled = styled.div` + box-sizing : border-box; + background-color : white; + max-width : none; + align : center; + display : flex; + flex-direction : column; + min-width : 450px; + + max-height : none; + position : relative; + padding : 10px; + @media ${device.mobileM} { + width : 100%; + height : 100%; + } +` + +const DialogFooterStyled = styled.div` + box-sizing : border-box; + font-family : 'Roboto', sans serif; + margin : 20px -20px; + padding-top : 20px; + border-top : 1px #e5e5e5 solid; + justify-content : center; + text-align : center; + line-height : 1.42857143 +` + +const TermosDeUsoStyled = styled.div` + font-family: 'Roboto', sans serif, 'Helvetica Neue', Helvetica, Arial, sans-serif; + color : #666; + font-size : 13px; + margin : 0 0 10px; + max-width : 350px; + margin-top : 10px; + text-align : start; +` + +const H2Styled = styled.h2` + align-self : center; + color : #666; + font-size : 26px; + font-weight : lighter; + justify-content: space-between; + font-family: 'Roboto', sans serif, 'Helvetica Neue', Helvetica, Arial, sans-serif !important; + text-align: center; + letter-spacing: .005em; +` + +const H3Styled = styled.h3` + overflow : hidden; + text-align : center; + font-size : 14px; + color : #666; + margin : 10px 0; +` +const RightSideStrikedH3 = styled.div` + display : inline-block; + border-bottom: 1px dotted #666; + vertical-align : middle; + font-weight : 500; + margin-right : 5px; + width : 45%; +` + +const LeftSideStrikedH3 = styled.div` + display : inline-block; + border-bottom: 1px dotted #666; + vertical-align : middle; + font-weight : 500; + margin-left : 5px; + width : 45%; +` + +const StyledAnchor = styled.a` + color : #00bcd4; + text-decoration : none; +` +//const StyledCloseModalButton = styled(Button)` +// display : inline-block; +// position : relative; +// float : right !important; +// margin-right : -8px; +// background : transparent; +// min-width: 0 !important; +// width : 40px; +//` + +const ConfirmContainerStyled = styled.div` + display : flex; + margin-top : 10px; + align-items : center; + justify-content : center; + box-sizing : border-box; + font-size : 13px; +` + +const StyledSignUpButton = styled(Button)` + background-color: #00bcd4 !important; + box-shadow : none !important; + outline: none !important; + border : 0 !important; + overflow : hidden !important; + width : 50% !important; + display : inline-block !important; + font-family : 'Roboto', sans serif !important; + font-size: 14px !important; + height : 36px !important; + align-items : center !important; + border-radius: 3px !important; + align-self : 50% !important; + :hover { + background-color : #00acc1 !important; + } +` + +const StyledRecaptcha = styled(Recaptcha)` + display : flex !important; + justify-content : center !important; +` diff --git a/src/Components/SignUpModal.js b/src/Components/SignUpModal.js index c25758f49c33d287bd28a13f321bdd7eeaa8b673..a04c9420701da16cc97f9e678121f18b460abd8e 100644 --- a/src/Components/SignUpModal.js +++ b/src/Components/SignUpModal.js @@ -22,7 +22,7 @@ import Modal from '@material-ui/core/Modal'; import Backdrop from '@material-ui/core/Backdrop'; import Fade from '@material-ui/core/Fade'; import styled from 'styled-components' -import SignUpContainer from './SignUpContainer.js' +import SignUpContainer from './SignUpContainerFunction.js' import {Store} from '../Store.js' import axios from 'axios' import {apiUrl} from '../env'; @@ -41,48 +41,43 @@ const StyledModalSignUp = styled(Modal)` ` -const useStyles = makeStyles(theme => ({ - modal: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - textAlign: "center", - maxBlockSize: "350px", - width: '100%', - minBlockSize: "100px", - }, - paper: { - backgroundColor: "theme.palette.background.paper", - border: '2px solid #000', - boxShadow: " 0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12);", - align:"center", - }, -})); + export default function SignUpModal (props) { const { state, dispatch } = useContext(Store) const handleLoginInfo = (newLogin) => { - + console.log(state.currentUser) axios.post(`${apiUrl}/auth`, { - name : newLogin.nomeCompleto, + name : newLogin.name, email: newLogin.email, - password : newLogin.senha, - password_confirmation : newLogin.senha + password : newLogin.password, + password_confirmation : newLogin.senha, + terms_of_service:true, + avatar: "" } ).then( (response) => { dispatch ( { type: 'USER_SIGNED_UP', userLoggedIn: !state.userIsLoggedIn, login: { - username : newLogin.username, - email : newLogin.email, + id : response.data.id, + username : response.data.name, + email : response.data.email, accessToken : response.headers['access-token'], - client : response.headers.client + clientToken : response.headers.client, + userAvatar : response.data.avatar_file_name, + userCover : response.data.cover_file_name } } ) + localStorage.setItem('@portalmec/accessToken', response.headers['access-token']) + localStorage.setItem('@portalmec/clientToken', response.headers.client,) + localStorage.setItem('@portalmec/id', response.data.data.id) + localStorage.setItem('@portalmec/username', response.data.data.name) + localStorage.setItem('@portalmec/uid', response.data.data.uid) + console.log(state.currentUser) props.handleClose() }, (error) => { console.log(':(') @@ -90,7 +85,7 @@ export default function SignUpModal (props) { ) } - //useEffect(()=>{console.log(state.loginInfo)},[state.loginInfo]) + //useEffect(()=>{console.log(state.currentUser)},[state.currentUser]) return ( <StyledModalSignUp diff --git a/src/Components/Stepper.js b/src/Components/Stepper.js new file mode 100644 index 0000000000000000000000000000000000000000..c550c2d94f110930e42ea057d6e47d737ab12353 --- /dev/null +++ b/src/Components/Stepper.js @@ -0,0 +1,53 @@ +import React, {useState} from 'react' +import styled from 'styled-components' + +export default function Stepper (props) { + + return ( + <div style={{display:"flex",justifyContent:"center", marginBottom:"50px"}}> + <FeedbackUpload> + { + props.items.map((item)=> + <div className={"page-selector " + (item.selected ? 'selected' : '')} > + {item.value} + </div> + ) + } + </FeedbackUpload> + </div> + ) +} + +const FeedbackUpload = styled.div` + width : 280px; + display : flex; + background :#e5e5e5; + flex-direction : row; + justify-content : space-between; + height : 50px; + align-items : center; + padding : 7px; + border-radius : 50px; + margin-top : 20px; + + .page-selector { + height : 36px; + width : 36px; + background : #fff; + border-radius : 50%; + color : #00bcd4; + line-height : 32px; + font-size : 20px; + font-weight : 500; + border: solid 3px #00bcd4; + text-align: center; + align-items : center; + vertical-align:middle; + } + + .selected { + background : #00bcd4; + color : #fff; + border-color : #00bcd4; + } +` diff --git a/src/Components/TabPanels/ContainerRedeVazia.js b/src/Components/TabPanels/ContainerRedeVazia.js new file mode 100644 index 0000000000000000000000000000000000000000..ad3b5863209a1b57c66f42db855d7be420887be2 --- /dev/null +++ b/src/Components/TabPanels/ContainerRedeVazia.js @@ -0,0 +1,72 @@ +import React, {useContext, useState, useEffect} from 'react' +import styled from 'styled-components' +import { Container } from 'react-grid-system' +import {ButtonMostrarTodos, ButtonMostrarMais, BtnAlinhaRecPvt, DivContainerRecursosPublicados, ContainerDivStyled, DivTitulo, StyledP, StyledHR} from './TabPanelMeusRecursos.js' +import NoRede1 from '../../img/no-rede-1.png' +import NoRede2 from '../../img/no-rede-2.png' +import NoRede3 from '../../img/no-rede-3.png' +import Paper from '@material-ui/core/Paper'; +import TabRedeImgDiv from './TabRedeImgDiv.js' + +export default function ContainerRedeVazia (props) { + return ( + <React.Fragment> + <ContainerDivStyled> + <Paper elevation={3}> + <div> + <RedeVaziaBoxContainer> + <StyledSpan>Você ainda não tem uma rede. + <br/> + Veja como começar: + </StyledSpan> + <StyledSpan> + <StyledHr/> + <DivColumns> + <TabRedeImgDiv img={NoRede1} text={"Para encontrar um usuário especÃfico, você pode utilizar a barra de busca e selecionar a busca por \"pessoas\""}/> + <TabRedeImgDiv img={NoRede2} text={"Você pode começar a seguir uma pessoa clicando no botão \"seguir\" no card (A) ou na página dela (B)"}/> + <TabRedeImgDiv img={NoRede3} text={"Pronto! Agora você poderá acompanhar os novos recursos e coleções dessa pessoas na sua página, na aba \"Perfil e Atividades\""}/> + </DivColumns> + </StyledSpan> + </RedeVaziaBoxContainer> + </div> + </Paper> + </ContainerDivStyled> + </React.Fragment> + ) +} + +const DivColumns = styled.div` + display : flex; + flex-direction : row; + aling-items : space-between + padding-right : 15px; + padding-left : 15px +` + +const StyledHr = styled.hr` + margin-top : 20px; + margin-bottom : 20px; + border : 0; + border-top: 1px solid #eee; +` + +const RedeVaziaBoxContainer = styled.div` + background-color : #fff; + box-shadow: 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24); + padding: 30px; + padding-right: 30px; + padding-left: 30px; + margin-bottom: 30px; + text-align: center; + height: 100%; + padding-left: 0 !important; + padding-right: 0 !important; + margin-top: 20px; +} +` +const StyledSpan = styled.span` + font-weight : lighter; + margin-top: 0; + font-family: Roboto; + font-size: 24px; +` diff --git a/src/Components/TabPanels/TabPanelAtividades.js b/src/Components/TabPanels/TabPanelAtividades.js new file mode 100644 index 0000000000000000000000000000000000000000..eda3b1e59ac85e639684dea1ae16059176fc2e70 --- /dev/null +++ b/src/Components/TabPanels/TabPanelAtividades.js @@ -0,0 +1,166 @@ +import React, {useContext, useState, useEffect} from 'react' +import styled from 'styled-components' +import { Container } from 'react-grid-system' +import Paper from '@material-ui/core/Paper'; +import Button from '@material-ui/core/Button'; +import axios from 'axios' +import {apiUrl} from '../../env'; +import Bolo from '../../img/Bolo.png' +import LoadingSpinner from '../LoadingSpinner.js' + +export default function TabPanelAtividades (props) { + const [notifications, setNotifications] = useState([]); + const [notificatonsLength, setLength] = useState(0); + const [loading, handleLoading] = useState(true) + + useEffect( () => { + axios.get(`${apiUrl}/feed`, props.config) + .then( (response) => { + handleLoading(false) + //console.log(response) + setNotifications(response.data) + //console.log(response.data.length) + setLength(response.data.length) + }, + (error) => { + console.log('error while running getNotifications') + } + ) + }, []) + + return ( + + <ContainerDivStyled> + <Paper elevation={3}> + <div> + <DivTitulo> + <InnerDivTitulo> + <TituloContent> + <p style={{margin:"0 0 10px", marginBottom : "40px"}}>Todas Notificações</p> + </TituloContent> + </InnerDivTitulo> + </DivTitulo> + { + loading ? + ( + <LoadingSpinner text={'Carregando Atividades'}/> + ) + : + ( + [ + <div> + { + notificatonsLength == 0 ? + ( + [ + <NoNotificationsDiv> + <div> + <div> + <H3Styled><img src={Bolo} alt='bolo' style={{width:"23px"}}/> Você se cadastrou na Plataforma</H3Styled> + </div> + <p + style={{fontSize:"15px", fontWeight:"lighter", margin:"0 0 10px", display:"flex", justifyContent:"center", textAlign:"center"}} + >Construa conosco a plataforma e amplie sua rede de conhecimento interagindo + <br/> + com pessoas envolvidas com experiências que ocorrem em todo o Brasil! + </p> + + </div> + </NoNotificationsDiv> + ] + ) + : + ( + [ <> + {/*some sort of map with a list of notifications idk what though*/} + <LoadMoreButton><span>CARREGAR MAIS 4</span></LoadMoreButton> + <LoadMoreButton><span>CARREGAR MAIS 20</span></LoadMoreButton> + </> + ] + ) + } + </div> + + ] + ) + } + </div> + </Paper> + </ContainerDivStyled> + ) +} + +const H3Styled = styled.h3` + font-size: 24px; + font-weight : lighter; + color : #00bcd4; + margin-top : 20px; + margin-bottom : 10px; + display : flex; + justify-content : center; + align-items : center; +` + +const NoNotificationsDiv = styled.div` + height : 250px; + display: flex; + align-items : center; + justify-content : center; +` + +const LoadMoreButton = styled(Button)` + outline : none !important; + display : inline-block !important; + cusor : pointer !important; + min-height : 36px !important; + min-widht : 88px !important; + line-height: 36px !important; + vertical-align: middle !important; + border : 0 !important; + padding : 0 px !important; + margin : 6px 8px !important; + text-decoration : none !important; + font-weight : 500 !important; + overflow : hidden !important; + text-transform : uppercase !important; + font-size : 14px !important; +` + +const TituloContent = styled.div` + display : block; + z-index : 1; + position : relative; + font-family: Roboto, sans-serif; + font-weight : ligther; +` + +const InnerDivTitulo = styled.div` + margin-top : 24px; + padding-top : 16px; + padding-left : 16px; + padding-right : 16px; + font-size: 30px; + font-weight: lighter; + color: #6e6e6e; + text-align: center; +` + + +const DivTitulo = styled.div` + display : flex; + justify-content : center; + font-size: 14px; + font-weight: 500; + letter-spacing: .01em; + line-height: 1.2em; + margin : 0; + border-bottom: 1px solid #eee; +` + +const ContainerDivStyled = styled.div` + max-width : 1140px; + margin-left : auto; + margin-right : auto; + margin-left : 20em; + background-color: #fff; +` diff --git a/src/Components/TabPanels/TabPanelColecoes.js b/src/Components/TabPanels/TabPanelColecoes.js new file mode 100644 index 0000000000000000000000000000000000000000..fbe39831c0f124a42258abf06f7a6966cd64df0d --- /dev/null +++ b/src/Components/TabPanels/TabPanelColecoes.js @@ -0,0 +1,158 @@ +import React, {useContext, useState, useEffect} from 'react' +import styled from 'styled-components' +import { Container } from 'react-grid-system' +import Paper from '@material-ui/core/Paper'; +import Button from '@material-ui/core/Button'; +import {ButtonMostrarTodos, ButtonMostrarMais, BtnAlinhaRecPvt, DivContainerRecursosPublicados, ContainerDivStyled, DivTitulo, StyledP, StyledHR} from './TabPanelMeusRecursos.js' +import {NoPubSpan, DivConteudoNaoPublicado, DivTextoNoPublications} from './TabPanelMeusRecursos.js' +import LoadingSpinner from '../LoadingSpinner.js' +import PaginaVaziaColecao from '../../img/Pagina_vazia_colecao.png' +import axios from 'axios' +import {apiUrl} from '../../env'; +import CreateNewFolderIcon from '@material-ui/icons/CreateNewFolder'; + +export default function TabPanelColecoes (props) { + const [loading, handleLoading] = useState(true) + + const [userCollections, setuserCollections] = useState([]) + const [userCollectionsLength, setuserCollectionsLength] = useState(0) + + const [followedCollections, setFollowedCollections] = useState([]) + const [followedCollectionsLength, setfollowedCollectionsLength] = useState(0) + + useEffect( () => { + axios.all([ + axios.get((`${apiUrl}/users/` + props.id + '/collections'), props.config), + axios.get((`${apiUrl}/users/` + props.id + '/following/Collection'), props.config), + ]) + .then( (responseArr) => { + handleLoading(false) + console.log(responseArr) + console.log(responseArr[0].data) + console.log(responseArr[1].data) + }, + (error) => { + handleLoading(false) + console.log('error while running axios all') + } + ) + }, []) + + return ( + <> + { + loading ? + ( + <LoadingSpinner text={'CARREGANDO COLEÇÕES'}/> + + ) + : + ( + [ + <React.Fragment> + <ContainerDivStyled> + <Paper elevation={3}> + <DivTitulo> + <StyledP>Minhas Coleções <b style={{fontWeight:"700", fontSize:"20px"}}>({userCollectionsLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div style={{paddingRight:"15px", paddingLeft:"15px"}}> + <CardDiv> + <div style={{backgroundColor:"#673ab7", height:"250px", display:"flex", justifyContent:"center", alignItems:"center"}}> + <CreateNewFolderIcon style={{color:"#fff", fontSize:"70px"}}/> + <p style={{fontSize:"16px", margin:"0 0 10px"}}> + CRIAR COLEÇÃO + </p> + </div> + </CardDiv> + { + userCollectionsLength == 0 ? + ( + [ + <DivTextoNoPublications style={{width:"50%"}}> + <div style={{position:"relative", top:"50%", transform:"translateY(-50%)"}}> + <div> + <img src={PaginaVaziaColecao} alt="PaginaVaziaColecao" + style={{height:"150px",width:"150px", verticalAlign:"middle", border:"0"}}/> + <br/> + <span style={{fontFamily:"Roboto", fontWeight:"lighter", fontSize:"24px"}}> + Criamos a sua primeira Coleção! + </span> + <p style={{fontFamily:"Roboto", fontSize:"16px", margin:"0 0 10px"}}> + Adicione nela recursos que você queira acessar mais tarde. + <br/> + Crie novas coleções clicando no cartão roxo "Criar Colecão". + </p> + </div> + </div> + </DivTextoNoPublications> + ] + ) + : + ( + <> + <DivContainerRecursosPublicados> + </DivContainerRecursosPublicados> + <BtnAlinhaRecPvt> + <p style={{margin:"0 0 10px", fontSize:"14px"}}>Carregados 2 de 2</p> + </BtnAlinhaRecPvt> + </> + ) + } + + </div> + </Paper> + </ContainerDivStyled> + + <ContainerDivStyled> + <Paper elevation={3}> + <DivTitulo> + <StyledP>Coleções que eu sigo <b style={{fontWeight:"700", fontSize:"20px"}}>({followedCollectionsLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div style={{height : "400px"}}> + { + followedCollectionsLength == 0 ? + ( + [ + <> + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você ainda não segue nenhuma coleção.</NoPubSpan> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + </> + ] + ) + : + ( + [ + <> + <DivContainerRecursosPublicados> + </DivContainerRecursosPublicados> + <BtnAlinhaRecPvt> + <p style={{margin:"0 0 10px", fontSize:"14px"}}>Carregados 4 de 4</p> + </BtnAlinhaRecPvt> + </> + ] + ) + } + </div> + </Paper> + </ContainerDivStyled> + </React.Fragment> + ] + ) + } + </> + ) +} + +const CardDiv = styled.div` + margin-top : 10px; + margin-bottom : 10px; + width : 25%; + float : left; + padding-left : 15px; + padding-right : 15px; +` diff --git a/src/Components/TabPanels/TabPanelEditarPerfil.js b/src/Components/TabPanels/TabPanelEditarPerfil.js new file mode 100644 index 0000000000000000000000000000000000000000..fc445817f6332fd65826adb6de0ec75f08688ec8 --- /dev/null +++ b/src/Components/TabPanels/TabPanelEditarPerfil.js @@ -0,0 +1,253 @@ +import React, {useContext, useState} from 'react' +import styled from 'styled-components' +import { Store } from '../../Store.js'; +import {Link} from 'react-router-dom' +import Button from '@material-ui/core/Button'; +import IconButton from '@material-ui/core/IconButton'; +import PhotoCamera from '@material-ui/icons/PhotoCamera'; +import Tooltip from '@material-ui/core/Tooltip'; +import FormInput from "../FormInput.js" +import ValidateUserInput from '../FormValidationFunction.js' + + + +export default function TabPanelEditarPerfil (props) { + const {state, dispatch} = useContext(Store) + const [hoverAlterarFoto, handleAlterarFoto] = React.useState(false) + + const [formNome, setNome] = useState({ + key : false, + value : "" + }) + + const [formAboutMe, setAboutMe] = useState({ + key : false, + value : "", + }) + + const handleHoverAlterarFoto = () => { + handleAlterarFoto(!hoverAlterarFoto) + } + + const updateCover = (selectorFiles : FileList) => { + console.log(selectorFiles) + console.log(selectorFiles[0].name) + } + + const handleChange = (e, type) => { + const userInput = e.target.value + const flag = ValidateUserInput(type, userInput) + + if(type === 'username') { + setNome({...formNome, + key : flag, + value : userInput + }) + console.log(formNome) + } + else if (type === 'aboutMe') { + setAboutMe({...formAboutMe, + key : flag, + value : userInput, + }) + console.log(formAboutMe) + } + } + + const limpaCamposForm = () => { + setNome({...formNome, + key : false, + value : '' + }) + + setAboutMe({...formAboutMe, + key : false, + value : '' + }) + } + + const handleSubmit = (e) => { + e.preventDefault() + const info = {nome : formNome.value, aboutMe : formAboutMe.value} + const flagNome = formNome.key + const flagAboutMe = formAboutMe.key + + if (!(flagNome || flagAboutMe)) { + console.log(info) + limpaCamposForm() + } + } + + return ( + <div className="card-config"> + <h1 style={{fontWeight:"300"}}>Editar Perfil </h1> + <div className='content-div'> + <div style={{padding:"0", display:"flex", flexDirection:"column"}}> + <HeaderContainer> + <div style={{position:"relative", height:"100%"}}> + <img src={state.currentUser.userCover} alt="user cover avatar" style={{width:"100%", height:"100%", objectFit:"cover"}}/> + <input accept="image/*" style = {{display:"none"}} id="icon-button-file" type="file" onChange={(e) => updateCover(e.target.files)}/> + <label htmlFor="icon-button-file"> + <Tooltip title={<span style={{fontSize:"14px", overflow:"hidden", transition:"all .5s ease"}}>ALTERAR CAPA</span>} placement="left"> + <IconButton style={{position:"absolute",right:"0",top:"0",color:"#fff"}}color="primary" aria-label="upload picture" component="span"> + <PhotoCamera /> + </IconButton> + </Tooltip> + </label> + </div> + <ProfileAvatarDiv onMouseEnter={handleHoverAlterarFoto} onMouseLeave={handleHoverAlterarFoto}> + <img src={state.currentUser.userAvatar} alt = "user avatar" style={{border:"0", verticalAlign:"middle"}}/> + <ChangeAvatarDiv style={ {display : hoverAlterarFoto ? 'flex' : 'none'}}> + <span>Alterar Foto</span> + </ChangeAvatarDiv> + </ProfileAvatarDiv> + </HeaderContainer> + <br/> + <br/> + <br/> + <br/> + </div> + + <div style={{paddingTop:"90px"}}> + <div style={{display:"flex", flexDirection:"row"}}> + <form onSubmit={e => handleSubmit(e)}> + <FormInput + inputType={"text"} + name={"Nome Completo"} + value={formNome.value} + placeholder={"Nome Completo"} + handleChange={e => handleChange(e, 'username')} + required={true} + error={formNome.key} + /> + <FormInput + inputType={"text"} + name={"Sobre Mim"} + value={formAboutMe.value} + multi = {true} + rows="3" + rowsMax = "3" + error={formAboutMe.key} + placeholder={"Sobre Mim"} + handleChange={e => handleChange(e, 'aboutMe')} + required={false} + help = {formAboutMe.value.length + '/160'} + /> + </form> + </div> + <ButtonsDiv> + <Link to="perfil" ><ButtonCancelar ><span>CANCELAR</span></ButtonCancelar></Link> + <ButtonConfirmar onClick={e => handleSubmit(e)}><span>SALVAR ALTERAÇÕES</span></ButtonConfirmar> + </ButtonsDiv> + </div> + </div > + </div> + ) +} + +const ButtonConfirmar = styled(Button)` + background-color : #00bcd4 !important; + color : #fff !important; + font-family : 'Roboto',sans-serif !important; + font-size : 14px !important; + font-weight : 500 !important; + padding-left : 16px !important; + padding-right : 16px !important; + outline : none !important; + margin : 6px 8px !important; + white-space : nowrap !important; + text-transform : uppercase !important; + font-weight : bold !important; + font-size : 14px !important; + font-style : inherit !important; + font-variant : inherit !important; + font-family : inherit !important; + text-decoration : none !important; + overflow : hidden !important; + display : inline-block !important; + position : relative !important; + cursor : pointer !important; + min-height : 36px !important; + min-width : 88px !important; + line-height : 36px !important; + vertical-align : middle !important; + align-items : center !important; + text-align : center !important; + border-radius : 3px !important; + box-sizing : border-box !important; + border : 0 !important; +` + +export const ButtonCancelar = styled(Button)` + height : 36px !important; + padding-left : 16px !important; + padding-right : 16px !important; + font-weight : bold !important; + border-radius : 3px !important; + outline : none !important; + text-transform : uppercase !important; + font-weight : 500 !important; + font-size : 14px !important; + font-style : inherit !important; + font-variant : inherit !important; + font-family : inherit !important; + text-decoration : none !important; + overflow : hidden !important; + display : inline-block !important; + position : relative !important; + cursor : pointer !important; + min-height : 36px !important; + min-width : 88px !important; + line-height : 36px !important; + vertical-align : middle !important; + align-items : center !important; + text-align : center !important; + border-radius : 3px !important; + box-sizing : border-box !important; + user-select : none !important; + border : 0 !important; + padding : 0 6px !important; + margin : 6px 8px !important; + :hover{ + background-color : #f1f1f1 !important; + } + +` + +const ButtonsDiv = styled.div` + text-align : right; + margin-top : 80px; +` + +const ChangeAvatarDiv = styled.div` + height : 40px; + position: absolute; + width : 100%; + bottom : 0; + display : flex; + background-color : #000; + color : #fff; + justify-content : center; +` + +const ProfileAvatarDiv = styled.div` + bottom : -10px; + left : 120px !important; + border-radius : 100%; + position : absolute; + width : 100px !important; + height : 100px !important; + overflow : hidden; + border : 8px solid #fff; + outline : 0; + cursor : pointer; + z-index : 10; + background-color : #fff !important; +` + +const HeaderContainer = styled.div` + background-color : #afeeee; + position : relative; + height : 150px; + border-radius : 8px; +` diff --git a/src/Components/TabPanels/TabPanelFavoritos.js b/src/Components/TabPanels/TabPanelFavoritos.js new file mode 100644 index 0000000000000000000000000000000000000000..3cb7ea74c8ebd043dcfe3ceaa9a669a07f74719b --- /dev/null +++ b/src/Components/TabPanels/TabPanelFavoritos.js @@ -0,0 +1,163 @@ +import React, {useContext, useState, useEffect} from 'react' +import styled from 'styled-components' +import { Container } from 'react-grid-system' +import Paper from '@material-ui/core/Paper'; +import Button from '@material-ui/core/Button'; +import axios from 'axios' +import {apiUrl} from '../../env'; +import {ButtonMostrarTodos, ButtonMostrarMais, BtnAlinhaRecPvt, DivContainerRecursosPublicados, ContainerDivStyled, DivTitulo, StyledP, StyledHR} from './TabPanelMeusRecursos.js' +import {NoPubSpan, DivConteudoNaoPublicado, DivTextoNoPublications} from './TabPanelMeusRecursos.js' +import LoadingSpinner from '../LoadingSpinner.js' + +export default function TabPanelFavoritos (props) { + const [loading, handleLoading] = useState(true) + + const [likedLearnObjs, setlikedLearnObjs] = useState([]) + const [likedLearnObjsLength, setlikedLearnObjsLength] = useState(0) + + const [likedCollections, setlikedCollections] = useState([]) + const [likedCollectionsLength, setlikedCollectionsLength] = useState(0) + + useEffect( () => { + axios.all([ + axios.get((`${apiUrl}/users/` + props.id + '/learning_objects/liked'), props.config), + axios.get((`${apiUrl}/users/` + props.id + '/collections/liked'), props.config), + ]) + .then( (responseArr) => { + handleLoading(false) + console.log(responseArr) + console.log(responseArr[0].data) + console.log(responseArr[1].data) + }, + (error) => { + handleLoading(false) + console.log('error while running axios all') + } + ) + }, []) + + return ( + <> + { + loading? + ( + <LoadingSpinner text={'CARREGANDO...'}/> + ) + : + ( + [ + <React.Fragment> + <ContainerDivStyled> + <Paper elevation={3}> + <DivTitulo> + <StyledP>Recursos Favoritados <b style={{fontWeight:"700", fontSize:"20px"}}>({likedLearnObjsLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div style={{height : "400px"}}> + { + likedLearnObjsLength == 0 ? + ( + [ + <> + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você ainda não curtiu nenhum Recurso.</NoPubSpan> + <p style={{fontFamily:"Roboto",fontSize:"16px"}}>Quando você favorita um recurso ele aparece nesta seção. Além disso, você + <br/> + aumenta o prestÃgio dele na Plataforma. Para favoritar, basta clicar no Ãcone de + <br/> + coração que aparece nos Recursos. + </p> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + </> + ] + ) + : + ( + [ + <> + <DivContainerRecursosPublicados> + </DivContainerRecursosPublicados> + <BtnAlinhaRecPvt> + <p style={{margin:"0 0 10px", fontSize:"14px"}}>Carregados 4 de 7</p> + <ButtonMostrarMais> + <span style={{color:"#fff", fontSize:"14px", fontWeight:"500"}}>MOSTRAR MAIS</span> + </ButtonMostrarMais> + <ButtonMostrarTodos> + <span style={{color:"#666", fontSize:"14px", fontWeight:"500"}}>MOSTRAR TODOS</span> + </ButtonMostrarTodos> + </BtnAlinhaRecPvt> + </> + ] + ) + } + </div> + </Paper> + </ContainerDivStyled> + + <ContainerDivStyled> + <Paper elevation={3}> + <DivTitulo> + <StyledP>Coleções Favoritadas <b style={{fontWeight:"700", fontSize:"20px"}}>({likedCollectionsLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div style={{height : "400px"}}> + { + likedCollectionsLength == 0 ? + ( + [ + <> + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você ainda não curtiu nenhuma coleção.</NoPubSpan> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + </> + ] + ) + : + ( + [ + <> + <DivContainerRecursosPublicados> + </DivContainerRecursosPublicados> + <BtnAlinhaRecPvt> + <p style={{margin:"0 0 10px", fontSize:"14px"}}>Carregados 4 de 7</p> + <ButtonMostrarMaisColecao> + <span style={{color:"#fff", fontSize:"14px", fontWeight:"500"}}>MOSTRAR MAIS</span> + </ButtonMostrarMaisColecao> + <ButtonMostrarTodos> + <span style={{color:"#666", fontSize:"14px", fontWeight:"500"}}>MOSTRAR TODOS</span> + </ButtonMostrarTodos> + </BtnAlinhaRecPvt> + </> + ] + ) + } + </div> + </Paper> + </ContainerDivStyled> + </React.Fragment> + ] + ) + } + </> + ) +} + +const ButtonMostrarMaisColecao = styled(Button)` + background-color : #503096 !important; + font-size: 14px !important; + font-weight: 500 !important; + height: 36px !important; + border-radius: 3px !important; + padding-left: 16px !important; + padding-right: 16px !important; + box-shadow: 0 2px 5px 0 rgba(0,0,0,.26) !important; + outline : none !important; + min-width : 88px !important; + vertical-align : middle !important; + margin : 6px 8px !important; + text-decoration : none !important; +` diff --git a/src/Components/TabPanels/TabPanelGerenciarConta.js b/src/Components/TabPanels/TabPanelGerenciarConta.js new file mode 100644 index 0000000000000000000000000000000000000000..4ed6f6a8df7812f7cf61a4d9f26ab21be3b8424d --- /dev/null +++ b/src/Components/TabPanels/TabPanelGerenciarConta.js @@ -0,0 +1,202 @@ +import React, {useState} from 'react' +import Paper from '@material-ui/core/Paper'; +import Button from '@material-ui/core/Button'; +import FormInput from "../FormInput.js" +import {CompletarCadastroButton} from './TabPanelSolicitarContaProfessor.js' +import {ButtonCancelar} from './TabPanelEditarPerfil.js' +import ValidateUserInput from '../FormValidationFunction.js' + +export default function TabPanelGerenciarConta (props) { + const [senhaAtual, setSenhaAtual] = useState( + { + key : false, + value : localStorage.getItem("@portalmec/senha") || "" + }) + + const [novaSenha, setNovaSenha] = useState( + { + key : false, + value : "" + }) + + const [novaSenhaConfirmacao, setNovaSenhaConfirmacao] = useState( + { + key : false, + value : "" + }) + + const [novoEmail, setNovoEmail] = useState( + { + key : false, + value : "" + }) + + const handleChangeSenha = (e, type) => { + const userInput = e.target.value + const flag = (type === 'confirmacao' ? ValidateUserInput('confirmation', userInput, novaSenha.value) : ValidateUserInput('password', userInput)) + + if(type === 'senhaAtual') { + setSenhaAtual({...senhaAtual, + key : flag, + value : userInput + }) + console.log(senhaAtual) + } + else if(type === 'novaSenha') { + setNovaSenha({...novaSenha, + key : flag, + value : userInput + }) + console.log(novaSenha) + } + else if (type === 'confirmacao'){ + setNovaSenhaConfirmacao({...novaSenhaConfirmacao, + key : flag, + value : userInput + }) + console.log(novaSenhaConfirmacao) + } + } + + const handleChangeEmail = (e) => { + const userInput = e.target.value + const flag = ValidateUserInput('email', userInput) + + setNovoEmail({...novoEmail, + key : flag, + value : userInput + }) + + console.log(novoEmail) + } + + const limpaCamposForm = () => { + setSenhaAtual({...senhaAtual, + key : false, + value : '' + }) + + setNovaSenha({...novaSenha, + key : false, + value : '' + }) + + setNovaSenhaConfirmacao({...novaSenhaConfirmacao, + key : false, + value : '' + }) + } + + const onSubmit = (e, type) => { + e.preventDefault() + + if (type === 'senha'){ + if (senhaAtual.value === localStorage.getItem("@portalmec/senha")) { + const login = {senhaAtual : senhaAtual.value, novaSenha : novaSenha.value, novaSenhaConfirmacao : novaSenhaConfirmacao.value} + + if (!(senhaAtual.key || novaSenha.key || novaSenhaConfirmacao.key)) { + console.log(login) + limpaCamposForm() + props.handleSnackbar() + } + } + else { + console.log(localStorage.getItem("@portalmec/senha"), senhaAtual.value) + } + } + else { + console.log(novoEmail.value) + } + + } + + return ( + <> + <Paper elevation={3} style= {{width:"100%"}}> + <div className='card-config'> + <div className='content-div'> + <h1>Gerenciar Conta</h1> + <div style={{display : "flex", flexDirection : "column"}}> + <form style={{width:"500px", margin : "0 0 20px 0"}} onSubmit={e => onSubmit(e, 'senha')}> + <h4 style={{display:"flex", justifyContent:"flex-start", fontSize:"18px"}}>Alterar Senha</h4> + <FormInput + inputType={"password"} + name={"Senha Atual"} + value={senhaAtual.value} + placeholder={"Senha atual"} + handleChange={e => handleChangeSenha(e, 'senhaAtual')} + required={true} + error={senhaAtual.key} + help={ senhaAtual.key ? "Faltou inserir sua senha atual" : ""} + /> + <FormInput + inputType={"password"} + name={"Nova senha"} + value={novaSenha.value} + placeholder={"Nova senha"} + handleChange={e => handleChangeSenha(e, 'novaSenha')} + required={true} + error={novaSenha.key} + help={ novaSenha.key ? (novaSenha.value.length == 0 ? "Faltou definir uma nova senha" : "A senha precisa ter no mÃnimo 8 caracteres.") : ""} + /> + <FormInput + inputType={"password"} + name={"Digite novamente a nova senha"} + value={novaSenhaConfirmacao.value} + placeholder={"Digite novamente a nova senha"} + handleChange={e => handleChangeSenha(e, 'confirmacao')} + required={true} + error={novaSenhaConfirmacao.key} + help={ novaSenhaConfirmacao.key ? "As senhas devem ser iguais" : ""} + /> + <div style={{display:"flex", flexDirection:"row", justifyContent:"space-evenly"}}> + <span style={{paddingTop:"0.7em"}}><a href="recuperar-senha" style={{textAlign: "flex-start", color:"#00bcd4"}}>Esqueceu a senha?</a></span> + <div style={{margin:"0"}}> + <ButtonCancelar onClick={limpaCamposForm}>Limpar Campos</ButtonCancelar> + <CompletarCadastroButton type="submit">Alterar Senha</CompletarCadastroButton> + </div> + </div> + </form> + </div> + </div> + </div> + </Paper> + <Paper elevation={3} style= {{width:"100%"}}> + <div className='card-config'> + <div className='content-div'> + <div style={{display : "flex", flexDirection : "column"}}> + <form style={{width:"500px"}} onSubmit={(e) => onSubmit(e, 'email')}> + <h4 style={{display:"flex", justifyContent:"flex-start", fontSize:"18px"}}>Alterar e-mail</h4> + <FormInput + inputType={"text"} + name={"email"} + value={novoEmail.value} + placeholder={"E-mail"} + handleChange={e => handleChangeEmail(e)} + required={true} + error = {novoEmail.key} + /> + <div style={{margin:"0", display:"flex", justifyContent:"flex-start"}}> + <CompletarCadastroButton type="submit">SALVAR ALTERAÇÕES</CompletarCadastroButton> + </div> + </form> + </div> + </div> + </div> + </Paper> + <Paper elevation={3} style= {{width:"100%"}}> + <div className='card-config'> + <div className='content-div'> + <div> + <h4 style={{display:"flex", justifyContent:"flex-start", fontSize:"18px"}}>Conta</h4> + <span style={{margin:"0", display:"flex", justifyContent:"flex-start"}}>Antes de excluir a sua conta, saiba que ela será removida permanentemente.</span> + </div> + <div style={{margin:"0", display:"flex", justifyContent:"flex-start"}}> + <ButtonCancelar style={{color:'#eb4034'}}>EXCLUIR CONTA</ButtonCancelar> + </div> + </div> + </div> + </Paper> + </> + ) +} diff --git a/src/Components/TabPanels/TabPanelMeusRecursos.js b/src/Components/TabPanels/TabPanelMeusRecursos.js new file mode 100644 index 0000000000000000000000000000000000000000..5e4c06166c1a769ff09820be93e1a9e8b4c3a7aa --- /dev/null +++ b/src/Components/TabPanels/TabPanelMeusRecursos.js @@ -0,0 +1,267 @@ +import React, {useContext, useState, useEffect} from 'react' +import styled from 'styled-components' +import { Container } from 'react-grid-system' +import Paper from '@material-ui/core/Paper'; +import Button from '@material-ui/core/Button'; +import axios from 'axios' +import {apiUrl} from '../../env'; +import LoadingSpinner from '../LoadingSpinner.js' + +export default function TabPanelAtividades (props) { + const [loading, handleLoading] = useState(true) + + const [learningObjects, setLearningObjects] = useState([]); + const [learningObjectsLength, setLengthLearnObj] = useState(0); + + const [drafts, setDrafts] = useState([]); + const [draftsLength, setLengthDrafts] = useState(0); + + const [curating, setCurating] = useState([]); + const [curatingLength, setLengthCurating] = useState(0); + + useEffect( () => { + axios.all([ + axios.get((`${apiUrl}/users/` + props.id + '/learning_objects'), props.config), + axios.get((`${apiUrl}/users/` + props.id + '/drafts'), props.config), + axios.get((`${apiUrl}/users/` + props.id + '/submissions?status=submitted'), props.config) + ]) + .then( (responseArr) => { + handleLoading(false) + console.log(responseArr) + console.log(responseArr[0].data) + console.log(responseArr[1].data) + console.log(responseArr[2].data) + + }, + (error) => { + handleLoading(false) + console.log('error while running axios all') + } + ) + }, []) + + + return ( + <> + { + loading ? + ( + <LoadingSpinner text={'Carregando Recursos'}/> + ) + : + ([ + <React.Fragment> + <ContainerDivStyled> + <Paper elevation={3}> + + <DivTitulo> + <StyledP>Recurso Publicado <b style={{fontWeight:"700", fontSize:"20px"}}>({learningObjectsLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div> + { + learningObjectsLength == 0 ? + ( + [ + <> + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você ainda não publicou nenhum Recurso!</NoPubSpan> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + </> + ] + ) + : + ( + <> + {/**some sort of map with a list of notifications idk what though**/} + <span>stuff goes here</span> + </> + ) + + } + </div> + </Paper> + </ContainerDivStyled> + + <ContainerDivStyled> + <Paper elevation={3}> + <DivTitulo> + <StyledP>Rascunhos <b style={{fontWeight:"700", fontSize:"20px"}}>({draftsLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div style={{height : "400px"}}> + { + draftsLength == 0 ? + ( + [ + <> + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você não tem nenhum recurso sendo editado.</NoPubSpan> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + </> + ] + ) + : ( + [ + <> + <DivContainerRecursosPublicados> + </DivContainerRecursosPublicados> + <BtnAlinhaRecPvt> + <p style={{margin:"0 0 10px", fontSize:"14px"}}>Carregados 4 de 7</p> + <ButtonMostrarMais> + <span style={{color:"#fff", fontSize:"14px", fontWeight:"500"}}>MOSTRAR MAIS</span> + </ButtonMostrarMais> + <ButtonMostrarTodos> + <span style={{color:"#666", fontSize:"14px", fontWeight:"500"}}>MOSTRAR TODOS</span> + </ButtonMostrarTodos> + </BtnAlinhaRecPvt> + </> + ] + ) + } + </div> + </Paper> + </ContainerDivStyled> + + <ContainerDivStyled> + <Paper elevation={3}> + + <DivTitulo> + <StyledP>Recurso sendo avaliado pela curadoria <b style={{fontWeight:"700", fontSize:"20px"}}>({curatingLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div> + { + curatingLength == 0 ? + ( + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você não tem nenhum recurso sendo avaliado pelos curadores.</NoPubSpan> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + ) + : + ( + <> + {/**some sort of map with a list of notifications idk what though**/} + <span>stuff goes here</span> + </> + ) + } + </div> + </Paper> + </ContainerDivStyled> + </React.Fragment> + ]) + } + </> + ) +} + +export const ButtonMostrarTodos = styled(Button)` + &:hover { + color : #d5d5d5 !important; + } + height : 36px !important; + padding-left: 16px !important; + padding-right: 16px !important; + font-weight: 500 !important; + border-radius: 3px !important; + color:#666 !important; + background-color: #e8e8e8 !important; + min-width : 88px !important; + height: 36px !important; +` + +export const ButtonMostrarMais = styled(Button)` + background-color : #ff7f00 !important; + font-size: 14px !important; + font-weight: 500 !important; + height: 36px !important; + border-radius: 3px !important; + padding-left: 16px !important; + padding-right: 16px !important; + box-shadow: 0 2px 5px 0 rgba(0,0,0,.26) !important; + outline : none !important; + min-width : 88px !important; + vertical-align : middle !important; + margin : 6px 8px !important; + text-decoration : none !important; +` + +export const BtnAlinhaRecPvt = styled.div` + text-align : center; + width : 100%; + float : left; + position : relative; + min-height : 1px; + padding-right : 15px; + padding-left : 15px; +` + +export const DivContainerRecursosPublicados = styled.div` + width : 100%; + float : left; + position : relative; + min-height : 1px; + padding-right : 15px; + padding-left : 15px; +` + +export const NoPubSpan = styled.span` + font-size : 24px; + font-family : Roboto; + font-weight : lighter; +` + +export const DivConteudoNaoPublicado = styled.div` + position : relative; + top : 50%; + transform : translateY(-50%); +` + +export const DivTextoNoPublications = styled.div` + height : 360px; + text-align : center; + width : 100%; + padding-right : 15px; + padding-left : 15px; +` + +export const StyledHR = styled.hr` + border-color : #757575; + border-top: 1px solid #eee; + margin : 0 15px 0 15px; + padding-right : 0; + padding-left : 0; +` + +export const StyledP = styled.p` + text-align : left; + margin-top : 10px; + padding-left : 15px; + padding-right : 15px; + font-weight : 300; + font-size : 1.875em; +` + +export const DivTitulo = styled.div` + padding : 0; + margin-bottom : 10px; + width : 100; + display: flex; + flex-direction : column; +` + +export const ContainerDivStyled = styled.div` + max-width : 1140px; + margin-left : auto; + margin-right : auto; + margin-left : 20em; + margin-bottom: 30px; + background-color: #fff; +` diff --git a/src/Components/TabPanels/TabPanelRede.js b/src/Components/TabPanels/TabPanelRede.js new file mode 100644 index 0000000000000000000000000000000000000000..d31f2bcfa480803f3476f05242bdb01d5eb631e2 --- /dev/null +++ b/src/Components/TabPanels/TabPanelRede.js @@ -0,0 +1,149 @@ +import React, {useContext, useState, useEffect} from 'react' +import styled from 'styled-components' +import { Container } from 'react-grid-system' +import Paper from '@material-ui/core/Paper'; +import Button from '@material-ui/core/Button'; +import {ButtonMostrarTodos, ButtonMostrarMais, BtnAlinhaRecPvt, DivContainerRecursosPublicados, ContainerDivStyled, DivTitulo, StyledP, StyledHR} from './TabPanelMeusRecursos.js' +import axios from 'axios' +import {apiUrl} from '../../env'; +import LoadingSpinner from '../LoadingSpinner.js' +import ContainerRedeVazia from './ContainerRedeVazia.js' +import {NoPubSpan, DivConteudoNaoPublicado, DivTextoNoPublications} from './TabPanelMeusRecursos.js' + +export default function TabPanelRede (props) { + const [loading, handleLoading] = useState(true) + + const [followingList, setFollowing] = useState([]) + const [followingListLength, setFollowingLength] = useState(0) + + const [followersList, setFollowers] = useState([]) + const [followersListLength, setFollowersLength] = useState(0) + + useEffect( () => { + axios.all([ + axios.get((`${apiUrl}/users/` + props.id + '/following/User'), props.config), + axios.get((`${apiUrl}/users/` + props.id + '/followers'), props.config) + ]) + .then( (responseArr) => { + handleLoading(false) + console.log(responseArr) + console.log(responseArr[0].data) + console.log(responseArr[1].data) + + + }, + (error) => { + handleLoading(false) + console.log('error while running axios all') + } + ) + }, []) + + return ( + <> + { + loading ? + ( + [ + <LoadingSpinner text={'CARREGANDO...'}/> + ] + ) + : + ( + [ + <> + { + followingListLength == 0 && followersListLength == 0 ? + ( + [ + <> + <ContainerRedeVazia/> + </> + ] + ) + : + ( + [ + <React.Fragment> + <ContainerDivStyled> + <Paper elevation={3}> + <DivTitulo> + <StyledP>Seguidor <b style={{fontWeight:"700", fontSize:"20px"}}>({followingListLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div style={{height : "400px"}}> + { + followingListLength == 0 ? + ( + [ + <> + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você não possui nenhum seguidor.</NoPubSpan> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + </> + ] + ) + : + ( + [ + <> + <DivContainerRecursosPublicados/> + <BtnAlinhaRecPvt> + <p style={{margin:"0 0 10px", fontSize:"14px"}}>Carregado 1 de 1</p> + </BtnAlinhaRecPvt> + </> + ] + ) + } + </div> + </Paper> + </ContainerDivStyled> + + <ContainerDivStyled> + <Paper elevation={3}> + <DivTitulo> + <StyledP>Seguindo <b style={{fontWeight:"700", fontSize:"20px"}}>({followersListLength})</b></StyledP> + <StyledHR/> + </DivTitulo> + <div style={{height : "400px"}}> + { + followersListLength == 0 ? + ( + [ + <> + <DivTextoNoPublications> + <DivConteudoNaoPublicado> + <NoPubSpan>Você ainda não segue nenhum outro usuário.</NoPubSpan> + </DivConteudoNaoPublicado> + </DivTextoNoPublications> + </> + ] + ) + : + ( + [ + <> + <DivContainerRecursosPublicados/> + <BtnAlinhaRecPvt> + <p style={{margin:"0 0 10px", fontSize:"14px"}}>Carregado 1 de 1</p> + </BtnAlinhaRecPvt> + </> + ] + ) + } + </div> + </Paper> + </ContainerDivStyled> + </React.Fragment> + ] + ) + } + </> + ] + ) + } + </> + ) +} diff --git a/src/Components/TabPanels/TabPanelSolicitarContaProfessor.js b/src/Components/TabPanels/TabPanelSolicitarContaProfessor.js new file mode 100644 index 0000000000000000000000000000000000000000..648a33213752414bf028d05b57abd82bafba5546 --- /dev/null +++ b/src/Components/TabPanels/TabPanelSolicitarContaProfessor.js @@ -0,0 +1,116 @@ +import React, {useContext} from 'react' +import { Store } from '../../Store.js'; +import styled from 'styled-components' +import Button from '@material-ui/core/Button'; + +//3 casos + //Professor nao cadastrado (nao pediu OU submitter_request = rejected) + //Professor em análise (submitter_request = requested) + //Professor aceito (submitter_request = accepted) +export default function TabPanelSolicitarContaProfessor (props) { + const {state, dispatch} = useContext(Store) + + return ( + <div className='card-config'> + <div className='content-div'> + { + state.currentUser.submitter_request === 'default' || state.currentUser.submitter_request === 'rejected' ? + ( + [ + <div style={{paddingLeft:"100px", paddingRight:"101px"}}> + <ImageDiv/> + <StyledH2>Você é professor(a) da educação básica e gostaria de colaborar com a Plataforma?</StyledH2> + <StyledP>Ao ser identificado como professor(a), você poderá publicar e compartilhar recursos educacionais + digitais na plataforma com toda a comunidade escolar do paÃs. + </StyledP> + <div> + <CompletarCadastroButton> + SIM, COMPLETAR CADASTRO + </CompletarCadastroButton> + </div> + </div> + ] + ) + : + ( + [ + <> + { + state.currentUser.submitter_request === 'requested' ? + ( + [ + <span>Requested</span> + ] + ) + : + ( + [ + <span>Professor</span> + ] + ) + } + </> + ] + ) + } + </div> + </div> + ) +} + +export const CompletarCadastroButton = styled(Button)` + background-color : #00bcd4 !important; + color : #fff !important; + font-family : 'Roboto',sans-serif !important; + font-size : 14px !important; + font-weight : bold !important; + height : 36px !important; + border-radius : 3px !important; + padding-left : 16px !important; + padding-right : 16px !important; + outline : none !important; + margin : 6px 8px !important; + white-space : nowrap !important; + text-transform : uppercase !important; + font-weight : bold !important; + font-size : 14px !important; + font-style : inherit !important; + font-variant : inherit !important; + font-family : inherit !important; + text-decoration : none !important; + overflow : hidden !important; + display : inline-block !important; + position : relative !important; + cursor : pointer !important; + min-height : 36px !important; + min-width : 88px !important; + vertical-align : middle !important; + align-items : center !important; + text-align : center !important; + box-sizing : border-box !important; + border : 0 !important; +` + +const StyledP = styled.p` + font-size : 15px; + line-height : 22px; + text-align : left; + padding-bottom : 20px; +` + +const StyledH2 = styled.h2` + font-weight : 200; + font-size : 26px; + line-height : 36px; + text-align : left; + padding-bottom : 20px; +` + +const ImageDiv = styled.div` + background-image : url(https://plataformaintegrada.mec.gov.br/img/Publicar.png); + display : block; + height : 114px; + background-size : contain; + background-position : center center; + background-repeat : no-repeat; +` diff --git a/src/Components/TabPanels/TabRedeImgDiv.js b/src/Components/TabPanels/TabRedeImgDiv.js new file mode 100644 index 0000000000000000000000000000000000000000..95ab72c3c4d79436d142f9d7acde608179c2a977 --- /dev/null +++ b/src/Components/TabPanels/TabRedeImgDiv.js @@ -0,0 +1,10 @@ +import React from 'react' + +export default function TabRedeImgDiv (props) { + return ( + <div style={{width:"33.33333333%", textAlign : "center"}}> + <img src={props.img} alt={'no rede 1'} style={{width : "100%", verticalAlign : "middle", border : "0"}}/> + <p style={{fontSize : "14px", fontFamily : "Roboto", margin : "0 0 10px"}}>{props.text}</p> + </div> + ) +} diff --git a/src/Components/Table.js b/src/Components/Table.js new file mode 100644 index 0000000000000000000000000000000000000000..773a5fffb85387a8a4571b6e80b087c85104c944 --- /dev/null +++ b/src/Components/Table.js @@ -0,0 +1,81 @@ +import React from 'react'; +import { withStyles, makeStyles } from '@material-ui/core/styles'; +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableContainer from '@material-ui/core/TableContainer'; +import TableHead from '@material-ui/core/TableHead'; +import TableRow from '@material-ui/core/TableRow'; +import Paper from '@material-ui/core/Paper'; + +const StyledTableCell = withStyles(theme => ({ + head: { + backgroundColor: '#00bcd4', + color: '#ffffff', + fontFamily: 'Roboto', + fontStyle: 'normal', + fontWeight: 500, + fontSize: 15, + letterSpacing: .01 + }, + body: { + fontSize: 14, + }, +}))(TableCell); + +const StyledTableRow = withStyles(theme => ({ + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.background.default, + }, + }, +}))(TableRow); + + +const useStyles = makeStyles({ + table: { + minWidth: 970, + }, +}); + +export default function CustomizedTables(props) { + const classes = useStyles(); + + const onClick = (row) => { + const {city_name, id, name, state_name} = row + props.onClickTable(city_name, id, name, state_name) + } + + return ( + <> + <TableContainer component={Paper}> + <Table className={classes.table} aria-label="customized table"> + <TableHead> + <TableRow> + { + props.columns.map( (column)=> + <StyledTableCell align="left">{column}</StyledTableCell> + ) + } + </TableRow> + </TableHead> + <TableBody> + {props.rows.map(row => ( + <> + {console.log(row)} + <StyledTableRow onClick={() => onClick(row)} key={row.id}> + <StyledTableCell component="th" scope="row"> + {row.id} + </StyledTableCell> + <StyledTableCell align="left">{row.name}</StyledTableCell> + <StyledTableCell align="left">{row.state_name}</StyledTableCell> + <StyledTableCell align="left">{row.city_name}</StyledTableCell> + </StyledTableRow> + </> + ))} + </TableBody> + </Table> + </TableContainer> + </> + ); +} diff --git a/src/Pages/EditProfilePage.js b/src/Pages/EditProfilePage.js new file mode 100644 index 0000000000000000000000000000000000000000..59ee4f37a453096a8c91c09f6270f216efc32562 --- /dev/null +++ b/src/Pages/EditProfilePage.js @@ -0,0 +1,176 @@ +import React, {useState, useContext, useEffect} from 'react'; +import styled from 'styled-components' +import {Link} from 'react-router-dom' +import Breadcrumbs from '@material-ui/core/Breadcrumbs'; +import {BreadcrumbsDiv, StyledBreadcrumbs} from './UserPage.js' +import Tabs from '@material-ui/core/Tabs' +import Tab from '@material-ui/core/Tab'; +import Paper from '@material-ui/core/Paper'; +import TabPanelEditarPerfil from '../Components/TabPanels/TabPanelEditarPerfil.js' +import TabPanelSolicitarContaProfessor from '../Components/TabPanels/TabPanelSolicitarContaProfessor.js' +import TabPanelGerenciarConta from '../Components/TabPanels/TabPanelGerenciarConta.js' +import Snackbar from '@material-ui/core/Snackbar'; +import MuiAlert from '@material-ui/lab/Alert'; +import {Alert} from '../Components/LoginModal.js' +import Grid from '@material-ui/core/Grid' + +export default function EditProfilePage (props) { + const [tabs, setTabs] = useState([ + 'Editar Perfil', 'Solicitar conta de Professor', 'Gerenciar Conta' + ]) + const [tabValue, setTabValue] = useState(0) + const handleChangeTab = (e, newValue) => { + setTabValue(newValue) + } + + const [snackbarOpened, handleSnackbar] = useState(false) + const handleCloseSnackbar = (event, reason) => { + if (reason === 'clickaway') { + return; + } + + handleSnackbar(false); + } + return ( + <div style={{backgroundColor:"#f4f4f4", color:"#666"}}> + <Snackbar open={snackbarOpened} autoHideDuration={1000} onClose={handleCloseSnackbar} + anchorOrigin = {{ vertical:'top', horizontal:'right' }} + > + <Alert severity="success" style={{backgroundColor:"#00acc1"}}>Senha alterada com sucesso!</Alert> + </Snackbar> + <BreadcrumbsDiv> + <StyledBreadcrumbs> + <Link to="/" style={{color:"#00bcd4", textDecoration:"none"}}> + Página Inicial + </Link> + <span> + Minha área + </span> + <span> + Configurações da Conta + </span> + <span> + {tabs[tabValue]} + </span> + </StyledBreadcrumbs> + </BreadcrumbsDiv> + + <div style={{justifyContent:"center", width:"1170px", margin:"auto"}}> + <MainContainerDiv container spacing={3}> + <Grid item xs={3} style={{width : "auto", fontFamily:"Roboto"}} > + <Paper elevation={3} style= {{width:"max-content"}}> + <ConfiguracoesMenu> + <h4 style={{marginTop:"10px", fontFamily:"inherit", display:"flex", justifyContent:"center"}}> + Configurações da Conta + </h4> + <StyledTabs + orientation = "vertical" + variant = "scrollable" + value = {tabValue} + onChange = {handleChangeTab} + TabIndicatorProps = {{style : {display : "none"}}} + > + <StyledTab label={tabs[0]}/> + <StyledTab label={tabs[1]}/> + <StyledTab label={tabs[2]}/> + </StyledTabs> + </ConfiguracoesMenu> + </Paper> + </Grid> + <TabContentDiv item xs={9}> + <Paper elevation={3} style= {{width:"100%"}}> + {tabValue === 0 && <TabPanelEditarPerfil />} + {tabValue === 1 && <TabPanelSolicitarContaProfessor/>} + </Paper> + {tabValue === 2 && <TabPanelGerenciarConta handleSnackbar={() => {handleSnackbar(true)}}/>} + </TabContentDiv> + </MainContainerDiv> + </div> + </div> + ) +} + +const TabContentDiv = styled(Grid)` + width : auto; + + .card-config { + padding : 40px; + margin : 20px 0 20px 10px; + border-radius : 3px; + box-shadow : 0 0 5px 0rgba(0,0,0,.25); + background-color : #fff; + text-align : start; + margin-left : auto; + margin-right : auto; + display : flex; + flex-direction : column; + } + + .content-div { + display : flex; + flex-direction : column; + align-content : stretch; + align-items : stretch; + font-family : 'Roboto', sans serif !important; + font-size : 14px; + justify-content : center; + line-height : 20px; + text-align : center; + color : #666; + } + + .h2 { + margin-top : 20px; + margin-bottom : 10px; + } + + .p { + margin : 0 0 10px; + } + + .h1 { + font-size : 30px; + font-weight : 300; + margin-top : 0; + margin-bottom : 10px; + } + + .h4 { + font-size : 18px; + margin-top : 10px; + margin-bottom : 10px; + font-weight : 500; + line-height : 1.1; + } +` + +const StyledTabs = styled(Tabs)` + .Mui-selected { + background-color : #f4f4f4; + } +` + +const StyledTab = styled(Tab)` + &:hover { + background-color : #6666663d; + } +` + +const ConfiguracoesMenu = styled.div` + margin : 20px 0 20px 0; + border-radius : 3px; + padding : 20px 0; + background-color : #fff; + text-align : start; +` + +const MainContainerDiv = styled(Grid)` + padding : 0; + width : 1170; + margin-right : auto; + margin-left : auto; + display : flex; + flex-direction : row; + align-content : center; + justify-content : center; +` diff --git a/src/Pages/PageProfessor.js b/src/Pages/PageProfessor.js new file mode 100644 index 0000000000000000000000000000000000000000..e177ade2c058603df6cdbe7a5e2a1014bd057a10 --- /dev/null +++ b/src/Pages/PageProfessor.js @@ -0,0 +1,204 @@ +import React, {useState,useContext} from 'react' +import {Store} from '../Store.js' +import styled from 'styled-components' +import Paper from '@material-ui/core/Paper'; +import PartOne from '../Components/PageProfessorComponents/PartOne.js' +import PartTwo from '../Components/PageProfessorComponents/PartTwo.js' +import PartThree from '../Components/PageProfessorComponents/PartThree.js' +import SuccessfulRequest from '../Components/PageProfessorComponents/SuccessfulRequest.js' +import ModalConfirmarProfessor from '../Components/PageProfessorComponents/ModalConfirmarProfessor.js' +import axios from 'axios' +import {apiUrl} from '../env'; + +export default function PageProfessor (props) { + const {state, dispatch} = useContext(Store) + const [modalOpen, toggleModal] = useState(false) + const handleModal = () => { + toggleModal(!modalOpen) ; + } + + const redirect = () => { + props.history.push('/termos-publicar-recurso') + } + + const [registerInformation, setRegisterInformation] = useState( + { + teacher_cpf: '', + school_phone: '', + school_name: '', + school_city : '', + school_uf : { + abbreviation : '', + name : '' + }, + inep_code: '' + } + ) + + const [stepper, handleStepper] = useState( + [ {value : '1', selected : false}, {value : '2', selected : false}, {value : '3', selected : false}, {value : '4', selected : true}] + ) + const toggleStepper = (selected1, selected2, selected3, selected4) => { + handleStepper( + [ + {value : '1', selected : selected1}, + {value : '2', selected : selected2}, + {value : '3', selected : selected3}, + {value : '4', selected : selected4} + ] + ) + } + + const handleBuscarParteUm = (ufAbbreviation, ufName, nomeMunicipio, inep) => { + console.log('handleBuscarParteUm: ', ufAbbreviation, ufName, nomeMunicipio, inep) + setRegisterInformation({...registerInformation, + school_uf : { + abbreviation: (ufAbbreviation ? ufAbbreviation : ''), + name : (ufName ? ufName : '') + }, + school_city : (nomeMunicipio ? nomeMunicipio : ''), + inep_code : (inep ? inep : '') + }) + toggleStepper(false, true, false, false) + } + + const handleBuscarParteDois = (city_name, inep, school_name, state_name) => { + const uf_abbreviation = registerInformation.school_uf.abbreviation + const prev_state_name = registerInformation.school_uf.name + const prev_city_name = registerInformation.school_city.name + + setRegisterInformation({...registerInformation, + school_uf : { + abbreviation : uf_abbreviation, + name: (state_name ? state_name : prev_state_name) + }, + school_city :(city_name ? city_name : prev_city_name), + school_name: (school_name ? school_name : ''), + inep_code : (inep ? inep : '') + }) + toggleStepper(false, false, true, false) + } + + const handleParteTres = (phone, cpf) => { + setRegisterInformation({...registerInformation, + teacher_cpf: (phone ? phone : ''), + school_phone: (cpf ? cpf : ''), + }) + handleModal(); + } + + const handleCancelar = () => { + props.history.push('/perfil/atualizacoes') + } + + const handleFinalSubmit = () => { + //adicionar headers de accessToken + axios.post( `${apiUrl}/users/teacher_request`, { + city : registerInformation.school_city.name, + cpf : registerInformation.teacher_cpf, + inep_id : registerInformation.inep_code, + phone : registerInformation.school_phone, + school : registerInformation.school_name, + uf : registerInformation.school_uf.name + }, + { headers : { + 'Access-Token': sessionStorage.getItem('@portalmec/accessToken'), + 'Client': sessionStorage.getItem('@portalmec/clientToken'), + 'Uid': sessionStorage.getItem('@portalmec/uid') + }} + ) + .then( (response) => { + console.log(response.data) + }, (error) => console.log('deu erro') + ) + toggleStepper(false, false, false, true) + } + + return ( + <> + { + state.userAgreedToPublicationTerms? + ( + [ + <> + <ModalConfirmarProfessor open={modalOpen} handleClose={handleModal} + info={registerInformation} confirmar = {() => {handleFinalSubmit()}} + cancelar = {() => {toggleModal()}} + /> + <div style={{backgroundColor:"#f4f4f4", color:"#666"}}> + <div style={{display: "flex", justifyContent:"center", paddingTop:"5vh", paddingBottom:"5vh"}}> + <Paper elevation={3} style= {{width:"max-content"}}> + <div style={{paddingRight:"15px", paddingLeft:"15px"}}> + {stepper[0].selected && + <PartOne stepper={stepper} handleBuscar={handleBuscarParteUm} + handleCancelar={handleCancelar} + /> + } + {stepper[1].selected && + <PartTwo stepper={stepper} + info={registerInformation} goBack={toggleStepper} + handleCancelar={handleCancelar} handleBuscar={handleBuscarParteDois} + /> + } + {stepper[2].selected && + <PartThree stepper={stepper} goBack={toggleStepper} + handleCancelar={handleCancelar} info={registerInformation} + handleSubmit={handleParteTres} + /> + } + { + stepper[3].selected && + <SuccessfulRequest email={state.currentUser.email}/> + } + </div> + </Paper> + </div> + </div> + </> + ] + ) + : + ( + <> + {redirect()} + </> + ) + } + </> + ) +} + +const ContainerDiv = styled.div` + .card { + box-shadow : 0 0 5px 0 rgba(0,0,0,.25); + background-color :#fff; + text-align : start; + margin-left : auto; + margin-right : auto; + } + + .part-one { + max-width : 570px; + } + + .container { + padding-right : 15px; + padding-left : 15px; + } + + .content { + margin-top : 16px; + margin-bottom : 16px; + margin-right : 10%; + margin-left : 10%; + } + + h4 { + font-family : Roboto; + font-style : normal; + font-weight : 300; + line-height : 36px; + font-size : 26px; + margin-top : 20px; + } +` diff --git a/src/Pages/PasswordRecoveryPage.js b/src/Pages/PasswordRecoveryPage.js new file mode 100644 index 0000000000000000000000000000000000000000..981a14e47f44c1955ab57df4a6d713760a52e3d8 --- /dev/null +++ b/src/Pages/PasswordRecoveryPage.js @@ -0,0 +1,107 @@ +import React, {useState, useContext} from 'react' +import {HeaderDiv, BreadcrumbsDiv, StyledBreadcrumbs} from './UserPage.js' +import Breadcrumbs from '@material-ui/core/Breadcrumbs'; +import {Link} from 'react-router-dom' +import Paper from '@material-ui/core/Paper'; +import styled from 'styled-components' +import FormInput from "../Components/FormInput.js" +import ValidateUserInput from '../Components/FormValidationFunction.js' +import {CompletarCadastroButton} from '../Components/TabPanels/TabPanelSolicitarContaProfessor.js' +import Default from '../Components/PasswordRecoveryComponents/Default.js' +import Success from '../Components/PasswordRecoveryComponents/Success.js' +import {Store} from '../Store.js' +import Error from '../Components/PasswordRecoveryComponents/Error.js' + +export default function PasswordRecoveryPage (props) { + const {state, dispatch} = useContext(Store) + + const [formEmail, setEmail] = useState( + { + dict : { + key : false, + value : "" + } + } + ) + + const handleChange = (e) => { + const userInput = e.target.value + const flag = ValidateUserInput('email', userInput) + + setEmail({...formEmail, dict : { + key : flag, + value : userInput + }}) + console.log(formEmail) + } + + const [aux, setCase] = useState('default') + const handleChangeSwitch = (value) => setCase(value); + + const onSubmit = (e, email) => { + e.stopPropagation() + const query = email + + setEmail({...formEmail, dict : { + key : false, + value : '' + }}) + handleChangeSwitch('error') + } + + + const components = { + default : <Default handleChange={handleChange} onSubmit={onSubmit} value={formEmail.dict.value} error={formEmail.dict.key}/>, + success : <Success email={state.currentUser.email} changeSwitch={handleChangeSwitch}/>, + error : <Error email={state.currentUser.email} handleChange={handleChange} onSubmit={onSubmit} value={formEmail.dict.value} error={formEmail.dict.key}/> + } + + const switchFunction = (value) => { + switch(value) { + case 'success': + return components.success; + break; + case 'error': + return components.error; + break; + default: + return components.default + break; + + } + } + + return ( + <> + <HeaderDiv> + <div style={{minWidth:"1170px"}}> + <BreadcrumbsDiv> + <StyledBreadcrumbs> + <Link to="/" style={{color:"#00bcd4", textDecoration:"none"}}> + Página Inicial + </Link> + <span> + Recuperar senha + </span> + </StyledBreadcrumbs> + </BreadcrumbsDiv> + </div> + + <div style={{justifyContent:"center", textAlign:"center", maxWidth:"600px", margin:"auto"}}> + <Paper elevation={3}> + <CardDiv> + {switchFunction(aux)} + </CardDiv> + </Paper> + </div> + </HeaderDiv> + </> + ) +} + +const CardDiv = styled.div` + background-color : #fff; + box-shadow : 0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24); + padding : 30px 60px; + margin : 50px 0; +` diff --git a/src/Pages/TermsPage.js b/src/Pages/TermsPage.js index 65081cf7990a3c41dc15591dcefe2f3c44c546e4..e0b6dde2e54179074a63d3c4ab9e8e3bf81557ed 100644 --- a/src/Pages/TermsPage.js +++ b/src/Pages/TermsPage.js @@ -76,9 +76,12 @@ export default function TermsContainer (props) { userAgreement: true }) - props.history.push('/permission') - - window.scrollTo(0, 0) + if (props.location.state.redirectedFromModal) { + props.history.push('/professor') + }else { + props.history.push('/permission') + window.scrollTo(0, 0) + } } return ( diff --git a/src/Pages/UserPage.js b/src/Pages/UserPage.js index 8e5da3b43aafa195457578183449ca4f6f51ee76..420912ac87e511bb2c1c2dd0576d882053437518 100644 --- a/src/Pages/UserPage.js +++ b/src/Pages/UserPage.js @@ -16,32 +16,386 @@ 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, useEffect} from 'react'; import styled from 'styled-components' +import { Container } from 'react-grid-system' +import Button from '@material-ui/core/Button'; +import IconButton from '@material-ui/core/IconButton'; +import PhotoCamera from '@material-ui/icons/PhotoCamera'; +import Tooltip from '@material-ui/core/Tooltip'; +import Breadcrumbs from '@material-ui/core/Breadcrumbs'; +import {Link} from 'react-router-dom'; +import Popover from '@material-ui/core/Popover'; +import { Store } from '../Store.js'; +import EditIcon from '@material-ui/icons/Edit'; +import CheckDecagram from '../img/check-decagram-gray.svg' +import Tabs from '@material-ui/core/Tabs'; +import Tab from '@material-ui/core/Tab'; +import Paper from '@material-ui/core/Paper'; +import TabPanelAtividades from '../Components/TabPanels/TabPanelAtividades.js' +import TabPanelMeusRecursos from '../Components/TabPanels/TabPanelMeusRecursos.js' +import TabPanelFavoritos from '../Components/TabPanels/TabPanelFavoritos.js' +import TabPanelColecoes from '../Components/TabPanels/TabPanelColecoes.js' +import TabPanelRede from '../Components/TabPanels/TabPanelRede.js' +import axios from 'axios' +import {apiUrl} from '../env'; +import ModalAlterarAvatar from '../Components/ModalAlterarAvatar.js' +export default function UserPage (props){ + const {state, dispatch} = useContext(Store) + const [hoverAlterarFoto, handleAlterarFoto] = React.useState(false) + const [tabValue, setTabValue] = useState( + Number(props.location.state) || 0 + ); + const [tabs, setTabs] = useState([ + 'Atividades', 'Meus Recursos', 'Favoritos', 'Coleções', 'Rede' + ]) + const user = sessionStorage.getItem('@portalmec/username') + const id = sessionStorage.getItem('@portalmec/id') + const [modalOpen, handleModal] = useState(false) + + const config = { + headers : { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Access-Token': sessionStorage.getItem('@portalmec/accessToken'), + 'Client': sessionStorage.getItem('@portalmec/clientToken'), + 'Uid': sessionStorage.getItem('@portalmec/uid'), + 'Host': 'api.portalmec.c3sl.ufpr.br', + 'Cookie': '' + } + } + + const modalControl = () => { + handleModal(!modalOpen) + } + + const handleHoverAlterarFoto = () => { + handleAlterarFoto(!hoverAlterarFoto) + } + + useEffect( () => { + axios.get( (`${apiUrl}/users/` + id), { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Host': 'api.portalmec.c3sl.ufpr.br', + 'Cookie': '' + }) + .then( (response) => { + dispatch ({ + type : 'USER_ACCESSED_USER_PAGE', + set: { + id : response.data.id, + email : response.data.email, + username : response.data.name, + education : response.data.education, + userAvatar : response.data.avatar, + userCover : response.data.cover, + followCount : response.data.follow_count, + collectionsCount: response.data.collections_count, + } + }) + }, + (error) => { + console.log('error while running ComponentDidMout') + } + ) + }, []) + + const redirect = () => { + props.history.push('/') + } + + const handleChangeTab = (event, newValue) => { + setTabValue(newValue) + } + + const updateCover = (selectorFiles : FileList) => { + console.log(selectorFiles) + console.log(selectorFiles[0]) + } + + return ( + <> + <link href="https://fonts.googleapis.com/css?family=Roboto:100,400,500&display=swap" rel="stylesheet"/> + { + state.userIsLoggedIn? + ( + [ + <React.Fragment> + <ModalAlterarAvatar + open={modalOpen} + handleClose={modalControl} + /> + <HeaderDiv> + <ContainerNoPad> + <BreadcrumbsDiv> + <StyledBreadcrumbs> + <Link to="/" style={{color:"#00bcd4", textDecoration:"none"}}> + Página Inicial + </Link> + <span> + Minha área + </span> + <span> + {tabs[tabValue]} + </span> + </StyledBreadcrumbs> + </BreadcrumbsDiv> + + <div style={{display:"flex", flexDirection:"column"}}> + <MainContainerDesktop maxwidth="xl"> + <Paper elevation={3} style= {{width:"max-content"}}> + <ContainerUserProfile> + <HeaderContainer> + <CoverContainer> + <img src={state.currentUser.userCover} alt = "user cover avatar" style= {{width:"100%", height:"100%", objectFit : "cover" }}/> + <input accept="image/*" style = {{display:"none"}} id="icon-button-file" type="file" onChange={(e) => updateCover(e.target.files)}/> + <label htmlFor="icon-button-file"> + <Tooltip title={<span style={{fontSize:"14px", overflow:"hidden", transition:"all .5s ease"}}>ALTERAR CAPA</span>} placement="left"> + <IconButton style={{position:"absolute",right:"0",top:"0",color:"#fff"}}color="primary" aria-label="upload picture" component="span"> + <PhotoCamera /> + </IconButton> + </Tooltip> + </label> + </CoverContainer> + <ProfileAvatarDiv onMouseEnter={handleHoverAlterarFoto} onMouseLeave={handleHoverAlterarFoto} onClick={modalControl}> + <img src={state.currentUser.userAvatar} alt = "user avatar" style={{height : "inherit", width : "inherit", border:"0", verticalAlign:"middle"}}/> + <ChangeAvatarDiv style={ {display : hoverAlterarFoto ? 'flex' : 'none'}}> + <span>Alterar Foto</span> + </ChangeAvatarDiv> + </ProfileAvatarDiv> + <UserProfileInfoDiv> + <p style={{fontSize:"28px", color:"#fff", marginBottom:"2px", fontWeight:"500", backgroundColor:"#77777796", backgroundRadius : "8px"}}>{user}</p> + <div style={{fontSize:"14px", color:"#fff", marginBottom:"2px"}}> + <p>{state.currentUser.education}</p> + </div> + </UserProfileInfoDiv> + <EditProfileAnchor to="/editarperfil"> + <Button> + <EditIcon style={{marginRight:"5px", verticalAlign:"middle"}}/> <span>EDITAR PERFIL</span> + </Button> + </EditProfileAnchor> + </HeaderContainer> + <CheckTeacherDiv> + <> + { + state.currentUser.isCollaborativeTeacher ? + ( + [ + <> + <img src={CheckDecagram} style={{color:"#00bcd4"}}/> + <span>Professor(a)</span> + </> + ] + ) + : + ( + [ + <p style={{fontSize:"15px", lineHeight:"22px", textAlign:"left", margin:"0 0 10px"}}> + <span style={{cursor:"pointer"}}> + <span style={{paddingRight:"5px"}}> + <img src={CheckDecagram}/> + </span> + Você é professor(a) e gostaria de publicar recursos? + <span style={{color:"#00bcd4"}}> SAIBA MAIS</span> + </span> + </p> + ] + ) + } + </> + </CheckTeacherDiv> + <RodapeDiv> + <NavBarContentContainer> + <StyledTabs + value ={tabValue} + onChange ={handleChangeTab} + indicatorColor ="primary" + textColor ="primary" + variant = "scrollable" + scrollButtons = "auto" + TabIndicatorProps={{style : {background:"#00bcd4"}}} + > + <StyledTab label={tabs[0]}/> + <StyledTab label={tabs[1]}/> + <StyledTab label={tabs[2]}/> + <StyledTab label={tabs[3]}/> + <StyledTab label={tabs[4]}/> + </StyledTabs> + </NavBarContentContainer> + </RodapeDiv> + </ContainerUserProfile> + </Paper> + </MainContainerDesktop> + </div> + {tabValue === 0 && <TabPanelAtividades id={id} config={config}/>} + {tabValue === 1 && <TabPanelMeusRecursos id={id} config={config}/>} + {tabValue === 2 && <TabPanelFavoritos id={id} config={config}/>} + {tabValue === 3 && <TabPanelColecoes id={id} config={config}/>} + {tabValue === 4 && <TabPanelRede id={id} config={config}/>} + </ContainerNoPad> + </HeaderDiv> + </React.Fragment> + ] + ) + : ( + <> + {redirect()} + </> + ) + } + </> -const maindDiv = styled.div` + ) + + } + +export const HeaderDiv = styled.div` background-color : #f4f4f4; color : #666; font-size : 14px; line-height : 20px; + padding-bottom : 40px; +` + +const ContainerNoPad = styled.div` + min-width : 1170px; ` -const breadcrumbsDiv = styled.div` + +export const BreadcrumbsDiv = styled.div` + padding : 10px; + display : flex; + justify-content : center; + ` + +export const StyledBreadcrumbs = styled(Breadcrumbs)` display : flex; - justify:content : center; - padding: 10px; + justify-content : flex-start; + max-width : 1170px; + span { + color : #a5a5a5; + } ` -export default function UserPage (props){ +const MainContainerDesktop = styled(Container)` + padding : 10px 0 8px 0; + .MuiContainer-maxWidthXl { + max-width : 1170px !important; + } +` - return ( - <mainDiv> - <breadcrumbsDiv> - <ol style={{listStyle:"none"}}> - <li><a href="/"><span>Página Principal</span> </a> </li>/<li><span>Minha área</span></li>/<li><span>Atividades</span></li> - </ol> - </breadcrumbsDiv> - </mainDiv> - ); +const ContainerUserProfile = styled(Container)` + padding : 0; + background-color : #fff; + margin-bottom: 30px; + width : 1170px; + margin-right : auto; + padding-left : 0 !important; + padding-right : 0 !important; + margin-left : auto; +` +const HeaderContainer = styled(Container)` + background-color : #afeeee; + position : relative; +` + + const CoverContainer = styled(Container)` + height : 230px; + position : relative; +` + +const ProfileAvatarDiv = styled.div` + bottom : -65px; + left : 60px; + border-radius : 100%; + position : absolute; + width : 150px; + height : 150px; + overflow : hidden; + border : 8px solid #fff; + outline : 0; + cursor : pointer; +` + +export const ChangeAvatarDiv = styled.div` + height : 40px; + position: absolute; + width : 100%; + bottom : 0; + display : flex; + background-color : #000; + color : #fff; + justify-content : center; +` + +const UserProfileInfoDiv = styled.div` + position : absolute; + bottom : 0; + left : 260px; + overflow : hidden; + margin-bottom : 20px; +` +const EditProfileAnchor = styled(Link)` + Button { + box-shadow : 0 2px 5px 0 rgba(0,0,0,.26); + background-color : #fafafa; + position : absolute; + right : 5px; + bottom : 0; + margin-bottom : 20px; + color : #666; + padding : 0 10px; + text-decoration : none; + border-radius : 3px; + min-height : 36px; + min-width : 88px; + line-height : 36px; + border : 0; + display: inline-block; + text-align : center; + :hover{ + background-color : #fafafa; + } } +` + +const CheckTeacherDiv = styled.div` + font-size : 14px; + padding-top : 10px; + padding-left : 250px; + margin-bottom : -10px; + color : #666 !important; +` + +const RodapeDiv = styled.div` + justify-content : flex-end; + display : flex; +` + +const NavBarContentContainer = styled(Container)` + background-color : #fff; + padding-bottom : 0; + overflow-x : hidden !important; + overflow-y : hid1den !important; + margin-right : 0 !important; +` + +const StyledTabs = styled(Tabs)` + .MuiTab-textColorPrimary.Mui-selected { + color : #00bcd4 !important; + border-bottom-color : #00bcd4 !important; + } + .Mui-selected { + border-bottom-color : #00bcd4 !important; + } +` +const StyledTab = styled(Tab)` + .Mui-selected { + border-bottom-color : #00bcd4 !important; + } + .MuiTab-wrapper { + border-bottom-color : #00bcd4 !important; + } +` diff --git a/src/Pages/UserTerms.js b/src/Pages/UserTerms.js index 9e29e2b2400e9dac71121efa66b3b2cb20007446..4c9562b1141c286e14c1e79d7af40f43ca4c067f 100644 --- a/src/Pages/UserTerms.js +++ b/src/Pages/UserTerms.js @@ -212,7 +212,7 @@ class UserTerms extends Component { return ( <div style={{color:"rgba(0,0,0,0.87"}} > - <link href="https://fonts.googleapis.com/css?family=Kalam|Pompiere|Roboto&display=swap" rel="stylesheet"/> + <BannerStyle> <h2 style={{width: "100%",textAlign: "center",marginTop:"0px", paddingTop:"6rem",marginBottom:"16px",fontSize:"52px",fontFamily: "'Pompiere', cursive",color:"#fff",fontWeight:"500"}}>TERMOS DE USO</h2> diff --git a/src/Store.js b/src/Store.js index c2e0f669847b6a71faf2f77f73dd079e27a8ab24..d57a0cde937ebbd0457934f9f8964f1308e211b5 100644 --- a/src/Store.js +++ b/src/Store.js @@ -22,8 +22,8 @@ export const Store = React.createContext() const initialState = { searchOpen: false, - userIsLoggedIn : true, - userAgreedToPublicationTerms: false, + userIsLoggedIn : false, + userAgreedToPublicationTerms: true, userAgreedToPublicationPermissions: false, modalColaborarPlataformaOpen : false, search: { @@ -34,11 +34,20 @@ const initialState = { width: 0, height: 0 }, - loginInfo: { - username : 'Horstmann', + currentUser: { + id : '', + username : '', email : '', accessToken : '', - client : '' + clientToken : '', + education : '', + isCollaborativeTeacher : false, + userAvatar : '', + userCover : '', + uid : '', + followCount : 0, + collectionsCount : 0, + submitter_request : 'default' } } @@ -63,19 +72,19 @@ function reducer(state, action) { return { ...state, userIsLoggedIn:action.userLoggedIn, - loginInfo:action.login + currentUser:action.login } case 'USER_SIGNED_UP': return { ...state, userIsLoggedIn:action.userLoggedIn, - loginInfo:action.login + currentUser:action.login } case 'USER_LOGGED_OUT': return { ...state, userIsLoggedIn:action.userLoggedOut, - loginInfo:action.login + currentUser:action.login } case 'USER_AGREED_TO_PUBLICATION_TERMS': return { @@ -87,6 +96,11 @@ function reducer(state, action) { ...state, userAgreedToPublicationPermissions : action.userAgreement } + case 'USER_ACCESSED_USER_PAGE': + return { + ...state, + currentUser : action.set + } default: return state } diff --git a/src/env.js b/src/env.js index f3072030af819b06ffeee3edf0daa783c35c524e..2450da0f16d3d4bfd1d340b927cc7d0838f510df 100644 --- a/src/env.js +++ b/src/env.js @@ -17,9 +17,14 @@ 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.portalmectest.c3sl.ufpr.br', apiVersion = 'v1', apiUrl = apiDomain + '/' + apiVersion; +var simcaqAPIDomain = 'https://www.simcaq.c3sl.ufpr.br/api', + apiVersion = 'v1', + simcaqAPIurl = simcaqAPIDomain + '/' + apiVersion + export {apiUrl}; export {apiDomain}; +export {simcaqAPIurl} diff --git a/src/img/Bolo.png b/src/img/Bolo.png new file mode 100644 index 0000000000000000000000000000000000000000..509d2acae8705430a4707bb88fc07bd04ae33999 Binary files /dev/null and b/src/img/Bolo.png differ diff --git a/src/img/Pagina_vazia_colecao.png b/src/img/Pagina_vazia_colecao.png new file mode 100644 index 0000000000000000000000000000000000000000..0dbf187a01d49f7df1d69780d18ceaf38f3c4efa Binary files /dev/null and b/src/img/Pagina_vazia_colecao.png differ diff --git a/src/img/check-decagram-gray.svg b/src/img/check-decagram-gray.svg new file mode 100644 index 0000000000000000000000000000000000000000..a2415acd16d87f63695aa51800458ade254c530c --- /dev/null +++ b/src/img/check-decagram-gray.svg @@ -0,0 +1,3 @@ +<svg width="22" height="21" viewBox="0 0 22 21" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M22 10.46L19.56 7.68L19.9 4L16.29 3.18L14.4 0L11 1.46L7.6 0L5.71 3.18L2.1 3.99L2.44 7.67L0 10.46L2.44 13.24L2.1 16.93L5.71 17.75L7.6 20.93L11 19.46L14.4 20.92L16.29 17.74L19.9 16.92L19.56 13.24L22 10.46ZM9 15.46L5 11.46L6.41 10.05L9 12.63L15.59 6.04L17 7.46L9 15.46Z" fill="#D1D1D1"/> +</svg> diff --git a/src/img/comentarios.png b/src/img/comentarios.png new file mode 100644 index 0000000000000000000000000000000000000000..8427d16029a99af4896d1d1ea0b16c7a76f88450 Binary files /dev/null and b/src/img/comentarios.png differ diff --git a/src/img/horstmann.jpg b/src/img/horstmann.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a4e7e494f1615ddd3e2a650a2fc7099c8e4b3c1a Binary files /dev/null and b/src/img/horstmann.jpg differ diff --git a/src/img/loading_busca.gif b/src/img/loading_busca.gif new file mode 100644 index 0000000000000000000000000000000000000000..3ce6d59693025fbd428c063f7f565a858c20d4db Binary files /dev/null and b/src/img/loading_busca.gif differ diff --git a/src/img/logo_google.svg b/src/img/logo_google.svg new file mode 100644 index 0000000000000000000000000000000000000000..a939ddc19ab24537dcd45e107724c7f55431a89a --- /dev/null +++ b/src/img/logo_google.svg @@ -0,0 +1 @@ +<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><defs><style>.cls-1{fill:#4285f4;}.cls-2{fill:#34a853;}.cls-3{fill:#fbbc05;}.cls-4{fill:#ea4335;}.cls-5{fill:none;}</style></defs><title>btn_google_dark_normal_ios</title><g id="Google-Button"><g id="btn_google_dark_normal" data-name="btn google dark normal"><g id="logo_googleg_48dp" data-name="logo googleg 48dp"><path id="Shape" class="cls-1" d="M18.64,10.2a10.341,10.341,0,0,0-.164-1.841H10v3.481h4.844a4.14,4.14,0,0,1-1.8,2.716V16.82h2.909A8.777,8.777,0,0,0,18.64,10.2h0Z" transform="translate(-1 -1)"/><path id="Shape-2" data-name="Shape" class="cls-2" d="M10,19a8.592,8.592,0,0,0,5.956-2.18l-2.909-2.258A5.43,5.43,0,0,1,4.964,11.71H1.957v2.332A9,9,0,0,0,10,19h0Z" transform="translate(-1 -1)"/><path id="Shape-3" data-name="Shape" class="cls-3" d="M4.964,11.71a5.321,5.321,0,0,1,0-3.42V5.958H1.957a9.011,9.011,0,0,0,0,8.084L4.964,11.71h0Z" transform="translate(-1 -1)"/><path id="Shape-4" data-name="Shape" class="cls-4" d="M10,4.58a4.862,4.862,0,0,1,3.44,1.346l2.581-2.581A8.649,8.649,0,0,0,10,1,9,9,0,0,0,1.957,5.958L4.964,8.29A5.364,5.364,0,0,1,10,4.58h0Z" transform="translate(-1 -1)"/><path id="Shape-5" data-name="Shape" class="cls-5" d="M1,1H19V19H1V1Z" transform="translate(-1 -1)"/></g></g></g></svg> \ No newline at end of file diff --git a/src/img/no-rede-1.png b/src/img/no-rede-1.png new file mode 100644 index 0000000000000000000000000000000000000000..7d4510823fa703462511b4b7f8f6643a2e72639f Binary files /dev/null and b/src/img/no-rede-1.png differ diff --git a/src/img/no-rede-2.png b/src/img/no-rede-2.png new file mode 100644 index 0000000000000000000000000000000000000000..c94c169f7caecd6763d628b87e752a45b1cd1d79 Binary files /dev/null and b/src/img/no-rede-2.png differ diff --git a/src/img/no-rede-3.png b/src/img/no-rede-3.png new file mode 100644 index 0000000000000000000000000000000000000000..58b934c3bc3ee2dfa597b5386d66434973fca2cf Binary files /dev/null and b/src/img/no-rede-3.png differ