ldc-laravel-base-project/resources/ts/back/Components/DynamicPages/DynamicInputs.tsx
2026-06-04 12:36:36 +02:00

351 lines
12 KiB
TypeScript

// * Packages
import { usePage } from "@inertiajs/react";
import { Fragment } from "react/jsx-runtime";
// * 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/Wysiwyg/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 StaticRouteSelect from "@/back/Components/Inputs/StaticRouteSelect";
import DynamicWrapperModelSelect from "@/back/Components/DynamicPages/DynamicWrapperModelSelect";
import DynamicInputRegistry from "@/back/Components/DynamicPages/DynamicInputRegistry";
import {
ConfigField,
DynamicFieldType,
DynamicInternalField,
} from "@/back/types/dynamic-pages";
import str from "@/hooks/use-string";
import useTrans from "@/hooks/use-translations";
import {
extractLaravelValidationValue,
extractMinMaxFromValidation,
extractRequiredValidation,
} from "@/hooks/use-laravel-validation";
/* eslint-disable no-unused-vars */
type DynamicInputsProps = {
name: string;
config: ConfigField[];
content: DynamicInternalField | null;
isChildren?: boolean;
setData: (
name: string,
value: string | number | boolean | File | object | null,
) => void;
reset: (name?: string) => void;
parentErrors?: Record<string, string> | null;
};
/* eslint-enable no-unused-vars */
// 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 DynamicFieldType;
// Translations.
const transAssociateTo = useTrans("uwil-backend::back.form_associate_to");
const transUnsupportedType = useTrans(
"uwil-dynamic-pages::trans.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}
tableName="dynamic_pages"
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={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",
)}
inputType="file"
/>
);
// 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
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)}
/>
);
// Model select.
case enumDynamicFieldTypes.model.value:
return (
<DynamicWrapperModelSelect
field={field}
fieldName={fieldName}
fieldValue={fieldValue}
setData={setData}
getTrans={getTrans}
/>
);
// Static route select.
case enumDynamicFieldTypes.staticroute.value:
return (
<StaticRouteSelect
name={fieldName}
label={getTrans(field.label)}
selected={fieldValue as number}
setData={setData}
required={extractRequiredValidation(field.validation)}
/>
);
default: {
// Check in custom types.
const customInput = DynamicInputRegistry.get(
typeEnum?.name ?? "type",
fieldName,
fieldValue,
field,
setData,
parentErrors,
);
if (customInput) {
return <Fragment key={id}>{customInput}</Fragment>;
}
// Show message if no type is matching.
return (
<p key={id} className="text-muted-foreground text-sm">
{transUnsupportedType} {typeEnum?.label ?? field.type}
</p>
);
}
}
})}
</div>
);
}