first commit
This commit is contained in:
		
							
								
								
									
										148
									
								
								resources/views/components/form/checkbox-group.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								resources/views/components/form/checkbox-group.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,148 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelos para Livewire
 | 
			
		||||
    'checkboxModel' => '',
 | 
			
		||||
    'textModel' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y clases de la etiqueta
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases generales
 | 
			
		||||
    'align' => 'start',
 | 
			
		||||
    'size' => '', // Tamaño del input (sm, lg)
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Elementos opcionales antes/después del input
 | 
			
		||||
    'prefix' => null,
 | 
			
		||||
    'suffix' => null,
 | 
			
		||||
 | 
			
		||||
    // Íconos dentro del input
 | 
			
		||||
    'icon' => null, // Ícono fijo
 | 
			
		||||
    'clickableIcon' => null, // Ícono con botón
 | 
			
		||||
 | 
			
		||||
    // Configuración del checkbox
 | 
			
		||||
    'checked' => false,
 | 
			
		||||
    'disabled' => false,
 | 
			
		||||
 | 
			
		||||
    // Configuración del input de texto
 | 
			
		||||
    'disableOnOffCheckbox' => true, // Deshabilita input hasta que el checkbox esté activo
 | 
			
		||||
    'focusOnCheck' => true, // Hace foco en el input al activar el checkbox
 | 
			
		||||
 | 
			
		||||
    // Texto de ayuda
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    // Atributos adicionales para el input de texto
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // **Generación de Name, ID y Model**
 | 
			
		||||
    $livewireCheckbox = $checkboxModel ? "wire:model=$checkboxModel" : '';
 | 
			
		||||
    $livewireText = $textModel ? "wire:model=$textModel" : '';
 | 
			
		||||
 | 
			
		||||
    $nameCheckbox = $checkboxModel;
 | 
			
		||||
    $nameText = $attributes->get('name', $textModel);
 | 
			
		||||
 | 
			
		||||
    $checkboxId = $attributes->get('id', 'chk_' . $uid);
 | 
			
		||||
    $textInputId = 'txt_' . $uid;
 | 
			
		||||
 | 
			
		||||
    // **Placeholder del input de texto**
 | 
			
		||||
    $placeholder = $attributes->get('placeholder', 'Ingrese información');
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $sizeClass = match ($size) {
 | 
			
		||||
        'sm' => 'form-control-sm',
 | 
			
		||||
        'lg' => 'form-control-lg',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $fullClass = trim("form-control $sizeClass");
 | 
			
		||||
 | 
			
		||||
    // **Fusionar atributos del input de texto**
 | 
			
		||||
    $inputAttributes = $attributes->merge([
 | 
			
		||||
        'id' => $textInputId,
 | 
			
		||||
        'name' => $nameText,
 | 
			
		||||
        'placeholder' => $placeholder,
 | 
			
		||||
    ])->class($fullClass);
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
{{-- ============================ CHECKBOX CON INPUT GROUP ============================ --}}
 | 
			
		||||
<div class="mb-4 {{ $parentClass }}">
 | 
			
		||||
    @if ($label)
 | 
			
		||||
        <label for="{{ $checkboxId }}" class="{{ $labelClass }}">{{ $label }}</label>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    <div class="input-group">
 | 
			
		||||
        {{-- Checkbox dentro del input-group-text --}}
 | 
			
		||||
        <div class="input-group-text">
 | 
			
		||||
            <input
 | 
			
		||||
                id="{{ $checkboxId }}"
 | 
			
		||||
                name="{{ $nameCheckbox }}"
 | 
			
		||||
                type="checkbox"
 | 
			
		||||
                {{ $livewireCheckbox }}
 | 
			
		||||
                {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
                class="form-check-input mt-0"
 | 
			
		||||
                onchange="toggleInputState('{{ $checkboxId }}', '{{ $textInputId }}', {{ $focusOnCheck ? 'true' : 'false' }}, {{ $disableOnOffCheckbox ? 'true' : 'false' }})"
 | 
			
		||||
            >
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {{-- Prefijo opcional --}}
 | 
			
		||||
        @isset($prefix)
 | 
			
		||||
            <span class="input-group-text">{{ $prefix }}</span>
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        {{-- Ícono fijo opcional --}}
 | 
			
		||||
        @isset($icon)
 | 
			
		||||
            <span class="input-group-text"><i class="{{ $icon }}"></i></span>
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        {{-- Input de texto dentro del mismo grupo --}}
 | 
			
		||||
        <input
 | 
			
		||||
            {{ $livewireText }}
 | 
			
		||||
            {!! $inputAttributes !!}
 | 
			
		||||
            @if ($disableOnOffCheckbox) disabled @endif
 | 
			
		||||
            aria-label="Text input with checkbox"
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
        {{-- Sufijo opcional --}}
 | 
			
		||||
        @isset($suffix)
 | 
			
		||||
            <span class="input-group-text">{{ $suffix }}</span>
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        {{-- Ícono clickeable opcional --}}
 | 
			
		||||
        @isset($clickableIcon)
 | 
			
		||||
            <button type="button" class="input-group-text cursor-pointer">
 | 
			
		||||
                <i class="{{ $clickableIcon }}"></i>
 | 
			
		||||
            </button>
 | 
			
		||||
        @endisset
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {{-- Texto de ayuda opcional --}}
 | 
			
		||||
    @if ($helperText)
 | 
			
		||||
        <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{{-- ============================ JAVASCRIPT PURO ============================ --}}
 | 
			
		||||
<script>
 | 
			
		||||
    function toggleInputState(checkboxId, inputId, focusOnCheck, disableOnOffCheckbox) {
 | 
			
		||||
        let checkbox = document.getElementById(checkboxId);
 | 
			
		||||
        let textInput = document.getElementById(inputId);
 | 
			
		||||
 | 
			
		||||
        if (!checkbox || !textInput) return;
 | 
			
		||||
 | 
			
		||||
        // Deshabilitar o habilitar el input de texto
 | 
			
		||||
        if (disableOnOffCheckbox) {
 | 
			
		||||
            textInput.disabled = !checkbox.checked;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Enfocar automáticamente el input si está habilitado
 | 
			
		||||
        if (focusOnCheck && checkbox.checked) {
 | 
			
		||||
            textInput.focus();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										133
									
								
								resources/views/components/form/checkbox.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								resources/views/components/form/checkbox.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,133 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelo de Livewire (si aplica)
 | 
			
		||||
    'model' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y clases de la etiqueta
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases generales
 | 
			
		||||
    'align' => 'start',
 | 
			
		||||
    'size' => 'md', // Tamaño del checkbox/switch: sm, md, lg
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Estilos del checkbox
 | 
			
		||||
    'switch' => false, // Cambiar a modo switch
 | 
			
		||||
    'switchType' => 'default', // 'default' o 'square'
 | 
			
		||||
    'color' => 'primary', // Bootstrap color: primary, secondary, success, danger, etc.
 | 
			
		||||
    'withIcon' => false, // Si el switch usa íconos en On/Off
 | 
			
		||||
 | 
			
		||||
    // Diseño de disposición
 | 
			
		||||
    'inline' => false, // Modo inline en lugar de bloque
 | 
			
		||||
 | 
			
		||||
    // Texto de ayuda
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    // Atributos adicionales
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // **Configuración de valores base**
 | 
			
		||||
    $livewireModel = $attributes->get('wire:model', $model);
 | 
			
		||||
    $name = $attributes->get('name', $livewireModel);
 | 
			
		||||
    $inputId = $attributes->get('id', $name . '_' . $uid);
 | 
			
		||||
    $checked = $attributes->get('checked', false);
 | 
			
		||||
    $disabled = $attributes->get('disabled', false);
 | 
			
		||||
 | 
			
		||||
    // **Manejo de errores**
 | 
			
		||||
    $errorKey = $livewireModel ?: $name;
 | 
			
		||||
    $hasError = $errors->has($errorKey);
 | 
			
		||||
    $errorClass = $hasError ? 'is-invalid' : '';
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $alignClass = match ($align) {
 | 
			
		||||
        'center' => 'text-center',
 | 
			
		||||
        'end' => 'text-end',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $sizeClass = match ($size) {
 | 
			
		||||
        'sm' => 'switch-sm',
 | 
			
		||||
        'lg' => 'switch-lg',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $switchTypeClass = $switchType === 'square' ? 'switch-square' : '';
 | 
			
		||||
    $switchColorClass = "switch-{$color}";
 | 
			
		||||
    $checkColorClass  = "form-check-{$color}";
 | 
			
		||||
 | 
			
		||||
    // **Fusionar atributos con clases dinámicas**
 | 
			
		||||
    $checkboxAttributes = $attributes->merge([
 | 
			
		||||
        'id' => $inputId,
 | 
			
		||||
        'name' => $name,
 | 
			
		||||
        'type' => 'checkbox',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // **Detectar si se usa input-group**
 | 
			
		||||
    $requiresInputGroup = $attributes->get('inline');
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
@if ($switch)
 | 
			
		||||
    {{-- ============================ MODO SWITCH ============================ --}}
 | 
			
		||||
    <div class="{{ $alignClass }} {{ $inline ? 'd-inline-block' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-2' }}">
 | 
			
		||||
        <label class="switch {{ $switchTypeClass }} {{ $switchColorClass }} {{ $sizeClass }} {{ $labelClass }}">
 | 
			
		||||
            <input
 | 
			
		||||
                {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
                {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
                {{ $checked ? 'checked' : '' }}
 | 
			
		||||
                {!! $checkboxAttributes->class("switch-input $errorClass")->toHtml() !!}
 | 
			
		||||
            />
 | 
			
		||||
            {{-- El Switch Slider --}}
 | 
			
		||||
            <span class="switch-toggle-slider">
 | 
			
		||||
                @if ($withIcon)
 | 
			
		||||
                    <span class="switch-on">
 | 
			
		||||
                        <i class="ti ti-check"></i>
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span class="switch-off">
 | 
			
		||||
                        <i class="ti ti-x"></i>
 | 
			
		||||
                    </span>
 | 
			
		||||
                @endif
 | 
			
		||||
            </span>
 | 
			
		||||
            {{-- Etiqueta textual a la derecha del switch --}}
 | 
			
		||||
            <span class="switch-label">
 | 
			
		||||
                {{ $label }}
 | 
			
		||||
            </span>
 | 
			
		||||
        </label>
 | 
			
		||||
 | 
			
		||||
        {{-- Texto de ayuda y error --}}
 | 
			
		||||
        @isset($helperText)
 | 
			
		||||
            <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
        @endisset
 | 
			
		||||
        @if ($hasError)
 | 
			
		||||
            <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@else
 | 
			
		||||
    {{-- ============================ MODO CHECKBOX ============================ --}}
 | 
			
		||||
    <div class="form-check {{ $checkColorClass }} {{ $alignClass }} {{ $sizeClass }} {{ $inline ? 'form-check-inline' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-4' }}">
 | 
			
		||||
        <input
 | 
			
		||||
            {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
            {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
            {{ $checked ? 'checked' : '' }}
 | 
			
		||||
            {!! $checkboxAttributes->class("form-check-input $errorClass")->toHtml() !!}
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
        <label for="{{ $inputId }}" class="form-check-label {{ $labelClass }}">
 | 
			
		||||
            {{ $label }}
 | 
			
		||||
        </label>
 | 
			
		||||
 | 
			
		||||
        {{-- Texto de ayuda y error --}}
 | 
			
		||||
        @isset($helperText)
 | 
			
		||||
            <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
        @endisset
 | 
			
		||||
        @if ($hasError)
 | 
			
		||||
            <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
@endif
 | 
			
		||||
							
								
								
									
										54
									
								
								resources/views/components/form/custom-option.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								resources/views/components/form/custom-option.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
    'id' => '',
 | 
			
		||||
    'model' => '',
 | 
			
		||||
    'name' => '',
 | 
			
		||||
    'type' => 'checkbox', // checkbox o radio
 | 
			
		||||
    'title' => '',
 | 
			
		||||
    'description' => '',
 | 
			
		||||
    'icon' => null, // Clases de iconos (ej: ti ti-rocket)
 | 
			
		||||
    'image' => null, // URL de imagen
 | 
			
		||||
    'checked' => false,
 | 
			
		||||
    'disabled' => false,
 | 
			
		||||
    'helperText' => '',     // Texto de ayuda opcional
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    $livewireModel = $attributes->get('wire:model', $model);
 | 
			
		||||
    $name = $name ?: $livewireModel;
 | 
			
		||||
    $inputId = $id ?: ($uid ? $name . '_' . $uid : $name);
 | 
			
		||||
    $errorClass = $errors->has($model) ? 'is-invalid' : '';
 | 
			
		||||
    $checkedAttribute = $checked ? 'checked' : '';
 | 
			
		||||
    $visualContent = $icon
 | 
			
		||||
        ? "<i class='{$icon}'></i>"
 | 
			
		||||
        : ($image ? "<img src='{$image}' alt='{$title}' class='img-fluid rounded'>" : '');
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div class="mb-4 form-check custom-option custom-option-icon {{ $checked ? 'checked' : '' }}">
 | 
			
		||||
    <label class="form-check-label custom-option-content" for="{{ $inputId }}">
 | 
			
		||||
        <span class="custom-option-body">
 | 
			
		||||
            {!! $visualContent !!}
 | 
			
		||||
            <span class="custom-option-title">{{ $title }}</span>
 | 
			
		||||
            @if($description)
 | 
			
		||||
                <small>{{ $description }}</small>
 | 
			
		||||
            @endif
 | 
			
		||||
        </span>
 | 
			
		||||
        <input
 | 
			
		||||
            type="{{ $type }}"
 | 
			
		||||
            class="form-check-input {{ $errorClass }}"
 | 
			
		||||
            id="{{ $inputId }}"
 | 
			
		||||
            name="{{ $name }}"
 | 
			
		||||
            wire:model="{{ $model }}"
 | 
			
		||||
            {{ $checked ? 'checked' : '' }}
 | 
			
		||||
            {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
        >
 | 
			
		||||
    </label>
 | 
			
		||||
 | 
			
		||||
    @if ($helperText)
 | 
			
		||||
        <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @error($model)
 | 
			
		||||
        <span class="text-danger">{{ $message }}</span>
 | 
			
		||||
    @enderror
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										48
									
								
								resources/views/components/form/form.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								resources/views/components/form/form.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'id' => uniqid(),                // ID único del formulario
 | 
			
		||||
    'uniqueId' => '',                // ID único del formulario
 | 
			
		||||
    'mode' => 'create',              // Modo actual ('create', 'edit', 'delete')
 | 
			
		||||
    'method' => 'POST',              // Método del formulario (POST, GET, PUT, DELETE)
 | 
			
		||||
    'action' => '',                  // URL de acción
 | 
			
		||||
    'enctype' => false,              // Para envío de archivos
 | 
			
		||||
    'wireSubmit' => false,           // Usar wire:submit.prevent
 | 
			
		||||
    'class' => '',                   // Clases adicionales para el formulario
 | 
			
		||||
    'actionPosition' => 'bottom',    // Posición de acciones: top, bottom, both, none
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    $formAttributes = [
 | 
			
		||||
        'id' => $id,
 | 
			
		||||
        'method' => $method,
 | 
			
		||||
        'action' => $action,
 | 
			
		||||
        'class' => "fv-plugins-bootstrap5 $class",
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    if ($wireSubmit) {
 | 
			
		||||
        $formAttributes['wire:submit.prevent'] = $wireSubmit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($enctype) {
 | 
			
		||||
        $formAttributes['enctype'] = 'multipart/form-data';
 | 
			
		||||
    }
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<form {{ $attributes->merge($formAttributes) }}>
 | 
			
		||||
    <x-vuexy-admin::form.input :uid="$uniqueId" type="hidden" model="id" />
 | 
			
		||||
    <x-vuexy-admin::form.input :uid="$uniqueId" type="hidden" model="mode" />
 | 
			
		||||
    @if ($mode !== 'delete' && in_array($actionPosition, ['top', 'both']))
 | 
			
		||||
        <div class="notification-container mb-4"></div>
 | 
			
		||||
        <div class="form-actions mb-4">
 | 
			
		||||
            {{ $actions ?? '' }}
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
    <div class="form-body">
 | 
			
		||||
        {{ $slot }}
 | 
			
		||||
    </div>
 | 
			
		||||
    @if (in_array($actionPosition, ['bottom', 'both']))
 | 
			
		||||
        <div class="notification-container mb-4"></div>
 | 
			
		||||
        <div class="form-actions mt-4">
 | 
			
		||||
            {{ $actions ?? '' }}
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
</form>
 | 
			
		||||
							
								
								
									
										184
									
								
								resources/views/components/form/input.blade copy.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								resources/views/components/form/input.blade copy.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,184 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    'model' => '',
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    'class' => '',
 | 
			
		||||
 | 
			
		||||
    'align' => 'start',
 | 
			
		||||
    'size' => '',
 | 
			
		||||
    'mb-0' => false,
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    'prefix' => null,
 | 
			
		||||
    'suffix' => null,
 | 
			
		||||
 | 
			
		||||
    'icon' => null,
 | 
			
		||||
    'clickableIcon' => null,
 | 
			
		||||
 | 
			
		||||
    'inline' => false,
 | 
			
		||||
 | 
			
		||||
    'labelCol' => 4,
 | 
			
		||||
    'inputCol' => 8,
 | 
			
		||||
 | 
			
		||||
    'floatLabel' => false,
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]), // Atributos adicionales
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // Configuración dinámica de atributos y clases CSS
 | 
			
		||||
    $livewireModel = $attributes->get('wire:model', $model); // Permitir uso directo de wire:model en el atributo
 | 
			
		||||
    $name = $name ?: $livewireModel; // Si no se proporciona el nombre, toma el nombre del modelo
 | 
			
		||||
    $inputId = $id ?: ($uid ? $name . '_' . $uid : $name); // ID generado si no se proporciona uno
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Obtener los atributos actuales en un array
 | 
			
		||||
    $attributesArray = array_merge([
 | 
			
		||||
        'type' => $type,
 | 
			
		||||
        'id' => $inputId,
 | 
			
		||||
        'name' => $name,
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Agregar wire:model solo si existe
 | 
			
		||||
    if ($livewireModel) {
 | 
			
		||||
        $attributesArray['wire:model'] = $livewireModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    $attributesArray = array_merge($attributesArray, $attributes->getAttributes());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Reconstruir el ComponentAttributeBag con los atributos modificados
 | 
			
		||||
    $inputAttributes = new \Illuminate\View\ComponentAttributeBag($attributesArray);
 | 
			
		||||
 | 
			
		||||
    dump($inputAttributes);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Manejo de errores de validación
 | 
			
		||||
    $errorKey = $livewireModel ?: $name;
 | 
			
		||||
    $errorClass = $errors->has($errorKey) ? 'is-invalid' : '';
 | 
			
		||||
 | 
			
		||||
    // Definir el tamaño del input basado en la clase seleccionada
 | 
			
		||||
    $sizeClass = $size === 'small' ? 'form-control-sm' : ($size === 'large' ? 'form-control-lg' : '');
 | 
			
		||||
 | 
			
		||||
    // Alineación del texto
 | 
			
		||||
    $alignClass = match ($align) {
 | 
			
		||||
        'center' => 'text-center',
 | 
			
		||||
        'end' => 'text-end',
 | 
			
		||||
        default => ''
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Clases combinadas para el input
 | 
			
		||||
    $fullClass = trim("form-control $sizeClass $alignClass $errorClass $class");
 | 
			
		||||
 | 
			
		||||
    // Detectar si se necesita usar input-group
 | 
			
		||||
    $requiresInputGroup = $prefix || $suffix || $icon || $clickableIcon;
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
{{-- Input oculto sin estilos --}}
 | 
			
		||||
@if($type === 'hidden')
 | 
			
		||||
    <input type="hidden" id="{{ $inputId }}" name="{{ $name }}" {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
     />
 | 
			
		||||
@elseif($floatLabel)
 | 
			
		||||
    {{-- Input con etiqueta flotante --}}
 | 
			
		||||
    <div class="form-floating mb-4 {{ $parentClass }}">
 | 
			
		||||
        <input
 | 
			
		||||
            type="{{ $type }}"
 | 
			
		||||
            id="{{ $inputId }}"
 | 
			
		||||
            name="{{ $name }}"
 | 
			
		||||
            {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
            class="{{ $fullClass }}"
 | 
			
		||||
            placeholder="{{ $placeholder ?: 'Ingrese ' . strtolower($label) }}"
 | 
			
		||||
            {{ $step ? "step=$step" : '' }}
 | 
			
		||||
            {{ $max ? "maxlength=$max" : '' }}
 | 
			
		||||
            {{ $min ? "minlength=$min" : '' }}
 | 
			
		||||
            {{ $pattern ? "pattern=$pattern" : '' }}
 | 
			
		||||
            {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
            {{ $multiple ? 'multiple' : '' }} />
 | 
			
		||||
        <label for="{{ $inputId }}">{{ $label }}</label>
 | 
			
		||||
 | 
			
		||||
        @if ($helperText)
 | 
			
		||||
            <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
        @endif
 | 
			
		||||
 | 
			
		||||
        @if ($errors->has($errorKey))
 | 
			
		||||
            <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
@else
 | 
			
		||||
    {{-- Input con formato clásico --}}
 | 
			
		||||
    <div class="{{ $inline ? 'row' : '' }} {{ $parentClass }} fv-row mb-4">
 | 
			
		||||
        @isset($label)
 | 
			
		||||
            <label for="{{ $inputId }}" class="{{ $inline ? 'col-form-label col-md-' . $labelCol : 'form-label' }} {{ $labelClass }}">{{ $label }}</label>
 | 
			
		||||
        @endisset
 | 
			
		||||
        <div class="{{ $inline ? 'col-md-' . $inputCol : '' }}">
 | 
			
		||||
            @if ($requiresInputGroup)
 | 
			
		||||
                <div class="input-group input-group-merge">
 | 
			
		||||
                    @if ($prefix)
 | 
			
		||||
                        <span class="input-group-text">{{ $prefix }}</span>
 | 
			
		||||
                    @endif
 | 
			
		||||
                    @if ($icon)
 | 
			
		||||
                        <span class="input-group-text"><i class="{{ $icon }}"></i></span>
 | 
			
		||||
                    @endif
 | 
			
		||||
                    <input
 | 
			
		||||
                        type="{{ $type }}"
 | 
			
		||||
                        id="{{ $inputId }}"
 | 
			
		||||
                        name="{{ $name }}"
 | 
			
		||||
                        {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
                        class="{{ $fullClass }}"
 | 
			
		||||
                        placeholder="{{ $placeholder ?: 'Ingrese ' . strtolower($label) }}"
 | 
			
		||||
                        {{ $step ? "step=$step" : '' }}
 | 
			
		||||
                        {{ $max ? "maxlength=$max" : '' }}
 | 
			
		||||
                        {{ $min ? "minlength=$min" : '' }}
 | 
			
		||||
                        {{ $pattern ? "pattern=$pattern" : '' }}
 | 
			
		||||
                        {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
                        {{ $multiple ? 'multiple' : '' }} />
 | 
			
		||||
                    @if ($suffix)
 | 
			
		||||
                        <span class="input-group-text">{{ $suffix }}</span>
 | 
			
		||||
                    @endif
 | 
			
		||||
                    @if ($clickableIcon)
 | 
			
		||||
                        <button type="button" class="input-group-text cursor-pointer">
 | 
			
		||||
                            <i class="{{ $clickableIcon }}"></i>
 | 
			
		||||
                        </button>
 | 
			
		||||
                    @endif
 | 
			
		||||
                </div>
 | 
			
		||||
            @else
 | 
			
		||||
                {{-- Input sin prefijo o íconos --}}
 | 
			
		||||
                <input
 | 
			
		||||
                    type="{{ $type }}"
 | 
			
		||||
                    id="{{ $inputId }}"
 | 
			
		||||
                    name="{{ $name }}"
 | 
			
		||||
                    {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
                    class="{{ $fullClass }}"
 | 
			
		||||
                    placeholder="{{ $placeholder ?: 'Ingrese ' . strtolower($label) }}"
 | 
			
		||||
                    {{ $step ? "step=$step" : '' }}
 | 
			
		||||
                    {{ $max ? "maxlength=$max" : '' }}
 | 
			
		||||
                    {{ $min ? "minlength=$min" : '' }}
 | 
			
		||||
                    {{ $pattern ? "pattern=$pattern" : '' }}
 | 
			
		||||
                    {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
                    {{ $multiple ? 'multiple' : '' }} />
 | 
			
		||||
            @endif
 | 
			
		||||
            @if ($helperText)
 | 
			
		||||
                <small class="form-text text-muted">{{ $helperText }}</small>
 | 
			
		||||
            @endif
 | 
			
		||||
            @if ($errors->has($errorKey))
 | 
			
		||||
                <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
            @endif
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@endif
 | 
			
		||||
							
								
								
									
										169
									
								
								resources/views/components/form/input.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								resources/views/components/form/input.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,169 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelo de Livewire
 | 
			
		||||
    'model' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y Clases
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
    'placeholder' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases Generales
 | 
			
		||||
    'align' => 'start',
 | 
			
		||||
    'size' => '', // Tamaño del input (sm, lg)
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Elementos opcionales antes/después del input
 | 
			
		||||
    'prefix' => null,
 | 
			
		||||
    'suffix' => null,
 | 
			
		||||
 | 
			
		||||
    // Íconos dentro del input
 | 
			
		||||
    'icon' => null,
 | 
			
		||||
    'clickableIcon' => null,
 | 
			
		||||
 | 
			
		||||
    // Configuración especial
 | 
			
		||||
    'phoneMode' => false, // "national", "international", "both"
 | 
			
		||||
 | 
			
		||||
    // Diseño de disposición (columnas)
 | 
			
		||||
    'inline' => false,
 | 
			
		||||
    'labelCol' => 4,
 | 
			
		||||
    'inputCol' => 8,
 | 
			
		||||
 | 
			
		||||
    // Configuración de etiquetas flotantes y texto de ayuda
 | 
			
		||||
    'floatLabel' => false,
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    // Atributos adicionales
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // **Configuración de Name, ID y Model**
 | 
			
		||||
    $livewireModel = $attributes->get('wire:model', $model);
 | 
			
		||||
    $name = $attributes->get('name', $livewireModel);
 | 
			
		||||
    $inputId = $attributes->get('id', $name . '_' . $uid);
 | 
			
		||||
    $type = $attributes->get('type', 'text');
 | 
			
		||||
 | 
			
		||||
    // **Definir formato de teléfono según `phoneMode`**
 | 
			
		||||
    if ($phoneMode) {
 | 
			
		||||
        $type = 'tel';
 | 
			
		||||
        $attributes = $attributes->merge([
 | 
			
		||||
            'autocomplete' => 'tel',
 | 
			
		||||
            'inputmode' => 'tel',
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        switch ($phoneMode) {
 | 
			
		||||
            case 'national':
 | 
			
		||||
                $attributes = $attributes->merge([
 | 
			
		||||
                    'pattern' => '^(?:\D*\d){10,}$',
 | 
			
		||||
                    'placeholder' => $placeholder !== false ? ($placeholder ?: 'Ej. (55) 1234-5678') : null,
 | 
			
		||||
                ]);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 'international':
 | 
			
		||||
                $attributes = $attributes->merge([
 | 
			
		||||
                    'pattern' => '^\+?[1-9]\d{1,14}$',
 | 
			
		||||
                    'placeholder' => $placeholder !== false ? ($placeholder ?: 'Ej. +52 1 55 1234-5678') : null,
 | 
			
		||||
                ]);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 'both':
 | 
			
		||||
                $attributes = $attributes->merge([
 | 
			
		||||
                    'pattern' => '(^(?:\D*\d){10,}$)|(^\+?[1-9]\d{1,14}$)',
 | 
			
		||||
                    'placeholder' => $placeholder !== false ? ($placeholder ?: 'Ej. (55) 1234-5678 o +52 1 55 1234-5678') : null,
 | 
			
		||||
                ]);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // **Manejo del Placeholder si no lo estableció `phoneMode`**
 | 
			
		||||
    if (!$attributes->has('placeholder')) {
 | 
			
		||||
        if ($placeholder === false) {
 | 
			
		||||
            // No agregar `placeholder`
 | 
			
		||||
            $placeholderAttr = [];
 | 
			
		||||
        } elseif (empty($placeholder)) {
 | 
			
		||||
            // Generar automáticamente desde el `label`
 | 
			
		||||
            $placeholderAttr = ['placeholder' => 'Ingrese ' . strtolower($label)];
 | 
			
		||||
        } else {
 | 
			
		||||
            // Usar `placeholder` definido manualmente
 | 
			
		||||
            $placeholderAttr = ['placeholder' => $placeholder];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Fusionar el placeholder si no fue definido en `phoneMode`
 | 
			
		||||
        $attributes = $attributes->merge($placeholderAttr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // **Manejo de errores**
 | 
			
		||||
    $errorKey = $livewireModel ?: $name;
 | 
			
		||||
    $hasError = $errors->has($errorKey);
 | 
			
		||||
    $errorClass = $hasError ? 'is-invalid' : '';
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $sizeClass = match ($size) {
 | 
			
		||||
        'sm' => 'form-control-sm',
 | 
			
		||||
        'lg' => 'form-control-lg',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $alignClass = match ($align) {
 | 
			
		||||
        'center' => 'text-center',
 | 
			
		||||
        'end' => 'text-end',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // **Fusionar atributos**
 | 
			
		||||
    $inputAttributes = $attributes->merge([
 | 
			
		||||
        'type' => $type,
 | 
			
		||||
        'id' => $inputId,
 | 
			
		||||
        'name' => $name,
 | 
			
		||||
    ])->class("form-control $sizeClass $alignClass $errorClass");
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
{{-- Estructura del Input --}}
 | 
			
		||||
<div class="{{ $mb0 ? '' : 'mb-4' }} {{ $parentClass }}">
 | 
			
		||||
    {{-- Etiqueta --}}
 | 
			
		||||
    @if ($label)
 | 
			
		||||
        <label for="{{ $inputId }}" class="form-label {{ $labelClass }}">{{ $label }}</label>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    {{-- Input con Prefijos, Sufijos o Íconos --}}
 | 
			
		||||
    @if ($prefix || $suffix || $icon || $clickableIcon)
 | 
			
		||||
        <div class="input-group input-group-merge">
 | 
			
		||||
            @isset($prefix)
 | 
			
		||||
                <span class="input-group-text">{{ $prefix }}</span>
 | 
			
		||||
            @endisset
 | 
			
		||||
 | 
			
		||||
            @isset($icon)
 | 
			
		||||
                <span class="input-group-text"><i class="{{ $icon }}"></i></span>
 | 
			
		||||
            @endisset
 | 
			
		||||
 | 
			
		||||
            <input {!! $inputAttributes !!} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} />
 | 
			
		||||
 | 
			
		||||
            @isset($suffix)
 | 
			
		||||
                <span class="input-group-text">{{ $suffix }}</span>
 | 
			
		||||
            @endisset
 | 
			
		||||
 | 
			
		||||
            @isset($clickableIcon)
 | 
			
		||||
                <button type="button" class="input-group-text cursor-pointer">
 | 
			
		||||
                    <i class="{{ $clickableIcon }}"></i>
 | 
			
		||||
                </button>
 | 
			
		||||
            @endisset
 | 
			
		||||
        </div>
 | 
			
		||||
    @else
 | 
			
		||||
        {{-- Input Simple --}}
 | 
			
		||||
        <input {!! $inputAttributes !!} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} />
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    {{-- Texto de ayuda --}}
 | 
			
		||||
    @if ($helperText)
 | 
			
		||||
        <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    {{-- Mensajes de error --}}
 | 
			
		||||
    @if ($hasError)
 | 
			
		||||
        <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										149
									
								
								resources/views/components/form/radio-group.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								resources/views/components/form/radio-group.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelos para Livewire
 | 
			
		||||
    'radioModel' => '',
 | 
			
		||||
    'textModel' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y clases de la etiqueta
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases generales
 | 
			
		||||
    'align' => 'start',
 | 
			
		||||
    'size' => '', // Tamaño del input (sm, lg)
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Elementos opcionales antes/después del input
 | 
			
		||||
    'prefix' => null,
 | 
			
		||||
    'suffix' => null,
 | 
			
		||||
 | 
			
		||||
    // Íconos dentro del input
 | 
			
		||||
    'icon' => null, // Ícono fijo
 | 
			
		||||
    'clickableIcon' => null, // Ícono con botón
 | 
			
		||||
 | 
			
		||||
    // Configuración del radio
 | 
			
		||||
    'checked' => false,
 | 
			
		||||
    'disabled' => false,
 | 
			
		||||
    'name' => '', // Grupo del radio
 | 
			
		||||
 | 
			
		||||
    // Configuración del input de texto
 | 
			
		||||
    'disableOnOffRadio' => true, // Deshabilita input hasta que el radio esté seleccionado
 | 
			
		||||
    'focusOnCheck' => true, // Hace foco en el input al seleccionar el radio
 | 
			
		||||
 | 
			
		||||
    // Texto de ayuda
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    // Atributos adicionales para el input de texto
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // **Generación de Name, ID y Model**
 | 
			
		||||
    $livewireRadio = $radioModel ? "wire:model=$radioModel" : '';
 | 
			
		||||
    $livewireText = $textModel ? "wire:model=$textModel" : '';
 | 
			
		||||
 | 
			
		||||
    $nameRadio = $attributes->get('name', $radioModel ?: $name);
 | 
			
		||||
    $nameText = $attributes->get('name', $textModel);
 | 
			
		||||
 | 
			
		||||
    $radioId = $attributes->get('id', 'radio_' . $uid);
 | 
			
		||||
    $textInputId = 'txt_' . $uid;
 | 
			
		||||
 | 
			
		||||
    // **Placeholder del input de texto**
 | 
			
		||||
    $placeholder = $attributes->get('placeholder', 'Ingrese información');
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $sizeClass = match ($size) {
 | 
			
		||||
        'sm' => 'form-control-sm',
 | 
			
		||||
        'lg' => 'form-control-lg',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $fullClass = trim("form-control $sizeClass");
 | 
			
		||||
 | 
			
		||||
    // **Fusionar atributos del input de texto**
 | 
			
		||||
    $inputAttributes = $attributes->merge([
 | 
			
		||||
        'id' => $textInputId,
 | 
			
		||||
        'name' => $nameText,
 | 
			
		||||
        'placeholder' => $placeholder,
 | 
			
		||||
    ])->class($fullClass);
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
{{-- ============================ RADIO BUTTON CON INPUT GROUP ============================ --}}
 | 
			
		||||
<div class="{{ $mb0 ? '' : 'mb-4' }} {{ $parentClass }}">
 | 
			
		||||
    @if ($label)
 | 
			
		||||
        <label for="{{ $radioId }}" class="{{ $labelClass }}">{{ $label }}</label>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    <div class="input-group">
 | 
			
		||||
        {{-- Radio dentro del input-group-text --}}
 | 
			
		||||
        <div class="input-group-text">
 | 
			
		||||
            <input
 | 
			
		||||
                id="{{ $radioId }}"
 | 
			
		||||
                name="{{ $nameRadio }}"
 | 
			
		||||
                type="radio"
 | 
			
		||||
                {{ $livewireRadio }}
 | 
			
		||||
                {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
                class="form-check-input mt-0"
 | 
			
		||||
                onchange="toggleRadioInputState('{{ $radioId }}', '{{ $textInputId }}', {{ $focusOnCheck ? 'true' : 'false' }}, {{ $disableOnOffRadio ? 'true' : 'false' }})"
 | 
			
		||||
            >
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {{-- Prefijo opcional --}}
 | 
			
		||||
        @isset($prefix)
 | 
			
		||||
            <span class="input-group-text">{{ $prefix }}</span>
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        {{-- Ícono fijo opcional --}}
 | 
			
		||||
        @isset($icon)
 | 
			
		||||
            <span class="input-group-text"><i class="{{ $icon }}"></i></span>
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        {{-- Input de texto dentro del mismo grupo --}}
 | 
			
		||||
        <input
 | 
			
		||||
            {{ $livewireText }}
 | 
			
		||||
            {!! $inputAttributes !!}
 | 
			
		||||
            @if ($disableOnOffRadio) disabled @endif
 | 
			
		||||
            aria-label="Text input with radio button"
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
        {{-- Sufijo opcional --}}
 | 
			
		||||
        @isset($suffix)
 | 
			
		||||
            <span class="input-group-text">{{ $suffix }}</span>
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        {{-- Ícono clickeable opcional --}}
 | 
			
		||||
        @isset($clickableIcon)
 | 
			
		||||
            <button type="button" class="input-group-text cursor-pointer">
 | 
			
		||||
                <i class="{{ $clickableIcon }}"></i>
 | 
			
		||||
            </button>
 | 
			
		||||
        @endisset
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {{-- Texto de ayuda opcional --}}
 | 
			
		||||
    @if ($helperText)
 | 
			
		||||
        <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{{-- ============================ JAVASCRIPT PURO ============================ --}}
 | 
			
		||||
<script>
 | 
			
		||||
    function toggleRadioInputState(radioId, inputId, focusOnCheck, disableOnOffRadio) {
 | 
			
		||||
        let radio = document.getElementById(radioId);
 | 
			
		||||
        let textInput = document.getElementById(inputId);
 | 
			
		||||
 | 
			
		||||
        if (!radio || !textInput) return;
 | 
			
		||||
 | 
			
		||||
        // Deshabilitar o habilitar el input de texto
 | 
			
		||||
        if (disableOnOffRadio) {
 | 
			
		||||
            textInput.disabled = !radio.checked;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Enfocar automáticamente el input si está habilitado
 | 
			
		||||
        if (focusOnCheck && radio.checked) {
 | 
			
		||||
            textInput.focus();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										125
									
								
								resources/views/components/form/radio.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								resources/views/components/form/radio.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelo de Livewire (si aplica)
 | 
			
		||||
    'model' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y clases de la etiqueta
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases generales
 | 
			
		||||
    'align' => 'start',
 | 
			
		||||
    'size' => '', // Tamaño del radio (sm, lg)
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Modo de visualización
 | 
			
		||||
    'switch' => false, // Convertir en switch
 | 
			
		||||
    'switchType' => 'default', // 'default' o 'square'
 | 
			
		||||
    'color' => 'primary', // Colores personalizados (Bootstrap)
 | 
			
		||||
    'stacked' => false, // Apilar radios en lugar de inline
 | 
			
		||||
    'inline' => false, // Mostrar radios en línea
 | 
			
		||||
 | 
			
		||||
    // Texto de ayuda
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    // Atributos adicionales
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // **Configuración de valores base**
 | 
			
		||||
    $livewireModel = $attributes->get('wire:model', $model);
 | 
			
		||||
    $name = $attributes->get('name', $livewireModel);
 | 
			
		||||
    $inputId = $attributes->get('id', $name . '_' . $uid);
 | 
			
		||||
    $checked = $attributes->get('checked', false);
 | 
			
		||||
    $disabled = $attributes->get('disabled', false);
 | 
			
		||||
 | 
			
		||||
    // **Manejo de errores**
 | 
			
		||||
    $errorKey = $livewireModel ?: $name;
 | 
			
		||||
    $hasError = $errors->has($errorKey);
 | 
			
		||||
    $errorClass = $hasError ? 'is-invalid' : '';
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $alignClass = match ($align) {
 | 
			
		||||
        'center' => 'text-center',
 | 
			
		||||
        'end' => 'text-end',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $sizeClass = match ($size) {
 | 
			
		||||
        'sm' => 'form-check-sm',
 | 
			
		||||
        'lg' => 'form-check-lg',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $switchTypeClass = $switchType === 'square' ? 'switch-square' : '';
 | 
			
		||||
    $switchColorClass = "switch-{$color}";
 | 
			
		||||
    $radioColorClass  = "form-check-{$color}";
 | 
			
		||||
 | 
			
		||||
    // **Fusionar atributos con clases dinámicas**
 | 
			
		||||
    $radioAttributes = $attributes->merge([
 | 
			
		||||
        'id' => $inputId,
 | 
			
		||||
        'name' => $name,
 | 
			
		||||
        'type' => 'radio',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // **Detectar si se usa `inline` o `stacked`**
 | 
			
		||||
    $layoutClass = $stacked ? 'switches-stacked' : 'form-check';
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
@if ($switch)
 | 
			
		||||
    {{-- ============================ MODO SWITCH ============================ --}}
 | 
			
		||||
    <div class="{{ $alignClass }} {{ $inline ? 'd-inline-block' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-4' }}">
 | 
			
		||||
        <label class="switch {{ $switchTypeClass }} {{ $switchColorClass }} {{ $sizeClass }} {{ $labelClass }}">
 | 
			
		||||
            <input
 | 
			
		||||
                {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
                {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
                {{ $checked ? 'checked' : '' }}
 | 
			
		||||
                {!! $radioAttributes->class("switch-input $errorClass")->toHtml() !!}
 | 
			
		||||
            />
 | 
			
		||||
            {{-- El Switch Slider --}}
 | 
			
		||||
            <span class="switch-toggle-slider">
 | 
			
		||||
                <span class="switch-on"></span>
 | 
			
		||||
                <span class="switch-off"></span>
 | 
			
		||||
            </span>
 | 
			
		||||
            {{-- Etiqueta textual a la derecha del switch --}}
 | 
			
		||||
            <span class="switch-label">
 | 
			
		||||
                {{ $label }}
 | 
			
		||||
            </span>
 | 
			
		||||
        </label>
 | 
			
		||||
 | 
			
		||||
        {{-- Texto de ayuda y error --}}
 | 
			
		||||
        @isset($helperText)
 | 
			
		||||
            <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
        @endisset
 | 
			
		||||
        @if ($hasError)
 | 
			
		||||
            <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@else
 | 
			
		||||
    {{-- ============================ MODO RADIO ============================ --}}
 | 
			
		||||
    <div class="{{ $layoutClass }} {{ $radioColorClass }} {{ $alignClass }} {{ $sizeClass }} {{ $inline ? 'form-check-inline' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-4' }}">
 | 
			
		||||
        <input
 | 
			
		||||
            {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
            {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
            {{ $checked ? 'checked' : '' }}
 | 
			
		||||
            {!! $radioAttributes->class("form-check-input $errorClass")->toHtml() !!}
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
        <label for="{{ $inputId }}" class="form-check-label {{ $labelClass }}">
 | 
			
		||||
            {{ $label }}
 | 
			
		||||
        </label>
 | 
			
		||||
 | 
			
		||||
        {{-- Texto de ayuda y error --}}
 | 
			
		||||
        @isset($helperText)
 | 
			
		||||
            <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
        @endisset
 | 
			
		||||
        @if ($hasError)
 | 
			
		||||
            <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
@endif
 | 
			
		||||
							
								
								
									
										86
									
								
								resources/views/components/form/select.blade copy.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								resources/views/components/form/select.blade copy.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
    'id' => '',
 | 
			
		||||
    'model' => '',
 | 
			
		||||
    'name' => '',
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => 'form-label',
 | 
			
		||||
    'placeholder' => '',
 | 
			
		||||
    'options' => [],
 | 
			
		||||
    'selected' => null,
 | 
			
		||||
    'class' => '',
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
    'multiple' => false,
 | 
			
		||||
    'disabled' => false,
 | 
			
		||||
    'prefixLabel' => null,
 | 
			
		||||
    'suffixLabel' => null,
 | 
			
		||||
    'buttonBefore' => null,
 | 
			
		||||
    'buttonAfter' => null,
 | 
			
		||||
    'inline' => false,    // Si es en línea
 | 
			
		||||
    'labelCol' => 2,      // Columnas que ocupa el label (Bootstrap grid)
 | 
			
		||||
    'inputCol' => 10,     // Columnas que ocupa el input (Bootstrap grid)
 | 
			
		||||
    'helperText' => '',   // Texto de ayuda opcional
 | 
			
		||||
    'select2' => false,   // Activar Select2 automáticamente
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    $name = $name ?: $model;
 | 
			
		||||
    $inputId = $id ?: ($uid ? str_replace('.', '_', $name) . '_' . $uid : $name);
 | 
			
		||||
    $placeholder = $placeholder ?: 'Seleccione ' . strtolower($label);
 | 
			
		||||
    $errorClass = $errors->has($model) ? 'is-invalid' : '';
 | 
			
		||||
    $options = is_array($options) ? collect($options) : $options;
 | 
			
		||||
    $select2Class = $select2 ? 'select2' : '';  // Agrega la clase select2 si está habilitado
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div class="{{ $inline ? 'row' : 'mb-4' }} {{ $parentClass }} fv-row">
 | 
			
		||||
    @if($label != null)
 | 
			
		||||
        <label for="{{ $inputId }}" class="{{ $inline ? 'col-md-' . $labelCol : '' }} {{ $labelClass }}">{{ $label }}</label>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    <div class="{{ $inline ? 'col-md-' . $inputCol : '' }}">
 | 
			
		||||
        <div class="input-group {{ $prefixLabel || $suffixLabel || $buttonBefore || $buttonAfter ? 'input-group-merge' : '' }}">
 | 
			
		||||
            @if ($buttonBefore)
 | 
			
		||||
                <button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonBefore }}</button>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            @if ($prefixLabel)
 | 
			
		||||
                <label class="input-group-text" for="{{ $inputId }}">{{ $prefixLabel }}</label>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            <select
 | 
			
		||||
                id="{{ $inputId }}"
 | 
			
		||||
                name="{{ $name }}"
 | 
			
		||||
                class="form-select {{ $errorClass }} {{ $class }} {{ $select2Class }}"
 | 
			
		||||
                {{ $multiple ? 'multiple' : '' }}
 | 
			
		||||
                {{ $disabled ? 'disabled' : '' }}
 | 
			
		||||
                {{ $model ? "wire:model=$model" : '' }}
 | 
			
		||||
                {{ $select2 ? 'data-live-search="true"' : '' }}
 | 
			
		||||
            >
 | 
			
		||||
                @if (!$multiple && $placeholder)
 | 
			
		||||
                    <option value="">{{ $placeholder }}</option>
 | 
			
		||||
                @endif
 | 
			
		||||
                @foreach ($options as $key => $value)
 | 
			
		||||
                    <option value="{{ $key }}" {{ (string) $key === (string) $selected ? 'selected' : '' }}>
 | 
			
		||||
                        {{ $value }}
 | 
			
		||||
                    </option>
 | 
			
		||||
                @endforeach
 | 
			
		||||
            </select>
 | 
			
		||||
 | 
			
		||||
            @if ($suffixLabel)
 | 
			
		||||
                <label class="input-group-text" for="{{ $inputId }}">{{ $suffixLabel }}</label>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            @if ($buttonAfter)
 | 
			
		||||
                <button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonAfter }}</button>
 | 
			
		||||
            @endif
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        @if ($helperText)
 | 
			
		||||
            <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
        @endif
 | 
			
		||||
 | 
			
		||||
        @if ($errors->has($model))
 | 
			
		||||
            <span class="text-danger">{{ $errors->first($model) }}</span>
 | 
			
		||||
        @endif
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										151
									
								
								resources/views/components/form/select.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								resources/views/components/form/select.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,151 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelo de Livewire (si aplica)
 | 
			
		||||
    'model' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y clases de la etiqueta
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases generales
 | 
			
		||||
    'align' => 'start',
 | 
			
		||||
    'size' => '', // Tamaño del select (small, large)
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Activar Select2 automáticamente
 | 
			
		||||
    'select2' => false,
 | 
			
		||||
 | 
			
		||||
    // Prefijos y sufijos en input-group
 | 
			
		||||
    'prefixLabel' => null,
 | 
			
		||||
    'suffixLabel' => null,
 | 
			
		||||
    'buttonBefore' => null,
 | 
			
		||||
    'buttonAfter' => null,
 | 
			
		||||
 | 
			
		||||
    // Diseño de disposición (columnas)
 | 
			
		||||
    'inline' => false,
 | 
			
		||||
    'labelCol' => 4,
 | 
			
		||||
    'inputCol' => 8,
 | 
			
		||||
 | 
			
		||||
    // Texto de ayuda
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    // Opciones del select
 | 
			
		||||
    'options' => [],
 | 
			
		||||
 | 
			
		||||
    // Atributos adicionales
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // **Configuración de valores base**
 | 
			
		||||
    $livewireModel = $attributes->get('wire:model', $model);
 | 
			
		||||
    $name = $attributes->get('name', $livewireModel);
 | 
			
		||||
    $inputId = $attributes->get('id', $name . '_' . $uid);
 | 
			
		||||
    $placeholder = $attributes->get('placeholder', 'Seleccione ' . strtolower($label));
 | 
			
		||||
    $selected = $attributes->get('selected', null);
 | 
			
		||||
 | 
			
		||||
    // **Manejo de errores**
 | 
			
		||||
    $errorKey = $livewireModel ?: $name;
 | 
			
		||||
    $hasError = $errors->has($errorKey);
 | 
			
		||||
    $errorClass = $hasError ? 'is-invalid' : '';
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $select2Class = $select2 ? 'select2' : '';  // Agrega la clase `select2` si está habilitado
 | 
			
		||||
    $sizeClass = match ($size) {
 | 
			
		||||
        'sm' => 'form-select-sm',
 | 
			
		||||
        'lg' => 'form-select-lg',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
    $alignClass = match ($align) {
 | 
			
		||||
        'center' => 'text-center',
 | 
			
		||||
        'end' => 'text-end',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // **Construcción de clases dinámicas**
 | 
			
		||||
    $fullClass = trim("form-select $select2Class $sizeClass $alignClass $errorClass");
 | 
			
		||||
    $fullLabelClass = trim(($inline ? 'col-form-label col-md-' . $labelCol : 'form-label') . ' ' . $labelClass);
 | 
			
		||||
    $containerClass = trim(($inline ? 'row' : '') . ' fv-row ' . ($mb0 ? '' : 'mb-4') . " $alignClass $parentClass");
 | 
			
		||||
 | 
			
		||||
    // **Fusionar atributos con clases dinámicas**
 | 
			
		||||
    $selectAttributes = $attributes->merge([
 | 
			
		||||
        'id' => $inputId,
 | 
			
		||||
        'name' => $name,
 | 
			
		||||
    ])->class($fullClass);
 | 
			
		||||
 | 
			
		||||
    // **Detectar si se necesita input-group**
 | 
			
		||||
    $requiresInputGroup = $prefixLabel || $suffixLabel || $buttonBefore || $buttonAfter;
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div class="{{ $containerClass }}">
 | 
			
		||||
    {{-- Etiqueta del select --}}
 | 
			
		||||
    @if($label)
 | 
			
		||||
        <label for="{{ $inputId }}" class="{{ $fullLabelClass }}">{{ $label }}</label>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @if($inline)
 | 
			
		||||
        <div class="col-md-{{ $inputCol }}">
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
        {{-- Input Group (Si tiene prefijo/sufijo) --}}
 | 
			
		||||
        @if ($requiresInputGroup)
 | 
			
		||||
            <div class="input-group input-group-merge">
 | 
			
		||||
                @isset($buttonBefore)
 | 
			
		||||
                    <button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonBefore }}</button>
 | 
			
		||||
                @endisset
 | 
			
		||||
 | 
			
		||||
                @if($prefixLabel)
 | 
			
		||||
                    <label class="input-group-text" for="{{ $inputId }}">{{ $prefixLabel }}</label>
 | 
			
		||||
                @endif
 | 
			
		||||
 | 
			
		||||
                {{-- Select --}}
 | 
			
		||||
                <select {!! $selectAttributes !!} {{ $attributes->get('multiple') ? 'multiple' : '' }} {{ $attributes->get('disabled') ? 'disabled' : '' }} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} {{ $select2 ? 'data-live-search="true"' : '' }}>
 | 
			
		||||
                    @if (!$attributes->get('multiple') && $placeholder)
 | 
			
		||||
                        <option value="">{{ $placeholder }}</option>
 | 
			
		||||
                    @endif
 | 
			
		||||
                    @foreach ($options as $key => $value)
 | 
			
		||||
                        <option value="{{ $key }}" {{ (string) $key === (string) $selected ? 'selected' : '' }}>
 | 
			
		||||
                            {{ $value }}
 | 
			
		||||
                        </option>
 | 
			
		||||
                    @endforeach
 | 
			
		||||
                </select>
 | 
			
		||||
 | 
			
		||||
                @if($suffixLabel)
 | 
			
		||||
                    <label class="input-group-text" for="{{ $inputId }}">{{ $suffixLabel }}</label>
 | 
			
		||||
                @endif
 | 
			
		||||
 | 
			
		||||
                @isset($buttonAfter)
 | 
			
		||||
                    <button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonAfter }}</button>
 | 
			
		||||
                @endisset
 | 
			
		||||
            </div>
 | 
			
		||||
        @else
 | 
			
		||||
            {{-- Select sin prefijo/sufijo --}}
 | 
			
		||||
            <select {!! $selectAttributes !!} {{ $attributes->get('multiple') ? 'multiple' : '' }} {{ $attributes->get('disabled') ? 'disabled' : '' }} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} {{ $select2 ? 'data-live-search="true"' : '' }}>
 | 
			
		||||
                @if (!$attributes->get('multiple') && $placeholder)
 | 
			
		||||
                    <option value="">{{ $placeholder }}</option>
 | 
			
		||||
                @endif
 | 
			
		||||
                @foreach ($options as $key => $value)
 | 
			
		||||
                    <option value="{{ $key }}" {{ (string) $key === (string) $selected ? 'selected' : '' }}>
 | 
			
		||||
                        {{ $value }}
 | 
			
		||||
                    </option>
 | 
			
		||||
                @endforeach
 | 
			
		||||
            </select>
 | 
			
		||||
        @endif
 | 
			
		||||
 | 
			
		||||
        {{-- Texto de ayuda --}}
 | 
			
		||||
        @isset($helperText)
 | 
			
		||||
            <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
        @endisset
 | 
			
		||||
 | 
			
		||||
        {{-- Errores de validación --}}
 | 
			
		||||
        @if ($hasError)
 | 
			
		||||
            <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
        @endif
 | 
			
		||||
 | 
			
		||||
    @if($inline)
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										178
									
								
								resources/views/components/form/textarea.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								resources/views/components/form/textarea.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,178 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelo para Livewire
 | 
			
		||||
    'model' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y clases de la etiqueta
 | 
			
		||||
    'label' => '',
 | 
			
		||||
    'labelClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases generales
 | 
			
		||||
    'align' => 'start', // Alineación del textarea (start, end)
 | 
			
		||||
    'size' => 'md', // Tamaño del textarea (sm, md, lg)
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
 | 
			
		||||
    // Elementos opcionales antes/después del textarea
 | 
			
		||||
    'prefix' => null,
 | 
			
		||||
    'suffix' => null,
 | 
			
		||||
 | 
			
		||||
    // Íconos dentro del input
 | 
			
		||||
    'prefixIcon' => null, // Ícono fijo a la izquierda
 | 
			
		||||
    'prefixClickableIcon' => null, // Ícono con botón a la izquierda
 | 
			
		||||
    'suffixIcon' => null, // Ícono fijo a la derecha
 | 
			
		||||
    'suffixClickableIcon' => null, // Ícono con botón a la derecha
 | 
			
		||||
 | 
			
		||||
    // Configuración del textarea
 | 
			
		||||
    'rows' => 3,
 | 
			
		||||
    'maxlength' => null,
 | 
			
		||||
    'autosize' => false, // Autoajuste de altura
 | 
			
		||||
    'resize' => true, // Permitir redimensionar
 | 
			
		||||
 | 
			
		||||
    // Soporte para etiquetas flotantes
 | 
			
		||||
    'floating' => false, // Si la etiqueta es flotante
 | 
			
		||||
 | 
			
		||||
    // Texto de ayuda
 | 
			
		||||
    'helperText' => '',
 | 
			
		||||
 | 
			
		||||
    // Atributos adicionales para el textarea
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // **Generación de Name, ID y Model**
 | 
			
		||||
    $livewireModel = $attributes->get('wire:model', $model);
 | 
			
		||||
    $name = $attributes->get('name', $livewireModel);
 | 
			
		||||
    $inputId = $attributes->get('id', $name . '_' . $uid);
 | 
			
		||||
 | 
			
		||||
    // **Placeholder obligatorio si es flotante**
 | 
			
		||||
    $placeholder = $attributes->get('placeholder', $floating ? ' ' : 'Ingrese ' . strtolower($label));
 | 
			
		||||
 | 
			
		||||
    // **Manejo de errores**
 | 
			
		||||
    $errorKey = $livewireModel ?: $name;
 | 
			
		||||
    $hasError = $errors->has($errorKey);
 | 
			
		||||
    $errorClass = $hasError ? 'is-invalid' : '';
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $sizeClass = match ($size) {
 | 
			
		||||
        'sm' => 'form-control-sm',
 | 
			
		||||
        'lg' => 'form-control-lg',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $alignClass = match ($align) {
 | 
			
		||||
        'center' => 'text-center',
 | 
			
		||||
        'end' => 'text-end',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // **Control de redimensionamiento**
 | 
			
		||||
    $resizeClass = $resize ? '' : 'resize-none';
 | 
			
		||||
 | 
			
		||||
    // **Fusionar atributos del textarea**
 | 
			
		||||
    $textareaAttributes = $attributes->merge([
 | 
			
		||||
        'id' => $inputId,
 | 
			
		||||
        'name' => $name,
 | 
			
		||||
        'rows' => $rows,
 | 
			
		||||
        'placeholder' => $placeholder,
 | 
			
		||||
        'maxlength' => $maxlength,
 | 
			
		||||
    ])->class("form-control $sizeClass $resizeClass $errorClass");
 | 
			
		||||
 | 
			
		||||
    // **Clases del contenedor flotante**
 | 
			
		||||
    $floatingClass = $floating ? 'form-floating' : '';
 | 
			
		||||
 | 
			
		||||
    // **Detectar si necesita Input-Group**
 | 
			
		||||
    $requiresInputGroup = $prefix || $suffix || $prefixIcon || $suffixIcon || $prefixClickableIcon || $suffixClickableIcon;
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
{{-- ============================ TEXTAREA ============================ --}}
 | 
			
		||||
<div class="{{ $mb0 ? '' : 'mb-4' }} {{ $parentClass }} {{ $alignClass }} {{ $floatingClass }}">
 | 
			
		||||
    @if (!$floating && $label)
 | 
			
		||||
        <label for="{{ $inputId }}" class="{{ $labelClass }}">{{ $label }}</label>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @if ($requiresInputGroup)
 | 
			
		||||
        {{-- Textarea con Input-Group --}}
 | 
			
		||||
        <div class="input-group">
 | 
			
		||||
            {{-- Prefijos (Izquierda) --}}
 | 
			
		||||
            @if ($prefix)
 | 
			
		||||
                <span class="input-group-text">{{ $prefix }}</span>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            @if ($prefixIcon)
 | 
			
		||||
                <span class="input-group-text"><i class="{{ $prefixIcon }}"></i></span>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            @if ($prefixClickableIcon)
 | 
			
		||||
                <button type="button" class="input-group-text cursor-pointer">
 | 
			
		||||
                    <i class="{{ $prefixClickableIcon }}"></i>
 | 
			
		||||
                </button>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            {{-- Textarea --}}
 | 
			
		||||
            <textarea
 | 
			
		||||
                {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
                {!! $textareaAttributes !!}
 | 
			
		||||
            ></textarea>
 | 
			
		||||
 | 
			
		||||
            {{-- Sufijos (Derecha) --}}
 | 
			
		||||
            @if ($suffixClickableIcon)
 | 
			
		||||
                <button type="button" class="input-group-text cursor-pointer">
 | 
			
		||||
                    <i class="{{ $suffixClickableIcon }}"></i>
 | 
			
		||||
                </button>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            @if ($suffixIcon)
 | 
			
		||||
                <span class="input-group-text"><i class="{{ $suffixIcon }}"></i></span>
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            @if ($suffix)
 | 
			
		||||
                <span class="input-group-text">{{ $suffix }}</span>
 | 
			
		||||
            @endif
 | 
			
		||||
        </div>
 | 
			
		||||
    @else
 | 
			
		||||
        {{-- Textarea simple o flotante --}}
 | 
			
		||||
        <textarea
 | 
			
		||||
            {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
 | 
			
		||||
            {!! $textareaAttributes !!}
 | 
			
		||||
        ></textarea>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    {{-- Etiqueta flotante --}}
 | 
			
		||||
    @if ($floating)
 | 
			
		||||
        <label for="{{ $inputId }}">{{ $label }}</label>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    {{-- Longitud máxima permitida --}}
 | 
			
		||||
    @if ($maxlength)
 | 
			
		||||
        <small class="form-text float-end text-muted">Máximo {{ $maxlength }} caracteres</small>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    {{-- Texto de ayuda --}}
 | 
			
		||||
    @if ($helperText)
 | 
			
		||||
        <div class="form-text">{{ $helperText }}</div>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    {{-- Mensaje de error --}}
 | 
			
		||||
    @if ($hasError)
 | 
			
		||||
        <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{{-- ============================ JAVASCRIPT PARA AUTOSIZE ============================ --}}
 | 
			
		||||
@if ($autosize)
 | 
			
		||||
    <script>
 | 
			
		||||
        document.addEventListener('DOMContentLoaded', function () {
 | 
			
		||||
            let textarea = document.getElementById('{{ $inputId }}');
 | 
			
		||||
            if (textarea) {
 | 
			
		||||
                textarea.addEventListener('input', function () {
 | 
			
		||||
                    this.style.height = 'auto';
 | 
			
		||||
                    this.style.height = this.scrollHeight + 'px';
 | 
			
		||||
                });
 | 
			
		||||
                textarea.dispatchEvent(new Event('input')); // Auto-trigger on load
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
@endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user