netgescon-day0/app/Support/Livewire/SupportsRubricaLookup.php

135 lines
4.5 KiB
PHP

<?php
namespace App\Support\Livewire;
use App\Models\RubricaUniversale;
use BackedEnum;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
trait SupportsRubricaLookup
{
/**
* Normalizza input Livewire eterogenei in una stringa di ricerca stabile.
*/
protected function normalizeRubricaLookupText($value): string
{
if (is_array($value)) {
$value = Arr::first(Arr::flatten($value));
}
if ($value instanceof BackedEnum) {
$value = $value->value;
}
if (! is_scalar($value) && $value !== null) {
return '';
}
return trim((string) ($value ?? ''));
}
protected function normalizeRubricaLookupId($value): ?int
{
$normalized = $this->normalizeRubricaLookupText($value);
if ($normalized === '' || ! is_numeric($normalized)) {
return null;
}
$id = (int) $normalized;
return $id > 0 ? $id : null;
}
protected function formatRubricaLookupLabel(?RubricaUniversale $rubrica): string
{
if (! $rubrica instanceof RubricaUniversale) {
return '';
}
$label = trim((string) ($rubrica->ragione_sociale ?: $rubrica->nome_completo));
return $label !== '' ? $label : ('Rubrica #' . (int) $rubrica->id);
}
/**
* Mappa una riga rubrica in un payload leggero e riusabile nelle dropdown live.
*
* @return array<string,mixed>
*/
protected function mapRubricaLookupRow(RubricaUniversale $rubrica): array
{
$phone = trim((string) ($rubrica->telefono_ufficio ?: $rubrica->telefono_cellulare ?: $rubrica->telefono_casa));
return [
'id' => (int) $rubrica->id,
'label' => $this->formatRubricaLookupLabel($rubrica),
'email' => trim((string) ($rubrica->email ?? '')),
'phone' => $phone,
'category' => (string) ($rubrica->categoria ?? ''),
'note' => Str::limit(trim((string) ($rubrica->note ?? '')), 100),
];
}
/**
* Ricerca libera su rubrica con deduplica label e fallback sulla selezione corrente.
*
* @param array<int,string> $categories
* @return array<int,array<string,mixed>>
*/
protected function searchRubricaLookupMatches(string $raw, ?int $selectedId = null, array $categories = ['assicurazione', 'fornitore', 'altro'], int $limit = 12): array
{
$raw = $this->normalizeRubricaLookupText($raw);
if ($raw === '') {
if (($selectedId ?? 0) > 0) {
$selected = RubricaUniversale::query()->find($selectedId);
return $selected instanceof RubricaUniversale ? [$this->mapRubricaLookupRow($selected)] : [];
}
return [];
}
$needle = '%' . mb_strtolower($raw) . '%';
$digits = preg_replace('/\D+/', '', $raw) ?: '';
$seen = [];
$rows = [];
$matches = RubricaUniversale::query()
->whereNull('deleted_at')
->whereIn('categoria', $categories)
->where(function ($query) use ($needle, $digits): void {
$query->whereRaw("LOWER(COALESCE(ragione_sociale, '')) LIKE ?", [$needle])
->orWhereRaw("LOWER(COALESCE(nome, '')) LIKE ?", [$needle])
->orWhereRaw("LOWER(COALESCE(cognome, '')) LIKE ?", [$needle])
->orWhereRaw("LOWER(COALESCE(email, '')) LIKE ?", [$needle])
->orWhereRaw("LOWER(COALESCE(note, '')) LIKE ?", [$needle]);
if ($digits !== '') {
$query->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_ufficio, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", ['%' . $digits . '%'])
->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_cellulare, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", ['%' . $digits . '%']);
}
})
->orderBy('ragione_sociale')
->orderBy('cognome')
->orderBy('nome')
->limit(80)
->get();
foreach ($matches as $rubrica) {
$row = $this->mapRubricaLookupRow($rubrica);
$key = mb_strtolower(trim((string) $row['label']));
if ($key === '' || isset($seen[$key])) {
continue;
}
$seen[$key] = true;
$rows[] = $row;
if (count($rows) >= $limit) {
break;
}
}
return $rows;
}
}