ui-nyla/src/hooks/useCurrentInstance.ts
2026-01-20 00:56:00 +01:00

133 lines
3.5 KiB
TypeScript

/**
* useCurrentInstance Hook
*
* Liest die aktuelle Feature-Instanz aus den URL-Parametern.
* Die URL-Struktur ist: /mandates/:mandateId/:featureCode/:instanceId/...
*
* Dieser Hook ist die zentrale Stelle um den aktuellen Arbeitskontext zu ermitteln.
*/
import { useParams } from 'react-router-dom';
import { useFeatureStore } from '../stores/featureStore';
import type { FeatureInstance, Mandate, MandateFeature } from '../types/mandate';
// =============================================================================
// URL PARAMETER TYPES
// =============================================================================
// Route-Parameter werden als Record<string, string | undefined> erwartet
// Wir verwenden daher einen einfachen Typ-Alias
// =============================================================================
// RETURN TYPES
// =============================================================================
export interface CurrentInstanceContext {
// Aus URL
mandateId: string | undefined;
featureCode: string | undefined;
instanceId: string | undefined;
// Aufgelöste Objekte
mandate: Mandate | undefined;
feature: MandateFeature | undefined;
instance: FeatureInstance | undefined;
// Hilfsfunktionen
isValid: boolean;
isLoading: boolean;
}
// =============================================================================
// HOOKS
// =============================================================================
/**
* Haupthook für den aktuellen Instanz-Kontext
*
* Verwendung:
* ```tsx
* function ContractList() {
* const { instance, isValid } = useCurrentInstance();
*
* if (!isValid) {
* return <Navigate to="/" />;
* }
*
* // Arbeite mit instance.permissions, etc.
* }
* ```
*/
export function useCurrentInstance(): CurrentInstanceContext {
const params = useParams();
const { getMandateById, getFeatureByCode, getInstanceById, loading } = useFeatureStore();
const mandateId = params.mandateId;
const featureCode = params.featureCode;
const instanceId = params.instanceId;
// Objekte auflösen
const mandate = mandateId ? getMandateById(mandateId) : undefined;
const feature = mandateId && featureCode ? getFeatureByCode(mandateId, featureCode) : undefined;
const instance = instanceId ? getInstanceById(instanceId) : undefined;
// Validierung: Alle drei müssen vorhanden und konsistent sein
const isValid = !!(
mandate &&
feature &&
instance &&
instance.mandateId === mandateId &&
instance.featureCode === featureCode
);
return {
mandateId,
featureCode,
instanceId,
mandate,
feature,
instance,
isValid,
isLoading: loading,
};
}
/**
* Vereinfachter Hook - gibt nur die Instanz zurück
*/
export function useInstance(): FeatureInstance | undefined {
const { instance } = useCurrentInstance();
return instance;
}
/**
* Hook für die Instanz-ID aus der URL
*/
export function useInstanceId(): string | undefined {
const params = useParams();
return params.instanceId;
}
/**
* Hook für den Feature-Code aus der URL
*/
export function useFeatureCode(): string | undefined {
const params = useParams();
return params.featureCode;
}
/**
* Hook für die Mandate-ID aus der URL
*/
export function useMandateId(): string | undefined {
const params = useParams();
return params.mandateId;
}
/**
* Hook der prüft ob wir in einem Feature-Kontext sind
*/
export function useIsInFeatureContext(): boolean {
const { isValid } = useCurrentInstance();
return isValid;
}