1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 10:09:35 +01:00
effigenix/frontend/apps/cli/src/state/navigation-context.tsx
Sebastian Frick c26d72fbe7 feat: TUI-Screens für Inventar und Produktion + API-Client Typ-Migration
Neue TUI-Features:
- Inventar: Lageorte auflisten, anlegen, bearbeiten, (de-)aktivieren
- Produktion: Rezepte auflisten, anlegen, Detail-Ansicht
- Navigation erweitert (Hauptmenü, Routing)

API-Client auf generierte OpenAPI-Typen umgestellt:
- 6 neue Alias-Dateien in @effigenix/types (supplier, category, article,
  customer, inventory, production)
- api-client Re-Exports direkt von @effigenix/types statt via Resources
- Backend: @Schema(requiredProperties) auf 16 Response-Records
- Backend: OpenApiCustomizer für application-layer DTOs (UserDTO, RoleDTO)

Hinweis: Backend-Endpoints für GET /api/recipes und
GET /api/inventory/storage-locations/{id} fehlen noch (separate Issues).
2026-02-19 13:54:29 +01:00

106 lines
2.7 KiB
TypeScript

import React, { createContext, useContext, useReducer } from 'react';
export type Screen =
| 'login'
| 'main-menu'
| 'user-list'
| 'user-create'
| 'user-detail'
| 'change-password'
| 'role-list'
| 'role-detail'
// Stammdaten
| 'masterdata-menu'
| 'category-list'
| 'category-detail'
| 'category-create'
| 'supplier-list'
| 'supplier-detail'
| 'supplier-create'
| 'supplier-rate'
| 'supplier-add-certificate'
| 'article-list'
| 'article-detail'
| 'article-create'
| 'article-add-sales-unit'
| 'customer-list'
| 'customer-detail'
| 'customer-create'
| 'customer-add-delivery-address'
| 'customer-set-preferences'
// Lagerverwaltung
| 'inventory-menu'
| 'storage-location-list'
| 'storage-location-create'
| 'storage-location-detail'
// Produktion
| 'production-menu'
| 'recipe-list'
| 'recipe-create'
| 'recipe-detail';
interface NavigationState {
current: Screen;
history: Screen[];
params: Record<string, string>;
}
type NavigationAction =
| { type: 'NAVIGATE'; screen: Screen; params?: Record<string, string> }
| { type: 'BACK' };
function navigationReducer(state: NavigationState, action: NavigationAction): NavigationState {
switch (action.type) {
case 'NAVIGATE':
return {
current: action.screen,
history: [...state.history, state.current],
params: action.params ?? {},
};
case 'BACK': {
const history = [...state.history];
const previous = history.pop();
if (!previous) return state;
return { current: previous, history, params: {} };
}
}
}
interface NavigationContextValue {
current: Screen;
params: Record<string, string>;
canGoBack: boolean;
navigate: (screen: Screen, params?: Record<string, string>) => void;
back: () => void;
}
const NavigationContext = createContext<NavigationContextValue | null>(null);
interface NavigationProviderProps {
children: React.ReactNode;
initialScreen?: Screen;
}
export function NavigationProvider({ children, initialScreen = 'login' }: NavigationProviderProps) {
const [state, dispatch] = useReducer(navigationReducer, {
current: initialScreen,
history: [],
params: {},
});
const value: NavigationContextValue = {
current: state.current,
params: state.params,
canGoBack: state.history.length > 0,
navigate: (screen, params) => dispatch({ type: 'NAVIGATE', screen, params: params ?? {} }),
back: () => dispatch({ type: 'BACK' }),
};
return <NavigationContext.Provider value={value}>{children}</NavigationContext.Provider>;
}
export function useNavigation(): NavigationContextValue {
const ctx = useContext(NavigationContext);
if (!ctx) throw new Error('useNavigation must be used within NavigationProvider');
return ctx;
}