@fayz-ai/plugin-reputation 0.8.0 → 0.9.0-next.1
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/package.json +11 -11
- package/dist/index.cjs +0 -117
- package/dist/index.cjs.map +0 -1
- package/dist/public/index.cjs +0 -196
- package/dist/public/index.cjs.map +0 -1
package/package.json
CHANGED
|
@@ -3,24 +3,23 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "preview"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.9.0-next.1",
|
|
7
7
|
"description": "[experimental] Fayz SDK — reviews & reputation management plugin",
|
|
8
8
|
"type": "module",
|
|
9
|
-
"
|
|
9
|
+
"sideEffects": false,
|
|
10
|
+
"main": "./dist/index.js",
|
|
10
11
|
"module": "./dist/index.js",
|
|
11
12
|
"types": "./dist/index.d.ts",
|
|
12
13
|
"exports": {
|
|
13
14
|
".": {
|
|
14
15
|
"source": "./src/index.ts",
|
|
15
16
|
"types": "./dist/index.d.ts",
|
|
16
|
-
"import": "./dist/index.js"
|
|
17
|
-
"require": "./dist/index.cjs"
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
18
|
},
|
|
19
19
|
"./public": {
|
|
20
20
|
"source": "./src/public/index.tsx",
|
|
21
21
|
"types": "./dist/public/index.d.ts",
|
|
22
|
-
"import": "./dist/public/index.js"
|
|
23
|
-
"require": "./dist/public/index.cjs"
|
|
22
|
+
"import": "./dist/public/index.js"
|
|
24
23
|
}
|
|
25
24
|
},
|
|
26
25
|
"files": [
|
|
@@ -29,19 +28,20 @@
|
|
|
29
28
|
],
|
|
30
29
|
"peerDependencies": {
|
|
31
30
|
"react": "^18.0.0 || ^19.0.0",
|
|
32
|
-
"react-dom": "^18.0.0 || ^19.0.0"
|
|
31
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
32
|
+
"lucide-react": ">=0.400.0 <1.0.0"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"
|
|
36
|
-
"@fayz-ai/core": "^0.
|
|
37
|
-
"@fayz-ai/ui": "^0.8.0"
|
|
35
|
+
"@fayz-ai/ui": "^0.9.0-next.1",
|
|
36
|
+
"@fayz-ai/core": "^0.9.0-next.1"
|
|
38
37
|
},
|
|
39
38
|
"devDependencies": {
|
|
40
39
|
"@types/react": "^18.3.0",
|
|
41
40
|
"react": "^18.3.0",
|
|
42
41
|
"tsup": "^8.2.0",
|
|
43
42
|
"typescript": "^5.5.0",
|
|
44
|
-
"@types/react-dom": "^18.3.0"
|
|
43
|
+
"@types/react-dom": "^18.3.0",
|
|
44
|
+
"lucide-react": "^0.400.0"
|
|
45
45
|
},
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"keywords": [
|
package/dist/index.cjs
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var React = require('react');
|
|
4
|
-
var lucideReact = require('lucide-react');
|
|
5
|
-
var ui = require('@fayz-ai/ui');
|
|
6
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
-
|
|
8
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
-
|
|
10
|
-
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
11
|
-
|
|
12
|
-
// src/index.ts
|
|
13
|
-
var REVIEWS = [
|
|
14
|
-
{ id: "1", author: "Camila R.", source: "Google", rating: 5, text: "Absolutely loved the experience. The team is professional and friendly!", date: "Jun 15", replied: true },
|
|
15
|
-
{ id: "2", author: "Tom B.", source: "Facebook", rating: 5, text: "Booking was effortless and the results were fantastic.", date: "Jun 13", replied: false },
|
|
16
|
-
{ id: "3", author: "Aisha K.", source: "Google", rating: 4, text: "Great service overall, slightly long wait but worth it.", date: "Jun 11", replied: false },
|
|
17
|
-
{ id: "4", author: "Marco P.", source: "Google", rating: 5, text: "Best in town. Highly recommend to anyone.", date: "Jun 9", replied: true },
|
|
18
|
-
{ id: "5", author: "Lena S.", source: "Facebook", rating: 3, text: "Good but the pricing could be clearer up front.", date: "Jun 6", replied: false }
|
|
19
|
-
];
|
|
20
|
-
var DISTRIBUTION = [
|
|
21
|
-
{ stars: 5, count: 182 },
|
|
22
|
-
{ stars: 4, count: 41 },
|
|
23
|
-
{ stars: 3, count: 12 },
|
|
24
|
-
{ stars: 2, count: 4 },
|
|
25
|
-
{ stars: 1, count: 3 }
|
|
26
|
-
];
|
|
27
|
-
function Stars({ rating, className }) {
|
|
28
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex items-center gap-0.5 ${className ?? ""}`, children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Star, { className: `h-4 w-4 ${i <= rating ? "fill-amber-400 text-amber-400" : "text-muted-foreground/30"}` }, i)) });
|
|
29
|
-
}
|
|
30
|
-
function ReputationHome() {
|
|
31
|
-
const total = DISTRIBUTION.reduce((s, d) => s + d.count, 0);
|
|
32
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-6xl p-6", children: [
|
|
33
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.PageHeaderActions, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { children: [
|
|
34
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "mr-1.5 h-4 w-4" }),
|
|
35
|
-
" Request reviews"
|
|
36
|
-
] }) }),
|
|
37
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 grid grid-cols-1 gap-4 lg:grid-cols-3", children: [
|
|
38
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-card border border-border bg-card p-5 text-center", children: [
|
|
39
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-4xl font-bold text-foreground", children: "4.8" }),
|
|
40
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stars, { rating: 5, className: "mt-1 justify-center" }),
|
|
41
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [
|
|
42
|
-
total,
|
|
43
|
-
" reviews"
|
|
44
|
-
] })
|
|
45
|
-
] }),
|
|
46
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-card border border-border bg-card p-5 lg:col-span-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: DISTRIBUTION.map((d) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
47
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "w-6 text-muted-foreground", children: [
|
|
48
|
-
d.stars,
|
|
49
|
-
"\u2605"
|
|
50
|
-
] }),
|
|
51
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 flex-1 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full rounded-full bg-amber-400", style: { width: `${d.count / total * 100}%` } }) }),
|
|
52
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-8 text-right text-muted-foreground", children: d.count })
|
|
53
|
-
] }, d.stars)) }) })
|
|
54
|
-
] }),
|
|
55
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-6 space-y-3", children: REVIEWS.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-card border border-border bg-card p-4", children: [
|
|
56
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
|
|
57
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
58
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-9 w-9 items-center justify-center rounded-full bg-muted text-sm font-semibold text-foreground", children: r.author[0] }),
|
|
59
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
60
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: r.author }),
|
|
61
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
62
|
-
r.source,
|
|
63
|
-
" \xB7 ",
|
|
64
|
-
r.date
|
|
65
|
-
] })
|
|
66
|
-
] })
|
|
67
|
-
] }),
|
|
68
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stars, { rating: r.rating })
|
|
69
|
-
] }),
|
|
70
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: r.text }),
|
|
71
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: r.replied ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-emerald-600", children: "\u2713 Replied" }) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "outline", size: "sm", children: [
|
|
72
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
73
|
-
" Reply"
|
|
74
|
-
] }) })
|
|
75
|
-
] }, r.id)) }),
|
|
76
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 text-center text-xs text-muted-foreground", children: "Mock preview \xB7 Google/Facebook review sync + automated requests ship in a later milestone." })
|
|
77
|
-
] });
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// src/index.ts
|
|
81
|
-
function createReputationPlugin(options) {
|
|
82
|
-
const PageComponent = () => React__default.default.createElement(ReputationHome);
|
|
83
|
-
PageComponent.displayName = "ReputationHome";
|
|
84
|
-
return {
|
|
85
|
-
id: "reputation",
|
|
86
|
-
name: options?.navLabel ?? "Reputation",
|
|
87
|
-
icon: "Award",
|
|
88
|
-
version: "1.0.0",
|
|
89
|
-
scope: options?.scope ?? "universal",
|
|
90
|
-
verticalId: options?.verticalId,
|
|
91
|
-
defaultEnabled: true,
|
|
92
|
-
dependencies: [],
|
|
93
|
-
declaredFeatures: [{ id: "reputation", label: "Reputation", group: "Retain" }],
|
|
94
|
-
navigation: [
|
|
95
|
-
{
|
|
96
|
-
section: options?.navSection ?? "main",
|
|
97
|
-
position: options?.navPosition ?? 8,
|
|
98
|
-
label: options?.navLabel ?? "Reputation",
|
|
99
|
-
route: "/reputation",
|
|
100
|
-
icon: "Award",
|
|
101
|
-
permission: { feature: "reputation", action: "read" }
|
|
102
|
-
}
|
|
103
|
-
],
|
|
104
|
-
routes: [
|
|
105
|
-
{
|
|
106
|
-
path: "/reputation",
|
|
107
|
-
component: PageComponent,
|
|
108
|
-
permission: { feature: "reputation", action: "read" }
|
|
109
|
-
}
|
|
110
|
-
],
|
|
111
|
-
widgets: []
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
exports.createReputationPlugin = createReputationPlugin;
|
|
116
|
-
//# sourceMappingURL=index.cjs.map
|
|
117
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/views/ReputationHome.tsx","../src/index.ts"],"names":["jsx","Star","jsxs","PageHeaderActions","Button","Send","MessageSquare","React"],"mappings":"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","file":"index.cjs","sourcesContent":["import React from 'react'\nimport { Star, Send, MessageSquare } from 'lucide-react'\nimport { Button, PageHeaderActions } from '@fayz-ai/ui'\n\ninterface Review {\n id: string\n author: string\n source: 'Google' | 'Facebook'\n rating: number\n text: string\n date: string\n replied: boolean\n}\n\nconst REVIEWS: Review[] = [\n { id: '1', author: 'Camila R.', source: 'Google', rating: 5, text: 'Absolutely loved the experience. The team is professional and friendly!', date: 'Jun 15', replied: true },\n { id: '2', author: 'Tom B.', source: 'Facebook', rating: 5, text: 'Booking was effortless and the results were fantastic.', date: 'Jun 13', replied: false },\n { id: '3', author: 'Aisha K.', source: 'Google', rating: 4, text: 'Great service overall, slightly long wait but worth it.', date: 'Jun 11', replied: false },\n { id: '4', author: 'Marco P.', source: 'Google', rating: 5, text: 'Best in town. Highly recommend to anyone.', date: 'Jun 9', replied: true },\n { id: '5', author: 'Lena S.', source: 'Facebook', rating: 3, text: 'Good but the pricing could be clearer up front.', date: 'Jun 6', replied: false },\n]\n\nconst DISTRIBUTION = [\n { stars: 5, count: 182 },\n { stars: 4, count: 41 },\n { stars: 3, count: 12 },\n { stars: 2, count: 4 },\n { stars: 1, count: 3 },\n]\n\nfunction Stars({ rating, className }: { rating: number; className?: string }) {\n return (\n <div className={`flex items-center gap-0.5 ${className ?? ''}`}>\n {[1, 2, 3, 4, 5].map((i) => (\n <Star key={i} className={`h-4 w-4 ${i <= rating ? 'fill-amber-400 text-amber-400' : 'text-muted-foreground/30'}`} />\n ))}\n </div>\n )\n}\n\nexport function ReputationHome() {\n const total = DISTRIBUTION.reduce((s, d) => s + d.count, 0)\n return (\n <div className=\"mx-auto max-w-6xl p-6\">\n <PageHeaderActions>\n <Button><Send className=\"mr-1.5 h-4 w-4\" /> Request reviews</Button>\n </PageHeaderActions>\n\n <div className=\"mt-6 grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <div className=\"rounded-card border border-border bg-card p-5 text-center\">\n <p className=\"text-4xl font-bold text-foreground\">4.8</p>\n <Stars rating={5} className=\"mt-1 justify-center\" />\n <p className=\"mt-1 text-xs text-muted-foreground\">{total} reviews</p>\n </div>\n <div className=\"rounded-card border border-border bg-card p-5 lg:col-span-2\">\n <div className=\"space-y-1.5\">\n {DISTRIBUTION.map((d) => (\n <div key={d.stars} className=\"flex items-center gap-2 text-xs\">\n <span className=\"w-6 text-muted-foreground\">{d.stars}★</span>\n <div className=\"h-2 flex-1 overflow-hidden rounded-full bg-muted\">\n <div className=\"h-full rounded-full bg-amber-400\" style={{ width: `${(d.count / total) * 100}%` }} />\n </div>\n <span className=\"w-8 text-right text-muted-foreground\">{d.count}</span>\n </div>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"mt-6 space-y-3\">\n {REVIEWS.map((r) => (\n <div key={r.id} className=\"rounded-card border border-border bg-card p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-full bg-muted text-sm font-semibold text-foreground\">\n {r.author[0]}\n </div>\n <div>\n <p className=\"text-sm font-semibold text-foreground\">{r.author}</p>\n <p className=\"text-xs text-muted-foreground\">{r.source} · {r.date}</p>\n </div>\n </div>\n <Stars rating={r.rating} />\n </div>\n <p className=\"mt-2 text-sm text-muted-foreground\">{r.text}</p>\n <div className=\"mt-2\">\n {r.replied ? (\n <span className=\"text-xs font-medium text-emerald-600\">✓ Replied</span>\n ) : (\n <Button variant=\"outline\" size=\"sm\"><MessageSquare className=\"mr-1.5 h-3.5 w-3.5\" /> Reply</Button>\n )}\n </div>\n </div>\n ))}\n </div>\n\n <p className=\"mt-4 text-center text-xs text-muted-foreground\">\n Mock preview · Google/Facebook review sync + automated requests ship in a later milestone.\n </p>\n </div>\n )\n}\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { ReputationHome } from './views/ReputationHome'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-reputation — reviews & reputation (GoHighLevel \"Reputation\").\n// Universal plugin. M1 ships a rich mock home; Google/Facebook review sync +\n// automated review requests (over connectors + automations) come later.\n//\n// The public/website surface (createReputationWebsite + hooks + ReviewsList)\n// lives in the lean './public' subpath so a marketing-site host imports it\n// WITHOUT pulling the admin view's @fayz-ai/ui graph.\n// ---------------------------------------------------------------------------\n\nexport interface ReputationPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n scope?: PluginScope\n verticalId?: VerticalId\n}\n\nexport function createReputationPlugin(options?: ReputationPluginOptions): PluginManifest {\n const PageComponent: React.ComponentType<unknown> = () => React.createElement(ReputationHome)\n PageComponent.displayName = 'ReputationHome'\n\n return {\n id: 'reputation',\n name: options?.navLabel ?? 'Reputation',\n icon: 'Award',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'reputation', label: 'Reputation', group: 'Retain' }],\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 8,\n label: options?.navLabel ?? 'Reputation',\n route: '/reputation',\n icon: 'Award',\n permission: { feature: 'reputation', action: 'read' as const },\n },\n ],\n routes: [\n {\n path: '/reputation',\n component: PageComponent,\n permission: { feature: 'reputation', action: 'read' as const },\n },\n ],\n widgets: [],\n }\n}\n"]}
|
package/dist/public/index.cjs
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var react = require('react');
|
|
4
|
-
var core = require('@fayz-ai/core');
|
|
5
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
var lucideReact = require('lucide-react');
|
|
7
|
-
|
|
8
|
-
// src/public/index.tsx
|
|
9
|
-
|
|
10
|
-
// src/data/mock.ts
|
|
11
|
-
var FALLBACK_REVIEWS = [
|
|
12
|
-
{ id: "r1", author: "Camila R.", source: "Google", rating: 5, text: "Excelente atendimento, recomendo!", date: "Jun 2025" },
|
|
13
|
-
{ id: "r2", author: "Tom B.", source: "Facebook", rating: 5, text: "Processo simples e resultado \xF3timo.", date: "Jun 2025" },
|
|
14
|
-
{ id: "r3", author: "Aisha K.", source: "Google", rating: 4, text: "Muito bom no geral.", date: "Jun 2025" }
|
|
15
|
-
];
|
|
16
|
-
function computeSummary(reviews) {
|
|
17
|
-
const count = reviews.length;
|
|
18
|
-
const average = count === 0 ? 0 : Math.round(reviews.reduce((s, r) => s + r.rating, 0) / count * 10) / 10;
|
|
19
|
-
const distribution = [5, 4, 3, 2, 1].map((stars) => ({
|
|
20
|
-
stars,
|
|
21
|
-
count: reviews.filter((r) => Math.round(r.rating) === stars).length
|
|
22
|
-
}));
|
|
23
|
-
return { average, count, distribution };
|
|
24
|
-
}
|
|
25
|
-
function createMockReputationProvider(options) {
|
|
26
|
-
const reviews = options?.seed?.reviews ?? FALLBACK_REVIEWS;
|
|
27
|
-
const summary = options?.seed?.summary ?? computeSummary(reviews);
|
|
28
|
-
return {
|
|
29
|
-
async listReviews(query) {
|
|
30
|
-
let result = reviews;
|
|
31
|
-
if (query?.minRating != null) result = result.filter((r) => r.rating >= query.minRating);
|
|
32
|
-
if (query?.limit != null) result = result.slice(0, query.limit);
|
|
33
|
-
return result;
|
|
34
|
-
},
|
|
35
|
-
async getSummary() {
|
|
36
|
-
return summary;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// src/data/supabase.ts
|
|
42
|
-
function createSupabaseReputationProvider() {
|
|
43
|
-
const notImplemented = () => {
|
|
44
|
-
throw new Error(
|
|
45
|
-
"[plugin-reputation] Supabase provider not implemented yet \u2014 deferred to Phase 2. Run on the mock/seed provider (no Supabase client configured) for now."
|
|
46
|
-
);
|
|
47
|
-
};
|
|
48
|
-
return {
|
|
49
|
-
listReviews: (_query) => notImplemented(),
|
|
50
|
-
getSummary: () => notImplemented()
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
var ReputationContext = react.createContext(null);
|
|
54
|
-
function ReputationProvider({ value, children }) {
|
|
55
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ReputationContext.Provider, { value, children });
|
|
56
|
-
}
|
|
57
|
-
function useReputationContext() {
|
|
58
|
-
const ctx = react.useContext(ReputationContext);
|
|
59
|
-
if (!ctx) {
|
|
60
|
-
throw new Error("[plugin-reputation] useReputationContext must be used within <ReputationProvider>.");
|
|
61
|
-
}
|
|
62
|
-
return ctx;
|
|
63
|
-
}
|
|
64
|
-
function useReviews(query) {
|
|
65
|
-
const { provider } = useReputationContext();
|
|
66
|
-
const [reviews, setReviews] = react.useState([]);
|
|
67
|
-
const [loading, setLoading] = react.useState(true);
|
|
68
|
-
const [error, setError] = react.useState(null);
|
|
69
|
-
const limit = query?.limit;
|
|
70
|
-
const minRating = query?.minRating;
|
|
71
|
-
react.useEffect(() => {
|
|
72
|
-
let active = true;
|
|
73
|
-
setLoading(true);
|
|
74
|
-
provider.listReviews({ limit, minRating }).then((result) => {
|
|
75
|
-
if (!active) return;
|
|
76
|
-
setReviews(result);
|
|
77
|
-
setError(null);
|
|
78
|
-
}).catch((err) => {
|
|
79
|
-
if (!active) return;
|
|
80
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
81
|
-
}).finally(() => {
|
|
82
|
-
if (active) setLoading(false);
|
|
83
|
-
});
|
|
84
|
-
return () => {
|
|
85
|
-
active = false;
|
|
86
|
-
};
|
|
87
|
-
}, [provider, limit, minRating]);
|
|
88
|
-
return { reviews, loading, error };
|
|
89
|
-
}
|
|
90
|
-
function useReviewSummary() {
|
|
91
|
-
const { provider } = useReputationContext();
|
|
92
|
-
const [summary, setSummary] = react.useState(null);
|
|
93
|
-
const [loading, setLoading] = react.useState(true);
|
|
94
|
-
const [error, setError] = react.useState(null);
|
|
95
|
-
react.useEffect(() => {
|
|
96
|
-
let active = true;
|
|
97
|
-
setLoading(true);
|
|
98
|
-
provider.getSummary().then((result) => {
|
|
99
|
-
if (!active) return;
|
|
100
|
-
setSummary(result);
|
|
101
|
-
setError(null);
|
|
102
|
-
}).catch((err) => {
|
|
103
|
-
if (!active) return;
|
|
104
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
105
|
-
}).finally(() => {
|
|
106
|
-
if (active) setLoading(false);
|
|
107
|
-
});
|
|
108
|
-
return () => {
|
|
109
|
-
active = false;
|
|
110
|
-
};
|
|
111
|
-
}, [provider]);
|
|
112
|
-
return { summary, loading, error };
|
|
113
|
-
}
|
|
114
|
-
function Stars({ rating }) {
|
|
115
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
116
|
-
lucideReact.Star,
|
|
117
|
-
{
|
|
118
|
-
className: `h-4 w-4 ${i <= rating ? "fill-primary text-primary" : "text-muted-foreground/30"}`
|
|
119
|
-
},
|
|
120
|
-
i
|
|
121
|
-
)) });
|
|
122
|
-
}
|
|
123
|
-
function ReviewsList({ limit, heading }) {
|
|
124
|
-
const { reviews, loading } = useReviews({ limit });
|
|
125
|
-
const { summary } = useReviewSummary();
|
|
126
|
-
return /* @__PURE__ */ jsxRuntime.jsx("section", { className: "py-16 bg-background", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container mx-auto px-6", children: [
|
|
127
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-12", children: [
|
|
128
|
-
heading ? /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "font-heading text-4xl md:text-5xl font-bold text-foreground mb-3", children: heading }) : null,
|
|
129
|
-
summary ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2", children: [
|
|
130
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stars, { rating: Math.round(summary.average) }),
|
|
131
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground font-semibold text-lg", children: summary.average }),
|
|
132
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-sm", children: [
|
|
133
|
-
"\xB7 ",
|
|
134
|
-
summary.count,
|
|
135
|
-
" avalia\xE7\xF5es"
|
|
136
|
-
] })
|
|
137
|
-
] }) : null
|
|
138
|
-
] }),
|
|
139
|
-
loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-muted-foreground", children: "Carregando avalia\xE7\xF5es\u2026" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-6", children: reviews.map((review) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-2xl bg-card border border-border p-6 shadow-sm", children: [
|
|
140
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsxRuntime.jsx(Stars, { rating: review.rating }) }),
|
|
141
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-foreground text-sm leading-relaxed mb-4", children: [
|
|
142
|
-
'"',
|
|
143
|
-
review.text,
|
|
144
|
-
'"'
|
|
145
|
-
] }),
|
|
146
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
147
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
148
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-8 rounded-full bg-accent flex items-center justify-center text-primary font-semibold text-sm", children: review.author[0] }),
|
|
149
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: review.author })
|
|
150
|
-
] }),
|
|
151
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: review.date })
|
|
152
|
-
] })
|
|
153
|
-
] }, review.id)) })
|
|
154
|
-
] }) });
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// src/public/index.tsx
|
|
158
|
-
function createReputationWebsite(options) {
|
|
159
|
-
const basePath = options?.basePath ?? "/reviews";
|
|
160
|
-
const heading = options?.heading ?? "O que os pacientes dizem";
|
|
161
|
-
const provider = options?.dataProvider ?? core.createSafeDataProvider(
|
|
162
|
-
() => createSupabaseReputationProvider(),
|
|
163
|
-
() => createMockReputationProvider({ seed: options?.seed })
|
|
164
|
-
);
|
|
165
|
-
const value = { provider };
|
|
166
|
-
const Provider = ({ children }) => react.createElement(ReputationProvider, { value, children });
|
|
167
|
-
Provider.displayName = "ReputationWebsiteProvider";
|
|
168
|
-
const ReviewsScreen = () => react.createElement(ReviewsList, { heading });
|
|
169
|
-
ReviewsScreen.displayName = "ReviewsScreen";
|
|
170
|
-
const manifest = {
|
|
171
|
-
id: "reputation",
|
|
172
|
-
name: "Reviews",
|
|
173
|
-
icon: "Star",
|
|
174
|
-
version: "0.1.0",
|
|
175
|
-
scope: options?.scope ?? "universal",
|
|
176
|
-
verticalId: options?.verticalId,
|
|
177
|
-
scaffolds: ["website", "landing_page"],
|
|
178
|
-
defaultEnabled: true,
|
|
179
|
-
dependencies: [],
|
|
180
|
-
navigation: [],
|
|
181
|
-
routes: [{ path: basePath, component: ReviewsScreen, guard: "public" }],
|
|
182
|
-
widgets: []
|
|
183
|
-
};
|
|
184
|
-
return { manifest, Provider, dataProvider: provider };
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
exports.ReputationProvider = ReputationProvider;
|
|
188
|
-
exports.ReviewsList = ReviewsList;
|
|
189
|
-
exports.createMockReputationProvider = createMockReputationProvider;
|
|
190
|
-
exports.createReputationWebsite = createReputationWebsite;
|
|
191
|
-
exports.createSupabaseReputationProvider = createSupabaseReputationProvider;
|
|
192
|
-
exports.useReputationContext = useReputationContext;
|
|
193
|
-
exports.useReviewSummary = useReviewSummary;
|
|
194
|
-
exports.useReviews = useReviews;
|
|
195
|
-
//# sourceMappingURL=index.cjs.map
|
|
196
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/data/mock.ts","../../src/data/supabase.ts","../../src/context.tsx","../../src/hooks/useReviews.ts","../../src/hooks/useReviewSummary.ts","../../src/components/ReviewsList.tsx","../../src/public/index.tsx"],"names":["createContext","jsx","useContext","useState","useEffect","Star","jsxs","createSafeDataProvider","createElement"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ReputationDataProvider } from './types'\nimport type { Review, ReviewSummary, ReviewListQuery } from '../types'\n\nexport interface ReputationSeed {\n reviews: Review[]\n /** Explicit aggregate. If omitted, it is computed from `reviews`. */\n summary?: ReviewSummary\n}\n\nexport interface MockReputationProviderOptions {\n seed?: ReputationSeed\n}\n\nconst FALLBACK_REVIEWS: Review[] = [\n { id: 'r1', author: 'Camila R.', source: 'Google', rating: 5, text: 'Excelente atendimento, recomendo!', date: 'Jun 2025' },\n { id: 'r2', author: 'Tom B.', source: 'Facebook', rating: 5, text: 'Processo simples e resultado ótimo.', date: 'Jun 2025' },\n { id: 'r3', author: 'Aisha K.', source: 'Google', rating: 4, text: 'Muito bom no geral.', date: 'Jun 2025' },\n]\n\nfunction computeSummary(reviews: Review[]): ReviewSummary {\n const count = reviews.length\n const average = count === 0 ? 0 : Math.round((reviews.reduce((s, r) => s + r.rating, 0) / count) * 10) / 10\n const distribution = [5, 4, 3, 2, 1].map((stars) => ({\n stars,\n count: reviews.filter((r) => Math.round(r.rating) === stars).length,\n }))\n return { average, count, distribution }\n}\n\nexport function createMockReputationProvider(options?: MockReputationProviderOptions): ReputationDataProvider {\n const reviews: Review[] = options?.seed?.reviews ?? FALLBACK_REVIEWS\n const summary: ReviewSummary = options?.seed?.summary ?? computeSummary(reviews)\n\n return {\n async listReviews(query?: ReviewListQuery): Promise<Review[]> {\n let result = reviews\n if (query?.minRating != null) result = result.filter((r) => r.rating >= query.minRating!)\n if (query?.limit != null) result = result.slice(0, query.limit)\n return result\n },\n async getSummary(): Promise<ReviewSummary> {\n return summary\n },\n }\n}\n","import type { ReputationDataProvider } from './types'\nimport type { Review, ReviewSummary, ReviewListQuery } from '../types'\n\n// ---------------------------------------------------------------------------\n// Supabase-backed reputation provider — STUB (deferred to Phase 2).\n//\n// Later: read a `reviews` table (tenant-scoped, RLS) and/or synced Google/\n// Facebook reviews. Swapping this in is a pure provider change — hooks and\n// components are untouched. Throws until then so createSafeDataProvider falls\n// back to the mock/seed provider whenever no Supabase client is configured.\n// ---------------------------------------------------------------------------\n\nexport function createSupabaseReputationProvider(): ReputationDataProvider {\n const notImplemented = (): never => {\n throw new Error(\n '[plugin-reputation] Supabase provider not implemented yet — deferred to Phase 2. ' +\n 'Run on the mock/seed provider (no Supabase client configured) for now.',\n )\n }\n return {\n listReviews: (_query?: ReviewListQuery): Promise<Review[]> => notImplemented(),\n getSummary: (): Promise<ReviewSummary> => notImplemented(),\n }\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport type { ReputationDataProvider } from './data/types'\n\nexport interface ReputationContextValue {\n provider: ReputationDataProvider\n}\n\nconst ReputationContext = createContext<ReputationContextValue | null>(null)\n\nexport function ReputationProvider({ value, children }: { value: ReputationContextValue; children: ReactNode }) {\n return <ReputationContext.Provider value={value}>{children}</ReputationContext.Provider>\n}\n\nexport function useReputationContext(): ReputationContextValue {\n const ctx = useContext(ReputationContext)\n if (!ctx) {\n throw new Error('[plugin-reputation] useReputationContext must be used within <ReputationProvider>.')\n }\n return ctx\n}\n","import { useEffect, useState } from 'react'\nimport { useReputationContext } from '../context'\nimport type { Review, ReviewListQuery } from '../types'\n\nexport interface UseReviewsResult {\n reviews: Review[]\n loading: boolean\n error: Error | null\n}\n\n/** Fetch the review list from the active reputation provider. */\nexport function useReviews(query?: ReviewListQuery): UseReviewsResult {\n const { provider } = useReputationContext()\n const [reviews, setReviews] = useState<Review[]>([])\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n\n const limit = query?.limit\n const minRating = query?.minRating\n\n useEffect(() => {\n let active = true\n setLoading(true)\n provider\n .listReviews({ limit, minRating })\n .then((result) => {\n if (!active) return\n setReviews(result)\n setError(null)\n })\n .catch((err) => {\n if (!active) return\n setError(err instanceof Error ? err : new Error(String(err)))\n })\n .finally(() => {\n if (active) setLoading(false)\n })\n return () => {\n active = false\n }\n }, [provider, limit, minRating])\n\n return { reviews, loading, error }\n}\n","import { useEffect, useState } from 'react'\nimport { useReputationContext } from '../context'\nimport type { ReviewSummary } from '../types'\n\nexport interface UseReviewSummaryResult {\n summary: ReviewSummary | null\n loading: boolean\n error: Error | null\n}\n\n/** Fetch the aggregate rating summary (average + count + distribution). */\nexport function useReviewSummary(): UseReviewSummaryResult {\n const { provider } = useReputationContext()\n const [summary, setSummary] = useState<ReviewSummary | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n\n useEffect(() => {\n let active = true\n setLoading(true)\n provider\n .getSummary()\n .then((result) => {\n if (!active) return\n setSummary(result)\n setError(null)\n })\n .catch((err) => {\n if (!active) return\n setError(err instanceof Error ? err : new Error(String(err)))\n })\n .finally(() => {\n if (active) setLoading(false)\n })\n return () => {\n active = false\n }\n }, [provider])\n\n return { summary, loading, error }\n}\n","import { Star } from 'lucide-react'\nimport { useReviews } from '../hooks/useReviews'\nimport { useReviewSummary } from '../hooks/useReviewSummary'\n\nfunction Stars({ rating }: { rating: number }) {\n return (\n <div className=\"flex items-center gap-0.5\">\n {[1, 2, 3, 4, 5].map((i) => (\n <Star\n key={i}\n className={`h-4 w-4 ${i <= rating ? 'fill-primary text-primary' : 'text-muted-foreground/30'}`}\n />\n ))}\n </div>\n )\n}\n\n/**\n * Default reviews list with an aggregate header — token-only so it inherits the\n * host theme. Optional: a host with bespoke review cards can ignore this and map\n * `useReviews()` / `useReviewSummary()` itself (as hempdent does on its home).\n */\nexport function ReviewsList({ limit, heading }: { limit?: number; heading?: string }) {\n const { reviews, loading } = useReviews({ limit })\n const { summary } = useReviewSummary()\n\n return (\n <section className=\"py-16 bg-background\">\n <div className=\"container mx-auto px-6\">\n <div className=\"text-center mb-12\">\n {heading ? (\n <h1 className=\"font-heading text-4xl md:text-5xl font-bold text-foreground mb-3\">{heading}</h1>\n ) : null}\n {summary ? (\n <div className=\"flex items-center justify-center gap-2\">\n <Stars rating={Math.round(summary.average)} />\n <span className=\"text-foreground font-semibold text-lg\">{summary.average}</span>\n <span className=\"text-muted-foreground text-sm\">· {summary.count} avaliações</span>\n </div>\n ) : null}\n </div>\n\n {loading ? (\n <p className=\"text-center text-muted-foreground\">Carregando avaliações…</p>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n {reviews.map((review) => (\n <div key={review.id} className=\"rounded-2xl bg-card border border-border p-6 shadow-sm\">\n <div className=\"mb-3\">\n <Stars rating={review.rating} />\n </div>\n <p className=\"text-foreground text-sm leading-relaxed mb-4\">\"{review.text}\"</p>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <div className=\"h-8 w-8 rounded-full bg-accent flex items-center justify-center text-primary font-semibold text-sm\">\n {review.author[0]}\n </div>\n <span className=\"text-sm font-medium text-foreground\">{review.author}</span>\n </div>\n <span className=\"text-xs text-muted-foreground\">{review.date}</span>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </section>\n )\n}\n","import { createElement, type FC, type ReactNode } from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { createSafeDataProvider } from '@fayz-ai/core'\nimport { createMockReputationProvider, type ReputationSeed } from '../data/mock'\nimport { createSupabaseReputationProvider } from '../data/supabase'\nimport { ReputationProvider, type ReputationContextValue } from '../context'\nimport { ReviewsList } from '../components/ReviewsList'\nimport type { ReputationDataProvider } from '../data/types'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-reputation/public — website reviews surface.\n//\n// Lean entry (no admin ReputationHome / @fayz-ai/ui). Returns a { manifest,\n// Provider } bundle the host reads uniformly: the Provider wraps the app root so\n// useReviews()/useReviewSummary() power the host's own review markup, and\n// manifest.routes ships an optional /reviews page.\n// ---------------------------------------------------------------------------\n\nexport interface ReputationWebsiteOptions {\n /** Base path for the optional public \"all reviews\" page. Default '/reviews'. */\n basePath?: string\n /** Seed reviews + summary for the mock provider (used until a real backend is wired). */\n seed?: ReputationSeed\n /** Inject a custom provider. Overrides the safe mock/Supabase resolver. */\n dataProvider?: ReputationDataProvider\n /** Heading for the optional /reviews screen. */\n heading?: string\n scope?: PluginScope\n verticalId?: VerticalId\n}\n\nexport interface ReputationWebsitePlugin {\n manifest: PluginManifest\n Provider: FC<{ children: ReactNode }>\n dataProvider: ReputationDataProvider\n}\n\nexport function createReputationWebsite(options?: ReputationWebsiteOptions): ReputationWebsitePlugin {\n const basePath = options?.basePath ?? '/reviews'\n const heading = options?.heading ?? 'O que os pacientes dizem'\n const provider =\n options?.dataProvider ??\n createSafeDataProvider(\n () => createSupabaseReputationProvider(),\n () => createMockReputationProvider({ seed: options?.seed }),\n )\n\n const value: ReputationContextValue = { provider }\n const Provider: FC<{ children: ReactNode }> = ({ children }) =>\n createElement(ReputationProvider, { value, children })\n Provider.displayName = 'ReputationWebsiteProvider'\n\n const ReviewsScreen: FC<unknown> = () => createElement(ReviewsList, { heading })\n ReviewsScreen.displayName = 'ReviewsScreen'\n\n const manifest: PluginManifest = {\n id: 'reputation',\n name: 'Reviews',\n icon: 'Star',\n version: '0.1.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n scaffolds: ['website', 'landing_page'],\n defaultEnabled: true,\n dependencies: [],\n navigation: [],\n routes: [{ path: basePath, component: ReviewsScreen, guard: 'public' }],\n widgets: [],\n }\n\n return { manifest, Provider, dataProvider: provider }\n}\n\n// Public API — website surface\nexport type { Review, ReviewSummary, ReviewSource, ReviewListQuery } from '../types'\nexport type { ReputationDataProvider } from '../data/types'\nexport { createMockReputationProvider, createSupabaseReputationProvider } from '../data'\nexport type { ReputationSeed } from '../data/mock'\nexport { ReputationProvider, useReputationContext } from '../context'\nexport type { ReputationContextValue } from '../context'\nexport { useReviews, useReviewSummary } from '../hooks'\nexport { ReviewsList } from '../components/ReviewsList'\n"]}
|