);
};
// 4. Action buttons use same hook instance + dynamic field access
// src/components/FormGenerator/ActionButtons/ViewActionButton.tsx
const ViewActionButton = ({ row, hookData, idField, nameField, typeField }) => {
// Dynamic field access - works with any data structure
const itemId = (row as any)[idField]; // 'id' or 'user_id' or anything
const itemName = (row as any)[nameField]; // 'file_name' or 'username' or anything
const itemType = (row as any)[typeField]; // 'mime_type' or 'role' or anything
// Use same hook instance for operations
const handlePreview = hookData.handlePreview;
const isPreviewing = hookData.previewingFiles?.has(itemId);
return ;
};
```
### Benefits of the New System
1. **No Component Creation**: Pages defined as data only
2. **Zero Code Duplication**: One PageRenderer handles all pages
3. **Consistent Styling**: All pages use the same CSS classes
4. **Generic Table Support**: Any hook + columns = instant table
5. **Shared Hook State**: All components use the same hook instance - no duplicate API calls
6. **Generic Action Buttons**: Same buttons work with any data type via field mappings
7. **Synchronized Operations**: Delete, view, edit operations update UI immediately
8. **Easy Maintenance**: Change PageRenderer once, affects all pages
9. **Rapid Development**: New pages in minutes, not hours
10. **Type Safety**: Full TypeScript support for page data
11. **Self-Contained**: Everything in one data file
12. **Plug-and-Play**: Just change hook factory and field mappings for different data types
### File Structure (After)
```
src/
├── core/PageManager/
│ ├── data/pages/
│ │ ├── dateien.ts ← Just data + hook factory
│ │ ├── dashboard.ts ← Just data
│ │ └── team-bereich.ts ← Just data
│ ├── PageRenderer.tsx ← One generic renderer
│ ├── PageManager.tsx ← Simplified router
│ └── pageInterface.ts ← Type definitions
├── hooks/
│ └── useFiles.ts ← Existing hook (reused)
└── components/FormGenerator/ ← Existing component (reused)
```
---
## Comparison: Creating a New Page
### BEFORE: Component-Based Approach
**Steps Required:**
1. Create React component (`MyPage.tsx`)
2. Add business logic hook (`useMyPageLogic.tsx`)
3. Create table component (`MyPageTable.tsx`)
4. Add to page configs (`pageConfigs.ts`)
5. Update PageManager routing
6. Add CSS styling
7. Test and debug
**Files Created:** 4-5 files
**Time Required:** 2-4 hours
**Code Lines:** 200-400 lines
```typescript
// MyPage.tsx (50+ lines)
function MyPage() {
const { data, loading, error } = useMyPageLogic();
return (
My Page
);
}
// useMyPageLogic.tsx (100+ lines)
export function useMyPageLogic() {
// Business logic, state management, API calls
}
// MyPageTable.tsx (100+ lines)
export function MyPageTable({ data, loading }) {
// Table rendering logic
}
// pageConfigs.ts
export const pageConfigs = [
// ... existing pages
{ path: 'my-page', component: MyPage, ... }
];
```
### AFTER: Data-Driven Approach
**Steps Required:**
1. Create data file (`my-page.ts`)
2. Define hook factory (if using table)
3. Add to pages index
**Files Created:** 1 file
**Time Required:** 10-15 minutes
**Code Lines:** 30-50 lines
```typescript
// my-page.ts (30-50 lines)
import { useMyData } from '../../../../hooks/useMyData';
const createMyDataHook = () => {
return () => {
const { data, loading, error, refetch } = useMyData();
return { data, loading, error, refetch };
};
};
const myColumns = [
{ key: 'name', label: 'Name', type: 'string', sortable: true },
{ key: 'date', label: 'Date', type: 'date', sortable: true }
];
export const myPageData: GenericPageData = {
id: 'my-page',
path: 'my-page',
name: 'My Page',
title: 'My Page',
subtitle: 'Page description',
content: [{
id: 'my-table',
type: 'table',
tableConfig: {
hookFactory: createMyDataHook,
columns: myColumns,
searchable: true,
sortable: true,
pagination: true
}
}],
privilegeChecker: privilegeCheckers.viewerRole,
showInSidebar: true
};
```
---
## Key Simplifications
### 1. **Elimination of Boilerplate**
- **Before:** 200-400 lines per page
- **After:** 30-50 lines per page
- **Reduction:** 85-90% less code
### 2. **Consistent UI**
- **Before:** Each component managed its own styling
- **After:** One PageRenderer ensures consistency
- **Result:** All pages look and behave identically
### 3. **Generic Table Support**
- **Before:** Custom table component for each page
- **After:** Any hook + columns = instant table
- **Result:** Reuse existing FormGenerator component
### 4. **Shared Hook State**
- **Before:** Each component calls hooks independently
- **After:** All components share the same hook instance
- **Result:** No duplicate API calls, synchronized state, immediate UI updates
### 5. **Generic Action Buttons**
- **Before:** Custom action buttons for each data type
- **After:** Same action buttons work with any data type via field mappings
- **Result:** ViewActionButton works with files, users, or any other data structure
### 6. **Rapid Development**
- **Before:** 2-4 hours per page
- **After:** 10-15 minutes per page
- **Improvement:** 10x faster development
### 7. **Maintenance**
- **Before:** Update multiple files for UI changes
- **After:** Update PageRenderer once
- **Result:** Changes propagate to all pages
### 8. **Type Safety**
- **Before:** Manual prop typing in each component
- **After:** Centralized TypeScript interfaces
- **Result:** Better IDE support and error catching
---
## Complete Data Flow
### Hook Factory Pattern
```typescript
// 1. Page data defines hook factory
const createFilesHook = () => {
return () => {
const { files, loading, error, refetch } = useUserFiles();
const { handleDownload, handleDelete, handlePreview } = useFileOperations();
return { data: files, loading, error, refetch, handleDownload, handleDelete, handlePreview };
};
};
```
### Data Flow Through Components
```
Page Data (dateien.ts)
↓ defines hookFactory + field mappings
Page Renderer (PageRenderer.tsx)
↓ calls hookFactory() → gets hook instance
Form Generator (FormGenerator.tsx)
↓ receives same hook instance + field mappings
Action Buttons (ViewActionButton, DeleteActionButton, etc.)
↓ uses same hook instance + dynamic field access
Shared State & Operations
```
### Key Benefits of This Flow
1. **Single Hook Instance**: All components use the exact same hook instance
2. **No Duplicate API Calls**: Data is fetched once, shared everywhere
3. **Synchronized State**: Changes in one component immediately reflect in others
4. **Generic Action Buttons**: Same buttons work with any data type via field mappings
5. **Immediate UI Updates**: Delete operations update UI instantly with optimistic updates
6. **Plug-and-Play**: Just change hook factory and field mappings for different data types
### Example: Files vs Users
**Files Page:**
```typescript
actionButtons: [
{
type: 'view',
idField: 'id', // 'id' field
nameField: 'file_name', // 'file_name' field
typeField: 'mime_type' // 'mime_type' field
}
]
```
**Users Page (same action buttons, different fields):**
```typescript
actionButtons: [
{
type: 'view',
idField: 'user_id', // 'user_id' field
nameField: 'username', // 'username' field
typeField: 'role' // 'role' field
}
]
```
The ViewActionButton component works with both by using dynamic field access:
```typescript
const itemId = (row as any)[idField]; // Works with any field name
const itemName = (row as any)[nameField]; // Works with any field name
const itemType = (row as any)[typeField]; // Works with any field name
```
---
## Migration Path
### Existing Pages
1. Extract page data from component
2. Create data file with same structure
3. Remove old component file
4. Update page registry
### New Pages
1. Create data file
2. Add to pages index
3. Done!
---
## Summary
The new data-driven system transforms page creation from a complex, time-consuming process requiring multiple files and components into a simple, declarative data configuration. This approach:
- **Reduces complexity** by 85-90%
- **Increases development speed** by 10x
- **Ensures consistency** across all pages
- **Simplifies maintenance** with centralized rendering
- **Reuses existing components** (FormGenerator, hooks)
- **Maintains type safety** with TypeScript
The result is a system where creating a new page is as simple as writing a JSON-like configuration file, while still maintaining all the power and flexibility of the original component-based approach.