186 lines
4.9 KiB
TypeScript
186 lines
4.9 KiB
TypeScript
import { ApiRequestOptions } from '../hooks/useApi';
|
||
|
||
// ============================================================================
|
||
// TYPES & INTERFACES
|
||
// ============================================================================
|
||
|
||
/**
|
||
* Mandate (Mandant) — represents one tenant in PowerOn PORTA.
|
||
*
|
||
* Field semantics (must stay in sync with the backend `Mandate` Pydantic model):
|
||
* - `id` — UUID, immutable.
|
||
* - `name` — Kurzzeichen / slug. Globally unique, lowercase [a-z0-9] with
|
||
* hyphen-separated segments (length 2–32). Used for audit/tracking
|
||
* and stable references. Only PlatformAdmin can change it after
|
||
* creation.
|
||
* - `label` — Voller Name. Mandatory, human-readable display name shown in the
|
||
* UI. Freely changeable by a Mandate-Admin.
|
||
*/
|
||
export interface Mandate {
|
||
id: string;
|
||
name: string;
|
||
label: string;
|
||
enabled?: boolean;
|
||
isSystem?: boolean;
|
||
deletedAt?: number | null;
|
||
[key: string]: any; // Allow additional properties from backend
|
||
}
|
||
|
||
/** Payload for creating a mandate. `label` is required, `name` is optional. */
|
||
export interface MandateCreateData {
|
||
label: string;
|
||
name?: string;
|
||
enabled?: boolean;
|
||
[key: string]: any;
|
||
}
|
||
|
||
/**
|
||
* Payload for updating a mandate. Only PlatformAdmin may change `name`;
|
||
* Mandate-Admin can update `label` and other UI fields.
|
||
*/
|
||
export type MandateUpdateData = Partial<Omit<Mandate, 'id'>>;
|
||
|
||
export interface PaginationParams {
|
||
page?: number;
|
||
pageSize?: number;
|
||
sort?: Array<{ field: string; direction: 'asc' | 'desc' }>;
|
||
filters?: Record<string, any>;
|
||
search?: string;
|
||
viewKey?: string;
|
||
}
|
||
|
||
export interface PaginatedResponse<T> {
|
||
items: T[];
|
||
pagination?: {
|
||
currentPage: number;
|
||
pageSize: number;
|
||
totalItems: number;
|
||
totalPages: number;
|
||
};
|
||
}
|
||
|
||
// Type for the request function passed to API functions
|
||
export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<any>;
|
||
|
||
// ============================================================================
|
||
// API REQUEST FUNCTIONS
|
||
// ============================================================================
|
||
|
||
/**
|
||
* Fetch list of mandates with optional pagination
|
||
* Endpoint: GET /api/mandates/
|
||
*/
|
||
export async function fetchMandates(
|
||
request: ApiRequestFunction,
|
||
params?: PaginationParams
|
||
): Promise<PaginatedResponse<Mandate> | Mandate[]> {
|
||
const requestParams: any = {};
|
||
|
||
// Build pagination object if provided
|
||
if (params) {
|
||
const paginationObj: any = {};
|
||
|
||
if (params.page !== undefined) paginationObj.page = params.page;
|
||
if (params.pageSize !== undefined) paginationObj.pageSize = params.pageSize;
|
||
if (params.sort) paginationObj.sort = params.sort;
|
||
if (params.filters) paginationObj.filters = params.filters;
|
||
if (params.search) paginationObj.search = params.search;
|
||
if (params.viewKey) paginationObj.viewKey = params.viewKey;
|
||
|
||
if (Object.keys(paginationObj).length > 0) {
|
||
requestParams.pagination = JSON.stringify(paginationObj);
|
||
}
|
||
}
|
||
|
||
const data = await request({
|
||
url: '/api/mandates/',
|
||
method: 'get',
|
||
params: requestParams
|
||
});
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* Fetch a single mandate by ID
|
||
* Endpoint: GET /api/mandates/{mandateId}
|
||
*/
|
||
export async function fetchMandateById(
|
||
request: ApiRequestFunction,
|
||
mandateId: string
|
||
): Promise<Mandate | null> {
|
||
try {
|
||
const data = await request({
|
||
url: `/api/mandates/${mandateId}`,
|
||
method: 'get'
|
||
});
|
||
return data || null;
|
||
} catch (error: any) {
|
||
console.error('Error fetching mandate by ID:', error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Update a mandate
|
||
* Endpoint: PUT /api/mandates/{mandateId}
|
||
*/
|
||
export async function updateMandate(
|
||
request: ApiRequestFunction,
|
||
mandateId: string,
|
||
updateData: MandateUpdateData
|
||
): Promise<Mandate> {
|
||
return await request({
|
||
url: `/api/mandates/${mandateId}`,
|
||
method: 'put',
|
||
data: updateData
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Create a new mandate
|
||
* Endpoint: POST /api/mandates/
|
||
*/
|
||
export async function createMandate(
|
||
request: ApiRequestFunction,
|
||
mandateData: MandateCreateData | Partial<Mandate>
|
||
): Promise<Mandate> {
|
||
return await request({
|
||
url: '/api/mandates/',
|
||
method: 'post',
|
||
data: mandateData
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Soft-delete a mandate (sets enabled=false, 30-day retention)
|
||
* Endpoint: DELETE /api/mandates/{mandateId}
|
||
*/
|
||
export async function deleteMandate(
|
||
request: ApiRequestFunction,
|
||
mandateId: string
|
||
): Promise<void> {
|
||
await request({
|
||
url: `/api/mandates/${mandateId}`,
|
||
method: 'delete'
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Hard-delete a mandate with full cascade (irreversible)
|
||
* Endpoint: DELETE /api/mandates/{mandateId}?force=true
|
||
*/
|
||
export async function hardDeleteMandate(
|
||
request: ApiRequestFunction,
|
||
mandateId: string,
|
||
confirmName: string
|
||
): Promise<void> {
|
||
await request({
|
||
url: `/api/mandates/${mandateId}`,
|
||
method: 'delete',
|
||
params: { force: true },
|
||
additionalConfig: {
|
||
headers: { 'X-Confirm-Name': confirmName }
|
||
}
|
||
});
|
||
}
|