Files
Benjamin Boenisch 5a31f52310 Initial commit: breakpilot-lehrer - Lehrer KI Platform
Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website,
Klausur-Service, School-Service, Voice-Service, Geo-Service,
BreakPilot Drive, Agent-Core

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 23:47:26 +01:00

122 lines
3.6 KiB
TypeScript

'use client'
import React, { createContext, useContext, useReducer, useMemo } from 'react'
import type { CustomCatalogEntry, CustomCatalogs, CatalogId } from './catalog-manager/types'
// =============================================================================
// SIMPLIFIED STATE (Admin-Lehrer only needs catalog-manager state)
// =============================================================================
export interface SDKState {
customCatalogs: CustomCatalogs
}
export type SDKAction =
| { type: 'ADD_CUSTOM_CATALOG_ENTRY'; payload: CustomCatalogEntry }
| { type: 'UPDATE_CUSTOM_CATALOG_ENTRY'; payload: { catalogId: CatalogId; entryId: string; data: Record<string, unknown> } }
| { type: 'DELETE_CUSTOM_CATALOG_ENTRY'; payload: { catalogId: CatalogId; entryId: string } }
| { type: 'SET_STATE'; payload: Partial<SDKState> }
export const initialState: SDKState = {
customCatalogs: {},
}
// =============================================================================
// REDUCER
// =============================================================================
function sdkReducer(state: SDKState, action: SDKAction): SDKState {
switch (action.type) {
case 'ADD_CUSTOM_CATALOG_ENTRY': {
const entry = action.payload
const existing = state.customCatalogs[entry.catalogId] || []
return {
...state,
customCatalogs: {
...state.customCatalogs,
[entry.catalogId]: [...existing, entry],
},
}
}
case 'UPDATE_CUSTOM_CATALOG_ENTRY': {
const { catalogId, entryId, data } = action.payload
const existing = state.customCatalogs[catalogId] || []
return {
...state,
customCatalogs: {
...state.customCatalogs,
[catalogId]: existing.map(e =>
e.id === entryId
? { ...e, data, updatedAt: new Date().toISOString() }
: e
),
},
}
}
case 'DELETE_CUSTOM_CATALOG_ENTRY': {
const { catalogId, entryId } = action.payload
const existing = state.customCatalogs[catalogId] || []
return {
...state,
customCatalogs: {
...state.customCatalogs,
[catalogId]: existing.filter(e => e.id !== entryId),
},
}
}
case 'SET_STATE': {
return { ...state, ...action.payload }
}
default:
return state
}
}
// =============================================================================
// CONTEXT
// =============================================================================
interface SDKContextValue {
state: SDKState
dispatch: React.Dispatch<SDKAction>
}
const SDKContext = createContext<SDKContextValue | null>(null)
// =============================================================================
// PROVIDER
// =============================================================================
interface SDKProviderProps {
children: React.ReactNode
}
export function SDKProvider({ children }: SDKProviderProps) {
const [state, dispatch] = useReducer(sdkReducer, initialState)
const value: SDKContextValue = useMemo(() => ({
state,
dispatch,
}), [state, dispatch])
return <SDKContext.Provider value={value}>{children}</SDKContext.Provider>
}
// =============================================================================
// HOOK
// =============================================================================
export function useSDK(): SDKContextValue {
const context = useContext(SDKContext)
if (!context) {
throw new Error('useSDK must be used within SDKProvider')
}
return context
}
export { SDKContext }