mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 07:41:16 +00:00
GET /v1/export/bookings.csv (optional from/to bounds) and /v1/export/customers.csv — UTF-8 with BOM for Excel, labels resolved at export time, buffered responses so auth failures stay JSON. Export buttons on the bookings and customers pages. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import { createSignal, Accessor } from "solid-js";
|
|
import { apiBaseUrl } from "../../lib/api-client";
|
|
import { useI18n } from "../../providers/i18n-provider";
|
|
import { DownloadIcon } from "./icons";
|
|
|
|
// Downloads an authenticated CSV endpoint — fetch + blob because the
|
|
// generated api-client is typed for JSON, not file responses.
|
|
export function ExportCsvButton(props: { path: string; filename: string; token: Accessor<string | null | undefined> }) {
|
|
const i18n = useI18n();
|
|
const [busy, setBusy] = createSignal(false);
|
|
|
|
const handleClick = async () => {
|
|
const bearer = props.token?.();
|
|
if (!bearer || busy()) return;
|
|
setBusy(true);
|
|
try {
|
|
const response = await fetch(`${apiBaseUrl}${props.path}`, {
|
|
headers: { Authorization: `Bearer ${bearer}` },
|
|
});
|
|
if (!response.ok) return;
|
|
const blob = await response.blob();
|
|
const url = URL.createObjectURL(blob);
|
|
const anchor = document.createElement("a");
|
|
anchor.href = url;
|
|
anchor.download = props.filename;
|
|
anchor.click();
|
|
URL.revokeObjectURL(url);
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<button onClick={handleClick} disabled={busy()} class="btn-secondary text-sm shrink-0">
|
|
<DownloadIcon /> {i18n.t("dashboard.exportCsv")}
|
|
</button>
|
|
);
|
|
}
|