feat(project-map): rework right panel per feedback

1. Hide the project navigation bar (kept in DOM via 'hidden', not deleted)
2. Move the tabs into the panel header where the 'Map' title was
3. (tabs setActiveTab logic already correct — recompiled)
4. Make the phases/layers panel collapsible via an Alpine toggle button
5. Replace all emoji icons with blade-heroicons (<x-heroicon-o-*>)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 11:44:48 +02:00
parent 3fd4d62df1
commit de68638d7c
@@ -1,11 +1,20 @@
<div x-data="{ formFullscreen: $wire.entangle('formFullscreen') }" <div x-data="{ formFullscreen: $wire.entangle('formFullscreen') }"
class="flex flex-col lg:flex-row gap-0 h-screen p-1"> class="flex flex-col lg:flex-row gap-0 h-screen p-1">
<!-- Columna izquierda: Mapa --> <!-- Columna izquierda: Mapa -->
<div x-show="!formFullscreen" x-cloak class="w-full lg:w-2/3 flex-1 relative"> <div x-show="!formFullscreen" x-cloak x-data="{ showLayers: true }" class="w-full lg:w-2/3 flex-1 relative">
<div id="map" style="height: 100%; min-height: 500px; width: 100%;" wire:ignore></div> <div id="map" style="height: 100%; min-height: 500px; width: 100%;" wire:ignore></div>
<!-- Toggle del panel de fases/capas -->
<button @click="showLayers = !showLayers"
class="absolute top-2 right-2 z-[1001] btn btn-sm btn-circle shadow-lg"
title="{{ __('Show/hide panel') }}">
<x-heroicon-o-x-mark class="w-5 h-5" x-show="showLayers" />
<x-heroicon-o-bars-3 class="w-5 h-5" x-show="!showLayers" x-cloak />
</button>
<!-- Panel lateral de capas --> <!-- Panel lateral de capas -->
<div class="absolute top-2 right-2 z-[1000] bg-base-100 rounded-box shadow-xl p-4 w-72 border border-base-300 text-sm max-h-[calc(100vh-4rem)] overflow-y-auto"> <div x-show="showLayers" x-transition
class="absolute top-14 right-2 z-[1000] bg-base-100 rounded-box shadow-xl p-4 w-72 border border-base-300 text-sm max-h-[calc(100vh-4rem)] overflow-y-auto">
<h3 class="font-semibold text-base mb-2">{{ __('Phases and layers') }}</h3> <h3 class="font-semibold text-base mb-2">{{ __('Phases and layers') }}</h3>
<div class="space-y-3"> <div class="space-y-3">
@foreach($phases as $phase) @foreach($phases as $phase)
@@ -35,11 +44,11 @@
{{-- Botón para ir a gestión de capas de esta fase --}} {{-- Botón para ir a gestión de capas de esta fase --}}
<div class="mt-1 ml-7"> <div class="mt-1 ml-7">
<a href="{{ route('layers.manage', [$project, $phase]) }}" class="btn btn-xs btn-outline btn-primary"> <a href="{{ route('layers.manage', [$project, $phase]) }}" class="btn btn-xs btn-outline btn-primary gap-1">
✏️ {{ __('Manage Layers') }} <x-heroicon-o-pencil-square class="w-3.5 h-3.5" /> {{ __('Manage Layers') }}
</a> </a>
<a href="{{ route('phases.progress', $phase) }}" class="btn btn-xs btn-outline"> <a href="{{ route('phases.progress', $phase) }}" class="btn btn-xs btn-outline gap-1">
📊 {{ __('Progress') }} <x-heroicon-o-chart-bar class="w-3.5 h-3.5" /> {{ __('Progress') }}
</a> </a>
</div> </div>
</div> </div>
@@ -50,7 +59,7 @@
<div class="mt-3"> <div class="mt-3">
<label class="flex items-center gap-2 text-xs cursor-pointer"> <label class="flex items-center gap-2 text-xs cursor-pointer">
<input type="checkbox" wire:change="toggleFeatureImages" @if($showFeatureImages) checked @endif class="checkbox checkbox-xs checkbox-primary" /> <input type="checkbox" wire:change="toggleFeatureImages" @if($showFeatureImages) checked @endif class="checkbox checkbox-xs checkbox-primary" />
🖼️ {{ __('Show images on map') }} <x-heroicon-o-photo class="w-4 h-4" /> {{ __('Show images on map') }}
@if($featureImageMarkers) @if($featureImageMarkers)
<span class="badge badge-xs">{{ count($featureImageMarkers) }}</span> <span class="badge badge-xs">{{ count($featureImageMarkers) }}</span>
@endif @endif
@@ -59,14 +68,14 @@
{{-- Botones generales --}} {{-- Botones generales --}}
<div class="mt-2 space-y-1"> <div class="mt-2 space-y-1">
<a href="{{ route('projects.media', $project) }}" class="btn btn-sm btn-outline w-full"> <a href="{{ route('projects.media', $project) }}" class="btn btn-sm btn-outline w-full gap-1">
📁 {{ __('Project files') }} <x-heroicon-o-folder class="w-4 h-4" /> {{ __('Project files') }}
</a> </a>
<button wire:click="$dispatch('centerMap')" class="btn btn-sm btn-outline w-full"> <button wire:click="$dispatch('centerMap')" class="btn btn-sm btn-outline w-full gap-1">
📍 {{ __('Centered in project') }} <x-heroicon-o-map-pin class="w-4 h-4" /> {{ __('Centered in project') }}
</button> </button>
<button onclick="getUserLocation()" class="btn btn-sm btn-outline w-full"> <button onclick="getUserLocation()" class="btn btn-sm btn-outline w-full gap-1">
🧭 {{ __('My location') }} <x-heroicon-o-viewfinder-circle class="w-4 h-4" /> {{ __('My location') }}
</button> </button>
</div> </div>
</div> </div>
@@ -76,42 +85,9 @@
<div class="w-full lg:w-1/3 transition-all duration-300" :class="{'lg:w-full': formFullscreen}"> <div class="w-full lg:w-1/3 transition-all duration-300" :class="{'lg:w-full': formFullscreen}">
<div class="card bg-base-100 shadow-xl h-full flex flex-col"> <div class="card bg-base-100 shadow-xl h-full flex flex-col">
<div class="card-body overflow-y-auto flex-1"> <div class="card-body overflow-y-auto flex-1">
<div class="flex justify-between items-center mb-2"> <div class="flex justify-between items-center gap-2 mb-4">
<h2 class="card-title">{{ __('Map') }}</h2>
<button wire:click="toggleFullscreen" class="btn btn-circle btn-sm" title="{{ __('Fullscreen') }}">
<span x-text="formFullscreen ? '✕' : '⤢'"></span>
</button>
</div>
<!-- Project navigation bar -->
<div class="flex flex-wrap gap-1 mb-3">
<a href="{{ route('projects.dashboard', $project) }}"
class="btn btn-xs {{ request()->routeIs('projects.dashboard') ? 'btn-primary' : 'btn-outline' }}">
📊 {{ __('Dashboard') }}
</a>
<a href="{{ route('projects.map', $project) }}"
class="btn btn-xs {{ request()->routeIs('projects.map') ? 'btn-primary' : 'btn-outline' }}">
🗺️ {{ __('Map') }}
</a>
<a href="{{ route('projects.gantt', $project) }}"
class="btn btn-xs {{ request()->routeIs('projects.gantt') ? 'btn-primary' : 'btn-outline' }}">
📅 {{ __('Gantt') }}
</a>
<a href="{{ route('projects.report', $project) }}"
class="btn btn-xs {{ request()->routeIs('projects.report') ? 'btn-primary' : 'btn-outline' }}">
📄 {{ __('Report') }}
</a>
<a href="{{ route('projects.issues', $project) }}"
class="btn btn-xs {{ request()->routeIs('projects.issues') ? 'btn-error' : 'btn-outline' }} gap-1">
⚠️ {{ __('Issues') }}
@if($openIssuesCount > 0)
<span class="badge badge-error badge-xs">{{ $openIssuesCount }}</span>
@endif
</a>
</div>
<!-- Tabs --> <!-- Tabs -->
<div class="tabs box mb-4"> <div class="tabs tabs-boxed flex-wrap">
<button wire:click="setActiveTab('edit')" class="tab {{ $activeTab === 'edit' ? 'tab-active' : '' }}">{{ __('Edit') }}</button> <button wire:click="setActiveTab('edit')" class="tab {{ $activeTab === 'edit' ? 'tab-active' : '' }}">{{ __('Edit') }}</button>
<button wire:click="setActiveTab('features')" class="tab {{ $activeTab === 'features' ? 'tab-active' : '' }}">{{ __('Features') }}</button> <button wire:click="setActiveTab('features')" class="tab {{ $activeTab === 'features' ? 'tab-active' : '' }}">{{ __('Features') }}</button>
<button wire:click="setActiveTab('inspections')" class="tab {{ $activeTab === 'inspections' ? 'tab-active' : '' }}">{{ __('Inspections') }}</button> <button wire:click="setActiveTab('inspections')" class="tab {{ $activeTab === 'inspections' ? 'tab-active' : '' }}">{{ __('Inspections') }}</button>
@@ -122,6 +98,37 @@
@endif @endif
</button> </button>
</div> </div>
<button wire:click="toggleFullscreen" class="btn btn-circle btn-sm shrink-0" title="{{ __('Fullscreen') }}">
<span x-text="formFullscreen ? '✕' : '⤢'"></span>
</button>
</div>
<!-- Project navigation bar (hidden for now, kept for later) -->
<div class="hidden flex-wrap gap-1 mb-3">
<a href="{{ route('projects.dashboard', $project) }}"
class="btn btn-xs gap-1 {{ request()->routeIs('projects.dashboard') ? 'btn-primary' : 'btn-outline' }}">
<x-heroicon-o-squares-2x2 class="w-3.5 h-3.5" /> {{ __('Dashboard') }}
</a>
<a href="{{ route('projects.map', $project) }}"
class="btn btn-xs gap-1 {{ request()->routeIs('projects.map') ? 'btn-primary' : 'btn-outline' }}">
<x-heroicon-o-map class="w-3.5 h-3.5" /> {{ __('Map') }}
</a>
<a href="{{ route('projects.gantt', $project) }}"
class="btn btn-xs gap-1 {{ request()->routeIs('projects.gantt') ? 'btn-primary' : 'btn-outline' }}">
<x-heroicon-o-calendar-days class="w-3.5 h-3.5" /> {{ __('Gantt') }}
</a>
<a href="{{ route('projects.report', $project) }}"
class="btn btn-xs gap-1 {{ request()->routeIs('projects.report') ? 'btn-primary' : 'btn-outline' }}">
<x-heroicon-o-document-text class="w-3.5 h-3.5" /> {{ __('Report') }}
</a>
<a href="{{ route('projects.issues', $project) }}"
class="btn btn-xs gap-1 {{ request()->routeIs('projects.issues') ? 'btn-error' : 'btn-outline' }}">
<x-heroicon-o-exclamation-triangle class="w-3.5 h-3.5" /> {{ __('Issues') }}
@if($openIssuesCount > 0)
<span class="badge badge-error badge-xs">{{ $openIssuesCount }}</span>
@endif
</a>
</div>
<!-- Tab Content --> <!-- Tab Content -->
<div class="tab-content"> <div class="tab-content">
@@ -148,14 +155,14 @@
<input type="text" wire:model="editResponsible" class="input input-bordered input-sm" placeholder="{{ __('Name of responsible') }}" /> <input type="text" wire:model="editResponsible" class="input input-bordered input-sm" placeholder="{{ __('Name of responsible') }}" />
</div> </div>
<button wire:click="saveFeatureProgress" class="btn btn-primary btn-sm w-full mb-3"> <button wire:click="saveFeatureProgress" class="btn btn-primary btn-sm w-full mb-3 gap-1">
💾 {{ __('Save progress') }} <x-heroicon-o-check-circle class="w-4 h-4" /> {{ __('Save progress') }}
</button> </button>
{{-- Gestor de archivos del feature --}} {{-- Gestor de archivos del feature --}}
<details class="mb-3 border rounded-lg"> <details class="mb-3 border rounded-lg">
<summary class="text-xs font-semibold cursor-pointer p-2 bg-base-200 rounded-t-lg"> <summary class="text-xs font-semibold cursor-pointer p-2 bg-base-200 rounded-t-lg">
📎 {{ __('Files of element') }} <x-heroicon-o-paper-clip class="w-4 h-4 inline" /> {{ __('Files of element') }}
</summary> </summary>
<div class="p-2"> <div class="p-2">
@livewire('media-manager', [ @livewire('media-manager', [
@@ -244,7 +251,7 @@
@endif @endif
@else @else
<div class="text-center text-gray-400 py-8"> <div class="text-center text-gray-400 py-8">
<p class="text-lg">👆</p> <x-heroicon-o-cursor-arrow-rays class="w-10 h-10 mx-auto opacity-30" />
<p>{{ __('Click on a map element or search above to edit it') }}</p> <p>{{ __('Click on a map element or search above to edit it') }}</p>
</div> </div>
@endif @endif
@@ -274,7 +281,7 @@
<td>{{ $feature->responsible ?? '-' }}</td> <td>{{ $feature->responsible ?? '-' }}</td>
<td>{{ $feature->template?->name ?? '-' }}</td> <td>{{ $feature->template?->name ?? '-' }}</td>
<td class="justify-end"> <td class="justify-end">
<button class="btn btn-xs btn-outline btn-primary">✏️</button> <button class="btn btn-xs btn-outline btn-primary"><x-heroicon-o-pencil class="w-3.5 h-3.5" /></button>
</td> </td>
</tr> </tr>
@endforeach @endforeach
@@ -283,7 +290,7 @@
</div> </div>
@else @else
<div class="text-center text-gray-400 py-8"> <div class="text-center text-gray-400 py-8">
<p class="text-lg">📋</p> <x-heroicon-o-clipboard-document-list class="w-10 h-10 mx-auto opacity-30" />
<p>{{ __('No elements in this project') }}</p> <p>{{ __('No elements in this project') }}</p>
</div> </div>
@endif @endif
@@ -309,7 +316,7 @@
<td>{{ $inspection->template->name }}</td> <td>{{ $inspection->template->name }}</td>
<td>{{ $inspection->user->name }}</td> <td>{{ $inspection->user->name }}</td>
<td class="justify-end"> <td class="justify-end">
<button class="btn btn-xs btn-outline btn-info">👁️</button> <button class="btn btn-xs btn-outline btn-info"><x-heroicon-o-eye class="w-3.5 h-3.5" /></button>
</td> </td>
</tr> </tr>
@endforeach @endforeach
@@ -318,7 +325,7 @@
</div> </div>
@else @else
<div class="text-center text-gray-400 py-8"> <div class="text-center text-gray-400 py-8">
<p class="text-lg">📋</p> <x-heroicon-o-clipboard-document-list class="w-10 h-10 mx-auto opacity-30" />
<p>{{ __('No inspections registered') }}</p> <p>{{ __('No inspections registered') }}</p>
</div> </div>
@endif @endif