diff --git a/README.md b/README.md index 8f61b6e..1362df8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://user-images.githubusercontent.com/43780137/158059050-481ffa30-e415-4156- As the name suggests, this project is a clone of a famous Q/A website for professional and enthusiast programmers built solely by me using a completely different stack. -This repo consists of the Frontend code of the project, the backend code is in __[Stackoverflow-Clone-Backend](https://github.com/Mayank0255/Stackoverflow-Clone-Backend)__ +This repo consists of the Frontend code of the project, the backend code is in __[Devcomm-Backend](https://github.com/Mayank0255/Stackoverflow-Clone-Backend)__ ## My Tech Stack (MERN) @@ -38,8 +38,8 @@ There are two ways to setup the project: manually or using the Dockerfile. Read 1. Open your local CLI - ``` - mkdir Stackoverflow-Clone - cd Stackoverflow-Clone + mkdir Devcomm + cd Devcomm ``` 2. Setup the backend code - @@ -65,7 +65,7 @@ There are two ways to setup the project: manually or using the Dockerfile. Read - Run the index `npm start`. -3. Open a new CLI terminal and goto the root `Stackoverflow-Clone` folder you created in the first step. +3. Open a new CLI terminal and goto the root `Devcomm` folder you created in the first step. 4. Setup the Frontend code - - Clone the code & install the modules- diff --git a/package.json b/package.json index 455ecf2..9e3cc9e 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,10 @@ "dependencies": { "@emotion/react": "^11.8.1", "@emotion/styled": "^11.8.1", + "@fortawesome/fontawesome-svg-core": "^6.2.0", + "@fortawesome/free-regular-svg-icons": "^6.2.0", + "@fortawesome/free-solid-svg-icons": "^6.2.0", + "@fortawesome/react-fontawesome": "^0.2.0", "@mui/icons-material": "^5.5.0", "@mui/material": "^5.5.0", "@stackoverflow/stacks-icons": "^2.25.1", diff --git a/public/IconLogo.svg b/public/IconLogo.svg new file mode 100644 index 0000000..f0efc5e --- /dev/null +++ b/public/IconLogo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/index.html b/public/index.html index 493325b..7be6622 100644 --- a/public/index.html +++ b/public/index.html @@ -2,7 +2,7 @@ - + - CLONE Stack Overflow - Where Developers Learn, Share, & Build Careers + Devcomm - Where Developers Learn, Share, & Build Careers { return ( -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; diff --git a/src/Router.jsx b/src/Router.jsx index 37adc7a..01f017c 100644 --- a/src/Router.jsx +++ b/src/Router.jsx @@ -1,28 +1,17 @@ import React from 'react'; import { Route } from 'react-router-dom'; -import LayoutWrapper from './components/organisms/LayoutWrapper/LayoutWrapper.component'; +import RightSideBar from './components/organisms/RightSideBar/RightSideBar.component'; import usePageTitle from './hooks/usePageTitle'; -export const LayoutRoute = ({ title, children, ...props }) => { - usePageTitle(title); - - return ( - - - {children} - - - ) -} - -export const BaseRoute = ({ title, children, ...props }) => { +export const PrivateRoute = ({ title, withRightSideBar = true, children, ...props }) => { usePageTitle(title); return ( {children} + {withRightSideBar && } ) } diff --git a/src/assets/IconLogo.svg b/src/assets/IconLogo.svg new file mode 100644 index 0000000..f0efc5e --- /dev/null +++ b/src/assets/IconLogo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/TextLogo.svg b/src/assets/TextLogo.svg new file mode 100644 index 0000000..db36cd0 --- /dev/null +++ b/src/assets/TextLogo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/PageTitle/PageTitle.component.jsx b/src/components/PageTitle/PageTitle.component.jsx index 2ff7475..9f8d977 100644 --- a/src/components/PageTitle/PageTitle.component.jsx +++ b/src/components/PageTitle/PageTitle.component.jsx @@ -3,7 +3,7 @@ import Helmet from 'react-helmet'; const PageTitle = ({title}) => { let defaultTitle = - 'CLONE Stack Overflow - Where Developers Learn, Share, & Build Careers'; + 'Devcomm - Where Developers Learn, Share, & Build Careers'; return ( diff --git a/src/components/atoms/box.atom.jsx b/src/components/atoms/box.atom.jsx index 2226bf2..685ccd1 100644 --- a/src/components/atoms/box.atom.jsx +++ b/src/components/atoms/box.atom.jsx @@ -8,6 +8,7 @@ import { typography, border, background, + shadow, } from 'styled-system'; export const Box = styled.div` @@ -21,6 +22,9 @@ export const Box = styled.div` ${typography} ${border} ${background} + ${shadow} + transform: ${({ transform = 'none' }) => transform}; + visibility: ${({ visibility = 'visible' }) => visibility}; `; export const FlexBox = styled(Box)` diff --git a/src/components/atoms/circle.atom.jsx b/src/components/atoms/circle.atom.jsx new file mode 100644 index 0000000..7f0be0c --- /dev/null +++ b/src/components/atoms/circle.atom.jsx @@ -0,0 +1,15 @@ +import { Box } from './box.atom'; +import styled from '@emotion/styled'; + +const Circle = styled(Box)` + display: flex; + align-items: center; + justify-content: center; + height: ${({ radius = '5px' }) => `calc(${radius} * 2)`}; + width: ${({ radius = '5px' }) => `calc(${radius} * 2)`}; + border-radius: 50%; + border: ${({ border = '0' }) => border}; + cursor: ${({ cursor = 'pointer' }) => cursor}; +`; + +export default Circle; diff --git a/src/components/atoms/icon.atom.jsx b/src/components/atoms/icon.atom.jsx new file mode 100644 index 0000000..c9a1701 --- /dev/null +++ b/src/components/atoms/icon.atom.jsx @@ -0,0 +1,24 @@ +import styled from '@emotion/styled'; +import { + space, + color, + layout, + position, + typography, + textAlign, +} from 'styled-system'; + +const Icon = styled.span` + font-family: 'Wasabi'; + &:before { + content: ${({ unicode }) => `'\\${unicode}'`}; + } + ${space} + ${color} + ${layout} + ${position} + ${typography} + ${textAlign} +`; + +export default Icon; diff --git a/src/components/atoms/image.atom.jsx b/src/components/atoms/image.atom.jsx new file mode 100644 index 0000000..9463f56 --- /dev/null +++ b/src/components/atoms/image.atom.jsx @@ -0,0 +1,24 @@ +import styled from '@emotion/styled'; +import { + space, + color, + layout, + flexbox, + position, + typography, + border, + background, + shadow, +} from 'styled-system'; + +export const Image = styled.img` + ${space} + ${color} + ${layout} + ${flexbox} + ${position} + ${typography} + ${border} + ${background} + ${shadow} +` \ No newline at end of file diff --git a/src/components/atoms/link.atom.jsx b/src/components/atoms/link.atom.jsx new file mode 100644 index 0000000..47b1f76 --- /dev/null +++ b/src/components/atoms/link.atom.jsx @@ -0,0 +1,26 @@ +import styled from '@emotion/styled'; +import { + space, + color, + layout, + flexbox, + position, + typography, + border, + background, + shadow, +} from 'styled-system'; + +import {Link} from 'react-router-dom'; + +export const CustomLink = styled(Link)` + ${space} + ${color} + ${layout} + ${flexbox} + ${position} + ${typography} + ${border} + ${background} + ${shadow} +` \ No newline at end of file diff --git a/src/components/molecules/Search/SearchBox.component.jsx b/src/components/molecules/Search/SearchBox.component.jsx new file mode 100644 index 0000000..22decdb --- /dev/null +++ b/src/components/molecules/Search/SearchBox.component.jsx @@ -0,0 +1,40 @@ +import React from 'react'; + +import { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' + +import { FlexBox } from '../../atoms/box.atom'; +import { blue } from '../../../themes'; + +import { SearchInput } from './styles'; + +const SearchBox = ({ + formBg = `${blue._50}26`, + value, + handleSubmit, + ...props +}) => { + return ( + + + + + ) +}; + +export default SearchBox; diff --git a/src/components/molecules/Search/SearchForm.component.jsx b/src/components/molecules/Search/SearchForm.component.jsx new file mode 100644 index 0000000..d27d6ac --- /dev/null +++ b/src/components/molecules/Search/SearchForm.component.jsx @@ -0,0 +1,16 @@ +import React from 'react'; + +import SearchBox from './SearchBox.component'; + +const SearchForm = ({ handleSubmit = () => {}, ...props }) => { + return ( +
+ + + ) +} + +export default SearchForm; \ No newline at end of file diff --git a/src/components/molecules/Search/styles.js b/src/components/molecules/Search/styles.js new file mode 100644 index 0000000..04412ab --- /dev/null +++ b/src/components/molecules/Search/styles.js @@ -0,0 +1,12 @@ +import styled from '@emotion/styled'; + +import { blue } from '../../../themes'; + +export const SearchInput = styled.input` + background: ${({ bg = 'transparent' }) => bg} !important; + border: ${({ border = 'transparent' }) => border} !important; + box-shadow: ${({ boxShadow = 'none' }) => boxShadow} !important; + color: ${({ color = blue._50 }) => color} !important; + width: ${({ width = '100%' }) => width} !important; + font-weight: ${({ fontWeight = 500 }) => fontWeight} !important; +` \ No newline at end of file diff --git a/src/components/molecules/SearchBox/SearchBox.component.jsx b/src/components/molecules/SearchBox/SearchBox.component.jsx deleted file mode 100644 index d2480d4..0000000 --- a/src/components/molecules/SearchBox/SearchBox.component.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import React, {Fragment} from 'react'; -import {ReactComponent as Search} from '../../../assets/Search.svg'; - -const SearchBox = ({ - placeholder, - value, - name, - handleSubmit, - handleChange, - pt, - px, - width, -}) => { - return ( - - - - ); -}; - -export default SearchBox; diff --git a/src/components/molecules/SearchBox/SearchBox.styles.scss b/src/components/molecules/SearchBox/SearchBox.styles.scss deleted file mode 100644 index 945b8ce..0000000 --- a/src/components/molecules/SearchBox/SearchBox.styles.scss +++ /dev/null @@ -1,11 +0,0 @@ -.search-frame { - width: 220px; - //float: right; -} - -.search-box:focus { - border-color: #2b5f8a; - box-shadow: 0 0 0 4px #378ad326; - color: #fff; - outline: 0; -} \ No newline at end of file diff --git a/src/components/organisms/AuthForm/AuthForm.styles.scss b/src/components/organisms/AuthForm/AuthForm.styles.scss index c477f18..2cde21e 100644 --- a/src/components/organisms/AuthForm/AuthForm.styles.scss +++ b/src/components/organisms/AuthForm/AuthForm.styles.scss @@ -5,7 +5,7 @@ margin-left: auto; margin-right: auto; margin-bottom: 24px; - background-color: #2d2d2d; + background-color: #2548A7; border-radius: 7px; box-sizing: inherit; display: block; diff --git a/src/components/organisms/Footer/Footer.component.jsx b/src/components/organisms/Footer/Footer.component.jsx deleted file mode 100644 index 39d4463..0000000 --- a/src/components/organisms/Footer/Footer.component.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import React, { Fragment } from "react"; - -import {ReactComponent as GitHub} from "../../../assets/GitHub.svg"; -import {ReactComponent as Database} from "../../../assets/Database.svg"; - -import './Footer.styles.scss'; - -const Footer = () => { - return -
-
-
- - - -

Frontend

-
-
- - - -

Backend

-
-
-
-
-}; - -export default Footer; \ No newline at end of file diff --git a/src/components/organisms/Footer/Footer.styles.scss b/src/components/organisms/Footer/Footer.styles.scss deleted file mode 100644 index 29d84a2..0000000 --- a/src/components/organisms/Footer/Footer.styles.scss +++ /dev/null @@ -1,19 +0,0 @@ -.footer { - height: 300px; - display: flex; - justify-content: center; - padding-top: 32px; - background-color: #232629; - - .socials { - display: flex; - justify-content: space-between; - width: 120px; - - .social-item { - display: flex; - flex-direction: column; - align-items: center; - } - } -} \ No newline at end of file diff --git a/src/components/organisms/Header/Header.component.jsx b/src/components/organisms/Header/Header.component.jsx index ee7bbcd..2a68a70 100644 --- a/src/components/organisms/Header/Header.component.jsx +++ b/src/components/organisms/Header/Header.component.jsx @@ -1,34 +1,50 @@ -import React, {Fragment, useState} from 'react'; -import {Link, useHistory} from 'react-router-dom'; +import React from 'react'; +import { Link, useHistory } from 'react-router-dom'; import {connect} from 'react-redux'; import PropTypes from 'prop-types'; -import { logout } from '../../../redux/auth/auth.actions'; -import {ReactComponent as Search} from '../../../assets/Search.svg'; -import {ReactComponent as Logo} from '../../../assets/LogoMd.svg'; -import {ReactComponent as SmallLogo} from '../../../assets/LogoGlyphMd.svg'; import Spinner from '../../molecules/Spinner/Spinner.component'; import LinkButton from '../../molecules/LinkButton/LinkButton.component'; import MobileSideBar from '../../organisms/MobileSideBar/MobileSideBar.component'; +import { Box, FlexBox } from '../../atoms/box.atom'; +import SearchForm from '../../molecules/Search/SearchForm.component'; + +import { logout } from '../../../redux/auth/auth.actions'; + +import { Image } from '../../atoms/image.atom'; +import { CustomLink } from '../../atoms/link.atom'; +import IconLogo from '../../../assets/IconLogo.svg'; +import TextLogo from '../../../assets/TextLogo.svg'; +import { blue } from '../../../themes'; import './Header.styles.scss'; const Header = ({auth: {isAuthenticated, loading, user}, logout}) => { let history = useHistory(); - const [searchState, setSearchState] = useState(false); const authLinks = ( -
+ {loading || user === null ? ( ) : ( - - + user-logo - + )} { type={'s-btn__filled'} handleClick={logout} /> -
- ); - - const authTabs = ( -
- - Products - -
- ); - - const guestTabs = ( -
- - Products - - - Customers - - - Use cases - -
+ ); const guestLinks = ( -
+ -
+ ); - const SearchBar = () => { - return ( -
history.push('/questions')} - className='small-search-form' - autoComplete='off' + return !loading && ( + +
+ +
+ + + + + + + - + history.push('/questions')} /> - - - ); - } - - - return loading ? ( - '' - ) : ( - - - {searchState && } - + +
+ ); }; diff --git a/src/components/organisms/Header/Header.styles.scss b/src/components/organisms/Header/Header.styles.scss index 57b4843..9be3cd6 100644 --- a/src/components/organisms/Header/Header.styles.scss +++ b/src/components/organisms/Header/Header.styles.scss @@ -1,277 +1,12 @@ -.navbar { - height: 63px; - border-top: 3px solid #f48024; - padding: 3px 3px 0 0; - box-shadow: 5px 2px rgba(0,0,0,0.1); - z-index: 1000; - background-color: #3d3d3d; - display: flex; - justify-content: space-between; -} - -.fixed-top { - position: fixed; - top: 0; - right: 0; - left: 0; -} - -.s-navigation { - padding: 2px 2px; -} - -.s-navigation .not-selected { - color: #c4c8cc; - - &:hover { - background-color: #404345; - color: #f2f2f3; - text-decoration: none; - outline: none; - } -} - -* { - box-sizing: border-box; -} - -.navbar-brand { - margin-left: 90px; - padding-left: 16px; - padding-right: 16px; - margin-right: 0; - - &:hover { - background-color: #404345; - } -} - -.btns { - margin-right: 140px; - display: flex; - justify-content: center; - align-items: center; - - .logo { - width: 32px; - border-radius: 3px; - margin-right: 9px; - } -} - -.btn-sm { - padding: 5px 10px; -} - -.btn-outline-primary { - background-color: #e1ecf4; - color: #39739d; - border-color: #7aa7c7; -} - -.btn-outline-primary:hover { - color: #2c5777; - background-color: #b3d3ea; - border-color: #7aa7c7; -} - -.bar-items { - font-size: 14px; - color: rgba(0, 0, 0, 0.6); - margin: 0 10px; -} - -.px12 { - padding-left: 12px !important; - padding-right: 12px !important; -} - -.header-brand-div { - display: flex; - align-items: center; -} - -.header-search-div { - display: flex; - justify-content: flex-end; - align-items: center -} - -.glyph-logo { - display: none; -} - -.search-icon { - display: none; - filter: invert(1); - - &:hover { - cursor: pointer; - } -} - -.small-search { - width: 98vw; - position: fixed; - top: 69px; - left: 5px; - border-radius: 8px; -} - -.small-search-form { - position: fixed; - display: flex; - z-index: 1000; - padding: 2rem; - justify-content: center; - align-items: center; - width: 100vw; - background-color: #00000042; - box-shadow: 2px 2px 8px 3px gray; -} - -.small-search-icon { - position: fixed; - top: 80px; - right: 5%; -} - -.s-input__search{ - margin-top: 10px; -} -.s-input-icon { - margin-top: -2px; -} - // Side Navbar .hamburger { display: none; } -/////////////// - -@media(max-width: 1280px) { - .navbar-brand { - margin-left: 60px; - } -} - -@media(max-width: 1200px) { - .btns { - margin-right: 30px; - } -} - -@media (max-width:986px) { - .navbar-brand { - margin-left: 20px ; - } - .btns { - margin-right: 20px; - } -} - -@media (max-width: 877px){ - .navbar-brand { - margin-left: 0; - } - .header-brand-div { - justify-content: flex-start; - padding: 0 1.5rem; - } - .header-search-div { - justify-content: space-around; - } - .searchbar { - display: none; - } - .search-icon { - display: block; - margin-right: 1rem; - position: absolute; - left: 77%; - top: 30%; - } - - .btns { - margin-right: 20px; - } - .s-input__search { - max-width: 250px; - } -} - - -@media (max-width: 715px) { - .glyph-logo { - display: block; - } - .full-logo { - display: none; - } - .search-icon { - display: block; - position: relative; - left: 15%; - top: 30%; - } -} - @media (max-width: 560px) { - .glyph-logo { - display: block; - } - .full-logo { - display: none; - } - .s-navigation .s-navigation--item { - display: none; - - &:first-of-type { - display: inline; - } - } - .search-icon { - display: block; - position: relative; - left: 5%; - top: 30%; - } .hamburger { display: block; padding-top: 6px; } - .header-search-div, .header-brand-div { - transform: scale(0.8); - } -} - -@media (max-width: 420px) { - .glyph-logo{ - display: none; - } - .s-navigation .s-navigation--item { - &:first-of-type { - margin-left: -4.7rem; - } - } - .search-icon { - display: block; - position: relative; - left: 5%; - top: 30%; - } -} - -@media (max-width: 390px) { - .navbar { - padding: 0; - } -} - -@media (max-width: 345px) { - .glyph-logo { - display: none; - } } \ No newline at end of file diff --git a/src/components/organisms/LayoutWrapper/LayoutWrapper.component.jsx b/src/components/organisms/LayoutWrapper/LayoutWrapper.component.jsx deleted file mode 100644 index f560528..0000000 --- a/src/components/organisms/LayoutWrapper/LayoutWrapper.component.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React, {Fragment} from 'react'; - -import SideBar from './SideBar/SideBar.component'; -import RightSideBar from './RightSideBar/RightSideBar.component'; -import Footer from "../Footer/Footer.component"; - -const LayoutWrapper = ({ children }) => { - return ( - -
- -
- {children} - -
-
-