166 lines
5.0 KiB
TypeScript
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);
|
|
}
|