Skip to content

Commit

Permalink
Fixed post page navigation issue and improved UI design
Browse files Browse the repository at this point in the history
  • Loading branch information
victor committed Sep 9, 2023
1 parent 41da595 commit 10596ae
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 125 deletions.
5 changes: 3 additions & 2 deletions client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Crowdly</title>
<link rel="preconnect" href="https://rsms.me/">
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&display=swap" rel="stylesheet">
</head>
<body class="dark:bg-gray-900 dark:text-gray-300">
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/DislikeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function DislikeButton({ postId, liked, disliked, onSuccess }: {
<button
onClick={handleDislike}
disabled={dislikePostOperation.loading || deleteDislikeOperation.loading || liked}
className='secondary flex items-center space-x-1.5 !px-2'
className='secondary flex items-center space-x-1.5 !px-2 !rounded-l-none'
>
{disliked ? (
<ArrowIcon className='w-5 h-5 rotate-90 text-violet-600' strokeWidth={2.5} />
Expand Down
17 changes: 13 additions & 4 deletions client/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {useEffect, useRef, useState} from 'react'
import {Link} from "react-router-dom"
import {Link, useLocation} from "react-router-dom"
import ThemeButton from "./ThemeButton"
import getCurrentUser from "../utilities/getCurrentUser"
import GitHubIcon from "../icons/GitHubIcon"
Expand All @@ -15,6 +15,12 @@ export default function Header() {
const [isAddPostOpen, setIsAddPostOpen] = useState(false)

const currentUser = getCurrentUser()
const location = useLocation()

useEffect(() => {
setIsMenuOpen(false)
setIsAddPostOpen(false)
}, [location.pathname])

function logout() {
localStorage.removeItem('jwt')
Expand All @@ -26,9 +32,12 @@ export default function Header() {
{isAddPostOpen && <PostForm type={'add'} close={() => setIsAddPostOpen(false)} closeMenu={() => setIsMenuOpen(false)} />}
<header className='fixed top-0 left-0 w-full pt-6 z-10'>
<div className='px-6 lg:max-w-screen-lg container mx-auto'>
<nav className={'p-5 sm:p-6 shadow-md bg-white rounded-lg text-[15px] overflow-hidden transition-all dark:bg-gray-800 ' + (isMenuOpen ? 'max-sm:h-[351px]' : 'max-sm:h-[63px]')}>
<nav className={'p-5 sm:p-6 shadow-md bg-white rounded-lg text-[15px] overflow-hidden transition-all dark:bg-gray-800 ' + (isMenuOpen ? 'max-sm:h-[336px]' : 'max-sm:h-[60px]')}>
<div className='flex items-center justify-between'>
<Link to={'/'} >👋 Crowdly</Link>
<Link to={'/'} className='flex items-center space-x-1.5' >
<div className='bg-violet-600 rounded-full h-3.5 w-3.5'></div>
<div>Crowdly</div>
</Link>
<div className='flex items-center space-x-5'>
<div className='flex items-center space-x-5 max-sm:hidden'>
<Link to={'/about'}>About</Link>
Expand Down Expand Up @@ -96,7 +105,7 @@ export default function Header() {

</>
)}
<div className='pt-2.5 w-full'><button onClick={() => setIsAddPostOpen(true)} className='primary w-full'>Add post</button></div>
{currentUser && <div className='pt-2.5 w-full'><button onClick={() => setIsAddPostOpen(true)} className='primary w-full'>Add post</button></div>}
</div>
<div className='border-t mt-5 pt-5 flex items-center justify-between'>
<div className='text-sm text-slate-400'>© 2023 Victor</div>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/LikeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function LikeButton({ postId, liked, disliked, onSuccess }: { pos
<button
onClick={handleLike}
disabled={likePostOperation.loading || deleteLikeOperation.loading || disliked}
className='secondary flex items-center space-x-1.5 !px-2'
className='secondary flex items-center space-x-1.5 !px-2 !rounded-r-none'
>
{liked ? (
<ArrowIcon className='w-5 h-5 -rotate-90 text-violet-600' strokeWidth={2.5} />
Expand Down
9 changes: 4 additions & 5 deletions client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

@layer base {
html {
@apply max-sm:text-[15px];
-webkit-font-smoothing: antialiased;
}

Expand All @@ -27,9 +28,11 @@
}

input, textarea {
appearance: none;
background: none;
border: none;
outline: none;
-webkit-appearance: none;
}
}

Expand Down Expand Up @@ -58,7 +61,7 @@ textarea:disabled {
}

textarea {
@apply flex resize-none overflow-hidden leading-[1.7] dark:placeholder:text-gray-500
@apply flex resize-none overflow-hidden leading-[1.6] dark:placeholder:text-gray-500
}

button.primary,
Expand Down Expand Up @@ -152,7 +155,3 @@ a:disabled {
.text-red-600 {
@apply dark:text-red-400
}

.help-article > *:first-of-type {
margin-top: 0 !important;
}
3 changes: 2 additions & 1 deletion client/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ const router = createBrowserRouter([
])

const httpLink = createHttpLink({
uri: process.env.REACT_APP_API_URL,
uri: process.env.REACT_APP_API_URL
})
// process.env.REACT_APP_API_URL http://localhost:4000

const authLink = setContext((_, { headers }) => {
// get the authentication token from local storage if it exists
Expand Down
154 changes: 57 additions & 97 deletions client/src/routes/helpArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,107 +40,67 @@ export default function HelpArticle() {
<div className='max-w-screen-md'>
<h1 className="first-letter:capitalize text-3xl font-bold">{article.title}</h1>
<div className="mt-4 text-slate-400">Last updated on {article.lastUpdate.toLocaleString(undefined, { day: 'numeric', month: 'short', year: 'numeric' })}</div>
<div className='mt-14 pt-14 border-t'>
<div className="flex flex-col gap-4 whitespace-pre-wrap help-article">
{article.content.map((c, i) => {
if (c.type === 'head') return (
<h2 className='mt-6 mb-1 subtitle' key={i}>{c.body}</h2>
)
if (c.type === 'text') return (
<p key={i}>{c.body}</p>
)
if (c.type === 'list') return (
<ol className='list-decimal pl-4 space-y-4' key={i}>
{c.body.map((l, j) => (
<li key={j}>
<p>{l}</p>
</li>
))}
</ol>
)
return <div></div>
})}
</div>
<div>
<h2 className='mt-14 pt-14 border-t subtitle'>Tagged in</h2>
<div className="flex gap-2 flex-wrap mt-5">
{article.topics.map((t, i) => (
<Link to={`/help/${t}`} className="first-letter:capitalize secondary text-violet-600" key={i}>{t}</Link>
))}
</div>
</div>
<div>
<h2 className='mt-14 pt-14 border-t subtitle'>Related articles</h2>
{randomArticles.map((article, index) => (
<Link to={`/help/articles/${article.id}`} className="block w-fit mt-3 font-medium text-violet-600 " key={index}>{article.title}</Link>
<div className="sm:mt-14 sm:pt-14 mt-12 pt-12 border-t flex flex-col gap-4 whitespace-pre-wrap">
{article.content.map((c, i) => {
if (c.type === 'head') return (
<h2 className='mt-6 mb-1 subtitle' key={i}>{c.body}</h2>
)
if (c.type === 'text') return (
<p key={i}>{c.body}</p>
)
if (c.type === 'list') return (
<ol className='list-decimal pl-4 space-y-4' key={i}>
{c.body.map((l, j) => (
<li key={j}>
<p>{l}</p>
</li>
))}
</ol>
)
return <div></div>
})}
</div>
<div className='sm:mt-14 sm:pt-14 mt-12 pt-12 border-t'>
<h2 className='subtitle'>Tagged in</h2>
<div className="flex gap-2 flex-wrap mt-5">
{article.topics.map((t, i) => (
<Link to={`/help/${t}`} className="first-letter:capitalize secondary text-violet-600" key={i}>{t}</Link>
))}
</div>
<div className="mt-14 pt-14 border-t grid grid-cols-2 gap-4">
{previousArticle ? (
<Link to={`/help/articles/${previousArticle.id}`} className="block secondary md:!py-4 md:!px-5">
<div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="rotate-180 w-3 h-auto inline"><path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /></svg>
<div className="inline md:text-sm ml-1">Previous article</div>
</div>
<div className="max-md:hidden mt-1 font-medium text-violet-600 !text-base">{previousArticle.title}</div>
</Link>
):(
<div></div>
)}
{nextArticle ? (
<Link to={`/help/articles/${nextArticle.id}`} className="text-right block secondary md:!py-4 md:!px-5">
<div>
<div className="inline md:text-sm mr-1">Next article</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-3 h-auto inline"><path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /></svg>
</div>
<div className="max-md:hidden mt-1 font-medium text-violet-600 !text-base">{nextArticle.title}</div>
</Link>
):(
<div></div>
)}
</div>
</div>
<div className='sm:mt-14 sm:pt-14 mt-12 pt-12 border-t'>
<h2 className='subtitle'>Related articles</h2>
{randomArticles.map((article, index) => (
<Link to={`/help/articles/${article.id}`} className="block w-fit mt-3 font-medium text-violet-600 " key={index}>{article.title}</Link>
))}
</div>
<div className="sm:mt-14 sm:pt-14 mt-12 pt-12 border-t grid grid-cols-2 gap-4">
{previousArticle ? (
<Link to={`/help/articles/${previousArticle.id}`} className="block secondary max-sm:!ring-0 max-sm:!p-0 max-sm:dark:!bg-gray-900 sm:!py-4 sm:!px-5">
<div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="rotate-180 w-3 h-auto inline"><path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /></svg>
<div className="inline md:text-sm ml-1">Previous</div>
</div>
<div className="max-sm:hidden mt-1 font-medium text-violet-600 !text-base">{previousArticle.title}</div>
</Link>
):(
<div></div>
)}
{nextArticle ? (
<Link to={`/help/articles/${nextArticle.id}`} className="text-right block secondary max-sm:!ring-0 max-sm:!p-0 max-sm:dark:!bg-gray-900 sm:!py-4 sm:!px-5">
<div>
<div className="inline md:text-sm mr-1">Next</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-3 h-auto inline"><path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /></svg>
</div>
<div className="max-sm:hidden mt-1 font-medium text-violet-600 !text-base">{nextArticle.title}</div>
</Link>
):(
<div></div>
)}
</div>
</div>
</div>
<Footer />
</>
);
}

/*
`WAS THIS ARTICLE USEFUL` SECTION
<div className="mt-10 pt-8 border-t flex flex-col items-center">
<h3 className="font-semibold text-lg text-black dark:text-white">Was this article useful?</h3>
<div className="flex gap-2 mt-4 font-medium text-indigo-600 ">
<button className="block border rounded-lg py-2 px-6">Yes</button>
<button className="block border rounded-lg py-2 px-6">No</button>
</div>
<p className="mt-4 text-sm">199 out of 274 found this helpful</p>
</div>
BREADCRUMBS
<ol className="text-sm italic leading-6">
<Link to="/" className="inline">Help</Link>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-3.5 h-auto inline mx-1.5 mb-0.5"><path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /></svg>
<Link to="/" className="inline">Getting started</Link>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-3.5 h-auto inline mx-1.5 mb-0.5"><path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /></svg>
<Link to="/" className="inline">Creating an account</Link>
</ol>
RELATED ARTICLES IN SINGLE-COLUMN FORMAT
<div className="mt-10 pt-10 border-t dark:border-gray-700">
<h3 className="font-semibold text-lg text-black dark:text-white">Related articles</h3>
<Link to="/" className="block w-fit mt-4 font-semibold text-indigo-600 dark:text-indigo-400">How do I save a post and where does it get saved?</Link>
<Link to="/" className="block w-fit mt-3 font-semibold text-indigo-600 dark:text-indigo-400">What are community content tags and how do they work?</Link>
<Link to="/" className="block w-fit mt-3 font-semibold text-indigo-600 dark:text-indigo-400">What can I do to get my posts noticed?</Link>
</div>
*/
)
}
26 changes: 13 additions & 13 deletions client/src/routes/post.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {useContext, useEffect, useState} from "react"
import {useQuery, gql, useMutation} from '@apollo/client'
import {useQuery, gql, useMutation, useLazyQuery} from '@apollo/client'
import setTimeLabel from "../utilities/setTimeLabel"
import FeedPost from "../components/FeedPost"
import getCurrentUser from "../utilities/getCurrentUser"
Expand Down Expand Up @@ -82,22 +82,22 @@ export default function Post() {
deletePost(id: $id, repliedId: $repliedId)
}
`
const { loading, error, data } = useQuery<{ post: PostType }>(GET_POST, {
variables: { id: postId }
})
const [getPost, { loading, error }] = useLazyQuery<{ post: PostType }>(GET_POST)
const [replyToPost, replyOperation] = useMutation<{ addPost: string }>(REPLY_TO_POST)
const [deletePost, deleteOperation] = useMutation(DELETE_POST)

useEffect(() => {
if (data && (!post)) {
setPost(data.post)
}
}, [data])

useEffect(() => {
// without these, the edit and quote boxes remain open after quoting a post or editing a post
setIsEditBoxOpen(false)
setIsQuoteBoxOpen(false)
// without this, previous post doesn't disappear
setPost(undefined)
// retrieve data
getPost({
variables: { id: postId }
}).then(response => {
setPost(response.data!.post)
})
}, [postId])

function handleReaction(isNew: boolean, type: 'like' | 'dislike') {
Expand Down Expand Up @@ -165,7 +165,7 @@ export default function Post() {
)}
<span className="text-slate-400">{setTimeLabel(post.createdAt)}</span>
</div>
<p className='text-lg leading-[1.75]'>{post.body}</p>
<p className='text-lg leading-[1.7]'>{post.body}</p>
<div className="flex items-center gap-4">
<span><span className='font-semibold'>{post.likes}</span> likes</span>
<span><span className='font-semibold'>{post.dislikes}</span> dislikes</span>
Expand All @@ -186,10 +186,10 @@ export default function Post() {
{currentUser && (
<div className='flex space-x-2.5 py-9'>
{(currentUser && (currentUser.id !== post.userId)) && (
<>
<div className='flex'>
<LikeButton postId={post.id} liked={post.liked} disliked={post.disliked} onSuccess={handleReaction} />
<DislikeButton postId={post.id} liked={post.liked} disliked={post.disliked} onSuccess={handleReaction} />
</>
</div>
)}
<button onClick={() => setIsQuoteBoxOpen(true)} className='secondary'>Quote</button>
{(currentUser && (currentUser.id === post.userId)) && (
Expand Down
2 changes: 1 addition & 1 deletion client/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module.exports = {
theme: {
extend: {
fontFamily: {
'sans': ['Inter var', ...defaultTheme.fontFamily.sans],
'sans': ['Noto Sans', ...defaultTheme.fontFamily.sans],
},
},
},
Expand Down

0 comments on commit 10596ae

Please sign in to comment.