Files
dashboard/frontend/DEVELOPER_GUIDE.md
Matthias Hochmeister f09748f4a1 inital
2026-02-23 17:08:58 +01:00

9.0 KiB

Developer Quick Reference Guide

Common Patterns

1. Adding Notifications to a Component

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

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

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

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

import ProtectedRoute from '../components/auth/ProtectedRoute';

// In App.tsx or routing configuration
<Route
  path="/protected"
  element={
    <ProtectedRoute>
      <MyProtectedComponent />
    </ProtectedRoute>
  }
/>

6. Accessing Auth Context

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

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

// 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

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

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

// 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

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

// 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

// 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

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

# 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:

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:

{
  "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};"
    ]
  }
}