feat(export): Stockkarte - a colony's complete record as PDF
New report colony-record-card (button "Stockkarte (PDF)" on the colony page): master data, current queen and queen history, every inspection as a table row (strength, eggs, open/capped brood, queen seen, queen cells, gentleness, swarm drive, feed, measures, notes), treatments with batch number and withdrawal period, feedings, varroa counts and harvests. Landscape A4, table header repeated on each page. Whole history by default, one calendar year with ?year=. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
5cf4e87ca3
commit
f263ec79f2
5 files changed
+586
-1
No files matched your search
@@ -4,7 +4,7 @@ import { useParams } from "next/navigation";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { fetchColony } from "@/lib/colonies/api";
|
||||
import { exportColonyAnnualReportPdf } from "@/lib/export/api";
|
||||
import { exportColonyAnnualReportPdf, exportColonyRecordCardPdf } from "@/lib/export/api";
|
||||
import { QrCodeDialog } from "@/components/qr-code-dialog";
|
||||
import { DocumentUploadCard } from "@/components/document-upload-card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -31,6 +31,11 @@ export default function ColonyDetailPage() {
|
||||
onError: () => toast.error("Jahresbericht konnte nicht exportiert werden"),
|
||||
});
|
||||
|
||||
const recordCardMutation = useMutation({
|
||||
mutationFn: () => exportColonyRecordCardPdf(params.id, colony?.code ?? "volk"),
|
||||
onError: () => toast.error("Stockkarte konnte nicht erstellt werden. Bitte noch einmal versuchen."),
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return <p className="p-4 text-sm text-muted-foreground sm:p-6">Lädt…</p>;
|
||||
}
|
||||
@@ -45,6 +50,13 @@ export default function ColonyDetailPage() {
|
||||
return (
|
||||
<main className="flex flex-col gap-4 p-4 sm:p-6">
|
||||
<div className="flex flex-wrap items-center justify-end gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
disabled={recordCardMutation.isPending}
|
||||
onClick={() => recordCardMutation.mutate()}
|
||||
>
|
||||
{recordCardMutation.isPending ? "Wird erstellt…" : "Stockkarte (PDF)"}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
disabled={exportReportMutation.isPending}
|
||||
|
||||
@@ -40,6 +40,15 @@ export async function exportColonyAnnualReportPdf(colonyId: string, year: number
|
||||
downloadBlob(blob, filename);
|
||||
}
|
||||
|
||||
/** Stockkarte: the colony's whole history as a printable PDF. */
|
||||
export async function exportColonyRecordCardPdf(colonyId: string, code: string): Promise<void> {
|
||||
const { blob, filename } = await apiFetchBlob(
|
||||
`/export/colony-record-card.pdf?colonyId=${colonyId}`,
|
||||
`stockkarte-${code}.pdf`,
|
||||
);
|
||||
downloadBlob(blob, filename);
|
||||
}
|
||||
|
||||
export async function exportApiaryAnnualReportPdf(apiaryId: string, year: number): Promise<void> {
|
||||
const { blob, filename } = await apiFetchBlob(
|
||||
`/export/apiary-annual-report.pdf?apiaryId=${apiaryId}&year=${year}`,
|
||||
|
||||
Reference in new issue
Block a user