webui/src/modules/manager/specifications/SpecificationsDetails.tsx

302 lines
8.8 KiB
TypeScript

import Joi from "joi";
import React, { useEffect, useRef, useState, useCallback } from "react";
import { Navigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import { Namespaces } from "../../../i18n/i18n";
import { useForm } from "../../../components/common/useForm";
import { InputType } from "../../../components/common/Input";
import Loading from "../../../components/common/Loading";
import TemplateFiller, {
TemplateFillerHandle,
} from "../../../components/common/TemplateFiller";
import { GeneralIdRef, MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
import {
CustomFieldValue,
PrintSpecificationsGlossary,
} from "../glossary/services/glossaryService";
import specificationService from "./services/specificationService";
import {
renderInput,
renderButton,
renderError,
renderGlossaryPicker,
} from "../../../components/common/formHelpers";
interface SpecificationsDetailsProps {
editMode?: boolean;
}
const SpecificationsDetails: React.FC<SpecificationsDetailsProps> = ({
editMode = false,
}) => {
const { organisationId, siteId, specificationId } = useParams<{
organisationId: string;
siteId: string;
specificationId?: string;
}>();
const { t } = useTranslation<typeof Namespaces.Common>();
const TemplateFillerRef = useRef<TemplateFillerHandle>(null);
const labelName = t("Name");
const labelPrintSpecification = t("PrintSpecification");
const labelSigmaId = t("SigmaId");
const labelApply = t("Save");
const labelSave = t("SaveAndClose");
const form = useForm({
loaded: false,
data: {
name: "",
sigmaId: null as bigint | null,
printSpecifications: [] as CustomFieldValue[],
formInstanceId: undefined,
},
errors: {},
redirect: "",
});
const [formTemplate, setFormTemplate] = useState<GeneralIdRef | undefined>(
undefined,
);
const [hasErrors, setHasErrors] = useState(false);
form.schema = {
name: Joi.string().required().max(450).label(labelName),
printSpecifications: Joi.optional(),
formInstanceId: Joi.optional(),
sigmaId: Joi.number().allow(null).label(labelSigmaId),
};
const isEditMode = () => editMode;
const loadFormTemplate = useCallback(
async (printSpecifications?: GeneralIdRef) => {
const { data } = form.state;
const printSpecArray =
(data.printSpecifications as CustomFieldValue[]) || [];
if (printSpecArray && printSpecArray.length > 0) {
if (
((printSpecArray[0] as CustomFieldValue).value as GeneralIdRef).id ===
BigInt(0)
) {
data.printSpecifications = undefined;
}
}
let template;
if (!printSpecArray || printSpecArray.length === 0) {
template = undefined;
} else {
template = await specificationService.GetTemplateForPrintSpec(
(printSpecArray[0] as CustomFieldValue).value as GeneralIdRef,
);
}
if (template) {
setFormTemplate(template);
form.setState({ loaded: true });
} else {
form.setState({ loaded: false });
}
},
[form],
);
const handleValidationChanged = useCallback(() => {
const templateFiller = TemplateFillerRef.current;
let templateErrors: boolean = false;
if (templateFiller) templateErrors = templateFiller.hasValidationErrors();
setHasErrors(templateErrors);
}, []);
useEffect(() => {
const loadData = async () => {
if (specificationId !== undefined) {
try {
const loadedData = await specificationService.GetSSpecification(
BigInt(specificationId),
);
if (loadedData) {
const newData = { ...form.state.data };
newData.name = loadedData.name;
newData.formInstanceId = loadedData.formInstanceId;
form.setState({ loaded: true, data: newData });
} else {
form.setState({ loaded: false });
}
} catch (ex: any) {
form.handleGeneralError(ex);
}
}
if (!editMode) {
form.setState({ loaded: true });
}
};
loadData();
}, [specificationId, editMode]); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
const { printSpecifications } = form.state.data;
const printSpecArray = (printSpecifications as CustomFieldValue[]) || [];
if (printSpecArray && printSpecArray.length > 0) {
loadFormTemplate(
(printSpecArray[0] as CustomFieldValue).value as GeneralIdRef,
);
}
}, [form.state.data.printSpecifications, loadFormTemplate, form]);
const doSubmit = async (buttonName: string) => {
try {
const { name, formInstanceId, sigmaId } = form.state.data;
const nameStr = typeof name === "string" ? name : "";
const sigmaIdValue =
sigmaId === null || sigmaId === undefined || sigmaId === ""
? null
: typeof sigmaId === "bigint"
? sigmaId
: BigInt(sigmaId as string | number);
const siteIdGeneralIdRef = MakeGeneralIdRef(
siteId ? BigInt(siteId) : undefined,
);
const templateFiller = TemplateFillerRef.current!;
if (isEditMode()) {
await templateFiller.Save();
const specificationIdGeneralIdRef = MakeGeneralIdRef(
specificationId ? BigInt(specificationId) : undefined,
);
const response = await specificationService.PutSpecification(
specificationIdGeneralIdRef,
siteIdGeneralIdRef,
nameStr,
formInstanceId as GeneralIdRef,
sigmaIdValue,
);
if (response) {
toast.info(t("SpecificationsEdited"));
}
} else {
const newFormInstanceId = await templateFiller.Save();
if (!newFormInstanceId) {
toast.error(t("FailedToSaveFormInstance"));
return;
}
const response = await specificationService.PostSpecification(
siteIdGeneralIdRef,
nameStr,
newFormInstanceId!,
sigmaIdValue,
);
if (response) {
toast.info(t("NewSpecificationsAdded"));
}
}
if (buttonName === "save") {
form.setState({
redirect: "/Specifications/" + organisationId + "/" + siteId,
});
}
} catch (ex: any) {
form.handleGeneralError(ex);
}
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
form.handleSubmit(e, doSubmit);
};
const { loaded, redirect } = form.state;
if (redirect && redirect !== "") return <Navigate to={redirect} />;
const mode = isEditMode() ? t("Edit") : t("Add");
return (
<Loading loaded={loaded}>
<h1>
{mode} {t("Specifications")}
</h1>
<form onSubmit={handleSubmit}>
{renderError("_general", form.state.errors)}
{renderInput(
"name",
labelName,
form.state.data,
form.state.errors,
InputType.text,
false,
"",
"",
0,
true,
undefined,
form.handleChange,
)}
{renderInput(
"sigmaId",
labelSigmaId,
form.state.data,
form.state.errors,
InputType.number,
false,
"",
"",
0,
false,
undefined,
form.handleChange,
)}
{!isEditMode() &&
renderGlossaryPicker(
true,
"printSpecifications",
labelPrintSpecification,
form.state.data,
form.state.errors,
1,
PrintSpecificationsGlossary,
form.handleGlossaryPickerChange,
)}
<TemplateFiller
templateId={formTemplate}
formInstanceId={
form.state.data.formInstanceId as GeneralIdRef | undefined
}
ref={TemplateFillerRef}
onValidationChanged={handleValidationChanged}
/>
<br />
{isEditMode() &&
renderButton(
labelApply,
form.state.errors,
"apply",
undefined,
undefined,
Object.keys(form.state.errors).length === 0 && !hasErrors,
undefined,
true,
)}
{renderButton(
labelSave,
form.state.errors,
"save",
undefined,
undefined,
Object.keys(form.state.errors).length === 0 && !hasErrors,
undefined,
true,
)}
</form>
</Loading>
);
};
export default SpecificationsDetails;