MotorSignal-App/website/components/ops/operations-error-state.tsx

98 lines
3.8 KiB
TypeScript

'use client';
import React from 'react';
import Link from 'next/link';
interface OperationsErrorStateProps {
status: 401 | 403 | 404 | 503 | 'disabled' | 'network' | number;
message?: string;
onRetry?: () => void;
}
export function OperationsErrorState({
status,
message,
onRetry,
}: OperationsErrorStateProps) {
let title = 'Operations Error';
let description = message ?? 'An unexpected error occurred in the Operations console.';
let icon = 'error';
let showSignIn = false;
let showRetry = true;
if (status === 401) {
title = 'Authentication Required';
description = message ?? 'Your Operations session has expired or is unauthenticated.';
icon = 'lock';
showSignIn = true;
showRetry = false;
} else if (status === 403) {
title = 'Access Restricted';
description = message ?? 'You do not have sufficient authority to access Operations.';
icon = 'gavel';
showSignIn = false;
showRetry = false;
} else if (status === 404) {
title = 'Resource Not Found';
description = message ?? 'The requested Operations resource does not exist.';
icon = 'search_off';
} else if (status === 503 || status === 'network') {
title = 'Operations Temporarily Unavailable';
description = message ?? 'Unable to communicate with the Operations API. Try again in a few moments.';
icon = 'cloud_off';
} else if (status === 'disabled') {
title = 'Operations Disabled';
description = message ?? 'The Operations platform is currently disabled by system policy.';
icon = 'block';
showRetry = false;
}
return (
<div className="p-8 rounded-xl bg-surface-container-low border border-outline-variant/30 text-center max-w-lg mx-auto my-12 space-y-4 shadow-sm">
<div className="w-12 h-12 rounded-full bg-surface-container-high border border-outline-variant/40 flex items-center justify-center text-outline mx-auto">
<span className="material-symbols-outlined text-[24px]">{icon}</span>
</div>
<div className="space-y-1">
<span className="text-[10px] font-mono uppercase tracking-widest text-outline">
STATUS {typeof status === 'number' ? status : status.toUpperCase()}
</span>
<h2 className="text-lg font-bold text-on-surface">{title}</h2>
<p className="text-xs text-on-surface-variant leading-relaxed">
{description}
</p>
</div>
<div className="pt-4 border-t border-outline-variant/20 flex items-center justify-center gap-3">
{showSignIn && (
<Link
href="/login"
className="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg bg-primary-container text-on-primary-container text-xs font-bold shadow-sm hover:brightness-105 transition-all focus-visible:ring-2 focus-visible:ring-primary-container focus-visible:outline-none"
>
<span className="material-symbols-outlined text-[16px]">login</span>
<span>Sign In</span>
</Link>
)}
{showRetry && onRetry && (
<button
type="button"
onClick={onRetry}
className="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg bg-surface-container-high hover:bg-surface-bright text-on-surface border border-outline-variant/30 text-xs font-semibold transition-all focus-visible:ring-2 focus-visible:ring-primary-container focus-visible:outline-none"
>
<span className="material-symbols-outlined text-[16px]">refresh</span>
<span>Retry</span>
</button>
)}
<Link
href="/"
className="inline-flex items-center gap-1.5 px-3 py-2 rounded-lg text-xs font-medium text-on-surface-variant hover:text-on-surface transition-colors"
>
Return Home
</Link>
</div>
</div>
);
}