- 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.
75 lines
1.5 KiB
TypeScript
75 lines
1.5 KiB
TypeScript
import { CSSProperties } from "react";
|
|
|
|
// Import shared tokens and styles to avoid duplication
|
|
// Note: We can't directly import tokens from shared.ts as it's not exported,
|
|
// so we'll use the shared style objects where possible
|
|
import {
|
|
layoutStyles,
|
|
cardStyles,
|
|
formStyles,
|
|
buttonStyles,
|
|
bannerStyles,
|
|
typographyStyles,
|
|
} from "./shared";
|
|
|
|
export const authFormStyles: Record<string, CSSProperties> = {
|
|
main: {
|
|
...layoutStyles.contentCentered,
|
|
minHeight: "100vh",
|
|
padding: "1rem",
|
|
},
|
|
container: {
|
|
width: "100%",
|
|
maxWidth: "420px",
|
|
},
|
|
card: {
|
|
...cardStyles.card,
|
|
padding: "3rem 2.5rem",
|
|
},
|
|
header: {
|
|
textAlign: "center" as const,
|
|
marginBottom: "2.5rem",
|
|
},
|
|
title: {
|
|
...typographyStyles.pageTitle,
|
|
fontSize: "2.5rem",
|
|
textAlign: "center" as const,
|
|
},
|
|
subtitle: {
|
|
...typographyStyles.pageSubtitle,
|
|
textAlign: "center" as const,
|
|
},
|
|
form: {
|
|
...formStyles.form,
|
|
gap: "1.5rem",
|
|
},
|
|
field: {
|
|
...formStyles.field,
|
|
},
|
|
label: {
|
|
...formStyles.label,
|
|
},
|
|
input: {
|
|
...formStyles.input,
|
|
},
|
|
button: {
|
|
...buttonStyles.primaryButton,
|
|
marginTop: "0.5rem",
|
|
},
|
|
error: {
|
|
...bannerStyles.errorBanner,
|
|
textAlign: "center" as const,
|
|
},
|
|
footer: {
|
|
fontFamily: "'DM Sans', system-ui, sans-serif",
|
|
textAlign: "center" as const,
|
|
marginTop: "2rem",
|
|
color: "rgba(255, 255, 255, 0.5)",
|
|
fontSize: "0.875rem",
|
|
},
|
|
link: {
|
|
color: "#a78bfa",
|
|
textDecoration: "none",
|
|
fontWeight: 500,
|
|
},
|
|
};
|