From a874454aa9758544708e0e59cdfef717adb71cb6 Mon Sep 17 00:00:00 2001 From: Florian Ferbach Date: Fri, 3 May 2024 16:56:08 +0200 Subject: [PATCH] Fix offcut create crash --- src/app/admin/offcuts/Create.tsx | 170 +--------------- .../admin/offcuts/OffcutReferenceInput.tsx | 189 ++++++++++++++++++ src/app/api/offcuts/getOffcuts.ts | 2 +- 3 files changed, 194 insertions(+), 167 deletions(-) create mode 100644 src/app/admin/offcuts/OffcutReferenceInput.tsx diff --git a/src/app/admin/offcuts/Create.tsx b/src/app/admin/offcuts/Create.tsx index e782d0e..23e3d23 100644 --- a/src/app/admin/offcuts/Create.tsx +++ b/src/app/admin/offcuts/Create.tsx @@ -1,28 +1,21 @@ import styled from "@emotion/styled"; -import { TextField, Typography } from "@mui/material"; import { RichTextInput } from "ra-input-rich-text"; -import { useCallback, useEffect, useState } from "react"; import { AutocompleteInput, CheckboxGroupInput, Create, ImageField, - ImageInput, - InputHelperText, - RadioButtonGroupInput, + ImageInput, RadioButtonGroupInput, ReferenceArrayInput, ReferenceInput, SimpleForm, TextInput, Validator, - required, - useGetList, - useGetOne, - useInput, - useRecordContext, + required } from "react-admin"; import { useWatch } from "react-hook-form"; import RemoveChoiceButton from "./RemoveChoiceButton"; +import OffcutReferenceInput from "./OffcutReferenceInput"; export const MaterialInput = ({ source, @@ -56,167 +49,12 @@ export const MaterialInput = ({ ); }; -const OffcutReferenceInputContainer = styled.div` - display: flex; - flex-direction: column; - margin-bottom: 24px; - width: 100%; - - .MuiFormHelperText-root { - width: 100%; - white-space: nowrap; - } -`; - const BrandPolicyContainer = styled.div` display: flex; align-items: center; width: 100%; `; -const OffcutReferenceInputWrapper = ({ - source: fieldSource, -}: { - source: string; -}) => { - const [source, materialId] = useWatch<{ source: string; material: string }>({ - name: ["source", "material"], - }); - - if (!source || !materialId) return null; - - return ( - - ); -}; - -const OffcutReferenceInput = ({ - fieldSource, - source, - materialId, -}: { - fieldSource: string; - source: string; - materialId: string; -}) => { - const { data: material } = useGetOne("materials", { id: materialId }); - const record = useRecordContext(); - const { - field, - fieldState: { isTouched, invalid, error }, - formState: { isSubmitted }, - } = useInput({ - source: fieldSource, - defaultValue: record ? record[fieldSource] : "", - validate: (value) => { - if (sameNameOffcut && sameNameOffcut[0]) { - return "Une chute avec cette référence existe déjà"; - } - }, - }); - - const referenceEnd = useCallback(() => { - if (!source || !material) return ""; - return `-${material?.value - .replaceAll(/\s/g, "") - .substring(0, 3) - .toUpperCase()}-${source - .replaceAll(/\s/g, "") - .substring(0, 3) - .toUpperCase()}`; - }, [source, material]); - - const { data: offcuts } = useGetList("offcuts", { - pagination: { - page: 1, - perPage: 1, - }, - sort: { - field: "reference", - order: "DESC", - }, - filter: { - referenceEnd: referenceEnd(), - }, - }); - - const { data: sameNameOffcut } = useGetList("offcuts", { - pagination: { - page: 1, - perPage: 1, - }, - sort: { - field: "reference", - order: "DESC", - }, - filter: { - reference: field.value, - }, - }); - - const nextReference = useCallback(() => { - if (!offcuts || !offcuts[0]) return `001`; - const nextNumber = parseInt(offcuts[0].reference.split("-")[0]) + 1; - if (isNaN(nextNumber)) return `001`; - return `${nextNumber.toString().padStart(3, "0")}`; - }, [offcuts]); - - const [referenceDigits, setReferenceDigits] = useState( - field.value.split("-")[2] || nextReference - ); - - useEffect(() => { - setReferenceDigits(nextReference()); - }, [nextReference]); - - const handleOnBlur = () => { - const value = parseInt(referenceDigits).toString().padStart(3, "0"); - setReferenceDigits(value); - }; - - return ( - - {referenceEnd()} - ), - }} - onBlur={handleOnBlur} - onChange={(event) => { - const value = parseInt(event.target.value); - if (value >= 0 && value <= 999) { - setReferenceDigits(value.toString()); - } - }} - variant="filled" - sx={{ - width: 120, - }} - error={(isTouched || isSubmitted) && invalid} - helperText={ - (isTouched || isSubmitted) && invalid ? ( - - ) : ( - "" - ) - } - /> - - ); -}; export const Fields = () => { return ( @@ -231,7 +69,7 @@ export const Fields = () => { /> - + { + const dataProvider = useDataProvider(); + + const record = useRecordContext(); + + const { + field, + fieldState: { isTouched, invalid, error }, + formState: { isSubmitted }, + } = useInput({ + source: fieldSource, + defaultValue: record ? record[fieldSource] : "", + validate: async (value) => { + const sameNameOffcut = await dataProvider.getList("offcuts", { + pagination: { page: 1, perPage: 1 }, + sort: { field: "reference", order: "DESC" }, + filter: { reference: value }, + }); + + if (sameNameOffcut && sameNameOffcut.data && sameNameOffcut.data.length) { + return "Une chute avec cette référence existe déjà"; + } + }, + }); + + useEffect(() => { + (async () => { + if (!source || !materialId) { + return; + } + const material = await dataProvider.getOne("materials", { + id: materialId, + }); + if (!material.data) { + return; + } + const referenceEnd = `-${material.data.value + .replaceAll(/\s/g, "") + .substring(0, 3) + .toUpperCase()}-${source + .replaceAll(/\s/g, "") + .substring(0, 3) + .toUpperCase()}`; + + const currentNumber = field.value.includes("-") + ? field.value.split("-")[0] + : field.value.substring(0, 3); + + if (currentNumber.length) { + field.onChange(`${currentNumber}${referenceEnd}`); + return; + } + + const offcuts = await dataProvider.getList("offcuts", { + pagination: { + page: 1, + perPage: 1, + }, + sort: { + field: "reference", + order: "DESC", + }, + filter: { + referenceEnd, + }, + }); + + if (!offcuts.data || !offcuts.data.length) { + field.onChange(`001${referenceEnd}`); + return; + } + + const nextNumber = parseInt(offcuts.data[0].reference.split("-")[0]) + 1; + if (isNaN(nextNumber)) { + field.onChange(`001${referenceEnd}`); + return; + } + field.onChange( + `${nextNumber.toString().padStart(3, "0")}${referenceEnd}` + ); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [source, materialId]); + + const handleChange = async (event: any) => { + const value = event.target.value; + if (value.length > 3) { + return; + } + const suffix = field.value.includes("-") + ? field.value.substring(field.value.indexOf("-")) + : field.value.substring(3); + + field.onChange(`${value.toString()}${suffix}`); + }; + + return ( + + + {field.value?.includes("-") + ? field.value.substring(field.value.indexOf("-")) + : field.value.substring(3)} + + ), + }} + onChange={handleChange} + variant="filled" + sx={{ + width: 120, + }} + error={(isTouched || isSubmitted) && invalid} + helperText={ + (isTouched || isSubmitted) && invalid ? ( + + ) : ( + "" + ) + } + /> + + ); +}; + +const OffcutReferenceInputWrapper = ({ + source: fieldSource, +}: { + source: string; +}) => { + const [source, materialId] = useWatch<{ source: string; material: string }>({ + name: ["source", "material"], + }); + + if (!source || !materialId) return null; + + return ( + + ); +}; + +export default OffcutReferenceInputWrapper; diff --git a/src/app/api/offcuts/getOffcuts.ts b/src/app/api/offcuts/getOffcuts.ts index b0f8d04..9142f65 100644 --- a/src/app/api/offcuts/getOffcuts.ts +++ b/src/app/api/offcuts/getOffcuts.ts @@ -28,7 +28,7 @@ const getOffcuts = async (request: NextRequest, audience?: string[]) => { filters = { ...filters, _id: { $in: ids } }; } - if(request.nextUrl.searchParams.has("reference")) { + if (request.nextUrl.searchParams.has("reference")) { const reference = request.nextUrl.searchParams.get("reference"); filters = { ...filters, reference }; }