diff --git a/apps/portal/app/components/detail-info-card.tsx b/apps/portal/app/components/detail-info-card.tsx new file mode 100644 index 000000000..81a7bda9b --- /dev/null +++ b/apps/portal/app/components/detail-info-card.tsx @@ -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 { + 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 ( +
+ {list && ( +
+ + List + +
+ + + + + +
+
+ )} +
+ + Creator + +
+ + + + + + + + + +
+ + {link && ( + + + + )} +
+
+
+ + + {formattedDate} + +
+
+
+ ) +} + +export { DetailInfoCard } diff --git a/apps/portal/app/routes/app+/claim+/$id.tsx b/apps/portal/app/routes/app+/claim+/$id.tsx index 7bf0bd3c4..5dd782bae 100644 --- a/apps/portal/app/routes/app+/claim+/$id.tsx +++ b/apps/portal/app/routes/app+/claim+/$id.tsx @@ -4,7 +4,6 @@ import { ClaimStakeCard, Icon, Identity, - InfoCard, PieChartVariant, PositionCard, PositionCardLastUpdated, @@ -21,6 +20,7 @@ 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' @@ -28,6 +28,7 @@ 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, @@ -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' @@ -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 @@ -285,8 +289,14 @@ export default function ClaimDetails() { } /> )} - { - navigate(`/app/profile/${claim.creator?.wallet}`) - }} - className="hover:cursor-pointer w-full" + className="w-full" /> ) diff --git a/apps/portal/app/routes/app+/identity+/$id.tsx b/apps/portal/app/routes/app+/identity+/$id.tsx index 3c6b1fdf8..dc639eeed 100644 --- a/apps/portal/app/routes/app+/identity+/$id.tsx +++ b/apps/portal/app/routes/app+/identity+/$id.tsx @@ -4,7 +4,6 @@ import { Banner, Icon, Identity, - InfoCard, PieChartVariant, PositionCard, PositionCardLastUpdated, @@ -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' @@ -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, @@ -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' @@ -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) { @@ -97,6 +118,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) { logger('[$ID] -- END') return json({ identity, + list, isPending, vaultDetails, userWallet, @@ -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(['attest', 'create']) const navigate = useNavigate() const { user_assets, assets_sum } = vaultDetails ? vaultDetails : identity @@ -236,8 +255,9 @@ export default function IdentityDetails() { /> )} -