139 lines
8.4 KiB
PHP
139 lines
8.4 KiB
PHP
@php
|
|
// Expected: $unitaFieldMapping (array of {legacy,target}), $legacyUnita sample rows, provide fallback headers
|
|
$sampleRows = collect($legacyUnita ?? [])->take(5)->map(fn($r)=>(array)$r)->values();
|
|
$legacyHeaders = [];
|
|
foreach ($sampleRows as $row) { $legacyHeaders = array_unique(array_merge($legacyHeaders, array_keys($row))); }
|
|
sort($legacyHeaders);
|
|
$legacyHeaders = array_values($legacyHeaders);
|
|
if (empty($legacyHeaders)) {
|
|
try {
|
|
$importConn = \App\Models\UserSetting::get('gescon.import_conn', 'gescon_import');
|
|
if (\Illuminate\Support\Facades\Schema::connection($importConn)->hasTable('condomin')) {
|
|
$legacyHeaders = \Illuminate\Support\Facades\Schema::connection($importConn)->getColumnListing('condomin');
|
|
}
|
|
} catch (\Throwable $e) {
|
|
$legacyHeaders = [];
|
|
}
|
|
}
|
|
$existingMap = collect($unitaFieldMapping ?? [])->keyBy('legacy');
|
|
// Target fields suggestion list (simplified subset; extend as needed)
|
|
$targetFields = [
|
|
'codice_unita','scala','piano','interno','categoria_catastale','millesimi_generali','millesimi_riscaldamento','superficie','note','sezione','foglio','particella','subalterno','indirizzo','civico','mq_riscaldati','mq_non_riscaldati','tipo_unita','pertinenza_di','codice_fiscale_proprietario','codice_fiscale_inquilino'
|
|
];
|
|
@endphp
|
|
<div class="netgescon-card mt-6" id="unita-field-mapping-card">
|
|
<div class="netgescon-card-header flex items-center justify-between">
|
|
<h4 class="card-title mb-0 text-base">Mapping Campi Unità (Legacy → Archivi)</h4>
|
|
<button type="button" class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-primary" onclick="window.saveUnitaFieldMapping && window.saveUnitaFieldMapping()">Salva Mapping</button>
|
|
</div>
|
|
<div class="netgescon-card-body p-0">
|
|
<div class="flex flex-col md:flex-row">
|
|
<div class="md:w-1/2 border-r">
|
|
<div class="p-3">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h5 class="font-semibold text-sm">Campi Legacy (condomin)</h5>
|
|
<input type="text" id="filter-legacy-fields" placeholder="Filtra..." class="netgescon-input netgescon-input-sm w-40" />
|
|
</div>
|
|
<div class="max-h-none overflow-visible" id="legacy-fields-list">
|
|
@foreach($legacyHeaders as $lh)
|
|
<div class="legacy-field-row px-2 py-1 text-sm cursor-pointer hover:bg-slate-100" data-field="{{ $lh }}">{{ $lh }}</div>
|
|
@endforeach
|
|
@if(empty($legacyHeaders))
|
|
<div class="text-xs text-slate-500 py-2">Nessun campo legacy rilevato (carica anteprima Unità)</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="md:w-1/2">
|
|
<div class="p-3">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<h5 class="font-semibold text-sm">Associazione a Campi Target</h5>
|
|
<input type="text" id="filter-mapping-rows" placeholder="Filtra mapping..." class="netgescon-input netgescon-input-sm w-44" />
|
|
</div>
|
|
<div class="max-h-none overflow-visible" id="mapping-rows">
|
|
@foreach($legacyHeaders as $lh)
|
|
@php $sel = $existingMap->get($lh)['target'] ?? null; @endphp
|
|
<div class="mapping-row group border-b last:border-b-0 px-2 py-2 text-xs flex items-start gap-2" data-legacy="{{ $lh }}">
|
|
<div class="w-40 truncate" title="{{ $lh }}">{{ $lh }}</div>
|
|
<div class="flex-1">
|
|
<select class="netgescon-input netgescon-input-sm w-full target-field-select" data-legacy="{{ $lh }}">
|
|
<option value="">— da associare —</option>
|
|
@foreach($targetFields as $tf)
|
|
<option value="{{ $tf }}" @selected(($sel ?? '')===$tf)>{{ $tf }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="flex flex-col items-end gap-1"></div>
|
|
</div>
|
|
@endforeach
|
|
@if(empty($legacyHeaders))
|
|
<div class="text-xs text-slate-500 py-2">Nessun mapping configurabile.</div>
|
|
@endif
|
|
</div>
|
|
<div class="mt-3 text-right">
|
|
<button type="button" class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-primary" onclick="window.saveUnitaFieldMapping && window.saveUnitaFieldMapping()">Salva</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="border-t p-3 bg-slate-50">
|
|
<div class="text-xs text-slate-600">Suggerimento: lascia vuoto il campo target se non vuoi importare quel campo legacy. Il mapping è salvato per codice legacy e utente.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
(function(){
|
|
const filterLegacy = document.getElementById('filter-legacy-fields');
|
|
const legacyList = document.getElementById('legacy-fields-list');
|
|
const filterMap = document.getElementById('filter-mapping-rows');
|
|
const mappingRows = document.getElementById('mapping-rows');
|
|
|
|
function applyFilter(container, selector, input){
|
|
if(!container || !input) return;
|
|
const q = (input.value||'').trim().toLowerCase();
|
|
container.querySelectorAll(selector).forEach(el=>{
|
|
const txt = (el.getAttribute('data-field')||el.getAttribute('data-legacy')||'').toLowerCase();
|
|
el.style.display = !q || txt.includes(q) ? '' : 'none';
|
|
});
|
|
}
|
|
filterLegacy && filterLegacy.addEventListener('input', ()=>applyFilter(legacyList,'.legacy-field-row',filterLegacy));
|
|
filterMap && filterMap.addEventListener('input', ()=>applyFilter(mappingRows,'.mapping-row',filterMap));
|
|
|
|
// Click left side to scroll corresponding mapping row
|
|
legacyList && legacyList.addEventListener('click', e=>{
|
|
const row = e.target.closest('.legacy-field-row');
|
|
if(!row) return;
|
|
const legacy = row.getAttribute('data-field');
|
|
const targetRow = mappingRows.querySelector('.mapping-row[data-legacy="'+legacy+'"]');
|
|
if(targetRow){ targetRow.scrollIntoView({behavior:'smooth', block:'center'}); targetRow.classList.add('bg-amber-50'); setTimeout(()=>targetRow.classList.remove('bg-amber-50'),1200); }
|
|
});
|
|
|
|
window.saveUnitaFieldMapping = async function(){
|
|
// Collect mapping
|
|
const rows = mappingRows ? Array.from(mappingRows.querySelectorAll('.mapping-row')) : [];
|
|
const data = rows.map(r=>{
|
|
const legacy = r.getAttribute('data-legacy');
|
|
const target = r.querySelector('.target-field-select')?.value.trim();
|
|
return {legacy, target: target||null};
|
|
}).filter(x=>x.legacy);
|
|
try {
|
|
const csrf = document.querySelector('meta[name="csrf-token"]').content;
|
|
const legacyCodeInput = document.getElementById('import-legacy-code') || document.querySelector('input[name="legacy_code"]') || document.querySelector('input[name="_legacy_code"]');
|
|
const legacyCode = legacyCodeInput ? legacyCodeInput.value.trim() : '';
|
|
if(!legacyCode){ alert('Prima seleziona un codice legacy stabile.'); return; }
|
|
const resp = await fetch('{{ route('admin.gescon-import.mapping.save') }}', {
|
|
method:'POST',
|
|
headers:{'Content-Type':'application/json','X-CSRF-TOKEN':csrf,'Accept':'application/json'},
|
|
body: JSON.stringify({ _legacy_code: legacyCode, unita_field_mapping: JSON.stringify(data), _mapping_only: true })
|
|
});
|
|
if(resp.ok){
|
|
try { const js = await resp.json(); if(js.redirect){ window.location = js.redirect; return; } } catch(_){ }
|
|
alert('Mapping campi Unità salvato.');
|
|
} else {
|
|
alert('Errore salvataggio mapping ('+resp.status+').');
|
|
}
|
|
}catch(e){ alert('Errore: '+e.message); }
|
|
};
|
|
})();
|
|
</script>
|