Files
Nexora/app/Livewire/ProjectDocumentStatusManager.php
Javi 047e155238
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
new functions
2025-12-14 23:59:32 +01:00

317 lines
9.8 KiB
PHP

<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Project;
use App\Models\ProjectDocumentStatus;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class ProjectDocumentStatusManager extends Component
{
public $project;
public $statuses = [];
public $showForm = false;
public $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,
];
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');
}
}