diff --git a/.changeset/icy-kings-enjoy.md b/.changeset/icy-kings-enjoy.md new file mode 100644 index 000000000..5706087c1 --- /dev/null +++ b/.changeset/icy-kings-enjoy.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-app": minor +--- + +Adds that the user can download a pdf, "Bemestingsplan", for a farm that gives on farm-level an overview of norms, advices, used fertilizers and on field-level,the norms, advices, soil status and planned fertilizer applications. diff --git a/fdm-app/app/components/blocks/pdf/PdfBadge.tsx b/fdm-app/app/components/blocks/pdf/PdfBadge.tsx new file mode 100644 index 000000000..8cfb74b06 --- /dev/null +++ b/fdm-app/app/components/blocks/pdf/PdfBadge.tsx @@ -0,0 +1,14 @@ +import { Text, View } from "@react-pdf/renderer" +import { pdfStyles } from "./bemestingsplan/styles" + +export const PdfBadge = ({ + children, + style, +}: { + children: string + style?: any +}) => ( + + {children} + +) diff --git a/fdm-app/app/components/blocks/pdf/PdfCard.tsx b/fdm-app/app/components/blocks/pdf/PdfCard.tsx new file mode 100644 index 000000000..19c7e229d --- /dev/null +++ b/fdm-app/app/components/blocks/pdf/PdfCard.tsx @@ -0,0 +1,10 @@ +import { View } from "@react-pdf/renderer" +import { pdfStyles } from "./bemestingsplan/styles" + +export const PdfCard = ({ + children, + style, +}: { + children: React.ReactNode + style?: any +}) => {children} diff --git a/fdm-app/app/components/blocks/pdf/PdfTable.tsx b/fdm-app/app/components/blocks/pdf/PdfTable.tsx new file mode 100644 index 000000000..e191fca93 --- /dev/null +++ b/fdm-app/app/components/blocks/pdf/PdfTable.tsx @@ -0,0 +1,44 @@ +import { Text, View } from "@react-pdf/renderer" +import { pdfStyles } from "./bemestingsplan/styles" + +export const PdfTable = ({ + children, + style, +}: { + children: React.ReactNode + style?: any +}) => {children} + +export const PdfTableHeader = ({ + children, + style, +}: { + children: React.ReactNode + style?: any +}) => {children} + +export const PdfTableRow = ({ + children, + style, +}: { + children: React.ReactNode + style?: any +}) => {children} + +export const PdfTableCell = ({ + children, + style, + weight = 1, +}: { + children: React.ReactNode + style?: any + weight?: number +}) => ( + + {typeof children === "string" || typeof children === "number" ? ( + {children} + ) : ( + children + )} + +) diff --git a/fdm-app/app/components/blocks/pdf/bemestingsplan/BemestingsplanPDF.tsx b/fdm-app/app/components/blocks/pdf/bemestingsplan/BemestingsplanPDF.tsx new file mode 100644 index 000000000..cca183f59 --- /dev/null +++ b/fdm-app/app/components/blocks/pdf/bemestingsplan/BemestingsplanPDF.tsx @@ -0,0 +1,1975 @@ +import { Document, Image, Link, Page, Text, View } from "@react-pdf/renderer" +import { format } from "date-fns" +import { nl } from "date-fns/locale" +import { PdfCard } from "../PdfCard" +import { + PdfTable, + PdfTableCell, + PdfTableHeader, + PdfTableRow, +} from "../PdfTable" +import { pdfStyles } from "./styles" +import type { BemestingsplanData } from "./types" + +const Footer = ({ + config, + style, + showPageNumbers = true, +}: { + config: { name: string } + style?: any + showPageNumbers?: boolean +}) => { + if (showPageNumbers) { + return ( + + + {config.name} - Gegenereerd op{" "} + {format(new Date(), "d MMMM yyyy", { locale: nl })} + + {showPageNumbers && ( + + `Pagina ${pageNumber} / ${totalPages}` + } + /> + )} + + ) + } + return null +} + +const SectionHeader = ({ children }: { children: string }) => ( + {children} +) + +/** + * Renders a chemical symbol with subscripts using nested Text components. + * This is the most reliable way to achieve subscripts in react-pdf with standard fonts. + */ +const Chemical = ({ symbol, style }: { symbol: string; style?: any }) => { + const parts = symbol.split(/(\d+)/) + return ( + + {parts.map((part, i) => ( + + {part} + + ))} + + ) +} + +const soilTypeLabels: Record = { + moerige_klei: "Moerige klei", + rivierklei: "Rivierklei", + dekzand: "Dekzand", + zeeklei: "Zeeklei", + dalgrond: "Dalgrond", + veen: "Veen", + loess: "Löss", + duinzand: "Duinzand", + maasklei: "Maasklei", +} + +const FrontPage = ({ data }: { data: BemestingsplanData }) => ( + + + {/* Using local cover image passed from loader */} + {data.config.coverImage ? ( + + ) : ( + + )} + + + + + + + {/* {data.config.logo ? ( + + ) : data.config.logoInverted ? ( + + ) : null} */} + + {data.config.name} + + + + + + Bemestingsplan + + + {data.year} + + + + + + {data.farm.name} + + + + KvK: {data.farm.kvk || "-"} + + + Oppervlakte: {data.totalArea.toFixed(1)} ha + + + + Datum:{" "} + {format(new Date(), "d MMMM yyyy", { locale: nl })} + + + + +