Skip to content

Commit

Permalink
Merge pull request #692 from dappforce/deploy/epic
Browse files Browse the repository at this point in the history
Deploy/epic
  • Loading branch information
teodorus-nathaniel authored Jul 19, 2024
2 parents e91579b + ca54b37 commit 38bab66
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 92 deletions.
60 changes: 60 additions & 0 deletions src/components/chats/ChatItem/profilePosts/ProfileDetailModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import MenuList from '@/components/MenuList'
import ProfilePreview from '@/components/ProfilePreview'
import { Skeleton } from '@/components/SkeletonFallback'
import Modal, { ModalFunctionalityProps } from '@/components/modals/Modal'
import useIsModerationAdmin from '@/hooks/useIsModerationAdmin'
import useTgLink from '@/hooks/useTgLink'
import { getUserReferralsQuery } from '@/services/datahub/leaderboard/query'
import { formatNumber } from '@/utils/strings'
import { FaPaperPlane } from 'react-icons/fa6'

export default function ProfileDetailModal({
address,
...props
}: ModalFunctionalityProps & { address: string }) {
const { telegramLink, isLoading } = useTgLink(address)
const { data: referralData } = getUserReferralsQuery.useQuery(address || '')
const isAdmin = useIsModerationAdmin()
if (!isAdmin) return null

return (
<Modal {...props} title='Profile' withCloseButton>
<div className='flex flex-col gap-3 border-b border-b-border-gray pb-4'>
<ProfilePreview asLink address={address} />
<div className='grid grid-cols-1'>
<div className='grid grid-cols-[max-content_1fr] gap-2'>
<span className='text-text-muted'>Referrals Count</span>
<span>
<span className='text-text-muted'>: </span>
{referralData ? (
formatNumber(referralData.refCount)
) : (
<Skeleton />
)}
</span>
<span className='text-text-muted'>Points from Referral</span>
<span>
<span className='text-text-muted'>: </span>
{referralData ? (
formatNumber(referralData.pointsEarned)
) : (
<Skeleton />
)}
</span>
</div>
</div>
</div>
<MenuList
className='-mx-3 -mb-5 w-[calc(100%_+_1.5rem)] px-0'
menus={[
{
text: 'Message User',
icon: FaPaperPlane,
href: telegramLink,
disabled: isLoading,
},
]}
/>
</Modal>
)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import AddressAvatar from '@/components/AddressAvatar'
import Button from '@/components/Button'
import Name from '@/components/Name'
import SkeletonFallback from '@/components/SkeletonFallback'
import { env } from '@/env.mjs'
import useAuthorizedForModeration from '@/hooks/useAuthorizedForModeration'
import useIsModerationAdmin from '@/hooks/useIsModerationAdmin'
import { TabButton } from '@/modules/chat/HomePage/ChatTabs'
import { getModerationReasonsQuery } from '@/services/datahub/moderation/query'
import { getUserPostedMemesForCountQuery } from '@/services/datahub/posts/query'
import { getPaginatedPostIdsByPostIdAndAccount } from '@/services/datahub/posts/queryByAccount'
import { useSendEvent } from '@/stores/analytics'
import { useProfilePostsModal } from '@/stores/profile-posts-modal'
Expand All @@ -13,9 +16,13 @@ import { Transition } from '@headlessui/react'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { createPortal } from 'react-dom'
import { HiOutlineChevronLeft } from 'react-icons/hi2'
import SkeletonFallback from '../../../SkeletonFallback'
import {
HiOutlineChevronLeft,
HiOutlineInformationCircle,
} from 'react-icons/hi2'
import UnapprovedMemeCount from '../../UnapprovedMemeCount'
import { useModerateWithSuccessToast } from '../ChatItemMenus'
import ProfileDetailModal from './ProfileDetailModal'
import ProfilePostsList from './ProfilePostsList'

type Tab = 'all' | 'contest'
Expand All @@ -33,6 +40,7 @@ const chatIdByTab = {
}

const ProfilePostsListModal = ({ tabsConfig }: ProfilePostsListModalProps) => {
const [isOpenDetail, setIsOpenDetail] = useState(false)
const [selectedTab, setSelectedTab] = useState<Tab>(
tabsConfig?.defaultTab || 'all'
)
Expand All @@ -51,16 +59,24 @@ const ProfilePostsListModal = ({ tabsConfig }: ProfilePostsListModalProps) => {

const { mutate: moderate } = useModerateWithSuccessToast(messageId, chatId)
const sendEvent = useSendEvent()
const isAdmin = useIsModerationAdmin()
const { isAuthorized } = useAuthorizedForModeration(chatId)

const { data: reasons } = getModerationReasonsQuery.useQuery(null)
const firstReasonId = reasons?.[0].id
const { data: userPostedMemes, isLoading: loadingMemes } =
getUserPostedMemesForCountQuery.useQuery(
{
address,
chatId,
},
{ enabled: isOpen }
)

const { data, isLoading } =
getPaginatedPostIdsByPostIdAndAccount.useInfiniteQuery(chatId, address)

const totalPostsCount = data?.pages[0].totalData || 0

const { data: reasons } = getModerationReasonsQuery.useQuery(null)
const firstReasonId = reasons?.[0].id

const onBlockUserClick = () => {
sendEvent('block_user', { hubId, chatId })
moderate({
Expand Down Expand Up @@ -102,8 +118,13 @@ const ProfilePostsListModal = ({ tabsConfig }: ProfilePostsListModalProps) => {
leaveFrom='h-auto'
leaveTo='opacity-0 -translate-y-24 !duration-150'
>
<ProfileDetailModal
isOpen={isOpenDetail}
closeModal={() => setIsOpenDetail(false)}
address={address}
/>
<div className='mx-auto flex w-full max-w-screen-md flex-1 flex-col overflow-auto'>
<div className='relative mx-auto flex w-full items-center justify-between gap-2 px-4 py-4'>
<div className='relative mx-auto flex w-full items-center justify-between gap-2 px-4 py-3'>
<div className='flex flex-1 items-center gap-2'>
<Button
variant='transparent'
Expand All @@ -122,29 +143,51 @@ const ProfilePostsListModal = ({ tabsConfig }: ProfilePostsListModalProps) => {
address={address}
className='flex-shrink-0 cursor-pointer'
/>
<div className='flex flex-col gap-1'>
<div
className='flex flex-col gap-0.5'
onClick={() => {
if (isAdmin) setIsOpenDetail(true)
}}
>
<Name address={address} className='!text-text' clipText />
<span className='flex items-center gap-1 text-xs font-medium leading-[normal] text-slate-400'>
<span>Memes:</span>
<SkeletonFallback
isLoading={isLoading}
className='my-0 w-fit min-w-8'
>
{totalPostsCount}
</SkeletonFallback>
</span>
{isAdmin ? (
<UnapprovedMemeCount
className='bg-transparent p-0 text-text-muted'
address={address}
chatId={chatId}
/>
) : (
<span className='flex items-center gap-1 text-xs font-medium leading-[normal] text-slate-400'>
<span>Memes:</span>
<SkeletonFallback
isLoading={isLoading}
className='my-0 w-fit min-w-8'
>
{totalPostsCount}
</SkeletonFallback>
</span>
)}
</div>
</div>

{isAuthorized && (
<Button
size='md'
variant='redOutline'
className='w-fit text-red-400'
onClick={onBlockUserClick}
>
Block user
</Button>
<div className='flex items-center gap-2'>
<Button
size='circleSm'
variant='transparent'
onClick={() => setIsOpenDetail(true)}
>
<HiOutlineInformationCircle className='text-lg text-text-muted' />
</Button>
<Button
size='md'
variant='redOutline'
className='w-fit text-red-400'
onClick={onBlockUserClick}
>
Block user
</Button>
</div>
)}
</div>
<div className='relative mx-auto flex h-full max-h-full min-h-[400px] w-full flex-col items-center px-4'>
Expand Down
12 changes: 6 additions & 6 deletions src/components/chats/UnapprovedMemeCount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,20 @@ export default function UnapprovedMemeCount({
)}
>
<div className='flex items-center gap-1'>
<div className='flex items-center gap-1'>
<Image src={CheckImage} className='h-4 w-4' alt='' />
<span>{approved}</span>
</div>
<span className='text-text-muted'>/</span>
<div className='flex items-center gap-1'>
<Image src={ForbiddenImage} className='h-4 w-4' alt='' />
<span>{blocked}</span>
</div>
<span>/</span>
<span className='text-text-muted'>/</span>
<div className='flex items-center gap-1'>
<Image src={TimeImage} className='h-4 w-4' alt='' />
<span>{unapproved}</span>
</div>
<span>/</span>
<div className='flex items-center gap-1'>
<Image src={CheckImage} className='h-4 w-4' alt='' />
<span>{approved}</span>
</div>
</div>
</div>
)
Expand Down
9 changes: 3 additions & 6 deletions src/components/content-staking/SuperLike.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Thumbsup from '@/assets/emojis/thumbsup.png'
import { env } from '@/env.mjs'
import { useIsAddressBlockedInApp } from '@/hooks/useIsAddressBlockedInApp'
import { getPostQuery, getServerTimeQuery } from '@/services/api/query'
import { useCreateSuperLike } from '@/services/datahub/content-staking/mutation'
Expand All @@ -16,6 +15,7 @@ import { useLoginModal } from '@/stores/login-modal'
import { useMessageData } from '@/stores/message'
import { useMyAccount, useMyMainAddress } from '@/stores/my-account'
import { cx } from '@/utils/class-names'
import { getIsContestEnded, getIsInContest } from '@/utils/contest'
import { currentNetwork } from '@/utils/network'
import { LocalStorage } from '@/utils/storage'
import dayjs from 'dayjs'
Expand Down Expand Up @@ -64,11 +64,8 @@ export function SuperLikeWrapper({
const { mutate: createSuperLike } = useCreateSuperLike()
const { data: superLikeCount } = getSuperLikeCountQuery.useQuery(postId)

const isInContest =
post?.struct.rootPostId === env.NEXT_PUBLIC_CONTEST_CHAT_ID
const isContestEnded = dayjs().isAfter(
dayjs(env.NEXT_PUBLIC_CONTEST_END_TIME)
)
const isInContest = getIsInContest(post?.struct.rootPostId ?? '')
const isContestEnded = getIsContestEnded()
const isInEndedContest = isInContest && isContestEnded

const { canBeLiked: canBeSuperliked, isLoading: loadingCanBeLiked } =
Expand Down
11 changes: 5 additions & 6 deletions src/components/extensions/common/CommonChatItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { getRepliedMessageId } from '@/components/chats/utils'
import SuperLike, {
SuperLikeButton,
} from '@/components/content-staking/SuperLike'
import { env } from '@/env.mjs'
import useAuthorizedForModeration from '@/hooks/useAuthorizedForModeration'
import useIsMessageBlocked from '@/hooks/useIsMessageBlocked'
import useIsModerationAdmin from '@/hooks/useIsModerationAdmin'
Expand All @@ -24,8 +23,8 @@ import {
import { isMessageSent } from '@/services/subsocial/commentIds/optimistic'
import { useMyMainAddress } from '@/stores/my-account'
import { cx } from '@/utils/class-names'
import { getIsContestEnded, getIsInContest } from '@/utils/contest'
import { getTimeRelativeToNow } from '@/utils/date'
import dayjs from 'dayjs'
import Linkify from 'linkify-react'
import { useInView } from 'react-intersection-observer'
import { ExtensionChatItemProps } from '../types'
Expand Down Expand Up @@ -343,7 +342,7 @@ export default function CommonChatItem({
}}
size='sm'
className={cx(
'w-full whitespace-nowrap px-0 text-xs !text-text-red',
'w-full whitespace-nowrap px-0 text-sm !text-text-red',
{
['!bg-[#EF4444] disabled:border-none disabled:!text-white disabled:!ring-0 disabled:!brightness-100']:
isMessageBlocked,
Expand Down Expand Up @@ -436,15 +435,15 @@ function ApproveMemeButton({
messageId: string
}) {
const { mutate, isLoading } = useApproveMessage()
const isInContest = chatId === env.NEXT_PUBLIC_CONTEST_CHAT_ID
const isContestEnded = dayjs().isAfter(env.NEXT_PUBLIC_CONTEST_END_TIME)
const isInContest = getIsInContest(chatId)
const isContestEnded = getIsContestEnded()
const isInEndedContest = isInContest && isContestEnded

return (
<Button
variant='greenOutline'
size='sm'
className='whitespace-nowrap px-0 text-xs disabled:!border-text-muted disabled:!text-text-muted disabled:!ring-text-muted'
className='whitespace-nowrap px-0 text-sm disabled:!border-text-muted disabled:!text-text-muted disabled:!ring-text-muted'
loadingText='Approving...'
isLoading={isLoading}
disabled={isInEndedContest}
Expand Down
25 changes: 22 additions & 3 deletions src/modules/chat/HomePage/ChatContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Meme2EarnIntroModal, {
import Modal, { ModalFunctionalityProps } from '@/components/modals/Modal'
import { env } from '@/env.mjs'
import useIsAddressBlockedInChat from '@/hooks/useIsAddressBlockedInChat'
import useIsModerationAdmin from '@/hooks/useIsModerationAdmin'
import useLinkedEvmAddress from '@/hooks/useLinkedEvmAddress'
import usePostMemeThreshold from '@/hooks/usePostMemeThreshold'
import PointsWidget from '@/modules/points/PointsWidget'
Expand All @@ -20,6 +21,8 @@ import { useSendEvent } from '@/stores/analytics'
import { useExtensionData } from '@/stores/extension'
import { useMessageData } from '@/stores/message'
import { useMyMainAddress } from '@/stores/my-account'
import { cx } from '@/utils/class-names'
import { getIsContestEnded } from '@/utils/contest'
import { useLocalStorage } from '@uidotdev/usehooks'
import dayjs from 'dayjs'
import duration from 'dayjs/plugin/duration'
Expand All @@ -43,12 +46,24 @@ const chatIdsBasedOnSelectedTab = {

export default function ChatContent({ className }: Props) {
const { query } = useRouter()
const isAdmin = useIsModerationAdmin()
let [selectedTab, setSelectedTab] = useLocalStorage<TabState>(
'memes-tab',
'all'
)
if (!tabStates.includes(selectedTab)) {
if (
!tabStates.includes(selectedTab) ||
(selectedTab === 'contest' && getIsContestEnded())
) {
selectedTab = 'all'
} else if (selectedTab === 'not-approved-contest' && getIsContestEnded()) {
selectedTab = 'not-approved'
}
if (
!isAdmin &&
(selectedTab === 'not-approved' || selectedTab === 'not-approved-contest')
) {
setSelectedTab('all')
}

useLayoutEffect(() => {
Expand Down Expand Up @@ -79,8 +94,12 @@ export default function ChatContent({ className }: Props) {

return (
<>
<PointsWidget isNoTgScroll className='sticky top-0' />
<Tabs selectedTab={selectedTab} setSelectedTab={setSelectedTab} />
{!isAdmin && <PointsWidget isNoTgScroll className='sticky top-0' />}
<Tabs
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
className={cx(isAdmin && 'top-0')}
/>
<ChatRoom
scrollableContainerClassName='pt-12'
asContainer
Expand Down
Loading

0 comments on commit 38bab66

Please sign in to comment.