{"id":29783,"date":"2025-03-22T16:25:32","date_gmt":"2025-03-22T16:25:32","guid":{"rendered":"https:\/\/staging-schaffenburg.nl\/download-offerte\/"},"modified":"2025-03-22T16:25:32","modified_gmt":"2025-03-22T16:25:32","slug":"download-offerte","status":"publish","type":"page","link":"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/","title":{"rendered":"Download offerte"},"content":{"rendered":"    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/1.5.3\/jspdf.debug.js\" integrity=\"sha384-NaWTHo\/8YCBYJ59830LTz\/P4aQZK1sS0SneOgAvhsIl3zBu8r9RevNg5lHCHAuQ\/\" crossorigin=\"anonymous\"><\/script>\n    <script>\n\nfunction hexToRgb(hex) {    \n    \/\/ Expand shorthand form (e.g. \"03F\") to full form (e.g. \"0033FF\")\n    const shorthandRegex = \/^#?([a-f\\d])([a-f\\d])([a-f\\d])$\/i;\n    const result = \/^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$\/i.exec(\n        hex\n    );\n    return result\n        ? {\n            r: parseInt(result[1], 16),\n            g: parseInt(result[2], 16),\n            b: parseInt(result[3], 16),\n        }\n        : null;\n}\n\n    \/\/ 1. Configuration constants\n    const A4_WIDTH_CM  = 21.0;\n    const A4_HEIGHT_CM = 29.7;\n\n    \/\/ Image resizing target (in pixels) to help reduce huge images\n    \/\/ Adjust as necessary for your quality\/size trade-offs.\n    const TARGET_IMAGE_WIDTH_PX = 800;\n\n    \/\/ 2. Gather items from PHP\n    var product_items = [];\n        console.log('Product items:', product_items);\n    var images;\n\n    \/\/ 3. Build array of image URLs (including your background)\n    var images_urls = [\n        \"https:\/\/portal.schaffenburg.nl\/wp-content\/uploads\/2025\/03\/Schaffenburg-offerte-Engels-scaled.jpg\",\n    ];\n    var primary_color = \"#17223D\";\n    var secondary_color = \"#B7CFE6\";\n    var reseller_logo = \"\";\n        \/\/convert colors to rgb\n    var primary_rgb = hexToRgb(primary_color);\n    var secondary_rgb = hexToRgb(secondary_color);\n    console.log('Primary color:', primary_color, primary_rgb);\n    console.log('Secondary color:', secondary_color, secondary_rgb);\n\n    if(reseller_logo !== \"\") {\n        images_urls.push(reseller_logo);\n    }\n    product_items.forEach(function(item) {\n        if (item.foto && item.foto !== \"\") {\n            images_urls.push(item.foto);\n        }\n    });\n    console.log('All image URLs:', images_urls);\n\n    \/**\n     * 4. Preload & compress images\n     *    - Loads each URL in a hidden <img>\n     *    - Draws to a <canvas> at a reduced size (if large)\n     *    - Converts to base64 (JPEG at ~70% quality)\n     *\/\n    function preloadImages(urls) {\n      return Promise.all(\n        urls.map((url) =>\n          new Promise((resolve, reject) => {\n            const img = new Image();\n            img.crossOrigin = \"Anonymous\"; \/\/ needed for toDataURL\n            img.src = url;\n\n            img.onload = function() {\n              \/\/ Decide how big we want to scale it down\n              let newWidth = img.width;\n              let newHeight = img.height;\n\n              \/\/ If the image is wider than our TARGET, scale it\n\n              if (img.width > TARGET_IMAGE_WIDTH_PX && url.indexOf(\"https:\/\/portal.schaffenburg.nl\/wp-content\/uploads\/2025\/03\/Schaffenburg-offerte-Engels-scaled.jpg\") === -1) {\n                newWidth = TARGET_IMAGE_WIDTH_PX;\n                newHeight = (img.height \/ img.width) * newWidth;\n              }\n\n              const canvas = document.createElement(\"canvas\");\n              canvas.width = newWidth;\n              canvas.height = newHeight;\n              const ctx = canvas.getContext(\"2d\");\n\n              \/\/ Draw the image onto the canvas\n              ctx.drawImage(img, 0, 0, newWidth, newHeight);\n\n              \/\/ Convert to base64 with JPEG compression (70% quality)\n              \n              var dataURL;\n              if(url.indexOf(\"Schaffenburg-offerte.jpg\") !== -1) {\n                dataURL = canvas.toDataURL(\"image\/jpeg\", 1);\n              } else {\n                dataURL = canvas.toDataURL(\"image\/jpeg\", 0.7);\n              }\n\n              resolve({\n                url: url,\n                data: dataURL,\n                width: newWidth,\n                height: newHeight,\n                format: \"JPEG\", \/\/ we\u2019re always converting to JPEG for compression\n              });\n            };\n\n            img.onerror = function() {\n              console.error(\"Failed to load image:\", url);\n              \/\/ Optional: you could resolve with a placeholder image\n              reject(new Error(\"Failed to load image: \" + url));\n            };\n          })\n        )\n      );\n    }\n\n    \/**\n     * Helper to retrieve the base64 data for a particular URL\n     *\/\n    function getImageData(url, imagesArray) {\n      const found = imagesArray.find((img) => img.url === url);\n      return found ? found.data : null;\n    }\n\n    \/**\n     * Helper to retrieve the image size & format\n     *\/\n    function getImageSize(url, imagesArray) {\n      const found = imagesArray.find((img) => img.url === url);\n      return found\n        ? { width: found.width, height: found.height, format: found.format }\n        : null;\n    }\n\n    \/**\n     * 5. Create the PDF (manually placing elements).\n     *\/ \n    function createPDF(images) {\n      \/\/ Initialize jsPDF (cm units, A4 page)\n      const pdf = new jsPDF({\n        orientation: \"p\",\n        unit: \"cm\",\n        format: \"a4\",\n        compress: true \/\/ attempt internal PDF compression\n      });\n\n      \/\/ ======== Draw first-page background image ========\n      const bgURL = \"https:\/\/portal.schaffenburg.nl\/wp-content\/uploads\/2025\/03\/Schaffenburg-offerte-Engels-scaled.jpg\";\n      const firstImageData = getImageData(bgURL, images);\n      if (firstImageData) {\n        pdf.addImage(\n          firstImageData,\n          \"JPEG\",\n          0,\n          0,\n          A4_WIDTH_CM,\n          A4_HEIGHT_CM\n        );\n      }\n      if(reseller_logo !== \"\") {\n        draw_reseller_logo(pdf, reseller_logo);\n      }\n\n      \/\/ ======== Define some coordinate constants ========\n      \/\/ Layout margins:\n      const LEFT_MARGIN   = 1.5;\n      const RIGHT_MARGIN  = 19.5; \/\/ near 21 - 1.5\n      const TABLE_START_Y = 16.0; \/\/ where we start the product table on the first page\n\n      \/\/ Column x-positions for the table\n      const X_IMG   = LEFT_MARGIN + 0.3;  \/\/ image\n      const X_PROD  = LEFT_MARGIN + 1.8;  \/\/ product text\n      const X_PRICE = 13.7;\n      const X_QTY   = 16.0;\n      const X_LINE  = 19.1; \/\/ right side for alignment of total price\n\n      \/\/ For your first-page text (offerte info)\n      drawFirstPageTexts(pdf);\n\n      \/\/ ======== Draw the table header once on the first page ========\n      let currentY = TABLE_START_Y;\n      drawTableHeader(pdf, LEFT_MARGIN, RIGHT_MARGIN, currentY);\n      currentY += 0.4; \/\/ space after header\n\n      \/\/ ======== Draw product rows, handle page breaks ========\n      const ROW_HEIGHT = 1.25; \/\/ vertical spacing per product\n      const MAX_Y = 25.0;     \/\/ approx. bottom margin before we break\n\n      for (let i = 0; i < product_items.length; i++) {\n        \/\/ Check if we need a new page (if next row would go past bottom margin)\n        if (currentY + ROW_HEIGHT > MAX_Y) {\n          \/\/ Start a new page\n          pdf.addPage();\n\n          \/\/ If you want the same background on new pages, re-draw it:\n          pdf.addImage(firstImageData, \"JPEG\", 0, 0, A4_WIDTH_CM, A4_HEIGHT_CM);\n          \/\/add a restangle before the background image to make the text more readable, start t 4cm from the top\n            pdf.setFillColor(255, 255, 255);\n            pdf.rect(0, 4, A4_WIDTH_CM, A4_HEIGHT_CM - 4, \"F\");\n            \/\/ Draw reseller logo\n            if(reseller_logo !== \"\") {\n                draw_reseller_logo(pdf, reseller_logo);\n            }\n\n\n          \/\/ Reset currentY near top\n          currentY = 6.0;\n\n          \/\/ Re-draw table header\n          drawTableHeader(pdf, LEFT_MARGIN, RIGHT_MARGIN, currentY);\n          currentY += 0.8;\n        }\n\n        \/\/ Draw the row\n        const item = product_items[i];\n        drawProductRow(pdf, item, images, {\n          xImg: X_IMG,\n          xProd: X_PROD,\n          xPrice: X_PRICE,\n          xQty: X_QTY,\n          xLine: X_LINE,\n          y: currentY\n        });\n\n        currentY += ROW_HEIGHT;\n      }\n\n      \/\/ ======== Summaries \/ Totals ========\n      currentY -= 1;\n      drawTotals(pdf, currentY);\n\n      \/\/ ======== Save the PDF ========\n      const unix = Math.round(Date.now() \/ 1000);\n      pdf.save(\"Schaffenburg offer \" + unix + \".pdf\");\n    }\n\n    function draw_reseller_logo(pdf, logo) {\n    console.log(\"draw_reseller_logo\", logo, images);\n\n    maxWidth = 5;\n    maxHeight = 3;\n\n    const imgSize = getImageSize(logo, images);\n    const logo_data = getImageData(logo, images);\n\n    \/\/ Original image width & height (in cm)\n    let width = imgSize.width;\n    let height = imgSize.height;\n    \n    \/\/ Calculate a scale factor that respects both maxWidth and maxHeight\n    const scaleFactor = Math.min(maxWidth \/ width, maxHeight \/ height);\n\n    \/\/ If the image is larger than either maxWidth or maxHeight, scale it down\n    if (scaleFactor < 1) {\n        width = width * scaleFactor;\n        height = height * scaleFactor;\n    }\n\n    \/\/ Position the image, for example near the top-right corner\n    const x = A4_WIDTH_CM - width - 1.5;\n    const y = 1;\n\n    \/\/set fill to white\n    pdf.setFillColor(255, 255, 255);\n    const format = logo.endsWith('.png') ? 'PNG' : 'JPEG';\n    console.log(\"logo_data\", logo_data, format, x, y, width, height);\n    pdf.addImage(logo_data, format, x, y, width, height);\n    }\n\n\n\n    \/**\n     * Draw first-page text items (offerte info).\n     *\/\n    function drawFirstPageTexts(pdf) {\n      \/\/ Example text positions\n      const datacol1_x = 5.12;\n      const datacol2_x = 15.73;\n\n      pdf.setFontSize(11);\n      pdf.setTextColor(0, 0, 0);\n\n\n    \/\/ Load data from ACF fields\n    var offerte_datum = \"\";\n    if(offerte_datum != \"\"){\n      offerte_datum = offerte_datum.split(\"-\").reverse().join(\"\/\");\n    }\n    var offerte_verloopdatum = \"\";\n    if(offerte_verloopdatum != \"\"){\n      offerte_verloopdatum = offerte_verloopdatum.split(\"-\").reverse().join(\"\/\");\n    }\n    var dealer_naam = \"Download offerte\";\n    var dealer_contactpersoon = \"\";\n    var dealer_klantnummer = \"\";\n    var dealer_adres = \"\";\n    var dealer_postcode = \"\";\n    var dealer_plaats = \"\";\n    var dealer_telefoon = \"\";\n    var eindklant_referentie = \"\";\n    var eindklant_naam = \"\";\n    var eindklant_contactpersoon = \"\";\n    var eindklant_adres = \"\";\n    var eindklant_postcode = \"\";\n    var eindklant_plaats = \"\";\n    var eindklant_telefoon = \"\";\n    var dealer_gewenste_leverdatum = \"\";\n    var eindklant_opmerkingen = \"\";\n    var eindklant_leveringscondities = \"\";\n\n    \/\/ Replace static text with dynamic data\n    \n    var gegcol_start = 8\n    var regel_hoogte = 0.6; \/\/ gemiddelde afstand tussen regels\n    pdf.text(offerte_datum , datacol1_x, gegcol_start - 1.33);\n    pdf.text(offerte_verloopdatum , datacol2_x, gegcol_start - 1.33);\n\n    pdf.text(dealer_naam, datacol1_x, gegcol_start + regel_hoogte * 1);\n    pdf.text(dealer_klantnummer, datacol1_x, gegcol_start);\n    pdf.text(dealer_contactpersoon, datacol1_x, gegcol_start + regel_hoogte * 2);\n    pdf.text(dealer_adres, datacol1_x, gegcol_start + regel_hoogte * 3);\n    pdf.text(dealer_postcode, datacol1_x, gegcol_start + regel_hoogte * 4);\n    pdf.text(dealer_plaats, datacol1_x, gegcol_start + regel_hoogte * 5);\n    pdf.text(dealer_telefoon, datacol1_x, gegcol_start + regel_hoogte * 6);\n\n    pdf.text(eindklant_referentie, datacol2_x, gegcol_start);\n    pdf.text(eindklant_naam, datacol2_x, gegcol_start + regel_hoogte * 1);\n    pdf.text(eindklant_contactpersoon, datacol2_x, gegcol_start + regel_hoogte * 2);\n    pdf.text(eindklant_adres, datacol2_x, gegcol_start + regel_hoogte * 3);\n    pdf.text(eindklant_postcode, datacol2_x, gegcol_start + regel_hoogte * 4);\n    pdf.text(eindklant_plaats, datacol2_x, gegcol_start + regel_hoogte * 5);\n    pdf.text(eindklant_telefoon, datacol2_x, gegcol_start + regel_hoogte * 6);\n\n    pdf.text(dealer_gewenste_leverdatum, datacol1_x + 2, (gegcol_start + regel_hoogte * 8));\n    pdf.text(eindklant_opmerkingen, datacol1_x + 2, (gegcol_start + regel_hoogte * 8) + 0.6); \/\/ Speciale positie aangepast\n   \/\/ pdf.text(eindklant_leveringscondities, datacol1_x, gegcol_start + regel_hoogte * 8.60);\n    }\n\n    \/**\n     * Draw the table header row.\n     *\/\n    function drawTableHeader(pdf, leftMargin, rightMargin, yPos) {\n      const headerHeight = 0.9; \/\/ height of the dark band\n      yPos -= 1; \/\/ slight offset from top\n\n      \/\/ Background rectangle (in color)\n      pdf.setFillColor(primary_rgb.r, primary_rgb.g, primary_rgb.b);   \/\/ if you want a red color fill\n      pdf.rect(leftMargin, yPos, rightMargin - leftMargin, headerHeight, \"F\");\n\n      \/\/ White text\n      pdf.setTextColor(255, 255, 255);\n      pdf.setFontSize(11);\n\n      pdf.text(\"Product\", leftMargin + 1.8, yPos + 0.55);\n      pdf.text(\"Price\/unit\", 13.7, yPos + 0.55);\n      pdf.text(\"Quantity\", 16.0, yPos + 0.55);\n      pdf.text(\"Price\", 19.1, yPos + 0.55, { align: \"right\" });\n\n      \/\/ Reset text color to black for subsequent content\n      pdf.setTextColor(0, 0, 0);\n    }\n\n    \/**\n     * Draw a single product row.\n     *\/\n    function drawProductRow(pdf, item, images, coords) {\n      const {\n        xImg, xProd, xPrice, xQty, xLine, y\n      } = coords;\n\n      \/\/ Add product image (if any)\n      if (item.foto) {\n        const imageData = getImageData(item.foto, images);\n        if (imageData) {\n            \/\/ We'll do a small thumbnail ~1.1cm wide\n            const THUMB_WIDTH_CM = 1.1;\n            const THUMB_HEIGHT_CM = 1.1;\n            \/\/ Keep aspect ratio\n            const size = getImageSize(item.foto, images);\n            let aspectW = THUMB_WIDTH_CM;\n            let aspectH = (size.height \/ size.width) * THUMB_WIDTH_CM;\n\n            \/\/ If the calculated height exceeds the max height, adjust the width and height\n            if (aspectH > THUMB_HEIGHT_CM) {\n              aspectH = THUMB_HEIGHT_CM;\n              aspectW = (size.width \/ size.height) * THUMB_HEIGHT_CM;\n            }\n\n          pdf.addImage(imageData, \"JPEG\", xImg, y - 0.26, THUMB_WIDTH_CM, aspectH);\n        }\n      }\n\n      \/\/ Product name, details\n      pdf.setFontSize(10);\n      pdf.text(item.naam, xProd, y);\n      pdf.setTextColor(150, 150, 150);\n      pdf.text(item.aantekening, xProd, y + 0.5);\n      pdf.setTextColor(0, 0, 0);\n\n      \/\/ Price\/Quantity\/Total\n      pdf.setFontSize(10);\n      pdf.text(format_euro(item.prijs),  xPrice, y);\n      pdf.text(item.aantal,      xQty,   y);\n        const subtotaal = item.prijs * item.aantal;\n      pdf.text(format_euro(subtotaal) , xLine, y, { align: \"right\" });\n    }\n\n    function format_euro(amount) {\n      const parsedAmount = parseFloat(amount);\n      if (!isNaN(parsedAmount)) {\n        return \"\u20ac\" + parsedAmount.toFixed(2).replace(\".\", \",\").replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, \".\");\n      } else {\n        return \"\u20ac0,00\";\n      }\n    }\n    \/**\n     * Draw totals at the bottom of the page\n     *\/\n    function drawTotals(pdf, currentY) {\n      currentY += 2.0; \/\/ offset from the last row\n\n      const xLabel = 12.7;\n      const xValue = 19.1;\n      const lineWidth = xValue - xLabel + 0.5;\n\n      var subtotaal = 0;\n      var totaal = 0;\n        product_items.forEach(function(item) {\n            subtotaal += Number(item.prijs) * Number(item.aantal);\n        });\n        var korting = \"\";\n        korting_label = \"\";\n        levering_label = ;\n        if(korting != \"\"){\n            if(korting.indexOf(\"%\") > -1){\n                korting = korting.replace(\"%\", \"\");\n                korting = Number(korting);\n                totaal = subtotaal - (subtotaal * (korting \/ 100));\n                korting_label = \"\"+korting + \"%\";\n            }\n            else if(korting != \"\"){\n                korting = Number(korting);\n                totaal = subtotaal - korting;\n                korting_label = format_euro(korting);\n            }\n        }else{\n            totaal = subtotaal;\n        }\n        totaal = totaal + Number(levering_label);\n        \/\/if totaal is lower than 500, add 7.5 order costs\n        if(totaal < 500){\n            totaal += 7.5;\n        }\n        var btw = totaal * 0.21;\n        var totaal_incl_btw = totaal + btw;\n\n      pdf.setFontSize(11);\n      pdf.text(\"Subtotal\", xLabel, currentY);\n      pdf.text(format_euro(subtotaal),       xValue, currentY, { align: \"right\" });\n      currentY += 0.5;\n\n      if(korting != \"\"){\n      pdf.text(\"Discount\", xLabel, currentY);\n      pdf.text((korting_label),            xValue, currentY, { align: \"right\" });\n      currentY += 0.5;\n      \/\/ horizontal line\n      pdf.setFillColor(secondary_rgb.r, secondary_rgb.g, secondary_rgb.b);\n      pdf.rect(xLabel - 0.2, currentY - 0.2, lineWidth, 0.08, \"F\");\n      currentY += 0.4;\n      }\n\n\n      pdf.text(\"Delivery\", xLabel, currentY);\n      pdf.text((format_euro(levering_label)), xValue, currentY, { align: \"right\" });\n      currentY += 0.5;\n\n      if(subtotaal < 500){\n        pdf.text(\"Order costs\", xLabel, currentY);\n        pdf.text((format_euro(7.5)), xValue, currentY, { align: \"right\" });\n        currentY += 0.5;\n      }\n\n      \n      \/\/ horizontal line\n      pdf.setFillColor(secondary_rgb.r, secondary_rgb.g, secondary_rgb.b);\n      pdf.rect(xLabel - 0.2, currentY - 0.2, lineWidth, 0.08, \"F\");\n      currentY += 0.4;\n\n\n      pdf.text(\"Total price excl. VAT\", xLabel, currentY);\n      pdf.text(format_euro(totaal),             xValue, currentY, { align: \"right\" });\n      currentY += 0.5;\n\n      pdf.text(\"VAT\", xLabel, currentY);\n      pdf.text(format_euro(btw),           xValue, currentY, { align: \"right\" });\n      currentY += 0.5;\n\n      pdf.setFillColor(secondary_rgb.r, secondary_rgb.g, secondary_rgb.b);\n      pdf.rect(xLabel - 0.2, currentY - 0.2, lineWidth, 0.08, \"F\");\n      currentY += 0.5;\n\n      pdf.text(\"Total price incl. VAT\", xLabel, currentY);\n      pdf.text(format_euro(totaal_incl_btw),           xValue, currentY, { align: \"right\" });\n      pdf.setFillColor(primary_rgb.r, primary_rgb.g, primary_rgb.b);\n    }\n\n    \/\/ 6. Preload images, then create the PDF once all are loaded.\n    preloadImages(images_urls)\n      .then((loadedImages) => {\n        images = loadedImages;\n        createPDF(loadedImages);\n      })\n      .catch((error) => {\n        console.error(\"Error loading\/compressing images:\", error);\n      });\n<\/script>\n\n\n\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":575,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-29783","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Download offerte - Schaffenburg<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Download offerte - Schaffenburg\" \/>\n<meta property=\"og:url\" content=\"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/\" \/>\n<meta property=\"og:site_name\" content=\"Schaffenburg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/\",\"url\":\"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/\",\"name\":\"Download offerte - Schaffenburg\",\"isPartOf\":{\"@id\":\"https:\/\/portal.schaffenburg.nl\/en\/#website\"},\"datePublished\":\"2025-03-22T16:25:32+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/portal.schaffenburg.nl\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Download offerte\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/portal.schaffenburg.nl\/en\/#website\",\"url\":\"https:\/\/portal.schaffenburg.nl\/en\/\",\"name\":\"Schaffenburg\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/portal.schaffenburg.nl\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Download offerte - Schaffenburg","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/","og_locale":"en_US","og_type":"article","og_title":"Download offerte - Schaffenburg","og_url":"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/","og_site_name":"Schaffenburg","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/","url":"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/","name":"Download offerte - Schaffenburg","isPartOf":{"@id":"https:\/\/portal.schaffenburg.nl\/en\/#website"},"datePublished":"2025-03-22T16:25:32+00:00","breadcrumb":{"@id":"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/portal.schaffenburg.nl\/en\/download-offerte\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/portal.schaffenburg.nl\/en\/"},{"@type":"ListItem","position":2,"name":"Download offerte"}]},{"@type":"WebSite","@id":"https:\/\/portal.schaffenburg.nl\/en\/#website","url":"https:\/\/portal.schaffenburg.nl\/en\/","name":"Schaffenburg","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/portal.schaffenburg.nl\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/portal.schaffenburg.nl\/en\/wp-json\/wp\/v2\/pages\/29783","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/portal.schaffenburg.nl\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/portal.schaffenburg.nl\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/portal.schaffenburg.nl\/en\/wp-json\/wp\/v2\/users\/575"}],"replies":[{"embeddable":true,"href":"https:\/\/portal.schaffenburg.nl\/en\/wp-json\/wp\/v2\/comments?post=29783"}],"version-history":[{"count":0,"href":"https:\/\/portal.schaffenburg.nl\/en\/wp-json\/wp\/v2\/pages\/29783\/revisions"}],"wp:attachment":[{"href":"https:\/\/portal.schaffenburg.nl\/en\/wp-json\/wp\/v2\/media?parent=29783"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}