-
This commit is contained in:
182
frontend/src/contexts/ModuleContext.tsx
Normal file
182
frontend/src/contexts/ModuleContext.tsx
Normal file
@@ -0,0 +1,182 @@
|
||||
import { createContext, useContext, useCallback, type ReactNode } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { moduleService } from "../services/moduleService";
|
||||
import type {
|
||||
ModuleDto,
|
||||
EnableModuleRequest,
|
||||
SubscriptionDto,
|
||||
} from "../types/module";
|
||||
|
||||
// ==================== TYPES ====================
|
||||
|
||||
export interface ModuleContextValue {
|
||||
/** Lista di tutti i moduli disponibili */
|
||||
modules: ModuleDto[];
|
||||
/** Lista dei moduli attualmente attivi */
|
||||
activeModules: ModuleDto[];
|
||||
/** Codici dei moduli attivi (per filtro veloce) */
|
||||
activeModuleCodes: string[];
|
||||
/** Stato di caricamento */
|
||||
isLoading: boolean;
|
||||
/** Errore di caricamento */
|
||||
error: Error | null;
|
||||
/** Verifica se un modulo è abilitato */
|
||||
isModuleEnabled: (code: string) => boolean;
|
||||
/** Ottiene un modulo per codice */
|
||||
getModule: (code: string) => ModuleDto | undefined;
|
||||
/** Attiva un modulo */
|
||||
enableModule: (
|
||||
code: string,
|
||||
request: EnableModuleRequest,
|
||||
) => Promise<SubscriptionDto>;
|
||||
/** Disattiva un modulo */
|
||||
disableModule: (code: string) => Promise<void>;
|
||||
/** Ricarica i dati dei moduli */
|
||||
refreshModules: () => Promise<void>;
|
||||
}
|
||||
|
||||
const ModuleContext = createContext<ModuleContextValue | null>(null);
|
||||
|
||||
// ==================== PROVIDER ====================
|
||||
|
||||
interface ModuleProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function ModuleProvider({ children }: ModuleProviderProps) {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// Query per tutti i moduli
|
||||
const {
|
||||
data: modules = [],
|
||||
isLoading: isLoadingModules,
|
||||
error: modulesError,
|
||||
} = useQuery({
|
||||
queryKey: ["modules"],
|
||||
queryFn: moduleService.getAll,
|
||||
staleTime: 5 * 60 * 1000, // 5 minuti
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
// Query per moduli attivi
|
||||
const {
|
||||
data: activeModules = [],
|
||||
isLoading: isLoadingActive,
|
||||
error: activeError,
|
||||
} = useQuery({
|
||||
queryKey: ["modules", "active"],
|
||||
queryFn: moduleService.getActive,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
// Calcola i codici dei moduli attivi
|
||||
const activeModuleCodes = activeModules.map((m) => m.code);
|
||||
|
||||
// Verifica se un modulo è abilitato
|
||||
const isModuleEnabled = useCallback(
|
||||
(code: string): boolean => {
|
||||
return activeModuleCodes.includes(code);
|
||||
},
|
||||
[activeModuleCodes],
|
||||
);
|
||||
|
||||
// Ottiene un modulo per codice
|
||||
const getModule = useCallback(
|
||||
(code: string): ModuleDto | undefined => {
|
||||
return modules.find((m) => m.code === code);
|
||||
},
|
||||
[modules],
|
||||
);
|
||||
|
||||
// Attiva un modulo
|
||||
const enableModule = useCallback(
|
||||
async (
|
||||
code: string,
|
||||
request: EnableModuleRequest,
|
||||
): Promise<SubscriptionDto> => {
|
||||
const subscription = await moduleService.enable(code, request);
|
||||
// Invalida le query per ricaricare i dati
|
||||
await queryClient.invalidateQueries({ queryKey: ["modules"] });
|
||||
return subscription;
|
||||
},
|
||||
[queryClient],
|
||||
);
|
||||
|
||||
// Disattiva un modulo
|
||||
const disableModule = useCallback(
|
||||
async (code: string): Promise<void> => {
|
||||
await moduleService.disable(code);
|
||||
// Invalida le query per ricaricare i dati
|
||||
await queryClient.invalidateQueries({ queryKey: ["modules"] });
|
||||
},
|
||||
[queryClient],
|
||||
);
|
||||
|
||||
// Ricarica i dati dei moduli
|
||||
const refreshModules = useCallback(async (): Promise<void> => {
|
||||
await queryClient.invalidateQueries({ queryKey: ["modules"] });
|
||||
}, [queryClient]);
|
||||
|
||||
const value: ModuleContextValue = {
|
||||
modules,
|
||||
activeModules,
|
||||
activeModuleCodes,
|
||||
isLoading: isLoadingModules || isLoadingActive,
|
||||
error: modulesError || activeError,
|
||||
isModuleEnabled,
|
||||
getModule,
|
||||
enableModule,
|
||||
disableModule,
|
||||
refreshModules,
|
||||
};
|
||||
|
||||
return (
|
||||
<ModuleContext.Provider value={value}>{children}</ModuleContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
// ==================== HOOKS ====================
|
||||
|
||||
/**
|
||||
* Hook per accedere al context dei moduli
|
||||
*/
|
||||
export function useModules(): ModuleContextValue {
|
||||
const context = useContext(ModuleContext);
|
||||
if (!context) {
|
||||
throw new Error("useModules must be used within a ModuleProvider");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook per verificare se un singolo modulo è abilitato
|
||||
*/
|
||||
export function useModuleEnabled(code: string): boolean {
|
||||
const { isModuleEnabled } = useModules();
|
||||
return isModuleEnabled(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook per ottenere solo i moduli attivi
|
||||
*/
|
||||
export function useActiveModules(): ModuleDto[] {
|
||||
const { activeModules } = useModules();
|
||||
return activeModules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook per ottenere i codici dei moduli attivi
|
||||
*/
|
||||
export function useActiveModuleCodes(): string[] {
|
||||
const { activeModuleCodes } = useModules();
|
||||
return activeModuleCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook per ottenere un modulo specifico
|
||||
*/
|
||||
export function useModule(code: string): ModuleDto | undefined {
|
||||
const { getModule } = useModules();
|
||||
return getModule(code);
|
||||
}
|
||||
Reference in New Issue
Block a user