Files
duty-teller/webapp-next/src/components/states/ErrorState.tsx
Nikolay Tatarinov 16bf1a1043 feat: migrate to Next.js for Mini App and enhance project structure
- Replaced the previous webapp with a new Mini App built using Next.js, improving performance and maintainability.
- Updated the `.gitignore` to exclude Next.js build artifacts and node modules.
- Revised documentation in `AGENTS.md`, `README.md`, and `architecture.md` to reflect the new Mini App structure and technology stack.
- Enhanced Dockerfile to support the new build process for the Next.js application.
- Updated CI workflow to build and test the Next.js application.
- Added new configuration options for the Mini App, including `MINI_APP_SHORT_NAME` for improved deep linking.
- Refactored frontend testing setup to accommodate the new structure and testing framework.
- Removed legacy webapp files and dependencies to streamline the project.
2026-03-03 16:04:08 +03:00

76 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Error state: warning icon, message, and optional Retry button.
* Ported from webapp/js/ui.js showError and states.css .error.
*/
"use client";
import { useTranslation } from "@/i18n/use-translation";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
export interface ErrorStateProps {
/** Error message to display. If not provided, uses generic i18n message. */
message?: string | null;
/** Optional retry callback; when provided, a Retry button is shown. */
onRetry?: (() => void) | null;
/** Optional class for the container. */
className?: string;
}
/** Warning triangle icon 24×24 for error state. */
function ErrorIcon({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={cn("shrink-0 text-error", className)}
aria-hidden
>
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
<line x1="12" y1="9" x2="12" y2="13" />
<line x1="12" y1="17" x2="12.01" y2="17" />
</svg>
);
}
/**
* Displays an error message with optional Retry button.
*/
export function ErrorState({ message, onRetry, className }: ErrorStateProps) {
const { t } = useTranslation();
const displayMessage =
message && String(message).trim() ? message : t("error_generic");
return (
<div
className={cn(
"flex flex-col items-center gap-3 rounded-xl bg-surface py-5 px-4 my-3 text-center text-error transition-opacity duration-200",
className
)}
role="alert"
>
<ErrorIcon />
<p className="m-0 text-sm font-medium">{displayMessage}</p>
{typeof onRetry === "function" && (
<Button
type="button"
variant="default"
size="sm"
className="mt-1 bg-primary text-primary-foreground hover:opacity-90 focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2"
onClick={onRetry}
>
{t("error.retry")}
</Button>
)}
</div>
);
}