@instockng/storefront-ui 1.0.108 → 1.0.109
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/components/ProductAssistantChips.d.ts +9 -8
- package/dist/components/ProductAssistantChips.d.ts.map +1 -1
- package/dist/index100.mjs +27 -52
- package/dist/index101.mjs +8 -5
- package/dist/index102.mjs +74 -4
- package/dist/index103.mjs +3 -178
- package/dist/index104.mjs +2 -53
- package/dist/index105.mjs +82 -68
- package/dist/index106.mjs +54 -2
- package/dist/index107.mjs +5 -5
- package/dist/index108.mjs +4 -1133
- package/dist/index109.mjs +177 -18
- package/dist/index110.mjs +50 -52
- package/dist/index111.mjs +69 -33
- package/dist/index112.mjs +2 -2
- package/dist/index113.mjs +28 -2
- package/dist/index114.mjs +18 -2
- package/dist/index115.mjs +213 -26
- package/dist/index116.mjs +175 -13
- package/dist/index117.mjs +17 -210
- package/dist/index118.mjs +17 -174
- package/dist/index119.mjs +25 -14
- package/dist/index120.mjs +150 -17
- package/dist/index121.mjs +13 -26
- package/dist/index122.mjs +24 -149
- package/dist/index123.mjs +77 -13
- package/dist/index124.mjs +27 -20
- package/dist/index125.mjs +137 -76
- package/dist/index126.mjs +50 -33
- package/dist/index127.mjs +19 -141
- package/dist/index128.mjs +22 -50
- package/dist/index129.mjs +14 -14
- package/dist/index130.mjs +18 -20
- package/dist/index131.mjs +14 -16
- package/dist/index132.mjs +14 -17
- package/dist/index133.mjs +12 -12
- package/dist/index134.mjs +58 -15
- package/dist/index135.mjs +11 -14
- package/dist/index136.mjs +30 -56
- package/dist/index137.mjs +15 -9
- package/dist/index138.mjs +26 -31
- package/dist/index139.mjs +16 -13
- package/dist/index140.mjs +11 -26
- package/dist/index141.mjs +12 -18
- package/dist/index142.mjs +40 -12
- package/dist/index143.mjs +16 -14
- package/dist/index144.mjs +263 -42
- package/dist/index145.mjs +62 -15
- package/dist/index146.mjs +7 -267
- package/dist/index147.mjs +2 -70
- package/dist/index148.mjs +2 -8
- package/dist/index149.mjs +33 -2
- package/dist/index150.mjs +2 -2
- package/dist/index151.mjs +37 -33
- package/dist/index152.mjs +43 -2
- package/dist/index153.mjs +2 -21
- package/dist/index154.mjs +19 -54
- package/dist/index155.mjs +55 -28
- package/dist/index156.mjs +28 -6
- package/dist/index157.mjs +6 -51
- package/dist/index158.mjs +51 -5
- package/dist/index159.mjs +6 -12
- package/dist/index160.mjs +12 -7
- package/dist/index161.mjs +6 -27
- package/dist/index162.mjs +28 -2
- package/dist/index163.mjs +2 -70
- package/dist/index164.mjs +67 -164
- package/dist/index165.mjs +167 -2
- package/dist/index169.mjs +1 -1
- package/dist/index170.mjs +1 -1
- package/dist/index171.mjs +1 -1
- package/dist/index172.mjs +1 -1
- package/dist/index173.mjs +1 -1
- package/dist/index175.mjs +3 -3
- package/dist/index176.mjs +1 -1
- package/dist/index178.mjs +3 -3
- package/dist/index179.mjs +1 -1
- package/dist/index184.mjs +2 -2
- package/dist/index186.mjs +1 -1
- package/dist/index188.mjs +2 -2
- package/dist/index189.mjs +5 -5
- package/dist/index192.mjs +1 -1
- package/dist/index195.mjs +1 -1
- package/dist/index198.mjs +3 -3
- package/dist/index199.mjs +1 -1
- package/dist/index203.mjs +2 -2
- package/dist/index205.mjs +2 -2
- package/dist/index209.mjs +1 -1
- package/dist/index211.mjs +2 -2
- package/dist/index22.mjs +1 -1
- package/dist/index220.mjs +2 -2
- package/dist/index224.mjs +2 -31
- package/dist/index225.mjs +107 -10
- package/dist/index226.mjs +2 -4
- package/dist/index227.mjs +2 -4
- package/dist/index228.mjs +2 -13
- package/dist/index229.mjs +2 -7
- package/dist/index23.mjs +13 -12
- package/dist/index230.mjs +2 -12
- package/dist/index231.mjs +2 -5
- package/dist/index232.mjs +2 -33
- package/dist/index233.mjs +2 -31
- package/dist/index234.mjs +2 -28
- package/dist/index235.mjs +34 -58
- package/dist/index236.mjs +2 -2
- package/dist/index237.mjs +233 -97
- package/dist/index238.mjs +2 -2
- package/dist/index239.mjs +33 -2
- package/dist/index240.mjs +65 -2
- package/dist/index241.mjs +25 -2
- package/dist/index243.mjs +2 -2
- package/dist/index245.mjs +2 -2
- package/dist/index246.mjs +2 -2
- package/dist/index247.mjs +2 -37
- package/dist/index248.mjs +2 -2
- package/dist/index249.mjs +2 -2
- package/dist/index250.mjs +2 -244
- package/dist/index251.mjs +13 -2
- package/dist/index252.mjs +7 -33
- package/dist/index253.mjs +30 -64
- package/dist/index254.mjs +10 -24
- package/dist/index255.mjs +4 -2
- package/dist/index256.mjs +4 -2
- package/dist/index257.mjs +2 -2
- package/dist/index258.mjs +4 -2
- package/dist/index259.mjs +12 -2
- package/dist/index260.mjs +5 -2
- package/dist/index261.mjs +33 -2
- package/dist/index262.mjs +31 -2
- package/dist/index263.mjs +28 -2
- package/dist/index264.mjs +61 -4
- package/dist/index267.mjs +2 -3
- package/dist/index268.mjs +2 -2
- package/dist/index269.mjs +18 -2
- package/dist/index270.mjs +46 -16
- package/dist/index271.mjs +2 -13
- package/dist/index272.mjs +2 -6
- package/dist/index273.mjs +2 -30
- package/dist/index275.mjs +91 -2
- package/dist/index276.mjs +2 -18
- package/dist/index277.mjs +3 -47
- package/dist/index278.mjs +2 -2
- package/dist/index279.mjs +2 -2
- package/dist/index280.mjs +17 -2
- package/dist/index281.mjs +13 -2
- package/dist/index282.mjs +6 -91
- package/dist/index283.mjs +30 -2
- package/dist/index43.mjs +1 -1
- package/dist/index44.mjs +1 -1
- package/dist/index45.mjs +1 -1
- package/dist/index46.mjs +1 -1
- package/dist/index47.mjs +1 -1
- package/dist/index48.mjs +2 -2
- package/dist/index50.mjs +1 -1
- package/dist/index54.mjs +3 -3
- package/dist/index58.mjs +1 -1
- package/dist/index63.mjs +17 -17
- package/dist/index64.mjs +2 -2
- package/dist/index65.mjs +1 -1
- package/dist/index66.mjs +1 -1
- package/dist/index67.mjs +1 -1
- package/dist/index68.mjs +1 -1
- package/dist/index69.mjs +1 -1
- package/dist/index70.mjs +1 -1
- package/dist/index71.mjs +1 -1
- package/dist/index72.mjs +1 -1
- package/dist/index73.mjs +1 -1
- package/dist/index74.mjs +1 -1
- package/dist/index75.mjs +1 -1
- package/dist/index76.mjs +1 -1
- package/dist/index77.mjs +1 -1
- package/dist/index78.mjs +1 -1
- package/dist/index79.mjs +23 -4
- package/dist/index80.mjs +2 -24
- package/dist/index81.mjs +23 -2
- package/dist/index82.mjs +7 -7
- package/dist/index83.mjs +73 -21
- package/dist/index84.mjs +14 -74
- package/dist/index85.mjs +62 -14
- package/dist/index86.mjs +4 -62
- package/dist/index87.mjs +2 -37
- package/dist/index88.mjs +5 -42
- package/dist/index89.mjs +1129 -230
- package/dist/index90.mjs +19 -5
- package/dist/index91.mjs +48 -127
- package/dist/index92.mjs +32 -67
- package/dist/index93.mjs +2 -87
- package/dist/index94.mjs +2 -29
- package/dist/index95.mjs +235 -9
- package/dist/index96.mjs +5 -74
- package/dist/index97.mjs +133 -3
- package/dist/index98.mjs +68 -2
- package/dist/index99.mjs +83 -79
- package/package.json +2 -2
- package/src/components/AssistantDrawer.stories.tsx +20 -41
- package/src/components/AssistantDrawer.tsx +1 -1
- package/src/components/ProductAssistantChips.stories.tsx +11 -6
- package/src/components/ProductAssistantChips.tsx +13 -8
package/dist/index99.mjs
CHANGED
|
@@ -1,86 +1,90 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import t from "./
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
import t from "./index95.mjs";
|
|
3
|
+
import c from "./index106.mjs";
|
|
4
|
+
import u from "./index159.mjs";
|
|
5
|
+
import S from "./index105.mjs";
|
|
6
|
+
import h from "./index160.mjs";
|
|
7
|
+
import a from "./index161.mjs";
|
|
8
|
+
import O from "./index100.mjs";
|
|
9
|
+
function y(i, r, e) {
|
|
10
|
+
if (t.isString(i))
|
|
11
|
+
try {
|
|
12
|
+
return (r || JSON.parse)(i), t.trim(i);
|
|
13
|
+
} catch (n) {
|
|
14
|
+
if (n.name !== "SyntaxError")
|
|
15
|
+
throw n;
|
|
16
|
+
}
|
|
17
|
+
return (e || JSON.stringify)(i);
|
|
17
18
|
}
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
function j(r, n, u) {
|
|
45
|
-
let f = r;
|
|
46
|
-
if (r && !u && typeof r == "object") {
|
|
47
|
-
if (t.endsWith(n, "{}"))
|
|
48
|
-
n = p ? n : n.slice(0, -2), r = JSON.stringify(r);
|
|
49
|
-
else if (t.isArray(r) && T(r) || (t.isFileList(r) || t.endsWith(n, "[]")) && (f = t.toArray(r)))
|
|
50
|
-
return n = h(n), f.forEach(function(b, x) {
|
|
51
|
-
!(t.isUndefined(b) || b === null) && e.append(
|
|
52
|
-
// eslint-disable-next-line no-nested-ternary
|
|
53
|
-
m === !0 ? O([n], x, d) : m === null ? n : n + "[]",
|
|
54
|
-
l(b)
|
|
55
|
-
);
|
|
56
|
-
}), !1;
|
|
19
|
+
const l = {
|
|
20
|
+
transitional: u,
|
|
21
|
+
adapter: ["xhr", "http", "fetch"],
|
|
22
|
+
transformRequest: [function(r, e) {
|
|
23
|
+
const n = e.getContentType() || "", s = n.indexOf("application/json") > -1, f = t.isObject(r);
|
|
24
|
+
if (f && t.isHTMLForm(r) && (r = new FormData(r)), t.isFormData(r))
|
|
25
|
+
return s ? JSON.stringify(O(r)) : r;
|
|
26
|
+
if (t.isArrayBuffer(r) || t.isBuffer(r) || t.isStream(r) || t.isFile(r) || t.isBlob(r) || t.isReadableStream(r))
|
|
27
|
+
return r;
|
|
28
|
+
if (t.isArrayBufferView(r))
|
|
29
|
+
return r.buffer;
|
|
30
|
+
if (t.isURLSearchParams(r))
|
|
31
|
+
return e.setContentType("application/x-www-form-urlencoded;charset=utf-8", !1), r.toString();
|
|
32
|
+
let o;
|
|
33
|
+
if (f) {
|
|
34
|
+
if (n.indexOf("application/x-www-form-urlencoded") > -1)
|
|
35
|
+
return h(r, this.formSerializer).toString();
|
|
36
|
+
if ((o = t.isFileList(r)) || n.indexOf("multipart/form-data") > -1) {
|
|
37
|
+
const p = this.env && this.env.FormData;
|
|
38
|
+
return S(
|
|
39
|
+
o ? { "files[]": r } : r,
|
|
40
|
+
p && new p(),
|
|
41
|
+
this.formSerializer
|
|
42
|
+
);
|
|
43
|
+
}
|
|
57
44
|
}
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
45
|
+
return f || s ? (e.setContentType("application/json", !1), y(r)) : r;
|
|
46
|
+
}],
|
|
47
|
+
transformResponse: [function(r) {
|
|
48
|
+
const e = this.transitional || l.transitional, n = e && e.forcedJSONParsing, s = this.responseType === "json";
|
|
49
|
+
if (t.isResponse(r) || t.isReadableStream(r))
|
|
50
|
+
return r;
|
|
51
|
+
if (r && t.isString(r) && (n && !this.responseType || s)) {
|
|
52
|
+
const m = !(e && e.silentJSONParsing) && s;
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(r, this.parseReviver);
|
|
55
|
+
} catch (o) {
|
|
56
|
+
if (m)
|
|
57
|
+
throw o.name === "SyntaxError" ? c.from(o, c.ERR_BAD_RESPONSE, this, null, this.response) : o;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return r;
|
|
61
|
+
}],
|
|
62
|
+
/**
|
|
63
|
+
* A timeout in milliseconds to abort a request. If set to 0 (default) a
|
|
64
|
+
* timeout is not created.
|
|
65
|
+
*/
|
|
66
|
+
timeout: 0,
|
|
67
|
+
xsrfCookieName: "XSRF-TOKEN",
|
|
68
|
+
xsrfHeaderName: "X-XSRF-TOKEN",
|
|
69
|
+
maxContentLength: -1,
|
|
70
|
+
maxBodyLength: -1,
|
|
71
|
+
env: {
|
|
72
|
+
FormData: a.classes.FormData,
|
|
73
|
+
Blob: a.classes.Blob
|
|
74
|
+
},
|
|
75
|
+
validateStatus: function(r) {
|
|
76
|
+
return r >= 200 && r < 300;
|
|
77
|
+
},
|
|
78
|
+
headers: {
|
|
79
|
+
common: {
|
|
80
|
+
Accept: "application/json, text/plain, */*",
|
|
81
|
+
"Content-Type": void 0
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
+
};
|
|
85
|
+
t.forEach(["delete", "get", "head", "post", "put", "patch"], (i) => {
|
|
86
|
+
l.headers[i] = {};
|
|
87
|
+
});
|
|
84
88
|
export {
|
|
85
|
-
|
|
89
|
+
l as default
|
|
86
90
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instockng/storefront-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.109",
|
|
4
4
|
"description": "Pre-built UI components for OMS e-commerce sites",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"type-check": "tsc --noEmit",
|
|
25
25
|
"build": "vite build && vite build --config vite.config.css.ts && tsc --project tsconfig.build.json || true",
|
|
26
26
|
"prepublishOnly": "npm run build",
|
|
27
|
-
"postpublish": "gh api repos/ola-wale/toyland/dispatches -f event_type=instockng-publish",
|
|
27
|
+
"postpublish": "sleep 15 && gh api repos/ola-wale/toyland/dispatches -f event_type=instockng-publish",
|
|
28
28
|
"storybook": "storybook dev -p 6006",
|
|
29
29
|
"build-storybook": "storybook build"
|
|
30
30
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { useState, useCallback } from 'react';
|
|
3
2
|
import { AssistantDrawer } from './AssistantDrawer';
|
|
4
3
|
import { ProductAssistantChips } from './ProductAssistantChips';
|
|
4
|
+
import { AssistantProvider } from '../contexts/AssistantContext';
|
|
5
5
|
|
|
6
6
|
const meta = {
|
|
7
7
|
title: 'Components/AssistantDrawer',
|
|
@@ -10,7 +10,6 @@ const meta = {
|
|
|
10
10
|
layout: 'fullscreen',
|
|
11
11
|
},
|
|
12
12
|
decorators: [
|
|
13
|
-
// Override the default p-8 decorator — drawer needs full viewport
|
|
14
13
|
(Story) => (
|
|
15
14
|
<div style={{ position: 'relative', width: '100vw', height: '100vh', overflow: 'hidden' }}>
|
|
16
15
|
<Story />
|
|
@@ -29,48 +28,28 @@ const mockFaqs = [
|
|
|
29
28
|
{ question: 'Can they be worn during workouts?', answer: 'Designed for high-intensity workouts.' },
|
|
30
29
|
];
|
|
31
30
|
|
|
32
|
-
function ProductChipsDemo() {
|
|
33
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
34
|
-
const [question, setQuestion] = useState('');
|
|
35
|
-
|
|
36
|
-
const handleAsk = useCallback((q: string) => {
|
|
37
|
-
setQuestion(q);
|
|
38
|
-
setIsOpen(true);
|
|
39
|
-
}, []);
|
|
40
|
-
|
|
41
|
-
const handleClose = useCallback(() => {
|
|
42
|
-
setIsOpen(false);
|
|
43
|
-
}, []);
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<div className="p-8">
|
|
47
|
-
<h3 className="text-lg font-semibold mb-4">Product Page</h3>
|
|
48
|
-
<div className="max-w-md">
|
|
49
|
-
<div className="aspect-[4/3] bg-gray-100 rounded-lg mb-4 flex items-center justify-center text-gray-400">
|
|
50
|
-
Product Image
|
|
51
|
-
</div>
|
|
52
|
-
<ProductAssistantChips faqs={mockFaqs} onAsk={handleAsk} />
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
<AssistantDrawer
|
|
56
|
-
isOpen={isOpen}
|
|
57
|
-
onClose={handleClose}
|
|
58
|
-
apiUrl="https://oms-api.instock.ng"
|
|
59
|
-
brandSlug="demo-brand"
|
|
60
|
-
productSlug="maternity-leggings"
|
|
61
|
-
initialQuestion={question}
|
|
62
|
-
assistantName="AI Assistant"
|
|
63
|
-
disablePortal
|
|
64
|
-
/>
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
31
|
/**
|
|
70
|
-
* Interactive demo: FAQ chips → click → drawer opens with streaming answer
|
|
32
|
+
* Interactive demo: FAQ chips → click → drawer opens with streaming answer.
|
|
33
|
+
* Uses AssistantProvider (same as production) so ProductAssistantChips can call useAssistant().
|
|
71
34
|
*/
|
|
72
35
|
export const WithProductChips: Story = {
|
|
73
|
-
render: () =>
|
|
36
|
+
render: () => (
|
|
37
|
+
<AssistantProvider
|
|
38
|
+
apiUrl="https://oms-api.instock.ng"
|
|
39
|
+
brandSlug="demo-brand"
|
|
40
|
+
assistantName="AI Assistant"
|
|
41
|
+
>
|
|
42
|
+
<div className="p-8">
|
|
43
|
+
<h3 className="text-lg font-semibold mb-4">Product Page</h3>
|
|
44
|
+
<div className="max-w-md">
|
|
45
|
+
<div className="aspect-[4/3] bg-gray-100 rounded-lg mb-4 flex items-center justify-center text-gray-400">
|
|
46
|
+
Product Image
|
|
47
|
+
</div>
|
|
48
|
+
<ProductAssistantChips product={{ slug: 'maternity-leggings', faqs: mockFaqs }} />
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</AssistantProvider>
|
|
52
|
+
),
|
|
74
53
|
args: {} as any,
|
|
75
54
|
};
|
|
76
55
|
|
|
@@ -116,7 +116,7 @@ export function AssistantDrawer({
|
|
|
116
116
|
}
|
|
117
117
|
}, []);
|
|
118
118
|
|
|
119
|
-
const sendMessageRef = useRef<(question: string) => Promise<void>>();
|
|
119
|
+
const sendMessageRef = useRef<(question: string) => Promise<void>>(null);
|
|
120
120
|
const sendMessage = useCallback(
|
|
121
121
|
async (question: string) => {
|
|
122
122
|
if (!question.trim()) return;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import { ProductAssistantChips } from './ProductAssistantChips';
|
|
3
|
+
import { AssistantProvider } from '../contexts/AssistantContext';
|
|
3
4
|
|
|
4
5
|
const meta = {
|
|
5
6
|
title: 'Components/ProductAssistantChips',
|
|
@@ -7,6 +8,13 @@ const meta = {
|
|
|
7
8
|
parameters: {
|
|
8
9
|
layout: 'centered',
|
|
9
10
|
},
|
|
11
|
+
decorators: [
|
|
12
|
+
(Story) => (
|
|
13
|
+
<AssistantProvider apiUrl="https://oms-api.instock.ng" brandSlug="demo-brand">
|
|
14
|
+
<Story />
|
|
15
|
+
</AssistantProvider>
|
|
16
|
+
),
|
|
17
|
+
],
|
|
10
18
|
tags: ['autodocs'],
|
|
11
19
|
} satisfies Meta<typeof ProductAssistantChips>;
|
|
12
20
|
|
|
@@ -22,21 +30,18 @@ const mockFaqs = [
|
|
|
22
30
|
|
|
23
31
|
export const Default: Story = {
|
|
24
32
|
args: {
|
|
25
|
-
faqs: mockFaqs,
|
|
26
|
-
onAsk: (question) => console.log('Asked:', question),
|
|
33
|
+
product: { slug: 'maternity-leggings', faqs: mockFaqs },
|
|
27
34
|
},
|
|
28
35
|
};
|
|
29
36
|
|
|
30
37
|
export const FewQuestions: Story = {
|
|
31
38
|
args: {
|
|
32
|
-
faqs: mockFaqs.slice(0, 2),
|
|
33
|
-
onAsk: (question) => console.log('Asked:', question),
|
|
39
|
+
product: { slug: 'maternity-leggings', faqs: mockFaqs.slice(0, 2) },
|
|
34
40
|
},
|
|
35
41
|
};
|
|
36
42
|
|
|
37
43
|
export const NoFaqs: Story = {
|
|
38
44
|
args: {
|
|
39
|
-
faqs: [],
|
|
40
|
-
onAsk: (question) => console.log('Asked:', question),
|
|
45
|
+
product: { slug: 'maternity-leggings', faqs: [] },
|
|
41
46
|
},
|
|
42
47
|
};
|
|
@@ -9,21 +9,26 @@
|
|
|
9
9
|
|
|
10
10
|
import { Sparkles } from 'lucide-react';
|
|
11
11
|
import { cn } from '../lib/utils';
|
|
12
|
+
import { useAssistant } from '../contexts/AssistantContext';
|
|
12
13
|
|
|
13
14
|
export interface ProductAssistantChipsProps {
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
/** Product with faqs and slug */
|
|
16
|
+
product: {
|
|
17
|
+
slug: string;
|
|
18
|
+
faqs?: Array<{ question: string; answer: string }> | null;
|
|
19
|
+
};
|
|
18
20
|
/** Custom class name */
|
|
19
21
|
className?: string;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export function ProductAssistantChips({
|
|
23
|
-
|
|
24
|
-
onAsk,
|
|
25
|
+
product,
|
|
25
26
|
className,
|
|
26
27
|
}: ProductAssistantChipsProps) {
|
|
28
|
+
const { ask } = useAssistant();
|
|
29
|
+
const faqs = product.faqs || [];
|
|
30
|
+
const productSlug = product.slug;
|
|
31
|
+
|
|
27
32
|
if (faqs.length === 0) return null;
|
|
28
33
|
|
|
29
34
|
return (
|
|
@@ -37,7 +42,7 @@ export function ProductAssistantChips({
|
|
|
37
42
|
<button
|
|
38
43
|
key={i}
|
|
39
44
|
type="button"
|
|
40
|
-
onClick={() =>
|
|
45
|
+
onClick={() => ask(faq.question, productSlug)}
|
|
41
46
|
className={cn(
|
|
42
47
|
'rounded-full border border-gray-200 bg-blue-50/60 px-3 py-1.5 text-sm text-gray-700',
|
|
43
48
|
'hover:bg-blue-100 hover:border-blue-200 transition-colors',
|
|
@@ -49,7 +54,7 @@ export function ProductAssistantChips({
|
|
|
49
54
|
))}
|
|
50
55
|
<button
|
|
51
56
|
type="button"
|
|
52
|
-
onClick={() =>
|
|
57
|
+
onClick={() => ask('', productSlug)}
|
|
53
58
|
className={cn(
|
|
54
59
|
'rounded-full border border-gray-300 bg-gray-800 px-3 py-1.5 text-sm text-white font-medium',
|
|
55
60
|
'hover:bg-gray-700 transition-colors',
|