explorer-search.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. "use client";
  2. import { useRouter } from "next/navigation";
  3. import { useState, type FormEvent } from "react";
  4. import { SearchIcon } from "@/components/icons/search";
  5. import { Button } from "@/components/ui/button";
  6. import { Input } from "@/components/ui/input";
  7. import { searchExplorer } from "@/lib/explorer-mock";
  8. export function ExplorerSearch() {
  9. const router = useRouter();
  10. const [q, setQ] = useState("");
  11. const [error, setError] = useState<string | null>(null);
  12. function onSubmit(e: FormEvent) {
  13. e.preventDefault();
  14. const hit = searchExplorer(q);
  15. if (hit.kind === "tx") {
  16. setError(null);
  17. router.push(`/portal/explorer/tx/${encodeURIComponent(hit.id)}`);
  18. return;
  19. }
  20. if (hit.kind === "block") {
  21. setError(null);
  22. router.push(`/portal/explorer/block/${encodeURIComponent(hit.id)}`);
  23. return;
  24. }
  25. setError(
  26. "No mock match. Try a full or partial tx hash, a block height (e.g. 1284901), or an address from the lists.",
  27. );
  28. }
  29. return (
  30. <form onSubmit={onSubmit} className="w-full max-w-2xl">
  31. <div className="flex gap-2">
  32. <div className="relative flex-1">
  33. <SearchIcon
  34. size={16}
  35. className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
  36. />
  37. <Input
  38. value={q}
  39. onChange={(e) => {
  40. setQ(e.target.value);
  41. if (error) setError(null);
  42. }}
  43. placeholder="Search by tx hash, block height, or address…"
  44. className="h-11 pl-9 font-mono text-sm"
  45. aria-label="Search explorer"
  46. autoComplete="off"
  47. />
  48. </div>
  49. <Button type="submit" size="lg" className="h-11 shrink-0 px-5">
  50. Search
  51. </Button>
  52. </div>
  53. {error ? (
  54. <p className="mt-2 text-sm text-pending" role="status">
  55. {error}
  56. </p>
  57. ) : (
  58. <p className="mt-2 text-xs text-muted-foreground">
  59. Mock data only — try height{" "}
  60. <button
  61. type="button"
  62. className="font-mono text-accent-hover hover:underline"
  63. onClick={() => setQ("1284901")}
  64. >
  65. 1284901
  66. </button>{" "}
  67. or paste a hash from the tables below.
  68. </p>
  69. )}
  70. </form>
  71. );
  72. }