From edb83ff6b5355343a9353f0141883f22a35437ae Mon Sep 17 00:00:00 2001 From: dzinesco Date: Sat, 16 Aug 2025 12:44:54 -0600 Subject: [PATCH] feat(config): enhance development experience with strict linting and types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update ESLint configuration with strict React/TypeScript rules - Enhance TypeScript configuration with stricter checks - Add comprehensive type definitions and exports - Update App.tsx with new routing and layout integration - Create showcase pages for component development - Improve package.json with proper dependencies Configuration ensures code quality and developer productivity with zero-tolerance for type errors and consistent code standards. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- reactrebuild0825/eslint.config.js | 69 ++++- reactrebuild0825/package-lock.json | 25 ++ reactrebuild0825/package.json | 15 +- reactrebuild0825/src/App.tsx | 124 +++++++- .../src/components/UIShowcase.tsx | 265 ++++++++++++++++++ reactrebuild0825/src/pages/DashboardPage.tsx | 197 +++++++------ reactrebuild0825/src/pages/EventsPage.tsx | 167 ++++++----- reactrebuild0825/src/pages/HomePage.tsx | 238 +++++++++++----- reactrebuild0825/tsconfig.json | 23 +- 9 files changed, 874 insertions(+), 249 deletions(-) create mode 100644 reactrebuild0825/src/components/UIShowcase.tsx diff --git a/reactrebuild0825/eslint.config.js b/reactrebuild0825/eslint.config.js index 0a3fda7..b5c7b38 100644 --- a/reactrebuild0825/eslint.config.js +++ b/reactrebuild0825/eslint.config.js @@ -79,11 +79,11 @@ export default tseslint.config( }, }, rules: { - // React Rules + // React Rules - Strict Configuration ...react.configs.recommended.rules, ...react.configs['jsx-runtime'].rules, ...reactHooks.configs.recommended.rules, - ...jsxA11y.configs.recommended.rules, + ...jsxA11y.configs.strict.rules, // React Refresh 'react-refresh/only-export-components': [ @@ -122,11 +122,27 @@ export default tseslint.config( }, ], 'react/jsx-pascal-case': ['error', { allowAllCaps: true }], - 'react/no-array-index-key': 'off', // Allow index keys for static lists + 'react/no-array-index-key': 'warn', // Warn about index keys - use stable IDs when possible 'react/no-danger': 'error', 'react/no-deprecated': 'error', 'react/no-unsafe': 'error', 'react/hook-use-state': 'warn', + 'react-hooks/exhaustive-deps': 'error', // Strict enforcement of exhaustive deps + 'react/display-name': 'error', // All components must have display names + + // Accessibility - Additional Strict Rules + 'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }], + 'jsx-a11y/anchor-is-valid': 'error', + 'jsx-a11y/click-events-have-key-events': 'error', + 'jsx-a11y/interactive-supports-focus': 'error', + 'jsx-a11y/label-has-associated-control': 'error', + 'jsx-a11y/media-has-caption': 'error', + 'jsx-a11y/no-static-element-interactions': 'error', + 'jsx-a11y/role-has-required-aria-props': 'error', + 'jsx-a11y/role-supports-aria-props': 'error', + 'jsx-a11y/scope': 'error', + 'jsx-a11y/heading-has-content': 'error', + 'jsx-a11y/img-redundant-alt': 'error', // TypeScript Rules '@typescript-eslint/no-unused-vars': [ @@ -148,12 +164,22 @@ export default tseslint.config( '@typescript-eslint/no-unused-expressions': 'error', '@typescript-eslint/prefer-readonly': 'warn', '@typescript-eslint/explicit-function-return-type': [ - 'off', // Let TypeScript infer return types for React components + 'warn', // Enforce explicit return types for better documentation { allowExpressions: true, allowTypedFunctionExpressions: true, allowHigherOrderFunctions: true, allowDirectConstAssertionInArrowFunctions: true, + allowConciseArrowFunctionExpressionsStartingWithVoid: true, + }, + ], + '@typescript-eslint/explicit-module-boundary-types': [ + 'warn', + { + allowArgumentsExplicitlyTypedAsAny: false, + allowDirectConstAssertionInArrowFunctions: true, + allowHigherOrderFunctions: true, + allowTypedFunctionExpressions: true, }, ], '@typescript-eslint/consistent-type-imports': [ @@ -216,8 +242,11 @@ export default tseslint.config( 'import/default': 'off', // React 18 JSX transform doesn't export default 'import/export': 'error', - // General Code Quality - 'no-console': ['warn', { allow: ['warn', 'error'] }], + // General Code Quality - Strict Rules + 'no-console': process.env.NODE_ENV === 'production' + ? ['error', { allow: ['warn', 'error'] }] + : ['warn', { allow: ['warn', 'error', 'info'] }], + 'prefer-const': 'error', 'no-debugger': 'error', 'no-alert': 'error', 'no-var': 'error', @@ -248,7 +277,7 @@ export default tseslint.config( 'no-async-promise-executor': 'error', 'no-await-in-loop': 'warn', - // Naming Conventions + // Naming Conventions - Strict Standards '@typescript-eslint/naming-convention': [ 'error', { @@ -268,6 +297,15 @@ export default tseslint.config( selector: 'interface', format: ['PascalCase'], }, + { + selector: 'interface', + filter: { + regex: '^.*Props$', + match: true, + }, + format: ['PascalCase'], + suffix: ['Props'], + }, { selector: 'typeAlias', format: ['PascalCase'], @@ -276,6 +314,10 @@ export default tseslint.config( selector: 'enum', format: ['PascalCase'], }, + { + selector: 'enumMember', + format: ['UPPER_CASE'], + }, ], }, }, @@ -320,11 +362,11 @@ export default tseslint.config( }, }, rules: { - // React Rules + // React Rules - Strict Configuration ...react.configs.recommended.rules, ...react.configs['jsx-runtime'].rules, ...reactHooks.configs.recommended.rules, - ...jsxA11y.configs.recommended.rules, + ...jsxA11y.configs.strict.rules, // React Refresh 'react-refresh/only-export-components': [ @@ -355,13 +397,16 @@ export default tseslint.config( }, ], 'react/jsx-pascal-case': ['error', { allowAllCaps: true }], - 'react/no-array-index-key': 'off', // Allow index keys for static lists + 'react/no-array-index-key': 'warn', // Warn about index keys - use stable IDs when possible 'react/no-danger': 'error', 'react/no-deprecated': 'error', 'react/no-unsafe': 'error', - // General Code Quality - 'no-console': ['warn', { allow: ['warn', 'error'] }], + // General Code Quality - Strict Rules + 'no-console': process.env.NODE_ENV === 'production' + ? ['error', { allow: ['warn', 'error'] }] + : ['warn', { allow: ['warn', 'error', 'info'] }], + 'prefer-const': 'error', 'no-debugger': 'error', 'no-alert': 'error', 'no-var': 'error', diff --git a/reactrebuild0825/package-lock.json b/reactrebuild0825/package-lock.json index 2b7db30..2920668 100644 --- a/reactrebuild0825/package-lock.json +++ b/reactrebuild0825/package-lock.json @@ -45,6 +45,7 @@ "prettier-plugin-tailwindcss": "^0.6.14", "tailwindcss": "^3.4.14", "typescript": "^5.6.3", + "typescript-eslint": "^8.39.1", "vite": "^6.0.1" } }, @@ -7158,6 +7159,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.1.tgz", + "integrity": "sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.39.1", + "@typescript-eslint/parser": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", diff --git a/reactrebuild0825/package.json b/reactrebuild0825/package.json index cfcdc1f..05ea901 100644 --- a/reactrebuild0825/package.json +++ b/reactrebuild0825/package.json @@ -18,7 +18,17 @@ "quality:fix": "npm run typecheck && npm run lint:fix && npm run format", "test": "playwright test", "test:ui": "playwright test --ui", - "test:headed": "playwright test --headed" + "test:headed": "playwright test --headed", + "test:qa": "tsx tests/test-runner.ts", + "test:qa:critical": "tsx tests/test-runner.ts --critical", + "test:qa:headed": "tsx tests/test-runner.ts --headed", + "test:smoke": "playwright test tests/smoke.spec.ts", + "test:auth": "playwright test tests/auth-realistic.spec.ts", + "test:auth:enhanced": "playwright test tests/auth.spec.ts", + "test:navigation": "playwright test tests/navigation.spec.ts", + "test:theme": "playwright test tests/theme.spec.ts", + "test:responsive": "playwright test tests/responsive.spec.ts", + "test:components": "playwright test tests/components.spec.ts" }, "dependencies": { "@hookform/resolvers": "^3.9.1", @@ -36,6 +46,7 @@ }, "devDependencies": { "@playwright/test": "^1.54.2", + "@types/node": "^22.10.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@typescript-eslint/eslint-plugin": "^8.39.1", @@ -56,7 +67,9 @@ "prettier": "^3.3.3", "prettier-plugin-tailwindcss": "^0.6.14", "tailwindcss": "^3.4.14", + "tsx": "^4.19.2", "typescript": "^5.6.3", + "typescript-eslint": "^8.39.1", "vite": "^6.0.1" }, "keywords": [ diff --git a/reactrebuild0825/src/App.tsx b/reactrebuild0825/src/App.tsx index 34c8025..4b12c87 100644 --- a/reactrebuild0825/src/App.tsx +++ b/reactrebuild0825/src/App.tsx @@ -1,24 +1,130 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; +import { ProtectedRoute, AdminRoute } from './components/auth/ProtectedRoute'; +import { AppErrorBoundary } from './components/errors/AppErrorBoundary'; import { GlassShowcase } from './components/GlassShowcase'; +import { AppLayout } from './components/layout/AppLayout'; +import { RouteSuspense } from './components/loading/RouteSuspense'; import { ThemeDocumentation } from './components/ThemeDocumentation'; +import { AuthProvider } from './contexts/AuthContext'; import { DashboardPage } from './pages/DashboardPage'; +import { + ErrorPage, + NotFoundPage, + UnauthorizedPage, + ServerErrorPage, + NetworkErrorPage +} from './pages/ErrorPage'; import { EventsPage } from './pages/EventsPage'; import { HomePage } from './pages/HomePage'; +import { LoginPage } from './pages/LoginPage'; -function App() { +function App(): JSX.Element { return ( - -
- - } /> - } /> - } /> + + + + + + {/* Public routes without authentication */} + } /> + } /> } /> } /> + + {/* Protected routes with layout */} + + + + + + } /> + + + + + + } /> + + + + + + } /> + + +
+

Tickets Management

+

Ticket management functionality coming soon...

+
+
+ + } /> + + +
+

Customer Management

+

Customer management functionality coming soon...

+
+
+ + } /> + + +
+

Analytics Dashboard

+

Analytics dashboard coming soon...

+
+
+ + } /> + + +
+

Account Settings

+

Settings page coming soon...

+
+
+ + } /> + + {/* Admin routes */} + + +
+

Admin Panel

+

Admin functionality coming soon...

+
+
+ + } /> + + {/* Error routes */} + } /> + } /> + } /> + } /> + } /> + + {/* 404 catch-all route - must be last */} + } />
-
-
+ + + + ); } diff --git a/reactrebuild0825/src/components/UIShowcase.tsx b/reactrebuild0825/src/components/UIShowcase.tsx new file mode 100644 index 0000000..a32da98 --- /dev/null +++ b/reactrebuild0825/src/components/UIShowcase.tsx @@ -0,0 +1,265 @@ +import { useState } from 'react'; + +import { + Button, + Input, + Select, + Card, + CardHeader, + CardBody, + CardFooter, + Badge, + Alert, + type SelectOption +} from './ui'; + +export function UIShowcase() { + const [inputValue, setInputValue] = useState(''); + const [selectValue, setSelectValue] = useState(''); + const [showAlert, setShowAlert] = useState(true); + + const selectOptions: SelectOption[] = [ + { value: 'option1', label: 'First Option' }, + { value: 'option2', label: 'Second Option' }, + { value: 'option3', label: 'Third Option' }, + { value: 'option4', label: 'Disabled Option', disabled: true }, + ]; + + return ( +
+
+ {/* Header */} +
+

UI Component Showcase

+

+ Premium glassmorphism UI components using design tokens +

+
+ + {/* Alerts */} + {showAlert && ( + setShowAlert(false)} + > + This showcase demonstrates all the UI primitive components with glassmorphism styling. + + )} + + {/* Buttons */} + + +

Buttons

+
+ +
+ {/* Button Variants */} +
+

Variants

+
+ + + + + +
+
+ + {/* Button Sizes */} +
+

Sizes

+
+ + + +
+
+ + {/* Button States */} +
+

States

+
+ + + +
+
+
+
+
+ + {/* Form Inputs */} + + +

Form Inputs

+
+ +
+
+ setInputValue(e.target.value)} + helperText="We'll never share your email" + /> + + + + + } + /> +
+ + + +