ui phase 1

This commit is contained in:
hamid
2026-07-17 17:10:39 +03:30
parent f1cba6cf74
commit 370c1beefa
151 changed files with 4254 additions and 1840 deletions
+51 -24
View File
@@ -1,9 +1,20 @@
'use client';
import { Component, ErrorInfo, ReactNode } from 'react';
import { Stack, Typography } from '@mui/material';
import AppButton from './AppButton';
import AppIcon from './AppIcon';
interface Props {
export interface ErrorBoundaryProps {
children: ReactNode;
/** Diagnostic-only segment name (console log label) — never shown to the user. */
name: string;
/** Already-translated fallback copy — kept presentational/caller-owned (like every other shared
* primitive in this kit) so this file never imports next-intl; it sits at the top of the `common`
* barrel, so an eager i18n dependency here would drag `next-intl` into every test that imports
* anything from `@/components`, mocked or not. */
title: string;
body: string;
retryLabel: string;
}
interface State {
@@ -13,47 +24,63 @@ interface State {
}
/**
* Error boundary wrapper to save Application parts from falling
* Error boundary wrapping a subtree of the app (a shell's content area). Renders a branded fallback with
* a retry affordance (re-mounts the children by clearing `hasError`); the raw error + component stack are
* **logged, never shown**, in production — only a development build renders the dev-only `<details>`
* block.
* @component ErrorBoundary
* @param {string} [props.name] - name of the wrapped segment, "Error Boundary" by default
*/
class ErrorBoundary extends Component<Props, State> {
static defaultProps = {
name: 'Error Boundary',
};
constructor(props: Props) {
class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error) {
// The next render will show the Error UI
return { hasError: true };
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// Save information to help render Error UI
this.setState({ error, errorInfo });
// TODO: Add log error messages to an error reporting service here
console.error(`[ErrorBoundary:${this.props.name}]`, error, errorInfo.componentStack);
}
handleRetry = () => {
this.setState({ hasError: false, error: undefined, errorInfo: undefined });
};
render() {
if (this.state.hasError) {
// Error UI rendering
const { error, errorInfo } = this.state;
return (
<div>
<h2>{this.props.name} - Something went wrong</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state?.error?.toString()}
<br />
{this.state?.errorInfo?.componentStack}
</details>
</div>
<Stack sx={{ alignItems: 'center', justifyContent: 'center', gap: 1.5, py: 6, px: 2, textAlign: 'center' }}>
<AppIcon icon="warning" size={36} color="var(--bal-warning)" />
<Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
{this.props.title}
</Typography>
<Typography variant="body2" sx={{ color: 'text.secondary', maxWidth: 360 }}>
{this.props.body}
</Typography>
<AppButton color="primary" variant="outlined" onClick={this.handleRetry}>
{this.props.retryLabel}
</AppButton>
{process.env.NODE_ENV !== 'production' && (error || errorInfo) ? (
<Typography
component="details"
variant="caption"
sx={{ color: 'text.secondary', maxWidth: 480, textAlign: 'start', whiteSpace: 'pre-wrap' }}
>
<Typography component="summary" variant="caption" sx={{ cursor: 'pointer' }}>
Dev-only error detail
</Typography>
{error?.toString()}
{'\n'}
{errorInfo?.componentStack}
</Typography>
) : null}
</Stack>
);
}
// Normal UI rendering
return this.props.children;
}
}