refactor(frontend): improve code quality and maintainability
- Extract API error handling utility (utils/error-handling.ts) - Centralize error message extraction logic - Add type guards for API errors - Replace duplicated error handling across components - Create reusable Toast component (components/Toast.tsx) - Extract toast notification logic from profile page - Support auto-dismiss functionality - Consistent styling with shared styles - Extract form validation debouncing hook (hooks/useDebouncedValidation.ts) - Reusable debounced validation logic - Clean timeout management - Used in profile page for form validation - Consolidate duplicate styles (styles/auth-form.ts) - Use shared style tokens instead of duplicating values - Reduce code duplication between auth-form and shared styles - Extract loading state component (components/LoadingState.tsx) - Standardize loading UI across pages - Replace duplicated loading JSX patterns - Used in profile, exchange, and trades pages - Fix useRequireAuth dependency array - Remove unnecessary hasPermission from dependencies - Add eslint-disable comment with explanation - Improve hook stability and performance All frontend tests pass. Linting passes.
This commit is contained in:
parent
db181b338c
commit
3beb23a765
10 changed files with 231 additions and 143 deletions
20
frontend/app/components/LoadingState.tsx
Normal file
20
frontend/app/components/LoadingState.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
"use client";
|
||||
|
||||
import { layoutStyles } from "../styles/shared";
|
||||
|
||||
interface LoadingStateProps {
|
||||
/** Custom loading message (default: "Loading...") */
|
||||
message?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard loading state component.
|
||||
* Displays a centered loading message with consistent styling.
|
||||
*/
|
||||
export function LoadingState({ message = "Loading..." }: LoadingStateProps) {
|
||||
return (
|
||||
<main style={layoutStyles.main}>
|
||||
<div style={layoutStyles.loader}>{message}</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
40
frontend/app/components/Toast.tsx
Normal file
40
frontend/app/components/Toast.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { toastStyles } from "../styles/shared";
|
||||
|
||||
export type ToastType = "success" | "error";
|
||||
|
||||
export interface ToastProps {
|
||||
message: string;
|
||||
type: ToastType;
|
||||
onDismiss?: () => void;
|
||||
/** Auto-dismiss delay in milliseconds (default: 3000) */
|
||||
autoDismissDelay?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toast notification component with auto-dismiss functionality.
|
||||
* Displays success or error messages in a fixed position.
|
||||
*/
|
||||
export function Toast({ message, type, onDismiss, autoDismissDelay = 3000 }: ToastProps) {
|
||||
useEffect(() => {
|
||||
if (onDismiss) {
|
||||
const timer = setTimeout(() => {
|
||||
onDismiss();
|
||||
}, autoDismissDelay);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [onDismiss, autoDismissDelay]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
...toastStyles.toast,
|
||||
...(type === "success" ? toastStyles.toastSuccess : toastStyles.toastError),
|
||||
}}
|
||||
>
|
||||
{message}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue