Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import { useEffect } from "react";
import Link from "next/link";
import { Nav } from "@/components/Nav";
import { Footer } from "@/components/Footer";

interface ErrorPageProps {
error: Error & { digest?: string };
reset: () => void;
}

export default function Error({ error, reset }: ErrorPageProps) {
useEffect(() => {
// Log to an error reporting service in production.
console.error(error);
}, [error]);

return (
<div className="min-h-screen">
<Nav variant="breadcrumb" label="Error" />

<main
id="main-content"
className="max-w-2xl mx-auto px-5 py-24 text-center"
>
<div className="eyebrow mb-3">Something went wrong</div>
<h1 className="text-3xl font-bold text-vx-text mb-3">
An unexpected error occurred
</h1>
<p className="text-vx-muted text-sm mb-8">
{error.message
? error.message
: "We hit an unexpected error. Please try again or return home."}
</p>

<div className="flex items-center justify-center gap-4">
<button
type="button"
onClick={reset}
className="text-sm px-4 py-2 rounded-lg bg-vx-sage text-vx-ink font-semibold
hover:brightness-110 transition-all"
>
Try again
</button>
<Link href="/" className="text-sm text-vx-sage hover:underline">
← Back to Vortex
</Link>
</div>
</main>

<Footer />
</div>
);
}
54 changes: 54 additions & 0 deletions src/app/explore/[id]/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use client";

import { useEffect } from "react";
import Link from "next/link";
import { Nav } from "@/components/Nav";
import { Footer } from "@/components/Footer";

interface ErrorPageProps {
error: Error & { digest?: string };
reset: () => void;
}

export default function IntentDetailError({ error, reset }: ErrorPageProps) {
useEffect(() => {
console.error(error);
}, [error]);

return (
<div className="min-h-screen">
<Nav variant="breadcrumb" label="Intent Detail — Error" />

<main
id="main-content"
className="max-w-2xl mx-auto px-5 py-24 text-center"
>
<div className="eyebrow mb-3">Intent Detail</div>
<h1 className="text-3xl font-bold text-vx-text mb-3">
Couldn&apos;t load this intent
</h1>
<p className="text-vx-muted text-sm mb-8">
{error.message
? error.message
: "There was a problem loading the intent details. It may have been removed or the ID may be invalid."}
</p>

<div className="flex items-center justify-center gap-4">
<button
type="button"
onClick={reset}
className="text-sm px-4 py-2 rounded-lg bg-vx-sage text-vx-ink font-semibold
hover:brightness-110 transition-all"
>
Try again
</button>
<Link href="/explore" className="text-sm text-vx-sage hover:underline">
← Back to Explorer
</Link>
</div>
</main>

<Footer />
</div>
);
}
28 changes: 28 additions & 0 deletions src/app/explore/[id]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { SkeletonBlock, SkeletonDetailCard } from "@/components/Skeleton";

/**
* Route-segment loading boundary for /explore/[id].
* Uses SkeletonDetailCard to match the intent detail layout.
*/
export default function IntentDetailLoading() {
return (
<div className="min-h-screen">
{/* Nav placeholder */}
<div className="h-14 border-b border-vx-line" aria-hidden="true" />

<div className="max-w-3xl mx-auto px-5 py-12" aria-hidden="true">
{/* Back link placeholder */}
<SkeletonBlock className="h-3 w-28 mb-6" />

{/* Detail card */}
<SkeletonDetailCard />

{/* Settlement tx section */}
<div className="mt-6 space-y-3">
<SkeletonBlock className="h-3 w-32" />
<SkeletonBlock className="h-10 w-full rounded-lg" />
</div>
</div>
</div>
);
}
54 changes: 54 additions & 0 deletions src/app/explore/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use client";

import { useEffect } from "react";
import Link from "next/link";
import { Nav } from "@/components/Nav";
import { Footer } from "@/components/Footer";

interface ErrorPageProps {
error: Error & { digest?: string };
reset: () => void;
}

export default function ExploreError({ error, reset }: ErrorPageProps) {
useEffect(() => {
console.error(error);
}, [error]);

return (
<div className="min-h-screen">
<Nav variant="breadcrumb" label="Explore — Error" />

<main
id="main-content"
className="max-w-2xl mx-auto px-5 py-24 text-center"
>
<div className="eyebrow mb-3">Explore</div>
<h1 className="text-3xl font-bold text-vx-text mb-3">
Couldn&apos;t load intents
</h1>
<p className="text-vx-muted text-sm mb-8">
{error.message
? error.message
: "There was a problem loading the intent explorer. Please try again."}
</p>

<div className="flex items-center justify-center gap-4">
<button
type="button"
onClick={reset}
className="text-sm px-4 py-2 rounded-lg bg-vx-sage text-vx-ink font-semibold
hover:brightness-110 transition-all"
>
Try again
</button>
<Link href="/" className="text-sm text-vx-sage hover:underline">
← Back to Vortex
</Link>
</div>
</main>

<Footer />
</div>
);
}
40 changes: 40 additions & 0 deletions src/app/explore/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { SkeletonBlock, SkeletonCard } from "@/components/Skeleton";

/**
* Route-segment loading boundary for /explore.
* Mirrors the filter bar + intent table layout.
*/
export default function ExploreLoading() {
return (
<div className="min-h-screen">
{/* Nav placeholder */}
<div className="h-14 border-b border-vx-line" aria-hidden="true" />

<div className="max-w-6xl mx-auto px-5 py-12" aria-hidden="true">
{/* Page heading */}
<div className="space-y-2 mb-8">
<SkeletonBlock className="h-3 w-20" />
<SkeletonBlock className="h-8 w-48" />
<SkeletonBlock className="h-4 w-72" />
</div>

{/* Filter bar */}
<div className="flex flex-wrap gap-3 mb-6">
<SkeletonBlock className="h-8 w-32 rounded-lg" />
<SkeletonBlock className="h-8 w-32 rounded-lg" />
<SkeletonBlock className="h-8 w-40 rounded-lg" />
</div>

{/* Intent rows */}
<SkeletonCard rows={8} rowHeight="h-16" />

{/* Pagination */}
<div className="flex justify-center gap-2 mt-6">
<SkeletonBlock className="h-8 w-8 rounded-lg" />
<SkeletonBlock className="h-8 w-8 rounded-lg" />
<SkeletonBlock className="h-8 w-8 rounded-lg" />
</div>
</div>
</div>
);
}
Loading