Skip to content

Commit

Permalink
Added navigation arrows to the transaction page (#552)
Browse files Browse the repository at this point in the history
* chore: added changeset

* feat: Add tooltips to NavArrows component

* refactor: Update tooltip text for NavArrows component
  • Loading branch information
luis-herasme authored Sep 5, 2024
1 parent 1bbf650 commit 253f293
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/six-bees-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/web": patch
---

Added navigation arrows to the transaction page
29 changes: 26 additions & 3 deletions apps/web/src/components/NavArrows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,35 @@ import { useRouter } from "next/router";
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/outline";

import { IconButton } from "./IconButton";
import { Tooltip, TooltipContent, TooltipTrigger } from "./Tooltip";

export function NavArrows({ next, prev }: { next?: string; prev?: string }) {
export function NavArrows({
next,
prev,
}: {
next: {
href?: string;
tooltip?: string;
};
prev: {
href?: string;
tooltip?: string;
};
}) {
return (
<div className="flex items-center justify-center gap-1">
<NavArrow type="prev" href={prev} />
<NavArrow type="next" href={next} />
<Tooltip>
<TooltipTrigger>
<NavArrow type="prev" href={prev.href} />
</TooltipTrigger>
<TooltipContent>{prev.tooltip || "Previous"}</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger>
<NavArrow type="next" href={next.href} />
</TooltipTrigger>
<TooltipContent>{next.tooltip || "Next"}</TooltipContent>
</Tooltip>
</div>
);
}
Expand Down
24 changes: 14 additions & 10 deletions apps/web/src/pages/block/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,20 @@ const Block: NextPage = function () {
{blockData.number}
{blockNumber !== undefined && (
<NavArrows
prev={
getFirstBlobNumber() < blockNumber
? `/block_neighbor?blockNumber=${blockNumber}&direction=prev`
: undefined
}
next={
latestBlock && blockNumber < latestBlock.number
? `/block_neighbor?blockNumber=${blockNumber}&direction=next`
: undefined
}
prev={{
tooltip: "Previous Block",
href:
getFirstBlobNumber() < blockNumber
? `/block_neighbor?blockNumber=${blockNumber}&direction=prev`
: undefined,
}}
next={{
tooltip: "Next Block",
href:
latestBlock && blockNumber < latestBlock.number
? `/block_neighbor?blockNumber=${blockNumber}&direction=next`
: undefined,
}}
/>
)}
</div>
Expand Down
34 changes: 33 additions & 1 deletion apps/web/src/pages/tx/[hash].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { StandardEtherUnitDisplay } from "~/components/Displays/StandardEtherUni
import { DetailsLayout } from "~/components/Layouts/DetailsLayout";
import type { DetailsLayoutProps } from "~/components/Layouts/DetailsLayout";
import { Link } from "~/components/Link";
import { NavArrows } from "~/components/NavArrows";
import { BlockStatus } from "~/components/Status";
import { api } from "~/api-client";
import NextError from "~/pages/_error";
Expand Down Expand Up @@ -45,6 +46,23 @@ const Tx: NextPage = () => {
return deserializeFullTransaction(rawTxData);
}, [rawTxData]);

const { data: neighbors } = api.tx.getTxNeighbors.useQuery(
tx
? {
senderAddress: tx.from,
blockNumber: tx.blockNumber,
index: tx.index,
}
: {
senderAddress: "",
blockNumber: 0,
index: 0,
},
{
enabled: Boolean(tx),
}
);

if (error) {
return (
<NextError
Expand Down Expand Up @@ -212,7 +230,21 @@ const Tx: NextPage = () => {
return (
<>
<DetailsLayout
header="Transaction Details"
header={
<div className="flex items-center justify-start gap-4">
Transaction Details
<NavArrows
prev={{
href: neighbors?.prev ? `/tx/${neighbors.prev}` : undefined,
tooltip: "Previous transaction from this sender",
}}
next={{
href: neighbors?.next ? `/tx/${neighbors.next}` : undefined,
tooltip: "Next transaction from this sender",
}}
/>
</div>
}
externalLink={tx ? buildTransactionExternalUrl(tx.hash) : undefined}
fields={detailsFields}
/>
Expand Down
81 changes: 81 additions & 0 deletions packages/api/src/routers/tx/getNextTxFromSender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { prisma } from "@blobscan/db";
import { z } from "@blobscan/zod";

import { publicProcedure } from "../../procedures";

const txNeighborSchema = z.object({
senderAddress: z.string(),
blockNumber: z.number(),
index: z.number().nullable(),
});

type TxNeighborInput = z.infer<typeof txNeighborSchema>;

export const getTxNeighborsProcedure = publicProcedure
.input(txNeighborSchema)
.query<TxNeighbors>(({ input }) => getTxNeighbors(input));

type TxNeighbors = {
next: string | null;
prev: string | null;
};

async function getTxNeighbors(input: TxNeighborInput): Promise<TxNeighbors> {
const [next, prev] = await Promise.all([
getTxNeighbor(input, "next"),
getTxNeighbor(input, "prev"),
]);

return {
next,
prev,
};
}

async function getTxNeighbor(
input: TxNeighborInput,
direction: "next" | "prev"
): Promise<string | null> {
const operator = direction === "next" ? "gt" : "lt";

const tx = await prisma.transaction.findFirst({
select: {
hash: true,
},
where: {
fromId: input.senderAddress,
OR:
input.index !== null
? [
{
blockNumber: {
[operator]: input.blockNumber,
},
},
{
blockNumber: input.blockNumber,
index: {
[operator]: input.index,
},
},
]
: [
{
blockNumber: {
[operator]: input.blockNumber,
},
},
],
},
orderBy:
direction === "next"
? [{ blockNumber: "asc" }, { index: "asc" }]
: [{ blockNumber: "desc" }, { index: "desc" }],
});

if (!tx) {
return null;
}

return tx.hash;
}
2 changes: 2 additions & 0 deletions packages/api/src/routers/tx/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { t } from "../../trpc-client";
import { getAll } from "./getAll";
import { getByHash } from "./getByHash";
import { getTxNeighborsProcedure } from "./getNextTxFromSender";

export const transactionRouter = t.router({
getAll,
getByHash,
getTxNeighbors: getTxNeighborsProcedure,
});

0 comments on commit 253f293

Please sign in to comment.