Files
leocrm/frontend/src/api/reports.ts
T

166 lines
5.0 KiB
TypeScript

/**
* Report Generator plugin API client.
*
* All requests use the shared `apiClient` (`baseURL: '/api/v1'`) and target the
* Report Generator plugin routes under `/reports/...`.
*/
import { apiClient, apiDelete, apiGet, apiPost, apiPut } from './client';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
// ─── Types ─────────────────────────────────────────────────────────────────
export type OutputFormat = 'csv' | 'excel' | 'json' | 'pdf' | 'print';
export type TemplateType = 'jinja2' | 'sql';
export interface ReportTemplate {
id: string;
name: string;
description: string;
template_type: TemplateType;
content: string;
output_format: OutputFormat;
created_by: string;
deleted_at?: string | null;
created_at?: string | null;
updated_at?: string | null;
}
export interface TemplateCreateInput {
name: string;
description?: string;
template_type?: TemplateType;
content: string;
output_format?: OutputFormat;
}
export interface TemplateUpdateInput {
name?: string;
description?: string;
template_type?: TemplateType;
content?: string;
output_format?: OutputFormat;
}
export interface ReportGenerateInput {
template_id: string;
data: Record<string, unknown>;
output_format?: OutputFormat;
}
export interface PresetReportInfo {
key: string;
name: string;
description: string;
icon: string;
output_formats: OutputFormat[];
}
export interface PresetGenerateInput {
preset: string;
output_format: OutputFormat;
parameters: Record<string, unknown>;
}
// ─── React Query Hooks ─────────────────────────────────────────────────────
const QUERY_KEYS = {
templates: ['reports', 'templates'] as const,
presets: ['reports', 'presets'] as const,
};
/** Fetch all report templates */
export function useReportTemplates() {
return useQuery<ReportTemplate[]>({
queryKey: QUERY_KEYS.templates,
queryFn: () => apiGet<ReportTemplate[]>('/reports/templates'),
});
}
/** Fetch a single report template by ID */
export function useReportTemplate(templateId: string | null) {
return useQuery<ReportTemplate>({
queryKey: ['reports', 'templates', templateId],
queryFn: () => apiGet<ReportTemplate>(`/reports/templates/${templateId}`),
enabled: !!templateId,
});
}
/** Create a new report template */
export function useCreateReportTemplate() {
const qc = useQueryClient();
return useMutation({
mutationFn: (input: TemplateCreateInput) =>
apiPost<ReportTemplate>('/reports/templates', input),
onSuccess: () => qc.invalidateQueries({ queryKey: QUERY_KEYS.templates }),
});
}
/** Update an existing report template */
export function useUpdateReportTemplate() {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ id, ...input }: TemplateUpdateInput & { id: string }) =>
apiPut<ReportTemplate>(`/reports/templates/${id}`, input),
onSuccess: () => qc.invalidateQueries({ queryKey: QUERY_KEYS.templates }),
});
}
/** Delete a report template (soft-delete) */
export function useDeleteReportTemplate() {
const qc = useQueryClient();
return useMutation({
mutationFn: (id: string) => apiDelete(`/reports/templates/${id}`),
onSuccess: () => qc.invalidateQueries({ queryKey: QUERY_KEYS.templates }),
});
}
/** Fetch all preset report templates */
export function useReportPresets() {
return useQuery<PresetReportInfo[]>({
queryKey: QUERY_KEYS.presets,
queryFn: async () => {
const res = await apiGet<PresetReportInfo[] | { items: PresetReportInfo[] }>('/reports/presets');
return Array.isArray(res) ? res : res.items ?? [];
},
});
}
/** Generate a report from a template — returns a file download (blob) */
export function useGenerateReport() {
return useMutation({
mutationFn: async (input: ReportGenerateInput) => {
const response = await apiClient.post('/reports/generate', input, {
responseType: 'blob',
});
return response;
},
});
}
/** Generate a preset report — returns a file download (blob) */
export function useGeneratePresetReport() {
return useMutation({
mutationFn: async (input: PresetGenerateInput) => {
const response = await apiClient.post('/reports/presets/generate', input, {
responseType: 'blob',
});
return response;
},
});
}
// ─── Download Helper ───────────────────────────────────────────────────────
/** Trigger a browser download from a blob response */
export function downloadBlob(blob: Blob, filename: string) {
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}