SPB Git forge

spb/spinza

Public
8commits 1branches 0releases
1.6 MBsize
maindefault branch
16 days agolast push
TypeScript 97.6% SQL 1.4% JavaScript 0.5%
1.9 KB · 35 lines tsx
Raw Blame History
1"use client";23import { useRouter } from "next/navigation";4import { WifiOff, ServerCrash, Wrench, AlertCircle, RefreshCw } from "lucide-react";5import { Button } from "@/components/ui";6import { describeError } from "@/lib/use-api";7import { ApiClientError } from "@/lib/api";8import { cn } from "@/lib/utils";910/** Polished error state for connection loss, server outage and maintenance. */11export function ApiErrorState({ error, retry, className, compact }: { error: unknown; retry?: () => void; className?: string; compact?: boolean }) {12  const d = describeError(error);13  const Icon = d.kind === "network" ? WifiOff : d.kind === "maintenance" ? Wrench : d.kind === "server" ? ServerCrash : AlertCircle;14  return (15    <div className={cn("surface rounded-lg text-center", compact ? "px-4 py-6" : "px-6 py-12", className)} role="alert">16      <div className={cn("mx-auto grid place-items-center rounded-full bg-surface-2 text-fg-2", compact ? "mb-3 h-10 w-10" : "mb-4 h-14 w-14", d.kind === "maintenance" && "text-accent")}>17        <Icon className={compact ? "h-5 w-5" : "h-6 w-6"} />18      </div>19      <h3 className={cn("font-semibold tracking-tight", compact ? "text-base" : "text-lg")}>{d.title}</h3>20      <p className="mx-auto mt-1.5 max-w-sm text-sm text-fg-3">{d.description}</p>21      {retry ? (22        <Button variant="secondary" size={compact ? "sm" : "md"} className="mt-5" onClick={retry}>23          <RefreshCw className="h-4 w-4" /> Try again24        </Button>25      ) : null}26    </div>27  );28}2930/** Server components can't retry in place — this reloads the route from the client. */31export function ServerUnavailable({ className, compact }: { className?: string; compact?: boolean }) {32  const router = useRouter();33  return <ApiErrorState error={new ApiClientError(503, "UNAVAILABLE", "Server unavailable. Please try again shortly.")} retry={() => router.refresh()} className={className} compact={compact} />;34}35