Files
pedwfrontend/components/case/representation/representationElements.js
T

1041 lines
36 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 from "jsonpath";
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 RenderCondtionalRadioList = ({
datafieldname,
legend,
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={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 == "Yes" && options[key] == "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");
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={[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>
)}
{/* {value}
<br />
{moment(value).format("DD/MM/YY")}
<br /> */}
<DatePicker
{...custom}
locale={router.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.query(
filelistObj,
"$..[?(@.documentType=='" + field.documentTypeCode + "')]"
);
const deleteThisBlob = async (
containerName,
blobName,
deleteblobhash,
getblobshash,
casefolderID
) => {
//console.log(containerName, blobName, deleteblobhash);
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 }) => (
<>
{/* {field.hint != false && (
<div className="govuk-hint">ss{t(field.hint)}</div>
)}
<div className="govuk-form-group"></div> */}
<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
}
>
<a className="govuk-body govuk-!-font-size-14 govuk-!-padding-left-5 govuk-link">
{blob.name} ({bytesToSize(blob.contentLength)})
</a>
</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) => {
console.log(appealType);
switch (appealType) {
case "846040004": //has/cas
return (
<p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
Please note that all questionnaire documents may be
published in line with our Publishing Policy. Should your
questionnaire include any sensitive information or
potentially defamatory information, it may be redacted
before publishing.{" "}
<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">
Please note that all representations may be published in
line with our Publishing Policy. Should your representation
include any sensitive information or potentially defamatory
information, it may be redacted before publishing. If it
contains racist, libellous or offensive content it will be
returned to you and you will be asked to provide an amended
version.{" "}
<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;
};