Commit df0b1caa authored by Mahmoud Aglan's avatar Mahmoud Aglan

Rethink facility grid UI: spreadsheet-style with row/col/all selectors

Replace the broken flex+grid layout with a proper CSS Grid that includes
header gutters for row/column selection buttons. Cells now fill naturally.
Corner button selects all, row/col headers toggle-select entire rows/columns.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent a088e747
......@@ -92,13 +92,19 @@
}
.facility-cell--selected {
background-color: oklch(0.65 0.2 250 / 0.2);
box-shadow: inset 0 0 0 2.5px oklch(0.55 0.2 250 / 0.7);
background-color: oklch(0.92 0.06 250) !important;
box-shadow: inset 0 0 0 2px oklch(0.60 0.18 250 / 0.6);
}
.facility-cell--drop-target {
background-color: oklch(0.7 0.15 155 / 0.2);
box-shadow: inset 0 0 0 2.5px oklch(0.55 0.15 155 / 0.6);
background-color: oklch(0.92 0.06 155) !important;
box-shadow: inset 0 0 0 2px oklch(0.55 0.15 155 / 0.6);
animation: pulse-drop 1s ease-in-out infinite;
}
@keyframes pulse-drop {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
}
......
......@@ -293,7 +293,7 @@ class="relative border rounded-xl p-3 sm:p-4 text-start transition-all hover:sha
</div>
{{-- Grid Area --}}
<div class="flex-1 overflow-auto p-3 sm:p-4 flex flex-col">
<div class="flex-1 overflow-auto p-3 sm:p-4">
@if(!empty($gridSegments))
@php
$maxRow = collect($gridSegments)->max('row') ?? 0;
......@@ -304,139 +304,164 @@ class="relative border rounded-xl p-3 sm:p-4 text-start transition-all hover:sha
$surfaceType = $facility->type->value ?? 'other';
@endphp
<div class="overflow-x-auto flex-1 flex flex-col">
<div class="facility-surface facility-surface--{{ $surfaceType }} min-w-[400px] flex-1"
style="grid-template-columns: repeat({{ $cols }}, minmax(0, 1fr)); grid-template-rows: repeat({{ $rows }}, 1fr);">
@foreach($gridSegments as $seg)
{{-- Spreadsheet-style grid with row/column selectors --}}
<div class="grid h-full" style="grid-template-columns: 36px repeat({{ $cols }}, 1fr); grid-template-rows: 36px repeat({{ $rows }}, 1fr);">
{{-- Corner: Select All --}}
<button @click="selectAll()" type="button"
class="flex items-center justify-center rounded-ss-lg bg-gray-100 hover:bg-blue-100 border-e border-b border-gray-200 transition-colors group"
title="{{ __('تحديد الكل') }}">
<svg class="w-4 h-4 text-gray-400 group-hover:text-blue-600 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
</button>
{{-- Column headers --}}
@for($c = 0; $c < $cols; $c++)
<button @click="selectColByIndex({{ $c }})" type="button"
class="flex items-center justify-center bg-gray-50 hover:bg-blue-50 border-e border-b border-gray-200 text-[11px] font-semibold text-gray-500 hover:text-blue-700 transition-colors {{ $c === $cols - 1 ? 'rounded-se-lg' : '' }}"
title="{{ __('تحديد العمود') }} {{ $c + 1 }}">
C{{ $c + 1 }}
</button>
@endfor
{{-- Rows with row headers --}}
@for($r = 0; $r < $rows; $r++)
{{-- Row header --}}
<button @click="selectRowByIndex({{ $r }})" type="button"
class="flex items-center justify-center bg-gray-50 hover:bg-blue-50 border-e border-b border-gray-200 text-[11px] font-semibold text-gray-500 hover:text-blue-700 transition-colors {{ $r === $rows - 1 ? 'rounded-es-lg' : '' }}"
title="{{ __('تحديد الصف') }} {{ $r + 1 }}">
R{{ $r + 1 }}
</button>
{{-- Row cells --}}
@for($c = 0; $c < $cols; $c++)
@php
$segAssignment = collect($assignments)->first(fn($a) => in_array($seg['id'], $a['segment_ids'] ?? []));
$isOccupied = $segAssignment !== null;
$isExisting = $isOccupied && ($segAssignment['type'] ?? '') === 'existing';
$isNewGroup = $isOccupied && ($segAssignment['type'] ?? '') === 'group';
$isNewTrainer = $isOccupied && ($segAssignment['type'] ?? '') === 'trainer';
$seg = collect($gridSegments)->first(fn($s) => ($s['row'] ?? 0) === $r && ($s['col'] ?? 0) === $c);
@endphp
<div
@dragover.prevent="highlightSegment({{ $seg['id'] }})"
@dragleave="unhighlightSegment({{ $seg['id'] }})"
@drop.prevent="dropOnSegment({{ $seg['id'] }})"
@click="toggleSegmentSelection({{ $seg['id'] }})"
:class="{
'facility-cell--selected': selectedSegments.includes({{ $seg['id'] }}),
'facility-cell--drop-target': highlightedSegment === {{ $seg['id'] }},
}"
class="relative border-e border-b p-3 flex flex-col transition-all duration-150 cursor-pointer
{{ !$seg['available'] ? 'facility-cell--unavailable cursor-not-allowed opacity-50' : '' }}
{{ $isExisting ? 'bg-blue-500/15' : '' }}
{{ $isNewGroup ? 'bg-emerald-500/15' : '' }}
{{ $isNewTrainer ? 'bg-purple-500/15' : '' }}
{{ !$isOccupied && $seg['available'] ? 'hover:bg-white/30' : '' }}"
@if($isGrid) style="grid-row: {{ ($seg['row'] ?? 0) + 1 }}; grid-column: {{ ($seg['col'] ?? 0) + 1 }}" @endif
>
{{-- Cell header --}}
<div class="flex items-center justify-between mb-1">
<span class="text-xs font-mono opacity-50">{{ $seg['code'] }}</span>
@if($seg['capacity'])
<span class="text-[10px] opacity-40" dir="ltr">{{ $seg['capacity'] }}p</span>
@endif
</div>
{{-- Existing reservation --}}
@if($isExisting)
<div class="flex-1 flex flex-col justify-center">
<p class="text-sm font-semibold text-blue-900 truncate">{{ $segAssignment['title'] ?? '' }}</p>
@if($segAssignment['trainer_name'] ?? null)
<p class="text-[10px] text-blue-700 mt-0.5 truncate">
<svg class="w-3 h-3 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>
{{ $segAssignment['trainer_name'] }}
</p>
@endif
@if($segAssignment['is_recurring'] ?? false)
<span class="inline-flex items-center gap-1 mt-1 text-[10px] text-purple-700">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
{{ __('متكرر') }}
</span>
@endif
</div>
<div class="flex gap-1 mt-2">
<button wire:click="cancelReservation({{ $segAssignment['reservation_id'] }})"
wire:confirm="{{ __('إلغاء هذا الحجز؟') }}"
class="text-[10px] text-red-600 hover:text-red-800 hover:underline">{{ __('إلغاء') }}</button>
@if($segAssignment['is_recurring'] ?? false)
<button wire:click="cancelSeries({{ $segAssignment['reservation_id'] }})"
wire:confirm="{{ __('إلغاء كل حجوزات هذه السلسلة المستقبلية؟') }}"
class="text-[10px] text-red-600 hover:text-red-800 hover:underline">{{ __('إلغاء السلسلة') }}</button>
@if($seg)
@php
$segAssignment = collect($assignments)->first(fn($a) => in_array($seg['id'], $a['segment_ids'] ?? []));
$isOccupied = $segAssignment !== null;
$isExisting = $isOccupied && ($segAssignment['type'] ?? '') === 'existing';
$isNewGroup = $isOccupied && ($segAssignment['type'] ?? '') === 'group';
$isNewTrainer = $isOccupied && ($segAssignment['type'] ?? '') === 'trainer';
$isLastCol = $c === $cols - 1;
$isLastRow = $r === $rows - 1;
@endphp
<div
@dragover.prevent="highlightSegment({{ $seg['id'] }})"
@dragleave="unhighlightSegment({{ $seg['id'] }})"
@drop.prevent="dropOnSegment({{ $seg['id'] }})"
@click="toggleSegmentSelection({{ $seg['id'] }})"
:class="{
'facility-cell--selected': selectedSegments.includes({{ $seg['id'] }}),
'facility-cell--drop-target': highlightedSegment === {{ $seg['id'] }},
}"
class="relative flex flex-col p-3 transition-all duration-100 cursor-pointer
{{ !$isLastCol ? 'border-e' : '' }}
{{ !$isLastRow ? 'border-b' : '' }}
border-gray-200
{{ !$seg['available'] ? 'facility-cell--unavailable cursor-not-allowed opacity-50' : '' }}
{{ $isExisting ? 'bg-blue-500/10' : '' }}
{{ $isNewGroup ? 'bg-emerald-500/10' : '' }}
{{ $isNewTrainer ? 'bg-purple-500/10' : '' }}
{{ !$isOccupied && $seg['available'] ? 'hover:bg-gray-100/80' : '' }}
{{ $isLastCol && $isLastRow ? 'rounded-ee-lg' : '' }}"
>
{{-- Cell code label --}}
<span class="text-[10px] font-mono text-gray-400 absolute top-1.5 end-2">{{ $seg['code'] }}</span>
{{-- Existing reservation --}}
@if($isExisting)
<div class="flex-1 flex flex-col justify-center items-center text-center">
<p class="text-sm font-semibold text-blue-900 truncate max-w-full">{{ $segAssignment['title'] ?? '' }}</p>
@if($segAssignment['trainer_name'] ?? null)
<p class="text-[10px] text-blue-700 mt-0.5 truncate max-w-full">
<svg class="w-3 h-3 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>
{{ $segAssignment['trainer_name'] }}
</p>
@endif
@if($segAssignment['is_recurring'] ?? false)
<span class="inline-flex items-center gap-1 mt-1 text-[10px] text-purple-700">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
{{ __('متكرر') }}
</span>
@endif
</div>
<div class="flex gap-1 justify-center mt-1">
<button wire:click="cancelReservation({{ $segAssignment['reservation_id'] }})"
wire:confirm="{{ __('إلغاء هذا الحجز؟') }}"
class="text-[10px] text-red-600 hover:text-red-800 hover:underline">{{ __('إلغاء') }}</button>
@if($segAssignment['is_recurring'] ?? false)
<button wire:click="cancelSeries({{ $segAssignment['reservation_id'] }})"
wire:confirm="{{ __('إلغاء كل حجوزات هذه السلسلة المستقبلية؟') }}"
class="text-[10px] text-red-500 hover:text-red-700 hover:underline">{{ __('السلسلة') }}</button>
@endif
</div>
{{-- New group --}}
@elseif($isNewGroup)
<div class="flex-1 flex flex-col justify-center items-center text-center">
<p class="text-sm font-semibold text-emerald-900 truncate max-w-full">{{ $segAssignment['group_name'] ?? '' }}</p>
@if($segAssignment['implied_trainer'] ?? null)
<p class="text-[10px] text-emerald-700 mt-0.5 truncate max-w-full">{{ $segAssignment['implied_trainer'] }}</p>
@endif
<span class="text-[9px] text-emerald-500 mt-1">{{ __('جديد') }}</span>
</div>
@php $assignIdx = collect($assignments)->search(fn($a) => ($a['type'] ?? '') === 'group' && ($a['group_id'] ?? null) === ($segAssignment['group_id'] ?? -1)); @endphp
@if($assignIdx !== false)
<button wire:click="removeAssignment({{ $assignIdx }})" class="text-[10px] text-red-500 hover:text-red-700 hover:underline mt-1 text-center">{{ __('إزالة') }}</button>
@endif
</div>
{{-- New group assignment (unsaved) --}}
@elseif($isNewGroup)
<div class="flex-1 flex flex-col justify-center">
<p class="text-sm font-semibold text-emerald-900 truncate">{{ $segAssignment['group_name'] ?? '' }}</p>
@if($segAssignment['implied_trainer'] ?? null)
<p class="text-[10px] text-emerald-700 mt-0.5 truncate">
<svg class="w-3 h-3 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>
{{ $segAssignment['implied_trainer'] }} ({{ __('تلقائي') }})
</p>
{{-- New trainer --}}
@elseif($isNewTrainer)
<div class="flex-1 flex flex-col justify-center items-center text-center">
<p class="text-sm font-semibold text-purple-900 truncate max-w-full">{{ $segAssignment['trainer_name'] ?? '' }}</p>
<span class="text-[9px] text-purple-500 mt-1">{{ __('مدرب') }}</span>
</div>
@php $assignIdx = collect($assignments)->search(fn($a) => ($a['type'] ?? '') === 'trainer' && ($a['trainer_id'] ?? null) === ($segAssignment['trainer_id'] ?? -1)); @endphp
@if($assignIdx !== false)
<button wire:click="removeAssignment({{ $assignIdx }})" class="text-[10px] text-red-500 hover:text-red-700 hover:underline mt-1 text-center">{{ __('إزالة') }}</button>
@endif
<span class="inline-flex items-center mt-1 text-[10px] text-emerald-600">{{ __('جديد — لم يُحفظ بعد') }}</span>
</div>
@php $assignIdx = collect($assignments)->search(fn($a) => ($a['type'] ?? '') === 'group' && ($a['group_id'] ?? null) === ($segAssignment['group_id'] ?? -1)); @endphp
@if($assignIdx !== false)
<button wire:click="removeAssignment({{ $assignIdx }})" class="text-[10px] text-red-600 hover:text-red-800 hover:underline mt-1">{{ __('إزالة') }}</button>
@endif
{{-- New trainer assignment (unsaved) --}}
@elseif($isNewTrainer)
<div class="flex-1 flex flex-col justify-center">
<p class="text-sm font-semibold text-purple-900 truncate">{{ $segAssignment['trainer_name'] ?? '' }}</p>
<span class="inline-flex items-center mt-1 text-[10px] text-purple-700">{{ __('مدرب — لم يُحفظ بعد') }}</span>
</div>
@php $assignIdx = collect($assignments)->search(fn($a) => ($a['type'] ?? '') === 'trainer' && ($a['trainer_id'] ?? null) === ($segAssignment['trainer_id'] ?? -1)); @endphp
@if($assignIdx !== false)
<button wire:click="removeAssignment({{ $assignIdx }})" class="text-[10px] text-red-600 hover:text-red-800 hover:underline mt-1">{{ __('إزالة') }}</button>
{{-- Unavailable --}}
@elseif(!$seg['available'])
<div class="flex-1 flex items-center justify-center">
<span class="text-xs text-gray-400">{{ __('غير متاح') }}</span>
</div>
{{-- Empty / available --}}
@else
<div class="flex-1 flex items-center justify-center">
<span class="text-xs text-gray-400" x-show="!selectedSegments.includes({{ $seg['id'] }})">{{ __('اسحب هنا') }}</span>
<span class="text-xs text-blue-600 font-medium" x-show="selectedSegments.includes({{ $seg['id'] }})">✓ {{ __('محدد') }}</span>
</div>
@endif
{{-- Unavailable --}}
@elseif(!$seg['available'])
<div class="flex-1 flex items-center justify-center">
<span class="text-xs text-gray-400">{{ __('غير متاح') }}</span>
</div>
{{-- Empty / available --}}
@else
<div class="flex-1 flex items-center justify-center">
<span class="text-xs opacity-40" x-show="!selectedSegments.includes({{ $seg['id'] }})">{{ __('اسحب مجموعة هنا') }}</span>
<span class="text-xs text-blue-700 font-medium" x-show="selectedSegments.includes({{ $seg['id'] }})">{{ __('محدد') }} ✓</span>
</div>
@endif
</div>
@endforeach
</div>
</div>
{{-- Legend --}}
<div class="mt-4 flex flex-wrap items-center gap-3 sm:gap-4 text-xs text-gray-500">
<span class="flex items-center gap-1.5"><span class="w-3.5 h-3.5 rounded bg-surface-field/60 border border-line-field"></span> {{ __('متاح') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3.5 h-3.5 rounded bg-blue-500/15 border border-blue-400/50"></span> {{ __('محجوز') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3.5 h-3.5 rounded bg-emerald-500/15 border border-emerald-400/50"></span> {{ __('جديد (لم يُحفظ)') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3.5 h-3.5 rounded bg-purple-500/15 border border-purple-400/50"></span> {{ __('مدرب') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3.5 h-3.5 rounded facility-cell--unavailable border border-gray-300"></span> {{ __('غير متاح') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3.5 h-3.5 rounded facility-cell--selected"></span> {{ __('محدد') }}</span>
</div>
@else
{{-- Empty grid cell (no segment) --}}
<div class="bg-gray-50/50 {{ $c < $cols - 1 ? 'border-e' : '' }} {{ $r < $rows - 1 ? 'border-b' : '' }} border-gray-200"></div>
@endif
@endfor
@endfor
</div>
{{-- Multi-select helper --}}
<div x-show="selectedSegments.length > 0" x-transition class="mt-4 bg-blue-50/80 border border-blue-200 rounded-xl p-3 sm:p-4">
<p class="text-sm font-medium text-blue-800 mb-2">
{{ __('تم تحديد') }} <span x-text="selectedSegments.length" class="font-bold"></span> {{ __('خلية') }}
</p>
<p class="text-xs text-blue-600 mb-3">{{ __('اسحب مجموعة أو مدرب على أي خلية محددة لتعيينهم جميعاً') }}</p>
<div class="flex flex-wrap gap-2">
<button @click="selectedSegments = []" class="text-xs text-gray-500 hover:text-gray-700 border border-gray-300 px-2 py-1.5 rounded">{{ __('إلغاء التحديد') }}</button>
<button @click="selectRow()" class="text-xs text-blue-600 hover:text-blue-700 border border-blue-300 px-2 py-1.5 rounded">{{ __('تحديد الصف') }}</button>
<button @click="selectCol()" class="text-xs text-blue-600 hover:text-blue-700 border border-blue-300 px-2 py-1.5 rounded">{{ __('تحديد العمود') }}</button>
<button @click="selectAll()" class="text-xs text-blue-600 hover:text-blue-700 border border-blue-300 px-2 py-1.5 rounded">{{ __('تحديد الكل') }}</button>
{{-- Legend + selection info --}}
<div class="mt-3 flex flex-wrap items-center justify-between gap-3">
<div class="flex flex-wrap items-center gap-3 text-[11px] text-gray-500">
<span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-sm bg-white border border-gray-200"></span> {{ __('متاح') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-sm bg-blue-500/15 border border-blue-300/50"></span> {{ __('محجوز') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-sm bg-emerald-500/15 border border-emerald-300/50"></span> {{ __('جديد') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-sm bg-purple-500/15 border border-purple-300/50"></span> {{ __('مدرب') }}</span>
<span class="flex items-center gap-1.5"><span class="w-3 h-3 rounded-sm facility-cell--selected"></span> {{ __('محدد') }}</span>
</div>
<div x-show="selectedSegments.length > 0" x-transition class="flex items-center gap-2">
<span class="text-xs font-medium text-blue-700">
<span x-text="selectedSegments.length"></span> {{ __('محدد') }}
</span>
<button @click="selectedSegments = []" type="button" class="text-[11px] text-gray-500 hover:text-red-600 underline">{{ __('مسح') }}</button>
</div>
</div>
@else
<div class="text-center py-12">
<svg class="w-12 h-12 sm:w-16 sm:h-16 text-gray-300 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"/></svg>
......@@ -586,13 +611,45 @@ class="text-[10px] text-red-600 hover:text-red-800 hover:underline">{{ __('إل
}
},
selectRowByIndex(rowIndex) {
const segments = @json($gridSegments);
const rowSegs = segments.filter(s => s.row === rowIndex && s.available).map(s => s.id);
const allSelected = rowSegs.every(id => this.selectedSegments.includes(id));
if (allSelected) {
this.selectedSegments = this.selectedSegments.filter(id => !rowSegs.includes(id));
} else {
this.selectedSegments = [...new Set([...this.selectedSegments, ...rowSegs])];
}
},
selectColByIndex(colIndex) {
const segments = @json($gridSegments);
const colSegs = segments.filter(s => s.col === colIndex && s.available).map(s => s.id);
const allSelected = colSegs.every(id => this.selectedSegments.includes(id));
if (allSelected) {
this.selectedSegments = this.selectedSegments.filter(id => !colSegs.includes(id));
} else {
this.selectedSegments = [...new Set([...this.selectedSegments, ...colSegs])];
}
},
selectAll() {
const segments = @json($gridSegments);
const allAvailable = segments.filter(s => s.available).map(s => s.id);
const allSelected = allAvailable.every(id => this.selectedSegments.includes(id));
if (allSelected) {
this.selectedSegments = [];
} else {
this.selectedSegments = allAvailable;
}
},
selectRow() {
if (this.selectedSegments.length === 0) return;
const segments = @json($gridSegments);
const firstSelected = segments.find(s => s.id === this.selectedSegments[0]);
if (!firstSelected) return;
const rowSegs = segments.filter(s => s.row === firstSelected.row && s.available).map(s => s.id);
this.selectedSegments = [...new Set([...this.selectedSegments, ...rowSegs])];
this.selectRowByIndex(firstSelected.row);
},
selectCol() {
......@@ -600,13 +657,7 @@ class="text-[10px] text-red-600 hover:text-red-800 hover:underline">{{ __('إل
const segments = @json($gridSegments);
const firstSelected = segments.find(s => s.id === this.selectedSegments[0]);
if (!firstSelected) return;
const colSegs = segments.filter(s => s.col === firstSelected.col && s.available).map(s => s.id);
this.selectedSegments = [...new Set([...this.selectedSegments, ...colSegs])];
},
selectAll() {
const segments = @json($gridSegments);
this.selectedSegments = segments.filter(s => s.available).map(s => s.id);
this.selectColByIndex(firstSelected.col);
},
}));
</script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment