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:
Aissa
2026-07-19 18:47:12 +00:00
parent 6856d09cd1
commit 8d2766efb6
6 changed files with 263 additions and 14 deletions
+85 -8
View File
@@ -4,14 +4,21 @@
<link rel="stylesheet" href="/static/vendor/leaflet/leaflet.css?v=1" />
<link rel="stylesheet" href="/static/vendor/leaflet.markercluster/MarkerCluster.css?v=1" />
<link rel="stylesheet" href="/static/vendor/leaflet.markercluster/MarkerCluster.Default.css?v=1" />
<link rel="stylesheet" href="/static/css/export-intel.css?v=14" />
<link rel="stylesheet" href="/static/css/export-intel.css?v=15" />
<link rel="stylesheet" href="/static/css/export-intel-tabs.css?v=10" />
<script src="/static/vendor/leaflet/leaflet.js?v=1"></script>
<script src="/static/vendor/leaflet.markercluster/leaflet.markercluster.js?v=1"></script>
<script src="/static/js/export-intel-map.js?v=10"></script>
<script src="/static/js/export-intel-map.js?v=11"></script>
{% endblock %}
{% block content %}
<div class="ei-page" x-data="exportIntelApp()" x-init="init()">
<div class="ei-progress-overlay" x-show="isWorking()" x-cloak>
<div class="ei-progress-card">
<div class="ei-progress-spinner"></div>
<p x-text="progressLabel()"></p>
<div class="ei-progress-bar"><div class="ei-progress-bar-fill"></div></div>
</div>
</div>
<header class="ei-header page-header">
<div>
<h1>Wereldexport <span class="live-badge">Live</span></h1>
@@ -235,9 +242,9 @@
</div>
</div>
</div>
<div class="ei-map-error" x-show="mapError" x-cloak x-text="mapError"></div>
<p class="ei-map-truncated" x-show="mapTruncated && !mapLoading" x-cloak>Wereldoverzicht toont de belangrijkste ~2.500 locaties. Filter op regio of land voor meer detail.</p>
<div class="ei-split">
<div class="ei-map-error" x-show="mapError" x-cloak x-text="mapError"></div>
<p class="ei-map-truncated" x-show="mapTruncated && !mapLoading" x-cloak>Wereldoverzicht toont de belangrijkste ~2.500 locaties. Filter op regio of land voor meer detail.</p>
<div class="ei-map-wrap"><div class="ei-map-loading" x-show="mapLoading" x-cloak><span class="ei-map-spinner"></span> Kaart laden…</div><div id="ei-map"></div></div>
<div class="ei-panel">
<h3 style="margin:0 0 0.5rem;font-size:0.9rem" x-text="mapHalalMode ? 'Top halal-kansen' : 'Entities op kaart'"></h3>
@@ -292,6 +299,8 @@
</template>
<div class="ei-list-focus-actions">
<button type="button" class="btn btn-sm btn-pulse" @click="openEntity(listFocusDetail.id)">Volledig profiel →</button>
<button type="button" class="btn btn-sm btn-pulse-green" x-show="!listFocusDetail.client_id" @click="pushEntityToCrm(listFocusDetail.id)" :disabled="crmPushBusy"> CRM</button>
<a class="btn btn-sm btn-pulse" x-show="listFocusDetail.client_id" href="/clients">Open CRM</a>
<a class="btn btn-sm" x-show="listFocusDetail.maps_url" :href="listFocusDetail.maps_url" target="_blank" rel="noopener">Google Maps</a>
</div>
</div>
@@ -321,6 +330,7 @@
<th>Contact</th>
<th x-show="mapHalalMode">Score</th>
<th>Land</th>
<th class="ei-th-actions">Acties</th>
</tr>
</thead>
<tbody>
@@ -345,6 +355,11 @@
<td class="ei-contact-cell" x-text="contactPreview(e)"></td>
<td x-show="mapHalalMode"><span class="ei-halal-pill" :class="'ei-halal-'+(e.halal_score>=75?'hot':e.halal_score>=55?'warm':'mild')" x-text="Math.round(e.halal_score||0)"></span></td>
<td x-text="e.country_iso2"></td>
<td class="ei-td-actions" @click.stop>
<button type="button" class="btn btn-sm btn-pulse-green" x-show="!e.client_id" @click="pushEntityToCrm(e.id)" :disabled="crmPushBusy">CRM</button>
<a class="btn btn-sm" x-show="e.client_id" href="/clients">CRM ✓</a>
<button type="button" class="btn btn-sm" @click="openEntity(e.id)">Edit</button>
</td>
</tr>
</template>
</tbody>
@@ -372,16 +387,30 @@
<div class="ei-panel" style="border:none;background:transparent;padding:0">
<div class="ei-table-wrap">
<table class="ei-table">
<thead><tr><th>Naam</th><th>Land</th><th>Stad</th><th>E-mail</th><th>Telefoon</th><th>Confidence</th></tr></thead>
<thead><tr>
<th class="ei-th-check"><input type="checkbox" @change="toggleSelectAllVisible()" title="Alles" /></th>
<th>Naam</th><th>Land</th><th>Stad</th><th>E-mail</th><th>Telefoon</th><th>Confidence</th><th class="ei-th-actions">Acties</th>
</tr></thead>
<tbody>
<template x-for="e in entities" :key="e.id">
<tr @click="openEntity(e.id)" style="cursor:pointer">
<td x-text="e.name"></td>
<tr @click="openEntity(e.id)" :class="{ 'ei-row-selected': isSelected(e.id), 'ei-row-crm': e.client_id }" style="cursor:pointer">
<td class="ei-td-check" @click.stop>
<input type="checkbox" :checked="isSelected(e.id)" @change="toggleSelect(e.id, $event)" />
</td>
<td>
<span x-text="e.name"></span>
<span class="ei-crm-badge" x-show="e.client_id">CRM</span>
</td>
<td x-text="e.country_iso2"></td>
<td x-text="e.city||'—'"></td>
<td x-text="e.primary_email||e.email||'—'"></td>
<td x-text="e.primary_phone||e.phone||'—'"></td>
<td class="ei-confidence" x-text="e.confidence+'%'"></td>
<td class="ei-td-actions" @click.stop>
<button type="button" class="btn btn-sm btn-pulse-green" x-show="!e.client_id" @click="pushEntityToCrm(e.id)" :disabled="crmPushBusy">CRM</button>
<a class="btn btn-sm" x-show="e.client_id" href="/clients">CRM ✓</a>
<button type="button" class="btn btn-sm" @click="openEntity(e.id)">Edit</button>
</td>
</tr>
</template>
</tbody>
@@ -671,6 +700,7 @@
</div>
<template x-if="selected && !drawerLoading">
<div class="ei-drawer-body">
<div x-show="!editMode">
<div class="ei-drawer-hero">
<span class="ei-drawer-badge" :class="'ei-type-'+selected.entity_type" x-text="typeLabel(selected.entity_type)"></span>
<span class="ei-drawer-flag" x-text="selected.country_iso2"></span>
@@ -760,7 +790,54 @@
<p x-show="!(selected.contacts||[]).length" class="ei-drawer-empty">Geen contactpersonen in registry.</p>
</section>
</div>
<div class="ei-drawer-edit" x-show="editMode" x-cloak>
<h4>Bewerken</h4>
<div class="ei-edit-grid">
<label>Naam<input type="text" x-model="editForm.name" /></label>
<label>Type
<select x-model="editForm.entity_type">
<option value="distributor">Distributeur</option>
<option value="wholesaler">Groothandel</option>
<option value="importer">Importeur</option>
<option value="logistics">Logistiek</option>
<option value="contract_caterer">Cateraar</option>
<option value="restaurant">Restaurant</option>
<option value="doner_shoarma">Döner/shoarma</option>
<option value="butcher">Slager</option>
<option value="foodservice">Foodservice</option>
</select>
</label>
<label>Land (ISO2)<input type="text" maxlength="2" x-model="editForm.country_iso2" /></label>
<label>Stad<input type="text" x-model="editForm.city" /></label>
<label>Adres<input type="text" x-model="editForm.address_line" /></label>
<label>E-mail<input type="email" x-model="editForm.email" /></label>
<label>Telefoon<input type="text" x-model="editForm.phone" /></label>
<label>Website<input type="url" x-model="editForm.website" /></label>
<label>Pipeline
<select x-model="editForm.pipeline_stage">
<option value="identified">Geïdentificeerd</option>
<option value="qualified">Gekwalificeerd</option>
<option value="contacted">Gecontacteerd</option>
<option value="proposal">Voorstel</option>
<option value="won">Gewonnen</option>
<option value="lost">Verloren</option>
</select>
</label>
<label>Confidence %<input type="number" min="0" max="100" x-model.number="editForm.confidence" /></label>
<label>Volume<input type="text" x-model="editForm.volume_band" placeholder="pallet / container" /></label>
<label class="ei-edit-full">Halal notities<textarea rows="2" x-model="editForm.halal_cert_notes"></textarea></label>
<label class="ei-filter-check ei-edit-full"><input type="checkbox" x-model="editForm.cold_chain" /> Cold chain</label>
</div>
<div class="ei-edit-actions">
<button type="button" class="btn btn-sm btn-pulse-green" @click="saveEdit()" :disabled="busy">Opslaan</button>
<button type="button" class="btn btn-sm" @click="cancelEdit()">Annuleren</button>
</div>
</div>
<div class="ei-drawer-actions">
<button type="button" class="btn btn-sm btn-pulse" x-show="!editMode" @click="startEdit()">✎ Bewerken</button>
<button type="button" class="btn btn-sm" :class="selected.is_favorite ? 'btn-pulse' : ''" @click="toggleFavorite(selected.id, selected.is_favorite)">
<span x-text="selected.is_favorite ? '★ Favoriet' : '☆ Favoriet maken'"></span>
</button>
@@ -798,5 +875,5 @@
</div>
{% endblock %}
{% block scripts %}
<script src="/static/js/export-intel.js?v=13"></script>
<script src="/static/js/export-intel.js?v=14"></script>
{% endblock %}