feat: aggiunge archivio e modal alla lavagna post-it
This commit is contained in:
parent
ab7b804d08
commit
b9b9e999f7
|
|
@ -48,6 +48,10 @@ class PostItGestione extends Page
|
|||
|
||||
public string $tecnicoScopeFilter = 'tutti';
|
||||
|
||||
public ?string $selectedGroupModalKey = null;
|
||||
|
||||
public string $selectedGroupModalMode = 'open';
|
||||
|
||||
/** @var array<int,string> */
|
||||
public array $riaperturaNote = [];
|
||||
|
||||
|
|
@ -68,7 +72,7 @@ public function mount(): void
|
|||
$focus = (int) request()->query('focus_post_it', 0);
|
||||
$this->focusPostItId = $focus > 0 ? $focus : null;
|
||||
|
||||
if (in_array((string) request()->query('tab'), ['storico', 'lavagna'], true)) {
|
||||
if (in_array((string) request()->query('tab'), ['storico', 'lavagna', 'archivio'], true)) {
|
||||
$this->activeTab = (string) request()->query('tab');
|
||||
}
|
||||
}
|
||||
|
|
@ -245,53 +249,76 @@ public function getRecentiVisibiliProperty()
|
|||
->values();
|
||||
}
|
||||
|
||||
public function getRecentiApertiVisibiliProperty()
|
||||
{
|
||||
return $this->recentiVisibili
|
||||
->filter(fn(ChiamataPostIt $postIt): bool => (string) $postIt->stato !== 'chiusa')
|
||||
->values();
|
||||
}
|
||||
|
||||
public function getRecentiChiusiVisibiliProperty()
|
||||
{
|
||||
return $this->recentiVisibili
|
||||
->filter(fn(ChiamataPostIt $postIt): bool => (string) $postIt->stato === 'chiusa')
|
||||
->values();
|
||||
}
|
||||
|
||||
public function getRecentiRaggruppatiProperty()
|
||||
{
|
||||
$groups = [];
|
||||
return $this->buildGroupedCollection($this->recentiApertiVisibili);
|
||||
}
|
||||
|
||||
foreach ($this->recentiVisibili as $postIt) {
|
||||
if ($this->isInternalPostIt($postIt)) {
|
||||
continue;
|
||||
}
|
||||
public function getRecentiChiusiRaggruppatiProperty()
|
||||
{
|
||||
return $this->buildGroupedCollection($this->recentiChiusiVisibili);
|
||||
}
|
||||
|
||||
$groupKey = $this->buildGroupedPostItKey($postIt);
|
||||
if (isset($groups[$groupKey])) {
|
||||
$groups[$groupKey]['items'][] = $postIt;
|
||||
$groups[$groupKey]['count']++;
|
||||
$groups[$groupKey]['last_at'] = optional($postIt->chiamata_il)->format('d/m/Y H:i') ?: '-';
|
||||
$groups[$groupKey]['latest'] = $this->resolveLatestGroupedPostIt($groups[$groupKey]['items']);
|
||||
$groups[$groupKey]['caller_label'] = $this->resolveGroupedCallerLabel($groups[$groupKey]['items']);
|
||||
continue;
|
||||
}
|
||||
public function openGroupModal(string $modalKey, string $mode = 'open'): void
|
||||
{
|
||||
$this->selectedGroupModalKey = $modalKey;
|
||||
$this->selectedGroupModalMode = in_array($mode, ['open', 'closed'], true) ? $mode : 'open';
|
||||
}
|
||||
|
||||
$groups[$groupKey] = [
|
||||
'key' => $groupKey,
|
||||
'items' => [$postIt],
|
||||
'count' => 1,
|
||||
'latest' => $postIt,
|
||||
'caller_label' => $postIt->nome_chiamante ?: 'Chiamante non identificato',
|
||||
'phone' => (string) ($postIt->telefono ?? ''),
|
||||
'first_at' => optional($postIt->chiamata_il)->format('d/m/Y H:i') ?: '-',
|
||||
'last_at' => optional($postIt->chiamata_il)->format('d/m/Y H:i') ?: '-',
|
||||
];
|
||||
public function closeGroupModal(): void
|
||||
{
|
||||
$this->selectedGroupModalKey = null;
|
||||
$this->selectedGroupModalMode = 'open';
|
||||
}
|
||||
|
||||
public function getSelectedGroupModalProperty(): ?array
|
||||
{
|
||||
if ($this->selectedGroupModalKey === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return collect(array_values($groups))
|
||||
->map(function (array $group): array {
|
||||
usort($group['items'], function (ChiamataPostIt $left, ChiamataPostIt $right): int {
|
||||
return ($right->chiamata_il?->getTimestamp() ?? 0) <=> ($left->chiamata_il?->getTimestamp() ?? 0);
|
||||
});
|
||||
$groups = $this->selectedGroupModalMode === 'closed'
|
||||
? $this->recentiChiusiRaggruppati
|
||||
: $this->recentiRaggruppati;
|
||||
|
||||
$group['latest'] = $this->resolveLatestGroupedPostIt($group['items']);
|
||||
$oldest = collect($group['items'])
|
||||
->sortBy(fn(ChiamataPostIt $item) => $item->chiamata_il?->getTimestamp() ?? 0)
|
||||
->first();
|
||||
$group['first_at'] = optional($oldest?->chiamata_il)->format('d/m/Y H:i') ?: '-';
|
||||
$group['last_at'] = optional($group['latest']->chiamata_il)->format('d/m/Y H:i') ?: '-';
|
||||
return $groups->firstWhere('modal_key', $this->selectedGroupModalKey);
|
||||
}
|
||||
|
||||
return $group;
|
||||
public function getSelectedGroupModalDaysProperty()
|
||||
{
|
||||
$group = $this->selectedGroupModal;
|
||||
if (! is_array($group)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return collect($group['items'])
|
||||
->groupBy(function (ChiamataPostIt $item): string {
|
||||
return $item->chiamata_il?->format('d/m/Y') ?: 'Data non disponibile';
|
||||
})
|
||||
->map(function ($items, string $day): array {
|
||||
$sorted = collect($items)
|
||||
->sortByDesc(fn(ChiamataPostIt $item) => $item->chiamata_il?->getTimestamp() ?? 0)
|
||||
->values();
|
||||
|
||||
return [
|
||||
'day' => $day,
|
||||
'items' => $sorted,
|
||||
];
|
||||
})
|
||||
->sortByDesc(fn(array $group) => $group['latest']->chiamata_il?->getTimestamp() ?? 0)
|
||||
->values();
|
||||
}
|
||||
|
||||
|
|
@ -585,6 +612,11 @@ private function buildTicketDescriptionFromPostIt(int $postItId, ChiamataPostIt
|
|||
|
||||
private function buildGroupedPostItKey(ChiamataPostIt $postIt): string
|
||||
{
|
||||
$rubricaId = $this->resolveGroupedRubricaId($postIt);
|
||||
if ($rubricaId !== null) {
|
||||
return 'rubrica:' . $rubricaId;
|
||||
}
|
||||
|
||||
$phone = $this->normalizeGroupedPhone((string) ($postIt->telefono ?? ''));
|
||||
if ($phone !== '') {
|
||||
return 'phone:' . $phone;
|
||||
|
|
@ -600,6 +632,11 @@ private function isInternalPostIt(ChiamataPostIt $postIt): bool
|
|||
return $this->isInternalSmdrMessage($message);
|
||||
}
|
||||
|
||||
$phone = preg_replace('/\D+/', '', (string) ($postIt->telefono ?? ''));
|
||||
if (is_string($phone) && $phone !== '' && $this->isKnownPbxExtension($phone)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -625,6 +662,16 @@ private function normalizeGroupedPhone(string $phone): string
|
|||
return preg_replace('/\D+/', '', $phone) ?: '';
|
||||
}
|
||||
|
||||
private function resolveGroupedRubricaId(ChiamataPostIt $postIt): ?int
|
||||
{
|
||||
$rubricaId = (int) ($postIt->rubrica_id ?? 0);
|
||||
if ($rubricaId > 0) {
|
||||
return $rubricaId;
|
||||
}
|
||||
|
||||
return $this->resolveRubricaIdByPhone((string) ($postIt->telefono ?? ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int,ChiamataPostIt> $items
|
||||
*/
|
||||
|
|
@ -643,6 +690,17 @@ private function resolveLatestGroupedPostIt(array $items): ChiamataPostIt
|
|||
private function resolveGroupedCallerLabel(array $items): string
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
$rubricaId = $this->resolveGroupedRubricaId($item);
|
||||
if ($rubricaId) {
|
||||
$rubrica = RubricaUniversale::query()->find($rubricaId, ['ragione_sociale', 'nome', 'cognome']);
|
||||
if ($rubrica) {
|
||||
$label = trim((string) ($rubrica->ragione_sociale ?: (($rubrica->nome ?? '') . ' ' . ($rubrica->cognome ?? ''))));
|
||||
if ($label !== '') {
|
||||
return $label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$label = trim((string) ($item->nome_chiamante ?? ''));
|
||||
if ($label !== '') {
|
||||
return $label;
|
||||
|
|
@ -652,6 +710,70 @@ private function resolveGroupedCallerLabel(array $items): string
|
|||
return 'Chiamante non identificato';
|
||||
}
|
||||
|
||||
private function resolveGroupedPhoneLabel(array $items): string
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
$phone = trim((string) ($item->telefono ?? ''));
|
||||
if ($phone !== '') {
|
||||
return $phone;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function buildGroupedCollection($items)
|
||||
{
|
||||
$groups = [];
|
||||
|
||||
foreach ($items as $postIt) {
|
||||
if ($this->isInternalPostIt($postIt)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$groupKey = $this->buildGroupedPostItKey($postIt);
|
||||
if (isset($groups[$groupKey])) {
|
||||
$groups[$groupKey]['items'][] = $postIt;
|
||||
$groups[$groupKey]['count']++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$groups[$groupKey] = [
|
||||
'key' => $groupKey,
|
||||
'modal_key' => md5($groupKey),
|
||||
'items' => [$postIt],
|
||||
'count' => 1,
|
||||
'latest' => $postIt,
|
||||
'caller_label' => $postIt->nome_chiamante ?: 'Chiamante non identificato',
|
||||
'phone' => (string) ($postIt->telefono ?? ''),
|
||||
'first_at' => optional($postIt->chiamata_il)->format('d/m/Y H:i') ?: '-',
|
||||
'last_at' => optional($postIt->chiamata_il)->format('d/m/Y H:i') ?: '-',
|
||||
];
|
||||
}
|
||||
|
||||
return collect(array_values($groups))
|
||||
->map(function (array $group): array {
|
||||
usort($group['items'], function (ChiamataPostIt $left, ChiamataPostIt $right): int {
|
||||
return ($right->chiamata_il?->getTimestamp() ?? 0) <=> ($left->chiamata_il?->getTimestamp() ?? 0);
|
||||
});
|
||||
|
||||
$group['latest'] = $this->resolveLatestGroupedPostIt($group['items']);
|
||||
$oldest = collect($group['items'])
|
||||
->sortBy(fn(ChiamataPostIt $item) => $item->chiamata_il?->getTimestamp() ?? 0)
|
||||
->first();
|
||||
$group['first_at'] = optional($oldest?->chiamata_il)->format('d/m/Y H:i') ?: '-';
|
||||
$group['last_at'] = optional($group['latest']->chiamata_il)->format('d/m/Y H:i') ?: '-';
|
||||
$group['caller_label'] = $this->resolveGroupedCallerLabel($group['items']);
|
||||
$group['phone'] = $this->resolveGroupedPhoneLabel($group['items']);
|
||||
$group['visible_items'] = collect($group['items'])->take(4)->values()->all();
|
||||
$group['hidden_count'] = max(0, count($group['items']) - count($group['visible_items']));
|
||||
|
||||
return $group;
|
||||
})
|
||||
->sortByDesc(fn(array $group) => $group['latest']->chiamata_il?->getTimestamp() ?? 0)
|
||||
->values();
|
||||
}
|
||||
|
||||
public function richiediClickToCallDaMessaggio(int $messageId): void
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
<button type="button" wire:click="$set('activeTab', 'lavagna')" class="rounded-md px-3 py-1.5 text-xs font-medium {{ $activeTab === 'lavagna' ? 'bg-amber-600 text-white' : 'bg-amber-50 text-amber-900 hover:bg-amber-100' }}">
|
||||
Lavagna chiamate
|
||||
</button>
|
||||
<button type="button" wire:click="$set('activeTab', 'archivio')" class="rounded-md px-3 py-1.5 text-xs font-medium {{ $activeTab === 'archivio' ? 'bg-slate-700 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}">
|
||||
Archivio chiusi
|
||||
</button>
|
||||
<button type="button" wire:click="$set('activeTab', 'smdr')" class="rounded-md px-3 py-1.5 text-xs font-medium {{ $activeTab === 'smdr' ? 'bg-indigo-700 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }}">
|
||||
Chiamate Tecniche SMDR
|
||||
</button>
|
||||
|
|
@ -118,10 +121,10 @@
|
|||
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
@forelse($this->recentiRaggruppati as $gruppo)
|
||||
@php($box = $gruppo['latest'])
|
||||
<article class="rounded-2xl border border-amber-200 bg-[#fff4b8] p-4 shadow-sm">
|
||||
<article class="flex min-h-[320px] flex-col rounded-2xl border border-amber-200 bg-[#fff4b8] p-4 shadow-sm">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div class="text-sm font-semibold uppercase tracking-wide text-amber-900">{{ $box->oggetto ?: 'Post-it chiamate' }}</div>
|
||||
<div class="text-sm font-semibold uppercase tracking-wide text-amber-900">{{ $box->direzione === 'in_uscita' ? 'Chiamata in uscita' : 'Chiamata in arrivo' }}</div>
|
||||
<div class="mt-1 text-sm text-amber-950">
|
||||
{{ $gruppo['caller_label'] }}
|
||||
@if($gruppo['phone'] !== '')
|
||||
|
|
@ -140,27 +143,32 @@
|
|||
Aperto dal {{ $gruppo['first_at'] }} al {{ $gruppo['last_at'] }}
|
||||
</div>
|
||||
|
||||
<div class="mt-4 space-y-3 border-t border-amber-300 pt-3">
|
||||
@foreach($gruppo['items'] as $item)
|
||||
<div class="rounded-xl border border-amber-300 bg-amber-50/70 p-3">
|
||||
<div class="mt-4 flex-1 space-y-2 border-t border-amber-300 pt-3">
|
||||
@foreach($gruppo['visible_items'] as $item)
|
||||
<div class="rounded-xl border border-amber-300 bg-amber-50/70 p-2.5">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div class="text-sm font-medium text-amber-950">{{ $item->oggetto ?: 'Senza oggetto' }}</div>
|
||||
<div class="text-xs text-amber-800">{{ optional($item->chiamata_il)->format('d/m/Y H:i') }}</div>
|
||||
<div class="text-xs font-medium text-amber-950">{{ $item->oggetto ?: 'Senza oggetto' }}</div>
|
||||
<div class="text-[11px] text-amber-800">{{ optional($item->chiamata_il)->format('d/m/Y H:i') }}</div>
|
||||
</div>
|
||||
<span class="rounded-md bg-white/70 px-2 py-1 text-[11px] text-amber-900">{{ $item->stato }}</span>
|
||||
</div>
|
||||
|
||||
@if($item->stabile)
|
||||
<div class="mt-1 text-xs text-amber-900">{{ $item->stabile->denominazione ?: ('Stabile #' . $item->stabile->id) }}</div>
|
||||
<div class="mt-1 text-[11px] text-amber-900">{{ $item->stabile->denominazione ?: ('Stabile #' . $item->stabile->id) }}</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-2 whitespace-pre-wrap text-xs text-amber-950">{{ $item->nota }}</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
@if($gruppo['hidden_count'] > 0)
|
||||
<div class="rounded-xl border border-dashed border-amber-300 bg-white/50 p-2.5 text-[11px] text-amber-900">
|
||||
Altre {{ $gruppo['hidden_count'] }} chiamate visibili nel dettaglio.
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<x-filament::button size="sm" color="warning" wire:click="openGroupModal('{{ $gruppo['modal_key'] }}', 'open')">Vedi dettaglio</x-filament::button>
|
||||
<a href="{{ $this->getPostItPageUrl((int) $box->id) }}" class="inline-flex items-center rounded-md bg-amber-700 px-3 py-1.5 text-xs font-medium text-white hover:bg-amber-600">Apri Post-it</a>
|
||||
@if($box->ticket_id)
|
||||
<a href="{{ \App\Filament\Pages\Supporto\TicketGestione::getUrl(panel: 'admin-filament') }}#ticket-{{ (int) $box->ticket_id }}" class="inline-flex items-center rounded-md border border-amber-400 bg-white/70 px-3 py-1.5 text-xs text-amber-900">Apri ticket</a>
|
||||
|
|
@ -172,6 +180,49 @@
|
|||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@elseif($activeTab === 'archivio')
|
||||
<div class="rounded-xl border border-slate-200 bg-slate-50/50 p-4">
|
||||
<div class="mb-4">
|
||||
<h2 class="text-base font-semibold text-slate-900">Archivio Post-it chiusi</h2>
|
||||
<p class="text-sm text-slate-700">I Post-it chiusi restano collegati al numero o al nominativo e possono essere riaperti quando serve. Anche qui le chiamate interne sono escluse.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
@forelse($this->recentiChiusiRaggruppati as $gruppo)
|
||||
@php($box = $gruppo['latest'])
|
||||
<article class="flex min-h-[260px] flex-col rounded-2xl border border-slate-200 bg-white p-4 shadow-sm">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div class="text-sm font-semibold uppercase tracking-wide text-slate-800">Archivio chiuso</div>
|
||||
<div class="mt-1 text-sm text-slate-950">{{ $gruppo['caller_label'] }}@if($gruppo['phone'] !== '') - {{ $gruppo['phone'] }}@endif</div>
|
||||
</div>
|
||||
<span class="rounded-full bg-slate-100 px-2.5 py-1 text-xs font-semibold text-slate-700">{{ $gruppo['count'] }} chiusi</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 text-xs text-slate-600">Dal {{ $gruppo['first_at'] }} al {{ $gruppo['last_at'] }}</div>
|
||||
|
||||
<div class="mt-4 flex-1 space-y-2 border-t border-slate-200 pt-3">
|
||||
@foreach($gruppo['visible_items'] as $item)
|
||||
<div class="rounded-xl border border-slate-200 bg-slate-50 p-2.5">
|
||||
<div class="text-xs font-medium text-slate-900">{{ $item->oggetto ?: 'Senza oggetto' }}</div>
|
||||
<div class="text-[11px] text-slate-600">{{ optional($item->chiamata_il)->format('d/m/Y H:i') }}</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@if($gruppo['hidden_count'] > 0)
|
||||
<div class="rounded-xl border border-dashed border-slate-300 bg-white p-2.5 text-[11px] text-slate-700">Altri {{ $gruppo['hidden_count'] }} Post-it chiusi nel dettaglio.</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<x-filament::button size="sm" color="gray" wire:click="openGroupModal('{{ $gruppo['modal_key'] }}', 'closed')">Vedi dettaglio</x-filament::button>
|
||||
<a href="{{ $this->getPostItPageUrl((int) $box->id) }}" class="inline-flex items-center rounded-md border border-slate-300 px-3 py-1.5 text-xs text-slate-700">Apri ultimo Post-it</a>
|
||||
</div>
|
||||
</article>
|
||||
@empty
|
||||
<div class="rounded-lg border border-dashed border-slate-300 bg-white p-4 text-sm text-slate-700 md:col-span-2 xl:col-span-3">Nessun Post-it chiuso disponibile in archivio.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@elseif(in_array($activeTab, ['smdr', 'csta'], true))
|
||||
<div class="rounded-xl border bg-white p-4">
|
||||
@php($isCstaTab = $activeTab === 'csta')
|
||||
|
|
@ -333,6 +384,49 @@
|
|||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($this->selectedGroupModal)
|
||||
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
|
||||
<div class="max-h-[85vh] w-full max-w-5xl overflow-hidden rounded-2xl bg-white shadow-2xl">
|
||||
<div class="flex items-center justify-between border-b px-5 py-4">
|
||||
<div>
|
||||
<div class="text-sm font-semibold text-slate-900">{{ $this->selectedGroupModal['caller_label'] }}@if($this->selectedGroupModal['phone'] !== '') - {{ $this->selectedGroupModal['phone'] }}@endif</div>
|
||||
<div class="text-xs text-slate-500">{{ $this->selectedGroupModal['count'] }} chiamate totali · {{ $selectedGroupModalMode === 'closed' ? 'archivio chiusi' : 'lavagna aperti' }}</div>
|
||||
</div>
|
||||
<button type="button" wire:click="closeGroupModal" class="rounded-md bg-slate-100 px-3 py-1.5 text-xs text-slate-700 hover:bg-slate-200">Chiudi</button>
|
||||
</div>
|
||||
|
||||
<div class="max-h-[70vh] overflow-y-auto p-5">
|
||||
<div class="space-y-5">
|
||||
@foreach($this->selectedGroupModalDays as $day)
|
||||
<section>
|
||||
<div class="mb-2 text-xs font-semibold uppercase tracking-wide text-slate-500">{{ $day['day'] }}</div>
|
||||
<div class="space-y-3">
|
||||
@foreach($day['items'] as $item)
|
||||
<div class="rounded-xl border bg-slate-50 p-3">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div class="text-sm font-medium text-slate-900">{{ $item->oggetto ?: 'Senza oggetto' }}</div>
|
||||
<div class="text-xs text-slate-600">{{ optional($item->chiamata_il)->format('d/m/Y H:i') }}</div>
|
||||
</div>
|
||||
<span class="rounded-md bg-white px-2 py-1 text-[11px] text-slate-700">{{ $item->stato }}</span>
|
||||
</div>
|
||||
|
||||
@if($item->stabile)
|
||||
<div class="mt-1 text-xs text-slate-700">{{ $item->stabile->denominazione ?: ('Stabile #' . $item->stabile->id) }}</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-2 whitespace-pre-wrap text-xs text-slate-800">{{ $item->nota }}</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</section>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</x-filament-panels::page>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user