Skip to content

Commit

Permalink
Fix offcut create crash
Browse files Browse the repository at this point in the history
  • Loading branch information
floo51 committed May 3, 2024
1 parent 360cf9b commit a874454
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 167 deletions.
170 changes: 4 additions & 166 deletions src/app/admin/offcuts/Create.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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 (
<OffcutReferenceInput
fieldSource={fieldSource}
source={source}
materialId={materialId}
/>
);
};

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 (
<OffcutReferenceInputContainer>
<TextField
label="Référence"
value={referenceDigits}
inputProps={{
style: { textAlign: "left", paddingRight: 0 },
}}
InputProps={{
endAdornment: (
<Typography variant="caption">{referenceEnd()}</Typography>
),
}}
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 ? (
<InputHelperText
touched={isTouched || isSubmitted}
error={error?.message}
/>
) : (
""
)
}
/>
</OffcutReferenceInputContainer>
);
};

export const Fields = () => {
return (
Expand All @@ -231,7 +69,7 @@ export const Fields = () => {
/>
</ReferenceInput>
<MaterialInput source="material" label="Matériau" validate={required()} />
<OffcutReferenceInputWrapper source="reference" />
<OffcutReferenceInput source="reference" />
<RichTextInput
source="description"
label="Cartel"
Expand Down
189 changes: 189 additions & 0 deletions src/app/admin/offcuts/OffcutReferenceInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import styled from "@emotion/styled";
import { TextField, Typography } from "@mui/material";
import { useEffect } from "react";
import {
InputHelperText,
useDataProvider, useInput,
useRecordContext
} from "react-admin";
import { useWatch } from "react-hook-form";

const OffcutReferenceInputContainer = styled.div`
display: flex;
flex-direction: column;
margin-bottom: 24px;
width: 100%;
.MuiFormHelperText-root {
width: 100%;
white-space: nowrap;
}
`;

const OffcutReferenceInput = ({
fieldSource,
source,
materialId,
}: {
fieldSource: string;
source: string;
materialId: string;
}) => {
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 (
<OffcutReferenceInputContainer>
<TextField
label="Référence"
value={
field.value.includes("-")
? field.value.split("-")[0]
: field.value.substring(0, 3)
}
inputProps={{
style: { textAlign: "left", paddingRight: 0 },
}}
InputProps={{
endAdornment: (
<Typography variant="caption">
{field.value?.includes("-")
? field.value.substring(field.value.indexOf("-"))
: field.value.substring(3)}
</Typography>
),
}}
onChange={handleChange}
variant="filled"
sx={{
width: 120,
}}
error={(isTouched || isSubmitted) && invalid}
helperText={
(isTouched || isSubmitted) && invalid ? (
<InputHelperText
touched={isTouched || isSubmitted}
error={error?.message}
/>
) : (
""
)
}
/>
</OffcutReferenceInputContainer>
);
};

const OffcutReferenceInputWrapper = ({
source: fieldSource,
}: {
source: string;
}) => {
const [source, materialId] = useWatch<{ source: string; material: string }>({
name: ["source", "material"],
});

if (!source || !materialId) return null;

return (
<OffcutReferenceInput
fieldSource={fieldSource}
source={source}
materialId={materialId}
/>
);
};

export default OffcutReferenceInputWrapper;
Loading

0 comments on commit a874454

Please sign in to comment.