Fix map layout jump, CRM/edit distributeurs, progress overlay.
Stable map grid, no fitBounds on world view, entity PATCH edit form, CRM buttons on distributors, and loading animation for sync/wait states.
This commit is contained in:
@@ -40,6 +40,56 @@
|
||||
.ei-filter-meta { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }
|
||||
.ei-filter-count { font-size: 0.75rem; color: #64748b; white-space: nowrap; }
|
||||
.ei-filter-clear { font-size: 0.72rem; opacity: 0.85; }
|
||||
|
||||
.ei-split { align-items: stretch; }
|
||||
.ei-split > .ei-map-wrap { grid-column: 1; }
|
||||
.ei-split > .ei-panel { grid-column: 2; }
|
||||
|
||||
.ei-progress-overlay {
|
||||
position: fixed; inset: 0; z-index: 1200;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
background: rgba(4, 8, 14, 0.55); backdrop-filter: blur(2px);
|
||||
}
|
||||
.ei-progress-card {
|
||||
min-width: 260px; max-width: 90vw; padding: 1.1rem 1.25rem;
|
||||
border-radius: 14px; border: 1px solid rgba(56, 189, 248, 0.35);
|
||||
background: rgba(10, 14, 20, 0.95); text-align: center;
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,0.45);
|
||||
}
|
||||
.ei-progress-card p { margin: 0.65rem 0 0.85rem; color: #e2e8f0; font-size: 0.88rem; }
|
||||
.ei-progress-spinner {
|
||||
width: 28px; height: 28px; margin: 0 auto; border-radius: 50%;
|
||||
border: 3px solid rgba(56, 189, 248, 0.2); border-top-color: #38bdf8;
|
||||
animation: ei-spin 0.75s linear infinite;
|
||||
}
|
||||
.ei-progress-bar {
|
||||
height: 4px; border-radius: 999px; background: rgba(148, 163, 184, 0.2); overflow: hidden;
|
||||
}
|
||||
.ei-progress-bar-fill {
|
||||
height: 100%; width: 35%; border-radius: 999px;
|
||||
background: linear-gradient(90deg, #0ea5e9, #38bdf8, #0ea5e9);
|
||||
background-size: 200% 100%; animation: ei-progress-slide 1.2s ease-in-out infinite;
|
||||
}
|
||||
@keyframes ei-progress-slide {
|
||||
0% { transform: translateX(-120%); }
|
||||
100% { transform: translateX(320%); }
|
||||
}
|
||||
|
||||
.ei-th-actions, .ei-td-actions { white-space: nowrap; width: 1%; }
|
||||
.ei-td-actions { display: flex; gap: 0.25rem; flex-wrap: wrap; }
|
||||
.ei-td-actions .btn { padding: 0.2rem 0.45rem; font-size: 0.68rem; }
|
||||
|
||||
.ei-drawer-edit { margin: 1rem 0; padding: 0.85rem; border-radius: 12px; border: 1px solid rgba(56,189,248,0.25); background: rgba(8,12,18,0.6); }
|
||||
.ei-drawer-edit h4 { margin: 0 0 0.65rem; font-size: 0.85rem; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.06em; }
|
||||
.ei-edit-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.55rem; }
|
||||
.ei-edit-grid label { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.68rem; color: #64748b; text-transform: uppercase; }
|
||||
.ei-edit-grid input, .ei-edit-grid select, .ei-edit-grid textarea {
|
||||
padding: 0.45rem 0.55rem; border-radius: 8px; border: 1px solid rgba(148,163,184,0.2);
|
||||
background: rgba(15,23,42,0.8); color: #e2e8f0; font-size: 0.82rem;
|
||||
}
|
||||
.ei-edit-full { grid-column: 1 / -1; }
|
||||
.ei-edit-actions { display: flex; gap: 0.5rem; margin-top: 0.75rem; }
|
||||
|
||||
.ei-split { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; min-height: 420px; }
|
||||
@media (max-width: 900px) { .ei-split { grid-template-columns: 1fr; } }
|
||||
|
||||
|
||||
@@ -221,7 +221,8 @@ window.ExportIntelMap = (function () {
|
||||
return map;
|
||||
}
|
||||
|
||||
function setFeatures(geojson) {
|
||||
function setFeatures(geojson, opts) {
|
||||
opts = opts || {};
|
||||
if (!map || !clusterLayer) return;
|
||||
clusterLayer.clearLayers();
|
||||
markersById = {};
|
||||
@@ -247,10 +248,12 @@ window.ExportIntelMap = (function () {
|
||||
|
||||
invalidateMapSize();
|
||||
|
||||
if (features.length === 1) {
|
||||
if (opts.autoFit === false) {
|
||||
map.setView([20, 10], 2);
|
||||
} else if (features.length === 1) {
|
||||
var c = features[0].geometry.coordinates;
|
||||
map.setView([c[1], c[0]], 10);
|
||||
} else if (markers.length > 1 && clusterLayer.getBounds) {
|
||||
} else if (opts.autoFit && markers.length > 1 && clusterLayer.getBounds) {
|
||||
try {
|
||||
map.fitBounds(clusterLayer.getBounds(), { padding: [40, 40], maxZoom: 12 });
|
||||
} catch (e) { /* empty */ }
|
||||
|
||||
@@ -42,6 +42,8 @@ function exportIntelApp() {
|
||||
crmModalOpen: false,
|
||||
crmCreateDeals: true,
|
||||
crmPushBusy: false,
|
||||
editMode: false,
|
||||
editForm: {},
|
||||
resultCount: 0,
|
||||
_searchTimer: null,
|
||||
|
||||
@@ -193,7 +195,19 @@ function exportIntelApp() {
|
||||
},
|
||||
|
||||
showSelectionBar() {
|
||||
return this.tab === 'map' || this.tab === 'contacts';
|
||||
return ['map', 'contacts', 'distributors', 'customers', 'caterers'].indexOf(this.tab) >= 0;
|
||||
},
|
||||
|
||||
isWorking() {
|
||||
return this.busy || this.crmPushBusy || this.mapLoading || this.drawerLoading;
|
||||
},
|
||||
|
||||
progressLabel() {
|
||||
if (this.busy && this.syncMsg) return this.syncMsg;
|
||||
if (this.crmPushBusy) return 'CRM import bezig…';
|
||||
if (this.mapLoading) return 'Kaart laden…';
|
||||
if (this.drawerLoading) return 'Profiel laden…';
|
||||
return 'Bezig…';
|
||||
},
|
||||
|
||||
entityTypeOptions() {
|
||||
@@ -343,7 +357,8 @@ function exportIntelApp() {
|
||||
window.ExportIntelMap.init('ei-map');
|
||||
window.ExportIntelMap.setOnEntityClick(function (id) { self.openEntity(id); });
|
||||
window.ExportIntelMap.setHalalMode(this.mapHalalMode);
|
||||
window.ExportIntelMap.setFeatures(bundle.entities || { features: [] });
|
||||
var autoFit = !!(this.country || this.region);
|
||||
window.ExportIntelMap.setFeatures(bundle.entities || { features: [] }, { autoFit: autoFit });
|
||||
if (this.country) {
|
||||
var t = this.territories.find((x) => x.country_iso2 === this.country);
|
||||
if (t && t.lat && t.lon) window.ExportIntelMap.flyTo(t.lat, t.lon, t.map_zoom || 6);
|
||||
@@ -456,6 +471,59 @@ function exportIntelApp() {
|
||||
this.drawerOpen = false;
|
||||
this.selected = null;
|
||||
this.drawerLoading = false;
|
||||
this.editMode = false;
|
||||
this.editForm = {};
|
||||
},
|
||||
|
||||
startEdit() {
|
||||
if (!this.selected) return;
|
||||
var s = this.selected;
|
||||
this.editForm = {
|
||||
name: s.name || '',
|
||||
entity_type: s.entity_type || '',
|
||||
country_iso2: s.country_iso2 || '',
|
||||
city: s.city || '',
|
||||
address_line: s.address_line || '',
|
||||
postal_code: s.postal_code || '',
|
||||
phone: s.phone || '',
|
||||
email: s.email || '',
|
||||
website: s.website || '',
|
||||
volume_band: s.volume_band || '',
|
||||
pipeline_stage: s.pipeline_stage || 'identified',
|
||||
confidence: s.confidence != null ? s.confidence : 50,
|
||||
halal_cert_notes: s.halal_cert_notes || '',
|
||||
cold_chain: !!s.cold_chain,
|
||||
};
|
||||
this.editMode = true;
|
||||
},
|
||||
|
||||
cancelEdit() {
|
||||
this.editMode = false;
|
||||
this.editForm = {};
|
||||
},
|
||||
|
||||
async saveEdit() {
|
||||
if (!this.selected || !this.selected.id) return;
|
||||
this.busy = true;
|
||||
this.syncMsg = 'Opslaan…';
|
||||
try {
|
||||
var r = await fetch('/api/export-intel/entities/' + this.selected.id, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(this.editForm),
|
||||
});
|
||||
if (!r.ok) {
|
||||
var err = await r.json().catch(function () { return {}; });
|
||||
throw new Error(err.detail || err.error || 'Opslaan mislukt');
|
||||
}
|
||||
this.selected = await r.json();
|
||||
this.editMode = false;
|
||||
this.syncMsg = 'Opgeslagen';
|
||||
await this.refresh();
|
||||
} catch (e) {
|
||||
this.syncMsg = 'Opslaan mislukt: ' + e.message;
|
||||
}
|
||||
this.busy = false;
|
||||
},
|
||||
|
||||
async syncKind(kind) {
|
||||
|
||||
Reference in New Issue
Block a user