From 3bc3759a482b99298c88c24c25f9bb4d0da771d8 Mon Sep 17 00:00:00 2001 From: robbond Date: Mon, 30 Mar 2026 12:35:41 +0100 Subject: [PATCH] welsh downloadable new appeal form --- components/newappeal/buildchecksection.js | 16 +- components/pdftemplates/appealRow_pdf.js | 76 +++++-- .../pdftemplates/planningappeals78_pdf.js | 195 +++++++++++++----- data/crmfieldlookuptranslations.json | 14 +- locales/cy/newappeal.json | 24 ++- locales/en/newappeal.json | 24 ++- pages/api/file/generateappealpdf.js | 3 +- 7 files changed, 271 insertions(+), 81 deletions(-) diff --git a/components/newappeal/buildchecksection.js b/components/newappeal/buildchecksection.js index 6285306f..d5672c35 100644 --- a/components/newappeal/buildchecksection.js +++ b/components/newappeal/buildchecksection.js @@ -158,6 +158,7 @@ let BuildCheckSection = (props) => { ); pdfObj.filesList = uniqueArray; + pdfObj.locale = locale; confirmSections ? (setFinaliseAppealProcess(true), @@ -186,6 +187,9 @@ let BuildCheckSection = (props) => { }; const triggerAppealDownload = async () => { + if (!downloadAppealForm) { + return; + } if (downloadInProgress) { return; } @@ -199,8 +203,7 @@ let BuildCheckSection = (props) => { ); pdfObj.filesList = uniqueArray; - - console.log(pdfObj); + pdfObj.locale = locale; const containerID = props.accountDetails?.containerID || @@ -442,10 +445,9 @@ let BuildCheckSection = (props) => { ) : ( <> - { @@ -454,7 +456,7 @@ let BuildCheckSection = (props) => { }} > {t("newappeal:submit-appeal-button")} - + { let { t } = useTranslation(); + let locale = props.props.locale; const { formXML, @@ -146,18 +148,32 @@ export const AppealRow_pdf = (props) => { return dateString; } - const FieldsTranslations = (label) => { - const { appealtypes } = router.query; + const FieldsTranslations = (label, locale) => { + const appealtypes = getFormCollectionByID( + props.props.caseObj.pinswg_appealcasetype + ).UrlName; - let formObj = jsonpath({ - path: "$['" + appealtypes + "']", + const formObj = jsonpath({ + path: `$['${appealtypes}'].[?(@.value=="${label}")]`, json: fieldLookup, eval: true }); - let labelTrans = label; - return labelTrans; + const item = formObj?.[0]; + + if (locale === "cy" && !item?.value_cy) { + console.warn(`[Missing Welsh translation]`, { + label: item?.value, + orig: label, + appealType: appealtypes + }); + } + + return locale === "cy" + ? (item?.value_cy ?? item?.value ?? label) + : (item?.value ?? label); }; + Font.registerHyphenationCallback((word) => [word]); function CleanHTML(htmlStr) { @@ -219,8 +235,10 @@ export const AppealRow_pdf = (props) => { - {/* {FieldsTranslations(rows[0].value)} */} - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )}{" "} { styles.questionTextMid } > - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )} { styles.questionTextWide } > - {rows[0].value}{" "} + {FieldsTranslations( + rows[0].value, + locale + )}{" "} { styles.questionTextWide } > - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )} { > {/* {FieldsTranslations(rows[0].value)} */} - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )} {getPickListLabel( @@ -453,7 +483,10 @@ export const AppealRow_pdf = (props) => { styles.questionTextWide } > - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )} @@ -524,7 +557,10 @@ export const AppealRow_pdf = (props) => { styles.questionTextMid } > - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )} { style={styles.questionText} wrap={false} > - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )} { }} > - {rows[0].value} + {FieldsTranslations( + rows[0].value, + locale + )} { diff --git a/components/pdftemplates/planningappeals78_pdf.js b/components/pdftemplates/planningappeals78_pdf.js index 8ee1d5da..caf90f61 100644 --- a/components/pdftemplates/planningappeals78_pdf.js +++ b/components/pdftemplates/planningappeals78_pdf.js @@ -6,7 +6,7 @@ import ReactPDF, { Image, StyleSheet, PDFViewer, - Font, + Font } from "@react-pdf/renderer"; import Html from "react-pdf-html"; import { getFormCollectionByID, bytesToSize } from "../utils"; @@ -17,28 +17,42 @@ import _ from "lodash"; import { DOMParser, XMLSerializer } from "@xmldom/xmldom"; import { AppealRow_pdf } from "./appealRow_pdf"; +import transLookupCY from "../../locales/cy/newappeal.json"; +import transLookupEN from "../../locales/en/newappeal.json"; +import fieldLookup from "../../data/crmfieldlookuptranslations.json"; +import { JSONPath as jsonpath } from "jsonpath-plus"; + +const getTrans = (locale, key) => { + let jsonQuery = `$.${key}`; + + let jsonObj = locale == "cy" ? transLookupCY : transLookupEN; + + //console.log(locale, jsonObj[key]); + return jsonObj[key]; +}; + const styles = StyleSheet.create({ page: { backgroundColor: "white", padding: 20, fontSize: 16, - paddingBottom: 50, + paddingBottom: 50 }, header: { fontSize: 25, fontFamily: "Helvetica", flexDirection: "row", - justifyContent: "space-between", + justifyContent: "space-between" }, subHeader: { - fontSize: 20, + fontSize: 20 }, logoImage: { width: "200pt" }, questionBullet: { width: "5%", fontSize: 12 }, questionText: { width: "35%", fontSize: 12, - fontFamily: "Helvetica-Bold", + fontFamily: "Helvetica-Bold" }, questionTextMid: { width: "80%", fontSize: 12 }, questionTextWide: { width: "95%", fontSize: 12, marginBottom: 5 }, @@ -50,7 +64,7 @@ const styles = StyleSheet.create({ border: 1, borderColor: "#eee", paddingLeft: 10, - backgroundColor: "white", + backgroundColor: "white" }, questionAnswerMid: { color: "#757575", @@ -60,7 +74,7 @@ const styles = StyleSheet.create({ border: 1, borderColor: "#eee", paddingLeft: 10, - backgroundColor: "white", + backgroundColor: "white" }, questionAnswerWide: { color: "#757575", @@ -70,14 +84,14 @@ const styles = StyleSheet.create({ border: 1, borderColor: "#eee", backgroundColor: "white", - padding: 5, + padding: 5 }, sectionContainer: { backgroundColor: "#F8F8F8", padding: 10, marginTop: 20, - fontSize: 15, + fontSize: 15 }, pageNumber: { position: "absolute", @@ -86,17 +100,18 @@ const styles = StyleSheet.create({ left: 0, right: 0, textAlign: "center", - color: "grey", + color: "grey" }, richArea: { fontSize: 12, - flexDirection: "column", - }, + flexDirection: "column" + } }); export const planningappeals78_pdf = ({ docProps, pickListData }) => { //console.log("----", docProps); + const locale = docProps.locale; function formatDates(dateObj) { var dateObj = new Date(dateObj); var dd = String(dateObj.getDate()).padStart(2, "0"); @@ -145,6 +160,32 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { Font.registerHyphenationCallback((word) => [word]); + const FieldsTranslations = (label, locale) => { + const appealtypes = getFormCollectionByID( + docProps.caseObj.pinswg_appealcasetype + ).UrlName; + + const formObj = jsonpath({ + path: `$['${appealtypes}'].[?(@.value=="${label}")]`, + json: fieldLookup, + eval: true + }); + + const item = formObj?.[0]; + + if (locale === "cy" && !item?.value_cy) { + console.warn(`[Missing Welsh translation]`, { + label: item?.value, + orig: label, + appealType: appealtypes + }); + } + + return locale === "cy" + ? (item?.value_cy ?? item?.value ?? label) + : (item?.value ?? label); + }; + return ( @@ -154,10 +195,10 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { - Planning Appeals s78 + {getTrans(locale, "pdf-s78-heading")} { width: "60%", fontSize: 15, marginTop: 20, - fontFamily: "Helvetica-Bold", + fontFamily: "Helvetica-Bold" }} > - For Planning, Conservation area, Listed - Building and Advertisement - applications/appeals + {" "} + {getTrans( + locale, + "pdf-s78-header-paragraph" + )} @@ -188,23 +231,27 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { - {parseInt(key)} {titles[key].value} + {parseInt(key)}{" "} + {FieldsTranslations( + titles[key].value, + locale + )} { borderColor: "#eee", padding: 20, paddingTop: 30, - height: "100%", + height: "100%" }} > @@ -261,33 +308,39 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { - Case Details + + {" "} + {getTrans(locale, "pdf-s78-heading")} + - Appeal submitted on behalf of: + {getTrans( + locale, + "pdf-case-details-label-1" + )} {" "} @@ -298,11 +351,14 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Appellant or Agent + {getTrans( + locale, + "pdf-case-details-label-2" + )} {" "} @@ -317,11 +373,14 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Appellant name + {getTrans( + locale, + "pdf-case-details-label-3" + )} {values.caseObj @@ -335,11 +394,14 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Appellant email address + {getTrans( + locale, + "pdf-case-details-label-4" + )} { @@ -352,11 +414,14 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Appellant address + {getTrans( + locale, + "pdf-case-details-label-5" + )} { @@ -369,11 +434,14 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Appellant phone number + {getTrans( + locale, + "pdf-case-details-label-3" + )} {" "} @@ -390,13 +458,16 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Company name + {getTrans( + locale, + "pdf-case-details-agent-label-1" + )} { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Agent name + {getTrans( + locale, + "pdf-case-details-agent-label-2" + )} { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Agent email address + {getTrans( + locale, + "pdf-case-details-agent-label-3" + )} { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Agent address + {getTrans( + locale, + "pdf-case-details-agent-label-4" + )} { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Agent phone number + {getTrans( + locale, + "pdf-case-details-agent-label-5" + )} { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - LPA + {getTrans( + locale, + "pdf-case-details-label-7" + )} {values.caseObj.pinswg_lpaname || @@ -547,11 +633,14 @@ export const planningappeals78_pdf = ({ docProps, pickListData }) => { wrap={false} style={{ flexDirection: "row", - marginBottom: 10, + marginBottom: 10 }} > - Language Preference + {getTrans( + locale, + "pdf-case-details-label-8" + )} {values.caseObj diff --git a/data/crmfieldlookuptranslations.json b/data/crmfieldlookuptranslations.json index 836af269..65d18e6d 100644 --- a/data/crmfieldlookuptranslations.json +++ b/data/crmfieldlookuptranslations.json @@ -2231,7 +2231,7 @@ "value_cy": "A yw'n hanfodol i'r Arolygydd fynd i mewn i'r safle i wirio mesuriadau neu ffeithiau eraill perthnasol?" }, { - "value": "Please explain why the inspector needs to enter the site", + "value": "Please explain why the Inspector needs to enter the site", "value_cy": "Eglurwch pam mae angen i'r Arolygydd fynd i mewn i'r safle" }, { @@ -2433,6 +2433,18 @@ { "value": "The S106 agreement or unilateral undertaking", "value_cy": "Cytundeb S106 neu ymgymeriad unochrog" + }, + { + "value": "Owner", + "value_cy": "Perchennog" + }, + { + "value": "Tenant name", + "value_cy": "Enw tenant" + }, + { + "value": "Please submit your statement of case", + "value_cy": "Cyflwynwch eich datganiad achos" } ] } diff --git a/locales/cy/newappeal.json b/locales/cy/newappeal.json index 21695e44..09c6aba4 100644 --- a/locales/cy/newappeal.json +++ b/locales/cy/newappeal.json @@ -123,5 +123,27 @@ "new-appeal-finalising-label": "Wrthi'n uwchlwytho ffeiliau ar hyn o bryd a chwblhau eich cyflwyniad apêl", "new-appeal-wait-label": "Arhoswch os gwelwch yn dda", "invalid-email-address-errormsg": "Cyfeiriad e-bost annilys", - "return-to-myportal-link": "Dychwelyd i Fy Mhorth" + "return-to-myportal-link": "Dychwelyd i Fy Mhorth", + "pdf-s78-heading": "Apelau Cynllunio s78", + "pdf-s78-header-paragraph": "Ar gyfer ceisiadau/apelau Cynllunio, Ardal Gadwraeth, Adeilad Rhestredig a Hysbysebu", + "pdf-heading-1": "Manylion yr apêl", + "pdf-case-subheading-1": "Manylion perchnogaeth safle'r apêl", + "pdf-case-subheading-2": "Gwybodaeth am ymweliad â'r safle", + "pdf-case-subheading-3": "Apelau eraill", + "pdf-case-subheading-4": "Cyflwyno achos", + "pdf-case-subheading-5": "Uwchlwytho dogfennau", + "pdf-case-details-subheading": "Manylion yr Achos", + "pdf-case-details-label-1": "Apel a gyflwynwyd ar ran", + "pdf-case-details-label-2": "Apelydd neu Asiant", + "pdf-case-details-label-3": "Enw'r apelydd", + "pdf-case-details-label-4": "E-bost yr apelydd", + "pdf-case-details-label-5": "Cyfeiriad yr apelydd", + "pdf-case-details-label-6": "Rhif ffôn yr apelydd", + "pdf-case-details-label-7": "LPA", + "pdf-case-details-label-8": "Dewis Iaith", + "pdf-case-details-agent-label-1": "Enw'r cwmni", + "pdf-case-details-agent-label-2": "Enw'r asiant", + "pdf-case-details-agent-label-3": "Cyfeiriad e-bost yr asiant", + "pdf-case-details-agent-label-4": "Cyfeiriad yr asiant", + "pdf-case-details-agent-label-5": "Rhif ffôn yr asiant" } \ No newline at end of file diff --git a/locales/en/newappeal.json b/locales/en/newappeal.json index 6548f801..200b4c30 100644 --- a/locales/en/newappeal.json +++ b/locales/en/newappeal.json @@ -123,5 +123,27 @@ "new-appeal-finalising-label": "Currently uploading files and finalising your appeal submission", "new-appeal-wait-label": "Please wait", "invalid-email-address-errormsg": "Invalid email address", - "return-to-myportal-link": "Return to My Portal" + "return-to-myportal-link": "Return to My Portal", + "pdf-s78-heading": "Planning Appeals s78", + "pdf-s78-header-paragraph": "For Planning, Conservation area, Listed Building and Advertisement applications/appeals", + "pdf-heading-1": "Appeal details", + "pdf-case-subheading-1": "Appeal site ownership details", + "pdf-case-subheading-2": "Site visit information", + "pdf-case-subheading-3": "Other appeals", + "pdf-case-subheading-4": "Submission of case", + "pdf-case-subheading-5": "Upload documents", + "pdf-case-details-subheading": "Case Details", + "pdf-case-details-label-1": "Appeal submitted on behalf of", + "pdf-case-details-label-2": "Appellant or Agent", + "pdf-case-details-label-3": "Appellant name", + "pdf-case-details-label-4": "Appellant email address", + "pdf-case-details-label-5": "Appellant address", + "pdf-case-details-label-6": "Appellant phone number", + "pdf-case-details-label-7": "LPA", + "pdf-case-details-label-8": "Language Preference", + "pdf-case-details-agent-label-1": "Company name", + "pdf-case-details-agent-label-2": "Agent name", + "pdf-case-details-agent-label-3": "Agent email address", + "pdf-case-details-agent-label-4": "Agent address", + "pdf-case-details-agent-label-5": "Agent phone number" } \ No newline at end of file diff --git a/pages/api/file/generateappealpdf.js b/pages/api/file/generateappealpdf.js index d4fb3569..34fc1119 100644 --- a/pages/api/file/generateappealpdf.js +++ b/pages/api/file/generateappealpdf.js @@ -100,6 +100,7 @@ export default async function handler(req, res) { typeof req.body === "string" ? JSON.parse(req.body) : req.body; const containerID = appealBodyObj.containerID; const casefolderID = appealBodyObj.casefolderID; + const locale = appealBodyObj.locale || "en"; let checkquerypath = "/api/file/generateappealpdf"; if ( @@ -207,7 +208,7 @@ export default async function handler(req, res) { const renderedPDF = await ReactPDF.renderToStream( MyDocument({ - docProps: blobProgress, + docProps: { ...blobProgress, locale }, pickListData: pickListData }) );