52 lines
2.0 KiB
TypeScript
52 lines
2.0 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
|
|
interface SafeErrorStateProps {
|
|
title?: string;
|
|
message?: string;
|
|
actionLabel?: string;
|
|
onAction?: () => void;
|
|
onRetry?: () => void;
|
|
}
|
|
|
|
export function SafeErrorState({
|
|
title = 'Notice',
|
|
message = "Club information couldn't be loaded.",
|
|
actionLabel,
|
|
onAction,
|
|
onRetry,
|
|
}: SafeErrorStateProps) {
|
|
return (
|
|
<div
|
|
role="alert"
|
|
className="rounded-2xl glass-card border border-brand-border/60 p-8 sm:p-10 max-w-lg mx-auto my-12 text-center shadow-2xl"
|
|
>
|
|
<div className="w-14 h-14 rounded-2xl bg-error-container text-on-error-container flex items-center justify-center mx-auto mb-4 border border-error/40 shadow-lg">
|
|
<span className="material-symbols-outlined text-[28px]">shield_with_heart</span>
|
|
</div>
|
|
<h3 className="font-headline text-2xl font-bold text-white mb-2">{title}</h3>
|
|
<p className="font-body text-sm text-slate-400 mb-6 leading-relaxed">{message}</p>
|
|
<div className="flex flex-wrap items-center justify-center gap-3">
|
|
{onRetry && (
|
|
<button
|
|
onClick={onRetry}
|
|
className="h-10 px-5 rounded-xl bg-surface-container border border-outline-variant/60 text-slate-200 hover:text-white hover:bg-surface-container-high transition-colors font-body text-xs sm:text-sm font-medium inline-flex items-center gap-2 cursor-pointer"
|
|
>
|
|
<span className="material-symbols-outlined text-[18px]">refresh</span>
|
|
<span>Try Again</span>
|
|
</button>
|
|
)}
|
|
{onAction && actionLabel && (
|
|
<button
|
|
onClick={onAction}
|
|
className="h-10 px-5 rounded-xl bg-primary-container text-on-primary-container hover:brightness-110 shadow-[0_0_16px_rgba(0,242,254,0.3)] transition-all font-body text-xs sm:text-sm font-bold inline-flex items-center gap-2 cursor-pointer"
|
|
>
|
|
<span>{actionLabel}</span>
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|