Skip to content

Commit 75bbd91

Browse files
committed
search
1 parent 2a7d67d commit 75bbd91

File tree

5 files changed

+186
-73
lines changed

5 files changed

+186
-73
lines changed

src/app/address/[id]/page.tsx

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"use client";
2+
3+
import React from "react";
4+
5+
import { Card, CardBody } from "@nextui-org/react";
6+
import { redirect, useParams } from "next/navigation";
7+
import {
8+
block_by_hash,
9+
evm_contract_by_id,
10+
extrinsic_by_hash,
11+
transfer_by_hash,
12+
Result,
13+
select,
14+
} from "@/graphql/queries";
15+
import { HashLoader } from "react-spinners";
16+
17+
function Page() {
18+
let id: any = useParams().id;
19+
console.log(id);
20+
let result: Result<any> | undefined = select([
21+
block_by_hash(id),
22+
transfer_by_hash(id),
23+
evm_contract_by_id(id),
24+
extrinsic_by_hash(id),
25+
] as any);
26+
console.log(result);
27+
if (result === undefined) {
28+
return (
29+
<div className="px-20 mt-6">
30+
<Card>
31+
<CardBody> unfortunately there are no results</CardBody>
32+
</Card>
33+
</div>
34+
);
35+
}
36+
switch (result.state) {
37+
case "loading":
38+
return (
39+
<HashLoader
40+
size={150}
41+
style={{ alignContent: "center" }}
42+
color={"#00A3E4"}
43+
/>
44+
);
45+
case "error":
46+
return (
47+
<Card>we had an error processing your request: {result.message}</Card>
48+
);
49+
case "ok":
50+
}
51+
console.log(result);
52+
switch ((result.data as any).__typename) {
53+
case "Block":
54+
console.log("ZOOM!");
55+
return redirect(`/blocks/${id}`);
56+
case "Transfer":
57+
return redirect(`/tx/${id}`);
58+
case "EvmContract":
59+
return redirect(`/evm/contracts/${id}`);
60+
case "Extrinsic":
61+
return redirect(`/extrinsics/${id}`);
62+
}
63+
return <></>;
64+
}
65+
66+
export default Page;

src/app/extrinsics/[id]/page.tsx

+41-26
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,19 @@ import { useParams } from "next/navigation";
88
import timeAgo from "@/lib/ConvertTime";
99
import { Card, CardBody } from "@nextui-org/react";
1010
import { CheckCircle, Copy, XCircle } from "lucide-react";
11-
import { get_extrinsic_by_hash } from "@/graphql/queries";
11+
import { extrinsic_by_hash } from "@/graphql/queries";
1212
import { Extrinsic } from "@/graphql/types";
1313
import truncateMiddle from "@/lib/TruncateMiddle";
1414

1515
export default function ExtrinsicPage() {
1616
const params: any = useParams().id;
17-
const result = get_extrinsic_by_hash(params);
17+
const result = extrinsic_by_hash(params);
1818
let extrinsic: Extrinsic;
1919
switch (result.state) {
20-
case "loading": return <p>loading</p>
21-
case "error": return <p>error</p>
20+
case "loading":
21+
return <p>loading</p>;
22+
case "error":
23+
return <p>error</p>;
2224
case "ok": {
2325
if (result.data) extrinsic = result.data;
2426
else return <p>incorrect id</p>;
@@ -28,10 +30,17 @@ export default function ExtrinsicPage() {
2830
return (
2931
<div className="px-4 sm:px-20 md:px-60 lg:px-80">
3032
<div className="flex items-center">
31-
<span className="text-2xl w-[7ch]">Extrinsic</span><span className="text-sel_blue">
32-
<Link href={`/blocks/${extrinsic.blockNumber}`}>#{extrinsic.blockNumber}</Link>
33+
<span className="text-2xl w-[7ch]">Extrinsic</span>
34+
<span className="text-sel_blue">
35+
<Link href={`/blocks/${extrinsic.blockNumber}`}>
36+
#{extrinsic.blockNumber}
37+
</Link>
3338
</span>
34-
{extrinsic.success ? (<CheckCircle className="m-2" color="green" size="32px" />) : (<XCircle className="m-2" color="red" size="32px" />)}
39+
{extrinsic.success ? (
40+
<CheckCircle className="m-2" color="green" size="32px" />
41+
) : (
42+
<XCircle className="m-2" color="red" size="32px" />
43+
)}
3544
</div>
3645
<Card>
3746
<CardBody>
@@ -60,9 +69,7 @@ export default function ExtrinsicPage() {
6069
color="gray"
6170
className="cursor-pointer"
6271
onClick={() =>
63-
navigator.clipboard.writeText(
64-
extrinsic.extrinsicHash
65-
)
72+
navigator.clipboard.writeText(extrinsic.extrinsicHash)
6673
}
6774
/>
6875
</span>
@@ -96,22 +103,30 @@ export default function ExtrinsicPage() {
96103
</td>
97104
</tr> */}
98105

99-
{extrinsic.fee ? <tr className="bg-white border-b">
100-
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
101-
Fee
102-
</td>
103-
<td className=" text-sm font-light px-6 py-4 whitespace-nowrap">
104-
{extrinsic.fee}
105-
</td>
106-
</tr> : <></>}
107-
{extrinsic.tip ? <tr className="bg-white border-b">
108-
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
109-
Tip
110-
</td>
111-
<td className="text-sm font-light px-6 py-4 whitespace-nowrap">
112-
{extrinsic.tip}
113-
</td>
114-
</tr> : <></>}
106+
{extrinsic.fee ? (
107+
<tr className="bg-white border-b">
108+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
109+
Fee
110+
</td>
111+
<td className=" text-sm font-light px-6 py-4 whitespace-nowrap">
112+
{extrinsic.fee}
113+
</td>
114+
</tr>
115+
) : (
116+
<></>
117+
)}
118+
{extrinsic.tip ? (
119+
<tr className="bg-white border-b">
120+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
121+
Tip
122+
</td>
123+
<td className="text-sm font-light px-6 py-4 whitespace-nowrap">
124+
{extrinsic.tip}
125+
</td>
126+
</tr>
127+
) : (
128+
<></>
129+
)}
115130
{/* <tr className="bg-white border-b">
116131
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
117132
Signer Public key

src/components/SearchInput.tsx

+22-37
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1-
import {
2-
Button,
3-
Dropdown,
4-
DropdownItem,
5-
DropdownMenu,
6-
DropdownTrigger,
7-
Input,
8-
} from "@nextui-org/react";
9-
import { ChevronDown, Search } from "lucide-react";
10-
import React from "react";
1+
import { Button, Input } from "@nextui-org/react";
2+
import { Search } from "lucide-react";
3+
import { RedirectType, redirect } from "next/navigation";
4+
import React, { useState } from "react";
115

126
function SearchInput() {
7+
let [shr, sr] = useState(false);
8+
let [txt, st] = useState("");
9+
if (shr && txt && /^(?:0x)?[a-f0-9]+/.test(txt))
10+
redirect(`/address/${txt}`, RedirectType.push);
1311
return (
1412
<Input
1513
type="text"
16-
placeholder="Search by Address / Txn Hash / Block / Token / Ens"
14+
placeholder="Search by Address / Txn Hash / Block / Token"
1715
labelPlacement="outside"
1816
size="lg"
1917
radius="md"
@@ -23,33 +21,20 @@ function SearchInput() {
2321
inputWrapper: ["px-1"],
2422
}}
2523
fullWidth={true}
26-
startContent={
27-
<>
28-
<Dropdown placement="bottom-start">
29-
<DropdownTrigger>
30-
<Button className="capitalize pl-6 bg-transparent border-r-2">
31-
Filter
32-
<span>
33-
<ChevronDown />
34-
</span>
35-
</Button>
36-
</DropdownTrigger>
37-
<DropdownMenu
38-
aria-label="Single selection example"
39-
variant="flat"
40-
disallowEmptySelection
41-
>
42-
<DropdownItem key="text">Addresses</DropdownItem>
43-
<DropdownItem key="number">Tokens</DropdownItem>
44-
<DropdownItem key="date">Name Tags</DropdownItem>
45-
<DropdownItem key="single_date">Label</DropdownItem>
46-
<DropdownItem key="iteration">Website</DropdownItem>
47-
</DropdownMenu>
48-
</Dropdown>
49-
</>
50-
}
24+
id="inpt"
25+
onKeyDown={(x) => {
26+
if (x.key == "Enter") {
27+
sr(true);
28+
}
29+
}}
30+
onChange={(x) => st(x.target.value)}
5131
endContent={
52-
<Button isIconOnly color="primary" aria-label="Like">
32+
<Button
33+
isIconOnly
34+
color="primary"
35+
aria-label="Like"
36+
onClick={() => sr(true)}
37+
>
5338
<Search />
5439
</Button>
5540
}

src/graphql/queries.ts

+27-4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export type Errors = {
9494
error?: string;
9595
}
9696

97-
function flatten<T>(t: Result<Result<T>>): Result<T> {
97+
export function flatten<T>(t: Result<Result<T>>): Result<T> {
9898
switch (t.state) {
9999
case "loading": return t
100100
case "error": return t
@@ -106,7 +106,30 @@ function flatten<T>(t: Result<Result<T>>): Result<T> {
106106
}
107107
}
108108

109-
function and_then<T, U>(t: Result<T>, f: (x: T | undefined) => Result<U>): Result<U> {
109+
export function ok<T>(t: Result<T>): T | undefined {
110+
switch (t.state) {
111+
case "error":
112+
case "loading": return undefined
113+
case "ok": return t.data
114+
}
115+
}
116+
117+
118+
/** selects the first loaded option */
119+
export function select<T>(data:[Result<T | undefined>]): Result<T> | undefined {
120+
for (var x of data) {
121+
switch (x.state) {
122+
case "ok": if (x.data === undefined || x.data===null) continue
123+
case "error": return x as any
124+
case "loading": continue
125+
}
126+
}
127+
return (data.every(x => x.state == "ok" && x.data == undefined))
128+
? undefined
129+
: { state: "loading" }
130+
}
131+
132+
export function and_then<T, U>(t: Result<T>, f: (x: T | undefined) => Result<U>): Result<U> {
110133
switch (t.state) {
111134
// hooks must be called
112135
case "loading": { f(undefined); return t };
@@ -116,7 +139,7 @@ function and_then<T, U>(t: Result<T>, f: (x: T | undefined) => Result<U>): Resul
116139
}
117140

118141

119-
type Result<T> = Ok<T> | Loading | Error;
142+
export type Result<T> = Ok<T> | Loading | Error;
120143

121144
export type Refreshable<T> = {
122145
result: Result<T>,
@@ -320,7 +343,7 @@ export function evm_transfers_by_id(id: string): Result<Transfer[]> {
320343
)
321344
}
322345

323-
export function get_extrinsic_by_hash(hash: string): Result<Extrinsic | undefined> {
346+
export function extrinsic_by_hash(hash: string): Result<Extrinsic | undefined> {
324347
return map_query(useQuery(gql`
325348
query ExtrinsicByHash($hash: String!) {
326349
extrinsics(where: {extrinsicHash_eq: $hash}) {

src/lib/utils.tsx

+30-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,38 @@
1-
import { clsx, type ClassValue } from 'clsx';
2-
import { twMerge } from 'tailwind-merge';
1+
import { clsx, type ClassValue } from "clsx";
2+
import { twMerge } from "tailwind-merge";
33

44
export const cn = (...inputs: ClassValue[]) => {
55
return twMerge(clsx(inputs));
66
};
77

88
export function map<T, U>(x: T | undefined, f: (y: T) => U): U | undefined {
9-
const res: any = x !== undefined ? f(x) : x
10-
return res;
9+
return x !== undefined && x !== null ? f(x) : (x as any);
1110
}
1211
export function map_or<T, U>(x: T | undefined, def: U, f: (y: T) => U): U {
13-
return x === undefined ? def : f(x)
14-
}
12+
return x === undefined && x !== null ? def : f(x);
13+
}
14+
15+
export function mapped<T>(
16+
x: T | undefined,
17+
f: (y: T) => undefined
18+
): T | undefined {
19+
return map(x, (y) => {
20+
f(y);
21+
return y;
22+
});
23+
}
24+
25+
function or_else<T>(t: T | undefined, f: () => T | undefined): T | undefined {
26+
return t === undefined ? f() : t;
27+
}
28+
29+
/** selects the first loaded option */
30+
export function select<T>(data: [T | undefined]): T | undefined {
31+
for (var x of data) {
32+
if (x === undefined || x === null) {
33+
continue;
34+
} else {
35+
return x!;
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)