feat: Jahresbericht-PDF pro Volk/Stand
Neue PDF-Reports im Export-Modul: colony-annual-report (Durchsichten, Behandlungen, Varroakontrollen, Schwarmkontrolle, Ernten eines Volkes fuer ein Jahr) und apiary-annual-report (Voelker-Uebersicht + Ernten eines Stands fuer ein Jahr). Jahr ist optional, faellt auf das aktuelle Jahr zurueck. Frontend: "Jahresbericht"-Button auf Volk- und Stand-Detailseite, laedt das PDF ueber den bestehenden Blob-Download-Mechanismus herunter.
This commit is contained in:
1 parent
f1298eff08
commit
3f7c4ed404
8 files changed
+630
-26
No files matched your search
@@ -2,13 +2,16 @@
|
||||
|
||||
import Link from "next/link";
|
||||
import { useParams } from "next/navigation";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { fetchApiary } from "@/lib/apiaries/api";
|
||||
import { exportApiaryAnnualReportPdf } from "@/lib/export/api";
|
||||
import { QrCodeDialog } from "@/components/qr-code-dialog";
|
||||
import { DocumentUploadCard } from "@/components/document-upload-card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ApiaryEditCard } from "./apiary-edit-card";
|
||||
|
||||
const CURRENT_YEAR = new Date().getFullYear();
|
||||
|
||||
export default function ApiaryDetailPage() {
|
||||
const params = useParams<{ id: string }>();
|
||||
const { data: apiary, isLoading, isError } = useQuery({
|
||||
@@ -16,6 +19,10 @@ export default function ApiaryDetailPage() {
|
||||
queryFn: () => fetchApiary(params.id),
|
||||
});
|
||||
|
||||
const exportReportMutation = useMutation({
|
||||
mutationFn: () => exportApiaryAnnualReportPdf(params.id, CURRENT_YEAR),
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return <p className="p-4 text-sm text-muted-foreground sm:p-6">Lädt…</p>;
|
||||
}
|
||||
@@ -34,13 +41,23 @@ export default function ApiaryDetailPage() {
|
||||
</div>
|
||||
<ApiaryEditCard key={apiary.id} apiary={apiary} />
|
||||
<DocumentUploadCard entityType="APIARY" entityId={apiary.id} />
|
||||
<Button
|
||||
className="w-fit"
|
||||
nativeButton={false}
|
||||
render={<Link href={`/harvests/new?apiaryId=${apiary.id}`} />}
|
||||
>
|
||||
Neue Ernte
|
||||
</Button>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button
|
||||
nativeButton={false}
|
||||
render={<Link href={`/harvests/new?apiaryId=${apiary.id}`} />}
|
||||
>
|
||||
Neue Ernte
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
disabled={exportReportMutation.isPending}
|
||||
onClick={() => exportReportMutation.mutate()}
|
||||
>
|
||||
{exportReportMutation.isPending
|
||||
? "Wird erstellt…"
|
||||
: `Jahresbericht ${CURRENT_YEAR}`}
|
||||
</Button>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useParams } from "next/navigation";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { fetchColony } from "@/lib/colonies/api";
|
||||
import { exportColonyAnnualReportPdf } from "@/lib/export/api";
|
||||
import { QrCodeDialog } from "@/components/qr-code-dialog";
|
||||
import { DocumentUploadCard } from "@/components/document-upload-card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ColonyEditCard } from "./colony-edit-card";
|
||||
import { ColonyActions } from "./colony-actions";
|
||||
import { ColonyHistoryCard } from "./colony-history";
|
||||
@@ -14,6 +16,8 @@ import { ColonySwarmControlCard } from "./colony-swarm-control";
|
||||
import { ColonyTreatmentsCard } from "./colony-treatments";
|
||||
import { ColonyFeedingsCard } from "./colony-feedings";
|
||||
|
||||
const CURRENT_YEAR = new Date().getFullYear();
|
||||
|
||||
export default function ColonyDetailPage() {
|
||||
const params = useParams<{ id: string }>();
|
||||
const { data: colony, isLoading, isError } = useQuery({
|
||||
@@ -21,6 +25,10 @@ export default function ColonyDetailPage() {
|
||||
queryFn: () => fetchColony(params.id),
|
||||
});
|
||||
|
||||
const exportReportMutation = useMutation({
|
||||
mutationFn: () => exportColonyAnnualReportPdf(params.id, CURRENT_YEAR),
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return <p className="p-4 text-sm text-muted-foreground sm:p-6">Lädt…</p>;
|
||||
}
|
||||
@@ -34,7 +42,16 @@ export default function ColonyDetailPage() {
|
||||
|
||||
return (
|
||||
<main className="flex flex-col gap-4 p-4 sm:p-6">
|
||||
<div className="flex justify-end">
|
||||
<div className="flex flex-wrap items-center justify-end gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
disabled={exportReportMutation.isPending}
|
||||
onClick={() => exportReportMutation.mutate()}
|
||||
>
|
||||
{exportReportMutation.isPending
|
||||
? "Wird erstellt…"
|
||||
: `Jahresbericht ${CURRENT_YEAR}`}
|
||||
</Button>
|
||||
<QrCodeDialog entityType="colonies" id={colony.id} label="QR-Code für Durchsicht" />
|
||||
</div>
|
||||
<ColonyEditCard key={colony.id} colony={colony} />
|
||||
|
||||
Reference in new issue
Block a user