Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/atoms/postsAtom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,23 @@ export type Post = {
createdAt: Timestamp
}

export type PostVote = {
id: string
postId: string
communityId: string
voteValue: number
}

interface PostState {
selectedPost: Post | null
posts: Post[]
// postVotes: PostVote[]
// postsCache: {
// [key: string]: Post[]
// }
// postUpdateRequired: boolean
postVotes: PostVote[]
}

export const defaultPostState: PostState = {
selectedPost: null,
posts: [],
// postVotes: [],
// postsCache: {},
// postUpdateRequired: true,
postVotes: [],
}

export const postState = atom<PostState>({
Expand Down
131 changes: 129 additions & 2 deletions src/components/community/About.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Community } from '@/src/atoms/communitiesAtom'
import { Community, communityState } from '@/src/atoms/communitiesAtom'
import {
Box,
Button,
Expand All @@ -12,14 +12,55 @@ import {
Image,
Spinner,
} from '@chakra-ui/react'
import React from 'react'
import React, { useRef, useState } from 'react'
import { HiOutlineDotsHorizontal } from 'react-icons/hi'
import { FaReddit } from 'react-icons/fa'
import { RiCakeLine } from 'react-icons/ri'
import Link from 'next/link'
import moment from 'moment'
import { useAuthState } from 'react-firebase-hooks/auth'
import { auth, firestore, storage } from '@/src/firebase/clientApp'
import useSelectFile from '@/src/hooks/useSelectFile'
import { useSetRecoilState } from 'recoil'
import { getDownloadURL, ref, uploadString } from 'firebase/storage'
import { doc, updateDoc } from 'firebase/firestore'

type AboutProps = {
communityData: Community
}

const About: React.FC<AboutProps> = ({ communityData }) => {
const [user] = useAuthState(auth)
const selectedFileRef = useRef<HTMLInputElement>(null)
const { selectedFile, setSelectedFile, onSelectFile } = useSelectFile()
const [uploadingImage, setUploadingImage] = useState(false)
const setCommuityStateValue = useSetRecoilState(communityState)

const onUpdateImage = async () => {
if (!selectedFile) return
setUploadingImage(true)
try {
const imageRef = ref(storage, `communities/${communityData.id}/image`)
await uploadString(imageRef, selectedFile, 'data_url')
const downloadURL = await getDownloadURL(imageRef)

await updateDoc(doc(firestore, 'communities', communityData.id), {
imageURL: downloadURL,
})
console.log('HERE IS DOWNLOAD URL', downloadURL)

setCommuityStateValue(prev => ({
...prev,
currentCommunity: {
...prev.currentCommunity,
imageURL: downloadURL,
} as Community,
}))
} catch (error: any) {
console.log('onUpdateImage error', error.message)
}
setUploadingImage(false)
}
return (
<Box position='sticky' top='14px'>
<Flex
Expand All @@ -35,6 +76,92 @@ const About: React.FC<AboutProps> = ({ communityData }) => {
</Text>
<Icon as={HiOutlineDotsHorizontal} cursor='pointer' />
</Flex>
<Flex direction='column' p={3} bg='white' borderRadius='0px 0px 4px 4px'>
<Stack>
<Flex width='100%' p={2} fontSize='10pt' fontWeight={700}>
<Flex direction='column' flexGrow={1}>
<Text>{communityData.numberOfMembers.toLocaleString()}</Text>
<Text>Members</Text>
</Flex>
<Flex direction='column' flexGrow={1}>
<Text>1</Text>
<Text>Online</Text>
</Flex>
</Flex>
<Divider />
<Flex
align='center'
width='100%'
p={1}
fontWeight={500}
fontSize='10pt'
>
<Icon as={RiCakeLine} mr={2} fontSize={18} />
{communityData?.createdAt && (
<Text>
Created{' '}
{moment(
new Date(communityData.createdAt.seconds * 1000)
).format('MMM DD, YYYY')}
</Text>
)}
</Flex>
<Link href={`/r/${communityData.id}/submit`}>
<Button w='100%' mt={3} height='30px'>
Create post
</Button>
</Link>
{user?.uid === communityData.creatorId && (
<>
<Divider />
<Stack fontSize='10pt' spacing={1}>
<Text fontWeight={600}>Admin</Text>
<Flex align='center' justify='space-between'>
<Text
color='blue.500'
cursor='pointer'
_hover={{ textDecoration: 'underline' }}
onClick={() => selectedFileRef.current?.click()}
>
Change Image
</Text>
{communityData?.imageURL || selectedFile ? (
<Image
borderRadius='full'
boxSize='40px'
src={selectedFile || communityData?.imageURL}
alt='Community IMG'
/>
) : (
<Icon
as={FaReddit}
fontSize={40}
color='brand.100'
mr={2}
/>
)}
</Flex>
{selectedFile &&
(uploadingImage ? (
<Spinner />
) : (
<Text cursor='pointer' onClick={onUpdateImage}>
Save Changes
</Text>
))}
<input
id='file-upload'
type='file'
accept='image/x-png,image/gif,image/jpeg'
hidden
ref={selectedFileRef}
onChange={onSelectFile}
/>
</Stack>
</>
)}
</Stack>
</Flex>
</Box>
)
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/community/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ const Header: React.FC<HeaderProps> = ({ communityData }) => {
<Box height='50%' bg='blue.400' />
<Flex justifyContent='center' bg='white' height='50%'>
<Flex width='95%' maxWidth='860px'>
{communityData.imageURL ? (
{communityStateValue.currentCommunity?.imageURL ? (
<Image
borderRadius='full'
boxSize='66px'
src={communityData.imageURL}
src={communityStateValue.currentCommunity.imageURL}
alt='Dan Abramov'
position='relative'
top={-3}
Expand Down
2 changes: 0 additions & 2 deletions src/components/navbar/rightContent/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ type UserMenuProps = {
}

const UserMenu: React.FC<UserMenuProps> = ({ user }) => {
const resetCommunityState = useResetRecoilState(communityState)
const setAuthModalState = useSetRecoilState(authModalState)

const logout = async () => {
await signOut(auth)
resetCommunityState()
}

return (
Expand Down
19 changes: 3 additions & 16 deletions src/components/posts/NewPostForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import ImageUpload from './postForm/ImageUpload'
import { Post } from '@/src/atoms/postsAtom'
import { firestore, storage } from '@/src/firebase/clientApp'
import { ref, uploadString, getDownloadURL } from 'firebase/storage'
import useSelectFile from '@/src/hooks/useSelectFile'

type NewPostFormProps = {
user: User
Expand Down Expand Up @@ -75,9 +76,9 @@ const NewPostForm: React.FC<NewPostFormProps> = ({ user }) => {
title: '',
body: '',
})
const [selectedFile, setSelectedFile] = useState<string>()
const [loading, setLoading] = useState(false)
const [error, setError] = useState(false)
const { setSelectedFile, selectedFile, onSelectFile } = useSelectFile()

const handleCreatePost = async () => {
const { communityId } = router.query
Expand Down Expand Up @@ -112,20 +113,6 @@ const NewPostForm: React.FC<NewPostFormProps> = ({ user }) => {
setLoading(false)
}

const onSelectImage = (event: React.ChangeEvent<HTMLInputElement>) => {
const reader = new FileReader()

if (event.target.files?.[0]) {
reader.readAsDataURL(event.target.files[0])
}

reader.onload = readerEvent => {
if (readerEvent.target?.result) {
setSelectedFile(readerEvent.target.result as string)
}
}
}

const onTextChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
Expand Down Expand Up @@ -164,7 +151,7 @@ const NewPostForm: React.FC<NewPostFormProps> = ({ user }) => {
selectedFile={selectedFile}
setSelectedFile={setSelectedFile}
setSelectedTab={setSelectedTab}
onSelectImage={onSelectImage}
onSelectImage={onSelectFile}
/>
)}
</Flex>
Expand Down
38 changes: 26 additions & 12 deletions src/components/posts/PostItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ import moment from 'moment'
import { async } from '@firebase/util'
import { log } from 'console'
import { AiOutlineDelete } from 'react-icons/ai'
import { useRouter } from 'next/router'

type PostItemProps = {
post: Post
userIsCreator: boolean
userVoteValue?: number
onVote: () => {}
onVote: (
event: React.MouseEvent<SVGElement, MouseEvent>,
post: Post,
vote: number,
communityId: string
) => void
onDeletePost: (post: Post) => Promise<boolean>
onSelectPost: () => void
onSelectPost?: (post: Post) => void
}

const PostItem: React.FC<PostItemProps> = ({
Expand All @@ -46,17 +52,25 @@ const PostItem: React.FC<PostItemProps> = ({
}) => {
const [loadingImage, setLoadingImage] = useState(true)
const [loadingDelete, setLoadingDelete] = useState(false)
const router = useRouter()
const singlePostPage = !onSelectPost

const [error, setError] = useState(false)

const handleDelete = async () => {
const handleDelete = async (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
event.stopPropagation()
setLoadingDelete(true)
try {
const success = await onDeletePost(post)
if (!success) {
throw new Error('Failed to delete post')
}
console.log('Post was succesfuly delited')
if (singlePostPage) {
router.push(`/r/${post.communityId}`)
}
} catch (error: any) {
setError(error.message)
console.log('deleteError', error)
Expand All @@ -68,19 +82,19 @@ const PostItem: React.FC<PostItemProps> = ({
<Flex
border='1px solid'
bg='white'
borderColor='gray.300'
borderRadius={4}
cursor='pointer'
_hover={{ borderColor: 'gray:500' }}
onClick={onSelectPost}
borderColor={singlePostPage ? 'white' : 'gray.300'}
borderRadius={singlePostPage ? '4px 4px 0px 0px' : '4px'}
cursor={singlePostPage ? 'unset' : 'pointer'}
_hover={{ borderColor: singlePostPage ? 'none' : 'gray.500' }}
onClick={() => onSelectPost && onSelectPost(post)}
>
<Flex
direction='column'
align='center'
bg='gray.100'
bg={singlePostPage ? 'none' : 'gray.100'}
p={2}
width='40px'
borderRadius={4}
borderRadius={singlePostPage ? '0' : '3px 0px 0px 3px'}
>
<Icon
as={
Expand All @@ -89,7 +103,7 @@ const PostItem: React.FC<PostItemProps> = ({
color={userVoteValue === 1 ? 'brand.100' : 'gray.400'}
fontSize={22}
cursor='pointer'
onClick={onVote}
onClick={event => onVote(event, post, 1, post.communityId)}
/>
<Text fontSize='9pt' fontWeight={600}>
{post.voteStatus}
Expand All @@ -103,7 +117,7 @@ const PostItem: React.FC<PostItemProps> = ({
color={userVoteValue === -1 ? '#4379FF' : 'gray.400'}
fontSize={22}
cursor='pointer'
onClick={onVote}
onClick={event => onVote(event, post, -1, post.communityId)}
/>
</Flex>
<Flex direction='column' width='100%'>
Expand Down
15 changes: 5 additions & 10 deletions src/components/posts/Posts.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import React, { useEffect, useState } from 'react'
import { Community } from '@/src/atoms/communitiesAtom'
import {
collection,
doc,
getDoc,
getDocs,
orderBy,
query,
where,
} from 'firebase/firestore'
import { collection, getDocs, orderBy, query, where } from 'firebase/firestore'
import { auth, firestore } from '@/src/firebase/clientApp'
import usePosts from '@/src/hooks/usePosts'
import { Post } from '@/src/atoms/postsAtom'
Expand Down Expand Up @@ -68,7 +60,10 @@ const Posts: React.FC<PostsProps> = ({ communityData }) => {
key={item.id}
post={item}
userIsCreator={user?.uid === item.creatorId}
userVoteValue={undefined}
userVoteValue={
postStateValue.postVotes.find(vote => vote.postId === item.id)
?.voteValue
}
onVote={onVote}
onSelectPost={onSelectPost}
onDeletePost={onDeletePost}
Expand Down
Loading