119 lines
3.3 KiB
TypeScript
119 lines
3.3 KiB
TypeScript
import { useState } from "react";
|
|
import axios from "axios";
|
|
|
|
interface UseExportReturn {
|
|
exportSnapshot: (format: "csv" | "xlsx") => Promise<void>;
|
|
exportAuditTrail: (format: "csv" | "xlsx") => Promise<void>;
|
|
isLoading: boolean;
|
|
error: string | null;
|
|
}
|
|
|
|
/**
|
|
* Custom hook for managing inventory export operations.
|
|
* Handles API calls, file downloads, and error management.
|
|
*
|
|
* @returns Object with export functions and state
|
|
*/
|
|
export function useExport(): UseExportReturn {
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
/**
|
|
* Extract filename from Content-Disposition header.
|
|
* Handles both inline and attachment disposition.
|
|
*/
|
|
const extractFilenameFromHeader = (contentDisposition: string): string => {
|
|
const match = contentDisposition.match(/filename="?([^"]+)"?/);
|
|
return match ? match[1] : `export_${Date.now()}`;
|
|
};
|
|
|
|
/**
|
|
* Trigger file download from blob response.
|
|
*/
|
|
const downloadFile = (blob: Blob, filename: string) => {
|
|
const url = URL.createObjectURL(blob);
|
|
const link = document.createElement("a");
|
|
link.href = url;
|
|
link.download = filename;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
URL.revokeObjectURL(url);
|
|
};
|
|
|
|
/**
|
|
* Export inventory snapshot in specified format.
|
|
*/
|
|
const exportSnapshot = async (format: "csv" | "xlsx"): Promise<void> => {
|
|
setIsLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const response = await axios.post(
|
|
`/api/admin/exports/inventory-snapshot?format=${format}`,
|
|
{},
|
|
{
|
|
responseType: "blob",
|
|
}
|
|
);
|
|
|
|
// Extract filename from response headers
|
|
const contentDisposition = response.headers["content-disposition"] || "";
|
|
const filename = contentDisposition
|
|
? extractFilenameFromHeader(contentDisposition)
|
|
: `inventory_snapshot_${new Date().toISOString().split("T")[0]}.${format}`;
|
|
|
|
// Trigger download
|
|
downloadFile(response.data, filename);
|
|
} catch (err) {
|
|
const errorMessage =
|
|
err instanceof Error ? err.message : "Failed to export inventory snapshot";
|
|
setError(errorMessage);
|
|
throw err;
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Export audit trail in specified format.
|
|
*/
|
|
const exportAuditTrail = async (format: "csv" | "xlsx"): Promise<void> => {
|
|
setIsLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const response = await axios.post(
|
|
`/api/admin/exports/audit-trail?format=${format}`,
|
|
{},
|
|
{
|
|
responseType: "blob",
|
|
}
|
|
);
|
|
|
|
// Extract filename from response headers
|
|
const contentDisposition = response.headers["content-disposition"] || "";
|
|
const filename = contentDisposition
|
|
? extractFilenameFromHeader(contentDisposition)
|
|
: `audit_trail_${new Date().toISOString().split("T")[0]}.${format}`;
|
|
|
|
// Trigger download
|
|
downloadFile(response.data, filename);
|
|
} catch (err) {
|
|
const errorMessage =
|
|
err instanceof Error ? err.message : "Failed to export audit trail";
|
|
setError(errorMessage);
|
|
throw err;
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return {
|
|
exportSnapshot,
|
|
exportAuditTrail,
|
|
isLoading,
|
|
error,
|
|
};
|
|
}
|