frontend_nyla/src/api/fileApi.ts
2026-03-17 19:19:32 +01:00

298 lines
7.4 KiB
TypeScript

import { ApiRequestOptions } from '../hooks/useApi';
// ============================================================================
// TYPES & INTERFACES
// ============================================================================
export interface FileInfo {
id: string;
mandateId: string;
fileName: string;
mimeType: string;
fileHash: string;
fileSize: number;
creationDate: number;
[key: string]: any; // Allow additional properties
}
export interface AttributeDefinition {
name: string;
label: string;
type: 'string' | 'number' | 'date' | 'boolean' | 'enum';
sortable?: boolean;
filterable?: boolean;
searchable?: boolean;
width?: number;
minWidth?: number;
maxWidth?: number;
filterOptions?: string[];
}
export interface PaginationParams {
page?: number;
pageSize?: number;
sort?: Array<{ field: string; direction: 'asc' | 'desc' }>;
filters?: Record<string, any>;
search?: 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 file attributes from backend
* Endpoint: GET /api/attributes/FileItem
*/
export async function fetchFileAttributes(request: ApiRequestFunction): Promise<AttributeDefinition[]> {
const data = await request({
url: '/api/attributes/FileItem',
method: 'get'
});
// Handle different response formats
if (Array.isArray(data)) {
return data;
}
if (data && typeof data === 'object' && 'attributes' in data && Array.isArray(data.attributes)) {
return data.attributes;
}
// Try to find any array property in the response
if (data && typeof data === 'object') {
const keys = Object.keys(data);
for (const key of keys) {
if (Array.isArray((data as any)[key])) {
return (data as any)[key];
}
}
}
return [];
}
/**
* Fetch list of files with optional pagination
* Endpoint: GET /api/files/list
*/
export async function fetchFiles(
request: ApiRequestFunction,
params?: PaginationParams
): Promise<PaginatedResponse<FileInfo> | FileInfo[]> {
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 (Object.keys(paginationObj).length > 0) {
requestParams.pagination = JSON.stringify(paginationObj);
}
}
const data = await request({
url: '/api/files/list',
method: 'get',
params: requestParams
});
return data;
}
/**
* Fetch a single file by ID
* Endpoint: GET /api/files/{fileId}
*/
export async function fetchFileById(
request: ApiRequestFunction,
fileId: string
): Promise<FileInfo | null> {
try {
const data = await request({
url: `/api/files/${fileId}`,
method: 'get'
});
return data || null;
} catch (error: any) {
console.error('Error fetching file by ID:', error);
return null;
}
}
/**
* Update a file
* Endpoint: PUT /api/files/{fileId}
*/
export async function updateFile(
request: ApiRequestFunction,
fileId: string,
fileData: Partial<FileInfo>
): Promise<FileInfo> {
return await request({
url: `/api/files/${fileId}`,
method: 'put',
data: fileData
});
}
/**
* Delete a file
* Endpoint: DELETE /api/files/{fileId}
*/
export async function deleteFile(
request: ApiRequestFunction,
fileId: string
): Promise<void> {
await request({
url: `/api/files/${fileId}`,
method: 'delete'
});
}
/**
* Delete multiple files
* Endpoint: DELETE /api/files/{fileId} (called multiple times)
*/
export async function deleteFiles(
request: ApiRequestFunction,
fileIds: string[]
): Promise<Array<{ success: boolean; fileId: string; error?: any }>> {
const uniqueIds = [...new Set(fileIds.filter(Boolean))];
if (uniqueIds.length === 0) return [];
await request({
url: '/api/files/batch-delete',
method: 'post',
data: { fileIds: uniqueIds }
});
return uniqueIds.map(fileId => ({ success: true, fileId }));
}
export async function deleteFolders(
request: ApiRequestFunction,
folderIds: string[],
recursiveFolders: boolean = true
): Promise<{ deletedFiles: number; deletedFolders: number }> {
const uniqueIds = [...new Set(folderIds.filter(Boolean))];
if (uniqueIds.length === 0) return { deletedFiles: 0, deletedFolders: 0 };
return await request({
url: '/api/files/batch-delete',
method: 'post',
data: { folderIds: uniqueIds, recursiveFolders }
});
}
// ============================================================================
// FOLDER API FUNCTIONS
// ============================================================================
export interface FolderInfo {
id: string;
name: string;
parentId: string | null;
mandateId?: string;
featureInstanceId?: string;
createdAt?: number;
}
export async function fetchFolders(
request: ApiRequestFunction,
parentId?: string | null
): Promise<FolderInfo[]> {
const params: any = {};
if (parentId !== undefined && parentId !== null) {
params.parentId = parentId;
}
const data = await request({
url: '/api/files/folders',
method: 'get',
params,
});
return Array.isArray(data) ? data : [];
}
export async function createFolder(
request: ApiRequestFunction,
name: string,
parentId?: string | null
): Promise<FolderInfo> {
return await request({
url: '/api/files/folders',
method: 'post',
data: { name, parentId: parentId || null },
});
}
export async function renameFolder(
request: ApiRequestFunction,
folderId: string,
name: string
): Promise<any> {
return await request({
url: `/api/files/folders/${folderId}`,
method: 'put',
data: { name },
});
}
export async function deleteFolderApi(
request: ApiRequestFunction,
folderId: string,
recursive: boolean = false
): Promise<any> {
return await request({
url: `/api/files/folders/${folderId}`,
method: 'delete',
params: { recursive },
});
}
export async function moveFolder(
request: ApiRequestFunction,
folderId: string,
targetParentId: string | null
): Promise<any> {
return await request({
url: `/api/files/folders/${folderId}/move`,
method: 'post',
data: { targetParentId },
});
}
export async function moveFile(
request: ApiRequestFunction,
fileId: string,
targetFolderId: string | null
): Promise<any> {
return await request({
url: `/api/files/${fileId}/move`,
method: 'post',
data: { targetFolderId },
});
}
// Note: The following operations require special handling (FormData, blob responses)
// and should use the api instance directly from '../api' rather than the request function:
// - uploadFile: Requires FormData with multipart/form-data
// - downloadFile: Requires blob responseType
// - previewFile: Requires flexible responseType (json or blob)
// These are kept in the hooks for now due to their special requirements