8d2766efb6
Stable map grid, no fitBounds on world view, entity PATCH edit form, CRM buttons on distributors, and loading animation for sync/wait states.
880 lines
48 KiB
HTML
880 lines
48 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Wereldexport · Foodlinkk B2B{% endblock %}
|
||
{% block extra_head %}
|
||
<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=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=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>
|
||
<p class="ei-subtitle">Foodlinkk B2B · wereldwijde markten · halal vlees · cateraars · distributeurs</p>
|
||
</div>
|
||
<div class="retail-actions">
|
||
<button class="btn btn-sm btn-pulse-green" @click="syncKind('world')" :disabled="busy" title="Europa · MENA · Afrika · Amerika">🌍 Sync wereld</button>
|
||
<button class="btn btn-sm btn-pulse" @click="syncKind('region')" :disabled="busy || !region" title="Sync huidige regio-filter">Sync regio</button>
|
||
<button class="btn btn-sm btn-pulse-green" @click="syncKind('all')" :disabled="busy">⚡ Sync alles</button>
|
||
<button class="btn btn-sm btn-pulse" @click="syncKind('distributors')" :disabled="busy">Distributeurs</button>
|
||
<button class="btn btn-sm btn-pulse" @click="syncKind('caterers')" :disabled="busy">Cateraars</button>
|
||
<button class="btn btn-sm btn-pulse-green" @click="syncKind('contacts')" :disabled="busy">Contacten</button>
|
||
<button class="btn btn-sm btn-pulse-purple" @click="syncKind('tenders')" :disabled="busy">TED</button>
|
||
<a class="btn btn-sm" :href="contactsExportUrl()" target="_blank">CSV export</a>
|
||
</div>
|
||
</header>
|
||
|
||
<p class="ei-sync-msg" x-show="syncMsg" x-text="syncMsg"></p>
|
||
|
||
<div class="ei-selection-bar" x-show="showSelectionBar()" x-cloak>
|
||
<div class="ei-selection-left">
|
||
<span class="ei-selection-count" x-show="selectedIds.length" x-text="selectedIds.length + ' geselecteerd'"></span>
|
||
<span class="ei-selection-hint" x-show="!selectedIds.length" x-text="tab === 'contacts' ? 'Selecteer contacten met ☑ — organisatie gaat naar CRM' : 'Selecteer rijen met ☑ voor bulk-acties'"></span>
|
||
</div>
|
||
<div class="ei-selection-actions">
|
||
<button type="button" class="btn btn-sm" @click="toggleSelectAllVisible()" title="Alles op lijst">☑ Alles</button>
|
||
<button type="button" class="btn btn-sm" x-show="selectedIds.length" @click="clearSelection()">Wis selectie</button>
|
||
<button type="button" class="btn btn-sm btn-pulse" :disabled="!selectedIds.length || busy" @click="favoriteSelection()">★ Favoriet</button>
|
||
<button type="button" class="btn btn-sm" :disabled="!selectedIds.length || busy" @click="unfavoriteSelection()">☆ Verwijder favoriet</button>
|
||
<button type="button" class="btn btn-sm btn-pulse-green" :disabled="!selectedIds.length || crmPushBusy" @click="openCrmModal()">➕ Naar CRM</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="ei-neo-kpi-row">
|
||
<div class="ei-neo-kpi">
|
||
<div class="ei-neo-kpi-top">
|
||
<div class="ei-neo-ring" style="--ring-color:#0ea5e9;--ring-pct:85"><div class="ei-neo-ring-inner">🌍</div></div>
|
||
<div><div class="ei-neo-kpi-label">Landen</div></div>
|
||
</div>
|
||
<div class="ei-neo-kpi-value" x-text="stats.territories||0"></div>
|
||
</div>
|
||
<div class="ei-neo-kpi">
|
||
<div class="ei-neo-kpi-top">
|
||
<div class="ei-neo-ring" style="--ring-color:#38bdf8;--ring-pct:70"><div class="ei-neo-ring-inner">📊</div></div>
|
||
<div><div class="ei-neo-kpi-label">Entities</div></div>
|
||
</div>
|
||
<div class="ei-neo-kpi-value" x-text="stats.entities||0"></div>
|
||
</div>
|
||
<div class="ei-neo-kpi">
|
||
<div class="ei-neo-kpi-top">
|
||
<div class="ei-neo-ring" style="--ring-color:#fbbf24;--ring-pct:75"><div class="ei-neo-ring-inner">📦</div></div>
|
||
<div><div class="ei-neo-kpi-label">Distributeurs</div></div>
|
||
</div>
|
||
<div class="ei-neo-kpi-value" x-text="stats.distributors||0"></div>
|
||
</div>
|
||
<div class="ei-neo-kpi">
|
||
<div class="ei-neo-kpi-top">
|
||
<div class="ei-neo-ring" style="--ring-color:#a78bfa;--ring-pct:65"><div class="ei-neo-ring-inner">🏢</div></div>
|
||
<div><div class="ei-neo-kpi-label">Cateraars</div></div>
|
||
</div>
|
||
<div class="ei-neo-kpi-value" x-text="stats.caterers||0"></div>
|
||
</div>
|
||
<div class="ei-neo-kpi">
|
||
<div class="ei-neo-kpi-top">
|
||
<div class="ei-neo-ring" style="--ring-color:#34d399;--ring-pct:60"><div class="ei-neo-ring-inner">📇</div></div>
|
||
<div><div class="ei-neo-kpi-label">Contacten</div></div>
|
||
</div>
|
||
<div class="ei-neo-kpi-value" x-text="stats.contacts||0"></div>
|
||
</div>
|
||
<div class="ei-neo-kpi">
|
||
<div class="ei-neo-kpi-top">
|
||
<div class="ei-neo-ring" style="--ring-color:#c084fc;--ring-pct:50"><div class="ei-neo-ring-inner">📋</div></div>
|
||
<div><div class="ei-neo-kpi-label">Tenders open</div></div>
|
||
</div>
|
||
<div class="ei-neo-kpi-value" x-text="stats.tenders_open||0"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="ei-filter-bar">
|
||
<div class="ei-filter-group ei-filter-group-geo">
|
||
<label class="ei-filter-label">Regio
|
||
<select x-model="region" @change="country=''; refresh()">
|
||
<option value="">Alle regio's</option>
|
||
<template x-for="r in regions" :key="r.code">
|
||
<option :value="r.code" x-text="r.name_nl"></option>
|
||
</template>
|
||
</select>
|
||
</label>
|
||
<label class="ei-filter-label">Land
|
||
<select x-model="country" @change="onCountryChange()">
|
||
<option value="">Alle landen</option>
|
||
<template x-for="t in territories.filter(t => !region || t.region_code===region)" :key="t.code">
|
||
<option :value="t.country_iso2" x-text="t.name_nl"></option>
|
||
</template>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<div class="ei-filter-group ei-filter-group-search">
|
||
<label class="ei-filter-label ei-filter-search-wrap">
|
||
<span class="ei-filter-sr">Zoeken</span>
|
||
<input type="search" placeholder="Organisatie, e-mail, stad…" x-model="q" @input="onSearchInput()" />
|
||
</label>
|
||
</div>
|
||
<div class="ei-filter-group ei-filter-group-maptypes" x-show="showMapTypeFilter()" x-cloak>
|
||
<span class="ei-filter-label">Kaart toont</span>
|
||
<div class="ei-type-chips" role="group" aria-label="Types op kaart">
|
||
<button type="button" class="ei-type-chip" :class="{ active: !mapTypesSelected.length }" @click="clearMapTypes()">Alle</button>
|
||
<template x-for="chip in mapTypeChips" :key="chip.v">
|
||
<button type="button" class="ei-type-chip" :class="{ active: isMapTypeActive(chip.v) }" @click="toggleMapType(chip.v)">
|
||
<span x-text="chip.icon"></span> <span x-text="chip.l"></span>
|
||
</button>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
<div class="ei-filter-group ei-filter-group-halal" x-show="showMapTypeFilter()" x-cloak>
|
||
<label class="ei-filter-check">
|
||
<input type="checkbox" x-model="mapHalalMode" @change="applyMapFilters()" />
|
||
<span>🥩 Halal-kansen modus</span>
|
||
</label>
|
||
<label class="ei-filter-label ei-halal-min" x-show="mapHalalMode">
|
||
Min. score
|
||
<input type="range" min="30" max="90" step="5" x-model.number="mapHalalMin" @change="applyMapFilters()" />
|
||
<strong x-text="mapHalalMin"></strong>
|
||
</label>
|
||
</div>
|
||
<div class="ei-filter-group ei-filter-group-collection" x-show="showCrmFilter()" x-cloak>
|
||
<label class="ei-filter-check" x-show="tab === 'map'">
|
||
<input type="checkbox" x-model="filterFavoritesOnly" @change="onFilterCollectionChange()" />
|
||
<span>★ Alleen favorieten</span>
|
||
</label>
|
||
<label class="ei-filter-label">CRM
|
||
<select x-model="filterCrmStatus" @change="onFilterCollectionChange()">
|
||
<option value="">Alle</option>
|
||
<option value="not_linked">Nog niet in CRM</option>
|
||
<option value="linked">In CRM</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<div class="ei-filter-group ei-filter-group-context" x-show="showEntityTypeFilter() || showEmailFilter()" x-cloak>
|
||
<label class="ei-filter-label" x-show="showEntityTypeFilter()">Type
|
||
<select x-model="entityTypeFilter" @change="loadTabData()">
|
||
<template x-for="o in entityTypeOptions()" :key="o.v">
|
||
<option :value="o.v" x-text="o.l"></option>
|
||
</template>
|
||
</select>
|
||
</label>
|
||
<label class="ei-filter-label" x-show="showEmailFilter()">E-mail
|
||
<select x-model="filterHasEmail" @change="loadTabData()">
|
||
<option value="">Alle</option>
|
||
<option value="yes">Met e-mail</option>
|
||
<option value="no">Zonder e-mail</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<div class="ei-filter-meta">
|
||
<span class="ei-filter-count" x-show="resultCount > 0" x-text="resultCount + ' resultaten'"></span>
|
||
<span class="ei-filter-count ei-filter-fav" x-show="stats.favorites > 0" x-text="(stats.favorites||0) + ' ★'"></span>
|
||
<button type="button" class="btn btn-sm ei-filter-clear" x-show="q || entityTypeFilter || mapTypesSelected.length || mapHalalMode || filterHasEmail || filterFavoritesOnly || filterCrmStatus" @click="clearFilters()">Wis filters</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="vtabs-layout wereldexport-workspace" style="--vt-color:#0ea5e9" x-ref="vtabsWrap">
|
||
<nav class="vtabs-nav" x-ref="vtabsNav" :style="'--vt-indicator-top:'+tabIndicatorTop+'px;--vt-indicator-h:'+tabIndicatorH+'px'">
|
||
<div class="vtabs-nav-header"><strong>Modules</strong></div>
|
||
<template x-for="t in tabs" :key="t.id">
|
||
<button type="button" class="vtab-btn vtab-btn-rich" :class="{active: tab===t.id}" :data-tab="t.id"
|
||
:style="'--tab-accent:'+t.color"
|
||
@click="setTab(t.id, $el)">
|
||
<span class="ei-vtab-icon-wrap" x-text="t.icon"></span>
|
||
<span class="ei-vtab-text">
|
||
<span class="ei-vtab-label" x-text="t.label"></span>
|
||
<span class="ei-vtab-sub" x-show="tabSub(t.id)" x-text="tabSub(t.id)"></span>
|
||
</span>
|
||
<span class="ei-vtab-meta">
|
||
<span class="ei-vtab-key" x-text="t.key"></span>
|
||
<span class="ei-vtab-badge" x-show="tabCount(t.id) > 0" x-text="tabCount(t.id)"></span>
|
||
</span>
|
||
</button>
|
||
</template>
|
||
</nav>
|
||
|
||
<div class="vtabs-content">
|
||
<!-- Kaart -->
|
||
<section x-show="tab==='map'" x-cloak>
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div>
|
||
<h2>Wereldkaart</h2>
|
||
<p>Klik pin voor preview · dubbelklik of “Volledig profiel” voor alle gegevens</p>
|
||
</div>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<div class="ei-map-legend">
|
||
<template x-if="!mapHalalMode">
|
||
<div class="ei-legend-row">
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#f59e0b">📦</i> Distributeur</span>
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#eab308">🏪</i> Groothandel</span>
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#a78bfa">🏢</i> Cateraar</span>
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#34d399">🍽️</i> Horeca</span>
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#0ea5e9">📍</i> Overig</span>
|
||
</div>
|
||
</template>
|
||
<template x-if="mapHalalMode">
|
||
<div class="ei-legend-row ei-legend-halal">
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#22c55e">●</i> Hoge kans (75+)</span>
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#eab308">●</i> Gemiddeld (55+)</span>
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#f97316">●</i> Matig (40+)</span>
|
||
<span class="ei-legend-item"><i class="ei-leg-pin" style="--c:#64748b">●</i> Laag</span>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
<div class="ei-map-empty" x-show="tab==='map' && !entities.length && !busy" x-cloak>
|
||
<div class="ei-map-empty-inner">
|
||
<strong x-show="region || country">Nog geen data op de kaart voor deze selectie</strong>
|
||
<strong x-show="!region && !country">Zoom in of filter op regio</strong>
|
||
<p>Landen staan in het systeem, maar entities + contacten komen pas na een <em>OSM sync</em> (OpenStreetMap).</p>
|
||
<p x-show="region==='africa'">Afrika: 51 landen toegevoegd — sync nog niet gedraaid voor dit continent.</p>
|
||
<div class="ei-map-empty-actions">
|
||
<button type="button" class="btn btn-sm btn-pulse-green" x-show="region" @click="syncKind('region')" :disabled="busy">↻ Sync regio</button>
|
||
<button type="button" class="btn btn-sm btn-pulse" @click="syncKind('world')" :disabled="busy">🌍 Sync wereld</button>
|
||
</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-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>
|
||
<p style="font-size:0.75rem;color:#64748b;margin:0 0 0.75rem" x-show="!mapHalalMode">Klik rij of kaart-pin voor volledig profiel.</p>
|
||
<p style="font-size:0.75rem;color:#64748b;margin:0 0 0.75rem" x-show="mapHalalMode">Klik een rij voor contact & context · kaart zoomt mee. Groen = beste halal-vlees kans.</p>
|
||
|
||
<div class="ei-list-focus" x-show="listFocusLoading || listFocusDetail" x-cloak>
|
||
<div class="ei-list-focus-head">
|
||
<strong x-show="listFocusLoading">Profiel laden…</strong>
|
||
<template x-if="listFocusDetail">
|
||
<div>
|
||
<span class="ei-drawer-badge" :class="'ei-type-'+listFocusDetail.entity_type" x-text="typeLabel(listFocusDetail.entity_type)"></span>
|
||
<span class="ei-halal-pill ei-halal-hot" x-show="listFocusDetail.halal_score" x-text="Math.round(listFocusDetail.halal_score)+'/100'"></span>
|
||
</div>
|
||
</template>
|
||
<button type="button" class="btn btn-sm" @click="clearListFocus()">✕</button>
|
||
</div>
|
||
<template x-if="listFocusDetail">
|
||
<div class="ei-list-focus-body">
|
||
<h4 class="ei-list-focus-title" x-text="listFocusDetail.name"></h4>
|
||
<p class="ei-list-focus-meta">
|
||
<span x-text="territoryName(listFocusDetail.country_iso2)"></span>
|
||
<span x-show="listFocusDetail.city"> · <span x-text="listFocusDetail.city"></span></span>
|
||
<span> · Confidence <span x-text="listFocusDetail.confidence||0"></span>%</span>
|
||
</p>
|
||
<div class="ei-list-focus-kv" x-show="listFocusDetail.address_line">
|
||
<span>Adres</span><span x-text="listFocusDetail.address_line"></span>
|
||
</div>
|
||
<div class="ei-list-focus-kv" x-show="listFocusDetail.email">
|
||
<span>E-mail</span><a :href="'mailto:'+listFocusDetail.email" x-text="listFocusDetail.email"></a>
|
||
</div>
|
||
<div class="ei-list-focus-kv" x-show="listFocusDetail.phone">
|
||
<span>Telefoon</span><a :href="'tel:'+listFocusDetail.phone" x-text="listFocusDetail.phone"></a>
|
||
</div>
|
||
<div class="ei-list-focus-kv" x-show="listFocusDetail.website">
|
||
<span>Website</span><a :href="listFocusDetail.website" target="_blank" rel="noopener" x-text="listFocusDetail.website"></a>
|
||
</div>
|
||
<p class="ei-drawer-empty" x-show="!listFocusDetail.email && !listFocusDetail.phone && !listFocusDetail.website && !(listFocusDetail.contacts||[]).length">
|
||
Geen contactgegevens — OSM heeft vaak alleen naam+locatie. Probeer ↻ Sync contacten.
|
||
</p>
|
||
<div class="ei-halal-tags" x-show="(listFocusDetail.halal_reason_labels||[]).length">
|
||
<template x-for="tag in (listFocusDetail.halal_reason_labels||[])" :key="tag">
|
||
<span class="ei-halal-tag" x-text="tag"></span>
|
||
</template>
|
||
</div>
|
||
<template x-for="c in (listFocusDetail.contacts||[]).slice(0,3)" :key="c.id">
|
||
<div class="ei-contact-row ei-contact-row-compact">
|
||
<strong x-text="c.name || c.role || 'Contact'"></strong>
|
||
<div x-show="c.email">📧 <a :href="'mailto:'+c.email" x-text="c.email"></a></div>
|
||
<div x-show="c.phone">📞 <a :href="'tel:'+c.phone" x-text="c.phone"></a></div>
|
||
</div>
|
||
</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>
|
||
</template>
|
||
</div>
|
||
|
||
<div class="ei-halal-markets" x-show="mapHalalMode && halalTopMarkets.length">
|
||
<h4>Landen met meeste kans</h4>
|
||
<template x-for="m in halalTopMarkets.slice(0,8)" :key="m.country_iso2">
|
||
<div class="ei-halal-market-row" @click="country=m.country_iso2; refresh()" style="cursor:pointer">
|
||
<span class="ei-halal-flag" x-text="m.country_iso2"></span>
|
||
<span class="ei-halal-market-name" x-text="m.country_iso2"></span>
|
||
<strong class="ei-halal-score" x-text="Math.round(m.combined_score||0)"></strong>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
|
||
<div class="ei-table-wrap">
|
||
<table class="ei-table">
|
||
<thead>
|
||
<tr>
|
||
<th class="ei-th-check"><input type="checkbox" @change="toggleSelectAllVisible()" title="Alles selecteren" /></th>
|
||
<th class="ei-th-fav">★</th>
|
||
<th>Naam</th>
|
||
<th>Type</th>
|
||
<th>Stad</th>
|
||
<th>Contact</th>
|
||
<th x-show="mapHalalMode">Score</th>
|
||
<th>Land</th>
|
||
<th class="ei-th-actions">Acties</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<template x-for="e in (mapHalalMode && halalTopEntities.length ? halalTopEntities : entities)" :key="e.id">
|
||
<tr
|
||
@click="selectListEntity(e.id)"
|
||
:class="{ 'ei-row-active': listFocusId === e.id, '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 class="ei-td-fav" @click.stop>
|
||
<button type="button" class="ei-fav-btn" :class="{ active: e.is_favorite }" @click="toggleFavorite(e.id, e.is_favorite, $event)" x-text="e.is_favorite ? '★' : '☆'"></button>
|
||
</td>
|
||
<td>
|
||
<span class="ei-row-name" x-text="e.name"></span>
|
||
<span class="ei-crm-badge" x-show="e.client_id" title="In CRM">CRM</span>
|
||
</td>
|
||
<td><span class="ei-type-pill ei-type-pill-sm" :class="'ei-type-'+e.entity_type" x-text="typeLabel(e.entity_type)"></span></td>
|
||
<td x-text="e.city || '—'"></td>
|
||
<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>
|
||
</table>
|
||
</div>
|
||
<div class="ei-empty" x-show="!entities.length">
|
||
<p>Geen entities met geo in selectie.</p>
|
||
<button class="btn btn-sm btn-pulse ei-empty-cta" @click="syncKind('distributors')">Start sync — fase B vult data</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Distributeurs -->
|
||
<section x-show="tab==='distributors'" x-cloak x-effect="tab==='distributors' && loadTabData()">
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div><h2>Distributeurs & groothandels</h2><p>OSM · Google Places · handmatige seeds</p></div>
|
||
<button class="btn btn-sm btn-pulse" @click="syncKind('distributors')" :disabled="busy">↻ Sync</button>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<div class="ei-panel" style="border:none;background:transparent;padding:0">
|
||
<div class="ei-table-wrap">
|
||
<table class="ei-table">
|
||
<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)" :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>
|
||
</table>
|
||
</div>
|
||
<div class="ei-empty" x-show="!entities.length">
|
||
<p>Nog geen distributeurs in deze selectie.</p>
|
||
<button class="btn btn-sm btn-pulse" @click="syncKind('distributors')">Sync distributeurs (fase B)</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Eindklanten -->
|
||
<section x-show="tab==='customers'" x-cloak>
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div><h2>Eindklanten</h2><p>Restaurants · döner · slagers · horeca</p></div>
|
||
<button class="btn btn-sm btn-pulse" @click="syncKind('customers')" :disabled="busy || !country">↻ Sync horeca</button>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<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>Type</th><th>Land</th><th>Stad</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>
|
||
<td x-text="typeLabel(e.entity_type)"></td>
|
||
<td x-text="e.country_iso2"></td>
|
||
<td x-text="e.city||'—'"></td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="ei-empty" x-show="!entities.length">
|
||
<p>Selecteer een land en sync horeca via OSM.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Cateraars -->
|
||
<section x-show="tab==='caterers'" x-cloak>
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div><h2>Facilitaire cateraars</h2><p>Albron · Sodexo · Compass · presence per land</p></div>
|
||
<button class="btn btn-sm btn-pulse" @click="syncKind('caterers')" :disabled="busy">↻ Sync</button>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<div class="ei-panel" style="margin-bottom:1rem">
|
||
<h3 style="margin:0 0 0.5rem">Brand presence</h3>
|
||
<div class="ei-table-wrap">
|
||
<table class="ei-table">
|
||
<thead><tr><th>Brand</th><th>Land</th><th>Lokale naam</th><th>Takken</th></tr></thead>
|
||
<tbody>
|
||
<template x-for="p in catererPresence" :key="p.id">
|
||
<tr>
|
||
<td x-text="p.brand_name"></td>
|
||
<td x-text="p.country_iso2"></td>
|
||
<td x-text="p.local_legal_name||'—'"></td>
|
||
<td x-text="(p.service_lines||[]).join(', ')"></td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="ei-panel">
|
||
<h3 style="margin:0 0 0.5rem">Cateraar entities</h3>
|
||
<div class="ei-table-wrap">
|
||
<table class="ei-table">
|
||
<thead><tr><th>Naam</th><th>Land</th><th>E-mail</th><th>Website</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>
|
||
<td x-text="e.country_iso2"></td>
|
||
<td x-text="e.primary_email||'—'"></td>
|
||
<td><a :href="e.website" target="_blank" rel="noopener" x-text="e.website||'—'"></a></td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Contacten -->
|
||
<section x-show="tab==='contacts'" x-cloak>
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div><h2>Contactregistry</h2><p>E-mail · telefoon · outreach-ready · direct naar CRM</p></div>
|
||
<div class="ei-tab-panel-actions">
|
||
<button type="button" class="btn btn-sm btn-pulse-green" :disabled="!selectedIds.length || crmPushBusy" @click="openCrmModal()">➕ Geselecteerde naar CRM</button>
|
||
<a class="btn btn-sm" :href="contactsExportUrl()" target="_blank">CSV export</a>
|
||
</div>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<div class="ei-panel" style="border:none;background:transparent;padding:0">
|
||
<div class="ei-table-wrap">
|
||
<table class="ei-table">
|
||
<thead>
|
||
<tr>
|
||
<th class="ei-th-check"><input type="checkbox" @change="toggleSelectAllVisible()" title="Alles selecteren" /></th>
|
||
<th>Organisatie</th>
|
||
<th>Stad</th>
|
||
<th>Type</th>
|
||
<th>Land</th>
|
||
<th>Rol</th>
|
||
<th>Naam</th>
|
||
<th>E-mail</th>
|
||
<th>Telefoon</th>
|
||
<th>CRM</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<template x-for="c in contacts" :key="c.id">
|
||
<tr :class="{ 'ei-row-selected': isSelected(c.entity_id), 'ei-row-crm': c.client_id }">
|
||
<td class="ei-td-check" @click.stop>
|
||
<input type="checkbox" :checked="isSelected(c.entity_id)" @change="toggleSelect(c.entity_id, $event)" />
|
||
</td>
|
||
<td>
|
||
<button type="button" class="ei-link-btn" @click="openEntity(c.entity_id)" x-text="c.entity_name"></button>
|
||
</td>
|
||
<td x-text="c.entity_city || '—'"></td>
|
||
<td><span class="ei-type-pill ei-type-pill-sm" :class="'ei-type-'+c.entity_type" x-text="typeLabel(c.entity_type)"></span></td>
|
||
<td x-text="c.country_iso2"></td>
|
||
<td x-text="c.role || '—'"></td>
|
||
<td x-text="c.name||'—'"></td>
|
||
<td x-text="c.email||'—'"></td>
|
||
<td x-text="c.phone||c.mobile||'—'"></td>
|
||
<td>
|
||
<span class="ei-crm-badge" x-show="c.client_id" :title="c.crm_client_name || 'In CRM'">CRM</span>
|
||
<span class="muted" x-show="!c.client_id">—</span>
|
||
</td>
|
||
<td class="ei-td-actions" @click.stop>
|
||
<button type="button" class="btn btn-sm btn-pulse-green" x-show="!c.client_id" @click="pushEntityToCrm(c.entity_id)" :disabled="crmPushBusy">➕ CRM</button>
|
||
<a class="btn btn-sm" x-show="c.client_id" :href="'/clients'" title="Bekijk in CRM">Open</a>
|
||
</td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="ei-load-more" x-show="contactsHasMore">
|
||
<button type="button" class="btn btn-sm" @click="loadMoreContacts()" :disabled="contactsLoadingMore || busy">
|
||
<span x-text="contactsLoadingMore ? 'Laden…' : ('Meer laden (' + contacts.length + ' / ' + resultCount + ')')"></span>
|
||
</button>
|
||
</div>
|
||
<div class="ei-empty" x-show="!contacts.length && !busy">
|
||
<p>Geen contacten voor deze filters — pas land, type of zoekterm aan.</p>
|
||
<button class="btn btn-sm btn-pulse-green" @click="syncKind('contacts')">Sync contacten</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Tenders -->
|
||
<section x-show="tab==='tenders'" x-cloak>
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div><h2>Tenders</h2><p>TED API · food · catering · meat</p></div>
|
||
<button class="btn btn-sm btn-pulse-purple" @click="syncKind('tenders')" :disabled="busy">↻ TED sync</button>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<div class="ei-panel" style="border:none;background:transparent;padding:0">
|
||
<div class="ei-table-wrap">
|
||
<table class="ei-table">
|
||
<thead><tr><th>Titel</th><th>Land</th><th>Status</th><th>Link</th></tr></thead>
|
||
<tbody>
|
||
<template x-for="t in tenders" :key="t.id">
|
||
<tr>
|
||
<td x-text="t.title"></td>
|
||
<td x-text="t.country_iso2||'—'"></td>
|
||
<td x-text="t.status"></td>
|
||
<td><a :href="t.url" target="_blank" rel="noopener">Open</a></td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="ei-empty" x-show="!tenders.length">
|
||
<p>Geen tenders — klik TED sync.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Overheid -->
|
||
<section x-show="tab==='gov'" x-cloak>
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div><h2>Overheid & data</h2><p>Statistiek · tender portals per land</p></div>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<div class="ei-panel" style="border:none;background:transparent;padding:0">
|
||
<div class="ei-table-wrap">
|
||
<table class="ei-table">
|
||
<thead><tr><th>Land</th><th>Naam</th><th>Categorie</th><th>Link</th></tr></thead>
|
||
<tbody>
|
||
<template x-for="g in govSources" :key="g.id">
|
||
<tr>
|
||
<td x-text="g.country_iso2"></td>
|
||
<td x-text="g.name"></td>
|
||
<td x-text="g.category"></td>
|
||
<td><a :href="g.url" target="_blank" rel="noopener">Open</a></td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Pipeline -->
|
||
<section x-show="tab==='pipeline'" x-cloak>
|
||
<div class="ei-tab-panel">
|
||
<div class="ei-tab-panel-head">
|
||
<div><h2>CRM Pipeline</h2><p>Van Wereldexport naar klanten & deals</p></div>
|
||
<div class="retail-actions">
|
||
<button type="button" class="btn btn-sm btn-pulse-green" :disabled="!selectedIds.length" @click="openCrmModal()">➕ Geselecteerde naar CRM</button>
|
||
<a class="btn btn-sm btn-pulse" href="/clients">Klanten</a>
|
||
<a class="btn btn-sm btn-pulse" href="/deals">Deals</a>
|
||
</div>
|
||
</div>
|
||
<div class="ei-tab-panel-body">
|
||
<p class="ei-pipeline-hint">Entities die je via <strong>Naar CRM</strong> hebt toegevoegd verschijnen hier met koppeling naar klant + deal.</p>
|
||
<div class="ei-table-wrap" x-show="crmPipeline.length">
|
||
<table class="ei-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Organisatie</th>
|
||
<th>Type</th>
|
||
<th>Land</th>
|
||
<th>CRM klant</th>
|
||
<th>Deal</th>
|
||
<th>Toegevoegd</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<template x-for="p in crmPipeline" :key="p.id">
|
||
<tr @click="openEntity(p.id)" style="cursor:pointer">
|
||
<td x-text="p.name"></td>
|
||
<td x-text="typeLabel(p.entity_type)"></td>
|
||
<td x-text="p.country_iso2"></td>
|
||
<td>
|
||
<a x-show="p.client_id" :href="'/clients'" @click.stop x-text="p.crm_client_name || ('#'+p.client_id)"></a>
|
||
</td>
|
||
<td x-text="p.crm_deal_title || '—'"></td>
|
||
<td x-text="p.crm_pushed_at ? new Date(p.crm_pushed_at).toLocaleDateString('nl-NL') : '—'"></td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="ei-empty" x-show="!crmPipeline.length">
|
||
<p>Nog geen entities in CRM vanuit Wereldexport.</p>
|
||
<p>Selecteer leads op de kaart en klik <strong>➕ Naar CRM</strong>.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Drawer — volledig profiel -->
|
||
<div class="ei-drawer-root" x-show="drawerOpen" x-cloak>
|
||
<div class="ei-drawer-backdrop" @click="closeDrawer()"></div>
|
||
<aside class="ei-drawer ei-drawer-rich">
|
||
<header class="ei-drawer-head">
|
||
<button type="button" class="btn btn-sm" @click="closeDrawer()">✕ Sluiten</button>
|
||
</header>
|
||
<div class="ei-drawer-body" x-show="drawerLoading">
|
||
<p class="ei-drawer-empty">Profiel laden…</p>
|
||
</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>
|
||
<span class="ei-halal-pill ei-halal-hot" x-show="selected.halal_score" x-text="Math.round(selected.halal_score)+'/100'"></span>
|
||
</div>
|
||
<h2 class="ei-drawer-title" x-text="selected.name"></h2>
|
||
<p class="ei-drawer-meta">
|
||
<span x-text="territoryName(selected.country_iso2)"></span>
|
||
· Confidence <strong x-text="(selected.confidence||0)+'%'"></strong>
|
||
· Pipeline <strong x-text="selected.pipeline_stage||'—'"></strong>
|
||
· Bron <strong x-text="selected.source||'—'"></strong>
|
||
</p>
|
||
|
||
<div class="ei-halal-tags" x-show="(selected.halal_reason_labels||[]).length">
|
||
<template x-for="tag in (selected.halal_reason_labels||[])" :key="tag">
|
||
<span class="ei-halal-tag" x-text="tag"></span>
|
||
</template>
|
||
</div>
|
||
|
||
<section class="ei-drawer-section" x-show="selected.city || selected.address_line || (selected.lat && selected.lon)">
|
||
<h4>Locatie</h4>
|
||
<p x-show="selected.address_line" x-text="selected.address_line"></p>
|
||
<p x-show="selected.city"><span x-text="selected.city"></span><span x-show="selected.postal_code">, </span><span x-text="selected.postal_code"></span></p>
|
||
<p x-show="selected.lat && selected.lon" class="ei-drawer-coords">
|
||
<span x-text="selected.lat.toFixed(5)+', '+selected.lon.toFixed(5)"></span>
|
||
<a x-show="selected.maps_url" :href="selected.maps_url" target="_blank" rel="noopener">Open in Maps →</a>
|
||
</p>
|
||
</section>
|
||
|
||
<section class="ei-drawer-section">
|
||
<h4>Contact & web</h4>
|
||
<div class="ei-drawer-kv" x-show="selected.email">
|
||
<span>E-mail</span>
|
||
<a :href="'mailto:'+selected.email" x-text="selected.email"></a>
|
||
</div>
|
||
<div class="ei-drawer-kv" x-show="selected.phone">
|
||
<span>Telefoon</span>
|
||
<a :href="'tel:'+selected.phone" x-text="selected.phone"></a>
|
||
</div>
|
||
<div class="ei-drawer-kv" x-show="selected.website">
|
||
<span>Website</span>
|
||
<a :href="selected.website" target="_blank" rel="noopener" x-text="selected.website"></a>
|
||
</div>
|
||
<p x-show="!selected.email && !selected.phone && !selected.website && !(selected.contacts||[]).length" class="ei-drawer-empty">
|
||
Geen direct contact in OSM — klik <strong>Sync contacten</strong> om website/e-mail te verrijken.
|
||
</p>
|
||
</section>
|
||
|
||
<section class="ei-drawer-section" x-show="selected.halal_score != null || selected.volume_band || selected.cold_chain || selected.halal_cert_notes">
|
||
<h4>Business & halal</h4>
|
||
<div class="ei-drawer-kv" x-show="selected.halal_score != null">
|
||
<span>Halal kans</span>
|
||
<strong x-text="Math.round(selected.halal_score||0)+'/100'"></strong>
|
||
</div>
|
||
<div class="ei-drawer-kv" x-show="selected.volume_band">
|
||
<span>Volume</span><span x-text="selected.volume_band"></span>
|
||
</div>
|
||
<div class="ei-drawer-kv" x-show="selected.cold_chain">
|
||
<span>Cold chain</span><span>Ja</span>
|
||
</div>
|
||
<p x-show="selected.halal_cert_notes" x-text="selected.halal_cert_notes"></p>
|
||
</section>
|
||
|
||
<section class="ei-drawer-section" x-show="selected.client_id">
|
||
<h4>CRM koppeling</h4>
|
||
<div class="ei-drawer-kv">
|
||
<span>Klant</span>
|
||
<a href="/clients" x-text="selected.crm_client_name || ('Klant #'+selected.client_id)"></a>
|
||
</div>
|
||
<div class="ei-drawer-kv" x-show="selected.crm_deal_title">
|
||
<span>Deal</span><span x-text="selected.crm_deal_title"></span>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="ei-drawer-section">
|
||
<h4>Contactpersonen (<span x-text="(selected.contacts||[]).length"></span>)</h4>
|
||
<template x-for="c in (selected.contacts||[])" :key="c.id">
|
||
<div class="ei-contact-row">
|
||
<strong x-text="c.name || c.role || 'Contact'"></strong>
|
||
<span class="ei-contact-role" x-show="c.role" x-text="c.role"></span>
|
||
<span class="ei-contact-source" x-show="c.source" x-text="'Bron: '+c.source"></span>
|
||
<div x-show="c.email">📧 <a :href="'mailto:'+c.email" x-text="c.email"></a></div>
|
||
<div x-show="c.phone">📞 <a :href="'tel:'+c.phone" x-text="c.phone"></a></div>
|
||
<div x-show="c.mobile">📱 <span x-text="c.mobile"></span></div>
|
||
</div>
|
||
</template>
|
||
<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>
|
||
<button type="button" class="btn btn-sm btn-pulse-green" x-show="!selected.client_id" @click="pushEntityToCrm(selected.id)" :disabled="crmPushBusy">➕ Naar CRM</button>
|
||
<a class="btn btn-sm btn-pulse" x-show="selected.client_id" href="/clients">Open klant in CRM</a>
|
||
<a class="btn btn-sm" href="/deals" x-show="selected.deal_id">Open deal</a>
|
||
<a class="btn btn-sm" href="/deals">Pipeline / Deals</a>
|
||
<a class="btn btn-sm btn-pulse" :href="'/herman?context=export_catalog&entity='+selected.id">Catalogus via Herman</a>
|
||
<button type="button" class="btn btn-sm btn-pulse-green" @click="syncKind('contacts')" :disabled="busy">↻ Sync contacten</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</aside>
|
||
</div>
|
||
|
||
<!-- CRM bevestiging -->
|
||
<div class="ei-modal-root" x-show="crmModalOpen" x-cloak>
|
||
<div class="ei-drawer-backdrop" @click="crmModalOpen=false"></div>
|
||
<div class="ei-modal-card">
|
||
<h3>Toevoegen aan CRM</h3>
|
||
<p><strong x-text="selectedIds.length"></strong> organisatie(s) worden klant in CRM.</p>
|
||
<label class="ei-filter-check">
|
||
<input type="checkbox" x-model="crmCreateDeals" />
|
||
<span>Maak ook een deal per klant (aanbevolen)</span>
|
||
</label>
|
||
<p class="ei-modal-note">Bestaande klanten met hetzelfde e-mailadres worden gekoppeld i.p.v. dubbel aangemaakt.</p>
|
||
<div class="ei-modal-actions">
|
||
<button type="button" class="btn btn-sm" @click="crmModalOpen=false">Annuleren</button>
|
||
<button type="button" class="btn btn-sm btn-pulse-green" @click="pushToCrm()" :disabled="crmPushBusy">
|
||
<span x-text="crmPushBusy ? 'Bezig…' : 'Bevestig → CRM'"></span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
{% block scripts %}
|
||
<script src="/static/js/export-intel.js?v=14"></script>
|
||
{% endblock %}
|