@contractspec/example.marketplace 3.7.6 → 3.8.2
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/README.md +64 -131
- package/dist/browser/entities/index.js +470 -470
- package/dist/browser/index.js +1257 -1019
- package/dist/browser/marketplace.feature.js +175 -0
- package/dist/browser/order/index.js +155 -155
- package/dist/browser/order/order.event.js +1 -1
- package/dist/browser/payout/index.js +71 -71
- package/dist/browser/payout/payout.event.js +1 -1
- package/dist/browser/product/index.js +104 -104
- package/dist/browser/product/product.event.js +1 -1
- package/dist/browser/review/index.js +75 -75
- package/dist/browser/review/review.event.js +1 -1
- package/dist/browser/store/index.js +68 -68
- package/dist/browser/store/store.event.js +1 -1
- package/dist/browser/ui/MarketplaceDashboard.js +328 -110
- package/dist/browser/ui/MarketplaceDashboard.visualizations.js +216 -0
- package/dist/browser/ui/hooks/index.js +1 -1
- package/dist/browser/ui/hooks/useMarketplaceData.js +1 -1
- package/dist/browser/ui/index.js +590 -359
- package/dist/browser/ui/renderers/index.js +190 -4
- package/dist/browser/ui/renderers/marketplace.markdown.js +190 -4
- package/dist/browser/visualizations/catalog.js +126 -0
- package/dist/browser/visualizations/index.js +183 -0
- package/dist/browser/visualizations/selectors.js +177 -0
- package/dist/entities/index.d.ts +110 -110
- package/dist/entities/index.js +470 -470
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1257 -1019
- package/dist/marketplace.feature.js +175 -0
- package/dist/node/entities/index.js +470 -470
- package/dist/node/index.js +1257 -1019
- package/dist/node/marketplace.feature.js +175 -0
- package/dist/node/order/index.js +155 -155
- package/dist/node/order/order.event.js +1 -1
- package/dist/node/payout/index.js +71 -71
- package/dist/node/payout/payout.event.js +1 -1
- package/dist/node/product/index.js +104 -104
- package/dist/node/product/product.event.js +1 -1
- package/dist/node/review/index.js +75 -75
- package/dist/node/review/review.event.js +1 -1
- package/dist/node/store/index.js +68 -68
- package/dist/node/store/store.event.js +1 -1
- package/dist/node/ui/MarketplaceDashboard.js +328 -110
- package/dist/node/ui/MarketplaceDashboard.visualizations.js +216 -0
- package/dist/node/ui/hooks/index.js +1 -1
- package/dist/node/ui/hooks/useMarketplaceData.js +1 -1
- package/dist/node/ui/index.js +590 -359
- package/dist/node/ui/renderers/index.js +190 -4
- package/dist/node/ui/renderers/marketplace.markdown.js +190 -4
- package/dist/node/visualizations/catalog.js +126 -0
- package/dist/node/visualizations/index.js +183 -0
- package/dist/node/visualizations/selectors.js +177 -0
- package/dist/order/index.d.ts +2 -2
- package/dist/order/index.js +155 -155
- package/dist/order/order.event.js +1 -1
- package/dist/payout/index.d.ts +2 -2
- package/dist/payout/index.js +71 -71
- package/dist/payout/payout.event.js +1 -1
- package/dist/product/index.d.ts +2 -2
- package/dist/product/index.js +104 -104
- package/dist/product/product.event.js +1 -1
- package/dist/review/index.d.ts +2 -2
- package/dist/review/index.js +75 -75
- package/dist/review/review.event.js +1 -1
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +68 -68
- package/dist/store/store.event.js +1 -1
- package/dist/ui/MarketplaceDashboard.js +328 -110
- package/dist/ui/MarketplaceDashboard.visualizations.d.ts +5 -0
- package/dist/ui/MarketplaceDashboard.visualizations.js +217 -0
- package/dist/ui/hooks/index.d.ts +1 -1
- package/dist/ui/hooks/index.js +1 -1
- package/dist/ui/hooks/useMarketplaceData.js +1 -1
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +590 -359
- package/dist/ui/renderers/index.d.ts +1 -1
- package/dist/ui/renderers/index.js +190 -4
- package/dist/ui/renderers/marketplace.markdown.js +190 -4
- package/dist/visualizations/catalog.d.ts +10 -0
- package/dist/visualizations/catalog.js +127 -0
- package/dist/visualizations/index.d.ts +2 -0
- package/dist/visualizations/index.js +184 -0
- package/dist/visualizations/selectors.d.ts +11 -0
- package/dist/visualizations/selectors.js +178 -0
- package/dist/visualizations/selectors.test.d.ts +1 -0
- package/package.json +66 -10
|
@@ -1,3 +1,177 @@
|
|
|
1
|
+
// src/visualizations/catalog.ts
|
|
2
|
+
import {
|
|
3
|
+
defineVisualization,
|
|
4
|
+
VisualizationRegistry
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
6
|
+
var ORDER_LIST_REF = {
|
|
7
|
+
key: "marketplace.order.list",
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
};
|
|
10
|
+
var PRODUCT_LIST_REF = {
|
|
11
|
+
key: "marketplace.product.list",
|
|
12
|
+
version: "1.0.0"
|
|
13
|
+
};
|
|
14
|
+
var META = {
|
|
15
|
+
version: "1.0.0",
|
|
16
|
+
domain: "marketplace",
|
|
17
|
+
stability: "experimental",
|
|
18
|
+
owners: ["@example.marketplace"],
|
|
19
|
+
tags: ["marketplace", "visualization", "commerce"]
|
|
20
|
+
};
|
|
21
|
+
var MarketplaceOrderStatusVisualization = defineVisualization({
|
|
22
|
+
meta: {
|
|
23
|
+
...META,
|
|
24
|
+
key: "marketplace.visualization.order-status",
|
|
25
|
+
title: "Order Status Breakdown",
|
|
26
|
+
description: "Distribution of current order states.",
|
|
27
|
+
goal: "Expose delivery and backlog mix at a glance.",
|
|
28
|
+
context: "Marketplace operations overview."
|
|
29
|
+
},
|
|
30
|
+
source: { primary: ORDER_LIST_REF, resultPath: "data" },
|
|
31
|
+
visualization: {
|
|
32
|
+
kind: "pie",
|
|
33
|
+
nameDimension: "status",
|
|
34
|
+
valueMeasure: "orders",
|
|
35
|
+
dimensions: [
|
|
36
|
+
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
37
|
+
],
|
|
38
|
+
measures: [
|
|
39
|
+
{ key: "orders", label: "Orders", dataPath: "orders", format: "number" }
|
|
40
|
+
],
|
|
41
|
+
table: { caption: "Order counts by status." }
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
var MarketplaceCategoryValueVisualization = defineVisualization({
|
|
45
|
+
meta: {
|
|
46
|
+
...META,
|
|
47
|
+
key: "marketplace.visualization.category-value",
|
|
48
|
+
title: "Category Value Comparison",
|
|
49
|
+
description: "Catalog value by product category derived from current pricing and stock.",
|
|
50
|
+
goal: "Compare where the marketplace catalog is concentrated.",
|
|
51
|
+
context: "Merchandising overview."
|
|
52
|
+
},
|
|
53
|
+
source: { primary: PRODUCT_LIST_REF, resultPath: "data" },
|
|
54
|
+
visualization: {
|
|
55
|
+
kind: "cartesian",
|
|
56
|
+
variant: "bar",
|
|
57
|
+
xDimension: "category",
|
|
58
|
+
yMeasures: ["catalogValue"],
|
|
59
|
+
dimensions: [
|
|
60
|
+
{
|
|
61
|
+
key: "category",
|
|
62
|
+
label: "Category",
|
|
63
|
+
dataPath: "category",
|
|
64
|
+
type: "category"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
measures: [
|
|
68
|
+
{
|
|
69
|
+
key: "catalogValue",
|
|
70
|
+
label: "Catalog Value",
|
|
71
|
+
dataPath: "catalogValue",
|
|
72
|
+
format: "currency",
|
|
73
|
+
color: "#1d4ed8"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
table: { caption: "Catalog value by product category." }
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
var MarketplaceOrderActivityVisualization = defineVisualization({
|
|
80
|
+
meta: {
|
|
81
|
+
...META,
|
|
82
|
+
key: "marketplace.visualization.order-activity",
|
|
83
|
+
title: "Recent Order Activity",
|
|
84
|
+
description: "Daily order volume from recent order creation timestamps.",
|
|
85
|
+
goal: "Show recent order activity trends.",
|
|
86
|
+
context: "Commerce operations trend monitoring."
|
|
87
|
+
},
|
|
88
|
+
source: { primary: ORDER_LIST_REF, resultPath: "data" },
|
|
89
|
+
visualization: {
|
|
90
|
+
kind: "cartesian",
|
|
91
|
+
variant: "line",
|
|
92
|
+
xDimension: "day",
|
|
93
|
+
yMeasures: ["orders"],
|
|
94
|
+
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
95
|
+
measures: [
|
|
96
|
+
{
|
|
97
|
+
key: "orders",
|
|
98
|
+
label: "Orders",
|
|
99
|
+
dataPath: "orders",
|
|
100
|
+
format: "number",
|
|
101
|
+
color: "#0f766e"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
table: { caption: "Daily order counts." }
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
var MarketplaceVisualizationSpecs = [
|
|
108
|
+
MarketplaceOrderStatusVisualization,
|
|
109
|
+
MarketplaceCategoryValueVisualization,
|
|
110
|
+
MarketplaceOrderActivityVisualization
|
|
111
|
+
];
|
|
112
|
+
var MarketplaceVisualizationRegistry = new VisualizationRegistry([
|
|
113
|
+
...MarketplaceVisualizationSpecs
|
|
114
|
+
]);
|
|
115
|
+
var MarketplaceVisualizationRefs = MarketplaceVisualizationSpecs.map((spec) => ({
|
|
116
|
+
key: spec.meta.key,
|
|
117
|
+
version: spec.meta.version
|
|
118
|
+
}));
|
|
119
|
+
|
|
120
|
+
// src/visualizations/selectors.ts
|
|
121
|
+
function toDayKey(value) {
|
|
122
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
123
|
+
return date.toISOString().slice(0, 10);
|
|
124
|
+
}
|
|
125
|
+
function createMarketplaceVisualizationItems(products, orders) {
|
|
126
|
+
const orderStatus = new Map;
|
|
127
|
+
const orderActivity = new Map;
|
|
128
|
+
const categoryValue = new Map;
|
|
129
|
+
for (const order of orders) {
|
|
130
|
+
orderStatus.set(order.status, (orderStatus.get(order.status) ?? 0) + 1);
|
|
131
|
+
const day = toDayKey(order.createdAt);
|
|
132
|
+
orderActivity.set(day, (orderActivity.get(day) ?? 0) + 1);
|
|
133
|
+
}
|
|
134
|
+
for (const product of products) {
|
|
135
|
+
const category = product.category ?? "Uncategorized";
|
|
136
|
+
categoryValue.set(category, (categoryValue.get(category) ?? 0) + product.price * product.stock);
|
|
137
|
+
}
|
|
138
|
+
return [
|
|
139
|
+
{
|
|
140
|
+
key: "marketplace-order-status",
|
|
141
|
+
spec: MarketplaceOrderStatusVisualization,
|
|
142
|
+
data: {
|
|
143
|
+
data: Array.from(orderStatus.entries()).map(([status, count]) => ({
|
|
144
|
+
status,
|
|
145
|
+
orders: count
|
|
146
|
+
}))
|
|
147
|
+
},
|
|
148
|
+
title: "Order Status Breakdown",
|
|
149
|
+
description: "Status mix across the current order set.",
|
|
150
|
+
height: 260
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
key: "marketplace-category-value",
|
|
154
|
+
spec: MarketplaceCategoryValueVisualization,
|
|
155
|
+
data: {
|
|
156
|
+
data: Array.from(categoryValue.entries()).sort(([, left], [, right]) => right - left).map(([category, value]) => ({
|
|
157
|
+
category,
|
|
158
|
+
catalogValue: value
|
|
159
|
+
}))
|
|
160
|
+
},
|
|
161
|
+
title: "Category Value Comparison",
|
|
162
|
+
description: "Derived from current product pricing and stock."
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
key: "marketplace-order-activity",
|
|
166
|
+
spec: MarketplaceOrderActivityVisualization,
|
|
167
|
+
data: {
|
|
168
|
+
data: Array.from(orderActivity.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, orders: count }))
|
|
169
|
+
},
|
|
170
|
+
title: "Recent Order Activity",
|
|
171
|
+
description: "Daily order count from current order history."
|
|
172
|
+
}
|
|
173
|
+
];
|
|
174
|
+
}
|
|
1
175
|
// src/ui/renderers/marketplace.markdown.ts
|
|
2
176
|
var mockStores = [
|
|
3
177
|
{
|
|
@@ -27,6 +201,7 @@ var mockProducts = [
|
|
|
27
201
|
id: "prod-1",
|
|
28
202
|
name: "Wireless Earbuds",
|
|
29
203
|
storeId: "store-1",
|
|
204
|
+
category: "Electronics",
|
|
30
205
|
price: 79.99,
|
|
31
206
|
currency: "USD",
|
|
32
207
|
status: "ACTIVE",
|
|
@@ -36,6 +211,7 @@ var mockProducts = [
|
|
|
36
211
|
id: "prod-2",
|
|
37
212
|
name: "Smart Watch",
|
|
38
213
|
storeId: "store-1",
|
|
214
|
+
category: "Wearables",
|
|
39
215
|
price: 249.99,
|
|
40
216
|
currency: "USD",
|
|
41
217
|
status: "ACTIVE",
|
|
@@ -45,6 +221,7 @@ var mockProducts = [
|
|
|
45
221
|
id: "prod-3",
|
|
46
222
|
name: "Garden Tools Set",
|
|
47
223
|
storeId: "store-2",
|
|
224
|
+
category: "Garden",
|
|
48
225
|
price: 89.99,
|
|
49
226
|
currency: "USD",
|
|
50
227
|
status: "ACTIVE",
|
|
@@ -54,6 +231,7 @@ var mockProducts = [
|
|
|
54
231
|
id: "prod-4",
|
|
55
232
|
name: "Indoor Plant Kit",
|
|
56
233
|
storeId: "store-2",
|
|
234
|
+
category: "Garden",
|
|
57
235
|
price: 45.99,
|
|
58
236
|
currency: "USD",
|
|
59
237
|
status: "ACTIVE",
|
|
@@ -63,6 +241,7 @@ var mockProducts = [
|
|
|
63
241
|
id: "prod-5",
|
|
64
242
|
name: "LED Desk Lamp",
|
|
65
243
|
storeId: "store-1",
|
|
244
|
+
category: "Home Office",
|
|
66
245
|
price: 34.99,
|
|
67
246
|
currency: "USD",
|
|
68
247
|
status: "OUT_OF_STOCK",
|
|
@@ -127,6 +306,7 @@ var marketplaceDashboardMarkdownRenderer = {
|
|
|
127
306
|
const stores = mockStores;
|
|
128
307
|
const products = mockProducts;
|
|
129
308
|
const orders = mockOrders;
|
|
309
|
+
const visualizationItems = createMarketplaceVisualizationItems(products, orders);
|
|
130
310
|
const activeStores = stores.filter((s) => s.status === "ACTIVE");
|
|
131
311
|
const activeProducts = products.filter((p) => p.status === "ACTIVE");
|
|
132
312
|
const totalRevenue = orders.reduce((sum, o) => sum + o.total, 0);
|
|
@@ -146,11 +326,17 @@ var marketplaceDashboardMarkdownRenderer = {
|
|
|
146
326
|
`| Total Revenue | ${formatCurrency(totalRevenue)} |`,
|
|
147
327
|
`| Pending Orders | ${pendingOrders.length} |`,
|
|
148
328
|
"",
|
|
149
|
-
"##
|
|
150
|
-
""
|
|
151
|
-
"| Store | Products | Rating | Status |",
|
|
152
|
-
"|-------|----------|--------|--------|"
|
|
329
|
+
"## Visualization Overview",
|
|
330
|
+
""
|
|
153
331
|
];
|
|
332
|
+
for (const item of visualizationItems) {
|
|
333
|
+
lines.push(`- **${item.title}** via \`${item.spec.meta.key}\``);
|
|
334
|
+
}
|
|
335
|
+
lines.push("");
|
|
336
|
+
lines.push("## Top Stores");
|
|
337
|
+
lines.push("");
|
|
338
|
+
lines.push("| Store | Products | Rating | Status |");
|
|
339
|
+
lines.push("|-------|----------|--------|--------|");
|
|
154
340
|
for (const store of stores.slice(0, 5)) {
|
|
155
341
|
lines.push(`| ${store.name} | ${store.productCount} | ⭐ ${store.rating || "N/A"} | ${store.status} |`);
|
|
156
342
|
}
|
|
@@ -1,3 +1,177 @@
|
|
|
1
|
+
// src/visualizations/catalog.ts
|
|
2
|
+
import {
|
|
3
|
+
defineVisualization,
|
|
4
|
+
VisualizationRegistry
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
6
|
+
var ORDER_LIST_REF = {
|
|
7
|
+
key: "marketplace.order.list",
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
};
|
|
10
|
+
var PRODUCT_LIST_REF = {
|
|
11
|
+
key: "marketplace.product.list",
|
|
12
|
+
version: "1.0.0"
|
|
13
|
+
};
|
|
14
|
+
var META = {
|
|
15
|
+
version: "1.0.0",
|
|
16
|
+
domain: "marketplace",
|
|
17
|
+
stability: "experimental",
|
|
18
|
+
owners: ["@example.marketplace"],
|
|
19
|
+
tags: ["marketplace", "visualization", "commerce"]
|
|
20
|
+
};
|
|
21
|
+
var MarketplaceOrderStatusVisualization = defineVisualization({
|
|
22
|
+
meta: {
|
|
23
|
+
...META,
|
|
24
|
+
key: "marketplace.visualization.order-status",
|
|
25
|
+
title: "Order Status Breakdown",
|
|
26
|
+
description: "Distribution of current order states.",
|
|
27
|
+
goal: "Expose delivery and backlog mix at a glance.",
|
|
28
|
+
context: "Marketplace operations overview."
|
|
29
|
+
},
|
|
30
|
+
source: { primary: ORDER_LIST_REF, resultPath: "data" },
|
|
31
|
+
visualization: {
|
|
32
|
+
kind: "pie",
|
|
33
|
+
nameDimension: "status",
|
|
34
|
+
valueMeasure: "orders",
|
|
35
|
+
dimensions: [
|
|
36
|
+
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
37
|
+
],
|
|
38
|
+
measures: [
|
|
39
|
+
{ key: "orders", label: "Orders", dataPath: "orders", format: "number" }
|
|
40
|
+
],
|
|
41
|
+
table: { caption: "Order counts by status." }
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
var MarketplaceCategoryValueVisualization = defineVisualization({
|
|
45
|
+
meta: {
|
|
46
|
+
...META,
|
|
47
|
+
key: "marketplace.visualization.category-value",
|
|
48
|
+
title: "Category Value Comparison",
|
|
49
|
+
description: "Catalog value by product category derived from current pricing and stock.",
|
|
50
|
+
goal: "Compare where the marketplace catalog is concentrated.",
|
|
51
|
+
context: "Merchandising overview."
|
|
52
|
+
},
|
|
53
|
+
source: { primary: PRODUCT_LIST_REF, resultPath: "data" },
|
|
54
|
+
visualization: {
|
|
55
|
+
kind: "cartesian",
|
|
56
|
+
variant: "bar",
|
|
57
|
+
xDimension: "category",
|
|
58
|
+
yMeasures: ["catalogValue"],
|
|
59
|
+
dimensions: [
|
|
60
|
+
{
|
|
61
|
+
key: "category",
|
|
62
|
+
label: "Category",
|
|
63
|
+
dataPath: "category",
|
|
64
|
+
type: "category"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
measures: [
|
|
68
|
+
{
|
|
69
|
+
key: "catalogValue",
|
|
70
|
+
label: "Catalog Value",
|
|
71
|
+
dataPath: "catalogValue",
|
|
72
|
+
format: "currency",
|
|
73
|
+
color: "#1d4ed8"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
table: { caption: "Catalog value by product category." }
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
var MarketplaceOrderActivityVisualization = defineVisualization({
|
|
80
|
+
meta: {
|
|
81
|
+
...META,
|
|
82
|
+
key: "marketplace.visualization.order-activity",
|
|
83
|
+
title: "Recent Order Activity",
|
|
84
|
+
description: "Daily order volume from recent order creation timestamps.",
|
|
85
|
+
goal: "Show recent order activity trends.",
|
|
86
|
+
context: "Commerce operations trend monitoring."
|
|
87
|
+
},
|
|
88
|
+
source: { primary: ORDER_LIST_REF, resultPath: "data" },
|
|
89
|
+
visualization: {
|
|
90
|
+
kind: "cartesian",
|
|
91
|
+
variant: "line",
|
|
92
|
+
xDimension: "day",
|
|
93
|
+
yMeasures: ["orders"],
|
|
94
|
+
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
95
|
+
measures: [
|
|
96
|
+
{
|
|
97
|
+
key: "orders",
|
|
98
|
+
label: "Orders",
|
|
99
|
+
dataPath: "orders",
|
|
100
|
+
format: "number",
|
|
101
|
+
color: "#0f766e"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
table: { caption: "Daily order counts." }
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
var MarketplaceVisualizationSpecs = [
|
|
108
|
+
MarketplaceOrderStatusVisualization,
|
|
109
|
+
MarketplaceCategoryValueVisualization,
|
|
110
|
+
MarketplaceOrderActivityVisualization
|
|
111
|
+
];
|
|
112
|
+
var MarketplaceVisualizationRegistry = new VisualizationRegistry([
|
|
113
|
+
...MarketplaceVisualizationSpecs
|
|
114
|
+
]);
|
|
115
|
+
var MarketplaceVisualizationRefs = MarketplaceVisualizationSpecs.map((spec) => ({
|
|
116
|
+
key: spec.meta.key,
|
|
117
|
+
version: spec.meta.version
|
|
118
|
+
}));
|
|
119
|
+
|
|
120
|
+
// src/visualizations/selectors.ts
|
|
121
|
+
function toDayKey(value) {
|
|
122
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
123
|
+
return date.toISOString().slice(0, 10);
|
|
124
|
+
}
|
|
125
|
+
function createMarketplaceVisualizationItems(products, orders) {
|
|
126
|
+
const orderStatus = new Map;
|
|
127
|
+
const orderActivity = new Map;
|
|
128
|
+
const categoryValue = new Map;
|
|
129
|
+
for (const order of orders) {
|
|
130
|
+
orderStatus.set(order.status, (orderStatus.get(order.status) ?? 0) + 1);
|
|
131
|
+
const day = toDayKey(order.createdAt);
|
|
132
|
+
orderActivity.set(day, (orderActivity.get(day) ?? 0) + 1);
|
|
133
|
+
}
|
|
134
|
+
for (const product of products) {
|
|
135
|
+
const category = product.category ?? "Uncategorized";
|
|
136
|
+
categoryValue.set(category, (categoryValue.get(category) ?? 0) + product.price * product.stock);
|
|
137
|
+
}
|
|
138
|
+
return [
|
|
139
|
+
{
|
|
140
|
+
key: "marketplace-order-status",
|
|
141
|
+
spec: MarketplaceOrderStatusVisualization,
|
|
142
|
+
data: {
|
|
143
|
+
data: Array.from(orderStatus.entries()).map(([status, count]) => ({
|
|
144
|
+
status,
|
|
145
|
+
orders: count
|
|
146
|
+
}))
|
|
147
|
+
},
|
|
148
|
+
title: "Order Status Breakdown",
|
|
149
|
+
description: "Status mix across the current order set.",
|
|
150
|
+
height: 260
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
key: "marketplace-category-value",
|
|
154
|
+
spec: MarketplaceCategoryValueVisualization,
|
|
155
|
+
data: {
|
|
156
|
+
data: Array.from(categoryValue.entries()).sort(([, left], [, right]) => right - left).map(([category, value]) => ({
|
|
157
|
+
category,
|
|
158
|
+
catalogValue: value
|
|
159
|
+
}))
|
|
160
|
+
},
|
|
161
|
+
title: "Category Value Comparison",
|
|
162
|
+
description: "Derived from current product pricing and stock."
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
key: "marketplace-order-activity",
|
|
166
|
+
spec: MarketplaceOrderActivityVisualization,
|
|
167
|
+
data: {
|
|
168
|
+
data: Array.from(orderActivity.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, orders: count }))
|
|
169
|
+
},
|
|
170
|
+
title: "Recent Order Activity",
|
|
171
|
+
description: "Daily order count from current order history."
|
|
172
|
+
}
|
|
173
|
+
];
|
|
174
|
+
}
|
|
1
175
|
// src/ui/renderers/marketplace.markdown.ts
|
|
2
176
|
var mockStores = [
|
|
3
177
|
{
|
|
@@ -27,6 +201,7 @@ var mockProducts = [
|
|
|
27
201
|
id: "prod-1",
|
|
28
202
|
name: "Wireless Earbuds",
|
|
29
203
|
storeId: "store-1",
|
|
204
|
+
category: "Electronics",
|
|
30
205
|
price: 79.99,
|
|
31
206
|
currency: "USD",
|
|
32
207
|
status: "ACTIVE",
|
|
@@ -36,6 +211,7 @@ var mockProducts = [
|
|
|
36
211
|
id: "prod-2",
|
|
37
212
|
name: "Smart Watch",
|
|
38
213
|
storeId: "store-1",
|
|
214
|
+
category: "Wearables",
|
|
39
215
|
price: 249.99,
|
|
40
216
|
currency: "USD",
|
|
41
217
|
status: "ACTIVE",
|
|
@@ -45,6 +221,7 @@ var mockProducts = [
|
|
|
45
221
|
id: "prod-3",
|
|
46
222
|
name: "Garden Tools Set",
|
|
47
223
|
storeId: "store-2",
|
|
224
|
+
category: "Garden",
|
|
48
225
|
price: 89.99,
|
|
49
226
|
currency: "USD",
|
|
50
227
|
status: "ACTIVE",
|
|
@@ -54,6 +231,7 @@ var mockProducts = [
|
|
|
54
231
|
id: "prod-4",
|
|
55
232
|
name: "Indoor Plant Kit",
|
|
56
233
|
storeId: "store-2",
|
|
234
|
+
category: "Garden",
|
|
57
235
|
price: 45.99,
|
|
58
236
|
currency: "USD",
|
|
59
237
|
status: "ACTIVE",
|
|
@@ -63,6 +241,7 @@ var mockProducts = [
|
|
|
63
241
|
id: "prod-5",
|
|
64
242
|
name: "LED Desk Lamp",
|
|
65
243
|
storeId: "store-1",
|
|
244
|
+
category: "Home Office",
|
|
66
245
|
price: 34.99,
|
|
67
246
|
currency: "USD",
|
|
68
247
|
status: "OUT_OF_STOCK",
|
|
@@ -127,6 +306,7 @@ var marketplaceDashboardMarkdownRenderer = {
|
|
|
127
306
|
const stores = mockStores;
|
|
128
307
|
const products = mockProducts;
|
|
129
308
|
const orders = mockOrders;
|
|
309
|
+
const visualizationItems = createMarketplaceVisualizationItems(products, orders);
|
|
130
310
|
const activeStores = stores.filter((s) => s.status === "ACTIVE");
|
|
131
311
|
const activeProducts = products.filter((p) => p.status === "ACTIVE");
|
|
132
312
|
const totalRevenue = orders.reduce((sum, o) => sum + o.total, 0);
|
|
@@ -146,11 +326,17 @@ var marketplaceDashboardMarkdownRenderer = {
|
|
|
146
326
|
`| Total Revenue | ${formatCurrency(totalRevenue)} |`,
|
|
147
327
|
`| Pending Orders | ${pendingOrders.length} |`,
|
|
148
328
|
"",
|
|
149
|
-
"##
|
|
150
|
-
""
|
|
151
|
-
"| Store | Products | Rating | Status |",
|
|
152
|
-
"|-------|----------|--------|--------|"
|
|
329
|
+
"## Visualization Overview",
|
|
330
|
+
""
|
|
153
331
|
];
|
|
332
|
+
for (const item of visualizationItems) {
|
|
333
|
+
lines.push(`- **${item.title}** via \`${item.spec.meta.key}\``);
|
|
334
|
+
}
|
|
335
|
+
lines.push("");
|
|
336
|
+
lines.push("## Top Stores");
|
|
337
|
+
lines.push("");
|
|
338
|
+
lines.push("| Store | Products | Rating | Status |");
|
|
339
|
+
lines.push("|-------|----------|--------|--------|");
|
|
154
340
|
for (const store of stores.slice(0, 5)) {
|
|
155
341
|
lines.push(`| ${store.name} | ${store.productCount} | ⭐ ${store.rating || "N/A"} | ${store.status} |`);
|
|
156
342
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// src/visualizations/catalog.ts
|
|
2
|
+
import {
|
|
3
|
+
defineVisualization,
|
|
4
|
+
VisualizationRegistry
|
|
5
|
+
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
6
|
+
var ORDER_LIST_REF = {
|
|
7
|
+
key: "marketplace.order.list",
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
};
|
|
10
|
+
var PRODUCT_LIST_REF = {
|
|
11
|
+
key: "marketplace.product.list",
|
|
12
|
+
version: "1.0.0"
|
|
13
|
+
};
|
|
14
|
+
var META = {
|
|
15
|
+
version: "1.0.0",
|
|
16
|
+
domain: "marketplace",
|
|
17
|
+
stability: "experimental",
|
|
18
|
+
owners: ["@example.marketplace"],
|
|
19
|
+
tags: ["marketplace", "visualization", "commerce"]
|
|
20
|
+
};
|
|
21
|
+
var MarketplaceOrderStatusVisualization = defineVisualization({
|
|
22
|
+
meta: {
|
|
23
|
+
...META,
|
|
24
|
+
key: "marketplace.visualization.order-status",
|
|
25
|
+
title: "Order Status Breakdown",
|
|
26
|
+
description: "Distribution of current order states.",
|
|
27
|
+
goal: "Expose delivery and backlog mix at a glance.",
|
|
28
|
+
context: "Marketplace operations overview."
|
|
29
|
+
},
|
|
30
|
+
source: { primary: ORDER_LIST_REF, resultPath: "data" },
|
|
31
|
+
visualization: {
|
|
32
|
+
kind: "pie",
|
|
33
|
+
nameDimension: "status",
|
|
34
|
+
valueMeasure: "orders",
|
|
35
|
+
dimensions: [
|
|
36
|
+
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
37
|
+
],
|
|
38
|
+
measures: [
|
|
39
|
+
{ key: "orders", label: "Orders", dataPath: "orders", format: "number" }
|
|
40
|
+
],
|
|
41
|
+
table: { caption: "Order counts by status." }
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
var MarketplaceCategoryValueVisualization = defineVisualization({
|
|
45
|
+
meta: {
|
|
46
|
+
...META,
|
|
47
|
+
key: "marketplace.visualization.category-value",
|
|
48
|
+
title: "Category Value Comparison",
|
|
49
|
+
description: "Catalog value by product category derived from current pricing and stock.",
|
|
50
|
+
goal: "Compare where the marketplace catalog is concentrated.",
|
|
51
|
+
context: "Merchandising overview."
|
|
52
|
+
},
|
|
53
|
+
source: { primary: PRODUCT_LIST_REF, resultPath: "data" },
|
|
54
|
+
visualization: {
|
|
55
|
+
kind: "cartesian",
|
|
56
|
+
variant: "bar",
|
|
57
|
+
xDimension: "category",
|
|
58
|
+
yMeasures: ["catalogValue"],
|
|
59
|
+
dimensions: [
|
|
60
|
+
{
|
|
61
|
+
key: "category",
|
|
62
|
+
label: "Category",
|
|
63
|
+
dataPath: "category",
|
|
64
|
+
type: "category"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
measures: [
|
|
68
|
+
{
|
|
69
|
+
key: "catalogValue",
|
|
70
|
+
label: "Catalog Value",
|
|
71
|
+
dataPath: "catalogValue",
|
|
72
|
+
format: "currency",
|
|
73
|
+
color: "#1d4ed8"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
table: { caption: "Catalog value by product category." }
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
var MarketplaceOrderActivityVisualization = defineVisualization({
|
|
80
|
+
meta: {
|
|
81
|
+
...META,
|
|
82
|
+
key: "marketplace.visualization.order-activity",
|
|
83
|
+
title: "Recent Order Activity",
|
|
84
|
+
description: "Daily order volume from recent order creation timestamps.",
|
|
85
|
+
goal: "Show recent order activity trends.",
|
|
86
|
+
context: "Commerce operations trend monitoring."
|
|
87
|
+
},
|
|
88
|
+
source: { primary: ORDER_LIST_REF, resultPath: "data" },
|
|
89
|
+
visualization: {
|
|
90
|
+
kind: "cartesian",
|
|
91
|
+
variant: "line",
|
|
92
|
+
xDimension: "day",
|
|
93
|
+
yMeasures: ["orders"],
|
|
94
|
+
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
95
|
+
measures: [
|
|
96
|
+
{
|
|
97
|
+
key: "orders",
|
|
98
|
+
label: "Orders",
|
|
99
|
+
dataPath: "orders",
|
|
100
|
+
format: "number",
|
|
101
|
+
color: "#0f766e"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
table: { caption: "Daily order counts." }
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
var MarketplaceVisualizationSpecs = [
|
|
108
|
+
MarketplaceOrderStatusVisualization,
|
|
109
|
+
MarketplaceCategoryValueVisualization,
|
|
110
|
+
MarketplaceOrderActivityVisualization
|
|
111
|
+
];
|
|
112
|
+
var MarketplaceVisualizationRegistry = new VisualizationRegistry([
|
|
113
|
+
...MarketplaceVisualizationSpecs
|
|
114
|
+
]);
|
|
115
|
+
var MarketplaceVisualizationRefs = MarketplaceVisualizationSpecs.map((spec) => ({
|
|
116
|
+
key: spec.meta.key,
|
|
117
|
+
version: spec.meta.version
|
|
118
|
+
}));
|
|
119
|
+
export {
|
|
120
|
+
MarketplaceVisualizationSpecs,
|
|
121
|
+
MarketplaceVisualizationRegistry,
|
|
122
|
+
MarketplaceVisualizationRefs,
|
|
123
|
+
MarketplaceOrderStatusVisualization,
|
|
124
|
+
MarketplaceOrderActivityVisualization,
|
|
125
|
+
MarketplaceCategoryValueVisualization
|
|
126
|
+
};
|