null, 'name' => '', 'color' => '#6b7280', 'text_color' => '#ffffff', 'description' => '', 'allow_upload' => true, 'allow_edit' => true, 'allow_delete' => false, 'requires_approval' => false, 'is_default' => false, ]; public $showDeleteModal = false; public $statusToDelete = null; public $orderedStatusIds = []; protected $rules = [ 'formData.name' => 'required|string|min:2|max:100', 'formData.color' => 'required|string|max:7', 'formData.text_color' => 'nullable|string|max:7', 'formData.description' => 'nullable|string|max:500', 'formData.allow_upload' => 'boolean', 'formData.allow_edit' => 'boolean', 'formData.allow_delete' => 'boolean', 'formData.requires_approval' => 'boolean', 'formData.is_default' => 'boolean', ]; public function mount(Project $project) { $this->project = $project; $this->loadStatuses(); } public function loadStatuses() { $this->statuses = $this->project->documentStatuses() ->orderBy('order') ->get() ->toArray(); $this->statuses = []; $this->orderedStatusIds = collect($this->statuses)->pluck('id')->toArray(); } public function openForm($statusId = null) { $this->resetForm(); if ($statusId) { $status = ProjectDocumentStatus::find($statusId); if ($status && $status->project_id === $this->project->id) { $this->formData = [ 'id' => $status->id, 'name' => $status->name, 'color' => $status->color, 'text_color' => $status->text_color, 'description' => $status->description, 'allow_upload' => $status->allow_upload, 'allow_edit' => $status->allow_edit, 'allow_delete' => $status->allow_delete, 'requires_approval' => $status->requires_approval, 'is_default' => $status->is_default, ]; } } $this->showForm = true; } public function closeForm() { $this->showForm = false; $this->resetForm(); } public function resetForm() { $this->formData = [ 'id' => null, 'name' => '', 'color' => '#6b7280', 'text_color' => '#ffffff', 'description' => '', 'allow_upload' => true, 'allow_edit' => true, 'allow_delete' => false, 'requires_approval' => false, 'is_default' => false, ]; $this->resetErrorBag(); } public function saveStatus() { $this->validate(); try { DB::beginTransaction(); // Si se marca como default, quitar el default de otros estados if ($this->formData['is_default']) { $this->project->documentStatuses()->update(['is_default' => false]); } $data = [ 'name' => $this->formData['name'], 'color' => $this->formData['color'], 'text_color' => $this->formData['text_color'] ?: $this->calculateTextColor($this->formData['color']), 'description' => $this->formData['description'], 'allow_upload' => $this->formData['allow_upload'], 'allow_edit' => $this->formData['allow_edit'], 'allow_delete' => $this->formData['allow_delete'], 'requires_approval' => $this->formData['requires_approval'], 'is_default' => $this->formData['is_default'], ]; if ($this->formData['id']) { // Editar estado existente $status = ProjectDocumentStatus::find($this->formData['id']); if ($status && $status->project_id === $this->project->id) { $status->update($data); } } else { // Crear nuevo estado $data['project_id'] = $this->project->id; $data['slug'] = $this->generateUniqueSlug($this->formData['name']); $data['order'] = $this->project->documentStatuses()->count(); ProjectDocumentStatus::create($data); } DB::commit(); $this->loadStatuses(); $this->closeForm(); $this->dispatch('show-message', [ 'type' => 'success', 'message' => $this->formData['id'] ? 'Estado actualizado correctamente.' : 'Estado creado correctamente.' ]); } catch (\Exception $e) { DB::rollBack(); $this->dispatch('show-message', [ 'type' => 'error', 'message' => 'Error al guardar: ' . $e->getMessage() ]); } } private function generateUniqueSlug($name) { $slug = Str::slug($name); $originalSlug = $slug; $counter = 1; while ($this->project->documentStatuses()->where('slug', $slug)->exists()) { $slug = $originalSlug . '-' . $counter; $counter++; } return $slug; } private function calculateTextColor($backgroundColor) { // Convertir hex a RGB $hex = str_replace('#', '', $backgroundColor); if (strlen($hex) == 3) { $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2]; } $r = hexdec(substr($hex, 0, 2)); $g = hexdec(substr($hex, 2, 2)); $b = hexdec(substr($hex, 4, 2)); // Calcular luminosidad $luminosity = (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255; return $luminosity > 0.5 ? '#000000' : '#ffffff'; } public function confirmDelete($statusId) { $this->statusToDelete = ProjectDocumentStatus::find($statusId); if ($this->statusToDelete && $this->statusToDelete->project_id === $this->project->id) { $this->showDeleteModal = true; } } public function closeDeleteModal() { $this->showDeleteModal = false; $this->statusToDelete = null; } public function deleteStatus() { if (!$this->statusToDelete) { return; } try { // Verificar que no haya documentos con este estado if ($this->statusToDelete->documents()->exists()) { $this->dispatch('show-message', [ 'type' => 'error', 'message' => 'No se puede eliminar el estado porque hay documentos asociados.' ]); $this->closeDeleteModal(); return; } // Si es el estado por defecto, establecer otro como default if ($this->statusToDelete->is_default) { $newDefault = $this->project->documentStatuses() ->where('id', '!=', $this->statusToDelete->id) ->first(); if ($newDefault) { $newDefault->update(['is_default' => true]); } } $this->statusToDelete->delete(); $this->loadStatuses(); $this->dispatch('show-message', [ 'type' => 'success', 'message' => 'Estado eliminado correctamente.' ]); } catch (\Exception $e) { $this->dispatch('show-message', [ 'type' => 'error', 'message' => 'Error al eliminar: ' . $e->getMessage() ]); } $this->closeDeleteModal(); } public function updateOrder() { try { foreach ($this->orderedStatusIds as $index => $statusId) { $status = ProjectDocumentStatus::find($statusId); if ($status && $status->project_id === $this->project->id) { $status->update(['order' => $index]); } } $this->loadStatuses(); $this->dispatch('show-message', [ 'type' => 'success', 'message' => 'Orden actualizado correctamente.' ]); } catch (\Exception $e) { $this->dispatch('show-message', [ 'type' => 'error', 'message' => 'Error al actualizar el orden: ' . $e->getMessage() ]); } } public function moveUp($statusId) { $index = array_search($statusId, $this->orderedStatusIds); if ($index > 0) { $temp = $this->orderedStatusIds[$index]; $this->orderedStatusIds[$index] = $this->orderedStatusIds[$index - 1]; $this->orderedStatusIds[$index - 1] = $temp; $this->updateOrder(); } } public function moveDown($statusId) { $index = array_search($statusId, $this->orderedStatusIds); if ($index < count($this->orderedStatusIds) - 1) { $temp = $this->orderedStatusIds[$index]; $this->orderedStatusIds[$index] = $this->orderedStatusIds[$index + 1]; $this->orderedStatusIds[$index + 1] = $temp; $this->updateOrder(); } } public function render() { return view('livewire.project-document-status-manager'); } }