diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..7a3c0f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Figma Design** +Visualization of what needs to get created + +**Component Details** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..00fd0f2 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +# What did you implement/accomplish in this pull request +A clear and concise description of what you did and the changes that you are merging. + +# What are the issues that you completed +Link the issues that you completed/solved: +- #ISSUE_NUMBER (eg: #17) + +# Close Issues(Only fill this out if merging to master branch) +You can use the keyword 'close' and the issue number to close an issue automatically when the pull request is merged +- close #ISSUE_NUMBER (ex: "close #17") + +# Checklist +- [ ] Add staging tag to issues if the pull request is being merged into new-ui +- [ ] Remove staging tag from issues if pull request is being merged in to master diff --git a/src/App.js b/src/App.js index 429dd33..2b51cc7 100644 --- a/src/App.js +++ b/src/App.js @@ -10,6 +10,7 @@ import Learn from './components/Learn/Learn' import Explore from './components/Explore/Explore' import Module from './components/Student/Module/Module' import Activity from './components/Student/Activity/Activity' +import Article from './components/Article' import World from './components/Student/World/World' import NotFound from './components/Error/404NotFound' @@ -35,7 +36,8 @@ const App = () => { - + + diff --git a/src/components/Article.js b/src/components/Article.js new file mode 100644 index 0000000..3711748 --- /dev/null +++ b/src/components/Article.js @@ -0,0 +1,303 @@ +import React, { useEffect, useState } from 'react' +import styled from 'styled-components' +import { + fetchArticle, + fetchUser, + fetchUserArticles, + followUser, + unfollowUser, + fetchUserFollowers +} from '../services/ArticleService' +import Button from './shared/low/Button.js' +import Avatar from 'react-avatar' +const ReactMarkdown = require('react-markdown') + +const Container = styled.div` + margin: 4em; + display: flex; + font-family: Apercu Pro; +` +const ArticleBody = styled.div` + background: #ffffff; +` +const Image = styled.img` +height :400px; +width: 100%; +object-fit: cover +margin-bottom :1em;` + +const AvatarPlaceHolder = styled.div` + display: flex; + margin-left: ${props => (!props.user ? '1.5em' : '')}; + margin-top: ${props => (!props.user ? '0.5em' : '')}; + margin-bottom: ${props => (props.user ? '0.5em' : '')}; + margin-top: ${props => (props.user ? '0.5em' : '')}; +` + +const Tags = styled.div` + color: grey; + display: flex; + margin-left: ${props => (!props.user ? '2.5em' : '1em')}; + + margin-right: ${props => (!props.user ? '' : '1em')}; + width: ${props => (!props.user ? '' : '70%')}; + margin-top: ${props => (!props.user ? '' : '0.5em')}; + font-size: 15px; +` + +const Tag = styled.div` + margin-right: 1em; +` + +const ContentHolder = styled.div` + margin-left: 2em; + margin-right: 2em; +` +const Title = styled.div` + font-weight: bold; + margin-left: 1em; + margin-top: 0.5em; + font-size: ${props => (!props.user ? '36px' : '16px')}; + margin-right: 1em; +` + +const AvatarName = styled.div` +margin-top: ${props => (!props.user ? '0.8em' : '0.4em')}; +margin-left: 0.5em; +margin-right: 0.5em +font-size: ${props => (props.user ? '13px' : '20px')}; +font-weight: 600; +font-family: Apercu Pro; +color: ${props => (!props.user ? '#707070' : '')}; +` +const UserInfo = styled.div` + padding: 2em; + margin-left: 2em; + + background: #ffffff; +` +const UserData = styled.div` + font-family: Apercu Pro; + font-style: normal; + font-weight: 600; + font-size: 12px; + color: #000000; +` +const UserBio = styled.div` + font-family: Apercu Pro; + font-style: normal; + font-size: 12px; + color: #000000; +` +const UserTitle = styled.div` +margin-top : 1em +font-family: Apercu Pro; +font-style: normal; +font-weight: 500; +font-size: 10px; +color: rgba(0, 0, 0, 0.5); +` + +const AvatarGitHubUserName = styled.div` +margin-right: 0.5em +font-size: 12px; +font-weight: normal; +` + +const ButtonContainer = styled.div` + font-family: Open Sans; + font-style: normal; + font-weight: normal; + font-size: 10px; + line-height: 14px; +` +const StyledButton = styled(Button)` + margin: 1em 0 0 0; + font-family: Open Sans; + font-style: normal; + font-weight: normal; + font-size: 12px; + line-height: 14px; + background-color: ${props => props.color}; + width: 100%; + border-radius: 7px; + font-weight: bold; +` + +const UserArticles = styled.div` + margin: 2em 0 0 2em; + background: #ffffff; + padding: 1em; +` +const UserArticlesContainer = styled.div`` +const User = styled.div` + width: 49em; +` + +const AvatarUserDisplay = styled.div` + display: flex; +` + +const Article = props => { + const [results, setResults] = useState('') + const [userData, setUserData] = useState('') + const [userArticles, setUserArtciles] = useState('') + const [isUserFollowing, setUserFollowing] = useState(false) + const id = props.match.params.id + + useEffect(() => { + async function getData() { + if (results.length == 0) { + setResults(await fetchArticle(id)) + setUserData(await fetchUser(id)) + setUserArtciles(await fetchUserArticles(id)) + } + var data = await fetchUserFollowers(id) + var flag = false + if (data != null) { + for (var follower of data.followers) { + if (follower.id == id) { + flag = true + + break + } + } + if (flag) setUserFollowing(true) + else setUserFollowing(false) + } + } + getData() + }) + + var i = 0 + var cardItem = [] + + if (results != null) { + if (results['tags'] != null) { + for (i = 0; i < results.tags.length; i++) { + cardItem.push(#{results.tags[i].name}) + } + } + } + + var mainArticles = [] + if (userArticles != null) { + if (userArticles['articles'] != null) { + i = 0 + for (i = 0; i < userArticles.articles.length; i++) { + var userArticlesMain = [] + + userArticlesMain.push( + {userArticles.articles[i].title} + ) + var userArticlesTag = [] + if (userArticles.articles[i]['tags'] != null) { + var j = 0 + for (j = 0; j < userArticles.articles[i]['tags'].length; j++) { + userArticlesTag.push('#') + userArticlesTag.push(userArticles.articles[i].tags[j].name) + userArticlesTag.push('\t ') + } + userArticlesMain.push( + + {userArticlesTag}{' '} + {' '} + + ) + + mainArticles.push({userArticlesMain}) + } + } + } + } + + var text = '' + var color = '' + + if (isUserFollowing) { + text = 'Following' + color = '#4EC700;' + } else { + text = ' + Follow' + color = '#007BED;' + } + + return ( + + + + {cardItem} + {results.title} + + + {userData.name} + + + + + + + + + + + {userData.name} + + {' '} + @{userData.github_username}{' '} + + + + {userData.bio} + Location + {userData.location} + Occupation + {userData.occupation} + Joined + {userData.day_joined} + + { + async function getUserFollow() { + if (isUserFollowing == true) { + await unfollowUser(id) + setUserFollowing(false) + } else { + await followUser(id) + + setUserFollowing(true) + } + } + getUserFollow() + }} + > + {' '} + {text}{' '} + + + + + {mainArticles} + + + ) +} + +export default Article diff --git a/src/components/shared/high/RoadMap.js b/src/components/shared/high/RoadMap.js new file mode 100644 index 0000000..51aac17 --- /dev/null +++ b/src/components/shared/high/RoadMap.js @@ -0,0 +1,267 @@ +import React from 'react'; +import styled from 'styled-components'; +import Button from '../low/Button.js'; +import { Icon } from "@chakra-ui/core"; + +const Container = styled.div` +background-color : ${props => props.color}; +padding : 2em; +min-width: 331px; +max-height: 307px; +height: fit-content; +` +const InvertCon = styled.div` +display :flex; +justify-content: center; +` + +const Line1 = styled.div ` + +width: ${props => (props.invert ? '12%' : '26%')}; +height: 0px; +opacity: ${props => (props.invert ? '0.33' :'0.2')}; +border: ${props => (!props.invert ? ' 2px solid #007BED' :'2px dashed #007BED')}; +transform: ${props => (props.invert ? 'rotate(-34deg)' : 'rotate(-160deg)')}; + +margin-left: ${props => (props.invert ? '-3%' : '43%')}; +margin-top: ${props => (props.invert ? '15%' : '')}; +margin-right: ${props => (props.invert ?'-2%' : '')}; + + +` +const Line2 = styled.div ` + +width: ${props => (props.invert ? '16%' : '35%')}; +height: 0px; +opacity: ${props => (props.invert ? '0.33' :'0.5')}; +border: ${props => (props.invert ? ' 2px dashed #007BED' :'2px solid #007BED')}; +transform: ${props => (props.invert ? 'rotate(69deg)' : 'rotate(-12.47deg)')}; + +margin-left: ${props => (props.invert ? '-11%' : '34%')}; +margin-top: ${props => (props.invert ? '24%' : '')}; +margin-right: ${props => (props.invert ?'-12%' : '')}; + +` +const Line3 = styled.div ` + +width: ${props => (props.invert ? '20%' : '20%')}; +height: 0px; +opacity: ${props => (props.invert ? '0.33' :'0.8')}; +border: ${props => (props.invert ? ' 2px dashed #007BED' :'2px solid #007BED')}; +transform: ${props => (props.invert ? 'rotate(-42deg)' : 'rotate(-159.44deg)')}; +margin-left: ${props => (props.invert ? '-3%' : '34%')}; +margin-top: ${props => (props.invert ? '28%' : '')}; +margin-right: ${props => (props.invert ? '-4%' : '')}; + + + +` +const CardText = styled.div` + +font-family: Open Sans; +font-style: normal; +font-weight: bold; +font-size: 16px; +line-height: 18px; +color: ${props => props.fontColor}; +text-align: center; +margin :1em; +` +const CardText1 = styled.div` + +text-align: center; +margin :1em; +color: ${props => props.fontColor}; +font-family: Open Sans; +font-style: normal; +font-weight: normal; +font-size: 10px; +line-height: 14px; + +` +const ButtonContainer = styled.div` + +text-align: center; +margin :1em; +font-family: Open Sans; +font-style: normal; +font-weight: normal; +font-size: 10px; +line-height: 14px; + +` +const StyledButton = styled(Button)` + text-align: center; +margin :1em; +font-family: Open Sans; +font-style: normal; +font-weight: normal; +font-size: 10px; +line-height: 14px; +background-color: #007BED; +width: 130px; +border-radius: 7px; +` +const Icon1 = styled.div` +width: 25.74px; +height: 25px; +width: ${props => (props.invert ? '41.18px ': '25.74px')}; +height : ${props => (props.invert ? '40px' : '25px')}; +background: #FFFFFF; +box-shadow: 0px 4px 25px rgba(0, 0, 0, 0.15); +border-radius: 30px; +margin-left: ${props => (props.invert ? '' : '35%')}; +margin-top: ${props => (props.invert ? '10%' : '')}; + +` +const Icon2 = styled.div` +width: ${props => (props.invert ? '41.18px ': '30.88px')}; +height : ${props => (props.invert ?'40px ' : '30px')}; +background: #FFFFFF; +box-shadow: 0px 4px 25px rgba(0, 0, 0, 0.15); +border-radius: 30px; +margin-left: ${props => (props.invert ? '' : '68%')}; +margin-top: ${props => (props.invert ? '33%' : '')}; + +` +const Icon3 = styled.div` +width: ${props => (props.invert ? '41.18px ': '36.03px')}; +height : ${props => (props.invert ? '40px' : '35px')}; + +background: #FFFFFF; +box-shadow: 0px 4px 25px rgba(0, 0, 0, 0.15); +border-radius: 30px; +margin-left: ${props => (props.invert ? '' : '22%')}; +margin-top: ${props => (props.invert ? '0%' : '')}; +` +const Icon4 = styled.div` + +width: 41.18px; +height: 40px; +left: 73px; +top: 80px; +background: #FFFFFF; +box-shadow: 0px 4px 25px rgba(0, 0, 0, 0.15); +border-radius: 30px; +margin-left: ${props => (props.invert ? '' : '52%')}; +margin-top: ${props => (props.invert ?'18%' : '')}; +` +const IconImg1 = styled.div` +width: 11.03px; +height: 14.71px; +font-family: Open Sans; +font-style: normal; +font-weight: normal; +font-size: 13px; +line-height: 18px; +text-transform: capitalize; +margin-left: 25%; +padding-top: 12%; +` +const IconImg4= styled.div` +width: 17.65px; +height: 23.53px; +font-family: Open Sans; +font-style: normal; +font-weight: normal; +font-size: 20px; +line-height: 27px; +text-transform: capitalize; + +color: #000000; +padding-top :22%; +padding-left : 24%; +` +const IconImg2= styled.div` +width: 13.24px; +height: 17.65px; + +font-family: Open Sans; +font-style: normal; +font-weight: normal; +font-size: 14px; +line-height: 19px; +text-align: center; +text-transform: capitalize; +margin-left: 25%; +padding-top: 12%; +color: #000000; +` +const IconImg3= styled.div` +width: 15.44px; +height: 20.59px; +left: 10px; +top: 59px; + +font-family: Open Sans; +font-style: normal; +font-weight: normal; +font-size: 17px; +line-height: 23px; +text-transform: capitalize; + +margin-left: 25%; +padding-top: 12%; +color: #000000; +` +const Icon5 = styled.span` +background-color: #007BED; +border-radius: 50%; +padding : 1.5%; +width : 40px; +height : 40px; +margin-left : 2%; + +` + +const RoadMap = ({ + onClick, + invert, + invertColor + }) => { + var fontColor; + var color ; + if(invertColor){ + fontColor = "black" + color = "white" + }else { + fontColor = "white" + color = "#00498C" + } + if( !invert ){ + return ( + + 🐱 + + 💃 + + 🤟 + + 🎉 + Javascript Roadmap + Explore your skills + ) + }else { + return ( + + + 🎉 + + 🤟 + + + 💃 + + + 🐱 + + Learning Roadmap + + Explore Modules + + ) + } + +} + +export default RoadMap; \ No newline at end of file diff --git a/src/services/ArticleService.js b/src/services/ArticleService.js new file mode 100644 index 0000000..79c742f --- /dev/null +++ b/src/services/ArticleService.js @@ -0,0 +1,51 @@ +import { backend } from './AxiosInstances' +/** + * GET request for getting articleID data + * @param {String} articleId + */ +export const fetchArticle = async articleId => { + var response = await fetch( + 'https://e8cf77b9-33b9-46c4-b7e5-f79e62e478e8.mock.pstmn.io/articles/' + + articleId + ) + return await response.json() +} +export const fetchUser = async articleId => { + var response1 = await fetch( + 'https://e8cf77b9-33b9-46c4-b7e5-f79e62e478e8.mock.pstmn.io/users/' + + articleId + ) + + return await response1.json() +} +export const fetchUserArticles = async articleId => { + var response2 = await fetch( + 'https://e8cf77b9-33b9-46c4-b7e5-f79e62e478e8.mock.pstmn.io/articles/' + + articleId + + '/articles' + ) + return await response2.json() +} + +export const unfollowUser = async user => { + var response2 = await fetch( + 'https://e8cf77b9-33b9-46c4-b7e5-f79e62e478e8.mock.pstmn.io/followers/users/' + + user, + { method: 'DELETE' } + ) + return await response2.json() +} +export const followUser = async user => { + var response2 = await fetch( + 'https://e8cf77b9-33b9-46c4-b7e5-f79e62e478e8.mock.pstmn.io/followers/users/' + + user, + { method: 'PUT' } + ) + return await response2.json() +} +export const fetchUserFollowers = async user => { + var response2 = await fetch( + 'https://e8cf77b9-33b9-46c4-b7e5-f79e62e478e8.mock.pstmn.io/followers/users/' + ) + return await response2.json() +}