Skip to content

Commit

Permalink
Merge pull request #637 from peanutprotocol/feat/asset-page
Browse files Browse the repository at this point in the history
feat: updated wallet asset page ui
  • Loading branch information
kushagrasarathe authored Jan 21, 2025
2 parents 2bb8367 + 40cad99 commit 742e879
Show file tree
Hide file tree
Showing 11 changed files with 309 additions and 139 deletions.
99 changes: 56 additions & 43 deletions src/app/(mobile-ui)/history/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
'use client'

import { ARBITRUM_ICON } from '@/assets'
import { Button } from '@/components/0_Bruddle'
import { useDashboard } from '@/components/Dashboard/useDashboard'
import NoDataEmptyState from '@/components/Global/EmptyStates/NoDataEmptyState'
import { ListItemView, TransactionType } from '@/components/Global/ListItemView'
import * as utils from '@/utils'

import NavHeader from '@/components/Global/NavHeader'
import { PEANUT_API_URL } from '@/constants'
import { useWallet } from '@/hooks/wallet/useWallet'
import { IDashboardItem } from '@/interfaces'
import { formatAmountWithSignificantDigits, printableAddress } from '@/utils'
import { formatAmountWithSignificantDigits, formatDate, printableAddress } from '@/utils'
import { useInfiniteQuery } from '@tanstack/react-query'
import Link from 'next/link'
import { useEffect, useRef, useState } from 'react'

const ITEMS_PER_PAGE = 10
Expand All @@ -37,7 +38,7 @@ const HistoryPage = () => {
const formattedData = pageData.map((data) => {
const linkDetails = updatedData.find((item) => item.link === data.link)
return {
id: (data.link ?? data.txHash ?? '') + Math.random(),
id: `${data.link ?? data.txHash ?? ''}-${Date.now()}`,
transactionType: data.type,
amount: `$ ${formatAmountWithSignificantDigits(Number(data.amount), 2)}`,
recipientAddress: data.address ? `To ${printableAddress(data.address)}` : '',
Expand Down Expand Up @@ -106,46 +107,58 @@ const HistoryPage = () => {

return (
<div className="mx-auto w-full space-y-6 md:max-w-2xl md:space-y-3">
<NavHeader title="History" />
<div className="w-full">
{data?.pages.map((page, pageIndex) => (
<div key={pageIndex}>
{data?.pages.map((page, pageIndex) => (
<div key={pageIndex}>
{page.items.map((item) => (
<div key={item.id} className="border-b border-n-1">
<ListItemView
id={item.id}
variant="history"
primaryInfo={{
title: item.transactionType,
}}
secondaryInfo={{
mainText: item.amount,
}}
metadata={{
tokenLogo:
item.transactionDetails.tokenSymbol === 'USDC'
? 'https://cryptologos.cc/logos/usd-coin-usdc-logo.png?v=040'
: undefined,
chainLogo:
item.transactionDetails.chain === 'Arbitrum One'
? ARBITRUM_ICON
: undefined,
subText: item.transactionDetails.date
? utils.formatDate(new Date(item.transactionDetails.date))
: '',
recipientAddress: item.recipientAddress,
transactionType: item.transactionType as TransactionType,
}}
details={item.transactionDetails}
/>
</div>
))}
</div>
))}
{!!data?.pages.length ? <NavHeader title="History" /> : null}
<div className="h-full w-full">
{!!data?.pages.length ? (
data?.pages.map((page, pageIndex) => (
<div key={pageIndex}>
{page.items.map((item) => (
<div key={item.id} className="border-b border-n-1">
<ListItemView
id={item.id}
variant="history"
primaryInfo={{
title: item.transactionType,
}}
secondaryInfo={{
mainText: item.amount,
}}
metadata={{
tokenLogo:
item.transactionDetails.tokenSymbol === 'USDC'
? 'https://cryptologos.cc/logos/usd-coin-usdc-logo.png?v=040'
: undefined,
chainLogo:
item.transactionDetails.chain === 'Arbitrum One'
? ARBITRUM_ICON
: undefined,
subText: item.transactionDetails.date
? formatDate(new Date(item.transactionDetails.date))
: '',
recipientAddress: item.recipientAddress,
transactionType: item.transactionType as TransactionType,
}}
details={item.transactionDetails}
/>
</div>
))}
</div>
))
) : (
<div className="flex h-full items-center justify-center">
<NoDataEmptyState
animSize="lg"
message="You haven't done any transactions"
cta={
<Link href="/home" className="cursor-pointer">
<Button shadowSize="4" size="medium" variant={'purple'} className="cursor-pointer">
Go to Dashboard
</Button>
</Link>
}
/>
</div>
))}
)}

<div ref={loaderRef} className="w-full py-4">
{isFetchingNextPage && <div className="w-full text-center">Loading more...</div>}
Expand Down
36 changes: 12 additions & 24 deletions src/app/(mobile-ui)/home/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client'

import { ArrowIcon, Button } from '@/components/0_Bruddle'
import { Button } from '@/components/0_Bruddle'
import { useToast } from '@/components/0_Bruddle/Toast'
import DirectionalActionButtons from '@/components/Global/DirectionalActionButtons'
import WalletHeader from '@/components/Global/WalletHeader'
import { WalletCard } from '@/components/Home/WalletCard'
import ProfileSection from '@/components/Profile/Components/ProfileSection'
Expand All @@ -15,7 +16,6 @@ import { walletActions } from '@/redux/slices/wallet-slice'
import { getUserPreferences, updateUserPreferences } from '@/utils'
import classNames from 'classnames'
import { motion, useAnimation } from 'framer-motion'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { useEffect, useRef, useState } from 'react'

Expand Down Expand Up @@ -200,28 +200,16 @@ export default function Home() {
)}
</div>

<div className="flex w-full flex-grow flex-row items-center justify-center gap-5 sm:justify-evenly md:mx-auto md:w-fit">
<Link href={'/send'}>
<Button
variant="purple"
shadowSize="4"
className="flex w-38 items-center gap-2 rounded-full transition-all ease-in-out active:scale-95"
>
<ArrowIcon />
<p className="text-base">Send</p>
</Button>
</Link>
<Link href={'/request/create'}>
<Button
variant="purple"
shadowSize="4"
className="flex w-38 items-center gap-2 rounded-full transition-all ease-in-out active:scale-95"
>
<ArrowIcon className="rotate-180" />
<p className="text-base">Receive</p>
</Button>
</Link>
</div>
<DirectionalActionButtons
leftButton={{
title: 'Send',
href: '/send',
}}
rightButton={{
title: 'Receive',
href: '/request/create',
}}
/>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(mobile-ui)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const Layout = ({ children }: { children: React.ReactNode }) => {

if (!isReady) return null
return (
<div className="flex h-[100dvh] flex-col bg-background md:flex-row-reverse">
<div className="flex min-h-[100dvh] flex-col bg-background md:flex-row-reverse">
<div
className={classNames('z-1 flex w-full flex-1 overflow-x-visible overflow-y-scroll', {
'p-6': !isHome,
Expand Down
174 changes: 110 additions & 64 deletions src/app/(mobile-ui)/wallet/page.tsx
Original file line number Diff line number Diff line change
@@ -1,81 +1,127 @@
'use client'

import smallPeanut from '@/assets/icons/small-peanut.png'
import { ArrowIcon, Button, Card } from '@/components/0_Bruddle'
import { Button } from '@/components/0_Bruddle'
import DirectionalActionButtons from '@/components/Global/DirectionalActionButtons'
import NoDataEmptyState from '@/components/Global/EmptyStates/NoDataEmptyState'
import Icon from '@/components/Global/Icon'
import { HomeLink } from '@/components/Home/HomeLink'
import { ListItemView } from '@/components/Global/ListItemView'
import NavHeader from '@/components/Global/NavHeader'
import { WalletCard } from '@/components/Home/WalletCard'
import { useAuth } from '@/context/authContext'
import { WalletProviderType } from '@/interfaces'
import { useWalletStore } from '@/redux/hooks'
import { printableUsdc } from '@/utils'
import { motion } from 'framer-motion'
import Link from 'next/link'
import { useWallet } from '@/hooks/wallet/useWallet'
import { IUserBalance, WalletProviderType } from '@/interfaces'
import { formatAmount, getChainName, getUserPreferences, updateUserPreferences } from '@/utils'
import { useAppKit, useDisconnect } from '@reown/appkit/react'
import { useState } from 'react'
import { twMerge } from 'tailwind-merge'

const WalletDetailsPage = () => {
const { focusedWallet, wallets } = useWalletStore()
const { user } = useAuth()
const { selectedWallet, isConnected } = useWallet()
const { open } = useAppKit()
const { disconnect } = useDisconnect()
const [isBalanceHidden, setIsBalanceHidden] = useState(() => {
const prefs = getUserPreferences()
return prefs?.balanceHidden ?? false
})

const walletDetails = wallets.find((wallet) => wallet.address === focusedWallet)
const { username } = useAuth()
const isActiveWalletPW = selectedWallet?.walletProviderType === WalletProviderType.PEANUT
const isActiveWalletBYOW = selectedWallet?.walletProviderType === WalletProviderType.BYOW

const isActiveWalletPW = walletDetails?.walletProviderType === WalletProviderType.PEANUT
const isActiveWalletBYOW = walletDetails?.walletProviderType === WalletProviderType.BYOW
console.log('selectedWallet', selectedWallet)

const handleToggleBalanceVisibility = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
setIsBalanceHidden((prev: boolean) => {
const newValue = !prev
updateUserPreferences({ balanceHidden: newValue })
return newValue
})
}

return (
<div className="flex w-full flex-row justify-center gap-2">
<div className="flex w-[100%] flex-col gap-4 sm:w-[90%] sm:gap-2 md:w-[70%] lg:w-[35%]">
{focusedWallet && (
<Card shadowSize="4" className="w-full rounded-md py-5">
<Card.Content className="flex h-full flex-row items-center justify-evenly">
<img src={smallPeanut.src} className="h-15 w-15 object-contain" />
{isActiveWalletPW && (
<p className="text-xl sm:text-2xl">
<span className="font-bold">{user?.user.username}</span>.peanut.wallet
</p>
)}
{isActiveWalletBYOW && (
<p className="text-xl sm:text-2xl">
<span className="font-bold">{walletDetails.address}</span>.peanut.wallet
</p>
)}
</Card.Content>
</Card>
<div className="mx-auto flex w-full flex-col gap-6 md:max-w-2xl">
<div className="md:hidden">
<NavHeader title="Wallet asset" />
</div>

<div className="mx-auto">
{selectedWallet && (
<WalletCard
key={selectedWallet.address}
type="wallet"
wallet={selectedWallet}
username={username ?? ''}
selected
onClick={() => {}}
index={0}
isBalanceHidden={isBalanceHidden}
onToggleBalanceVisibility={handleToggleBalanceVisibility}
/>
)}
</div>

<Card shadowSize="4" className="w-full rounded-md py-10">
<Card.Content className="flex h-full flex-row items-center justify-center">
<div className="text-5xl">$ {printableUsdc(walletDetails?.balance ?? 0n)}</div>
</Card.Content>
</Card>
<div className="flex flex-row gap-2">
<Button shadowSize="4">
<Link href="/cashout" className="flex flex-row items-center text-nowrap">
<div>
<Icon name="minus-circle" />
</div>
Cash out
</Link>
</Button>
<Button shadowSize="4" className="text-nowrap" disabled>
<DirectionalActionButtons
leftButton={{
title: 'Top up',
href: '/topup',
disabled: true,
}}
rightButton={{
title: 'Cash out',
href: '/cashout',
}}
/>

<div
className={twMerge(
selectedWallet?.balances && !!selectedWallet?.balances?.length ? 'border-b border-b-n-1' : ''
)}
>
{!!selectedWallet?.balances?.length ? (
<div className="space-y-3">
<div className="text-base font-semibold">Balance</div>
<div>
<Icon name="plus-circle" />
{selectedWallet.balances.map((balance: IUserBalance) => (
<ListItemView
key={`${balance.chainId}-${balance.symbol}`}
id={`${balance.chainId}-${balance.symbol}`}
variant="balance"
primaryInfo={{
title: balance.symbol,
}}
secondaryInfo={{
mainText: `$${Number(balance.value).toFixed(2)}`,
subText: getChainName(balance.chainId),
}}
metadata={{
tokenLogo: balance.logoURI,
subText: `${formatAmount(balance.amount)} ${balance.symbol}`,
}}
details={balance}
/>
))}
</div>
Top Up
</Button>
</div>
<div className="flex w-full flex-grow flex-row items-center justify-center gap-4 sm:justify-evenly sm:gap-8">
<motion.div className="flex flex-col items-center gap-2" whileTap={{ scale: 0.95 }}>
<HomeLink href={'/send'}>
<ArrowIcon />
</HomeLink>
<p className="text-base">Send</p>
</motion.div>
<motion.div className="flex flex-col items-center gap-2" whileTap={{ scale: 0.95 }}>
<HomeLink href={'/request/create'}>
<ArrowIcon className="rotate-180" />
</HomeLink>
<p>Recieve</p>
</motion.div>
</div>
</div>
) : (
<NoDataEmptyState message="No tokens found" />
)}
</div>
<div>
<Button
onClick={() => {
if (isConnected) {
disconnect()
} else {
open()
}
}}
variant="stroke"
className="flex w-full items-center justify-center gap-2 bg-purple-4/30 hover:bg-purple-4/20"
>
<Icon name={isConnected ? 'minus-circle' : 'plus-circle'} className="size-4" />
<div>{isConnected ? 'Disconnect' : 'Connect'}</div>
</Button>
</div>
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion src/components/0_Bruddle/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { forwardRef } from 'react'
import { twMerge } from 'tailwind-merge'
import Loading from '../Global/Loading'

type ButtonVariant = 'purple' | 'dark' | 'stroke' | 'transparent-light' | 'transparent-dark' | 'green' | 'yellow'
export type ButtonVariant = 'purple' | 'dark' | 'stroke' | 'transparent-light' | 'transparent-dark' | 'green' | 'yellow'
type ButtonSize = 'small' | 'medium' | 'large' | 'xl' | 'xl-fixed'
type ButtonShape = 'default' | 'square'
type ShadowSize = '4' | '6' | '8'
Expand Down
Loading

0 comments on commit 742e879

Please sign in to comment.