Skip to content

Commit

Permalink
feat: refactor, typed enhacement (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
SAINIAbhishek authored Nov 20, 2024
1 parent f98db0e commit 7e95639
Show file tree
Hide file tree
Showing 87 changed files with 715 additions and 934 deletions.
33 changes: 18 additions & 15 deletions frontend/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
module.exports = {
root: true,
env: { browser: true, es2020: true, node: true },
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:react-hooks/recommended',
'plugin:react/jsx-runtime',
'plugin:prettier/recommended',
'plugin:react-query/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
ignorePatterns: ['dist', '.eslintrc.cjs'], // Ignore output and config files
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
ecmaVersion: 'latest', // Parse latest ECMAScript features
sourceType: 'module', // Enable import/export syntax
ecmaFeatures: {
jsx: true, // Allows for the parsing of JSX,
jsx: true, // Enable JSX syntax parsing
},
project: ['./tsconfig.json', './vite.config.ts'], // Use TypeScript project settings for type checking
tsconfigRootDir: __dirname, // Set the root directory for TypeScript config files relative to this file
},
plugins: ['react-refresh', 'prettier', 'react-query'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
{ allowConstantExport: true }, // Warn when non-component exports are found
],
'no-use-before-define': 'off',
semi: ['error', 'always'],
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'react/no-unescaped-entities': 'off',
'react/react-in-jsx-scope': 'off',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'no-use-before-define': 'off', // TypeScript handles this rule well
semi: ['error', 'always'], // Enforce semicolons at the end of statements
'@typescript-eslint/ban-ts-ignore': 'off', // Allow @ts-ignore (use cautiously)
'@typescript-eslint/no-explicit-any': 'off', // Allow 'any' type (can be tightened later)
'react/no-unescaped-entities': 'off', // Allow unescaped characters in JSX (like `&`)
'react-hooks/rules-of-hooks': 'error', // Enforce React Hooks rules
'react-hooks/exhaustive-deps': 'warn', // Warn about missing dependencies in hooks
'@typescript-eslint/no-unsafe-argument': 'warn',
},
};
113 changes: 113 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,116 @@ If you are developing a production application, we recommend updating the config
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list

## TypeScript Configuration Documentation

1. Main TypeScript Configuration (tsconfig.json)

```json
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"isolatedModules": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"resolveJsonModule": true,
"allowImportingTsExtensions": true,
"noEmit": true,
"types": ["vite/client"],
"typeRoots": ["./@types", "./node_modules/@types"]
}
```

## Explanation of compilerOptions

- **target: "ESNext":** Set the JavaScript language version for the output code to the latest ECMAScript features.
- **module: "ESNext":** Use the latest ECMAScript module features like import and export.
- **moduleResolution: "bundler":** Tells TypeScript how to resolve modules, optimized for bundlers like Vite.
- **jsx: "react-jsx":** Enable the React 17 JSX transform without needing to import React in each JSX file.
- **strict: true:** Enables strict type-checking settings for better type safety.
- **noImplicitAny: true:** Prevents variables from being implicitly typed as any.
- **strictNullChecks: true:** Makes null and undefined distinct types, improving type safety.
- **noUnusedLocals: true:** Flags unused local variables as errors.
- **noUnusedParameters: true:** Flags unused parameters in functions as errors.
- **noFallthroughCasesInSwitch: true:** Prevents fall-through cases in switch statements.
- **forceConsistentCasingInFileNames:** true: Enforces consistent casing for file names, helping avoid issues across different file systems.
- **isolatedModules: true:** Ensures that TypeScript files can be transpiled independently, which is useful for bundling tools.
- **allowSyntheticDefaultImports: true:** Allows default imports from non-default-exporting modules.
- **esModuleInterop: true:** Allows compatibility with CommonJS-style modules.
- **lib: ["ESNext", "DOM", "DOM.Iterable"]:** Specifies the libraries to include during compilation, ensuring support for the latest JavaScript and DOM features.
- **resolveJsonModule: true:** Allows importing JSON files as modules.
- **allowImportingTsExtensions: true:** Enables importing TypeScript files with .ts and .tsx extensions.
- **noEmit: true:** Prevents TypeScript from emitting JavaScript files during compilation, useful when using a bundler.
- **types: ["vite/client"]:** Specifies types related to Vite’s client-side environment for better type checking.
- **typeRoots: ["./@types", "./node_modules/@types"]:** Defines directories where TypeScript should look for type declarations.

## Includes and Excludes

```json
"include": ["src/**/*.ts", "src/**/*.tsx", "./vite.config.ts"],,
"exclude": ["node_modules", "dist"]
```

- **include:** Specifies the files to include in the compilation process, such as all .ts and .tsx files inside the src directory.
- **exclude:** Excludes certain directories (e.g., node_modules, dist) from being compiled by TypeScript.

## Extending Other Configurations

```json
"extends": "./tsconfig.paths.json",
"references": []
```

- **extends:** This allows tsconfig.json to inherit settings from tsconfig.paths.json, which handles path alias configurations.
- **references:** In a multi-project setup, this field is used to reference other TypeScript projects. It is left empty here since it's not needed.

2. Path Aliases (tsconfig.paths.json)

```json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
```

## Path Aliases Explanation

- **baseUrl:** Defines the base directory for resolving non-relative module names. By setting it to ".", we specify that the root directory of the project is the base directory.
- **paths:** This configures path aliases to simplify imports. For example, "@/_": ["./src/_"] allows importing files from the src directory using the @ alias:

3. Test Configuration (tsconfig.test.json)

```json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"types": ["vitest/globals", "vitest", "@testing-library/jest-dom"],
"noUnusedLocals": false,
"noUnusedParameters": false
}
}
```

## Test Configuration Explanation

- **extends:** Inherits from tsconfig.base.json, so the settings from the base configuration are shared across all configurations.
- **types:** Specifies additional type definitions for testing. This includes types for Vitest and Jest DOM, which are commonly used in testing React components:
- **vitest/globals:** Global types for Vitest.
- **vitest:** Types for Vitest itself.
- **@testing-library/jest-dom:** Types for testing React components with Jest DOM.
- **noUnusedLocals and noUnusedParameters:** These are set to false during testing to allow temporary or incomplete code while writing tests, where unused variables and parameters might be present.
25 changes: 6 additions & 19 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fullstack_tasks-frontend",
"version": "1.2.0",
"version": "1.3.0",
"description": "",
"type": "module",
"scripts": {
Expand All @@ -27,10 +27,9 @@
"@fortawesome/react-fontawesome": "^0.2.2",
"@fvilers/disable-react-devtools": "^1.3.0",
"@tanstack/react-query": "^5.51.23",
"axios": "^1.7.5",
"axios": "^1.7.7",
"date-fns": "^2.30.0",
"dompurify": "^3.1.7",
"dotenv": "^16.4.5",
"formik": "^2.4.6",
"i18next": "^23.12.2",
"react": "^18.3.1",
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/api/auth.api.ts → frontend/src/api/AuthApi.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { RegisterType } from '@/features/auth/types/register.type';
import { protectedRequest, publicRequest } from '@/lib/axios';
import { LoginType } from '@/features/auth/types/login.type';
import { ResetPasswordType } from '@/features/auth/types/reset-password.type';
import { ApiBaseResponse } from '@/types/api-base.type';
import { RegisterType } from '@/types/RegisterType';
import { protectedRequest, publicRequest } from '@/lib/axios/Axios';
import { LoginType } from '@/types/LoginType';
import { ResetPasswordType } from '@/types/ResetPasswordType';
import { ApiBaseResponse } from '@/types/ApiBaseType';
import {
ForgotPasswordResponse,
ForgotPasswordType,
} from '@/features/auth/types/forgot-password.type';
} from '@/types/ForgotPasswordType';

export const API_REFRESH_TOKEN = async () => {
return await protectedRequest<null, ApiBaseResponse>({
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/api/task.api.ts → frontend/src/api/TaskApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { protectedRequest } from '@/lib/axios';
import { protectedRequest } from '@/lib/axios/Axios';
import {
TaskDeleteResponse,
TaskResponse,
Expand All @@ -7,7 +7,7 @@ import {
UpdateCompletedTaskType,
UpdateImportantTaskType,
UpdateTaskType,
} from '@/features/tasks/types/task.type';
} from '@/types/TaskType';

export const API_TASK_UPDATE = async (data: UpdateTaskType) => {
return await protectedRequest<
Expand Down
14 changes: 7 additions & 7 deletions frontend/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import '@/lib/i18n';
import AppProvider from '@/providers/app-provider';
import AppRoute from '@/routes';
import AuthProvider from '@/providers/auth-provider';
import { queryClient } from '@/lib/react-query';
import '@/lib/i18n/i18n';
import AppProvider from '@/contexts/app-context/AppProvider';
import AppRoutes from '@/routes/Routes';
import { queryClient } from '@/lib/react-query/ReactQuery';
import { Toaster } from 'react-hot-toast';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import useDisableReactDevTools from '@/hooks/useDisableReactDevTools';
import useDisableReactDevTools from '@/hooks/use-disable-react-dev-tools/useDisableReactDevTools';
import AuthProvider from '@/contexts/auth-context/AuthProvider';

const App = () => {
// Disable React DevTools in production
Expand All @@ -17,7 +17,7 @@ const App = () => {
<Toaster position="bottom-left" />
<AuthProvider>
<AppProvider>
<AppRoute />
<AppRoutes />
</AppProvider>
</AuthProvider>
{/* React Query DevTools for debugging */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ const IconButton = ({
}: IconButtonProps) => {
const { t } = useTranslation();

const handleButtonClick = () => {
if (!isDisabled && !isLoading && handleClick) {
handleClick();
}
};

return (
<button
type={type}
title={title && t(title)}
disabled={isDisabled}
onClick={handleClick}
disabled={isDisabled || isLoading}
onClick={handleButtonClick}
className={`font-medium text-sm p-2.5 text-center inline-flex items-center
mr-2 text-blue-500 hover:text-white rounded-full hover:bg-blue-500 ${
isDisabled || isLoading ? 'cursor-not-allowed' : ''
Expand Down
Loading

0 comments on commit 7e95639

Please sign in to comment.