@athoscommerce/snap-store-mobx 1.2.3-beta.4 → 1.2.3-beta.6
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/cjs/Autocomplete/AutocompleteStore.d.ts +1 -1
- package/dist/cjs/Autocomplete/AutocompleteStore.d.ts.map +1 -1
- package/dist/cjs/Autocomplete/AutocompleteStore.js +8 -5
- package/dist/cjs/Autocomplete/Stores/AutocompleteFacetStore.d.ts.map +1 -1
- package/dist/cjs/Autocomplete/Stores/AutocompleteFacetStore.js +1 -2
- package/dist/cjs/Chat/ChatStore.d.ts +35 -6
- package/dist/cjs/Chat/ChatStore.d.ts.map +1 -1
- package/dist/cjs/Chat/ChatStore.js +201 -77
- package/dist/cjs/Chat/Stores/ChatAttachmentStore.d.ts.map +1 -1
- package/dist/cjs/Chat/Stores/ChatAttachmentStore.js +3 -3
- package/dist/cjs/Chat/Stores/ChatCompareStore.d.ts +2 -0
- package/dist/cjs/Chat/Stores/ChatCompareStore.d.ts.map +1 -1
- package/dist/cjs/Chat/Stores/ChatCompareStore.js +4 -2
- package/dist/cjs/Chat/Stores/ChatSessionStore.d.ts +10 -20
- package/dist/cjs/Chat/Stores/ChatSessionStore.d.ts.map +1 -1
- package/dist/cjs/Chat/Stores/ChatSessionStore.js +33 -87
- package/dist/cjs/Finder/FinderStore.d.ts +1 -1
- package/dist/cjs/Finder/FinderStore.d.ts.map +1 -1
- package/dist/cjs/Finder/FinderStore.js +3 -3
- package/dist/cjs/Finder/Stores/FinderSelectionStore.d.ts +1 -1
- package/dist/cjs/Finder/Stores/FinderSelectionStore.d.ts.map +1 -1
- package/dist/cjs/ProductQuickView/ProductQuickViewStore.d.ts +21 -0
- package/dist/cjs/ProductQuickView/ProductQuickViewStore.d.ts.map +1 -0
- package/dist/cjs/ProductQuickView/ProductQuickViewStore.js +69 -0
- package/dist/cjs/ProductQuickView/cloneProductForQuickView.d.ts +7 -0
- package/dist/cjs/ProductQuickView/cloneProductForQuickView.d.ts.map +1 -0
- package/dist/cjs/ProductQuickView/cloneProductForQuickView.js +23 -0
- package/dist/cjs/Recommendation/RecommendationStore.d.ts +2 -0
- package/dist/cjs/Recommendation/RecommendationStore.d.ts.map +1 -1
- package/dist/cjs/Recommendation/RecommendationStore.js +3 -0
- package/dist/cjs/Recommendation/Stores/RecommendationProfileStore.js +1 -1
- package/dist/cjs/Search/SearchStore.d.ts +1 -1
- package/dist/cjs/Search/SearchStore.d.ts.map +1 -1
- package/dist/cjs/Search/SearchStore.js +2 -2
- package/dist/cjs/Search/Stores/SearchFacetStore.d.ts +12 -12
- package/dist/cjs/Search/Stores/SearchFacetStore.d.ts.map +1 -1
- package/dist/cjs/Search/Stores/SearchFacetStore.js +25 -32
- package/dist/cjs/Search/Stores/SearchHistoryStore.js +2 -2
- package/dist/cjs/index.d.ts +4 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -4
- package/dist/cjs/types.d.ts +8 -2
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/esm/Autocomplete/AutocompleteStore.d.ts +1 -1
- package/dist/esm/Autocomplete/AutocompleteStore.d.ts.map +1 -1
- package/dist/esm/Autocomplete/AutocompleteStore.js +5 -3
- package/dist/esm/Autocomplete/Stores/AutocompleteFacetStore.d.ts.map +1 -1
- package/dist/esm/Autocomplete/Stores/AutocompleteFacetStore.js +4 -6
- package/dist/esm/Chat/ChatStore.d.ts +35 -6
- package/dist/esm/Chat/ChatStore.d.ts.map +1 -1
- package/dist/esm/Chat/ChatStore.js +188 -65
- package/dist/esm/Chat/Stores/ChatAttachmentStore.d.ts.map +1 -1
- package/dist/esm/Chat/Stores/ChatAttachmentStore.js +3 -3
- package/dist/esm/Chat/Stores/ChatCompareStore.d.ts +2 -0
- package/dist/esm/Chat/Stores/ChatCompareStore.d.ts.map +1 -1
- package/dist/esm/Chat/Stores/ChatCompareStore.js +3 -1
- package/dist/esm/Chat/Stores/ChatSessionStore.d.ts +10 -20
- package/dist/esm/Chat/Stores/ChatSessionStore.d.ts.map +1 -1
- package/dist/esm/Chat/Stores/ChatSessionStore.js +26 -86
- package/dist/esm/Finder/FinderStore.d.ts +1 -1
- package/dist/esm/Finder/FinderStore.d.ts.map +1 -1
- package/dist/esm/Finder/FinderStore.js +1 -1
- package/dist/esm/Finder/Stores/FinderSelectionStore.d.ts +1 -1
- package/dist/esm/Finder/Stores/FinderSelectionStore.d.ts.map +1 -1
- package/dist/esm/ProductQuickView/ProductQuickViewStore.d.ts +21 -0
- package/dist/esm/ProductQuickView/ProductQuickViewStore.d.ts.map +1 -0
- package/dist/esm/ProductQuickView/ProductQuickViewStore.js +56 -0
- package/dist/esm/ProductQuickView/cloneProductForQuickView.d.ts +7 -0
- package/dist/esm/ProductQuickView/cloneProductForQuickView.d.ts.map +1 -0
- package/dist/esm/ProductQuickView/cloneProductForQuickView.js +19 -0
- package/dist/esm/Recommendation/RecommendationStore.d.ts +2 -0
- package/dist/esm/Recommendation/RecommendationStore.d.ts.map +1 -1
- package/dist/esm/Recommendation/RecommendationStore.js +3 -0
- package/dist/esm/Recommendation/Stores/RecommendationProfileStore.js +1 -1
- package/dist/esm/Search/SearchStore.d.ts +1 -1
- package/dist/esm/Search/SearchStore.d.ts.map +1 -1
- package/dist/esm/Search/SearchStore.js +1 -1
- package/dist/esm/Search/Stores/SearchFacetStore.d.ts +12 -12
- package/dist/esm/Search/Stores/SearchFacetStore.d.ts.map +1 -1
- package/dist/esm/Search/Stores/SearchFacetStore.js +25 -31
- package/dist/esm/Search/Stores/SearchHistoryStore.js +1 -1
- package/dist/esm/index.d.ts +4 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/types.d.ts +8 -2
- package/dist/esm/types.d.ts.map +1 -1
- package/package.json +11 -6
- package/dist/cjs/Storage/StorageStore.d.ts +0 -27
- package/dist/cjs/Storage/StorageStore.d.ts.map +0 -1
- package/dist/cjs/Storage/StorageStore.js +0 -176
- package/dist/esm/Storage/StorageStore.d.ts +0 -27
- package/dist/esm/Storage/StorageStore.d.ts.map +0 -1
- package/dist/esm/Storage/StorageStore.js +0 -169
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { makeObservable, observable, computed } from 'mobx';
|
|
1
|
+
import { makeObservable, observable, computed, reaction } from 'mobx';
|
|
2
2
|
import { MetaStore } from '../Meta/MetaStore';
|
|
3
3
|
import { AbstractStore } from '../Abstract/AbstractStore';
|
|
4
|
-
import { StorageStore } from '
|
|
4
|
+
import { StorageStore } from '@athoscommerce/snap-toolbox';
|
|
5
5
|
import { ChatSessionStore } from './Stores/ChatSessionStore';
|
|
6
|
-
import { Variants } from '../Search/Stores/SearchResultStore';
|
|
6
|
+
import { Product, Variants } from '../Search/Stores/SearchResultStore';
|
|
7
|
+
import { SearchFacetStore } from '../Search/Stores/SearchFacetStore';
|
|
7
8
|
const CHAT_STATUS_EXPIRATION_TIME = 1000 * 60 * 60 * 12; // 12 hours
|
|
8
9
|
export class ChatStore extends AbstractStore {
|
|
9
|
-
constructor(config) {
|
|
10
|
+
constructor(config, services) {
|
|
10
11
|
super(config);
|
|
11
12
|
this.meta = undefined;
|
|
12
13
|
this.inputValue = '';
|
|
@@ -21,12 +22,25 @@ export class ChatStore extends AbstractStore {
|
|
|
21
22
|
this.productQuickviewError = null;
|
|
22
23
|
/** Raw meta kept for lazy hydration of inactive chat sessions. */
|
|
23
24
|
this.storedMetaData = null;
|
|
25
|
+
/** Tracks which message currently owns the displayed facets — guards against redundant rebuilds. */
|
|
26
|
+
this.activeFacetsMessageId = null;
|
|
27
|
+
/** Bumps on every detached-urlManager change so observers re-evaluate isFacetSelected. */
|
|
28
|
+
this.urlVersion = 0;
|
|
29
|
+
/** Snapshot of the applied filter state captured the last time the active message was seeded.
|
|
30
|
+
* Compared against the live urlManager state to decide whether there are pending changes. */
|
|
31
|
+
this.appliedFilterSnapshot = '{}';
|
|
32
|
+
this.services = services;
|
|
33
|
+
this.urlManager = services.urlManager.detach(true);
|
|
34
|
+
this.urlManager.subscribe(() => {
|
|
35
|
+
this.urlVersion++;
|
|
36
|
+
});
|
|
24
37
|
const legacyKey = `ss-${this.config.id}`;
|
|
25
38
|
const storageKey = this.config.siteId ? `ss-${this.config.siteId}-${this.config.id}` : legacyKey;
|
|
26
39
|
this.storage = new StorageStore({
|
|
27
40
|
type: 'local',
|
|
28
41
|
key: storageKey,
|
|
29
42
|
});
|
|
43
|
+
this.facets = this.buildFacetStore();
|
|
30
44
|
const storedChatStatusResponse = this.storage.get('chatStatusResponse');
|
|
31
45
|
if (storedChatStatusResponse) {
|
|
32
46
|
try {
|
|
@@ -113,7 +127,95 @@ export class ChatStore extends AbstractStore {
|
|
|
113
127
|
welcomeMessage: observable,
|
|
114
128
|
productQuickview: observable,
|
|
115
129
|
productQuickviewError: observable,
|
|
130
|
+
facets: observable,
|
|
131
|
+
urlVersion: observable,
|
|
132
|
+
hasPendingFacetChanges: computed,
|
|
133
|
+
});
|
|
134
|
+
// Sync the root facets display with the active message. Only productSearchResult
|
|
135
|
+
// messages carry facets — for any other active message, clear the display so a
|
|
136
|
+
// stale facet bar from a previous response doesn't linger.
|
|
137
|
+
reaction(() => {
|
|
138
|
+
const active = this.currentChat?.activeMessage;
|
|
139
|
+
return active && active.messageType === 'productSearchResult' ? active : null;
|
|
140
|
+
}, (active) => {
|
|
141
|
+
if (active && active.id !== this.activeFacetsMessageId) {
|
|
142
|
+
const facets = active.facets;
|
|
143
|
+
this.setActiveFacets(facets || [], active.id);
|
|
144
|
+
}
|
|
145
|
+
else if (!active && this.activeFacetsMessageId !== null) {
|
|
146
|
+
this.setActiveFacets([], null);
|
|
147
|
+
}
|
|
148
|
+
}, { fireImmediately: true });
|
|
149
|
+
}
|
|
150
|
+
/** Build a SearchFacetStore from raw facet data using the current detached urlManager.
|
|
151
|
+
* Synthesizes meta entries for each facet so SearchFacetStore's display/meta filter
|
|
152
|
+
* doesn't drop chat facets (the chat backend already decided what to send). */
|
|
153
|
+
buildFacetStore(facets = []) {
|
|
154
|
+
const baseMeta = this.meta?.data || {};
|
|
155
|
+
const baseFacetMeta = baseMeta.facets || {};
|
|
156
|
+
const facetMeta = { ...baseFacetMeta };
|
|
157
|
+
facets.forEach((facet) => {
|
|
158
|
+
if (!facet.field)
|
|
159
|
+
return;
|
|
160
|
+
const expectedDisplay = facet.type === 'range' ? 'slider' : 'list';
|
|
161
|
+
const existing = facetMeta[facet.field];
|
|
162
|
+
if (!existing || existing.display !== expectedDisplay) {
|
|
163
|
+
facetMeta[facet.field] = {
|
|
164
|
+
...(existing || {}),
|
|
165
|
+
field: facet.field,
|
|
166
|
+
label: facet.label,
|
|
167
|
+
display: expectedDisplay,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
return new SearchFacetStore({
|
|
172
|
+
config: {},
|
|
173
|
+
services: { ...this.services, urlManager: this.urlManager },
|
|
174
|
+
stores: { storage: this.storage },
|
|
175
|
+
data: {
|
|
176
|
+
search: { facets },
|
|
177
|
+
meta: { ...baseMeta, facets: facetMeta },
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/** Reset the detached urlManager and seed it with this message's filtered facet values,
|
|
182
|
+
* then rebuild the root SearchFacetStore so the UI shows the matching display. */
|
|
183
|
+
setActiveFacets(facets, messageId) {
|
|
184
|
+
// reset url state, then seed with the API-reported filtered values
|
|
185
|
+
this.urlManager.reset().go();
|
|
186
|
+
facets.forEach((facet) => {
|
|
187
|
+
// Slider/range facets carry the active selection on the facet itself rather
|
|
188
|
+
// than on individual bucket values.
|
|
189
|
+
if (facet.type === 'range') {
|
|
190
|
+
const active = facet.active;
|
|
191
|
+
const range = facet.range;
|
|
192
|
+
if (active && range && (active.low !== range.low || active.high !== range.high)) {
|
|
193
|
+
this.urlManager.set(`filter.${facet.field}`, { low: active.low, high: active.high }).go();
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const filteredValues = (facet.values || []).filter((v) => v?.filtered);
|
|
198
|
+
filteredValues.forEach((v) => {
|
|
199
|
+
if (typeof v.low !== 'undefined' || typeof v.high !== 'undefined') {
|
|
200
|
+
this.urlManager.merge(`filter.${facet.field}`, [{ low: v.low, high: v.high }]).go();
|
|
201
|
+
}
|
|
202
|
+
else if (typeof v.value !== 'undefined') {
|
|
203
|
+
this.urlManager.merge(`filter.${facet.field}`, v.value).go();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
116
206
|
});
|
|
207
|
+
this.facets = this.buildFacetStore(facets);
|
|
208
|
+
this.activeFacetsMessageId = messageId;
|
|
209
|
+
this.appliedFilterSnapshot = stableStringify(this.urlManager.state?.filter);
|
|
210
|
+
}
|
|
211
|
+
/** True when the in-progress facet selection differs from the filters that were applied
|
|
212
|
+
* by the active productSearchResult — i.e. the user has selected/removed something that
|
|
213
|
+
* hasn't been sent yet. Used to decide whether to show the Apply button. */
|
|
214
|
+
get hasPendingFacetChanges() {
|
|
215
|
+
// touch the version so mobx re-runs this when urlManager state changes
|
|
216
|
+
void this.urlVersion;
|
|
217
|
+
const current = stableStringify(this.urlManager.state?.filter);
|
|
218
|
+
return current !== this.appliedFilterSnapshot;
|
|
117
219
|
}
|
|
118
220
|
get currentChat() {
|
|
119
221
|
return this.chats.find((chat) => chat.id === this.currentChatId);
|
|
@@ -152,7 +254,10 @@ export class ChatStore extends AbstractStore {
|
|
|
152
254
|
this.createChat();
|
|
153
255
|
}
|
|
154
256
|
setProductQuickview(product) {
|
|
155
|
-
|
|
257
|
+
// Clone the product so variant selections (and the parent-mappings merge done
|
|
258
|
+
// in updateProductQuickview) only affect the quickview — the carousel and any
|
|
259
|
+
// other surfaces still hold the original instance.
|
|
260
|
+
this.productQuickview = cloneProductForQuickview(product, this.meta?.data);
|
|
156
261
|
this.productQuickviewError = null;
|
|
157
262
|
}
|
|
158
263
|
updateProductQuickview(response) {
|
|
@@ -216,6 +321,7 @@ export class ChatStore extends AbstractStore {
|
|
|
216
321
|
const newChat = new ChatSessionStore({
|
|
217
322
|
data: {
|
|
218
323
|
sessionId: data?.sessionId,
|
|
324
|
+
sessionEndTime: data?.sessionEndTime,
|
|
219
325
|
},
|
|
220
326
|
stores: {
|
|
221
327
|
storage: this.storage,
|
|
@@ -260,75 +366,45 @@ export class ChatStore extends AbstractStore {
|
|
|
260
366
|
});
|
|
261
367
|
}
|
|
262
368
|
addFacet(facet) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
key: facet.key,
|
|
266
|
-
facetLabel: facet.facetLabel,
|
|
267
|
-
value: facet.value,
|
|
268
|
-
label: facet.label,
|
|
269
|
-
count: facet.count,
|
|
270
|
-
});
|
|
271
|
-
// If re-selecting a previously removed server-side filter, remove it from removedFacets
|
|
272
|
-
if (this.currentChat) {
|
|
273
|
-
const removedIndex = this.currentChat.removedFacets.findIndex((rf) => rf.key === facet.key && rf.value === facet.value);
|
|
274
|
-
if (removedIndex !== -1) {
|
|
275
|
-
this.currentChat.removedFacets.splice(removedIndex, 1);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
369
|
+
const value = parseFacetValue(facet.value);
|
|
370
|
+
this.urlManager.merge(`filter.${facet.key}`, Array.isArray(value) ? value : value).go();
|
|
278
371
|
}
|
|
279
372
|
removeFacet(key, value) {
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
item.value === value &&
|
|
283
|
-
(item.state === 'active' || item.state === 'attached'));
|
|
284
|
-
if (facetAttachment) {
|
|
285
|
-
const index = this.currentChat?.attachments.items.indexOf(facetAttachment);
|
|
286
|
-
if (index !== undefined && index !== -1) {
|
|
287
|
-
this.currentChat?.attachments.items.splice(index, 1);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
else if (this.currentChat) {
|
|
291
|
-
// No attachment exists — this is a server-side filtered facet.
|
|
292
|
-
// Track it as explicitly removed so the next request excludes it.
|
|
293
|
-
const alreadyRemoved = this.currentChat.removedFacets.some((rf) => rf.key === key && rf.value === value);
|
|
294
|
-
if (!alreadyRemoved) {
|
|
295
|
-
this.currentChat.removedFacets.push({ key, value });
|
|
296
|
-
}
|
|
297
|
-
}
|
|
373
|
+
const parsed = parseFacetValue(value);
|
|
374
|
+
this.urlManager.remove(`filter.${key}`, parsed).go();
|
|
298
375
|
}
|
|
299
376
|
clearPendingFacets() {
|
|
300
|
-
|
|
301
|
-
facetAttachments.forEach((item) => {
|
|
302
|
-
const index = this.currentChat?.attachments.items.indexOf(item);
|
|
303
|
-
if (index !== undefined && index !== -1) {
|
|
304
|
-
this.currentChat?.attachments.items.splice(index, 1);
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
if (this.currentChat) {
|
|
308
|
-
this.currentChat.removedFacets = [];
|
|
309
|
-
}
|
|
377
|
+
this.urlManager.remove('filter').go();
|
|
310
378
|
}
|
|
311
379
|
isFacetSelected(key, value) {
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
|
|
380
|
+
// touch the version so mobx re-runs this when urlManager state changes (the
|
|
381
|
+
// underlying UrlManager isn't a mobx observable, so we mirror its updates here)
|
|
382
|
+
void this.urlVersion;
|
|
383
|
+
const filterState = this.urlManager.state?.filter;
|
|
384
|
+
if (!filterState || !filterState[key])
|
|
315
385
|
return false;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
item.value === value &&
|
|
320
|
-
(item.state === 'active' || item.state === 'attached')) || false);
|
|
321
|
-
}
|
|
322
|
-
isFacetRemoved(key, value) {
|
|
323
|
-
return this.currentChat?.removedFacets.some((rf) => rf.key === key && rf.value === value) || false;
|
|
386
|
+
const stored = Array.isArray(filterState[key]) ? filterState[key] : [filterState[key]];
|
|
387
|
+
const parsed = parseFacetValue(value);
|
|
388
|
+
return stored.some((entry) => facetValueEquals(entry, parsed));
|
|
324
389
|
}
|
|
325
390
|
request(request) {
|
|
326
|
-
|
|
327
|
-
//
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
391
|
+
// snapshot facet labels (field + per-value) from the active facets display so the
|
|
392
|
+
// outgoing user message can render "Filter by Color Red" rather than raw keys
|
|
393
|
+
const filterLabels = {};
|
|
394
|
+
for (const facet of this.facets) {
|
|
395
|
+
const valueFacet = facet;
|
|
396
|
+
const values = {};
|
|
397
|
+
(valueFacet.values || []).forEach((v) => {
|
|
398
|
+
if (typeof v.low !== 'undefined' || typeof v.high !== 'undefined') {
|
|
399
|
+
values[`${v.low ?? '*'}:${v.high ?? '*'}`] = v.label;
|
|
400
|
+
}
|
|
401
|
+
else if (typeof v.value !== 'undefined') {
|
|
402
|
+
values[v.value] = v.label;
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
filterLabels[valueFacet.field] = { facetLabel: valueFacet.label || valueFacet.field, values };
|
|
406
|
+
}
|
|
407
|
+
this.currentChat?.request(request, filterLabels);
|
|
332
408
|
// remove any productSimilar attachments after request
|
|
333
409
|
const productSimilarAttachments = this.currentChat?.attachments.attached.filter((item) => item.type === 'product' && item.requestType === 'productSimilar') || [];
|
|
334
410
|
productSimilarAttachments.forEach((item) => {
|
|
@@ -353,3 +429,50 @@ export class ChatStore extends AbstractStore {
|
|
|
353
429
|
this.storedMetaData = data.meta;
|
|
354
430
|
}
|
|
355
431
|
}
|
|
432
|
+
/** Deterministic JSON.stringify — sorts object keys recursively so equality comparisons
|
|
433
|
+
* aren't sensitive to insertion order. */
|
|
434
|
+
function stableStringify(value) {
|
|
435
|
+
if (value === null || value === undefined)
|
|
436
|
+
return 'null';
|
|
437
|
+
if (typeof value !== 'object')
|
|
438
|
+
return JSON.stringify(value);
|
|
439
|
+
if (Array.isArray(value)) {
|
|
440
|
+
return `[${value.map((v) => stableStringify(v)).join(',')}]`;
|
|
441
|
+
}
|
|
442
|
+
const keys = Object.keys(value).sort();
|
|
443
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(',')}}`;
|
|
444
|
+
}
|
|
445
|
+
/** Convert a chat-facet UI value into the URL-state shape — range buckets arrive as "low:high". */
|
|
446
|
+
function parseFacetValue(value) {
|
|
447
|
+
if (typeof value === 'string' && value.includes(':')) {
|
|
448
|
+
const [low, high] = value.split(':');
|
|
449
|
+
return {
|
|
450
|
+
low: low === '*' ? undefined : Number(low),
|
|
451
|
+
high: high === '*' ? undefined : Number(high),
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
return value;
|
|
455
|
+
}
|
|
456
|
+
function facetValueEquals(a, b) {
|
|
457
|
+
if (typeof a === 'object' && a !== null && typeof b === 'object' && b !== null) {
|
|
458
|
+
return a.low === b.low && a.high === b.high;
|
|
459
|
+
}
|
|
460
|
+
return a === b;
|
|
461
|
+
}
|
|
462
|
+
/** Build a fresh observable Product from an existing one. Variants are intentionally
|
|
463
|
+
* omitted — `updateProductQuickview` populates them from the products API response. */
|
|
464
|
+
function cloneProductForQuickview(product, meta) {
|
|
465
|
+
const result = {
|
|
466
|
+
id: product.id,
|
|
467
|
+
responseId: product.responseId,
|
|
468
|
+
mappings: JSON.parse(JSON.stringify(product.mappings || {})),
|
|
469
|
+
attributes: JSON.parse(JSON.stringify(product.attributes || {})),
|
|
470
|
+
badges: product.badges?.all?.map((b) => ({ tag: b.tag })) || [],
|
|
471
|
+
};
|
|
472
|
+
return new Product({
|
|
473
|
+
config: {},
|
|
474
|
+
data: { result, meta: meta || {} },
|
|
475
|
+
position: product.position ?? 0,
|
|
476
|
+
responseId: product.responseId,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatAttachmentStore.d.ts","sourceRoot":"","sources":["../../../../src/Chat/Stores/ChatAttachmentStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ChatAttachmentStore.d.ts","sourceRoot":"","sources":["../../../../src/Chat/Stores/ChatAttachmentStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// how should localStorage be handled for attachments?
|
|
3
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
4
4
|
import { makeObservable, observable, computed } from 'mobx';
|
|
5
|
+
import { CHAT_COMPARISON_MAX } from './ChatCompareStore';
|
|
5
6
|
export class ChatAttachmentStore {
|
|
6
7
|
constructor() {
|
|
7
8
|
this.items = [];
|
|
@@ -58,11 +59,10 @@ export class ChatAttachmentStore {
|
|
|
58
59
|
existingProductAttachment.requestType = attachment.requestType; // changes existing attachments to the incoming requestType
|
|
59
60
|
return existingProductAttachment;
|
|
60
61
|
}
|
|
61
|
-
// productComparison supports up to
|
|
62
|
+
// productComparison supports up to CHAT_COMPARISON_MAX products (matches ChatCompareStore.maxItems);
|
|
62
63
|
// trim oldest active/attached product attachments to keep total below the cap.
|
|
63
|
-
const COMPARISON_MAX = 4;
|
|
64
64
|
const productAttachments = this.items.filter((item) => item.type === 'product' && (item.state === 'active' || item.state === 'attached'));
|
|
65
|
-
while (productAttachments.length >=
|
|
65
|
+
while (productAttachments.length >= CHAT_COMPARISON_MAX) {
|
|
66
66
|
const toRemove = productAttachments.pop();
|
|
67
67
|
if (toRemove) {
|
|
68
68
|
this.remove(toRemove.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatCompareStore.d.ts","sourceRoot":"","sources":["../../../../src/Chat/Stores/ChatCompareStore.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IACrB,KAAK,EAAE,GAAG,EAAE,CAAM;IAClB,cAAc,EAAE,GAAG,EAAE,CAAM;IAC3B,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ChatCompareStore.d.ts","sourceRoot":"","sources":["../../../../src/Chat/Stores/ChatCompareStore.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,qBAAa,gBAAgB;IACrB,KAAK,EAAE,GAAG,EAAE,CAAM;IAClB,cAAc,EAAE,GAAG,EAAE,CAAM;IAC3B,QAAQ,EAAE,MAAM,CAAuB;;IAa9C,GAAG,CAAC,IAAI,EAAE,GAAG;IAYb,MAAM,CAAC,MAAM,EAAE,MAAM;IAIrB,KAAK;IAIL,cAAc;IAKd,MAAM;IAON,IAAI,QAAQ,UAEX;IAED,IAAI,SAAS,UAEZ;CACD"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { computed, makeObservable, observable } from 'mobx';
|
|
2
|
+
/** Maximum number of products that can be added to a chat comparison. */
|
|
3
|
+
export const CHAT_COMPARISON_MAX = 4;
|
|
2
4
|
export class ChatCompareStore {
|
|
3
5
|
constructor() {
|
|
4
6
|
this.items = [];
|
|
5
7
|
this.committedItems = [];
|
|
6
|
-
this.maxItems =
|
|
8
|
+
this.maxItems = CHAT_COMPARISON_MAX;
|
|
7
9
|
makeObservable(this, {
|
|
8
10
|
items: observable,
|
|
9
11
|
committedItems: observable,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { ChatResponseModel, ChatRequestModel, ChatResponseTextData, ChatResponseProductSearchResultData, ChatResponseInspirationResultData, ChatResponseContentData, ChatResponseProductAnswerData, ChatResponseProductComparisonData, ChatResponseProductRecommendationData, ChatResponseErrorData, ChatResponseTopicDriftData } from '@athoscommerce/snap-client';
|
|
2
2
|
import { ChatAttachmentAddAttachment, ChatAttachmentStore } from '../Stores/ChatAttachmentStore';
|
|
3
|
-
import type { StorageStore } from '
|
|
3
|
+
import type { StorageStore } from '@athoscommerce/snap-toolbox';
|
|
4
4
|
import { MetaResponseModel } from '@athoscommerce/snapi-types';
|
|
5
5
|
import { ChatCompareStore } from './ChatCompareStore';
|
|
6
|
-
import { SearchFacetStore } from '../../Search/Stores/SearchFacetStore';
|
|
7
6
|
export type ChatFeedbacks = {
|
|
8
7
|
messageId: string;
|
|
9
8
|
rating: 'UP' | 'DOWN';
|
|
@@ -38,28 +37,23 @@ type ChatSessionStoreConfig = {
|
|
|
38
37
|
sessionFeedback?: ChatSessionFeedback | null;
|
|
39
38
|
feedbackDismissed?: boolean;
|
|
40
39
|
createdAt?: Date;
|
|
40
|
+
sessionEndTime?: Date;
|
|
41
41
|
committedComparisons?: any[];
|
|
42
42
|
};
|
|
43
43
|
stores: {
|
|
44
44
|
storage: StorageStore;
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
-
export type FacetsData = {
|
|
48
|
-
type: 'facets';
|
|
49
|
-
data: SearchFacetStore;
|
|
50
|
-
filterSummary?: {
|
|
51
|
-
field: string;
|
|
52
|
-
value: string;
|
|
53
|
-
label?: string;
|
|
54
|
-
filterLabel?: string;
|
|
55
|
-
filterValue?: string;
|
|
56
|
-
}[];
|
|
57
|
-
};
|
|
58
47
|
export type ActionsData = {
|
|
59
48
|
type: 'actions';
|
|
60
49
|
data: any;
|
|
61
50
|
};
|
|
62
|
-
export type ChatActions =
|
|
51
|
+
export type ChatActions = ActionsData[];
|
|
52
|
+
/** Snapshot of facet labels keyed by field — used to render the user message text for a productSearch request. */
|
|
53
|
+
export type FilterLabelMap = Record<string, {
|
|
54
|
+
facetLabel: string;
|
|
55
|
+
values: Record<string, string>;
|
|
56
|
+
}>;
|
|
63
57
|
export declare class ChatSessionStore {
|
|
64
58
|
chat: ChatMessage[];
|
|
65
59
|
actions: ChatActions;
|
|
@@ -73,15 +67,11 @@ export declare class ChatSessionStore {
|
|
|
73
67
|
feedbackDismissed: boolean;
|
|
74
68
|
feedbackJustGiven: boolean;
|
|
75
69
|
createdAt: Date;
|
|
70
|
+
sessionEndTime?: Date;
|
|
76
71
|
requestType: string;
|
|
77
72
|
dismissedSideChatMessageId: string | null;
|
|
78
73
|
activeMessageId: string | null;
|
|
79
74
|
sessionLimitReached: boolean;
|
|
80
|
-
/** Tracks server-filtered facets the user has explicitly unselected (pending next request). */
|
|
81
|
-
removedFacets: {
|
|
82
|
-
key: string;
|
|
83
|
-
value: string;
|
|
84
|
-
}[];
|
|
85
75
|
/** Whether raw stored results have been hydrated into Product/SearchResultStore instances. */
|
|
86
76
|
hydrated: boolean;
|
|
87
77
|
constructor(params: ChatSessionStoreConfig);
|
|
@@ -107,7 +97,7 @@ export declare class ChatSessionStore {
|
|
|
107
97
|
static pruneStoredSessions(storage: StorageStore, maxSessions?: number): void;
|
|
108
98
|
/** Re-wrap raw stored results as Product / SearchResultStore instances. */
|
|
109
99
|
hydrateResults(meta: MetaResponseModel): void;
|
|
110
|
-
request(request: ChatRequestModel): void;
|
|
100
|
+
request(request: ChatRequestModel, filterLabels?: FilterLabelMap): void;
|
|
111
101
|
update(data: {
|
|
112
102
|
chat: ChatResponseModel;
|
|
113
103
|
meta: MetaResponseModel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatSessionStore.d.ts","sourceRoot":"","sources":["../../../../src/Chat/Stores/ChatSessionStore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,mCAAmC,EACnC,iCAAiC,EACjC,uBAAuB,EACvB,6BAA6B,EAC7B,iCAAiC,EACjC,qCAAqC,EACrC,qBAAqB,EACrB,0BAA0B,EAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,2BAA2B,EAI3B,mBAAmB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ChatSessionStore.d.ts","sourceRoot":"","sources":["../../../../src/Chat/Stores/ChatSessionStore.ts"],"names":[],"mappings":"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"}
|