inital
This commit is contained in:
437
frontend/DEVELOPER_GUIDE.md
Normal file
437
frontend/DEVELOPER_GUIDE.md
Normal file
@@ -0,0 +1,437 @@
|
||||
# Developer Quick Reference Guide
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### 1. Adding Notifications to a Component
|
||||
|
||||
```typescript
|
||||
import { useNotification } from '../contexts/NotificationContext';
|
||||
|
||||
function MyComponent() {
|
||||
const notification = useNotification();
|
||||
|
||||
const handleAction = async () => {
|
||||
try {
|
||||
await performAction();
|
||||
notification.showSuccess('Aktion erfolgreich durchgeführt');
|
||||
} catch (error) {
|
||||
notification.showError('Aktion fehlgeschlagen');
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Implementing Loading States
|
||||
|
||||
```typescript
|
||||
import { useState, useEffect } from 'react';
|
||||
import SkeletonCard from '../components/shared/SkeletonCard';
|
||||
import { Fade } from '@mui/material';
|
||||
|
||||
function MyComponent() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [data, setData] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData().then(data => {
|
||||
setData(data);
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return <SkeletonCard variant="basic" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fade in={true} timeout={600}>
|
||||
<div>{/* Your content */}</div>
|
||||
</Fade>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Displaying Empty States
|
||||
|
||||
```typescript
|
||||
import EmptyState from '../components/shared/EmptyState';
|
||||
import { FolderOpen } from '@mui/icons-material';
|
||||
|
||||
function DataList({ items }) {
|
||||
if (items.length === 0) {
|
||||
return (
|
||||
<EmptyState
|
||||
icon={<FolderOpen />}
|
||||
title="Keine Daten vorhanden"
|
||||
message="Es wurden noch keine Einträge erstellt."
|
||||
action={{
|
||||
label: 'Neuen Eintrag erstellen',
|
||||
onClick: () => navigate('/create')
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <div>{/* Render items */}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. API Calls with Error Handling
|
||||
|
||||
```typescript
|
||||
import { api } from '../services/api';
|
||||
import { useNotification } from '../contexts/NotificationContext';
|
||||
|
||||
function MyComponent() {
|
||||
const notification = useNotification();
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await api.get('/endpoint');
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
notification.showError(
|
||||
error.message || 'Fehler beim Laden der Daten'
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Protected Route Pattern
|
||||
|
||||
```typescript
|
||||
import ProtectedRoute from '../components/auth/ProtectedRoute';
|
||||
|
||||
// In App.tsx or routing configuration
|
||||
<Route
|
||||
path="/protected"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<MyProtectedComponent />
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
```
|
||||
|
||||
### 6. Accessing Auth Context
|
||||
|
||||
```typescript
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
|
||||
function MyComponent() {
|
||||
const { user, isAuthenticated, logout } = useAuth();
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Willkommen, {user?.name}</p>
|
||||
<button onClick={logout}>Abmelden</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Using Custom Theme
|
||||
|
||||
```typescript
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
function MyComponent() {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: theme.palette.primary.contrastText,
|
||||
padding: theme.spacing(2),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
}}
|
||||
>
|
||||
Content
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Accessibility Best Practices
|
||||
|
||||
```typescript
|
||||
// Always add ARIA labels
|
||||
<IconButton
|
||||
aria-label="Menü öffnen"
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
|
||||
// Use Tooltips for icon-only buttons
|
||||
<Tooltip title="Einstellungen öffnen">
|
||||
<IconButton aria-label="Einstellungen öffnen">
|
||||
<SettingsIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
// Proper form labels
|
||||
<TextField
|
||||
label="E-Mail-Adresse"
|
||||
type="email"
|
||||
required
|
||||
aria-required="true"
|
||||
helperText="Bitte geben Sie eine gültige E-Mail-Adresse ein"
|
||||
/>
|
||||
```
|
||||
|
||||
### 9. Responsive Design Pattern
|
||||
|
||||
```typescript
|
||||
import { Box, useMediaQuery, useTheme } from '@mui/material';
|
||||
|
||||
function MyComponent() {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
padding: isMobile ? 2 : 4,
|
||||
flexDirection: isMobile ? 'column' : 'row',
|
||||
}}
|
||||
>
|
||||
{/* Content */}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 10. Staggered Animations
|
||||
|
||||
```typescript
|
||||
import { Fade } from '@mui/material';
|
||||
|
||||
function ItemList({ items }) {
|
||||
return (
|
||||
<>
|
||||
{items.map((item, index) => (
|
||||
<Fade
|
||||
key={item.id}
|
||||
in={true}
|
||||
timeout={600}
|
||||
style={{ transitionDelay: `${index * 100}ms` }}
|
||||
>
|
||||
<div>{item.name}</div>
|
||||
</Fade>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Common Components
|
||||
|
||||
### SkeletonCard Variants
|
||||
|
||||
```typescript
|
||||
// Basic skeleton - simple text lines
|
||||
<SkeletonCard variant="basic" />
|
||||
|
||||
// With avatar - includes circular avatar
|
||||
<SkeletonCard variant="withAvatar" />
|
||||
|
||||
// Detailed - complex content with image
|
||||
<SkeletonCard variant="detailed" />
|
||||
```
|
||||
|
||||
### Notification Severity Levels
|
||||
|
||||
```typescript
|
||||
const notification = useNotification();
|
||||
|
||||
// Success (green)
|
||||
notification.showSuccess('Erfolgreich gespeichert');
|
||||
|
||||
// Error (red)
|
||||
notification.showError('Fehler beim Speichern');
|
||||
|
||||
// Warning (orange)
|
||||
notification.showWarning('Bitte überprüfen Sie Ihre Eingabe');
|
||||
|
||||
// Info (blue)
|
||||
notification.showInfo('Dies ist eine Information');
|
||||
```
|
||||
|
||||
## Styling Patterns
|
||||
|
||||
### Using Theme Colors
|
||||
|
||||
```typescript
|
||||
// Primary color
|
||||
sx={{ color: 'primary.main' }}
|
||||
sx={{ bgcolor: 'primary.light' }}
|
||||
|
||||
// Error/Success/Warning/Info
|
||||
sx={{ color: 'error.main' }}
|
||||
sx={{ bgcolor: 'success.light' }}
|
||||
|
||||
// Text colors
|
||||
sx={{ color: 'text.primary' }}
|
||||
sx={{ color: 'text.secondary' }}
|
||||
|
||||
// Background
|
||||
sx={{ bgcolor: 'background.default' }}
|
||||
sx={{ bgcolor: 'background.paper' }}
|
||||
```
|
||||
|
||||
### Spacing
|
||||
|
||||
```typescript
|
||||
// Using theme spacing (8px base)
|
||||
sx={{
|
||||
p: 2, // padding: 16px
|
||||
mt: 3, // margin-top: 24px
|
||||
mb: 4, // margin-bottom: 32px
|
||||
gap: 2, // gap: 16px
|
||||
}}
|
||||
```
|
||||
|
||||
### Responsive Breakpoints
|
||||
|
||||
```typescript
|
||||
sx={{
|
||||
fontSize: { xs: '1rem', sm: '1.25rem', md: '1.5rem' },
|
||||
display: { xs: 'none', sm: 'block' },
|
||||
width: { xs: '100%', sm: '50%', md: '33.33%' },
|
||||
}}
|
||||
```
|
||||
|
||||
## Error Handling Checklist
|
||||
|
||||
- [ ] Wrap async operations in try-catch
|
||||
- [ ] Show user-friendly error messages
|
||||
- [ ] Log errors to console for debugging
|
||||
- [ ] Handle network errors specifically
|
||||
- [ ] Handle authentication errors (401)
|
||||
- [ ] Handle permission errors (403)
|
||||
- [ ] Provide recovery actions when possible
|
||||
- [ ] Don't expose sensitive error details to users
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. Use React.memo for components that render often
|
||||
2. Use useMemo for expensive calculations
|
||||
3. Use useCallback for event handlers passed to children
|
||||
4. Implement proper loading states
|
||||
5. Use lazy loading for large components
|
||||
6. Optimize images (compress, use correct format)
|
||||
7. Keep bundle size small (check build warnings)
|
||||
8. Use skeleton loaders instead of spinners
|
||||
|
||||
## Accessibility Checklist
|
||||
|
||||
- [ ] All images have alt text
|
||||
- [ ] All form inputs have labels
|
||||
- [ ] All buttons have descriptive text or ARIA labels
|
||||
- [ ] Color is not the only means of conveying information
|
||||
- [ ] Focus indicators are visible
|
||||
- [ ] Keyboard navigation works throughout
|
||||
- [ ] Headings are in logical order (h1, h2, h3...)
|
||||
- [ ] ARIA labels on icon buttons
|
||||
- [ ] Error messages are announced to screen readers
|
||||
|
||||
## Common German Translations
|
||||
|
||||
- Success: "Erfolgreich"
|
||||
- Error: "Fehler"
|
||||
- Loading: "Wird geladen..."
|
||||
- Save: "Speichern"
|
||||
- Cancel: "Abbrechen"
|
||||
- Delete: "Löschen"
|
||||
- Edit: "Bearbeiten"
|
||||
- Create: "Erstellen"
|
||||
- Back: "Zurück"
|
||||
- Settings: "Einstellungen"
|
||||
- Profile: "Profil"
|
||||
- Logout: "Abmelden"
|
||||
- Login: "Anmelden"
|
||||
- Welcome: "Willkommen"
|
||||
- No data: "Keine Daten vorhanden"
|
||||
- Try again: "Erneut versuchen"
|
||||
|
||||
## Testing Commands
|
||||
|
||||
```bash
|
||||
# Development server
|
||||
npm run dev
|
||||
|
||||
# Build for production
|
||||
npm run build
|
||||
|
||||
# Preview production build
|
||||
npm run preview
|
||||
|
||||
# Run linter
|
||||
npm run lint
|
||||
```
|
||||
|
||||
## File Naming Conventions
|
||||
|
||||
- Components: PascalCase (e.g., `MyComponent.tsx`)
|
||||
- Hooks: camelCase with 'use' prefix (e.g., `useMyHook.ts`)
|
||||
- Utilities: camelCase (e.g., `myHelper.ts`)
|
||||
- Types: PascalCase (e.g., `MyType.ts`)
|
||||
- Constants: UPPER_SNAKE_CASE in files named lowercase
|
||||
|
||||
## Import Order
|
||||
|
||||
1. React and React libraries
|
||||
2. Third-party libraries (Material-UI, etc.)
|
||||
3. Internal contexts
|
||||
4. Internal components
|
||||
5. Internal utilities
|
||||
6. Types
|
||||
7. Styles
|
||||
|
||||
Example:
|
||||
```typescript
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { useNotification } from '../contexts/NotificationContext';
|
||||
import MyComponent from '../components/MyComponent';
|
||||
import { formatDate } from '../utils/dateHelpers';
|
||||
import { User } from '../types/auth.types';
|
||||
```
|
||||
|
||||
## Useful VS Code Snippets
|
||||
|
||||
Add to your `.vscode/snippets.code-snippets`:
|
||||
|
||||
```json
|
||||
{
|
||||
"React Component": {
|
||||
"prefix": "rfc",
|
||||
"body": [
|
||||
"import React from 'react';",
|
||||
"",
|
||||
"interface ${1:ComponentName}Props {",
|
||||
" $2",
|
||||
"}",
|
||||
"",
|
||||
"const ${1:ComponentName}: React.FC<${1:ComponentName}Props> = ($3) => {",
|
||||
" return (",
|
||||
" <div>",
|
||||
" $4",
|
||||
" </div>",
|
||||
" );",
|
||||
"};",
|
||||
"",
|
||||
"export default ${1:ComponentName};"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user