ui-nyla/src/components/UiComponents/Button/CreateButton/CreateButton.tsx
2026-04-11 22:23:35 +02:00

192 lines
5.7 KiB
TypeScript

import React, { useState, useMemo } from 'react';
import { CreateButtonProps } from '../ButtonTypes';
import Button from '../Button';
import { Popup } from '../../Popup';
import { FormGeneratorForm, AttributeDefinition } from '../../../FormGenerator/FormGeneratorForm';
import { useLanguage } from '../../../../providers/language/LanguageContext';
const CreateButton: React.FC<CreateButtonProps> = ({
onCreate,
fields,
popupTitle = 'Neues Element erstellen',
popupSize = 'medium',
disabled = false,
loading = false,
className = '',
children,
icon,
iconPosition = 'left',
variant = 'primary',
size = 'md',
onSuccess,
onError,
...props
}) => {
const { t } = useLanguage();
const [isCreating, setIsCreating] = useState(false);
const [isPopupOpen, setIsPopupOpen] = useState(false);
// Convert CreateButtonFieldConfig to AttributeDefinition format
const attributes: AttributeDefinition[] = useMemo(() => {
return fields.map(field => {
// Convert options to AttributeOption[] format
let options: AttributeDefinition['options'] = undefined;
if (field.options) {
// If options is an array of strings, convert to AttributeOption format
if (Array.isArray(field.options)) {
options = field.options.map((opt: any) => {
if (typeof opt === 'string') {
return { value: opt, label: opt };
}
// Already in {value, label} format
return opt;
});
}
} else if (field.optionsReference) {
// Use optionsReference as string (will be fetched from API)
options = field.optionsReference;
}
// Map field types to FormGeneratorForm attribute types
let attributeType: AttributeDefinition['type'] = 'text';
if (field.type === 'boolean') {
attributeType = 'checkbox';
} else if (field.type === 'enum') {
attributeType = 'select';
} else if (field.type === 'multiselect') {
attributeType = 'multiselect';
} else if (field.type === 'email') {
attributeType = 'email';
} else if (field.type === 'date') {
attributeType = 'date';
} else if (field.type === 'textarea') {
attributeType = 'textarea';
} else if (field.type === 'readonly') {
attributeType = 'readonly';
} else if (field.type === 'string') {
// Check if it's a password field by key name
attributeType = field.key.toLowerCase().includes('password') ? 'password' : 'text';
}
return {
name: field.key,
label: typeof field.label === 'string' ? field.label : String(field.label),
type: attributeType,
required: field.required || false,
placeholder: field.placeholder,
default: field.defaultValue,
editable: true,
visible: true,
minRows: field.minRows,
maxRows: field.maxRows,
validation: field.validator,
options: options
};
});
}, [fields]);
// Initialize form data with default values
const initialFormData = useMemo(() => {
const data: any = {};
fields.forEach(field => {
if (field.type === 'multiselect') {
// Multiselect fields should default to empty array
data[field.key] = field.defaultValue || [];
} else if (field.type === 'boolean') {
// Boolean fields should default to false
data[field.key] = field.defaultValue !== undefined ? field.defaultValue : false;
} else {
// Other fields default to empty string or provided default
data[field.key] = field.defaultValue !== undefined ? field.defaultValue : '';
}
});
return data;
}, [fields]);
const handleButtonClick = () => {
if (!disabled && !loading && !isCreating) {
setIsPopupOpen(true);
}
};
const handleSave = async (updatedData: any) => {
setIsCreating(true);
try {
const result = await onCreate(updatedData);
if (result?.success !== false) {
// Success
setIsPopupOpen(false);
if (onSuccess) {
onSuccess(result);
}
} else {
// Handle error
if (onError) {
onError(result?.error || 'Creation failed');
}
}
} catch (error: any) {
console.error('Creation failed:', error);
if (onError) {
onError(error.message || t('Erstellung fehlgeschlagen'));
}
} finally {
setIsCreating(false);
}
};
const handleCancel = () => {
setIsPopupOpen(false);
};
const isDisabled = disabled || loading || isCreating;
const resolvedPopupTitle = popupTitle;
const resolvedAttributes = attributes;
return (
<>
<Button
{...props}
variant={variant}
size={size}
disabled={isDisabled}
loading={false}
className={`createButton ${className}`}
onClick={handleButtonClick}
icon={isCreating ? undefined : icon}
iconPosition={iconPosition}
>
{isCreating && (
<div className="spinnerIcon" style={{ marginRight: '8px' }} />
)}
{children || (isCreating ? t('Erstellen...') : t('Erstellen'))}
</Button>
{/* Create Popup */}
<Popup
isOpen={isPopupOpen}
title={resolvedPopupTitle}
onClose={handleCancel}
size={popupSize}
closable={!isCreating}
>
<FormGeneratorForm
attributes={resolvedAttributes}
data={initialFormData}
mode="create"
onSubmit={handleSave}
onCancel={handleCancel}
submitButtonText={t('Erstellen')}
cancelButtonText={t('Abbrechen')}
/>
</Popup>
</>
);
};
export default CreateButton;