@ourlu/assistant-sdk 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/iife/audio.v1.028c93fe.js +160 -0
- package/dist/iife/audio.v1.051ececf.js +183 -0
- package/dist/iife/audio.v1.200db1a6.js +208 -0
- package/dist/iife/audio.v1.20858b08.js +191 -0
- package/dist/iife/audio.v1.2690e445.js +179 -0
- package/dist/iife/audio.v1.2742ff12.js +188 -0
- package/dist/iife/audio.v1.70af81b3.js +191 -0
- package/dist/iife/audio.v1.95146620.js +1 -1
- package/dist/iife/audio.v1.b330baaf.js +166 -0
- package/dist/iife/audio.v1.bb9c2d88.js +181 -0
- package/dist/iife/audio.v1.ea7571b2.js +182 -0
- package/dist/iife/audio.v1.fc0aa8af.js +191 -0
- package/dist/iife/audio.v1.js +107 -95
- package/dist/iife/engine.v1.2b5bb43b.js +3 -3
- package/dist/iife/engine.v1.3b09dc20.js +3 -3
- package/dist/iife/engine.v1.56074e5a.js +769 -0
- package/dist/iife/engine.v1.61c10e6c.js +770 -0
- package/dist/iife/engine.v1.773fc15d.js +2 -2
- package/dist/iife/engine.v1.80d2230f.js +3 -3
- package/dist/iife/engine.v1.940ba9ea.js +764 -0
- package/dist/iife/engine.v1.99a33ee2.js +767 -0
- package/dist/iife/engine.v1.9ca6b7ec.js +3 -3
- package/dist/iife/engine.v1.a1f7dea2.js +764 -0
- package/dist/iife/engine.v1.c0c00bd0.js +3 -3
- package/dist/iife/engine.v1.c127656e.js +820 -0
- package/dist/iife/engine.v1.c54c9a1a.js +3 -3
- package/dist/iife/engine.v1.d1052e81.js +3 -3
- package/dist/iife/engine.v1.f6d23a0f.js +770 -0
- package/dist/iife/engine.v1.js +75 -25
- package/dist/iife/loader.v1.js +5 -1
- package/dist/iife/signalement.v1.d321dfde.js +518 -0
- package/dist/iife/signalement.v1.js +518 -0
- package/dist/iife/ui.v1.00abf020.js +895 -0
- package/dist/iife/ui.v1.6becaa84.js +895 -0
- package/dist/iife/ui.v1.6c9e4995.js +895 -0
- package/dist/iife/ui.v1.88bf5494.js +898 -0
- package/dist/iife/ui.v1.a8cfe724.js +900 -0
- package/dist/iife/ui.v1.e007c7c4.js +926 -0
- package/dist/iife/ui.v1.e24ba2bd.js +903 -0
- package/dist/iife/ui.v1.f1d8e998.js +903 -0
- package/dist/iife/ui.v1.fc52b520.js +895 -0
- package/dist/iife/ui.v1.js +44 -77
- package/dist/iife/widget-manifest.json +4 -3
- package/package.json +2 -1
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
"use strict";
|
|
3
|
+
var runtime = window.__OurluWidgetRuntimeV1 || (window.__OurluWidgetRuntimeV1 = {});
|
|
4
|
+
|
|
5
|
+
function SignalementCssBuilder() {}
|
|
6
|
+
|
|
7
|
+
SignalementCssBuilder.prototype.build = function() {
|
|
8
|
+
return [
|
|
9
|
+
this.buildTabsBar(),
|
|
10
|
+
this.buildTabContent(),
|
|
11
|
+
this.buildFormSections(),
|
|
12
|
+
this.buildCategories(),
|
|
13
|
+
this.buildPhotos(),
|
|
14
|
+
this.buildLocation(),
|
|
15
|
+
this.buildSignalementButton(),
|
|
16
|
+
this.buildMobileOverrides()
|
|
17
|
+
].join("\n");
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
SignalementCssBuilder.prototype.buildTabsBar = function() {
|
|
21
|
+
return [
|
|
22
|
+
"#cm-tabs-bar{display:none;gap:0;background:#f8fafc;border-bottom:1px solid #e2e8f0;flex-shrink:0;padding:0 4px}",
|
|
23
|
+
"#cm-tabs-bar.visible{display:flex}",
|
|
24
|
+
".cm-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:11px 8px;border:none;background:none;color:#94a3b8;font-size:13.5px;font-weight:500;cursor:pointer;position:relative;transition:color .2s;border-bottom:2.5px solid transparent;font-family:inherit}",
|
|
25
|
+
".cm-tab svg{width:16px;height:16px;flex-shrink:0}",
|
|
26
|
+
".cm-tab:hover{color:#475569}",
|
|
27
|
+
".cm-tab.active{color:#0066ff;border-bottom-color:#0066ff;font-weight:600}",
|
|
28
|
+
".cm-tab-close{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;border:none;background:transparent;color:inherit;cursor:pointer;opacity:.5;transition:all .15s;padding:0;margin-left:4px}",
|
|
29
|
+
".cm-tab-close svg{width:12px;height:12px}",
|
|
30
|
+
".cm-tab-close:hover{opacity:1;background:rgba(0,0,0,.08)}",
|
|
31
|
+
".cm-tab[data-tab='signalement'].hidden{display:none}"
|
|
32
|
+
].join("\n");
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
SignalementCssBuilder.prototype.buildTabContent = function() {
|
|
36
|
+
return [
|
|
37
|
+
"#cm-signalement-content{display:none;flex-direction:column;flex:1;overflow:hidden}",
|
|
38
|
+
"#cm-signalement-content.active{display:flex}",
|
|
39
|
+
".cm-signalement-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding:16px;display:flex;flex-direction:column;gap:18px;min-width:0;width:100%}",
|
|
40
|
+
".cm-signalement-scroll::-webkit-scrollbar{width:6px}",
|
|
41
|
+
".cm-signalement-scroll::-webkit-scrollbar-thumb{background:rgba(0,0,0,.1);border-radius:3px}"
|
|
42
|
+
].join("\n");
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
SignalementCssBuilder.prototype.buildFormSections = function() {
|
|
46
|
+
return [
|
|
47
|
+
".cm-sig-section{display:flex;flex-direction:column;min-width:0;padding-bottom:14px;border-bottom:1px solid #e2e8f0}",
|
|
48
|
+
".cm-sig-label{font-size:12px;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px}",
|
|
49
|
+
".cm-sig-label-opt{font-weight:400;text-transform:none;letter-spacing:0;color:#94a3b8;font-size:11px}"
|
|
50
|
+
].join("\n");
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
SignalementCssBuilder.prototype.buildCategories = function() {
|
|
54
|
+
return [
|
|
55
|
+
".cm-sig-cats{display:flex;gap:6px;overflow-x:scroll;overflow-y:hidden;flex-wrap:nowrap;padding-bottom:6px;-webkit-overflow-scrolling:touch;scrollbar-width:none;max-width:100%}",
|
|
56
|
+
".cm-sig-cats::-webkit-scrollbar{display:none}",
|
|
57
|
+
".cm-sig-cat{display:flex;align-items:center;gap:5px;padding:10px 18px;border-radius:20px;border:1.5px solid #e2e8f0;background:#fff;color:#475569;font-size:14px;font-weight:500;cursor:pointer;transition:all .15s;white-space:nowrap;flex-shrink:0;font-family:inherit}",
|
|
58
|
+
".cm-sig-cat svg{width:18px;height:18px}",
|
|
59
|
+
".cm-sig-cat:hover{border-color:#93c5fd;background:#eff6ff;color:#1d4ed8}",
|
|
60
|
+
".cm-sig-cat.active{border-color:#0066ff;background:#eff6ff;color:#0066ff;font-weight:600;box-shadow:0 0 0 2px rgba(0,102,255,.12)}"
|
|
61
|
+
].join("\n");
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
SignalementCssBuilder.prototype.buildPhotos = function() {
|
|
65
|
+
return [
|
|
66
|
+
".cm-sig-photo-actions{display:flex;gap:8px;margin-bottom:5px}",
|
|
67
|
+
".cm-sig-photo-btn{display:flex;align-items:center;gap:5px;padding:8px 16px;border-radius:10px;border:1.5px solid #e2e8f0;background:#fff;color:#475569;font-size:14px;font-weight:500;cursor:pointer;transition:all .15s;font-family:inherit}",
|
|
68
|
+
".cm-sig-photo-btn svg{width:18px;height:18px}",
|
|
69
|
+
".cm-sig-photo-btn:hover{border-color:#93c5fd;background:#eff6ff;color:#1d4ed8}",
|
|
70
|
+
".cm-sig-grid{display:flex;gap:10px;flex-wrap:wrap;margin-top:5px}",
|
|
71
|
+
".cm-sig-thumb{width:88px;height:88px;border-radius:12px;overflow:hidden;position:relative;border:1.5px solid #e2e8f0;box-shadow:0 2px 6px rgba(0,0,0,.06)}",
|
|
72
|
+
".cm-sig-thumb img{width:100%;height:100%;object-fit:cover}",
|
|
73
|
+
".cm-sig-thumb-rm{position:absolute;top:4px;right:4px;width:24px;height:24px;border-radius:50%;background:rgba(0,0,0,.55);color:#fff;border:none;cursor:pointer;font-size:15px;display:flex;align-items:center;justify-content:center;line-height:1;transition:background .15s}",
|
|
74
|
+
".cm-sig-thumb-rm:hover{background:rgba(220,38,38,.9)}",
|
|
75
|
+
".cm-sig-add{width:88px;height:88px;border-radius:12px;border:2px dashed #cbd5e1;background:#f8fafc;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:border-color .2s,background .2s;color:#94a3b8}",
|
|
76
|
+
".cm-sig-add svg{width:28px;height:28px}",
|
|
77
|
+
".cm-sig-add:hover{border-color:#0066ff;background:#eff6ff;color:#0066ff}"
|
|
78
|
+
].join("\n");
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
SignalementCssBuilder.prototype.buildLocation = function() {
|
|
82
|
+
return [
|
|
83
|
+
".cm-sig-loc-row{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-radius:12px;background:#f0fdf4;border:1.5px solid #bbf7d0;transition:background .25s,border-color .25s}",
|
|
84
|
+
".cm-sig-loc-row.denied{background:#fef2f2;border-color:#fecaca}",
|
|
85
|
+
".cm-sig-loc-status{display:flex;align-items:center;gap:10px}",
|
|
86
|
+
".cm-sig-loc-globe{position:relative;flex-shrink:0;width:36px;height:36px;display:flex;align-items:center;justify-content:center;background:#dcfce7;border-radius:50%;transition:background .25s}",
|
|
87
|
+
".cm-sig-loc-row.denied .cm-sig-loc-globe{background:#fee2e2}",
|
|
88
|
+
".cm-sig-loc-check{position:absolute;top:-2px;right:-2px;width:16px;height:16px;border-radius:50%;background:#16a34a;color:#fff;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1;transition:background .25s}",
|
|
89
|
+
".cm-sig-loc-row.denied .cm-sig-loc-check{background:#dc2626}",
|
|
90
|
+
".cm-sig-loc-info{display:flex;flex-direction:column;gap:1px}",
|
|
91
|
+
".cm-sig-loc-text{font-size:13px;font-weight:600;color:#15803d;transition:color .25s}",
|
|
92
|
+
".cm-sig-loc-row.denied .cm-sig-loc-text{color:#dc2626}",
|
|
93
|
+
".cm-sig-loc-addr{font-size:12px;color:#4ade80;font-weight:400;transition:color .25s}",
|
|
94
|
+
".cm-sig-loc-row.denied .cm-sig-loc-addr{color:#fca5a5}",
|
|
95
|
+
".cm-sig-toggle{position:relative;display:inline-block;width:52px;height:28px;flex-shrink:0;cursor:pointer}",
|
|
96
|
+
".cm-sig-toggle input{opacity:0;width:0;height:0}",
|
|
97
|
+
".cm-sig-toggle-slider{position:absolute;inset:0;background:#cbd5e1;border-radius:28px;transition:background .25s}",
|
|
98
|
+
".cm-sig-toggle-slider::before{content:'';position:absolute;width:22px;height:22px;border-radius:50%;left:3px;bottom:3px;background:#fff;transition:transform .25s;box-shadow:0 1px 3px rgba(0,0,0,.15)}",
|
|
99
|
+
".cm-sig-toggle input:checked+.cm-sig-toggle-slider{background:#16a34a}",
|
|
100
|
+
".cm-sig-toggle input:checked+.cm-sig-toggle-slider::before{transform:translateX(24px)}"
|
|
101
|
+
].join("\n");
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
SignalementCssBuilder.prototype.buildSignalementButton = function() {
|
|
105
|
+
return [
|
|
106
|
+
".cm-sig-open-btn{display:inline-flex;align-items:center;gap:8px;margin-top:10px;padding:10px 18px;border-radius:12px;border:1.5px solid #0066ff;background:#eff6ff;color:#0066ff;font-size:14px;font-weight:600;cursor:pointer;transition:all .15s;font-family:inherit}",
|
|
107
|
+
".cm-sig-open-btn svg{width:18px;height:18px;flex-shrink:0}",
|
|
108
|
+
".cm-sig-open-btn:hover{background:#0066ff;color:#fff;transform:translateY(-1px);box-shadow:0 4px 12px rgba(0,102,255,.3)}",
|
|
109
|
+
".cm-sig-open-btn:active{transform:scale(0.97)}"
|
|
110
|
+
].join("\n");
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
SignalementCssBuilder.prototype.buildMobileOverrides = function() {
|
|
114
|
+
return [
|
|
115
|
+
"@media(max-width:600px){",
|
|
116
|
+
".cm-sig-cat{padding:8px 14px;font-size:13px}",
|
|
117
|
+
".cm-sig-thumb,.cm-sig-add{width:72px;height:72px}",
|
|
118
|
+
".cm-sig-photo-btn{padding:6px 12px;font-size:13px}",
|
|
119
|
+
"}"
|
|
120
|
+
].join("\n");
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
function GeoLocationManager() {
|
|
124
|
+
this.latitude = null;
|
|
125
|
+
this.longitude = null;
|
|
126
|
+
this.accuracy = null;
|
|
127
|
+
this.status = "unknown";
|
|
128
|
+
this.watchId = null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
GeoLocationManager.prototype.isSupported = function() {
|
|
132
|
+
return typeof navigator !== "undefined" && "geolocation" in navigator;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
GeoLocationManager.prototype.request = function(onUpdate) {
|
|
136
|
+
if (!this.isSupported()) {
|
|
137
|
+
this.status = "unsupported";
|
|
138
|
+
if (onUpdate) onUpdate(this);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
var self = this;
|
|
142
|
+
navigator.geolocation.getCurrentPosition(
|
|
143
|
+
function(pos) {
|
|
144
|
+
self.latitude = pos.coords.latitude;
|
|
145
|
+
self.longitude = pos.coords.longitude;
|
|
146
|
+
self.accuracy = pos.coords.accuracy;
|
|
147
|
+
self.status = "granted";
|
|
148
|
+
if (onUpdate) onUpdate(self);
|
|
149
|
+
},
|
|
150
|
+
function() {
|
|
151
|
+
self.status = "denied";
|
|
152
|
+
if (onUpdate) onUpdate(self);
|
|
153
|
+
},
|
|
154
|
+
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 60000 }
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
GeoLocationManager.prototype.stop = function() {
|
|
159
|
+
if (this.watchId !== null && this.isSupported()) {
|
|
160
|
+
navigator.geolocation.clearWatch(this.watchId);
|
|
161
|
+
this.watchId = null;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
GeoLocationManager.prototype.toPayload = function() {
|
|
166
|
+
return {
|
|
167
|
+
latitude: this.latitude,
|
|
168
|
+
longitude: this.longitude,
|
|
169
|
+
accuracy: this.accuracy,
|
|
170
|
+
geo_status: this.status
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
var CATEGORIES = [
|
|
175
|
+
{ id: "voirie", label: "Voirie", icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 21h18"/><path d="M5 21V7l8-4v18"/><path d="M19 21V11l-6-4"/></svg>' },
|
|
176
|
+
{ id: "espaces_verts", label: "Espaces verts", icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M9.5 2A2.5 2.5 0 0112 4.5v15a2.5 2.5 0 01-4.96.44 2.5 2.5 0 01-2.96-3.08 3 3 0 01-.34-5.58 2.5 2.5 0 011.32-4.24 2.5 2.5 0 013.54-.94"/><path d="M14.5 2A2.5 2.5 0 0012 4.5v15a2.5 2.5 0 004.96.44 2.5 2.5 0 002.96-3.08 3 3 0 00.34-5.58 2.5 2.5 0 00-1.32-4.24 2.5 2.5 0 00-3.54-.94"/></svg>' },
|
|
177
|
+
{ id: "bruit", label: "Bruit", icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>' },
|
|
178
|
+
{ id: "proprete", label: "Propreté", icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg>' },
|
|
179
|
+
{ id: "autre", label: "Autre", icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>' }
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
var MAX_PHOTOS = 5;
|
|
183
|
+
var ICON_PIN = '<svg viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="2" style="width:22px;height:22px"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"/><circle cx="12" cy="10" r="3"/></svg>';
|
|
184
|
+
var ICON_PIN_DENIED = '<svg viewBox="0 0 24 24" fill="none" stroke="#dc2626" stroke-width="2" style="width:22px;height:22px"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"/><circle cx="12" cy="10" r="3"/></svg>';
|
|
185
|
+
|
|
186
|
+
function SignalementModuleManager(rootEl, events, apiManager, uiManager) {
|
|
187
|
+
this.root = rootEl;
|
|
188
|
+
this.events = events;
|
|
189
|
+
this.api = apiManager;
|
|
190
|
+
this.ui = uiManager;
|
|
191
|
+
this.geo = new GeoLocationManager();
|
|
192
|
+
this.selectedCategory = "";
|
|
193
|
+
this.photoFiles = [];
|
|
194
|
+
this.photoPreviewUrls = [];
|
|
195
|
+
this.contentEl = null;
|
|
196
|
+
this.gridEl = null;
|
|
197
|
+
this.locRow = null;
|
|
198
|
+
this.locGlobe = null;
|
|
199
|
+
this.locCheck = null;
|
|
200
|
+
this.locText = null;
|
|
201
|
+
this.locAddr = null;
|
|
202
|
+
this.gpsToggle = null;
|
|
203
|
+
this.mounted = false;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
SignalementModuleManager.prototype.injectCSS = function() {
|
|
207
|
+
var builder = new SignalementCssBuilder();
|
|
208
|
+
var styleEl = document.createElement("style");
|
|
209
|
+
styleEl.id = "cm-signalement-css";
|
|
210
|
+
styleEl.textContent = builder.build();
|
|
211
|
+
this.root.appendChild(styleEl);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
SignalementModuleManager.prototype.mount = function(panelEl, headerEl) {
|
|
215
|
+
if (this.mounted) return;
|
|
216
|
+
this.injectCSS();
|
|
217
|
+
|
|
218
|
+
var tabsBar = document.createElement("div");
|
|
219
|
+
tabsBar.id = "cm-tabs-bar";
|
|
220
|
+
tabsBar.innerHTML = [
|
|
221
|
+
'<button class="cm-tab active" data-tab="chat" type="button">',
|
|
222
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
|
|
223
|
+
'Chat</button>',
|
|
224
|
+
'<button class="cm-tab hidden" data-tab="signalement" type="button">',
|
|
225
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 9v4"/><path d="M12 17h.01"/><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/></svg>',
|
|
226
|
+
'Signalement',
|
|
227
|
+
'<button class="cm-tab-close" type="button" aria-label="Fermer l\'onglet signalement">',
|
|
228
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',
|
|
229
|
+
'</button></button>'
|
|
230
|
+
].join("");
|
|
231
|
+
headerEl.insertAdjacentElement("afterend", tabsBar);
|
|
232
|
+
this.tabsBar = tabsBar;
|
|
233
|
+
|
|
234
|
+
var content = document.createElement("div");
|
|
235
|
+
content.id = "cm-signalement-content";
|
|
236
|
+
content.innerHTML = this.buildFormHTML();
|
|
237
|
+
panelEl.appendChild(content);
|
|
238
|
+
this.contentEl = content;
|
|
239
|
+
|
|
240
|
+
this.gridEl = content.querySelector(".cm-sig-grid");
|
|
241
|
+
this.locRow = content.querySelector(".cm-sig-loc-row");
|
|
242
|
+
this.locGlobe = content.querySelector(".cm-sig-loc-globe");
|
|
243
|
+
this.locCheck = content.querySelector(".cm-sig-loc-check");
|
|
244
|
+
this.locText = content.querySelector(".cm-sig-loc-text");
|
|
245
|
+
this.locAddr = content.querySelector(".cm-sig-loc-addr");
|
|
246
|
+
this.gpsToggle = content.querySelector(".cm-sig-toggle input");
|
|
247
|
+
|
|
248
|
+
this.bindEvents(tabsBar, content);
|
|
249
|
+
this.mounted = true;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
SignalementModuleManager.prototype.buildFormHTML = function() {
|
|
253
|
+
var catsHtml = CATEGORIES.map(function(cat) {
|
|
254
|
+
return '<button class="cm-sig-cat" data-cat="' + cat.id + '" type="button">' + cat.icon + cat.label + '</button>';
|
|
255
|
+
}).join("");
|
|
256
|
+
|
|
257
|
+
return [
|
|
258
|
+
'<div class="cm-signalement-scroll">',
|
|
259
|
+
'<div class="cm-sig-section"><label class="cm-sig-label">Catégorie <span class="cm-sig-label-opt">(optionnel)</span></label>',
|
|
260
|
+
'<div class="cm-sig-cats">' + catsHtml + '</div></div>',
|
|
261
|
+
'<div class="cm-sig-section"><label class="cm-sig-label">Photos</label>',
|
|
262
|
+
'<div class="cm-sig-photo-actions">',
|
|
263
|
+
'<button class="cm-sig-photo-btn" data-action="photo" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg>Photo</button>',
|
|
264
|
+
'<button class="cm-sig-photo-btn" data-action="camera" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/><circle cx="12" cy="13" r="4"/></svg>Caméra</button>',
|
|
265
|
+
'</div>',
|
|
266
|
+
'<div class="cm-sig-grid">',
|
|
267
|
+
'<button class="cm-sig-add" type="button" aria-label="Ajouter une photo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg></button>',
|
|
268
|
+
'</div></div>',
|
|
269
|
+
'<div class="cm-sig-section"><div class="cm-sig-loc-row">',
|
|
270
|
+
'<div class="cm-sig-loc-status"><div class="cm-sig-loc-globe">' + ICON_PIN + '<span class="cm-sig-loc-check">\u2713</span></div>',
|
|
271
|
+
'<div class="cm-sig-loc-info"><span class="cm-sig-loc-text">Position GPS en attente…</span><span class="cm-sig-loc-addr"></span></div></div>',
|
|
272
|
+
'<label class="cm-sig-toggle"><input type="checkbox" checked><span class="cm-sig-toggle-slider"></span></label>',
|
|
273
|
+
'</div></div>',
|
|
274
|
+
'</div>'
|
|
275
|
+
].join("");
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
SignalementModuleManager.prototype.bindEvents = function(tabsBar, content) {
|
|
279
|
+
var self = this;
|
|
280
|
+
|
|
281
|
+
tabsBar.querySelectorAll(".cm-tab").forEach(function(tab) {
|
|
282
|
+
tab.addEventListener("click", function() {
|
|
283
|
+
if (tab.classList.contains("hidden")) return;
|
|
284
|
+
self.switchTab(tab.getAttribute("data-tab"));
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
var closeBtn = tabsBar.querySelector(".cm-tab-close");
|
|
289
|
+
if (closeBtn) closeBtn.addEventListener("click", function(e) {
|
|
290
|
+
e.stopPropagation();
|
|
291
|
+
self.close();
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
content.querySelectorAll(".cm-sig-cat").forEach(function(cat) {
|
|
295
|
+
cat.addEventListener("click", function() {
|
|
296
|
+
content.querySelectorAll(".cm-sig-cat").forEach(function(c) { c.classList.remove("active"); });
|
|
297
|
+
cat.classList.add("active");
|
|
298
|
+
self.selectedCategory = cat.getAttribute("data-cat");
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
this.bindDragScroll(content.querySelector(".cm-sig-cats"));
|
|
303
|
+
|
|
304
|
+
content.querySelector('[data-action="photo"]').addEventListener("click", function() { self.triggerFileInput(false); });
|
|
305
|
+
content.querySelector('[data-action="camera"]').addEventListener("click", function() { self.triggerFileInput(true); });
|
|
306
|
+
content.querySelector(".cm-sig-add").addEventListener("click", function() { self.triggerFileInput(false); });
|
|
307
|
+
|
|
308
|
+
if (this.gpsToggle) {
|
|
309
|
+
this.gpsToggle.addEventListener("change", function() {
|
|
310
|
+
if (self.gpsToggle.checked) {
|
|
311
|
+
self.requestGPS();
|
|
312
|
+
} else {
|
|
313
|
+
self.geo.stop();
|
|
314
|
+
self.geo.status = "denied";
|
|
315
|
+
self.updateGPSDisplay();
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
SignalementModuleManager.prototype.bindDragScroll = function(el) {
|
|
322
|
+
if (!el) return;
|
|
323
|
+
var isDown = false, startX, scrollLeft;
|
|
324
|
+
el.style.cursor = "grab";
|
|
325
|
+
el.addEventListener("mousedown", function(e) {
|
|
326
|
+
isDown = true; el.style.cursor = "grabbing";
|
|
327
|
+
startX = e.pageX - el.offsetLeft; scrollLeft = el.scrollLeft;
|
|
328
|
+
e.preventDefault();
|
|
329
|
+
});
|
|
330
|
+
el.addEventListener("mouseleave", function() { isDown = false; el.style.cursor = "grab"; });
|
|
331
|
+
el.addEventListener("mouseup", function() { isDown = false; el.style.cursor = "grab"; });
|
|
332
|
+
el.addEventListener("mousemove", function(e) {
|
|
333
|
+
if (!isDown) return;
|
|
334
|
+
el.scrollLeft = scrollLeft - ((e.pageX - el.offsetLeft) - startX);
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
SignalementModuleManager.prototype.switchTab = function(tabName) {
|
|
339
|
+
var isSignalement = tabName === "signalement";
|
|
340
|
+
this.tabsBar.querySelectorAll(".cm-tab").forEach(function(t) {
|
|
341
|
+
t.classList.toggle("active", t.getAttribute("data-tab") === tabName);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
var chatElements = this.root.querySelectorAll("#cm-messages, #cm-typing, #cm-error, #cm-disclaimer, #cm-transparency");
|
|
345
|
+
chatElements.forEach(function(el) { el.style.display = isSignalement ? "none" : ""; });
|
|
346
|
+
|
|
347
|
+
var form = this.root.querySelector("#cm-form");
|
|
348
|
+
if (form) {
|
|
349
|
+
var input = form.querySelector("#cm-input");
|
|
350
|
+
if (input) input.placeholder = isSignalement ? "Décrivez votre signalement\u2026" : "Posez votre question\u2026";
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
this.contentEl.classList.toggle("active", isSignalement);
|
|
354
|
+
this.contentEl.style.display = isSignalement ? "flex" : "none";
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
SignalementModuleManager.prototype.open = function(prefill) {
|
|
358
|
+
var sigTab = this.tabsBar.querySelector('[data-tab="signalement"]');
|
|
359
|
+
sigTab.classList.remove("hidden");
|
|
360
|
+
this.tabsBar.classList.add("visible");
|
|
361
|
+
this.switchTab("signalement");
|
|
362
|
+
|
|
363
|
+
if (prefill) {
|
|
364
|
+
if (prefill.category) this.preselectCategory(prefill.category);
|
|
365
|
+
if (prefill.description) {
|
|
366
|
+
var input = this.root.querySelector("#cm-input");
|
|
367
|
+
if (input) { input.value = prefill.description; input.dispatchEvent(new Event("input", { bubbles: true })); }
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
this.requestGPS();
|
|
372
|
+
this.events.emit("module:signalement:open", prefill || {});
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
SignalementModuleManager.prototype.close = function() {
|
|
376
|
+
var sigTab = this.tabsBar.querySelector('[data-tab="signalement"]');
|
|
377
|
+
sigTab.classList.add("hidden");
|
|
378
|
+
this.switchTab("chat");
|
|
379
|
+
this.events.emit("module:signalement:closed", {});
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
SignalementModuleManager.prototype.preselectCategory = function(categoryId) {
|
|
383
|
+
var normalized = String(categoryId || "").toLowerCase().replace(/\s+/g, "_")
|
|
384
|
+
.replace(/é/g, "e").replace(/ê/g, "e");
|
|
385
|
+
this.contentEl.querySelectorAll(".cm-sig-cat").forEach(function(cat) {
|
|
386
|
+
var match = cat.getAttribute("data-cat") === normalized;
|
|
387
|
+
cat.classList.toggle("active", match);
|
|
388
|
+
});
|
|
389
|
+
this.selectedCategory = normalized;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
SignalementModuleManager.prototype.requestGPS = function() {
|
|
393
|
+
var self = this;
|
|
394
|
+
this.geo.request(function() { self.updateGPSDisplay(); });
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
SignalementModuleManager.prototype.updateGPSDisplay = function() {
|
|
398
|
+
var denied = this.geo.status === "denied" || this.geo.status === "unsupported";
|
|
399
|
+
this.locRow.classList.toggle("denied", denied);
|
|
400
|
+
this.locGlobe.innerHTML = denied ? ICON_PIN_DENIED : ICON_PIN;
|
|
401
|
+
this.locCheck.textContent = denied ? "\u2717" : "\u2713";
|
|
402
|
+
this.locText.textContent = denied ? "Position GPS indisponible" : "Position GPS active";
|
|
403
|
+
this.locAddr.textContent = denied ? "Activez la localisation" : "";
|
|
404
|
+
if (this.gpsToggle) this.gpsToggle.checked = !denied;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
SignalementModuleManager.prototype.triggerFileInput = function(useCamera) {
|
|
408
|
+
if (this.photoFiles.length >= MAX_PHOTOS) return;
|
|
409
|
+
var input = document.createElement("input");
|
|
410
|
+
input.type = "file";
|
|
411
|
+
input.accept = "image/*";
|
|
412
|
+
if (useCamera) input.setAttribute("capture", "environment");
|
|
413
|
+
input.style.display = "none";
|
|
414
|
+
var self = this;
|
|
415
|
+
input.addEventListener("change", function() {
|
|
416
|
+
if (input.files && input.files[0]) self.addPhoto(input.files[0]);
|
|
417
|
+
input.remove();
|
|
418
|
+
});
|
|
419
|
+
document.body.appendChild(input);
|
|
420
|
+
input.click();
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
SignalementModuleManager.prototype.addPhoto = function(file) {
|
|
424
|
+
if (this.photoFiles.length >= MAX_PHOTOS) return;
|
|
425
|
+
this.photoFiles.push(file);
|
|
426
|
+
var url = URL.createObjectURL(file);
|
|
427
|
+
this.photoPreviewUrls.push(url);
|
|
428
|
+
this.renderPhotoGrid();
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
SignalementModuleManager.prototype.removePhoto = function(index) {
|
|
432
|
+
URL.revokeObjectURL(this.photoPreviewUrls[index]);
|
|
433
|
+
this.photoFiles.splice(index, 1);
|
|
434
|
+
this.photoPreviewUrls.splice(index, 1);
|
|
435
|
+
this.renderPhotoGrid();
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
SignalementModuleManager.prototype.renderPhotoGrid = function() {
|
|
439
|
+
var self = this;
|
|
440
|
+
var html = this.photoPreviewUrls.map(function(url, idx) {
|
|
441
|
+
return '<div class="cm-sig-thumb"><img src="' + url + '" alt="Photo ' + (idx + 1) + '"/>' +
|
|
442
|
+
'<button class="cm-sig-thumb-rm" data-idx="' + idx + '" type="button" aria-label="Supprimer">\u00d7</button></div>';
|
|
443
|
+
}).join("");
|
|
444
|
+
|
|
445
|
+
if (this.photoFiles.length < MAX_PHOTOS) {
|
|
446
|
+
html += '<button class="cm-sig-add" type="button" aria-label="Ajouter une photo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg></button>';
|
|
447
|
+
}
|
|
448
|
+
this.gridEl.innerHTML = html;
|
|
449
|
+
|
|
450
|
+
this.gridEl.querySelectorAll(".cm-sig-thumb-rm").forEach(function(btn) {
|
|
451
|
+
btn.addEventListener("click", function() { self.removePhoto(Number(btn.getAttribute("data-idx"))); });
|
|
452
|
+
});
|
|
453
|
+
var addBtn = this.gridEl.querySelector(".cm-sig-add");
|
|
454
|
+
if (addBtn) addBtn.addEventListener("click", function() { self.triggerFileInput(false); });
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
SignalementModuleManager.prototype.submit = async function() {
|
|
458
|
+
var input = this.root.querySelector("#cm-input");
|
|
459
|
+
var message = input ? input.value.trim() : "";
|
|
460
|
+
|
|
461
|
+
if (!message && this.photoFiles.length === 0) return;
|
|
462
|
+
|
|
463
|
+
var formData = new FormData();
|
|
464
|
+
formData.append("session_id", this.api.state.sessionId || "");
|
|
465
|
+
formData.append("message", message);
|
|
466
|
+
formData.append("category", this.selectedCategory);
|
|
467
|
+
|
|
468
|
+
var geoPayload = this.geo.toPayload();
|
|
469
|
+
if (geoPayload.latitude !== null) formData.append("latitude", String(geoPayload.latitude));
|
|
470
|
+
if (geoPayload.longitude !== null) formData.append("longitude", String(geoPayload.longitude));
|
|
471
|
+
if (geoPayload.accuracy !== null) formData.append("accuracy", String(geoPayload.accuracy));
|
|
472
|
+
formData.append("geo_status", geoPayload.geo_status);
|
|
473
|
+
|
|
474
|
+
for (var i = 0; i < this.photoFiles.length; i++) {
|
|
475
|
+
formData.append("images[]", this.photoFiles[i]);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
var url = this.api.resolveRuntimeUrl("/v1/modules/signalements/submit");
|
|
479
|
+
var headers = this.api.buildHeaders();
|
|
480
|
+
delete headers["Content-Type"];
|
|
481
|
+
|
|
482
|
+
var response = await fetch(url, { method: "POST", headers: headers, body: formData });
|
|
483
|
+
if (!response.ok) {
|
|
484
|
+
var errBody = await response.text().catch(function() { return ""; });
|
|
485
|
+
throw new Error(errBody || "HTTP " + response.status);
|
|
486
|
+
}
|
|
487
|
+
var result = await response.json();
|
|
488
|
+
|
|
489
|
+
this.resetForm(input);
|
|
490
|
+
this.close();
|
|
491
|
+
this.events.emit("module:signalement:submitted", result);
|
|
492
|
+
return result;
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
SignalementModuleManager.prototype.resetForm = function(input) {
|
|
496
|
+
if (input) { input.value = ""; input.dispatchEvent(new Event("input", { bubbles: true })); }
|
|
497
|
+
this.selectedCategory = "";
|
|
498
|
+
this.contentEl.querySelectorAll(".cm-sig-cat").forEach(function(c) { c.classList.remove("active"); });
|
|
499
|
+
this.photoPreviewUrls.forEach(function(url) { URL.revokeObjectURL(url); });
|
|
500
|
+
this.photoFiles = [];
|
|
501
|
+
this.photoPreviewUrls = [];
|
|
502
|
+
this.renderPhotoGrid();
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
SignalementModuleManager.prototype.createOpenButton = function() {
|
|
506
|
+
var btn = document.createElement("button");
|
|
507
|
+
btn.className = "cm-sig-open-btn";
|
|
508
|
+
btn.type = "button";
|
|
509
|
+
btn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 9v4"/><path d="M12 17h.01"/><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/></svg>Mon signalement';
|
|
510
|
+
var self = this;
|
|
511
|
+
btn.addEventListener("click", function() { self.open(); });
|
|
512
|
+
return btn;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
runtime.SignalementModuleManager = SignalementModuleManager;
|
|
516
|
+
runtime.SignalementCssBuilder = SignalementCssBuilder;
|
|
517
|
+
runtime.GeoLocationManager = GeoLocationManager;
|
|
518
|
+
})();
|