vdb-ai-chat 1.0.13 → 1.0.14
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/chat-widget.js +1 -1
- package/lib/commonjs/api.js +6 -1
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/components/BetaNotice.js +1 -1
- package/lib/commonjs/components/BetaNotice.js.map +1 -1
- package/lib/commonjs/components/ChatInput.js +1 -1
- package/lib/commonjs/components/ChatInput.js.map +1 -1
- package/lib/commonjs/components/ChatWidget.js +15 -4
- package/lib/commonjs/components/ChatWidget.js.map +1 -1
- package/lib/commonjs/components/ProductsListView.js +26 -20
- package/lib/commonjs/components/ProductsListView.js.map +1 -1
- package/lib/commonjs/components/utils.js +37 -1
- package/lib/commonjs/components/utils.js.map +1 -1
- package/lib/module/api.js +6 -1
- package/lib/module/api.js.map +1 -1
- package/lib/module/components/BetaNotice.js +1 -1
- package/lib/module/components/BetaNotice.js.map +1 -1
- package/lib/module/components/ChatInput.js +1 -1
- package/lib/module/components/ChatInput.js.map +1 -1
- package/lib/module/components/ChatWidget.js +15 -4
- package/lib/module/components/ChatWidget.js.map +1 -1
- package/lib/module/components/ProductsListView.js +27 -21
- package/lib/module/components/ProductsListView.js.map +1 -1
- package/lib/module/components/utils.js +33 -0
- package/lib/module/components/utils.js.map +1 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/components/ChatWidget.d.ts.map +1 -1
- package/lib/typescript/components/ProductsListView.d.ts.map +1 -1
- package/lib/typescript/components/utils.d.ts +3 -0
- package/lib/typescript/components/utils.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +2 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +6 -0
- package/src/components/BetaNotice.tsx +1 -1
- package/src/components/ChatInput.tsx +1 -1
- package/src/components/ChatWidget.tsx +14 -2
- package/src/components/ProductsListView.tsx +39 -32
- package/src/components/utils.ts +36 -0
- package/src/types.ts +2 -0
|
@@ -8,6 +8,7 @@ export interface ChatMessage {
|
|
|
8
8
|
suggestions?: string[];
|
|
9
9
|
reaction?: string;
|
|
10
10
|
search_payload?: Record<string, any>;
|
|
11
|
+
external_context?: string | null;
|
|
11
12
|
}
|
|
12
13
|
export interface ChatTheme {
|
|
13
14
|
primaryColor: string;
|
|
@@ -42,6 +43,7 @@ export interface ChatWidgetProps {
|
|
|
42
43
|
onItemPress?: (deepLinkUrl: string, item: any) => void;
|
|
43
44
|
/** When true, shows beta labels and disclaimer. */
|
|
44
45
|
isBetaMode?: boolean;
|
|
46
|
+
activeProductType?: string;
|
|
45
47
|
}
|
|
46
48
|
export interface ChatWidgetRef {
|
|
47
49
|
clearChat: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,WAAW,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,WAAW,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3B,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,iFAAiF;IACjF,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7D,uFAAuF;IACvF,WAAW,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IACvD,mDAAmD;IACnD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7D,WAAW,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CACxD"}
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -148,8 +148,14 @@ export async function sendUserMessage(
|
|
|
148
148
|
return null;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
const external_context = await Storage.getJSON<string>("external_context");
|
|
152
|
+
if(external_context) {
|
|
153
|
+
await Storage.removeItem("external_context");
|
|
154
|
+
}
|
|
155
|
+
|
|
151
156
|
const body: any = {
|
|
152
157
|
query: userMessage,
|
|
158
|
+
external_context: external_context || null,
|
|
153
159
|
};
|
|
154
160
|
if (storedId) {
|
|
155
161
|
body.conversation_id = Number.isNaN(Number(storedId))
|
|
@@ -7,7 +7,7 @@ export const BetaNotice = ({ active }: { active?: boolean }) => {
|
|
|
7
7
|
if (!active) return null;
|
|
8
8
|
return (
|
|
9
9
|
<View style={styles.container}>
|
|
10
|
-
<TextView>This
|
|
10
|
+
<TextView>This beta feature uses AI-generated results that should be verified.</TextView>
|
|
11
11
|
</View>
|
|
12
12
|
);
|
|
13
13
|
};
|
|
@@ -75,7 +75,7 @@ export const ChatInput: React.FC<Props> = ({
|
|
|
75
75
|
// @ts-ignore - supported on web via react-native-web
|
|
76
76
|
id="chat-input"
|
|
77
77
|
style={[styles.inputWeb]}
|
|
78
|
-
placeholder={placeholder || "
|
|
78
|
+
placeholder={placeholder || "Describe the diamond you’re looking for..."}
|
|
79
79
|
placeholderTextColor={theme["core-06"] || "#999"}
|
|
80
80
|
value={value}
|
|
81
81
|
onChangeText={onChangeText}
|
|
@@ -63,6 +63,7 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
63
63
|
onViewAllPress,
|
|
64
64
|
onItemPress: onItemPressProp,
|
|
65
65
|
isBetaMode: isBetaModeProp,
|
|
66
|
+
activeProductType,
|
|
66
67
|
},
|
|
67
68
|
ref
|
|
68
69
|
) => {
|
|
@@ -117,6 +118,15 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
117
118
|
loadAuthData();
|
|
118
119
|
}, [userTokenProp]);
|
|
119
120
|
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
const setActiveProduct = async () => {
|
|
123
|
+
if (activeProductType) {
|
|
124
|
+
await Storage.setJSON("external_context", activeProductType);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
setActiveProduct();
|
|
128
|
+
}, [activeProductType]);
|
|
129
|
+
|
|
120
130
|
const onViewAll = (item: any) => {
|
|
121
131
|
let searchPayload = item?.search_payload;
|
|
122
132
|
if(searchPayload?.cut_from || searchPayload?.cut_to || searchPayload?.polish_from || searchPayload?.polish_to || searchPayload?.symmetry_from || searchPayload?.symmetry_to) {
|
|
@@ -252,7 +262,7 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
252
262
|
const initialAssistant: ChatMessage = {
|
|
253
263
|
id: "",
|
|
254
264
|
role: "assistant",
|
|
255
|
-
text: "
|
|
265
|
+
text: "Describe the diamond you’re looking for — for example, “2ct F VS2 under $10,000” or “1–2ct D–F VS pear” — and I’ll take it from there.",
|
|
256
266
|
createdAt: Date.now(),
|
|
257
267
|
isLoading: false,
|
|
258
268
|
suggestions: [],
|
|
@@ -288,12 +298,14 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
288
298
|
async (rawText: string) => {
|
|
289
299
|
const trimmed = rawText.trim();
|
|
290
300
|
if (!trimmed || loading) return;
|
|
301
|
+
const external_context = await Storage.getJSON<string>("external_context");
|
|
291
302
|
|
|
292
303
|
const userMessage: ChatMessage = {
|
|
293
304
|
id: `user-${Date.now()}`,
|
|
294
305
|
role: "user",
|
|
295
306
|
text: trimmed,
|
|
296
307
|
createdAt: Date.now(),
|
|
308
|
+
external_context: external_context || null
|
|
297
309
|
};
|
|
298
310
|
|
|
299
311
|
const loadingId = `bot-loading-${Date.now()}`;
|
|
@@ -569,7 +581,7 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
569
581
|
const initialAssistant: ChatMessage = {
|
|
570
582
|
id: "",
|
|
571
583
|
role: "assistant",
|
|
572
|
-
text: "
|
|
584
|
+
text: "Describe the diamond you’re looking for — for example, “2ct F VS2 under $10,000” or “1–2ct D–F VS pear” — and I’ll take it from there.",
|
|
573
585
|
createdAt: Date.now(),
|
|
574
586
|
isLoading: false,
|
|
575
587
|
suggestions: [],
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
Image,
|
|
10
10
|
Pressable,
|
|
11
11
|
} from "react-native";
|
|
12
|
-
import { getUserCurrencySymbol } from "./utils";
|
|
12
|
+
import { getUserCurrencySymbol, formatPriceValue, roundUpPrices } from "./utils";
|
|
13
13
|
import { useTheme } from "styled-components/native";
|
|
14
14
|
import { DefaultTheme } from "styled-components/native";
|
|
15
15
|
import styled from "styled-components/native";
|
|
@@ -128,7 +128,8 @@ const renderToken = (
|
|
|
128
128
|
token: TokenConfig,
|
|
129
129
|
item: any,
|
|
130
130
|
userCurrency: string | null,
|
|
131
|
-
index: number
|
|
131
|
+
index: number,
|
|
132
|
+
shouldRound: boolean = false
|
|
132
133
|
): React.ReactNode => {
|
|
133
134
|
const TextView = token.style === "secondary" ? TextStyleTwo : TextStyleOne;
|
|
134
135
|
const PrefixTextView = token.prefixStyle === "secondary" ? TextStyleTwo : TextStyleOne;
|
|
@@ -176,11 +177,14 @@ const renderToken = (
|
|
|
176
177
|
|
|
177
178
|
case "priceField": {
|
|
178
179
|
const value = item[token.field!];
|
|
180
|
+
const formattedPrice = formatPriceValue(token.field!, value, shouldRound);
|
|
181
|
+
console.log("formattedPrice", formattedPrice);
|
|
182
|
+
|
|
179
183
|
return (
|
|
180
184
|
<View key={index} style={styles.rowCenter}>
|
|
181
185
|
{token.prefix && <TextView theme={theme}>{token.prefix}</TextView>}
|
|
182
186
|
{value && <TextView theme={theme}>{currency}</TextView>}
|
|
183
|
-
<TextView theme={theme}>{
|
|
187
|
+
<TextView theme={theme}>{formattedPrice ?? "-"}</TextView>
|
|
184
188
|
{token.suffix && <SuffixTextView theme={theme}>{token.suffix}</SuffixTextView>}
|
|
185
189
|
</View>
|
|
186
190
|
);
|
|
@@ -190,7 +194,7 @@ const renderToken = (
|
|
|
190
194
|
return (
|
|
191
195
|
<View key={index} style={styles.rowCenter}>
|
|
192
196
|
{token.items?.map((subToken, subIndex) =>
|
|
193
|
-
renderToken(subToken, item, userCurrency, subIndex)
|
|
197
|
+
renderToken(subToken, item, userCurrency, subIndex, shouldRound)
|
|
194
198
|
)}
|
|
195
199
|
</View>
|
|
196
200
|
);
|
|
@@ -210,13 +214,20 @@ const ProductsListViewComponent: React.FC<ProductsListViewProps> = ({
|
|
|
210
214
|
if (!data || !data.length) return null;
|
|
211
215
|
const theme = useTheme();
|
|
212
216
|
const [userCurrency, setUserCurrency] = useState<string | null>(null);
|
|
217
|
+
const [shouldRound, setShouldRound] = useState<boolean>(false);
|
|
213
218
|
|
|
214
219
|
useEffect(() => {
|
|
215
220
|
const fetchCurrency = async () => {
|
|
216
221
|
const currency = await getUserCurrencySymbol();
|
|
217
222
|
setUserCurrency(currency);
|
|
218
223
|
};
|
|
224
|
+
|
|
225
|
+
const getRoundOffPrices = async () => {
|
|
226
|
+
const roundOff = await roundUpPrices();
|
|
227
|
+
setShouldRound(roundOff);
|
|
228
|
+
};
|
|
219
229
|
fetchCurrency();
|
|
230
|
+
getRoundOffPrices();
|
|
220
231
|
}, []);
|
|
221
232
|
|
|
222
233
|
return (
|
|
@@ -229,28 +240,28 @@ const ProductsListViewComponent: React.FC<ProductsListViewProps> = ({
|
|
|
229
240
|
<Pressable
|
|
230
241
|
key={dataItem.id}
|
|
231
242
|
onPress={() => onItemPress?.(dataItem)}
|
|
232
|
-
// @ts-ignore - hovered is available on web
|
|
233
|
-
style={({ hovered }) => [
|
|
234
|
-
styles.itemContainer,
|
|
235
|
-
hovered && styles.itemHover,
|
|
236
|
-
]}
|
|
237
243
|
>
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
{(state) => (
|
|
245
|
+
// @ts-ignore
|
|
246
|
+
<ListItemParent theme={theme} hovered={state.hovered}>
|
|
247
|
+
<View style={styles.left}>
|
|
248
|
+
<View style={styles.serialContainer}>
|
|
249
|
+
<Serial>{index + 1}.</Serial>
|
|
250
|
+
</View>
|
|
251
|
+
<View style={styles.tokens}>
|
|
252
|
+
{DIAMOND_TOKENS.map((token, tokenIndex) =>
|
|
253
|
+
renderToken(token, dataItem, userCurrency, tokenIndex, shouldRound)
|
|
254
|
+
)}
|
|
255
|
+
</View>
|
|
256
|
+
</View>
|
|
257
|
+
</ListItemParent>
|
|
258
|
+
)}
|
|
248
259
|
</Pressable>
|
|
249
260
|
))}
|
|
250
261
|
</ScrollView>
|
|
251
262
|
|
|
252
263
|
<ButtonView activeOpacity={0.8} onPress={() => onViewAll(item)}>
|
|
253
|
-
<ButtonText>{`View All ${totalResults}
|
|
264
|
+
<ButtonText>{`View All ${totalResults} diamonds`}</ButtonText>
|
|
254
265
|
<ImageComponent
|
|
255
266
|
source={{
|
|
256
267
|
uri: "https://cdn.vdbapp.com/ai/chat-widget/assets/img/right.svg",
|
|
@@ -320,6 +331,14 @@ const ButtonText = styled.Text<{ theme: DefaultTheme }>`
|
|
|
320
331
|
font-weight: 600;
|
|
321
332
|
`;
|
|
322
333
|
|
|
334
|
+
const ListItemParent = styled.Pressable<{ theme: DefaultTheme, hovered?: boolean }>`
|
|
335
|
+
padding-vertical: 2px;
|
|
336
|
+
background-color: ${({ theme, hovered }: { theme: DefaultTheme, hovered?: boolean }) =>
|
|
337
|
+
hovered
|
|
338
|
+
? theme["core-02"] || "#EDEDF2"
|
|
339
|
+
: "transparent"};
|
|
340
|
+
`;
|
|
341
|
+
|
|
323
342
|
const styles = StyleSheet.create({
|
|
324
343
|
listContent: {
|
|
325
344
|
gap: 8,
|
|
@@ -351,18 +370,6 @@ const styles = StyleSheet.create({
|
|
|
351
370
|
flexDirection: "row",
|
|
352
371
|
alignItems: "center",
|
|
353
372
|
},
|
|
354
|
-
priceContainer: {
|
|
355
|
-
alignItems: "flex-start",
|
|
356
|
-
justifyContent: "center",
|
|
357
|
-
},
|
|
358
|
-
|
|
359
|
-
itemContainer: {
|
|
360
|
-
paddingVertical: 2,
|
|
361
|
-
},
|
|
362
|
-
|
|
363
|
-
itemHover: {
|
|
364
|
-
backgroundColor: "#EDEDF2",
|
|
365
|
-
},
|
|
366
373
|
});
|
|
367
374
|
|
|
368
375
|
const ProductsListView = memo(ProductsListViewComponent);
|
package/src/components/utils.ts
CHANGED
|
@@ -68,6 +68,42 @@ export const getUserCurrencySymbol = async (): Promise<string | null> => {
|
|
|
68
68
|
return userData.currency_symbol || "$";
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
|
|
72
|
+
export const roundUpPrices = async (): Promise<boolean> => {
|
|
73
|
+
const userInfo = await Storage.getJSON<UserDetails>("persist:userInfo", {});
|
|
74
|
+
const userData = userInfo?.user as UserDetails;
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
return true; // org 1
|
|
77
|
+
// return !!userData?.feature_settings?.round_up_prices;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Helper to add commas to a number
|
|
81
|
+
export function formatWithCommas(value: number | string): string {
|
|
82
|
+
const num = typeof value === 'string' ? parseFloat(value) : value;
|
|
83
|
+
if (isNaN(num)) return String(value);
|
|
84
|
+
return num.toLocaleString();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Format price values according to requirements
|
|
88
|
+
export function formatPriceValue(key: string, value: any, shouldRound: boolean) {
|
|
89
|
+
console.log("formatPriceValue", key, value);
|
|
90
|
+
|
|
91
|
+
if (key === 'price_per_carat') {
|
|
92
|
+
// Remove decimals, round, add commas
|
|
93
|
+
const num = Math.round(Number(value));
|
|
94
|
+
return formatWithCommas(num);
|
|
95
|
+
}
|
|
96
|
+
if (key === 'total_sales_price') {
|
|
97
|
+
let num = Number(value);
|
|
98
|
+
if (shouldRound) {
|
|
99
|
+
num = Math.round(num);
|
|
100
|
+
}
|
|
101
|
+
return formatWithCommas(num);
|
|
102
|
+
}
|
|
103
|
+
// fallback: just add commas if number
|
|
104
|
+
return formatWithCommas(value);
|
|
105
|
+
}
|
|
106
|
+
|
|
71
107
|
export interface UserDetails {
|
|
72
108
|
id?: string | number;
|
|
73
109
|
email?: string;
|
package/src/types.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface ChatMessage {
|
|
|
9
9
|
suggestions?: string[];
|
|
10
10
|
reaction?: string;
|
|
11
11
|
search_payload?: Record<string, any>;
|
|
12
|
+
external_context?: string | null;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export interface ChatTheme {
|
|
@@ -45,6 +46,7 @@ export interface ChatWidgetProps {
|
|
|
45
46
|
onItemPress?: (deepLinkUrl: string, item: any) => void;
|
|
46
47
|
/** When true, shows beta labels and disclaimer. */
|
|
47
48
|
isBetaMode?: boolean;
|
|
49
|
+
activeProductType?: string;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
export interface ChatWidgetRef {
|