ldc-groupe/resources/ts/back/Components/DynamicPages/DynamicInputs.tsx

349 lines
15 KiB
TypeScript

// * Packages
import { usePage } from "@inertiajs/react";
// * Other
import SimpleString from "@/back/Components/Inputs/SimpleString";
import SimpleNumber from "@/back/Components/Inputs/SimpleNumber";
import SimpleSwitch from "@/back/Components/Inputs/SimpleSwitch";
import SimpleWysiwyg from "@/back/Components/Inputs/SimpleWysiwyg";
import CompleteInputFile from "@/back/Components/Inputs/CompleteInputFile";
import DynamicList from "@/back/Components/DynamicPages/DynamicList";
import SimpleTextarea from "@/back/Components/Inputs/SimpleTextarea";
import SimpleDatePicker from "@/back/Components/Inputs/SimpleDatePicker";
import SimpleColorPicker from "@/back/Components/Inputs/SimpleColorPicker";
import SimpleYoutubeId from "@/back/Components/Inputs/SimpleYoutubeId";
import SimpleVimeoId from "@/back/Components/Inputs/SimpleVimeoId";
import {
ConfigField,
DynamicFieldTypes,
DynamicInternalField,
} from "@/back/types/global";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import {
extractLaravelValidationValue,
extractMinMaxFromValidation,
extractRequiredValidation,
} from "@/hooks/use-laravel-validation";
type DynamicInputsProps = {
name: string;
config: ConfigField[];
content: DynamicInternalField | null;
isChildren?: boolean;
setData: (
name: string,
value: string | boolean | File | object | null,
) => void;
reset: (name?: string) => void;
parentErrors?: Record<string, string> | null;
};
// Allows to get specific input from enum value.
export default function DynamicInputs({
name,
config,
content = null,
isChildren = false,
setData,
reset,
parentErrors,
}: DynamicInputsProps) {
// Enums.
const enumDynamicFieldTypes = usePage().props
.enumDynamicFieldTypes as DynamicFieldTypes;
// Translations.
const transAssociateTo = useTrans("back.form_associate_to");
const transUnsupportedType = useTrans("back.unsupported_type");
/**
* Get a translation for a specific field label.
* Need to recreate useTrans hook to avoid hook error.
* @param fieldLabel string
* @returns string
*/
const getTrans = (fieldLabel: string): string => {
return str(
`${transAssociateTo.split("|")[0].replace(":attribute", fieldLabel)}`,
)
.ucFirst()
.value();
};
return (
<div className="grid grid-cols-1 md:grid-cols-2 items-start gap-4">
{/* Loop on all config elements. */}
{Object.entries(config).map(([id, field]) => {
// Get the enum value from the element type value.
const typeEnum = Object.values(enumDynamicFieldTypes).find(
(def) => def.value === field.type,
);
// Set the name of the current field.
const fieldName = `${name}.${field.key}`;
// Set the content value from the config key.
const fieldValue =
content?.[field.key as keyof typeof content] ?? "";
switch (field.type) {
// String input.
case enumDynamicFieldTypes.string.value:
return (
<SimpleString
key={id}
name={fieldName}
label={getTrans(field.label)}
required={extractRequiredValidation(
field.validation,
)}
value={String(fieldValue)}
setData={setData}
parentErrors={parentErrors}
/>
);
// Textarea input.
case enumDynamicFieldTypes.textarea.value:
return (
<SimpleTextarea
key={id}
name={fieldName}
label={getTrans(field.label)}
required={extractRequiredValidation(
field.validation,
)}
value={String(fieldValue)}
setData={setData}
parentErrors={parentErrors}
/>
);
// Wysiwyg input.
case enumDynamicFieldTypes.wysiwyg.value:
return (
<div key={id} className="col-span-1 md:col-span-2">
<SimpleWysiwyg
name={fieldName}
model="DynamicPage"
required={extractRequiredValidation(
field.validation,
)}
label={getTrans(field.label)}
value={String(fieldValue)}
setData={setData}
parentErrors={parentErrors}
/>
</div>
);
// Numbers input.
case enumDynamicFieldTypes.number.value:
return (
<SimpleNumber
key={id}
name={fieldName}
label={getTrans(field.label)}
limits={extractMinMaxFromValidation(
field.validation,
)}
required={extractRequiredValidation(
field.validation,
)}
value={Number(fieldValue)}
setData={setData}
/>
);
// Switch input.
case enumDynamicFieldTypes.boolean.value:
return (
<div key={id} className="grid grid-cols-1 gap-1.5">
<SimpleSwitch
label={`${getTrans(field.label)} ${extractRequiredValidation(field.validation) ? " *" : ""}`}
name={fieldName}
checked={Boolean(fieldValue)}
setData={setData}
/>
</div>
);
// Url input.
case enumDynamicFieldTypes.url.value:
return (
<SimpleString
key={id}
name={fieldName}
label={getTrans(field.label)}
type="url"
placeholder="ex: https://..."
required={extractRequiredValidation(
field.validation,
)}
value={String(fieldValue)}
setData={setData}
/>
);
// Image input.
case enumDynamicFieldTypes.image.value:
return (
<CompleteInputFile
key={id}
fileName="fichier"
name={fieldName}
label={getTrans(field.label)}
setData={setData}
reset={reset}
value={fieldValue as string | File | null}
required={extractRequiredValidation(
field.validation,
)}
maxFileSize={extractLaravelValidationValue(
field.validation,
"max",
)}
allowedFormats={extractLaravelValidationValue(
field.validation,
"mimes",
)}
validationRules={{
width: extractLaravelValidationValue(
field.validation,
"dimensions",
"width",
),
height: extractLaravelValidationValue(
field.validation,
"dimensions",
"height",
),
}}
/>
);
// Email input.
case enumDynamicFieldTypes.email.value:
return (
<SimpleString
key={id}
name={fieldName}
label={getTrans(field.label)}
type="email"
placeholder="ex: john.doe@ldc.fr"
required={extractRequiredValidation(
field.validation,
)}
value={String(fieldValue)}
setData={setData}
/>
);
// List input.
case enumDynamicFieldTypes.list.value:
return (
<DynamicList
key={id}
name={fieldName}
parentName={name}
content={content}
field={field}
value={
Array.isArray(fieldValue) ? fieldValue : []
}
enumLabel={enumDynamicFieldTypes.list.label}
setData={setData}
reset={reset}
isChildren={isChildren}
/>
);
// File input.
case enumDynamicFieldTypes.file.value:
return (
<CompleteInputFile
key={id}
name={fieldName}
label={str(
useTrans("back.form_associate_to", {
params: {
attribute: useTrans(
"validation.custom.file",
),
},
choice: 1,
}),
)
.ucFirst()
.value()}
setData={setData}
reset={reset}
value={fieldValue as string | File | null}
required={extractRequiredValidation(
field.validation,
)}
maxFileSize={extractLaravelValidationValue(
field.validation,
"max",
)}
allowedFormats={extractLaravelValidationValue(
field.validation,
"mimes",
)}
inputType={enumDynamicFieldTypes.file.value}
/>
);
// VimeoId input
case enumDynamicFieldTypes.vimeoid.value:
return (
<SimpleVimeoId
name={fieldName}
setData={setData}
value={String(fieldValue)}
required={extractRequiredValidation(
field.validation,
)}
/>
);
// YoutubeId input
case enumDynamicFieldTypes.youtubeid.value:
return (
<SimpleYoutubeId
name={fieldName}
setData={setData}
value={String(fieldValue)}
required={extractRequiredValidation(
field.validation,
)}
/>
);
// Date picker.
case enumDynamicFieldTypes.date.value:
return (
<SimpleDatePicker
name={fieldName}
setData={setData}
date={fieldValue as Date}
hasTime={true}
label={getTrans(field.label)}
/>
);
// Color picker.
case enumDynamicFieldTypes.color.value:
return (
<SimpleColorPicker
name={fieldName}
setData={setData}
value={String(fieldValue)}
label={getTrans(field.label)}
required={extractRequiredValidation(
field.validation,
)}
/>
);
default:
return (
<p
key={id}
className="text-muted-foreground text-sm"
>
{transUnsupportedType}{" "}
{typeEnum?.label ?? field.type}
</p>
);
}
})}
</div>
);
}