generated from t3-oss/create-t3-turbo
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #44 from ArkProjectNFTs/yohan/activity
feat: token activity with infinite scroll
- Loading branch information
Showing
13 changed files
with
315 additions
and
215 deletions.
There are no files selected for viewing
100 changes: 100 additions & 0 deletions
100
...arkmarket/src/app/token/[contractAddress]/[tokenId]/components/desktop-token-activity.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { | ||
ArrowLeftRight, | ||
CircleDot, | ||
Gavel, | ||
List, | ||
ListX, | ||
Meh, | ||
ShoppingCart, | ||
Tag, | ||
X, | ||
} from "lucide-react"; | ||
|
||
import type { PropsWithClassName } from "@ark-market/ui"; | ||
import { shortAddress, timeSince } from "@ark-market/ui"; | ||
import { PriceTag } from "@ark-market/ui/price-tag"; | ||
import { | ||
Table, | ||
TableBody, | ||
TableCell, | ||
TableHead, | ||
TableHeader, | ||
TableRow, | ||
} from "@ark-market/ui/table"; | ||
|
||
import type { TokenActivity } from "../queries/getTokenData"; | ||
|
||
export const activityTypeToItem = new Map([ | ||
["FULFILL", { icon: <ShoppingCart size={24} />, title: "Sale in progress" }], | ||
["EXECUTED", { icon: <ShoppingCart size={24} />, title: "Sale" }], | ||
["SALE", { icon: <ShoppingCart size={24} />, title: "Sale" }], | ||
["TRANSFER", { icon: <ArrowLeftRight size={24} />, title: "Transfer" }], | ||
["LISTING", { icon: <List size={24} />, title: "List" }], | ||
["OFFER", { icon: <Tag size={24} />, title: "Offer" }], | ||
["CANCELLED", { icon: <X size={24} />, title: "Cancel Offer" }], | ||
["MINT", { icon: <CircleDot size={24} />, title: "Mint" }], | ||
["AUCTION", { icon: <Gavel size={24} />, title: "Put in auction" }], | ||
["DELISTING", { icon: <ListX size={24} />, title: "Delist" }], | ||
]); | ||
|
||
interface DesktopTokenActivityProps { | ||
tokenActivity: TokenActivity[]; | ||
} | ||
|
||
export default function DesktopTokenActivity({ | ||
className, | ||
tokenActivity, | ||
}: PropsWithClassName<DesktopTokenActivityProps>) { | ||
return ( | ||
<Table className={className}> | ||
<TableHeader> | ||
<TableRow className="hover:bg-background"> | ||
<TableHead className="pl-5">Event</TableHead> | ||
<TableHead>Price</TableHead> | ||
<TableHead>From</TableHead> | ||
<TableHead>To</TableHead> | ||
<TableHead>Date</TableHead> | ||
</TableRow> | ||
</TableHeader> | ||
{tokenActivity.length === 0 ? ( | ||
<TableBody className="table-caption"> | ||
<div className="flex flex-col items-center gap-3 pt-10 text-muted-foreground"> | ||
<Meh size={42} /> | ||
<p className="text-xl font-semibold">No activity yet!</p> | ||
</div> | ||
</TableBody> | ||
) : ( | ||
<TableBody className="text-sm font-semibold"> | ||
{tokenActivity.map((activity, index) => { | ||
const activityItem = activityTypeToItem.get(activity.activity_type); | ||
|
||
return ( | ||
<TableRow className="group h-[4.6875rem]" key={index}> | ||
<TableCell className="pl-5 transition-colors group-hover:text-muted-foreground"> | ||
<div className="flex items-center gap-4 whitespace-nowrap"> | ||
{activityItem?.icon} | ||
<p>{activityItem?.title}</p> | ||
</div> | ||
</TableCell> | ||
<TableCell> | ||
{activity.price !== null ? ( | ||
<PriceTag price={activity.price} /> | ||
) : ( | ||
"_" | ||
)} | ||
</TableCell> | ||
<TableCell> | ||
{activity.from ? shortAddress(activity.from) : "_"} | ||
</TableCell> | ||
<TableCell> | ||
{activity.to ? shortAddress(activity.to) : "_"} | ||
</TableCell> | ||
<TableCell>{timeSince(activity.time_stamp)}</TableCell> | ||
</TableRow> | ||
); | ||
})} | ||
</TableBody> | ||
)} | ||
</Table> | ||
); | ||
} |
142 changes: 50 additions & 92 deletions
142
.../arkmarket/src/app/token/[contractAddress]/[tokenId]/components/mobile-token-activity.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,67 @@ | ||
import { Fragment } from "react"; | ||
import { | ||
ArrowLeftRight, | ||
List, | ||
ListX, | ||
ShoppingCart, | ||
Tag, | ||
X, | ||
} from "lucide-react"; | ||
import { Meh } from "lucide-react"; | ||
|
||
import type { PropsWithClassName } from "@ark-market/ui"; | ||
import { cn } from "@ark-market/ui"; | ||
import { shortAddress, timeSince } from "@ark-market/ui"; | ||
import { PriceTag } from "@ark-market/ui/price-tag"; | ||
import { Separator } from "@ark-market/ui/separator"; | ||
|
||
const activityTypeToItem = new Map([ | ||
["sale", { icon: <ShoppingCart size={20} />, title: "Sale" }], | ||
["transfer", { icon: <ArrowLeftRight size={20} />, title: "Transfer" }], | ||
["list", { icon: <List size={20} />, title: "List" }], | ||
["offer", { icon: <Tag size={20} />, title: "Offer" }], | ||
["cancel_offer", { icon: <X size={20} />, title: "Cancel Offer" }], | ||
["delist", { icon: <ListX size={20} />, title: "Delist" }], | ||
]); | ||
import type { TokenActivity } from "../queries/getTokenData"; | ||
import { activityTypeToItem } from "./desktop-token-activity"; | ||
|
||
const activityData = [ | ||
{ | ||
type: "transfer", | ||
from: "0x123", | ||
to: "0x456", | ||
}, | ||
{ | ||
type: "list", | ||
price: 1180000000000000000n, | ||
from: "0x123", | ||
}, | ||
{ | ||
type: "offer", | ||
price: 1840000000000000000n, | ||
from: "0x123", | ||
to: "0x456", | ||
}, | ||
{ | ||
type: "cancel_offer", | ||
price: 1540000000000000000n, | ||
from: "0x123", | ||
to: "0x456", | ||
}, | ||
{ | ||
type: "delist", | ||
price: 3240000000000000000n, | ||
from: "0x123", | ||
}, | ||
{ | ||
type: "sale", | ||
price: 1140000000000000000n, | ||
from: "0x123", | ||
to: "0x456", | ||
}, | ||
]; | ||
interface MobileTokenActivityProps { | ||
tokenActivity: TokenActivity[]; | ||
} | ||
|
||
export default function MobileTokenActivity({ className }: PropsWithClassName) { | ||
export default function MobileTokenActivity({ | ||
className, | ||
tokenActivity, | ||
}: PropsWithClassName<MobileTokenActivityProps>) { | ||
return ( | ||
<div className={cn("", className)}> | ||
<div className="flex items-center gap-4"> | ||
<h2 className="text-2xl font-semibold">Activity</h2> | ||
<div className="flex h-6 items-center rounded-full bg-secondary px-3 text-sm font-medium text-secondary-foreground"> | ||
{activityData.length} | ||
</div> | ||
</div> | ||
<div className={className}> | ||
<p className="text-sm font-semibold text-muted-foreground">Event</p> | ||
<Separator className="my-4" /> | ||
|
||
<div className="mt-6"> | ||
<p className="text-sm font-semibold text-muted-foreground">Event</p> | ||
<Separator className="my-4" /> | ||
{tokenActivity.length === 0 && ( | ||
<div className="flex flex-col items-center gap-3 py-10 text-muted-foreground"> | ||
<Meh size={42} /> | ||
<p className="text-xl font-semibold">No activity yet!</p> | ||
</div> | ||
)} | ||
|
||
{activityData.map((activity, index) => { | ||
const activityItem = activityTypeToItem.get(activity.type); | ||
{tokenActivity.map((activity, index) => { | ||
const activityItem = activityTypeToItem.get(activity.activity_type); | ||
|
||
return ( | ||
<Fragment key={index}> | ||
<div className="flex flex-col gap-2"> | ||
<div className="flex items-center justify-between"> | ||
<div className="flex items-center gap-2.5"> | ||
{activityItem?.icon} | ||
<p>{activityItem?.title}</p> | ||
</div> | ||
{activity.price !== undefined ? ( | ||
<PriceTag price={activity.price} className="h-7 text-xs" /> | ||
) : ( | ||
"_" | ||
)} | ||
</div> | ||
<div className="flex items-center justify-between text-sm font-semibold"> | ||
<p> | ||
by{" "} | ||
<span className="text-muted-foreground"> | ||
{activity.from}{" "} | ||
</span> | ||
</p> | ||
<p className="text-xs text-muted-foreground">8min ago</p> | ||
return ( | ||
<Fragment key={index}> | ||
<div className="flex flex-col gap-2"> | ||
<div className="flex items-center justify-between"> | ||
<div className="flex items-center gap-2.5"> | ||
{activityItem?.icon} | ||
<p>{activityItem?.title}</p> | ||
</div> | ||
{activity.price !== null ? ( | ||
<PriceTag price={activity.price} className="h-7 text-xs" /> | ||
) : ( | ||
"_" | ||
)} | ||
</div> | ||
<div className="flex items-center justify-between text-sm font-semibold"> | ||
<p> | ||
by{" "} | ||
<span className="text-muted-foreground"> | ||
{activity.from ? shortAddress(activity.from) : "_"} | ||
</span> | ||
</p> | ||
<p className="text-xs text-muted-foreground"> | ||
{timeSince(activity.time_stamp)} | ||
</p> | ||
</div> | ||
<Separator className="my-4" /> | ||
</Fragment> | ||
); | ||
})} | ||
</div> | ||
</div> | ||
<Separator className="my-4" /> | ||
</Fragment> | ||
); | ||
})} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.