Skip to content

Commit

Permalink
ENG-3859 feat(portal): better navigation between list details list id…
Browse files Browse the repository at this point in the history
…entity and tag claim (#822)

## Affected Packages

Apps

- [x] portal

Packages

- [ ] 1ui
- [ ] api
- [ ] protocol
- [ ] sdk

Tools

- [ ] tools

## Overview

This adds navigation elements to detail pages which link to any
associated lists. This might change a bit after we make some
modifications to lists, but in the meantime, this'll do.

## Screen Captures

If applicable, add screenshots or screen captures of your changes.

## Declaration

- [x] I hereby declare that I have abided by the rules and regulations
as outlined in the
[CONTRIBUTING.md](https://github.com/0xIntuition/intuition-ts/blob/main/CONTRIBUTING.md)

 
 **PR Summary by Typo**
------------

 **Summary**
This pull request introduces a new `DetailInfoCard` component and
updates imports in various files. It replaces `InfoCard` with
`DetailInfoCard` in some components and adds new properties and imports.

**Key Points**

1. New `DetailInfoCard` component added in
`apps/portal/app/components/detail-info-card.tsx`
2. Replaces `InfoCard` with `DetailInfoCard` in `ClaimDetails` and
imports new dependencies
3. Updates `IdentityLoaderData` interface and `useLiveLoader` hook to
load `DetailInfoCard` and new `list` property.

<h6>To turn off PR summary, please visit <a
href="https://app.typoapp.io/settings/dev-analytics/notification?tab=codeHealth">Notification
settings</a>.</h6>
  • Loading branch information
Vitalsine85 authored Sep 5, 2024
1 parent 2af07ea commit 4647685
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 20 deletions.
133 changes: 133 additions & 0 deletions apps/portal/app/components/detail-info-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import {
Button,
ButtonVariant,
cn,
HoverCard,
HoverCardContent,
HoverCardTrigger,
Icon,
Identity,
IdentityTag,
IdentityType,
ProfileCard,
Text,
TextVariant,
Trunctacular,
} from '@0xintuition/1ui'
import { ClaimPresenter } from '@0xintuition/api'

import { PATHS } from '@consts/paths'

export interface DetailInfoCardProps
extends React.HTMLAttributes<HTMLDivElement> {
variant: IdentityType
list?: ClaimPresenter
username: string
avatarImgSrc: string
id: string
description: string
link: string
ipfsLink: string
timestamp: string
}

const DetailInfoCard = ({
variant = Identity.user,
list,
username,
avatarImgSrc,
id,
description,
link,
ipfsLink,
timestamp,
className,
...props
}: DetailInfoCardProps) => {
const formattedDate = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(new Date(timestamp))

return (
<div
className={cn(
`flex flex-col gap-5 theme-border p-5 rounded-lg max-sm:items-center`,
className,
)}
{...props}
>
{list && (
<div>
<Text variant={TextVariant.caption} className="text-muted-foreground">
List
</Text>
<div className="flex justify-start items-center gap-1">
<a href={`${PATHS.LIST}/${list.claim_id}`}>
<IdentityTag
variant={list.object?.user ? Identity.user : Identity.nonUser}
imgSrc={list.object?.image ?? ''}
>
<Trunctacular
value={
list.object?.user_display_name ??
list.object?.display_name ??
'Unknown'
}
maxStringLength={32}
/>
</IdentityTag>
</a>
</div>
</div>
)}
<div>
<Text variant={TextVariant.caption} className="text-muted-foreground">
Creator
</Text>
<div className="flex justify-start items-center gap-1">
<HoverCard openDelay={150} closeDelay={150}>
<HoverCardTrigger>
<a href={link}>
<IdentityTag variant={variant} imgSrc={avatarImgSrc}>
<Trunctacular value={username} maxStringLength={18} />
</IdentityTag>
</a>
</HoverCardTrigger>
<HoverCardContent side="right" className="w-max">
<div className="flex flex-col gap-4 w-80 max-md:w-[80%]">
<ProfileCard
variant={variant}
avatarSrc={avatarImgSrc ?? ''}
name={username}
id={id ?? ''}
bio={description ?? ''}
ipfsLink={ipfsLink}
className="profile-card"
/>
{link && (
<a href={link}>
<Button
variant={ButtonVariant.secondary}
className="w-full"
>
View Identity{' '}
<Icon name={'arrow-up-right'} className="h-3 w-3" />
</Button>
</a>
)}
</div>
</HoverCardContent>
</HoverCard>
<span className="bg-muted-foreground h-[2px] w-[2px] block rounded-full" />
<Text variant={TextVariant.body} className="text-muted-foreground">
{formattedDate}
</Text>
</div>
</div>
</div>
)
}

export { DetailInfoCard }
27 changes: 17 additions & 10 deletions apps/portal/app/routes/app+/claim+/$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
ClaimStakeCard,
Icon,
Identity,
InfoCard,
PieChartVariant,
PositionCard,
PositionCardLastUpdated,
Expand All @@ -21,13 +20,15 @@ import {
SortDirection,
} from '@0xintuition/api'

import { DetailInfoCard } from '@components/detail-info-card'
import { ErrorPage } from '@components/error-page'
import NavigationButton from '@components/navigation-link'
import StakeModal from '@components/stake/stake-modal'
import { useGoBack } from '@lib/hooks/useGoBack'
import { useLiveLoader } from '@lib/hooks/useLiveLoader'
import { getClaimOrPending } from '@lib/services/claims'
import { stakeModalAtom } from '@lib/state/store'
import { getSpecialPredicate } from '@lib/utils/app'
import {
calculatePercentageOfTvl,
formatBalance,
Expand All @@ -39,10 +40,15 @@ import {
invariant,
} from '@lib/utils/misc'
import { json, LoaderFunctionArgs } from '@remix-run/node'
import { Outlet, useNavigate } from '@remix-run/react'
import { Outlet } from '@remix-run/react'
import { requireUserWallet } from '@server/auth'
import { getVaultDetails } from '@server/multivault'
import { BLOCK_EXPLORER_URL, NO_WALLET_ERROR, PATHS } from 'app/consts'
import {
BLOCK_EXPLORER_URL,
CURRENT_ENV,
NO_WALLET_ERROR,
PATHS,
} from 'app/consts'
import TwoPanelLayout from 'app/layouts/two-panel-layout'
import { VaultDetailsType } from 'app/types/vault'
import { useAtom } from 'jotai'
Expand Down Expand Up @@ -108,8 +114,6 @@ export default function ClaimDetails() {
vaultDetails: VaultDetailsType
isPending: boolean
}>(['create', 'attest'])
const navigate = useNavigate()

const [stakeModalActive, setStakeModalActive] = useAtom(stakeModalAtom)

const direction: 'for' | 'against' = isPending
Expand Down Expand Up @@ -285,8 +289,14 @@ export default function ClaimDetails() {
}
/>
)}
<InfoCard
<DetailInfoCard
variant={Identity.user}
list={
claim?.predicate?.id ===
getSpecialPredicate(CURRENT_ENV).tagPredicate.id
? claim
: undefined
}
username={claim.creator?.display_name ?? '?'}
avatarImgSrc={claim.creator?.image ?? ''}
id={claim.creator?.wallet ?? ''}
Expand All @@ -296,10 +306,7 @@ export default function ClaimDetails() {
}
ipfsLink={`${BLOCK_EXPLORER_URL}/address/${claim.creator?.wallet}`}
timestamp={claim.created_at}
onClick={() => {
navigate(`/app/profile/${claim.creator?.wallet}`)
}}
className="hover:cursor-pointer w-full"
className="w-full"
/>
</div>
)
Expand Down
40 changes: 30 additions & 10 deletions apps/portal/app/routes/app+/identity+/$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
Banner,
Icon,
Identity,
InfoCard,
PieChartVariant,
PositionCard,
PositionCardLastUpdated,
Expand All @@ -18,8 +17,14 @@ import {
TagsContent,
TagWithValue,
} from '@0xintuition/1ui'
import { IdentityPresenter, TagEmbeddedPresenter } from '@0xintuition/api'
import {
ClaimPresenter,
ClaimsService,
IdentityPresenter,
TagEmbeddedPresenter,
} from '@0xintuition/api'

import { DetailInfoCard } from '@components/detail-info-card'
import { ErrorPage } from '@components/error-page'
import NavigationButton from '@components/navigation-link'
import ImageModal from '@components/profile/image-modal'
Expand All @@ -34,6 +39,7 @@ import {
stakeModalAtom,
tagsModalAtom,
} from '@lib/state/store'
import { getSpecialPredicate } from '@lib/utils/app'
import logger from '@lib/utils/logger'
import {
calculatePercentageOfTvl,
Expand All @@ -51,12 +57,12 @@ import { requireUser, requireUserWallet } from '@server/auth'
import { getVaultDetails } from '@server/multivault'
import {
BLOCK_EXPLORER_URL,
CURRENT_ENV,
MULTIVAULT_CONTRACT_ADDRESS,
NO_WALLET_ERROR,
PATHS,
} from 'app/consts'
import TwoPanelLayout from 'app/layouts/two-panel-layout'
import { ExtendedIdentityPresenter } from 'app/types/identity'
import { VaultDetailsType } from 'app/types/vault'
import { useAtom } from 'jotai'

Expand All @@ -79,6 +85,21 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
throw new Response('Not Found', { status: 404 })
}

let list: ClaimPresenter | null = null

try {
const listResult = await ClaimsService.searchClaims({
predicate: getSpecialPredicate(CURRENT_ENV).tagPredicate.id,
object: identity.id,
})

if (listResult && listResult.data.length > 0) {
list = listResult.data[0]
}
} catch (error) {
logger('Failed to fetch list:', error)
}

let vaultDetails: VaultDetailsType | null = null

if (!!identity && identity.vault_id) {
Expand All @@ -97,6 +118,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
logger('[$ID] -- END')
return json({
identity,
list,
isPending,
vaultDetails,
userWallet,
Expand All @@ -105,18 +127,15 @@ export async function loader({ request, params }: LoaderFunctionArgs) {

export interface IdentityLoaderData {
identity: IdentityPresenter
list: ClaimPresenter
vaultDetails: VaultDetailsType
userWallet: string
isPending: boolean
}

export default function IdentityDetails() {
const { identity, vaultDetails, userWallet, isPending } = useLiveLoader<{
identity: ExtendedIdentityPresenter
vaultDetails: VaultDetailsType
userWallet: string
isPending: boolean
}>(['attest', 'create'])
const { identity, list, vaultDetails, userWallet, isPending } =
useLiveLoader<IdentityLoaderData>(['attest', 'create'])
const navigate = useNavigate()

const { user_assets, assets_sum } = vaultDetails ? vaultDetails : identity
Expand Down Expand Up @@ -236,8 +255,9 @@ export default function IdentityDetails() {
/>
</>
)}
<InfoCard
<DetailInfoCard
variant={Identity.user}
list={list}
username={identity.creator?.display_name ?? '?'}
avatarImgSrc={identity.creator?.image ?? ''}
id={identity.creator?.wallet ?? ''}
Expand Down

0 comments on commit 4647685

Please sign in to comment.