Files
pedwfrontend/components/case/representation/representationElements.js
T
2024-02-08 14:28:40 +00:00

1150 lines
41 KiB
JavaScript

import { Field, Fields, reduxForm } from "redux-form";
import router from "next/router";
import React, { useState, useMemo } from "react";
import useTranslation from "next-translate/useTranslation";
import { JSONPath as jsonpath } from "jsonpath-plus";
import Dropzone, { useDropzone } from "react-dropzone";
import Link from "next/link";
import dynamic from "next/dynamic";
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
import "react-quill/dist/quill.snow.css";
import DatePicker, { registerLocale, setDefaultLocale } from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import {
addYears,
addMonths,
addDays,
subYears,
subMonths,
subDays,
parseISO,
} from "date-fns";
import {
getFormCollectionByID,
getThumbnailIconByExtension,
bytesToSize,
} from "../../utils";
import { useRouter } from "next/router";
export const RenderRadioList = ({
datafieldname,
name,
label,
id,
errorMsg,
options,
input: { onChange, value },
meta: { touched, error },
...custom
}) => {
const required = (value) => (value ? undefined : "Required");
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<fieldset
className="govuk-fieldset"
aria-describedby={name + "-hint"}
>
<legend className="govuk-fieldset__legend govuk-fieldset__legend--s govuk-!-font-weight-regular">
<label
className="govuk-fieldset__heading govuk-body-m"
id={id + "_label"}
>
{label}
</label>
</legend>
{touched && error && (
<span
id={id + "-error"}
className="govuk-error-message"
>
<span className="govuk-visually-hidden">
Error:
</span>{" "}
{errorMsg}
</span>
)}
<div
className={
custom.inline == true
? "govuk-radios govuk-radios--inline govuk-radios--small"
: "govuk-radios govuk-radios--small"
}
>
{Object.keys(options).map((key, index) => (
<div
className="govuk-radios__item"
data-children-count={key}
key={key}
>
<Field
id={id + "_" + index}
name={id}
component="input"
type="radio"
className="govuk-radios__input"
value={options[key]}
/>
<label
className="govuk-label govuk-radios__label"
htmlFor={id + "_" + index}
>
{options[key]}
</label>
</div>
))}
</div>
</fieldset>
</div>
</>
);
};
export const RenderRadioListWithText = ({
datafieldname,
name,
label,
id,
errorMsg,
options,
input: { onChange, value },
meta: { touched, error },
...custom
}) => {
const required = (value) => (value ? undefined : "Required");
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<fieldset
className="govuk-fieldset"
aria-describedby={name + "-hint"}
>
<legend className="govuk-fieldset__legend govuk-fieldset__legend--s govuk-!-font-weight-regular">
<label
className="govuk-fieldset__heading govuk-body-m"
id={id + "_label"}
>
{label}
</label>
</legend>
{touched && error && (
<span
id={id + "-error"}
className="govuk-error-message"
>
<span className="govuk-visually-hidden">
Error:
</span>{" "}
{errorMsg}
</span>
)}
<div
className={
custom.inline == true
? "govuk-radios govuk-radios--inline govuk-radios--small "
: "govuk-radios govuk-radios--small govuk-grid-column-full"
}
>
{Object.keys(options).map((key, index) => (
<div
className="govuk-radios__item govuk-grid-column-full"
data-children-count={key}
key={key}
>
<Field
id={id + "_" + index}
name={id}
component="input"
type="radio"
className="govuk-radios__input"
value={options[key]}
/>
<label
className="govuk-label govuk-radios__label"
htmlFor={id + "_" + index}
>
{options[key]}
</label>
{value === options[key] && (
<div
className="govuk-radios__conditional "
id={"conditional_" + id + "_" + index}
>
<div className="govuk-form-group">
<label
className="govuk-label"
htmlFor={
"conditional_" +
id +
"_Comments"
}
>
Please give further details for
your this selection
</label>
<Field
name={
"conditional_" +
id +
"_Comments"
}
id={
"conditional_" +
id +
"_Comments"
}
component={RenderRichMultiline}
type="text"
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={
id + "_" + index + "-hint"
}
/>
</div>
</div>
)}
</div>
))}
</div>
</fieldset>
</div>
</>
);
};
export const RenderCondtionalRadioList = ({
datafieldname,
legend,
name,
label,
id,
errorMsg,
options,
input: { onChange, value },
meta: { touched, error },
...custom
}) => {
const required = (value) => (value ? undefined : "Required");
let { t } = useTranslation();
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<fieldset
className="govuk-fieldset"
aria-describedby={id + "-hint"}
>
<legend className="govuk-fieldset__legend govuk-fieldset__legend--s govuk-!-font-weight-regular">
<label
className="govuk-fieldset__heading govuk-body-m"
id={id + "_label"}
>
{label}
</label>
</legend>
{touched && error && (
<span
id={id + "-error"}
className="govuk-error-message"
>
<span className="govuk-visually-hidden">
Error:
</span>{" "}
{errorMsg}
</span>
)}
<legend className="govuk-fieldset__legend govuk-fieldset__legend--m">
<label
className="govuk-fieldset__heading govuk-body-m"
id="representationCapacity_label"
>
{legend}
</label>
</legend>
<div id={id + "-hint"} className="govuk-hint">
e.g. &lsquo;Owners of Numbers 1-5 High Street&lsquo;, or
&lsquo;Mr and Mrs Smith&lsquo; or &lsquo;The executors
of Mr Evans&lsquo; estate&lsquo;
</div>
<div className="govuk-radios">
{Object.keys(options).map((key, index) => (
<div key={key} className="govuk-!-margin-bottom-3">
<div
className="govuk-radios__item"
data-children-count={key}
key={key}
>
<Field
id={id + "_" + index}
name={id}
component="input"
type="radio"
className="govuk-radios__input"
value={options[key]}
validate={[required]}
/>
<label
className="govuk-label govuk-radios__label"
htmlFor={id + "_" + index}
>
{options[key]}
</label>
</div>
{value ==
t("myrepresentations:questionnaire-yes") &&
options[key] ==
t(
"myrepresentations:questionnaire-yes"
) && (
<div
className="govuk-radios__conditional "
id={"conditional-" + id}
>
<div
className="govuk-form-group"
key={"yes_group_" + key}
>
<label
className="govuk-label"
htmlFor={id + "_details"}
>
Enter the name of the
company/group/organisation *
</label>
<Field
className="govuk-input govuk-!-width-one-half"
id={id + "_details"}
name={id + "_details"}
component="input"
type="text"
/>
</div>
</div>
)}
</div>
))}
</div>
</fieldset>
</div>
</>
);
};
export const RenderLPACondtionalRadioList = ({
datafieldname,
legend,
name,
label,
id,
errorMsg,
options,
input: { onChange, value },
meta: { touched, error },
...custom
}) => {
const required = (value) => (value ? undefined : "Required");
console.log(error);
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<fieldset
className="govuk-fieldset"
aria-describedby={id + "-hint"}
>
<legend className="govuk-fieldset__legend govuk-fieldset__legend--s govuk-!-font-weight-regular">
<label
className="govuk-fieldset__heading govuk-body-m"
id={id + "_label"}
>
{label}
</label>
</legend>
{touched && error && (
<span
id={id + "-error"}
className="govuk-error-message"
>
<span className="govuk-visually-hidden">
Error:
</span>{" "}
{errorMsg}
</span>
)}
<legend className="govuk-fieldset__legend govuk-fieldset__legend--m">
<label
className=" govuk-body-m"
id="representationCapacity_label"
>
{legend}
</label>
</legend>
<div id={id + "-hint"} className="govuk-hint"></div>
<div className="govuk-radios govuk-radios--small">
{Object.keys(options).map((key, index) => (
<div key={key} className="govuk-!-margin-bottom-3">
<div
className="govuk-radios__item"
data-children-count={key}
key={key}
>
<Field
id={id + "_" + index}
name={id}
component="input"
type="radio"
className="govuk-radios__input"
value={options[key]}
validate={[eval(required)]}
/>
<label
className="govuk-label govuk-radios__label"
htmlFor={id + "_" + index}
>
{options[key]}
</label>
</div>
{value == custom.optionSelect &&
options[key] == custom.optionSelect && (
<div
className="govuk-radios__conditional "
id={id}
>
<div
className="govuk-form-group"
key={"yes_group_" + key}
>
<label
className="govuk-label"
htmlFor={id + "_details"}
>
{custom.conditionalLabel}
</label>
<Field
className="govuk-input govuk-!-width-one-half"
id={id + "Evidence"}
name={id + "Evidence"}
component={RenderMultiline}
/>
</div>
</div>
)}
</div>
))}
</div>
</fieldset>
</div>
</>
);
};
export const RenderPickList = ({
datafieldname,
name,
label,
input,
optionsArr,
meta: { touched, error },
errorMsg,
}) => {
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<label className="govuk-label" htmlFor="sort">
{label}
</label>
{touched && error && (
<span
id="passport-issued-error"
className="govuk-error-message"
>
<span className="govuk-visually-hidden">Error:</span>{" "}
{errorMsg}
</span>
)}
<div>
<select
{...input}
className="govuk-select "
id={name}
name={name}
>
<option>Select...</option>
{Object.keys(optionsArr).map((key, index) => {
return (
<option key={key} value={optionsArr[key]}>
{optionsArr[key]}
</option>
);
})}
</select>
</div>
</div>
</>
);
};
export const RenderTextfield = ({
id,
rows,
datafieldname,
name,
label,
input,
errorMsg,
type,
className,
meta: { touched, error },
...custom
}) => {
const required = (value) => (value ? undefined : "Required");
return (
<>
<label className="govuk-label " htmlFor={id} id={id + "_label"}>
{label}
</label>
{touched && error && (
<span id={id + "-error"} className="govuk-error-message">
<span className="govuk-visually-hidden">Error:</span>{" "}
{errorMsg}
</span>
)}
<input
{...input}
className={className}
name={name}
id={id}
type={type}
/>
</>
);
};
export const RenderDatePicker = ({
datafieldname,
name,
label,
id,
errorMsg,
input: { onChange, value },
meta: { touched, error },
...custom
}) => {
const router = useRouter();
var startDateArr =
custom.dateStart != "0" ? custom.dateStart.split("") : custom.dateStart;
var endDateArr =
custom.dateEnd != "0" ? custom.dateEnd.split("") : custom.dateEnd;
var minDate =
startDateArr == 0
? new Date()
: startDateArr[0] == "-"
? startDateArr[2] == "y"
? subYears(new Date(), startDateArr[1])
: startDateArr[2] == "m"
? subMonths(new Date(), startDateArr[1])
: subDays(new Date(), startDateArr[1])
: startDateArr[2] == "y"
? addYears(new Date(), startDateArr[1])
: startDateArr[2] == "m"
? addMonths(new Date(), startDateArr[1])
: addDays(new Date(), startDateArr[1]);
var maxDate =
endDateArr == 0
? new Date()
: startDateArr[0] == "-"
? startDateArr[2] == "y"
? subYears(new Date(), startDateArr[1])
: startDateArr[2] == "m"
? subMonths(new Date(), startDateArr[1])
: subDays(new Date(), startDateArr[1])
: startDateArr[2] == "y"
? addYears(new Date(), startDateArr[1])
: startDateArr[2] == "m"
? addMonths(new Date(), startDateArr[1])
: addDays(new Date(), startDateArr[1]);
return (
<>
<div
className={
touched && error
? "govuk-form-group govuk-form-group--error"
: "govuk-form-group "
}
>
<fieldset
className="govuk-fieldset"
role="group"
aria-describedby={id + "_label"}
>
<legend className="govuk-fieldset__legend govuk-fieldset__legend--s govuk-!-font-weight-regular">
<label
className="govuk-fieldset__heading"
id={id + "_label"}
htmlFor={id}
>
{label}
</label>
</legend>
{touched && error && (
<span
id={id + "-error"}
className="govuk-error-message"
>
<span className="govuk-visually-hidden">
Error:
</span>{" "}
{errorMsg}
</span>
)}
<DatePicker
{...custom}
locale={custom.locale}
autoOk={true}
id={id}
dateFormat="dd/MM/yyyy"
onChange={onChange}
selected={
value
? typeof value != "object"
? parseISO(value)
: value
: null
} //{parseISO(value) || null}
className="govuk-input govuk-input--width-10"
minDate={minDate}
maxDate={maxDate}
//value={!value ? null : moment(value, "DD/MM/yyyy")}
/>
</fieldset>
</div>
</>
);
};
export const RenderMultiline = ({
id,
className,
rows,
datafieldname,
name,
label,
input,
meta: { touched, error },
...custom
}) => {
const [editValue, setEditValue] = useState(
input.value != null ? input.value : ""
);
const changeEdit = (valStr) => {
setEditValue(valStr);
input.onChange(valStr);
};
var modules = {
toolbar: [
[{ "header": [1, 2, false] }],
["bold", "italic", "underline", "blockquote"],
[{ "list": "ordered" }, { "list": "bullet" }, "link"],
["clean"],
],
};
return (
<>
<div className="govuk-form-group ">
<label className="govuk-label" htmlFor={name}>
{label}
</label>
{"hint" in custom}
{"hint" in custom && (
<div
id={name + "-hint"}
className="govuk-hint govuk-!-font-size-14"
>
{custom.hint}
</div>
)}
<ReactQuill
modules={modules}
theme="snow"
value={editValue}
onChange={changeEdit}
/>
<textarea
{...input}
id={id}
name={name}
rows={rows}
className={className}
value={editValue}
style={{ display: "none" }}
></textarea>
</div>
</>
);
};
export const RenderRichMultiline = ({
id,
className,
rows,
datafieldname,
name,
label,
input,
meta: { touched, error },
...custom
}) => {
const [editValue, setEditValue] = useState(
input.value != null ? input.value : ""
);
const changeEdit = (valStr) => {
setEditValue(valStr);
input.onChange(valStr);
};
var modules = {
toolbar: [
[{ "header": [1, 2, false] }],
["bold", "italic", "underline", "blockquote"],
[{ "list": "ordered" }, { "list": "bullet" }],
["clean"],
],
};
return (
<>
<label className="govuk-label" htmlFor={name}>
{label}
</label>
<ReactQuill
modules={modules}
theme="snow"
value={editValue}
onChange={changeEdit}
/>
<textarea
{...input}
id={id}
name={name}
rows={rows}
className={className}
value={editValue}
style={{ display: "none" }}
></textarea>
</>
);
};
export function MultiLinefield(props) {
const { name, label } = props;
return (
<div className="govuk-form-group">
<h1 className="govuk-label-wrapper">
<label className="govuk-label" htmlFor={props.name}>
{props.label}
</label>
</h1>
<div
id={props.name + "-hint"}
className="govuk-hint govuk-!-font-size-14"
>
Do not include personal or financial information, like your
National Insurance number or credit card details.
</div>
<Field
name={props.name}
id={props.name}
component={RenderMultiline}
type="text"
rows="5"
validate={[required]}
className="govuk-textarea govuk-input--width-30"
aria-describedby={props.name + "-hint"}
/>
</div>
);
}
const baseStyle = {
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
borderWidth: 2,
borderRadius: 2,
borderColor: "#eeeeee",
borderStyle: "dashed",
backgroundColor: "#fafafa",
color: "#bdbdbd",
transition: "border .3s ease-in-out",
};
const activeStyle = {
borderColor: "#2196f3",
};
const acceptStyle = {
borderColor: "#00e676",
};
const rejectStyle = {
borderColor: "#ff1744",
};
export const RenderFileUpload = (field) => {
const files = field.input.value;
let { t } = useTranslation();
const style = useMemo(
() => ({
...baseStyle,
// ...(isDragActive ? activeStyle : {}),
// ...(isDragAccept ? acceptStyle : {}),
// ...(isDragReject ? rejectStyle : {}),
}),
[]
// [isDragActive, isDragReject, isDragAccept]
);
const [filesList, setFilesList] = useState([]);
const thumbs = filesList.map((file) => (
<div key={file.name} className="govuk-!-margin-bottom-5 fileThumb">
<img src={file.preview} alt={file.name} width="50" /> -{" "}
<span className="govuk-body">
{file.name} ({file.size / 1024}kb)
</span>
</div>
));
const getThumbnailIcon = (fileObj, fileType) => {
switch (fileType) {
case "text/html":
return "/assets/images/documenttypes/html.png";
break;
case "text/plain":
return "/assets/images/documenttypes/txt.png";
break;
case "application/msword":
return "/assets/images/documenttypes/doc.png";
break;
case "application/pdf":
return "/assets/images/documenttypes/pdf.png";
break;
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
return "/assets/images/documenttypes/docx.png";
break;
case "text/csv":
return "/assets/images/documenttypes/csv.png";
break;
case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
return "/assets/images/documenttypes/xlsx.png";
break;
case "application/zip":
return "/assets/images/documenttypes/zip.png";
break;
case "image/jpeg":
case "image/png":
return URL.createObjectURL(fileObj);
break;
default:
return "/assets/images/documenttypes/txt.png";
break;
}
};
const getDocumentType = (docCode) => {
switch (docCode) {
case "000001":
return "000001";
break;
case "000002":
return "000002";
break;
case "000003":
return "000003";
break;
case "000004":
return "000004";
break;
case "000005":
return "000005";
break;
case "000006":
return "000006";
break;
case "000007":
return "000007";
break;
case "000008":
return "000008";
break;
case "000009":
return "000009";
break;
case "000010":
return "000010";
break;
case "000011":
return "000011";
break;
case "000012":
return "000012";
break;
case "000013":
return "000013";
break;
case "000014":
return "000014";
break;
case "000015":
return "000015";
break;
default:
return "000000";
}
};
const filelistObj = field.fileList || {};
const blobList = jsonpath(
"$..[?(@.documentType=='" + field.documentTypeCode + "')]",
filelistObj
);
const deleteThisBlob = async (
containerName,
blobName,
deleteblobhash,
getblobshash,
casefolderID
) => {
deleteBlob(containerName, blobName, deleteblobhash, casefolderID)
.then((data) => data)
.then(() => {
getFilesFromBlobHashed(
containerName,
getblobshash,
casefolderID
).then((newfilelist) => field.setFilesForAppeal(newfilelist));
});
};
return (
<>
<Dropzone
accept="application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,image/tiff,image/jpeg,application/zip"
onDrop={(filesToUpload, e) => {
const renamedAcceptedFiles = filesToUpload.map(
(file) =>
new File([file], `${file.name}`, {
type: file.type,
})
);
field.input.onChange(renamedAcceptedFiles);
}}
>
{({ getRootProps, getInputProps }) => (
<>
<section className="container">
<div {...getRootProps({ style })}>
{" "}
<input id={field.id} {...getInputProps()} />
<div>
{t(
"newappeal:new-appeal-fileupload-drop-label"
)}
</div>
<em>
(
{t(
"newappeal:new-appeal-fileupload-file-list-label"
)}
)
</em>
</div>
<aside>{thumbs}</aside>
</section>
</>
)}
</Dropzone>
{field.meta.touched && field.meta.error && (
<span className="error">{field.meta.error}</span>
)}
{files && Array.isArray(files) && (
<ul>
{files.map((file, i) => (
<div
key={file.name}
className="govuk-!-margin-bottom-5 fileThumb"
>
<img
src={getThumbnailIcon(file, file.type)}
alt={file.name}
width="50"
/>
<span className="govuk-body govuk-!-font-size-14 govuk-!-padding-left-5">
{file.name} ({bytesToSize(file.size)})
</span>
</div>
))}
</ul>
)}
{blobList.map((blob, i) => (
<div
key={blob.name + "_" + i}
className="govuk-!-margin-bottom-5 fileThumb govuk-!-margin-top-5"
>
<div className="">
<span
className="govuk-summary-list__actionLink watched_link govuk-!-margin-right-5 govuk-!-text-align-left"
onClick={() => {
deleteThisBlob(
field.containerID,
blob.name,
blob.hasheddeletepath,
blob.hashgetblobs,
field.ticketnumber
);
}}
title="Remove this file"
>
&minus;
</span>
</div>
<img
src={getThumbnailIconByExtension(blob.name)}
alt={blob.name}
width="50"
/>
<Link
key={i}
scroll={false}
href={
"/api/file/downloadblob?container=" +
field.containerID +
"&casefolderID=" +
field.ticketnumber +
"&blobname=" +
blob.name +
blob.hashedfilepath
}
className="govuk-body govuk-!-font-size-14 govuk-!-padding-left-5 govuk-link"
>
{blob.name}({bytesToSize(blob.contentLength)})
</Link>
</div>
))}{" "}
</>
);
};
export function FileUploadField(props) {
return (
<>
<h2 className="govuk-heading-s">{props.label} </h2>
<Field
name={props.name}
id={props.name}
component={RenderFileUpload}
className="govuk-input govuk-input--width-20"
//validate={[required]}
label={props.label}
errorMsg="Is required"
ticketnumber={props.ticketnumber}
hint={props.hint}
fileList={props.fileList}
setFilesForAppeal={props.setFilesForAppeal}
containerID={props.containerID}
/>
</>
);
}
// export const RepresentationGuidanceText = (appealType) => {
// let { t } = useTranslation();
// console.log(appealType);
// switch (appealType) {
// case "846040004": //has/cas
// return (
// <p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
// {t("myrepresentations:questionnaire-publish-policy-label")}{" "}
// <a href="https://gov.wales/planning-and-environment-decisions-wales-publishing-policy-html">
// https://gov.wales/planning-and-environment-decisions-wales-publishing-policy-html
// </a>
// </p>
// );
// break;
// default:
// return (
// <p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
// {t("myrepresentations:publish-policy-label")}{" "}
// <a href="https://gov.wales/planning-and-environment-decisions-wales-publishing-policy-html">
// https://gov.wales/planning-and-environment-decisions-wales-publishing-policy-html
// </a>
// </p>
// );
// break;
// }
// return guidanceString;
// };