wineater-bot 4.11.0 → 4.16.0
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/wineater-chatbot.mjs +3279 -3218
- package/dist/wineater-chatbot.umd.js +29 -23
- package/package.json +1 -1
- package/src/App.svelte +25 -5
- package/src/components/WineTile.svelte +29 -3
- package/src/services/i18n/translations.json +9 -9
- package/src/services/ui-config/projects-config.ts +1 -1
- package/src/services/ui-config/projects-config 2.ts +0 -72
package/package.json
CHANGED
package/src/App.svelte
CHANGED
|
@@ -44,6 +44,9 @@
|
|
|
44
44
|
// должен повторять именно тот запрос, что дал текущие results.
|
|
45
45
|
let lastSearchedQuery = $state('');
|
|
46
46
|
let hasMore = $state(false);
|
|
47
|
+
// Всё, что уже показывали по текущему запросу — «Try again» заменяет выдачу,
|
|
48
|
+
// и без накопления повторный клик вернул бы те же вина.
|
|
49
|
+
let seenIds = $state<string[]>([]);
|
|
47
50
|
let appLanguage = $derived(appStore.getAppLanguage());
|
|
48
51
|
let storeLanguage = $derived(appStore.getStoreLanguage());
|
|
49
52
|
let apiKey = $derived(appStore.getApiKey());
|
|
@@ -138,6 +141,7 @@
|
|
|
138
141
|
results = [];
|
|
139
142
|
isAnimating = false;
|
|
140
143
|
hasMore = false;
|
|
144
|
+
seenIds = [];
|
|
141
145
|
|
|
142
146
|
query = searchQuery.trim() + ';';
|
|
143
147
|
lastSearchedQuery = query;
|
|
@@ -182,24 +186,40 @@
|
|
|
182
186
|
|
|
183
187
|
async function handleShowMore() {
|
|
184
188
|
if (isLoadingMore || !hasMore) return;
|
|
189
|
+
// Выдача заменяется целиком, поэтому держим предыдущую под рукой: если
|
|
190
|
+
// новых вин не нашлось или запрос упал, покупатель не должен остаться
|
|
191
|
+
// перед пустой сеткой.
|
|
192
|
+
const previousResults = results;
|
|
185
193
|
try {
|
|
186
194
|
isLoadingMore = true;
|
|
187
|
-
|
|
195
|
+
isLoading = true;
|
|
196
|
+
|
|
197
|
+
// Карточки заменяются, а не дописываются, поэтому исключать надо всё
|
|
198
|
+
// показанное за сессию — иначе следующий клик вернёт те же вина.
|
|
199
|
+
seenIds = [...new Set([...seenIds, ...results.map((w) => w.id)])];
|
|
200
|
+
|
|
201
|
+
// Тот же жест, что и при поиске: карточки уезжают вверх, дальше лоадер
|
|
202
|
+
await animateClearAll(220);
|
|
203
|
+
results = [];
|
|
204
|
+
isAnimating = false;
|
|
205
|
+
|
|
188
206
|
const { recommendations, hasMore: more } = await wineaterApi.getMoreWineRecommendations(
|
|
189
207
|
lastSearchedQuery,
|
|
190
|
-
|
|
208
|
+
seenIds
|
|
191
209
|
);
|
|
192
210
|
trackWidgetEvent(WIDGET_EVENTS.SHOW_MORE_CLICKED, storeId, {
|
|
193
211
|
query: lastSearchedQuery,
|
|
194
212
|
results_count: recommendations.length
|
|
195
213
|
});
|
|
196
|
-
results =
|
|
214
|
+
results = recommendations.length > 0 ? recommendations : previousResults;
|
|
197
215
|
hasMore = more;
|
|
198
216
|
} catch (error) {
|
|
199
|
-
console.error('[wineater]
|
|
217
|
+
console.error('[wineater] try again error:', error);
|
|
218
|
+
results = previousResults;
|
|
200
219
|
hasMore = false;
|
|
201
220
|
} finally {
|
|
202
221
|
isLoadingMore = false;
|
|
222
|
+
isLoading = false;
|
|
203
223
|
}
|
|
204
224
|
}
|
|
205
225
|
|
|
@@ -406,7 +426,7 @@
|
|
|
406
426
|
{#if hasMore}
|
|
407
427
|
<div class="wr-App-showMore">
|
|
408
428
|
<Action handleClick={handleShowMore} variant="outlined">
|
|
409
|
-
{getTranslation({ key: '
|
|
429
|
+
{getTranslation({ key: 'tryAgain', lang: appLanguage })}
|
|
410
430
|
</Action>
|
|
411
431
|
</div>
|
|
412
432
|
{/if}
|
|
@@ -287,11 +287,37 @@
|
|
|
287
287
|
gap: 8px;
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
|
|
291
|
-
|
|
290
|
+
/* :global обязателен — класс уезжает внутрь <Action>, а скоуп Svelte
|
|
291
|
+
действует только на разметку этого компонента, иначе правило отбрасывается
|
|
292
|
+
как неиспользуемое. Цвет тот же, что у Buy; подчёркивание выезжает слева. */
|
|
293
|
+
:global(.wr-WineTile-action--similar) {
|
|
294
|
+
/* Заметно легче кнопки Buy (14px/500) — это вторичное действие, не кнопка */
|
|
295
|
+
font-size: 12px;
|
|
296
|
+
font-weight: 400;
|
|
292
297
|
color: var(--wr-brand-color, #7b2beb);
|
|
293
|
-
text-decoration:
|
|
298
|
+
text-decoration: none;
|
|
299
|
+
background: transparent;
|
|
300
|
+
border: none;
|
|
294
301
|
padding: 0;
|
|
302
|
+
position: relative;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
:global(.wr-WineTile-action--similar)::after {
|
|
306
|
+
content: '';
|
|
307
|
+
position: absolute;
|
|
308
|
+
left: 0;
|
|
309
|
+
bottom: -2px;
|
|
310
|
+
width: 100%;
|
|
311
|
+
height: 1px;
|
|
312
|
+
background-color: currentColor;
|
|
313
|
+
transform: scaleX(0);
|
|
314
|
+
transform-origin: left;
|
|
315
|
+
transition: transform 180ms cubic-bezier(0.22, 0.61, 0.36, 1);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
:global(.wr-WineTile-action--similar:hover)::after,
|
|
319
|
+
:global(.wr-WineTile-action--similar:focus-visible)::after {
|
|
320
|
+
transform: scaleX(1);
|
|
295
321
|
}
|
|
296
322
|
|
|
297
323
|
/* Hover popup inside tile */
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"type": "Type",
|
|
18
18
|
"reason": "Suggestion",
|
|
19
19
|
"moreInfo": "Plus d'infos",
|
|
20
|
-
"
|
|
20
|
+
"tryAgain": "Réessayer",
|
|
21
21
|
"similarWines": "Vins similaires",
|
|
22
22
|
"byTheGlass": "Au verre",
|
|
23
23
|
"winePairingIntro": "Pour ce vin, voici quelques suggestions de plats :",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"type": "Tipo",
|
|
84
84
|
"reason": "Sugerencia",
|
|
85
85
|
"moreInfo": "Más info",
|
|
86
|
-
"
|
|
86
|
+
"tryAgain": "Probar otra vez",
|
|
87
87
|
"similarWines": "Vinos similares",
|
|
88
88
|
"byTheGlass": "Por copa",
|
|
89
89
|
"winePairingIntro": "Para este vino, aquí tienes algunas sugerencias de platos:",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"type": "Type",
|
|
150
150
|
"reason": "Suggestion",
|
|
151
151
|
"moreInfo": "More info",
|
|
152
|
-
"
|
|
152
|
+
"tryAgain": "Try again",
|
|
153
153
|
"similarWines": "Similar wines",
|
|
154
154
|
"byTheGlass": "By the glass",
|
|
155
155
|
"winePairingIntro": "For this wine, here are some suggested dishes:",
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
"type": "Tip",
|
|
216
216
|
"reason": "Preporuka",
|
|
217
217
|
"moreInfo": "Više informacija",
|
|
218
|
-
"
|
|
218
|
+
"tryAgain": "Pokušaj ponovo",
|
|
219
219
|
"similarWines": "Slična vina",
|
|
220
220
|
"byTheGlass": "Na čašu",
|
|
221
221
|
"winePairingIntro": "Za ovo vino, preporučuju se sledeća jela:",
|
|
@@ -281,7 +281,7 @@
|
|
|
281
281
|
"type": "Typ",
|
|
282
282
|
"reason": "Anregung",
|
|
283
283
|
"moreInfo": "Mehr Info",
|
|
284
|
-
"
|
|
284
|
+
"tryAgain": "Nochmal versuchen",
|
|
285
285
|
"similarWines": "Ähnliche Weine",
|
|
286
286
|
"byTheGlass": "Glasweise",
|
|
287
287
|
"winePairingIntro": "Für diesen Wein gibt es folgende Essensvorschläge:",
|
|
@@ -346,7 +346,7 @@
|
|
|
346
346
|
"type": "Тип",
|
|
347
347
|
"reason": "Рекомендація",
|
|
348
348
|
"moreInfo": "Докладніше",
|
|
349
|
-
"
|
|
349
|
+
"tryAgain": "Спробувати ще",
|
|
350
350
|
"similarWines": "Схожі вина",
|
|
351
351
|
"byTheGlass": "На келих",
|
|
352
352
|
"winePairingIntro": "До цього вина підходять такі страви:",
|
|
@@ -412,7 +412,7 @@
|
|
|
412
412
|
"type": "Тип",
|
|
413
413
|
"reason": "Рекомендация",
|
|
414
414
|
"moreInfo": "Подробнее",
|
|
415
|
-
"
|
|
415
|
+
"tryAgain": "Попробовать ещё",
|
|
416
416
|
"similarWines": "Похожие вина",
|
|
417
417
|
"byTheGlass": "По бокалам",
|
|
418
418
|
"winePairingIntro": "К этому вину подходят следующие блюда:",
|
|
@@ -478,7 +478,7 @@
|
|
|
478
478
|
"type": "Түрі",
|
|
479
479
|
"reason": "Ұсыныс",
|
|
480
480
|
"moreInfo": "Толығырақ",
|
|
481
|
-
"
|
|
481
|
+
"tryAgain": "Қайта көру",
|
|
482
482
|
"similarWines": "Ұқсас шараптар",
|
|
483
483
|
"byTheGlass": "Бокалмен",
|
|
484
484
|
"winePairingIntro": "Бұл шарапқа келесі тағамдар сәйкес келеді:",
|
|
@@ -544,7 +544,7 @@
|
|
|
544
544
|
"type": "Tipo",
|
|
545
545
|
"reason": "Sugestão",
|
|
546
546
|
"moreInfo": "Mais informações",
|
|
547
|
-
"
|
|
547
|
+
"tryAgain": "Tentar de novo",
|
|
548
548
|
"similarWines": "Vinhos semelhantes",
|
|
549
549
|
"byTheGlass": "Por taça",
|
|
550
550
|
"winePairingIntro": "Para este vinho, aqui estão algumas sugestões de pratos:",
|
|
@@ -124,7 +124,7 @@ export const projectConfigs: Record<string, ProjectUiConfig> = {
|
|
|
124
124
|
logoUrl: null,
|
|
125
125
|
brandColor: "#8bae98",
|
|
126
126
|
wineaterColor: "#8bae98",
|
|
127
|
-
titleText: "Looking for the perfect bottle? Ask our AI
|
|
127
|
+
titleText: "Looking for the perfect bottle? Ask our AI Wine Geek for personalised recommendations, whatever the meal, mood or occasion.",
|
|
128
128
|
customCss: `
|
|
129
129
|
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&display=swap');
|
|
130
130
|
:root { --wineater-font-primary: 'Montserrat', Verdana, Helvetica, Arial, sans-serif; }
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { ProjectUiConfig } from "./types";
|
|
2
|
-
|
|
3
|
-
export const projectConfigs: Record<string, ProjectUiConfig> = {
|
|
4
|
-
"0": {
|
|
5
|
-
logoUrl: null,
|
|
6
|
-
brandColor: "#7B2BEB",
|
|
7
|
-
},
|
|
8
|
-
"25": {
|
|
9
|
-
logoUrl: null,
|
|
10
|
-
brandColor: "#000000",
|
|
11
|
-
wineaterColor: "#000000",
|
|
12
|
-
buttonUppercase: true,
|
|
13
|
-
customCss: `
|
|
14
|
-
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
|
|
15
|
-
:root { --wineater-font-primary: 'Roboto', sans-serif; }
|
|
16
|
-
#wr-Custom {
|
|
17
|
-
.wr-Search-input {
|
|
18
|
-
border-color: #7c7c7c;
|
|
19
|
-
color: #7c7c7c;
|
|
20
|
-
}
|
|
21
|
-
.wr-Search-button:hover {
|
|
22
|
-
background: #E3BE8D;
|
|
23
|
-
opacity: 1;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.wr-WineTile-params {
|
|
27
|
-
color: #7c7c7c;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.wr-WineTilePopup-reason {
|
|
31
|
-
color: #000000;
|
|
32
|
-
}
|
|
33
|
-
.wr-WineTilePopup-tag {
|
|
34
|
-
color: #000000;
|
|
35
|
-
background: rgba(239,239,239,0.7);
|
|
36
|
-
border-color: transparent;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.wr-WineTile-action {
|
|
40
|
-
background: transparent;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.wr-WineTile-action:hover {
|
|
44
|
-
background: #000000;
|
|
45
|
-
color: #ffffff;
|
|
46
|
-
box-shadow: none;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
`,
|
|
50
|
-
translations: {
|
|
51
|
-
fr: {
|
|
52
|
-
"wineDetails.buy": "voir plus"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
"21": {
|
|
57
|
-
logoUrl: "https://www.intermarche.com/images/logoIntermarche.svg",
|
|
58
|
-
brandColor: "#B81242",
|
|
59
|
-
wineaterColor: "#7B2BEB",
|
|
60
|
-
buttonUppercase: true,
|
|
61
|
-
customCss: "",
|
|
62
|
-
translations: {}
|
|
63
|
-
},
|
|
64
|
-
"26": {
|
|
65
|
-
logoUrl: "https://paladarlondon.com/wp-content/uploads/2021/05/cropped-cropped-Paladar-Logo-1473x464-min-768x219.png",
|
|
66
|
-
brandColor: "#B81242",
|
|
67
|
-
wineaterColor: "#7B2BEB",
|
|
68
|
-
buttonUppercase: true,
|
|
69
|
-
customCss: "",
|
|
70
|
-
translations: {}
|
|
71
|
-
}
|
|
72
|
-
};
|