Improve the frontend

This commit is contained in:
Urtzi Alfaro
2025-10-21 19:50:07 +02:00
parent 05da20357d
commit 8d30172483
105 changed files with 14699 additions and 4630 deletions

View File

@@ -63,6 +63,7 @@ const ListFieldRenderer: React.FC<ListFieldRendererProps> = ({ field, value, onC
const renderItemField = (item: any, itemIndex: number, fieldConfig: any) => {
const fieldValue = item[fieldConfig.name] ?? '';
const isFieldDisabled = fieldConfig.disabled ?? false;
switch (fieldConfig.type) {
case 'select':
@@ -70,10 +71,11 @@ const ListFieldRenderer: React.FC<ListFieldRendererProps> = ({ field, value, onC
<select
value={fieldValue}
onChange={(e) => updateItem(itemIndex, fieldConfig.name, e.target.value)}
className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm"
className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm disabled:opacity-50 disabled:cursor-not-allowed"
required={fieldConfig.required}
disabled={isFieldDisabled}
>
<option value="">Seleccionar...</option>
<option value="">{fieldConfig.placeholder || 'Seleccionar...'}</option>
{fieldConfig.options?.map((option: any) => (
<option key={option.value} value={option.value}>{option.label}</option>
))}
@@ -87,11 +89,12 @@ const ListFieldRenderer: React.FC<ListFieldRendererProps> = ({ field, value, onC
type="number"
value={fieldValue}
onChange={(e) => updateItem(itemIndex, fieldConfig.name, parseFloat(e.target.value) || 0)}
className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm"
className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm disabled:opacity-50 disabled:cursor-not-allowed"
min="0"
step={fieldConfig.type === 'currency' ? '0.01' : '0.1'}
placeholder={fieldConfig.placeholder}
required={fieldConfig.required}
disabled={isFieldDisabled}
/>
);
@@ -101,14 +104,17 @@ const ListFieldRenderer: React.FC<ListFieldRendererProps> = ({ field, value, onC
type="text"
value={fieldValue}
onChange={(e) => updateItem(itemIndex, fieldConfig.name, e.target.value)}
className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm"
className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] text-sm disabled:opacity-50 disabled:cursor-not-allowed"
placeholder={fieldConfig.placeholder}
required={fieldConfig.required}
disabled={isFieldDisabled}
/>
);
}
};
const isDisabled = listConfig.disabled ?? false;
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
@@ -116,7 +122,12 @@ const ListFieldRenderer: React.FC<ListFieldRendererProps> = ({ field, value, onC
<button
type="button"
onClick={addItem}
className="flex items-center gap-2 px-3 py-1.5 text-sm bg-[var(--color-primary)] text-white rounded-md hover:bg-[var(--color-primary)]/90 transition-colors"
disabled={isDisabled}
className={`flex items-center gap-2 px-3 py-1.5 text-sm rounded-md transition-colors ${
isDisabled
? 'bg-gray-300 text-gray-500 cursor-not-allowed opacity-50'
: 'bg-[var(--color-primary)] text-white hover:bg-[var(--color-primary)]/90'
}`}
>
<Plus className="w-4 h-4" />
{listConfig.addButtonLabel || t('common:modals.actions.add', 'Agregar')}
@@ -129,7 +140,7 @@ const ListFieldRenderer: React.FC<ListFieldRendererProps> = ({ field, value, onC
<Plus className="w-full h-full" />
</div>
<p>{listConfig.emptyStateText || 'No hay elementos agregados'}</p>
<p className="text-sm">Haz clic en "{listConfig.addButtonLabel || 'Agregar'}" para comenzar</p>
{!isDisabled && <p className="text-sm">Haz clic en "{listConfig.addButtonLabel || 'Agregar'}" para comenzar</p>}
</div>
) : (
<div className="space-y-3 max-h-96 overflow-y-auto">
@@ -204,12 +215,14 @@ export interface AddModalField {
options?: Array<{label: string; value: string | number}>;
defaultValue?: any;
validation?: (value: any) => string | null;
disabled?: boolean;
}>;
addButtonLabel?: string;
removeButtonLabel?: string;
emptyStateText?: string;
showSubtotals?: boolean; // For calculating item totals
subtotalFields?: { quantity: string; price: string }; // Field names for calculation
disabled?: boolean; // Disable adding new items
};
}
@@ -686,8 +699,7 @@ export const AddModal: React.FC<AddModalProps> = ({
disabled={loading}
className="min-w-[80px]"
>
<X className="w-4 h-4 mr-2" />
{t('common:modals.actions.cancel', 'Cancelar')}
{t('common:modals.actions.cancel', 'Cancelar')}
</Button>
<Button
variant="primary"
@@ -698,10 +710,7 @@ export const AddModal: React.FC<AddModalProps> = ({
{loading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-current"></div>
) : (
<>
<Save className="w-4 h-4 mr-2" />
{t('common:modals.actions.save', 'Guardar')}
</>
t('common:modals.actions.save', 'Guardar')
)}
</Button>
</div>