Development
Standards de Code
Standards et conventions de code pour Company Manager.
Standards de Code
Ce document définit les standards et conventions de code à suivre pour le développement de Company Manager.
TypeScript
Configuration
{
"compilerOptions": {
"strict": true,
"target": "ES2022",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/*": ["./src/*"]
}
}
}Types et Interfaces
// Préférer les interfaces pour les objets
interface User {
id: string;
name: string;
email: string;
}
// Utiliser les types pour les unions/intersections
type Status = 'active' | 'inactive';
type UserWithRole = User & { role: string };React
Structure des Composants
// Composant exemple
import { useState, useEffect } from 'react';
import type { FC } from 'react';
interface Props {
data: Data;
onUpdate: (data: Data) => void;
}
export const Component: FC<Props> = ({ data, onUpdate }) => {
// 1. Hooks d'état
const [state, setState] = useState(initial);
// 2. Autres hooks
useEffect(() => {
// ...
}, []);
// 3. Handlers
const handleClick = () => {
// ...
};
// 4. Render helpers
const renderItem = (item: Item) => {
return <div key={item.id}>{item.name}</div>;
};
// 5. JSX
return (
<div>
{/* ... */}
</div>
);
};Styles
Tailwind CSS
// Préférer les classes utilitaires
const Button = () => (
<button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Click me
</button>
);
// Utiliser les variants pour les composants complexes
const variants = {
primary: "bg-blue-500 hover:bg-blue-600",
secondary: "bg-gray-500 hover:bg-gray-600",
};Tests
Convention de Nommage
describe('Component', () => {
describe('when condition', () => {
it('should do something', () => {
// ...
});
});
});Organisation
// 1. Imports
import { render, screen } from '@testing-library/react';
// 2. Mocks
jest.mock('./service');
// 3. Setup/Teardown
beforeEach(() => {
// ...
});
// 4. Tests
describe('Component', () => {
// ...
});API et Services
Structure
// Service exemple
export class UserService {
// 1. Propriétés privées
private readonly api: Api;
// 2. Constructeur
constructor(api: Api) {
this.api = api;
}
// 3. Méthodes publiques
async getUser(id: string): Promise<User> {
// ...
}
// 4. Méthodes privées
private validateUser(user: User): boolean {
// ...
}
}Gestion d'État
Zustand
// Store exemple
interface Store {
// 1. État
data: Data[];
loading: boolean;
error: Error | null;
// 2. Actions
fetchData: () => Promise<void>;
addData: (item: Data) => void;
removeData: (id: string) => void;
}
const useStore = create<Store>((set) => ({
// État initial
data: [],
loading: false,
error: null,
// Actions
fetchData: async () => {
set({ loading: true });
try {
const data = await api.getData();
set({ data, loading: false });
} catch (error) {
set({ error, loading: false });
}
},
// ...
}));Documentation
JSDoc
/**
* Description de la fonction
* @param param1 - Description du paramètre 1
* @param param2 - Description du paramètre 2
* @returns Description du retour
* @throws {Error} Description de l'erreur
*/
function example(param1: string, param2: number): Result {
// ...
}Git
Messages de Commit
type(scope): description
[corps]
[footer]Types:
- feat: nouvelle fonctionnalité
- fix: correction de bug
- docs: documentation
- style: formatage
- refactor: refactorisation
- test: ajout/modification de tests
- chore: maintenance
Sécurité
Validation des Données
// Schéma Zod
const userSchema = z.object({
email: z.string().email(),
password: z.string().min(8).regex(/[A-Z]/).regex(/[0-9]/),
role: z.enum(['user', 'admin']),
});
// Validation
const validateUser = (data: unknown): User => {
return userSchema.parse(data);
};Performance
Optimisations React
// Mémoisation des composants
const MemoizedComponent = memo(Component, (prev, next) => {
return prev.id === next.id;
});
// Hooks personnalisés
const useDebounce = (value: string, delay: number) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(timer);
};
}, [value, delay]);
return debouncedValue;
};