first commit
This commit is contained in:
		
							
								
								
									
										63
									
								
								resources/views/components/button/basic.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								resources/views/components/button/basic.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'type' => 'button', // Tipo de botón: button, submit, reset (solo para botones)
 | 
			
		||||
    'href' => null, // URL si es un enlace
 | 
			
		||||
    'route' => null, // URL si es un enlace
 | 
			
		||||
    'target' => '_self', // Target del enlace (_self, _blank, etc.)
 | 
			
		||||
    'label' => '', // Texto del botón
 | 
			
		||||
    'size'    => 'md', // Tamaño: xs, sm, md, lg, xl
 | 
			
		||||
    'variant' => 'primary', // Color del botón (primary, secondary, success, danger, warning, info, dark)
 | 
			
		||||
    'labelStyle' => false, // Usa `btn-label-*`
 | 
			
		||||
    'outline'    => false, // Habilitar estilo outline
 | 
			
		||||
    'textStyle'  => false, // Habilitar estilo de texto
 | 
			
		||||
    'rounded'    => false, // Habilitar bordes redondeados
 | 
			
		||||
    'block'      => false, // Convertir en botón de ancho completo
 | 
			
		||||
    'waves'      => true, // Habilitar efecto Vuexy (waves-effect)
 | 
			
		||||
    'icon'         => '', // Clases del ícono (ej: 'ti ti-home')
 | 
			
		||||
    'iconOnly'     => false, // Botón solo con ícono
 | 
			
		||||
    'iconPosition' => 'left', // Posición del ícono: left, right
 | 
			
		||||
    'active'   => false, // Activar estado de botón
 | 
			
		||||
    'disabled' => false, // Deshabilitar botón
 | 
			
		||||
    'attributes' => new \Illuminate\View\ComponentAttributeBag([]), // Atributos adicionales
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // Generar clases dinámicas
 | 
			
		||||
    $classes = [
 | 
			
		||||
        'btn',
 | 
			
		||||
        $labelStyle ? "btn-label-$variant" : '',
 | 
			
		||||
        $outline ? "btn-outline-$variant" :  '',
 | 
			
		||||
        $textStyle ? "btn-text-$variant" : '',
 | 
			
		||||
        $labelStyle || $outline || $textStyle ? '' : "btn-$variant",
 | 
			
		||||
        $rounded ? 'rounded-pill' : '',
 | 
			
		||||
        $block ? 'd-block w-100' : '',
 | 
			
		||||
        $waves ? 'waves-effect' : '',
 | 
			
		||||
        $size !== 'md' ? "btn-$size" : '',
 | 
			
		||||
        $active ? 'active' : '',
 | 
			
		||||
        $disabled ? 'disabled' : '',
 | 
			
		||||
        $iconOnly ? 'btn-icon' : '',
 | 
			
		||||
    ];
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
@if ($href || $route)
 | 
			
		||||
    {{-- Si es un enlace --}}
 | 
			
		||||
    <a {{ $attributes->merge(['class' => implode(' ', array_filter($classes)), 'href' => ($href?? route($route)), 'target' => $target]) }}>
 | 
			
		||||
        @if ($icon && $iconPosition === 'left')
 | 
			
		||||
            <i class="{{ $icon }} {{ $label ? 'me-2' : '' }}"></i>
 | 
			
		||||
        @endif
 | 
			
		||||
        {{ $label }}
 | 
			
		||||
        @if ($icon && $iconPosition === 'right')
 | 
			
		||||
            <i class="{{ $icon }} {{ $label ? 'ms-2' : '' }}"></i>
 | 
			
		||||
        @endif
 | 
			
		||||
    </a>
 | 
			
		||||
@else
 | 
			
		||||
    {{-- Si es un botón --}}
 | 
			
		||||
    <button type="{{ $type }}" {{ $attributes->merge(['class' => implode(' ', array_filter($classes))]) }}>
 | 
			
		||||
        @if ($icon && $iconPosition === 'left')
 | 
			
		||||
            <i class="{{ $icon }} {{ $label ? 'me-2' : '' }}"></i>
 | 
			
		||||
        @endif
 | 
			
		||||
        {{ $label }}
 | 
			
		||||
        @if ($icon && $iconPosition === 'right')
 | 
			
		||||
            <i class="{{ $icon }} {{ $label ? 'ms-2' : '' }}"></i>
 | 
			
		||||
        @endif
 | 
			
		||||
    </button>
 | 
			
		||||
@endif
 | 
			
		||||
							
								
								
									
										46
									
								
								resources/views/components/button/group.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								resources/views/components/button/group.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'buttons' => [], // Lista de botones en formato de array
 | 
			
		||||
    'toolbar' => false, // Si es un grupo de botones estilo "toolbar"
 | 
			
		||||
    'nesting' => false, // Si hay un grupo anidado con dropdown
 | 
			
		||||
    'class' => '', // Clases adicionales
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    // Determinar si es un toolbar o un grupo simple
 | 
			
		||||
    $groupClass = $toolbar ? 'btn-toolbar' : 'btn-group';
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div class="{{ $groupClass }} {{ $class }}" role="group" aria-label="Button group">
 | 
			
		||||
    @foreach($buttons as $button)
 | 
			
		||||
        @if(isset($button['dropdown']))
 | 
			
		||||
            {{-- Botón con dropdown anidado --}}
 | 
			
		||||
            <div class="btn-group" role="group">
 | 
			
		||||
                <button id="btnGroupDrop{{ $loop->index }}" type="button" class="btn {{ $button['variant'] ?? 'btn-outline-secondary' }} dropdown-toggle waves-effect" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
 | 
			
		||||
                    @if(isset($button['icon'])) <i class="{{ $button['icon'] }} ti-md"></i> @endif
 | 
			
		||||
                    <span class="d-none d-sm-block">{{ $button['label'] ?? 'Dropdown' }}</span>
 | 
			
		||||
                </button>
 | 
			
		||||
                <div class="dropdown-menu" aria-labelledby="btnGroupDrop{{ $loop->index }}">
 | 
			
		||||
                    @foreach($button['dropdown'] as $dropdownItem)
 | 
			
		||||
                        <a class="dropdown-item waves-effect" href="{{ $dropdownItem['href'] ?? 'javascript:void(0);' }}">
 | 
			
		||||
                            {{ $dropdownItem['label'] }}
 | 
			
		||||
                        </a>
 | 
			
		||||
                    @endforeach
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        @else
 | 
			
		||||
            {{-- Botón normal o ancla --}}
 | 
			
		||||
            @if(isset($button['href']))
 | 
			
		||||
                <a href="{{ route($button['href']) }}" class="btn {{ $button['variant'] ?? 'btn-outline-secondary' }} waves-effect">
 | 
			
		||||
                    @if(isset($button['icon'])) <i class="{{ $button['icon'] }} ti-md"></i> @endif
 | 
			
		||||
                    {{ $button['label'] }}
 | 
			
		||||
                </a>
 | 
			
		||||
            @else
 | 
			
		||||
                <button type="{{ $button['type'] ?? 'button' }}" class="btn {{ $button['variant'] ?? 'btn-outline-secondary' }} waves-effect"
 | 
			
		||||
                    {{ $button['disabled'] ?? false ? 'disabled' : '' }}>
 | 
			
		||||
                    @if(isset($button['icon'])) <i class="{{ $button['icon'] }} ti-md"></i> @endif
 | 
			
		||||
                    {{ $button['label'] }}
 | 
			
		||||
                </button>
 | 
			
		||||
            @endif
 | 
			
		||||
        @endif
 | 
			
		||||
    @endforeach
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										30
									
								
								resources/views/components/button/index-off-canvas.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								resources/views/components/button/index-off-canvas.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
@php
 | 
			
		||||
    use Illuminate\Support\Str;
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
@props([
 | 
			
		||||
    'label'   => '',
 | 
			
		||||
    'tagName' => '',
 | 
			
		||||
    'icon'    => 'ti ti-pencil-plus',
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    $tagOffcanvas = ucfirst(Str::camel($tagName));
 | 
			
		||||
    $helperTag    = Str::kebab($tagName);
 | 
			
		||||
 | 
			
		||||
    $ariaControls = "'offcanvas{$tagOffcanvas}";
 | 
			
		||||
    $dataBsToggle = 'offcanvas';
 | 
			
		||||
    $dataBsTarget = "#offcanvas{$tagOffcanvas}";
 | 
			
		||||
    $onclick      = "window.formHelpers['{$helperTag}'].reloadOffcanvas('create')";
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<button
 | 
			
		||||
    type="button"
 | 
			
		||||
    class="btn btn-primary waves-effect waves-light"
 | 
			
		||||
    tabindex="0"
 | 
			
		||||
    aria-controls='{{ $ariaControls }}'
 | 
			
		||||
    data-bs-toggle="{{ $dataBsToggle }}"
 | 
			
		||||
    data-bs-target="{{ $dataBsTarget }}"
 | 
			
		||||
    onclick="{!! $onclick !!}">
 | 
			
		||||
    <span class="ti-xs {{ $icon }} me-2"></span>{{ ucfirst($label) }}
 | 
			
		||||
</button>
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'tagName' => '',
 | 
			
		||||
    'mode'    => 'create',
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    $helperTag = Str::kebab($tagName);
 | 
			
		||||
 | 
			
		||||
    $onclick = "window.formHelpers['{$helperTag}'].reloadOffcanvas('reset')";
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div class="pt-3">
 | 
			
		||||
    <button type="submit" class="btn btn-submit waves-effect waves mr-3 mb-3"></button>
 | 
			
		||||
    <button type="reset" class="btn btn-reset mr-3 mb-3" onclick="{{ $onclick }}" data-bs-dismiss="offcanvas" aria-label="Close">Cancelar</button>
 | 
			
		||||
</div>
 | 
			
		||||
@if($mode == 'delete')
 | 
			
		||||
<x-vuexy-admin::form.checkbox model="confirmDeletion" label="Confirmar eliminación" parentClass="confirm-deletion" data-always-enabled switch switch-type="square" color="danger" size="lg" with-icon />
 | 
			
		||||
@endif
 | 
			
		||||
							
								
								
									
										76
									
								
								resources/views/components/card/basic.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								resources/views/components/card/basic.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,76 @@
 | 
			
		||||
@props([
 | 
			
		||||
    'title' => '',
 | 
			
		||||
    'subtitle' => '',
 | 
			
		||||
    'image' => null,
 | 
			
		||||
    'bgColor' => '', // primary, secondary, success, danger, etc.
 | 
			
		||||
    'borderColor' => '', // primary, secondary, etc.
 | 
			
		||||
    'textColor' => 'text-dark',
 | 
			
		||||
    'shadow' => true, // true / false
 | 
			
		||||
    'dropdown' => [], // Opciones para el menú
 | 
			
		||||
    'footer' => '',
 | 
			
		||||
    'footerClass' => '', // Clase CSS personalizada para el footer
 | 
			
		||||
    'footerAlign' => 'start', // Alineación: start, center, end
 | 
			
		||||
    'footerButtons' => [], // Botones de acción
 | 
			
		||||
    'class' => 'mb-6',
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    $cardClass = 'card ' . ($shadow ? '' : 'shadow-none') . ' ' . ($bgColor ? "bg-$bgColor text-white" : '') . ' ' . ($borderColor ? "border border-$borderColor" : '') . " $class";
 | 
			
		||||
    $footerAlignment = match ($footerAlign) {
 | 
			
		||||
        'center' => 'text-center',
 | 
			
		||||
        'end' => 'text-end',
 | 
			
		||||
        default => 'text-start'
 | 
			
		||||
    };
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div class="{{ $cardClass }}">
 | 
			
		||||
    @if ($image)
 | 
			
		||||
        <img class="card-img-top" src="{{ $image }}" alt="Card image">
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    @if ($title || $subtitle || $dropdown)
 | 
			
		||||
        <div class="card-header d-flex justify-content-between">
 | 
			
		||||
            <div class="card-title mb-0">
 | 
			
		||||
                @if ($title)
 | 
			
		||||
                    <h5 class="mb-1 {{ $textColor }}">{{ $title }}</h5>
 | 
			
		||||
                @endif
 | 
			
		||||
                @if ($subtitle)
 | 
			
		||||
                    <p class="card-subtitle {{ $textColor }}">{{ $subtitle }}</p>
 | 
			
		||||
                @endif
 | 
			
		||||
            </div>
 | 
			
		||||
            @if (!empty($dropdown))
 | 
			
		||||
                <div class="dropdown">
 | 
			
		||||
                    <button class="btn btn-text-secondary rounded-pill text-muted border-0 p-2" type="button" data-bs-toggle="dropdown">
 | 
			
		||||
                        <i class="ti ti-dots-vertical"></i>
 | 
			
		||||
                    </button>
 | 
			
		||||
                    <div class="dropdown-menu dropdown-menu-end">
 | 
			
		||||
                        @foreach ($dropdown as $item)
 | 
			
		||||
                            <a class="dropdown-item" href="{{ $item['href'] ?? 'javascript:void(0);' }}">{{ $item['label'] }}</a>
 | 
			
		||||
                        @endforeach
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            @endif
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
    <div class="card-body">
 | 
			
		||||
        {{ $slot }}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {{-- Footer flexible --}}
 | 
			
		||||
    @if ($footer || !empty($footerButtons))
 | 
			
		||||
        <div class="card-footer {{ $footerClass }} {{ $footerAlignment }}">
 | 
			
		||||
            {{-- Slot de contenido directo en el footer --}}
 | 
			
		||||
            @if ($footer)
 | 
			
		||||
                {!! $footer !!}
 | 
			
		||||
            @endif
 | 
			
		||||
 | 
			
		||||
            {{-- Generación dinámica de botones --}}
 | 
			
		||||
            @foreach ($footerButtons as $button)
 | 
			
		||||
                <a href="{{ $button['href'] ?? '#' }}" class="btn btn-{{ $button['type'] ?? 'primary' }} {{ $button['class'] ?? '' }}">
 | 
			
		||||
                    {{ $button['label'] }}
 | 
			
		||||
                </a>
 | 
			
		||||
            @endforeach
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										70
									
								
								resources/views/components/file/dropzone.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								resources/views/components/file/dropzone.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
@props([
 | 
			
		||||
    // Identificador único
 | 
			
		||||
    'uid' => uniqid(),
 | 
			
		||||
 | 
			
		||||
    // Modelo para Livewire
 | 
			
		||||
    'model' => '',
 | 
			
		||||
 | 
			
		||||
    // Etiqueta y Texto de ayuda
 | 
			
		||||
    'message' => '',
 | 
			
		||||
    'note' => '',
 | 
			
		||||
 | 
			
		||||
    // Clases generales
 | 
			
		||||
    'size' => 'md', // Tamaño del textarea (xxs, xs, sm, md)
 | 
			
		||||
    'mb0' => false, // Remover margen inferior
 | 
			
		||||
    'parentClass' => '',
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@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);
 | 
			
		||||
 | 
			
		||||
    // **Manejo de errores**
 | 
			
		||||
    $errorKey = $livewireModel ?: $name;
 | 
			
		||||
    $hasError = $errors->has($errorKey);
 | 
			
		||||
    $errorClass = $hasError ? 'is-invalid' : '';
 | 
			
		||||
 | 
			
		||||
    // **Clases dinámicas**
 | 
			
		||||
    $sizeClassDropzone = match ($size) {
 | 
			
		||||
        'sm' => 'dropzone-sm',
 | 
			
		||||
        'xs' => 'dropzone-xs',
 | 
			
		||||
        'md' => 'dropzone-md',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $sizeClassButton = match ($size) {
 | 
			
		||||
        'sm' => 'btn-sm',
 | 
			
		||||
        'xs' => 'btn-xs',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<!-- Dropzone (se oculta automáticamente después de la carga) -->
 | 
			
		||||
<div class="{{ $mb0 ? '' : 'mb-4 ' }} {{ $sizeClassDropzone }}">
 | 
			
		||||
    <div class="dropzone" id="dropzone_{{ $inputId }}"">
 | 
			
		||||
        <div class="dz-message">
 | 
			
		||||
            @if ($size == 'sm' || $size == 'xs')
 | 
			
		||||
                <div class="flex items-center">
 | 
			
		||||
                    <span class="btn btn-icon {{ $sizeClassButton }} btn-label-secondary mr-2">
 | 
			
		||||
                        <i class="ti ti-upload text-base"></i>
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span>
 | 
			
		||||
                        {{ $message }}
 | 
			
		||||
                        <span class="note needsclick">{!! $note !!}</span>
 | 
			
		||||
                    </span>
 | 
			
		||||
                </div>
 | 
			
		||||
            @else
 | 
			
		||||
                {{ $message }}
 | 
			
		||||
                <span class="note needsclick">{!! $note !!}</span>
 | 
			
		||||
            @endif
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <input type="file" wire:model="pdf" {{ $livewireModel ? "wire:model=$livewireModel" : '' }} id="{{ $inputId }}" accept="application/pdf" class="d-none">
 | 
			
		||||
 | 
			
		||||
    {{-- Mensaje de error --}}
 | 
			
		||||
    @if ($hasError)
 | 
			
		||||
        <span class="text-danger">{{ $errors->first($errorKey) }}</span>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										78
									
								
								resources/views/components/offcanvas/basic.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								resources/views/components/offcanvas/basic.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
			
		||||
@php
 | 
			
		||||
    use Illuminate\Support\Str;
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
@props([
 | 
			
		||||
    'id'         => '',     // ID único para el offcanvas
 | 
			
		||||
    'title'      => '',     // Título del offcanvas
 | 
			
		||||
    'position'   => 'end',  // Posición: 'start', 'end', 'top', 'bottom'
 | 
			
		||||
    'size'       => 'md',   // Tamaño: sm, md, lg, xl
 | 
			
		||||
    'backdrop'   => true,   // Si se debe mostrar backdrop
 | 
			
		||||
    'wireIgnore' => true,   // Ignorar eventos wire (Livewire)
 | 
			
		||||
    'listener'   => '',     // Nombre del listener para reload
 | 
			
		||||
    'tagName'    => '',     // Etiqueta del formHelpers
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    $offcanvasClasses = "offcanvas offcanvas-{$position}";
 | 
			
		||||
 | 
			
		||||
    $offcanvasSize = match ($size) {
 | 
			
		||||
        'sm' => 'offcanvas-sm',
 | 
			
		||||
        'lg' => 'offcanvas-lg',
 | 
			
		||||
        'xl' => 'offcanvas-xl',
 | 
			
		||||
        default => '',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $helperTag = Str::kebab($tagName);
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
    class="{{ $offcanvasClasses }} {{ $offcanvasSize }}"
 | 
			
		||||
    tabindex="-1"
 | 
			
		||||
    id="{{ $id }}"
 | 
			
		||||
    aria-labelledby="{{ $id }}Label"
 | 
			
		||||
    {{ $wireIgnore ? 'wire:ignore.self' : '' }}
 | 
			
		||||
    data-bs-backdrop="{{ $backdrop ? 'true' : 'false' }}">
 | 
			
		||||
 | 
			
		||||
    {{-- HEADER --}}
 | 
			
		||||
    <div class="offcanvas-header border-bottom">
 | 
			
		||||
        <h5 class="offcanvas-title">{{ $title }}</h5>
 | 
			
		||||
        <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Cerrar"></button>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {{-- BODY --}}
 | 
			
		||||
    <div class="offcanvas-body p-4">
 | 
			
		||||
        {{ $slot }}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {{-- FOOTER SLOT OPCIONAL --}}
 | 
			
		||||
    @if (isset($footer))
 | 
			
		||||
        <div class="offcanvas-footer border-top p-3">
 | 
			
		||||
            {{ $footer }}
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@push('page-script')
 | 
			
		||||
    <script>
 | 
			
		||||
        // Evento para inicializar el formulario cuando se carga la página
 | 
			
		||||
        window.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
            const register{{ $tagName }}FormEvents = () => {
 | 
			
		||||
                document.addEventListener("refresh-{{ $helperTag }}-offcanvas", () => {
 | 
			
		||||
                    window.formHelpers['{{ $helperTag }}'].refresh();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                var myOffcanvas = document.getElementById('{{ $id }}')
 | 
			
		||||
 | 
			
		||||
                myOffcanvas.addEventListener('show.bs.offcanvas', function () {
 | 
			
		||||
                    setTimeout(() => window.formHelpers['{{ $helperTag }}'].reloadOffcanvas(), 20);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            window.formHelpers = window.formHelpers || {};
 | 
			
		||||
            window.formHelpers['{{ $helperTag }}'] = new FormCanvasHelper('{{ $id }}', @this);
 | 
			
		||||
 | 
			
		||||
            register{{ $tagName }}FormEvents();
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
@endpush
 | 
			
		||||
							
								
								
									
										66
									
								
								resources/views/components/table/bootstrap/manager.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								resources/views/components/table/bootstrap/manager.blade.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
@php
 | 
			
		||||
    use Illuminate\Support\Str;
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
@props([
 | 
			
		||||
    'id'              => uniqid(),
 | 
			
		||||
    'tagName'         => '',
 | 
			
		||||
    'datatableConfig' => [],
 | 
			
		||||
    'routes'          => [],
 | 
			
		||||
    'noFilterButtons' => false
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@php
 | 
			
		||||
    if($tagName)
 | 
			
		||||
        $id = 'bt-' . Str::kebab($tagName) . 's';
 | 
			
		||||
@endphp
 | 
			
		||||
 | 
			
		||||
<div id="{{ $id }}" wire:ignore>
 | 
			
		||||
    {{-- Contenedor de notificaciones --}}
 | 
			
		||||
    <div class="notification-container"></div>
 | 
			
		||||
 | 
			
		||||
    {{-- Toolbar con filtros, agrupación y herramientas --}}
 | 
			
		||||
    <div class="bt-toolbar">
 | 
			
		||||
        <div class="d-flex flex-wrap">
 | 
			
		||||
            {{ $tools ?? '' }}
 | 
			
		||||
 | 
			
		||||
            @isset($filterButtons)
 | 
			
		||||
                {{ $filterButtons }}
 | 
			
		||||
 | 
			
		||||
            @elseif($noFilterButtons == false)
 | 
			
		||||
                <div class="my-1 pr-2">
 | 
			
		||||
                    <x-vuexy-admin::button.basic variant="secondary" class="bt-btn-refresh" icon="ti ti-zoom-reset" size="sm" label="Refrescar" />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="my-1 pr-2">
 | 
			
		||||
                    <x-vuexy-admin::button.basic variant="secondary" class="bt-btn-filter-edit" label-style icon="ti ti-filter-edit" size="sm" label="Filtros" />
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="my-1 pr-2">
 | 
			
		||||
                    <x-vuexy-admin::button.basic variant="secondary" class="bt-btn-filter-cancel" text-style icon="ti ti-filter-cancel" size="sm" label="Limpiar filtros" />
 | 
			
		||||
                </div>
 | 
			
		||||
            @endisset
 | 
			
		||||
 | 
			
		||||
            {{ $postTools ?? '' }}
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {{-- Tabla con Bootstrap Table --}}
 | 
			
		||||
    <table class="bootstrap-table"></table>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@push('page-script')
 | 
			
		||||
    <script>
 | 
			
		||||
        document.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
            new BootstrapTableManager('#{{ $id }}', {!! json_encode($datatableConfig) !!});
 | 
			
		||||
 | 
			
		||||
            document.addEventListener("reload-{{ $id }}", () => {
 | 
			
		||||
                $("#{{ $id }} .bootstrap-table").bootstrapTable("refresh");
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
    @isset($routes)
 | 
			
		||||
    <script id="app-routes" type="application/json">
 | 
			
		||||
        {!! json_encode($routes) !!}
 | 
			
		||||
    </script>
 | 
			
		||||
    @endisset
 | 
			
		||||
@endpush
 | 
			
		||||
		Reference in New Issue
	
	Block a user