Files
construprogress/resources/views/livewire/tasks/task-form.blade.php
T
Javier Braña 534d9f8eab Fix Livewire BindingResolutionException: replace @this calls in pushed scripts with #[On] + Livewire.emit
- Add #[On] attributes to 5 Livewire component methods:
  - LayerManager::saveManualGeojson
  - ProjectForm::setLocation
  - ProjectMap::selectFeature (already had #[On])
  - TaskForm::closeModal
  - TaskKanban::updateTaskStatus
- Replace @this.method() in @push('scripts') with Livewire.emit() calls
- Fix DataTable event payloads from objects {id: X} to scalars X for:
  - FeatureTable::map-select-feature
  - InspectionTable::map-view-inspection, edit-inspection, delete-inspection
2026-08-04 13:58:56 +02:00

177 lines
12 KiB
PHP

<div x-show="showModal" x-cloak x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 scale-95" x-transition:enter-end="opacity-100 scale-100" x-transition:leave="transition ease-in duration-150" x-transition:leave-start="opacity-100 scale-100" x-transition:leave-end="opacity-0 scale-95" class="fixed inset-0 z-50 overflow-y-auto" @keydown.escape.window="closeModal">
<div class="flex min-h-full items-center justify-center p-4">
<!-- Backdrop -->
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" @click="closeModal" aria-hidden="true"></div>
<!-- Modal -->
<div class="relative w-full max-w-2xl bg-white dark:bg-gray-800 rounded-xl shadow-xl">
<form wire:submit.prevent="save" class="p-6 space-y-6">
<!-- Header -->
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">
{{ $mode === 'create' ? 'Nueva Tarea' : 'Editar Tarea' }}
</h3>
<button type="button" wire:click="closeModal" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
@if($errors->any())
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
<div class="flex">
<svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
</svg>
<ul class="ml-3 text-sm text-red-700 dark:text-red-300">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
@endif
<!-- Title -->
<div>
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Título <span class="text-red-500">*</span></label>
<input type="text" id="title" wire:model="title"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
placeholder="Título de la tarea" required autofocus>
</div>
<!-- Description -->
<div>
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Descripción</label>
<textarea id="description" wire:model="description" rows="3"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
placeholder="Detalles de la tarea..."></textarea>
</div>
<!-- Row: Project/Phase + Parent Task -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="phase_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Fase</label>
<select id="phase_id" wire:model="phase_id"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
<option value="">Sin fase</option>
@foreach($phases as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
@endforeach
</select>
</div>
<div>
<label for="parent_task_id" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Tarea Padre (subtarea de)</label>
<select id="parent_task_id" wire:model="parent_task_id"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
<option value="">Ninguna (tarea principal)</option>
@foreach($parentTasks as $pt)
<option value="{{ $pt->id }}">{{ $pt->title }}</option>
@endforeach
</select>
</div>
</div>
<!-- Row: Status + Priority -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="status" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Estado <span class="text-red-500">*</span></label>
<select id="status" wire:model="status"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" required>
@foreach($statusOptions as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label for="priority" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Prioridad <span class="text-red-500">*</span></label>
<select id="priority" wire:model="priority"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white" required>
@foreach($priorityOptions as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
@endforeach
</select>
</div>
</div>
<!-- Row: Assignee + Order -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="assigned_to" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Asignado a</label>
<select id="assigned_to" wire:model="assigned_to"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
<option value="">Sin asignar</option>
@foreach($assignees as $assignee)
<option value="{{ $assignee->id }}">{{ $assignee->name }}</option>
@endforeach
</select>
</div>
<div>
<label for="order" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Orden</label>
<input type="number" id="order" wire:model="order" min="0"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
</div>
</div>
<!-- Row: Dates -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="start_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Fecha inicio</label>
<input type="date" id="start_date" wire:model="start_date"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
</div>
<div>
<label for="due_date" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Fecha vencimiento</label>
<input type="date" id="due_date" wire:model="due_date"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white">
</div>
</div>
<!-- Row: Hours -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="estimated_hours" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Horas estimadas</label>
<input type="number" id="estimated_hours" wire:model="estimated_hours" min="0" max="10000"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
placeholder="0">
</div>
<div>
<label for="actual_hours" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Horas reales</label>
<input type="number" id="actual_hours" wire:model="actual_hours" min="0" max="10000"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
placeholder="0">
</div>
</div>
<!-- Actions -->
<div class="flex justify-end gap-3 pt-4 border-t border-gray-200 dark:border-gray-700">
<button type="button" wire:click="closeModal"
class="px-4 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors">
Cancelar
</button>
<button type="submit"
class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
{{ $mode === 'create' ? 'Crear' : 'Guardar' }}
</button>
</div>
</form>
</div>
</div>
</div>
@push('scripts')
<script>
// Close modal on Escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
Livewire.emit('close-modal');
}
});
</script>
@endpush