Skip to content

Commit

Permalink
Merge branch 'deploy/claim-tokens' into deploy/epic
Browse files Browse the repository at this point in the history
  • Loading branch information
samchuk-vlad committed Jul 5, 2024
2 parents 72b91b9 + 894d1a7 commit 3d3189c
Show file tree
Hide file tree
Showing 16 changed files with 1,095 additions and 467 deletions.
3 changes: 3 additions & 0 deletions src/assets/icons/vertical-steps-dots.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 0 additions & 2 deletions src/components/layouts/MobileNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ const tabs: Tab[] = [
const { day } = getDayAndWeekTimestamp()
const tasksPageVisitedDate = tasksPageVisitedDateStore.get() as string

console.log(day, tasksPageVisitedDate)

if (tasksPageVisitedDate !== day.toString()) {
tasksPageVisitedDateStore.set(day.toString())
}
Expand Down
218 changes: 218 additions & 0 deletions src/modules/telegram/TasksPage/ClaimTaskTokensModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import Diamond from '@/assets/emojis/diamond.png'
import Telegram from '@/assets/graphics/tasks/telegram.png'
import VerticalStepsDots from '@/assets/icons/vertical-steps-dots.svg'
import WarningIcon from '@/assets/icons/warning.png'
import Button from '@/components/Button'
import LinkText from '@/components/LinkText'
import useToastError from '@/hooks/useToastError'
import { getBalanceQuery } from '@/services/datahub/leaderboard/points-balance/query'
import { GamificationTask } from '@/services/datahub/tasks'
import { useClaimTaskTokens } from '@/services/datahub/tasks/mutation'
import {
clearGamificationTasksError,
getGamificationTasksErrorQuery,
getGamificationTasksQuery,
} from '@/services/datahub/tasks/query'
import { useMyMainAddress } from '@/stores/my-account'
import { cx } from '@/utils/class-names'
import { LocalStorage } from '@/utils/storage'
import { formatNumber } from '@/utils/strings'
import { Transition } from '@headlessui/react'
import { useQueryClient } from '@tanstack/react-query'
import Image, { StaticImageData } from 'next/image'
import { useEffect, useState } from 'react'
import { createPortal } from 'react-dom'
import { FiArrowUpRight } from 'react-icons/fi'
import { HiXMark } from 'react-icons/hi2'
import TasksRewardsModal from './TasksRewardsModal'

export type ClaimModalVariant = 'epic-telegram' | null

export const claimTaskErrorStore = new LocalStorage(() => 'claim-tasks-error')

type ModalConfig = {
image: StaticImageData
steps: React.ReactNode[]
tag: string
}

export const modalConfigByVariant: Record<
Exclude<ClaimModalVariant, null>,
ModalConfig
> = {
'epic-telegram': {
image: Telegram,
tag: 'JOIN_TELEGRAM_CHANNEL_EpicAppNet',
steps: [
<div key='join-channel' className='flex flex-col gap-3'>
<span className='text-sm font-medium leading-none text-slate-200'>
Join the channel:
</span>
<LinkText
href='https://t.me/EpicAppNet'
variant='primary'
className='flex items-center gap-2 leading-none'
>
@EpicAppNet <FiArrowUpRight />
</LinkText>
</div>,
<span key='claim-click' className='text-sm font-medium text-slate-200'>
Click the button below to verify your task
</span>,
],
},
}

type ClaimTasksTokensModalProps = {
modalVariant: ClaimModalVariant
close: () => void
data: GamificationTask[]
}

const ClaimTasksTokensModal = ({
modalVariant,
close,
data,
}: ClaimTasksTokensModalProps) => {
const [isOpenAnimation, setIsOpenAnimation] = useState(false)
const client = useQueryClient()
const [loading, setLoading] = useState(false)
const myAddress = useMyMainAddress()

const { data: claimTaskTokensError } =
getGamificationTasksErrorQuery.useQuery('error')
const closeModal = () => {
setIsOpenAnimation(false)
close()
}

const isOpen = !!modalVariant

const variant = modalVariant || 'epic-telegram'

const { image: taskImage, steps, tag } = modalConfigByVariant[variant]

const task = data?.find((task) => task.tag === tag)

const reward = formatNumber(parseInt(task?.rewardPoints ?? '0'))

const {
mutate: claimTaskTokens,
error,
isLoading: isClaimLoading,
} = useClaimTaskTokens()

useEffect(() => {
if (!!claimTaskTokensError) setLoading(false)

if (claimTaskTokensError === 'None') {
setIsOpenAnimation(true)
getGamificationTasksQuery.invalidate(client, myAddress)
getBalanceQuery.invalidate(client, myAddress)
}
}, [claimTaskTokensError, client, myAddress])

useToastError(error, 'Failed to claim task tokens')

return createPortal(
<>
<Transition
show={isOpen}
appear
className='fixed inset-0 z-40 h-full w-full bg-black/50 backdrop-blur-md transition duration-300'
enterFrom={cx('opacity-0')}
enterTo='opacity-100'
leaveFrom='h-auto'
leaveTo='opacity-0 !duration-150'
onClick={close}
/>
{isOpenAnimation && isOpen && (
<TasksRewardsModal reward={reward} close={closeModal} />
)}
<Transition
show={isOpen && !isOpenAnimation}
appear
className='fixed bottom-0 left-1/2 z-40 mx-auto flex h-auto max-h-full w-full max-w-screen-md -translate-x-1/2 overflow-y-auto rounded-t-[10px] bg-background-light outline-none transition duration-300'
enterFrom={cx('opacity-0 translate-y-48')}
enterTo='opacity-100 translate-y-0'
leaveFrom='h-auto'
leaveTo='opacity-0 translate-y-24 !duration-150'
>
<Button
size='circleSm'
variant='transparent'
className='absolute right-4 top-4'
onClick={close}
>
<HiXMark className='text-lg' />
</Button>
<div className='mx-auto flex w-full max-w-screen-md flex-col gap-6 overflow-auto px-5 py-6 pb-12'>
<div className='flex flex-col gap-2'>
<span className='text-2xl font-medium'>Tasks</span>
</div>
<div className='flex w-full flex-col gap-6'>
<div className='flex w-full flex-col items-center gap-6'>
<Image src={taskImage} alt='' className='h-[100px] w-[100px]' />
<span className='flex items-center gap-1 text-lg font-medium leading-none'>
<Image src={Diamond} alt='' className='h-6 w-6' /> +{reward}
</span>
<span className='text-[22px] font-bold leading-none'>
Join Our Telegram Channel
</span>
</div>
<div className='flex flex-col gap-6 rounded-[20px] bg-slate-700 p-4'>
{steps.map((step, index) => (
<div key={index} className='relative flex items-center gap-2'>
<div
className={cx(
'flex h-10 w-10 items-center justify-center rounded-full',
'border border-slate-500 bg-slate-600 font-bold'
)}
>
{index + 1}
</div>
{step}
{index !== steps.length - 1 && (
<VerticalStepsDots className='absolute left-5 top-[46px]' />
)}
</div>
))}
</div>
{!!claimTaskTokensError &&
claimTaskTokensError ===
'GAMIFICATION_TASK_CLAIM_FAILED_NOT_COMPLETED' && (
<div className='flex items-center gap-4 rounded-2xl bg-[#EF444433]/20 p-4'>
<Image
src={WarningIcon}
alt=''
className='h-[30px] w-[30px]'
/>
<span className='flex-1 text-sm font-medium leading-[normal] text-red-300'>
Looks like you haven’t completed the required action.
Complete the task to continue.
</span>
</div>
)}
<Button
variant='primary'
size='lg'
isLoading={isClaimLoading || loading}
loadingText='Checking...'
onClick={async () => {
setLoading(true)
clearGamificationTasksError(client)

claimTaskTokens({ taskTag: tag })
}}
>
Check the task
</Button>
</div>
</div>
</Transition>
</>,
document.body
)
}

export default ClaimTasksTokensModal
48 changes: 48 additions & 0 deletions src/modules/telegram/TasksPage/TasksRewardsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Diamond from '@/assets/emojis/diamond.png'
import Button from '@/components/Button'
import { cx } from '@/utils/class-names'
import { Transition } from '@headlessui/react'
import Image from 'next/image'

export type TasksRewardsModalProps = {
reward: string
close: () => void
}

export default function TasksRewardsModal({
reward,
close,
}: TasksRewardsModalProps) {
return (
<>
<Transition
appear
show
className='fixed inset-0 z-40 flex h-full w-full max-w-screen-md origin-center items-center justify-center transition duration-300'
enterFrom={cx('opacity-0 scale-75')}
enterTo={cx('opacity-100 scale-100')}
leaveFrom={cx('opacity-100 scale-100')}
leaveTo={cx('opacity-0 scale-75')}
onClick={() => close()}
>
<div className='absolute left-1/2 top-1/2 h-[300px] w-[300px] -translate-x-1/2 -translate-y-1/2 animate-[pulse_3s_ease-in-out_infinite] rounded-full bg-background-primary/20 blur-3xl' />
<div className='relative flex h-full flex-1 flex-col items-center justify-center gap-1 px-4 py-3'>
<Image src={Diamond} alt='' className='h-12 w-12' />
<span className='text-3xl font-bold'>{reward}</span>
<span className='text-text/70'>Points earned!</span>

<div className='absolute bottom-6 w-full px-4'>
<Button
variant='primary'
className='w-full'
size='lg'
onClick={close}
>
Thank you!
</Button>
</div>
</div>
</Transition>
</>
)
}
44 changes: 38 additions & 6 deletions src/modules/telegram/TasksPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,23 @@ import {
getTodaySuperLikeCountQuery,
getTokenomicsMetadataQuery,
} from '@/services/datahub/content-staking/query'
import {
clearGamificationTasksError,
getGamificationTasksQuery,
} from '@/services/datahub/tasks/query'
import { useSendEvent } from '@/stores/analytics'
import { useMyMainAddress } from '@/stores/my-account'
import { formatNumber } from '@/utils/strings'
import { useQueryClient } from '@tanstack/react-query'
import Image, { ImageProps } from 'next/image'
import Link from 'next/link'
import { useState } from 'react'
import { FaChevronRight } from 'react-icons/fa6'
import SkeletonFallback from '../../../components/SkeletonFallback'
import ClaimTasksTokensModal, {
ClaimModalVariant,
modalConfigByVariant,
} from './ClaimTaskTokensModal'

export default function TasksPage() {
useTgNoScroll()
Expand All @@ -37,8 +46,8 @@ export default function TasksPage() {
className='sticky top-0'
/>
<div className='flex flex-1 flex-col gap-8 overflow-auto px-4 py-8'>
<DailyTasks />
<BasicTasks />
<DailyTasks />
<NewTasks />
</div>
</LayoutWithBottomNavigation>
Expand Down Expand Up @@ -102,9 +111,10 @@ function DailyTasks() {
completed={isTodayRewardClaimed}
isLoadingReward={loadingServerDay || loadingDailyReward}
customAction={
<span className='font-bold'>
<span className='flex w-fit items-center font-bold'>
<SkeletonFallback
isLoading={loadingServerDay || loadingDailyReward}
className='w-fit min-w-[40px]'
>
{(todayRewardIndex || 0) + 1}
</SkeletonFallback>
Expand Down Expand Up @@ -136,11 +146,24 @@ function DailyTasks() {

function BasicTasks() {
const sendEvent = useSendEvent()
const [modalVariant, setModalVariant] = useState<ClaimModalVariant>(null)
const myAddress = useMyMainAddress()
const client = useQueryClient()

const { data: gamificationTasks } = getGamificationTasksQuery.useQuery(
myAddress || ''
)

const data = gamificationTasks?.data

const { tag } = modalConfigByVariant['epic-telegram']
const task = data?.find((task) => task.tag === tag)

return (
<div className='flex flex-col gap-5'>
<div className='flex flex-col gap-1'>
<span className='self-center text-lg font-bold text-text-muted'>
Basic Tasks
Main Tasks
</span>
<span className='self-center text-center text-sm text-text-muted'>
Join our social media and receive rewards later
Expand All @@ -151,12 +174,16 @@ function BasicTasks() {
image={Telegram}
onClick={() => {
sendEvent('tasks_telegram_open')

if (task !== undefined && !task?.claimed) {
clearGamificationTasksError(client)
setModalVariant('epic-telegram')
}
}}
title='Join Our Telegram Channel'
href='https://t.me/EpicAppNet'
openInNewTab
reward={30000}
completed={false}
reward={parseInt(task?.rewardPoints ?? '0')}
completed={task?.claimed ?? false}
/>
<TaskCard
image={TwitterX}
Expand All @@ -170,6 +197,11 @@ function BasicTasks() {
completed={false}
/>
</div>
<ClaimTasksTokensModal
modalVariant={modalVariant}
close={() => setModalVariant(null)}
data={data || []}
/>
</div>
)
}
Expand Down
6 changes: 6 additions & 0 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ export type AppCommonProps = {
}

export default function App(props: AppProps<AppCommonProps>) {
useEffect(() => {
import('eruda').then(({ default: eruda }) => {
eruda.init()
})
})

return (
<SessionProvider
basePath={
Expand Down
Loading

0 comments on commit 3d3189c

Please sign in to comment.