import { useState, useCallback } from 'react'; import type { UserDTO, CreateUserRequest } from '@effigenix/api-client'; import type { PaginationParams } from '@effigenix/types'; import { client } from '../utils/api-client.js'; type RoleName = CreateUserRequest['roleNames'][number]; interface UsersState { users: UserDTO[]; loading: boolean; error: string | null; currentPage: number; totalElements: number; totalPages: number; pageSize: number; } function errorMessage(err: unknown): string { return err instanceof Error ? err.message : 'Unbekannter Fehler'; } export function useUsers() { const [state, setState] = useState({ users: [], loading: false, error: null, currentPage: 0, totalElements: 0, totalPages: 0, pageSize: 20, }); const fetchUsers = useCallback(async (pagination?: PaginationParams) => { setState((s) => ({ ...s, loading: true, error: null })); try { const res = await client.users.list(pagination); setState((s) => ({ ...s, users: res.content, currentPage: res.page.number, totalElements: res.page.totalElements, totalPages: res.page.totalPages, pageSize: res.page.size, loading: false, error: null, })); } catch (err) { setState((s) => ({ ...s, loading: false, error: errorMessage(err) })); } }, []); const createUser = useCallback( async (username: string, email: string, password: string, roleName?: string) => { setState((s) => ({ ...s, loading: true, error: null })); try { const user = await client.users.create({ username, email, password, roleNames: roleName ? [roleName as RoleName] : [], }); setState((s) => ({ ...s, users: [...s.users, user], loading: false, error: null })); return user; } catch (err) { setState((s) => ({ ...s, loading: false, error: errorMessage(err) })); return null; } }, [], ); const lockUser = useCallback(async (id: string) => { try { const user = await client.users.lock(id); setState((s) => ({ ...s, users: s.users.map((u) => (u.id === id ? user : u)), })); return user; } catch (err) { setState((s) => ({ ...s, error: errorMessage(err) })); return null; } }, []); const unlockUser = useCallback(async (id: string) => { try { const user = await client.users.unlock(id); setState((s) => ({ ...s, users: s.users.map((u) => (u.id === id ? user : u)), })); return user; } catch (err) { setState((s) => ({ ...s, error: errorMessage(err) })); return null; } }, []); const assignRole = useCallback(async (id: string, roleName: string) => { try { const user = await client.users.assignRole(id, { roleName: roleName as RoleName }); setState((s) => ({ ...s, users: s.users.map((u) => (u.id === id ? user : u)), })); return user; } catch (err) { setState((s) => ({ ...s, error: errorMessage(err) })); return null; } }, []); const removeRole = useCallback(async (id: string, roleName: string) => { try { await client.users.removeRole(id, roleName); const updated = await client.users.getById(id); setState((s) => ({ ...s, users: s.users.map((u) => (u.id === id ? updated : u)), })); return true; } catch (err) { setState((s) => ({ ...s, error: errorMessage(err) })); return false; } }, []); const changePassword = useCallback( async (id: string, currentPassword: string, newPassword: string) => { try { await client.users.changePassword(id, { currentPassword, newPassword }); return true; } catch (err) { setState((s) => ({ ...s, error: errorMessage(err) })); return false; } }, [], ); const nextPage = useCallback(() => { if (state.currentPage < state.totalPages - 1) { // Caller should re-fetch with new page } }, [state.currentPage, state.totalPages]); const prevPage = useCallback(() => { if (state.currentPage > 0) { // Caller should re-fetch with new page } }, [state.currentPage]); const goToPage = useCallback((_page: number) => { // Caller should re-fetch with new page }, []); const clearError = useCallback(() => { setState((s) => ({ ...s, error: null })); }, []); return { ...state, fetchUsers, createUser, lockUser, unlockUser, assignRole, removeRole, changePassword, nextPage, prevPage, goToPage, clearError, }; }