From 54f4b3856384aeeff837796a0e81d966cc578c6f Mon Sep 17 00:00:00 2001 From: Dipak Acharya Date: Sat, 30 Jan 2021 20:49:25 +0545 Subject: [PATCH] wip --- frontend/package.json | 3 + frontend/src/App.tsx | 67 +++++--- frontend/src/Post.tsx | 105 +++++++----- frontend/src/Posts.tsx | 8 +- frontend/src/helpers/date.tsx | 28 ++++ frontend/src/styles/_base.scss | 77 +++++++++ frontend/src/styles/_list.scss | 159 +++++++++++++++++++ frontend/src/styles/_navigation.scss | 112 +++++++++++++ frontend/src/styles/_post.scss | 18 +++ frontend/src/styles/abstract/_mixins.scss | 45 ++++++ frontend/src/styles/abstract/_variables.scss | 57 +++++++ frontend/src/styles/main.scss | 51 +----- frontend/yarn.lock | 26 +++ 13 files changed, 651 insertions(+), 105 deletions(-) create mode 100644 frontend/src/styles/_base.scss create mode 100644 frontend/src/styles/_list.scss create mode 100644 frontend/src/styles/_navigation.scss create mode 100644 frontend/src/styles/_post.scss create mode 100644 frontend/src/styles/abstract/_mixins.scss create mode 100644 frontend/src/styles/abstract/_variables.scss diff --git a/frontend/package.json b/frontend/package.json index 1540b00..85b74c0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,9 @@ "@babel/core": "^7.11.6", "@babel/preset-env": "^7.11.5", "@babel/preset-react": "^7.10.4", + "@fortawesome/fontawesome-svg-core": "^1.2.32", + "@fortawesome/free-solid-svg-icons": "^5.15.1", + "@fortawesome/react-fontawesome": "^0.1.14", "@types/jest": "^26.0.20", "@types/node": "^14.14.20", "@types/react": "^17.0.0", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6f1c32e..3ad3efe 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -12,6 +12,9 @@ import Docs from './Docs'; import './styles/main.scss'; import { Tokens } from './types/types'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faSignOutAlt, faHome, faUser, faUserPlus } from '@fortawesome/free-solid-svg-icons' + export default function App() { const tokensString = window.localStorage.getItem('tokens'); @@ -44,30 +47,56 @@ export default function App() {
-

Zwitter

- {message &&

{message}

} +
+

ZWITTER

+
    + +
  • + +

    Home

    +
  • + + {loggedIn ? ( + <> + +
  • + +

    Profile

    +
  • + + + +
  • + +

    Logout

    +
  • + + + ) : ( + <> + +
  • + +

    Login

    +
  • + + +
  • + +

    Signup

    +
  • + + + )} +
+
+ {loggedIn && (

Logged in as @{tokens.user.username}

)} -
- Home - {loggedIn ? ( - <> - Profile - - {' '} - Logout{' '} - - - ) : ( - <> - Login - Signup - - )} - +
void] = React.useState(p); const [message, setMessage]: [string, (message: string) => void] = React.useState(''); const history = useHistory(); - + const [timeString, setTimeString]: [string, (timeString: string) => void] = React.useState(''); const [updateKey, updatePage]: [number, (updateKey: number) => void] = React.useState(0); React.useEffect(() => { setPost(p); + let formattedDate: string = timeSince(parseInt(post.created)) + " ago"; + setTimeString(formattedDate); }, []); + React.useEffect(() => { + console.log('rerender') + const timer=setTimeout(() => { + let formattedDate = timeSince(parseInt(post.created)) + " ago"; + + setTimeString(formattedDate); + }, 1000); + + // Clear timeout if the component is unmounted + return () => clearTimeout(timer); + }) + + const updateTimeAgo = function() { + const created: Date = new Date(parseInt(post.created) * 1000); + const formattedDate: string = timeSince(parseInt(post.created)) + " ago" + setTimeString(formattedDate) + } + const dateOptions: Intl.DateTimeFormatOptions = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric', }; - const created: Date = new Date(parseInt(post.created) * 1000); - const formattedDate: string = created.toLocaleTimeString('en-US', dateOptions); - + function getRezweet(rezweet) { if (Object.keys(rezweet).length === 0) { return; @@ -89,6 +111,10 @@ function Post({ post: p, tokens, level, loggedIn, clickable }: PostProps) { } function likePost(): Promise { + if (!loggedIn) { + history.push("/login") + return + } return httpPost(`/posts/${post.id}/like`, { headers: { token: tokens.token } }) .then((res) => res.json()) .then( @@ -106,7 +132,10 @@ function Post({ post: p, tokens, level, loggedIn, clickable }: PostProps) { ); } - function toggleReplyRezweet(type: PostReactTypes) { + function toggleReplyRezweet(type: PostReactTypes): void { + if (!loggedIn) { + return history.push("/login") + } if (type == PostReactTypes.REZWEET) { setReplyShown(false); setRezweetShown(!rezweetShown); @@ -139,40 +168,40 @@ function Post({ post: p, tokens, level, loggedIn, clickable }: PostProps) { }} className={clickable && 'post-section'} > - updatePage(updateKey + 1)} to={`/post/${post.id}`}> -

{post.text}

- {post.rezweet.id === '0' ? <> : getRezweet(post.rezweet)} - - @{post.author.username} +
+ updatePage(updateKey + 1)} to={`/post/${post.id}`}> +
{post.text}
+ + {post.rezweet.id === '0' ? <> : getRezweet(post.rezweet)} + + @{post.author.username} + +

{timeString}

+ {post.media && ( + <> + {post.text} +
+ + )} -

{formattedDate}

- {post.media && ( - <> - {post.text} -
- - )} - - {!loggedIn || ( - <> - - - - - )} -

Likes: {post.likes || 0}

+
+
toggleReplyRezweet(PostReactTypes.REPLY)}> + +
13k
+
+ +
toggleReplyRezweet(PostReactTypes.REZWEET)}> + +
20k
+
+ +
+ +
{post.likes || 0}
+
+
+
+ {!(replyShown || rezweetShown) || ( <>

{message}

diff --git a/frontend/src/Posts.tsx b/frontend/src/Posts.tsx index 2652a3e..217710f 100644 --- a/frontend/src/Posts.tsx +++ b/frontend/src/Posts.tsx @@ -90,9 +90,11 @@ function Posts(props: PostsProps) { )} - {posts.map((post) => ( - - ))} +
+ {posts.map((post) => ( + + ))} +
); } diff --git a/frontend/src/helpers/date.tsx b/frontend/src/helpers/date.tsx index bdc3dcc..9ffebb4 100644 --- a/frontend/src/helpers/date.tsx +++ b/frontend/src/helpers/date.tsx @@ -15,3 +15,31 @@ export function getDate(timeStamp: number): string { const currentDate = date.toISOString().slice(0, 10); return currentDate; } + +export function timeSince(date: number): string { + + var seconds = Math.floor((new Date()).getTime() / 1000) - date; + + var interval = seconds / 31536000; + + if (interval > 1) { + return Math.floor(interval) + " years"; + } + interval = seconds / 2592000; + if (interval > 1) { + return Math.floor(interval) + " months"; + } + interval = seconds / 86400; + if (interval > 1) { + return Math.floor(interval) + " days"; + } + interval = seconds / 3600; + if (interval > 1) { + return Math.floor(interval) + " hours"; + } + interval = seconds / 60; + if (interval > 1) { + return Math.floor(interval) + " minutes"; + } + return Math.floor(seconds) + " seconds"; +} \ No newline at end of file diff --git a/frontend/src/styles/_base.scss b/frontend/src/styles/_base.scss new file mode 100644 index 0000000..d5be761 --- /dev/null +++ b/frontend/src/styles/_base.scss @@ -0,0 +1,77 @@ + + *, + *::after, + *::before { + margin: 0; + padding: 0; + box-sizing: inherit; + } + + html { + } + + a { + text-decoration: none; + } + + body { + box-sizing: border-box; + background-color: $color-grey-light-1; + grid-area: body; + + font-family: sans-serif; + margin: 0; + padding: 0; + } + + .main { + height: 92vh; + overflow: scroll; + background-color: #fefefe !important; + min-height: 100%; + + @include respond(tab-land) { + width: 100rem; + } + } + + .navigation { + grid-area: navigation; + z-index: 100; + } + + .container { + max-width: 50rem; + overflow: hidden; + display: grid; + + padding: 2rem; + margin: 0 auto; + + grid-template-areas: + 'body' + 'navigation'; + + @include respond(tab-land) { + grid-template-areas: + 'navigation' + 'body'; + } + + @include respond(tab-port) { + padding: .5rem + } + } + + .main-content { + margin-bottom: $nav-height; + margin-top: 0; + @include respond(tab-port) { + margin-top: $nav-height; + margin-bottom: 0; + } + } + + .username { + color: #008ce9; + } diff --git a/frontend/src/styles/_list.scss b/frontend/src/styles/_list.scss new file mode 100644 index 0000000..15c3af7 --- /dev/null +++ b/frontend/src/styles/_list.scss @@ -0,0 +1,159 @@ +.list { + &__head { + font-size: 2rem; + text-align: center; + + .fixed-header & { + background-color: blue; + } + } + } + .list-item { + // background-color: red; + font-size: 1rem; + padding: 0.5rem 0; + transition: all 0.3s; + // background-color: orangered; + border: 1px solid $color-grey-light-3; + border-radius: 2px; + padding: 0.5rem 1rem; + margin: 0.5rem auto; + + a { + color: $color-grey-dark-2; + text-decoration: none; + } + + &:not(:last-child) { + } + + &__title { + font-size: 1.5rem; + font-weight: 700; + color: rgba($color-navy-light, 0.7); + } + + &__description { + color: $color-grey-light-3; + } + + &__content { + } + + &__facts { + padding-top: 0.5rem; + margin-top: 0.5rem; + border-top: 1px solid $color-grey-light-3; + display: flex; + flex-direction: row; + justify-content: center; + + &--icon { + transition: all 0.3s; + cursor: pointer; + padding: 0.7rem 1rem 0.2rem 1rem; + border-radius: 2px; + &:hover { + color: $color-navy-light; + transform: scale(1.2) rotate(10deg); + background: rgba($color-navy-light, 0.3); + } + } + } + + &--notification { + padding: 0.5rem; + transition: all 0.3s; + font-size: 80%; + border-bottom: 1px solid $color-grey-light-3; + margin: 0 auto; + + &:hover { + border: 1px solid rgba($color-navy-light, 0.5); + background: rgba($color-navy-light, 0.05); + } + } + + &--selected { + padding: 0.5rem; + background: rgba($color-navy-light, 0.1); + } + } + + .query-list { + margin-top: 2rem; + + &__item { + padding: 0.5rem 2rem; + margin-bottom: 2rem; + border-radius: 5px; + } + } + + .user-stats-list { + &__item { + display: grid; + grid-template-columns: auto 1fr; + justify-content: center; + align-items: center; + grid-gap: 1rem; + &:not(:last-child) { + border-bottom: 1px solid $color-grey-light-3; + } + margin: 0; + padding: 0.5rem 0.5rem; + + &__title { + font-size: 1.2rem; + color: rgba($color-green-dark, 6); + } + } + } + + .facts { + padding-top: 0.5rem; + margin-top: 0.5rem; + border-top: 1px solid $color-grey-light-3; + display: flex; + justify-content: space-around; + + &--icon { + transition: all 0.3s; + cursor: pointer; + padding: 0.7rem 1rem 0.2rem 1rem; + border-radius: 2px; + &:hover { + color: $color-navy-light; + transform: scale(1.2) rotate(10deg); + background: rgba($color-navy-light, 0.3); + } + } + } + + .fact { + font-size: 1rem; + margin: 0; + display: flex; + justify-content: space-evenly; + text-align: center; + + &__icon { + justify-self: end; + margin-right: 0.5rem; + + &--1 { + color: $color-navy-light; + } + &--2 { + color: $color-red-light; + } + &--3 { + color: $color-orange-light; + } + } + + &__value { + margin: 0; + text-align: left; + } + } \ No newline at end of file diff --git a/frontend/src/styles/_navigation.scss b/frontend/src/styles/_navigation.scss new file mode 100644 index 0000000..266b96d --- /dev/null +++ b/frontend/src/styles/_navigation.scss @@ -0,0 +1,112 @@ +.navigation { + background-color: $color-navy-light; + position: fixed; + bottom: 0; + left: 0; + height: $nav-height; + width: 100vw; + display: grid; + grid-template-columns: 1fr auto; + box-shadow: $box-shadow-small; + + @include respond(tab-port){ + top: 0; + left: 0; + grid-template-columns: auto auto; + } + + + &__title { + display: none; + font-size: 1.5rem; + margin: auto 1rem; + color: $color-grey-light; + + @include respond(tab-port){ + display: inline-block; + } + + } + &__icon { + // padding: 1rem; + // background-color: $color-navy-light; + // font-size: 1rem; + margin: 0 auto; + // border-radius: 50%; + margin-top: .4rem; + // color: $color-white; + + &:hover { + // background-color: rgba($color-navy-light, 0.3); + } + + @include respond(tab-port){ + margin: auto 0rem auto auto; + } + } + + &__list { + height:$nav-height; + list-style: none; + text-align: center; + + display: grid; + grid-template-columns: repeat(auto-fit, minmax(5rem, 1fr)); + + align-items: center; + } + + &__item { + height:$nav-height; + background-color: $color-navy-light; + // border-top: 1px solid $color-grey-light-3; + // border-radius: 2px; + color: $color-grey-light; + + display: grid; + grid-template-columns: 1fr; + justify-content: space-around; + align-items: center; + transition: all .3s ease; + + @include respond(tab-port) { + grid-template-columns: auto 1fr; + padding-left: 1rem; + } + + + &:hover { + background-color: rgba($color-grey-light, 0.3); + } + + &--active { + color: $color-navy-light; + // border-top: 1px solid transparent; + // border-left: 1px solid $color-grey-light-3; + // border-right: 1px solid $color-grey-light-3; + background-color: $color-grey-light; + // margin-top: 20%; + + &:hover { + // background-color: rgba($color-navy-light, 0.1); + color: white; + } + + .icon__label { + // display: block !important; + } + } + } + + &__label { + font-size: 1rem; + // display: none; + + + @include respond(tab-port){ + margin-left: .5rem; + font-size: 1rem; + text-align: left; + } + } + } \ No newline at end of file diff --git a/frontend/src/styles/_post.scss b/frontend/src/styles/_post.scss new file mode 100644 index 0000000..f39c34d --- /dev/null +++ b/frontend/src/styles/_post.scss @@ -0,0 +1,18 @@ + +// .post-section { +// color: #ccc; +// max-width: 600px; +// padding-left: 10px; +// // border: 2px solid #333; + +// a { +// text-decoration: none; +// } +// } + +// .rezweet-section { +// margin: 10px; +// padding: 10px; +// max-width: 400px; +// border: 2px solid #333; +// } \ No newline at end of file diff --git a/frontend/src/styles/abstract/_mixins.scss b/frontend/src/styles/abstract/_mixins.scss new file mode 100644 index 0000000..781bee7 --- /dev/null +++ b/frontend/src/styles/abstract/_mixins.scss @@ -0,0 +1,45 @@ +@mixin clearfix { + &::after{ + content: ""; + display: table; + clear: both; + } +} + +@mixin absCenter { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + + +//media query manager +/* +0-600px; Phone +600-900px; Tablet Potrait +900-1200px; Tablet Landscape +1200-1800px; Normal styles apply +1800-; Large Desktops + +$breakpoint argument choices : +-phone +-tab-port +-tab-land +-big-desktop +*/ + +@mixin respond($breakpoint) { + @if $breakpoint == tab-port{ + @media only screen and (min-width: 56.25em){@content }; //900px + } + @if $breakpoint == tab-land { + @media only screen and (min-width: 75em){@content }; //1200px + } + @if $breakpoint == desktop { + @media only screen and (min-width: 100em){@content}; //1600px + } + @if $breakpoint == big-desktop { + @media only screen and (min-width: 112.5em){@content }; //1800px + } +} \ No newline at end of file diff --git a/frontend/src/styles/abstract/_variables.scss b/frontend/src/styles/abstract/_variables.scss new file mode 100644 index 0000000..ca42377 --- /dev/null +++ b/frontend/src/styles/abstract/_variables.scss @@ -0,0 +1,57 @@ +// colors + +// GREEN +$color-green: #55c57a; +$color-green-light: #7ed56f; +$color-green-dark: #28b485; + +// ORANGE +$color-orange-light: #ffb900; +$color-orange-dark: #ff7730; + +// NAVY +$color-navy-light: #2998ff; +$color-navy-dark: #5643fa; + +// BLUE +$color-blue-lightest: #cad7e0; +$color-blue-light: #406e8e; +$color-blue-dark: #161925; + +//RED +$color-red-lightest:#f14a78; +$color-red-light: #f0386b; +$color-red-dark:#db3362; + +// GREY +$color-grey-dark-1:#333; +$color-grey-dark-2:#555; +$color-grey-dark-3:#777; +$color-grey-dark-4:#999; + +$color-grey-light: #fcfcfc; +$color-grey-light-1: #f6f6f6; +$color-grey-light-2: #eee; +$color-grey-light-3: #ccc; + + +$color-white: #fff; +$color-black: #000; + +// grid +$grid-width: 114rem; +$gutter-vertical: 8rem; +$gutter-vertical-small: 6rem; +$gutter-horizontal: 6rem; + +//font +$default-font-size: 1.6rem; + +$nav-height: 3.5rem; +$body-height: calc(100vh-3.5rem); + + +$box-shadow-small: 0 -0.1rem 1rem 0.1rem rgba($color-black, 0.3); + + +$sidebar-width: 25rem; \ No newline at end of file diff --git a/frontend/src/styles/main.scss b/frontend/src/styles/main.scss index afcf3b1..18e8ed8 100644 --- a/frontend/src/styles/main.scss +++ b/frontend/src/styles/main.scss @@ -1,47 +1,8 @@ -body { - font-family: sans-serif; - margin: 0; - padding: 0; -} +@import 'abstract/variables'; +@import 'abstract/mixins'; -.main { - background-color: #222 !important; - color: #ccc; - min-height: 100%; -} +@import 'base'; +@import 'navigation'; +@import 'post'; +@import 'list'; -.post-section { - color: #ccc; - max-width: 600px; - padding-left: 10px; - // border: 2px solid #333; - - p { - color: #ccc; - } - - a { - text-decoration: none; - } -} - -.rezweet-section { - margin: 10px; - padding: 10px; - max-width: 400px; - border: 2px solid #333; -} - -.container { - padding: 2rem; - width: 900px; - margin: 0 auto; -} - -a { - color: #9cd7ff; -} - -.username { - color: #9cd7ff; -} diff --git a/frontend/yarn.lock b/frontend/yarn.lock index c8f3ca3..4cfcccb 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -908,6 +908,32 @@ resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.0.0-rc.3.tgz#dda2fbf3dafa5ad8c63dadff7e01d3fdf4736025" integrity sha512-GoXw0U2Qaa33m3eUcxuHnHpNvHjNlLo0gtV091XBpaRINaB4X6FGCG5XKxSFNFiPpugUDqNruHzaqpTdDm4AOg== +"@fortawesome/fontawesome-common-types@^0.2.32": + version "0.2.32" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.32.tgz#3436795d5684f22742989bfa08f46f50f516f259" + integrity sha512-ux2EDjKMpcdHBVLi/eWZynnPxs0BtFVXJkgHIxXRl+9ZFaHPvYamAfCzeeQFqHRjuJtX90wVnMRaMQAAlctz3w== + +"@fortawesome/fontawesome-svg-core@^1.2.32": + version "1.2.32" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.32.tgz#da092bfc7266aa274be8604de610d7115f9ba6cf" + integrity sha512-XjqyeLCsR/c/usUpdWcOdVtWFVjPbDFBTQkn2fQRrWhhUoxriQohO2RWDxLyUM8XpD+Zzg5xwJ8gqTYGDLeGaQ== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.32" + +"@fortawesome/free-solid-svg-icons@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.1.tgz#e1432676ddd43108b41197fee9f86d910ad458ef" + integrity sha512-EFMuKtzRMNbvjab/SvJBaOOpaqJfdSap/Nl6hst7CgrJxwfORR1drdTV6q1Ib/JVzq4xObdTDcT6sqTaXMqfdg== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.32" + +"@fortawesome/react-fontawesome@^0.1.14": + version "0.1.14" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz#bf28875c3935b69ce2dc620e1060b217a47f64ca" + integrity sha512-4wqNb0gRLVaBm/h+lGe8UfPPivcbuJ6ecI4hIgW0LjI7kzpYB9FkN0L9apbVzg+lsBdcTf0AlBtODjcSX5mmKA== + dependencies: + prop-types "^15.7.2" + "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"