feat(map): listas de elementos e inspecciones con tablas Rappasoft

- FeatureTable e InspectionTable (DataTableComponent) sustituyen las tablas HTML
  de las pestañas "Elementos" e "Inspecciones" del mapa: búsqueda, orden, filtro
  (progreso) y acciones.
- Selección de elemento e "ver inspección" se comunican al ProjectMap por eventos
  (map-select-feature / map-view-inspection, vía #[On]); seleccionar abre el panel
  de edición y centra el mapa igual que antes.
- Las relaciones requieren sus FKs en additionalSelects (layer_id / feature_id,
  template_id, user_id) porque Rappasoft no selecciona '*'.

Tests: MapTablesTest (3). Suite 74 passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 17:44:20 +02:00
parent 624260961b
commit 25a59e4413
5 changed files with 263 additions and 72 deletions
@@ -276,79 +276,11 @@
</div>
@endif
@elseif($activeTab === 'features')
<!-- Features Table -->
@if($allFeatures->isNotEmpty())
<div class="overflow-x-auto rounded-lg border border-base-300">
<table class="table table-sm table-zebra table-pin-rows">
<thead>
<tr>
<th>{{ __('Feature') }}</th>
<th>{{ __('Layer') }}</th>
<th>{{ __('Phase') }}</th>
<th class="text-center">{{ __('Progress') }}</th>
<th class="w-10"></th>
</tr>
</thead>
<tbody>
@foreach($allFeatures as $feature)
<tr class="hover cursor-pointer" wire:click="selectFeature({{ $feature->id }})" wire:key="feat-{{ $feature->id }}">
<td class="font-medium">{{ $feature->name }}</td>
<td>{{ $feature->layer?->name ?? '—' }}</td>
<td>{{ $feature->layer?->phase?->name ?? '—' }}</td>
<td class="text-center">
<span class="badge badge-sm {{ $feature->progress >= 100 ? 'badge-success' : ($feature->progress > 0 ? 'badge-warning' : 'badge-ghost') }}">{{ $feature->progress }}%</span>
</td>
<td class="text-right">
<x-heroicon-o-chevron-right class="w-4 h-4 opacity-40" />
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div class="text-center text-gray-400 py-8">
<x-heroicon-o-clipboard-document-list class="w-10 h-10 mx-auto opacity-30" />
<p>{{ __('No elements in this project') }}</p>
</div>
@endif
<!-- Elementos (tabla Rappasoft) -->
<livewire:projects.feature-table :project-id="$project->id" :key="'feature-table-'.$project->id" />
@elseif($activeTab === 'inspections')
<!-- Inspections Table -->
@if($allInspections->isNotEmpty())
<div class="overflow-x-auto rounded-lg border border-base-300">
<table class="table table-sm table-zebra table-pin-rows">
<thead>
<tr>
<th>{{ __('Date') }}</th>
<th>{{ __('Feature') }}</th>
<th>{{ __('Template') }}</th>
<th>{{ __('User') }}</th>
<th class="w-10"></th>
</tr>
</thead>
<tbody>
@foreach($allInspections as $inspection)
<tr class="hover" wire:key="insp-{{ $inspection->id }}">
<td class="whitespace-nowrap">{{ $inspection->created_at?->format('d/m/Y') ?? '—' }}</td>
<td class="font-medium">{{ $inspection->feature?->name ?? '—' }}</td>
<td>{{ $inspection->template?->name ?? '—' }}</td>
<td>{{ $inspection->user?->name ?? '—' }}</td>
<td class="text-right">
<button wire:click="viewInspection({{ $inspection->id }})" class="btn btn-xs btn-ghost" title="{{ __('View') }}">
<x-heroicon-o-eye class="w-4 h-4" />
</button>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div class="text-center text-gray-400 py-8">
<x-heroicon-o-clipboard-document-list class="w-10 h-10 mx-auto opacity-30" />
<p>{{ __('No inspections registered') }}</p>
</div>
@endif
<!-- Inspecciones (tabla Rappasoft) -->
<livewire:projects.inspection-table :project-id="$project->id" :key="'inspection-table-'.$project->id" />
@elseif($activeTab === 'issues')
<!-- Issues tab: render embedded IssueManager component -->
@livewire('issues.issue-manager', ['project' => $project], key('issues-tab-' . $project->id))