@bbearai/react 0.1.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/README.md +178 -0
- package/dist/index.d.mts +71 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +885 -0
- package/dist/index.mjs +854 -0
- package/package.json +56 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,854 @@
|
|
|
1
|
+
// src/BugBearProvider.tsx
|
|
2
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
3
|
+
import {
|
|
4
|
+
createBugBear
|
|
5
|
+
} from "@bbearai/core";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
var BugBearContext = createContext({
|
|
8
|
+
client: null,
|
|
9
|
+
isTester: false,
|
|
10
|
+
isQAEnabled: false,
|
|
11
|
+
shouldShowWidget: false,
|
|
12
|
+
testerInfo: null,
|
|
13
|
+
assignments: [],
|
|
14
|
+
currentAssignment: null,
|
|
15
|
+
refreshAssignments: async () => {
|
|
16
|
+
},
|
|
17
|
+
isLoading: true,
|
|
18
|
+
onNavigate: void 0
|
|
19
|
+
});
|
|
20
|
+
function useBugBear() {
|
|
21
|
+
return useContext(BugBearContext);
|
|
22
|
+
}
|
|
23
|
+
function BugBearProvider({ config, children }) {
|
|
24
|
+
const [client] = useState(() => createBugBear(config));
|
|
25
|
+
const [isTester, setIsTester] = useState(false);
|
|
26
|
+
const [isQAEnabled, setIsQAEnabled] = useState(false);
|
|
27
|
+
const [testerInfo, setTesterInfo] = useState(null);
|
|
28
|
+
const [assignments, setAssignments] = useState([]);
|
|
29
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
30
|
+
const refreshAssignments = async () => {
|
|
31
|
+
const newAssignments = await client.getAssignedTests();
|
|
32
|
+
setAssignments(newAssignments);
|
|
33
|
+
};
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const init = async () => {
|
|
36
|
+
setIsLoading(true);
|
|
37
|
+
try {
|
|
38
|
+
const [qaEnabled, info] = await Promise.all([
|
|
39
|
+
client.isQAEnabled(),
|
|
40
|
+
client.getTesterInfo()
|
|
41
|
+
]);
|
|
42
|
+
console.log("BugBear: Init complete", { qaEnabled, testerInfo: info });
|
|
43
|
+
setIsQAEnabled(qaEnabled);
|
|
44
|
+
setTesterInfo(info);
|
|
45
|
+
setIsTester(!!info);
|
|
46
|
+
if (info && qaEnabled) {
|
|
47
|
+
await refreshAssignments();
|
|
48
|
+
}
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.error("BugBear: Init error", err);
|
|
51
|
+
} finally {
|
|
52
|
+
setIsLoading(false);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
init();
|
|
56
|
+
}, [client]);
|
|
57
|
+
const currentAssignment = assignments.find(
|
|
58
|
+
(a) => a.status === "in_progress"
|
|
59
|
+
) || assignments[0] || null;
|
|
60
|
+
const shouldShowWidget = isQAEnabled && isTester;
|
|
61
|
+
return /* @__PURE__ */ jsx(
|
|
62
|
+
BugBearContext.Provider,
|
|
63
|
+
{
|
|
64
|
+
value: {
|
|
65
|
+
client,
|
|
66
|
+
isTester,
|
|
67
|
+
isQAEnabled,
|
|
68
|
+
shouldShowWidget,
|
|
69
|
+
testerInfo,
|
|
70
|
+
assignments,
|
|
71
|
+
currentAssignment,
|
|
72
|
+
refreshAssignments,
|
|
73
|
+
isLoading,
|
|
74
|
+
onNavigate: config.onNavigate
|
|
75
|
+
},
|
|
76
|
+
children
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/BugBearPanel.tsx
|
|
82
|
+
import { useState as useState2, useRef, useEffect as useEffect2, useCallback } from "react";
|
|
83
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
84
|
+
function BugBearIcon({ size = 24, className = "" }) {
|
|
85
|
+
return /* @__PURE__ */ jsxs(
|
|
86
|
+
"svg",
|
|
87
|
+
{
|
|
88
|
+
width: size,
|
|
89
|
+
height: size,
|
|
90
|
+
viewBox: "0 0 64 64",
|
|
91
|
+
fill: "none",
|
|
92
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
93
|
+
className,
|
|
94
|
+
children: [
|
|
95
|
+
/* @__PURE__ */ jsx2("circle", { cx: "32", cy: "32", r: "30", fill: "#1a1a2e", stroke: "#d4a852", strokeWidth: "3" }),
|
|
96
|
+
/* @__PURE__ */ jsx2("ellipse", { cx: "18", cy: "18", rx: "8", ry: "7", fill: "#8B4513" }),
|
|
97
|
+
/* @__PURE__ */ jsx2("ellipse", { cx: "18", cy: "18", rx: "5", ry: "4", fill: "#D2691E" }),
|
|
98
|
+
/* @__PURE__ */ jsx2("ellipse", { cx: "46", cy: "18", rx: "8", ry: "7", fill: "#8B4513" }),
|
|
99
|
+
/* @__PURE__ */ jsx2("ellipse", { cx: "46", cy: "18", rx: "5", ry: "4", fill: "#D2691E" }),
|
|
100
|
+
/* @__PURE__ */ jsx2("ellipse", { cx: "32", cy: "34", rx: "20", ry: "18", fill: "#8B4513" }),
|
|
101
|
+
/* @__PURE__ */ jsx2("ellipse", { cx: "32", cy: "40", rx: "12", ry: "10", fill: "#D2691E" }),
|
|
102
|
+
/* @__PURE__ */ jsx2("ellipse", { cx: "32", cy: "38", rx: "4", ry: "3", fill: "#1a1a2e" }),
|
|
103
|
+
/* @__PURE__ */ jsx2("circle", { cx: "24", cy: "30", r: "4", fill: "#1a1a2e" }),
|
|
104
|
+
/* @__PURE__ */ jsx2("circle", { cx: "40", cy: "30", r: "4", fill: "#1a1a2e" }),
|
|
105
|
+
/* @__PURE__ */ jsx2("circle", { cx: "25", cy: "29", r: "1.5", fill: "white" }),
|
|
106
|
+
/* @__PURE__ */ jsx2("circle", { cx: "41", cy: "29", r: "1.5", fill: "white" }),
|
|
107
|
+
/* @__PURE__ */ jsx2("circle", { cx: "48", cy: "44", r: "8", fill: "none", stroke: "#d4a852", strokeWidth: "2.5" }),
|
|
108
|
+
/* @__PURE__ */ jsx2("line", { x1: "54", y1: "50", x2: "58", y2: "54", stroke: "#d4a852", strokeWidth: "3", strokeLinecap: "round" }),
|
|
109
|
+
/* @__PURE__ */ jsx2("path", { d: "M44 40 Q46 38, 48 40", stroke: "rgba(255,255,255,0.4)", strokeWidth: "1.5", fill: "none", strokeLinecap: "round" })
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
var templateInfo = {
|
|
115
|
+
steps: { name: "Steps", icon: "\u{1F4DD}", action: "Follow each step" },
|
|
116
|
+
checklist: { name: "Checklist", icon: "\u2705", action: "Pass/Fail each item" },
|
|
117
|
+
rubric: { name: "Rubric", icon: "\u{1F4CA}", action: "Rate each criterion" },
|
|
118
|
+
freeform: { name: "Freeform", icon: "\u{1F4AD}", action: "Provide observations" }
|
|
119
|
+
};
|
|
120
|
+
var STORAGE_KEY = "bugbear-panel-position";
|
|
121
|
+
var PANEL_WIDTH = 320;
|
|
122
|
+
var PANEL_HEIGHT_ESTIMATE = 500;
|
|
123
|
+
function getDefaultPosition(position) {
|
|
124
|
+
if (typeof window === "undefined") return { x: 0, y: 0 };
|
|
125
|
+
const padding = 16;
|
|
126
|
+
switch (position) {
|
|
127
|
+
case "bottom-left":
|
|
128
|
+
return { x: padding, y: window.innerHeight - PANEL_HEIGHT_ESTIMATE - padding };
|
|
129
|
+
case "top-right":
|
|
130
|
+
return { x: window.innerWidth - PANEL_WIDTH - padding, y: padding };
|
|
131
|
+
case "top-left":
|
|
132
|
+
return { x: padding, y: padding };
|
|
133
|
+
case "bottom-right":
|
|
134
|
+
default:
|
|
135
|
+
return { x: window.innerWidth - PANEL_WIDTH - padding, y: window.innerHeight - PANEL_HEIGHT_ESTIMATE - padding };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function clampPosition(pos) {
|
|
139
|
+
if (typeof window === "undefined") return pos;
|
|
140
|
+
const padding = 8;
|
|
141
|
+
return {
|
|
142
|
+
x: Math.max(padding, Math.min(pos.x, window.innerWidth - PANEL_WIDTH - padding)),
|
|
143
|
+
y: Math.max(padding, Math.min(pos.y, window.innerHeight - 100))
|
|
144
|
+
// Keep at least 100px visible
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function BugBearPanel({
|
|
148
|
+
getAppContext,
|
|
149
|
+
position = "bottom-right",
|
|
150
|
+
defaultCollapsed = false,
|
|
151
|
+
draggable = true
|
|
152
|
+
}) {
|
|
153
|
+
const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate } = useBugBear();
|
|
154
|
+
const [collapsed, setCollapsed] = useState2(defaultCollapsed);
|
|
155
|
+
const [activeTab, setActiveTab] = useState2("tests");
|
|
156
|
+
const [showSteps, setShowSteps] = useState2(false);
|
|
157
|
+
const [testView, setTestView] = useState2("detail");
|
|
158
|
+
const [selectedTestId, setSelectedTestId] = useState2(null);
|
|
159
|
+
const displayedAssignment = selectedTestId ? assignments.find((a) => a.id === selectedTestId) || currentAssignment : currentAssignment;
|
|
160
|
+
const [panelPosition, setPanelPosition] = useState2(null);
|
|
161
|
+
const [isDragging, setIsDragging] = useState2(false);
|
|
162
|
+
const dragStartRef = useRef(null);
|
|
163
|
+
const panelRef = useRef(null);
|
|
164
|
+
const [reportType, setReportType] = useState2("bug");
|
|
165
|
+
const [description, setDescription] = useState2("");
|
|
166
|
+
const [severity, setSeverity] = useState2("medium");
|
|
167
|
+
const [submitting, setSubmitting] = useState2(false);
|
|
168
|
+
const [submitted, setSubmitted] = useState2(false);
|
|
169
|
+
const [justPassed, setJustPassed] = useState2(false);
|
|
170
|
+
const [criteriaResults, setCriteriaResults] = useState2({});
|
|
171
|
+
useEffect2(() => {
|
|
172
|
+
if (typeof window === "undefined") return;
|
|
173
|
+
try {
|
|
174
|
+
const saved = localStorage.getItem(STORAGE_KEY);
|
|
175
|
+
if (saved) {
|
|
176
|
+
const parsed = JSON.parse(saved);
|
|
177
|
+
setPanelPosition(clampPosition(parsed));
|
|
178
|
+
} else {
|
|
179
|
+
setPanelPosition(getDefaultPosition(position));
|
|
180
|
+
}
|
|
181
|
+
} catch {
|
|
182
|
+
setPanelPosition(getDefaultPosition(position));
|
|
183
|
+
}
|
|
184
|
+
}, [position]);
|
|
185
|
+
useEffect2(() => {
|
|
186
|
+
if (panelPosition && typeof window !== "undefined") {
|
|
187
|
+
try {
|
|
188
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(panelPosition));
|
|
189
|
+
} catch {
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}, [panelPosition]);
|
|
193
|
+
useEffect2(() => {
|
|
194
|
+
if (typeof window === "undefined") return;
|
|
195
|
+
const handleResize = () => {
|
|
196
|
+
setPanelPosition((prev) => prev ? clampPosition(prev) : getDefaultPosition(position));
|
|
197
|
+
};
|
|
198
|
+
window.addEventListener("resize", handleResize);
|
|
199
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
200
|
+
}, [position]);
|
|
201
|
+
useEffect2(() => {
|
|
202
|
+
setCriteriaResults({});
|
|
203
|
+
setShowSteps(false);
|
|
204
|
+
}, [displayedAssignment?.id]);
|
|
205
|
+
const handleMouseDown = useCallback((e) => {
|
|
206
|
+
if (!draggable || !panelPosition) return;
|
|
207
|
+
const target = e.target;
|
|
208
|
+
if (!target.closest("[data-drag-handle]")) return;
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
setIsDragging(true);
|
|
211
|
+
dragStartRef.current = {
|
|
212
|
+
mouseX: e.clientX,
|
|
213
|
+
mouseY: e.clientY,
|
|
214
|
+
panelX: panelPosition.x,
|
|
215
|
+
panelY: panelPosition.y
|
|
216
|
+
};
|
|
217
|
+
}, [draggable, panelPosition]);
|
|
218
|
+
useEffect2(() => {
|
|
219
|
+
if (!isDragging) return;
|
|
220
|
+
const handleMouseMove = (e) => {
|
|
221
|
+
if (!dragStartRef.current) return;
|
|
222
|
+
const deltaX = e.clientX - dragStartRef.current.mouseX;
|
|
223
|
+
const deltaY = e.clientY - dragStartRef.current.mouseY;
|
|
224
|
+
setPanelPosition(clampPosition({
|
|
225
|
+
x: dragStartRef.current.panelX + deltaX,
|
|
226
|
+
y: dragStartRef.current.panelY + deltaY
|
|
227
|
+
}));
|
|
228
|
+
};
|
|
229
|
+
const handleMouseUp = () => {
|
|
230
|
+
setIsDragging(false);
|
|
231
|
+
dragStartRef.current = null;
|
|
232
|
+
};
|
|
233
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
234
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
235
|
+
return () => {
|
|
236
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
237
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
238
|
+
};
|
|
239
|
+
}, [isDragging]);
|
|
240
|
+
const handleDoubleClick = useCallback(() => {
|
|
241
|
+
if (!draggable) return;
|
|
242
|
+
setPanelPosition(getDefaultPosition(position));
|
|
243
|
+
try {
|
|
244
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
245
|
+
} catch {
|
|
246
|
+
}
|
|
247
|
+
}, [draggable, position]);
|
|
248
|
+
if (isLoading || !shouldShowWidget) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
if (!panelPosition) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const handlePass = async () => {
|
|
255
|
+
if (!client || !displayedAssignment) return;
|
|
256
|
+
setSubmitting(true);
|
|
257
|
+
await client.submitReport({
|
|
258
|
+
type: "test_pass",
|
|
259
|
+
description: `Test passed: ${displayedAssignment.testCase.title}`,
|
|
260
|
+
assignmentId: displayedAssignment.id,
|
|
261
|
+
testCaseId: displayedAssignment.testCase.id,
|
|
262
|
+
appContext: getAppContext?.() || { currentRoute: window.location.pathname }
|
|
263
|
+
});
|
|
264
|
+
await refreshAssignments();
|
|
265
|
+
setSubmitting(false);
|
|
266
|
+
setJustPassed(true);
|
|
267
|
+
setTimeout(() => {
|
|
268
|
+
setJustPassed(false);
|
|
269
|
+
setSelectedTestId(null);
|
|
270
|
+
setTestView("detail");
|
|
271
|
+
}, 1200);
|
|
272
|
+
};
|
|
273
|
+
const handleFail = async () => {
|
|
274
|
+
setActiveTab("report");
|
|
275
|
+
setReportType("test_fail");
|
|
276
|
+
};
|
|
277
|
+
const handleSubmitReport = async () => {
|
|
278
|
+
if (!client || !description.trim()) return;
|
|
279
|
+
setSubmitting(true);
|
|
280
|
+
const isTestFailure = reportType === "test_fail" && displayedAssignment;
|
|
281
|
+
await client.submitReport({
|
|
282
|
+
type: reportType,
|
|
283
|
+
description,
|
|
284
|
+
severity: reportType === "bug" || reportType === "test_fail" ? severity : void 0,
|
|
285
|
+
assignmentId: isTestFailure ? displayedAssignment.id : void 0,
|
|
286
|
+
testCaseId: isTestFailure ? displayedAssignment.testCase.id : void 0,
|
|
287
|
+
appContext: getAppContext?.() || { currentRoute: window.location.pathname }
|
|
288
|
+
});
|
|
289
|
+
setDescription("");
|
|
290
|
+
setSeverity("medium");
|
|
291
|
+
setSubmitted(true);
|
|
292
|
+
if (isTestFailure) {
|
|
293
|
+
await refreshAssignments();
|
|
294
|
+
}
|
|
295
|
+
setTimeout(() => {
|
|
296
|
+
setSubmitted(false);
|
|
297
|
+
setActiveTab("tests");
|
|
298
|
+
if (isTestFailure) {
|
|
299
|
+
setSelectedTestId(null);
|
|
300
|
+
setTestView("list");
|
|
301
|
+
}
|
|
302
|
+
}, 2e3);
|
|
303
|
+
setSubmitting(false);
|
|
304
|
+
};
|
|
305
|
+
const pendingCount = assignments.filter((a) => a.status === "pending").length;
|
|
306
|
+
const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
|
|
307
|
+
return /* @__PURE__ */ jsxs(
|
|
308
|
+
"div",
|
|
309
|
+
{
|
|
310
|
+
ref: panelRef,
|
|
311
|
+
className: "fixed font-sans",
|
|
312
|
+
style: {
|
|
313
|
+
zIndex: 2147483647,
|
|
314
|
+
// Max z-index to stay above all modals
|
|
315
|
+
left: panelPosition.x,
|
|
316
|
+
top: panelPosition.y,
|
|
317
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
318
|
+
cursor: isDragging ? "grabbing" : void 0,
|
|
319
|
+
userSelect: isDragging ? "none" : void 0
|
|
320
|
+
},
|
|
321
|
+
onMouseDown: handleMouseDown,
|
|
322
|
+
children: [
|
|
323
|
+
collapsed && /* @__PURE__ */ jsxs(
|
|
324
|
+
"button",
|
|
325
|
+
{
|
|
326
|
+
onClick: () => setCollapsed(false),
|
|
327
|
+
"data-drag-handle": true,
|
|
328
|
+
onDoubleClick: handleDoubleClick,
|
|
329
|
+
className: "flex items-center gap-2 px-3 py-2 bg-purple-600 text-white rounded-full shadow-lg hover:bg-purple-700 transition-colors",
|
|
330
|
+
style: { cursor: draggable ? "grab" : "pointer" },
|
|
331
|
+
children: [
|
|
332
|
+
/* @__PURE__ */ jsx2(BugBearIcon, { size: 24 }),
|
|
333
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: "BugBear" }),
|
|
334
|
+
pendingCount > 0 && /* @__PURE__ */ jsx2("span", { className: "bg-white text-purple-600 text-xs font-bold px-1.5 py-0.5 rounded-full", children: pendingCount })
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
),
|
|
338
|
+
!collapsed && /* @__PURE__ */ jsxs("div", { className: "w-80 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden", children: [
|
|
339
|
+
/* @__PURE__ */ jsxs(
|
|
340
|
+
"div",
|
|
341
|
+
{
|
|
342
|
+
"data-drag-handle": true,
|
|
343
|
+
onDoubleClick: handleDoubleClick,
|
|
344
|
+
className: "bg-purple-600 text-white px-4 py-3 flex items-center justify-between",
|
|
345
|
+
style: { cursor: draggable ? isDragging ? "grabbing" : "grab" : "default" },
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
348
|
+
/* @__PURE__ */ jsx2(BugBearIcon, { size: 28 }),
|
|
349
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
350
|
+
/* @__PURE__ */ jsxs("h3", { className: "font-semibold text-sm flex items-center gap-2", children: [
|
|
351
|
+
"BugBear",
|
|
352
|
+
draggable && /* @__PURE__ */ jsx2("span", { className: "text-purple-300 text-xs", title: "Drag to move, double-click to reset", children: "\u22EE\u22EE" })
|
|
353
|
+
] }),
|
|
354
|
+
/* @__PURE__ */ jsx2("p", { className: "text-purple-200 text-xs", children: testerInfo?.name })
|
|
355
|
+
] })
|
|
356
|
+
] }),
|
|
357
|
+
/* @__PURE__ */ jsx2(
|
|
358
|
+
"button",
|
|
359
|
+
{
|
|
360
|
+
onClick: () => setCollapsed(true),
|
|
361
|
+
className: "p-1 hover:bg-purple-500 rounded",
|
|
362
|
+
children: /* @__PURE__ */ jsx2("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
|
|
363
|
+
}
|
|
364
|
+
)
|
|
365
|
+
]
|
|
366
|
+
}
|
|
367
|
+
),
|
|
368
|
+
/* @__PURE__ */ jsxs("div", { className: "flex border-b border-gray-200", children: [
|
|
369
|
+
/* @__PURE__ */ jsxs(
|
|
370
|
+
"button",
|
|
371
|
+
{
|
|
372
|
+
onClick: () => setActiveTab("tests"),
|
|
373
|
+
className: `flex-1 px-4 py-2 text-sm font-medium transition-colors ${activeTab === "tests" ? "text-purple-600 border-b-2 border-purple-600" : "text-gray-500 hover:text-gray-700"}`,
|
|
374
|
+
children: [
|
|
375
|
+
"Tests ",
|
|
376
|
+
pendingCount > 0 && `(${pendingCount})`
|
|
377
|
+
]
|
|
378
|
+
}
|
|
379
|
+
),
|
|
380
|
+
/* @__PURE__ */ jsx2(
|
|
381
|
+
"button",
|
|
382
|
+
{
|
|
383
|
+
onClick: () => setActiveTab("report"),
|
|
384
|
+
className: `flex-1 px-4 py-2 text-sm font-medium transition-colors ${activeTab === "report" ? "text-purple-600 border-b-2 border-purple-600" : "text-gray-500 hover:text-gray-700"}`,
|
|
385
|
+
children: "Report"
|
|
386
|
+
}
|
|
387
|
+
)
|
|
388
|
+
] }),
|
|
389
|
+
/* @__PURE__ */ jsxs("div", { className: "p-4 max-h-96 overflow-y-auto", children: [
|
|
390
|
+
activeTab === "tests" && /* @__PURE__ */ jsx2("div", { children: assignments.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
391
|
+
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u2705" }),
|
|
392
|
+
/* @__PURE__ */ jsx2("p", { className: "text-gray-600 mt-2 font-medium", children: "All caught up!" }),
|
|
393
|
+
/* @__PURE__ */ jsx2("p", { className: "text-gray-400 text-sm", children: "No tests assigned" })
|
|
394
|
+
] }) : testView === "list" ? (
|
|
395
|
+
/* List View - Show all tests */
|
|
396
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
397
|
+
/* @__PURE__ */ jsx2("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-gray-500", children: [
|
|
398
|
+
assignments.length,
|
|
399
|
+
" test",
|
|
400
|
+
assignments.length !== 1 ? "s" : "",
|
|
401
|
+
" assigned"
|
|
402
|
+
] }) }),
|
|
403
|
+
assignments.map((assignment) => /* @__PURE__ */ jsxs(
|
|
404
|
+
"button",
|
|
405
|
+
{
|
|
406
|
+
onClick: () => {
|
|
407
|
+
setSelectedTestId(assignment.id);
|
|
408
|
+
setTestView("detail");
|
|
409
|
+
setShowSteps(false);
|
|
410
|
+
},
|
|
411
|
+
className: `w-full text-left p-3 rounded-lg border transition-colors ${assignment.id === currentAssignment?.id ? "bg-purple-50 border-purple-200" : "bg-gray-50 border-gray-200 hover:bg-gray-100"}`,
|
|
412
|
+
children: [
|
|
413
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-1", children: [
|
|
414
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-mono text-gray-500", children: assignment.testCase.testKey }),
|
|
415
|
+
/* @__PURE__ */ jsx2("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${assignment.testCase.priority === "P0" ? "bg-red-100 text-red-700" : assignment.testCase.priority === "P1" ? "bg-orange-100 text-orange-700" : "bg-gray-100 text-gray-600"}`, children: assignment.testCase.priority })
|
|
416
|
+
] }),
|
|
417
|
+
/* @__PURE__ */ jsx2("h4", { className: "font-medium text-gray-900 text-sm line-clamp-2", children: assignment.testCase.title }),
|
|
418
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1 text-xs text-gray-400", children: [
|
|
419
|
+
assignment.testCase.track && /* @__PURE__ */ jsx2(
|
|
420
|
+
"span",
|
|
421
|
+
{
|
|
422
|
+
className: "px-1 py-0.5 rounded text-white",
|
|
423
|
+
style: { backgroundColor: assignment.testCase.track.color },
|
|
424
|
+
children: templateInfo[assignment.testCase.track.testTemplate || "steps"].icon
|
|
425
|
+
}
|
|
426
|
+
),
|
|
427
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
428
|
+
assignment.testCase.steps.length,
|
|
429
|
+
" ",
|
|
430
|
+
assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"
|
|
431
|
+
] }),
|
|
432
|
+
assignment.id === currentAssignment?.id && /* @__PURE__ */ jsx2("span", { className: "text-purple-600 font-medium", children: "\u2022 Current" })
|
|
433
|
+
] })
|
|
434
|
+
]
|
|
435
|
+
},
|
|
436
|
+
assignment.id
|
|
437
|
+
))
|
|
438
|
+
] })
|
|
439
|
+
) : justPassed ? (
|
|
440
|
+
/* Success state after passing */
|
|
441
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
442
|
+
/* @__PURE__ */ jsx2("span", { className: "text-5xl", children: "\u2713" }),
|
|
443
|
+
/* @__PURE__ */ jsx2("p", { className: "text-green-600 mt-3 font-semibold text-lg", children: "Passed!" }),
|
|
444
|
+
/* @__PURE__ */ jsx2("p", { className: "text-gray-400 text-sm mt-1", children: "Loading next test..." })
|
|
445
|
+
] })
|
|
446
|
+
) : displayedAssignment ? (
|
|
447
|
+
/* Detail View - Show single test */
|
|
448
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
449
|
+
/* @__PURE__ */ jsxs(
|
|
450
|
+
"button",
|
|
451
|
+
{
|
|
452
|
+
onClick: () => {
|
|
453
|
+
setTestView("list");
|
|
454
|
+
setSelectedTestId(null);
|
|
455
|
+
},
|
|
456
|
+
className: "flex items-center gap-1 text-xs text-purple-600 font-medium hover:text-purple-700 mb-3",
|
|
457
|
+
children: [
|
|
458
|
+
"\u2190 All Tests (",
|
|
459
|
+
assignments.length,
|
|
460
|
+
")"
|
|
461
|
+
]
|
|
462
|
+
}
|
|
463
|
+
),
|
|
464
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
|
|
465
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
|
|
466
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-mono text-gray-500", children: displayedAssignment.testCase.testKey }),
|
|
467
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
468
|
+
displayedAssignment.testCase.track && /* @__PURE__ */ jsx2(
|
|
469
|
+
"span",
|
|
470
|
+
{
|
|
471
|
+
className: "text-xs px-1.5 py-0.5 rounded text-white",
|
|
472
|
+
style: { backgroundColor: displayedAssignment.testCase.track.color },
|
|
473
|
+
children: templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon
|
|
474
|
+
}
|
|
475
|
+
),
|
|
476
|
+
/* @__PURE__ */ jsx2("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${displayedAssignment.testCase.priority === "P0" ? "bg-red-100 text-red-700" : displayedAssignment.testCase.priority === "P1" ? "bg-orange-100 text-orange-700" : "bg-gray-100 text-gray-600"}`, children: displayedAssignment.testCase.priority })
|
|
477
|
+
] })
|
|
478
|
+
] }),
|
|
479
|
+
/* @__PURE__ */ jsx2("h4", { className: "font-medium text-gray-900 text-sm mb-1", children: displayedAssignment.testCase.title }),
|
|
480
|
+
displayedAssignment.testCase.description && /* @__PURE__ */ jsx2("p", { className: "text-gray-500 text-xs mb-2", children: displayedAssignment.testCase.description }),
|
|
481
|
+
displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ jsxs(
|
|
482
|
+
"button",
|
|
483
|
+
{
|
|
484
|
+
onClick: () => onNavigate(displayedAssignment.testCase.targetRoute),
|
|
485
|
+
className: "w-full mb-2 py-1.5 px-3 bg-blue-50 text-blue-700 border border-blue-200 rounded-lg text-xs font-medium hover:bg-blue-100 transition-colors flex items-center justify-center gap-1",
|
|
486
|
+
children: [
|
|
487
|
+
/* @__PURE__ */ jsx2("span", { children: "Go to test location" }),
|
|
488
|
+
/* @__PURE__ */ jsx2("span", { children: "\u2192" })
|
|
489
|
+
]
|
|
490
|
+
}
|
|
491
|
+
),
|
|
492
|
+
(() => {
|
|
493
|
+
const template = displayedAssignment.testCase.track?.testTemplate || "steps";
|
|
494
|
+
const steps = displayedAssignment.testCase.steps;
|
|
495
|
+
const info = templateInfo[template];
|
|
496
|
+
const rubricMode = displayedAssignment.testCase.track?.rubricMode || "pass_fail";
|
|
497
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
498
|
+
/* @__PURE__ */ jsxs(
|
|
499
|
+
"div",
|
|
500
|
+
{
|
|
501
|
+
className: "flex items-center gap-2 text-xs px-2 py-1 rounded mb-2",
|
|
502
|
+
style: {
|
|
503
|
+
backgroundColor: displayedAssignment.testCase.track ? `${displayedAssignment.testCase.track.color}15` : "#f3f4f6"
|
|
504
|
+
},
|
|
505
|
+
children: [
|
|
506
|
+
/* @__PURE__ */ jsx2("span", { children: info.icon }),
|
|
507
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: info.name }),
|
|
508
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-500", children: [
|
|
509
|
+
"\u2022 ",
|
|
510
|
+
info.action
|
|
511
|
+
] })
|
|
512
|
+
]
|
|
513
|
+
}
|
|
514
|
+
),
|
|
515
|
+
/* @__PURE__ */ jsxs(
|
|
516
|
+
"button",
|
|
517
|
+
{
|
|
518
|
+
onClick: () => setShowSteps(!showSteps),
|
|
519
|
+
className: "text-purple-600 text-xs font-medium hover:text-purple-700 flex items-center gap-1",
|
|
520
|
+
children: [
|
|
521
|
+
showSteps ? "\u25BC" : "\u25B6",
|
|
522
|
+
" ",
|
|
523
|
+
template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`
|
|
524
|
+
]
|
|
525
|
+
}
|
|
526
|
+
),
|
|
527
|
+
showSteps && template === "steps" && /* @__PURE__ */ jsx2("div", { className: "mt-2 space-y-2", children: steps.map((step, idx) => /* @__PURE__ */ jsxs("div", { className: "flex gap-2 text-xs", children: [
|
|
528
|
+
/* @__PURE__ */ jsx2("span", { className: "w-5 h-5 rounded-full bg-purple-100 text-purple-700 flex items-center justify-center flex-shrink-0 font-medium", children: step.stepNumber }),
|
|
529
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
530
|
+
/* @__PURE__ */ jsx2("p", { className: "text-gray-700", children: step.action }),
|
|
531
|
+
step.expectedResult && /* @__PURE__ */ jsxs("p", { className: "text-gray-400 mt-0.5", children: [
|
|
532
|
+
"\u2192 ",
|
|
533
|
+
step.expectedResult
|
|
534
|
+
] })
|
|
535
|
+
] })
|
|
536
|
+
] }, idx)) }),
|
|
537
|
+
showSteps && template === "checklist" && /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-2", children: [
|
|
538
|
+
steps.map((step, idx) => /* @__PURE__ */ jsxs(
|
|
539
|
+
"button",
|
|
540
|
+
{
|
|
541
|
+
onClick: () => setCriteriaResults((prev) => {
|
|
542
|
+
const newResults = { ...prev };
|
|
543
|
+
if (prev[idx] === true) {
|
|
544
|
+
delete newResults[idx];
|
|
545
|
+
} else {
|
|
546
|
+
newResults[idx] = true;
|
|
547
|
+
}
|
|
548
|
+
return newResults;
|
|
549
|
+
}),
|
|
550
|
+
className: `w-full flex items-center gap-2 text-xs p-2 rounded border transition-colors text-left ${criteriaResults[idx] === true ? "bg-green-50 border-green-300" : "bg-white border-gray-200 hover:bg-gray-50"}`,
|
|
551
|
+
children: [
|
|
552
|
+
/* @__PURE__ */ jsx2("span", { className: `w-5 h-5 rounded border-2 flex items-center justify-center ${criteriaResults[idx] === true ? "bg-green-500 border-green-500 text-white" : "border-cyan-400 text-cyan-600"}`, children: criteriaResults[idx] === true ? "\u2713" : "" }),
|
|
553
|
+
/* @__PURE__ */ jsx2("p", { className: `flex-1 ${criteriaResults[idx] === true ? "text-green-700" : "text-gray-700"}`, children: step.action })
|
|
554
|
+
]
|
|
555
|
+
},
|
|
556
|
+
idx
|
|
557
|
+
)),
|
|
558
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-2", children: [
|
|
559
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-400", children: "Tap to check off each item." }),
|
|
560
|
+
Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ jsx2(
|
|
561
|
+
"button",
|
|
562
|
+
{
|
|
563
|
+
onClick: () => setCriteriaResults({}),
|
|
564
|
+
className: "text-xs text-gray-400 hover:text-red-500 transition-colors",
|
|
565
|
+
children: "\u21BA Reset"
|
|
566
|
+
}
|
|
567
|
+
)
|
|
568
|
+
] })
|
|
569
|
+
] }),
|
|
570
|
+
showSteps && template === "rubric" && /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-2", children: [
|
|
571
|
+
steps.map((step, idx) => /* @__PURE__ */ jsxs("div", { className: "bg-white p-2 rounded border border-gray-200", children: [
|
|
572
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs mb-1", children: [
|
|
573
|
+
/* @__PURE__ */ jsx2("span", { className: "w-5 h-5 rounded bg-purple-100 text-purple-700 flex items-center justify-center font-medium", children: idx + 1 }),
|
|
574
|
+
/* @__PURE__ */ jsx2("p", { className: "text-gray-900 font-medium flex-1", children: step.action })
|
|
575
|
+
] }),
|
|
576
|
+
step.expectedResult && /* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-500 ml-7 mb-2", children: step.expectedResult }),
|
|
577
|
+
rubricMode === "pass_fail" && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 ml-7", children: [
|
|
578
|
+
/* @__PURE__ */ jsx2(
|
|
579
|
+
"button",
|
|
580
|
+
{
|
|
581
|
+
onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: true })),
|
|
582
|
+
className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === true ? "bg-green-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-green-100"}`,
|
|
583
|
+
children: "\u2713 Pass"
|
|
584
|
+
}
|
|
585
|
+
),
|
|
586
|
+
/* @__PURE__ */ jsx2(
|
|
587
|
+
"button",
|
|
588
|
+
{
|
|
589
|
+
onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: false })),
|
|
590
|
+
className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === false ? "bg-red-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-red-100"}`,
|
|
591
|
+
children: "\u2717 Fail"
|
|
592
|
+
}
|
|
593
|
+
)
|
|
594
|
+
] }),
|
|
595
|
+
rubricMode === "rating" && /* @__PURE__ */ jsx2("div", { className: "flex gap-1 ml-7", children: [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsx2(
|
|
596
|
+
"button",
|
|
597
|
+
{
|
|
598
|
+
onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: n })),
|
|
599
|
+
className: `w-8 h-8 rounded font-medium text-sm transition-colors ${criteriaResults[idx] === n ? "bg-purple-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-purple-100"}`,
|
|
600
|
+
children: n
|
|
601
|
+
},
|
|
602
|
+
n
|
|
603
|
+
)) })
|
|
604
|
+
] }, idx)),
|
|
605
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-2", children: [
|
|
606
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-400", children: rubricMode === "rating" ? "Rate 1-5 for each criterion." : "Mark each criterion as Pass or Fail." }),
|
|
607
|
+
Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ jsx2(
|
|
608
|
+
"button",
|
|
609
|
+
{
|
|
610
|
+
onClick: () => setCriteriaResults({}),
|
|
611
|
+
className: "text-xs text-gray-400 hover:text-red-500 transition-colors",
|
|
612
|
+
children: "\u21BA Reset"
|
|
613
|
+
}
|
|
614
|
+
)
|
|
615
|
+
] })
|
|
616
|
+
] }),
|
|
617
|
+
showSteps && template === "freeform" && /* @__PURE__ */ jsxs("div", { className: "mt-2 p-2 bg-amber-50 rounded border border-amber-200 text-xs", children: [
|
|
618
|
+
/* @__PURE__ */ jsx2("p", { className: "text-amber-800 font-medium mb-1", children: "\u{1F4AD} Open Observation" }),
|
|
619
|
+
/* @__PURE__ */ jsx2("p", { className: "text-amber-700", children: "Review the area described above and note:" }),
|
|
620
|
+
/* @__PURE__ */ jsxs("ul", { className: "text-amber-700 mt-1 ml-4 list-disc", children: [
|
|
621
|
+
/* @__PURE__ */ jsx2("li", { children: "What works well" }),
|
|
622
|
+
/* @__PURE__ */ jsx2("li", { children: "Issues or concerns" }),
|
|
623
|
+
/* @__PURE__ */ jsx2("li", { children: "Suggestions" })
|
|
624
|
+
] })
|
|
625
|
+
] })
|
|
626
|
+
] });
|
|
627
|
+
})(),
|
|
628
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3 p-2 bg-green-50 rounded text-xs text-green-700", children: [
|
|
629
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:" }),
|
|
630
|
+
" ",
|
|
631
|
+
displayedAssignment.testCase.expectedResult
|
|
632
|
+
] })
|
|
633
|
+
] }),
|
|
634
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
635
|
+
/* @__PURE__ */ jsx2(
|
|
636
|
+
"button",
|
|
637
|
+
{
|
|
638
|
+
onClick: handleFail,
|
|
639
|
+
disabled: submitting,
|
|
640
|
+
className: "flex-1 py-2 px-3 bg-red-100 text-red-700 rounded-lg font-medium text-sm hover:bg-red-200 disabled:opacity-50 transition-colors",
|
|
641
|
+
children: "\u2717 Fail"
|
|
642
|
+
}
|
|
643
|
+
),
|
|
644
|
+
/* @__PURE__ */ jsx2(
|
|
645
|
+
"button",
|
|
646
|
+
{
|
|
647
|
+
onClick: handlePass,
|
|
648
|
+
disabled: submitting,
|
|
649
|
+
className: "flex-1 py-2 px-3 bg-green-600 text-white rounded-lg font-medium text-sm hover:bg-green-700 disabled:opacity-50 transition-colors",
|
|
650
|
+
children: submitting ? "..." : "\u2713 Pass"
|
|
651
|
+
}
|
|
652
|
+
)
|
|
653
|
+
] })
|
|
654
|
+
] })
|
|
655
|
+
) : null }),
|
|
656
|
+
activeTab === "report" && /* @__PURE__ */ jsx2("div", { children: submitted ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
657
|
+
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u{1F389}" }),
|
|
658
|
+
/* @__PURE__ */ jsx2("p", { className: "text-gray-600 mt-2 font-medium", children: "Report submitted!" })
|
|
659
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
660
|
+
/* @__PURE__ */ jsx2("div", { className: "flex gap-2 mb-4", children: [
|
|
661
|
+
{ type: "bug", label: "\u{1F41B} Bug", color: "red" },
|
|
662
|
+
{ type: "feedback", label: "\u{1F4A1} Feedback", color: "blue" },
|
|
663
|
+
{ type: "suggestion", label: "\u2728 Idea", color: "purple" }
|
|
664
|
+
].map(({ type, label, color }) => /* @__PURE__ */ jsx2(
|
|
665
|
+
"button",
|
|
666
|
+
{
|
|
667
|
+
onClick: () => setReportType(type),
|
|
668
|
+
className: `flex-1 py-1.5 px-2 rounded-lg text-xs font-medium transition-colors ${reportType === type ? color === "red" ? "bg-red-100 text-red-700 ring-2 ring-red-500" : color === "blue" ? "bg-blue-100 text-blue-700 ring-2 ring-blue-500" : "bg-purple-100 text-purple-700 ring-2 ring-purple-500" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
|
|
669
|
+
children: label
|
|
670
|
+
},
|
|
671
|
+
type
|
|
672
|
+
)) }),
|
|
673
|
+
(reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
674
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Severity" }),
|
|
675
|
+
/* @__PURE__ */ jsx2("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ jsx2(
|
|
676
|
+
"button",
|
|
677
|
+
{
|
|
678
|
+
onClick: () => setSeverity(sev),
|
|
679
|
+
className: `flex-1 py-1 px-2 rounded text-xs font-medium capitalize transition-colors ${severity === sev ? sev === "critical" ? "bg-red-600 text-white" : sev === "high" ? "bg-orange-500 text-white" : sev === "medium" ? "bg-yellow-500 text-black" : "bg-gray-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
|
|
680
|
+
children: sev
|
|
681
|
+
},
|
|
682
|
+
sev
|
|
683
|
+
)) })
|
|
684
|
+
] }),
|
|
685
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
686
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "What happened?" }),
|
|
687
|
+
/* @__PURE__ */ jsx2(
|
|
688
|
+
"textarea",
|
|
689
|
+
{
|
|
690
|
+
value: description,
|
|
691
|
+
onChange: (e) => setDescription(e.target.value),
|
|
692
|
+
placeholder: "Describe the issue...",
|
|
693
|
+
rows: 3,
|
|
694
|
+
className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 resize-none"
|
|
695
|
+
}
|
|
696
|
+
)
|
|
697
|
+
] }),
|
|
698
|
+
/* @__PURE__ */ jsx2(
|
|
699
|
+
"button",
|
|
700
|
+
{
|
|
701
|
+
onClick: handleSubmitReport,
|
|
702
|
+
disabled: submitting || !description.trim(),
|
|
703
|
+
className: "w-full py-2 px-4 bg-purple-600 text-white rounded-lg font-medium text-sm hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
704
|
+
children: submitting ? "Submitting..." : "Submit Report"
|
|
705
|
+
}
|
|
706
|
+
)
|
|
707
|
+
] }) })
|
|
708
|
+
] }),
|
|
709
|
+
/* @__PURE__ */ jsxs("div", { className: "px-4 py-2 bg-gray-50 border-t border-gray-200 flex items-center justify-between text-xs text-gray-400", children: [
|
|
710
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
711
|
+
pendingCount,
|
|
712
|
+
" pending \xB7 ",
|
|
713
|
+
inProgressCount,
|
|
714
|
+
" in progress"
|
|
715
|
+
] }),
|
|
716
|
+
/* @__PURE__ */ jsx2(
|
|
717
|
+
"button",
|
|
718
|
+
{
|
|
719
|
+
onClick: refreshAssignments,
|
|
720
|
+
className: "hover:text-gray-600",
|
|
721
|
+
children: "\u21BB Refresh"
|
|
722
|
+
}
|
|
723
|
+
)
|
|
724
|
+
] })
|
|
725
|
+
] })
|
|
726
|
+
]
|
|
727
|
+
}
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// src/BugBearErrorBoundary.tsx
|
|
732
|
+
import { Component } from "react";
|
|
733
|
+
import { captureError, contextCapture } from "@bbearai/core";
|
|
734
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
735
|
+
var BUGBEAR_LOGO_BASE64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAJhlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAABIAAAAAQAAAEgAAAABAASQBAACAAAAFAAAAISgAQADAAAAAQABAACgAgAEAAAAAQAAAECgAwAEAAAAAQAAAEAAAAAAMjAyNjowMToyNCAxNjoyMTozOAAvO6cIAAAACXBIWXMAAAsTAAALEwEAmpwYAAACo2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpJcHRjNHhtcEV4dD0iaHR0cDovL2lwdGMub3JnL3N0ZC9JcHRjNHhtcEV4dC8yMDA4LTAyLTI5LyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPElwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPmh0dHA6Ly9jdi5pcHRjLm9yZy9uZXdzY29kZXMvZGlnaXRhbHNvdXJjZXR5cGUvdHJhaW5lZEFsZ29yaXRobWljTWVkaWE8L0lwdGM0eG1wRXh0OkRpZ2l0YWxTb3VyY2VUeXBlPgogICAgICAgICA8SXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPmZjNzJlN2Q2LTYyYTEtNDE1ZS04MjY5LWM2NjA4MjY0OWRiMDwvSXB0YzR4bXBFeHQ6RGlnSW1hZ2VHVUlEPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyNi0wMS0yNFQxNjoyMTozODwveG1wOkNyZWF0ZURhdGU+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+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";
|
|
736
|
+
var BugBearErrorBoundary = class extends Component {
|
|
737
|
+
constructor(props) {
|
|
738
|
+
super(props);
|
|
739
|
+
this.reset = () => {
|
|
740
|
+
this.setState({
|
|
741
|
+
hasError: false,
|
|
742
|
+
error: null,
|
|
743
|
+
errorInfo: null
|
|
744
|
+
});
|
|
745
|
+
};
|
|
746
|
+
this.state = {
|
|
747
|
+
hasError: false,
|
|
748
|
+
error: null,
|
|
749
|
+
errorInfo: null
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
static getDerivedStateFromError(error) {
|
|
753
|
+
return { hasError: true, error };
|
|
754
|
+
}
|
|
755
|
+
componentDidCatch(error, errorInfo) {
|
|
756
|
+
this.setState({ errorInfo });
|
|
757
|
+
const capturedError = captureError(error, {
|
|
758
|
+
componentStack: errorInfo.componentStack ?? void 0
|
|
759
|
+
});
|
|
760
|
+
console.error("BugBear: Error caught by ErrorBoundary", {
|
|
761
|
+
error: capturedError.errorMessage,
|
|
762
|
+
componentStack: capturedError.componentStack?.slice(0, 500)
|
|
763
|
+
});
|
|
764
|
+
this.props.onError?.(error, errorInfo);
|
|
765
|
+
}
|
|
766
|
+
render() {
|
|
767
|
+
const { hasError, error } = this.state;
|
|
768
|
+
const { children, fallback } = this.props;
|
|
769
|
+
if (hasError && error) {
|
|
770
|
+
if (typeof fallback === "function") {
|
|
771
|
+
return fallback(error, this.reset);
|
|
772
|
+
}
|
|
773
|
+
if (fallback) {
|
|
774
|
+
return fallback;
|
|
775
|
+
}
|
|
776
|
+
return /* @__PURE__ */ jsxs2(
|
|
777
|
+
"div",
|
|
778
|
+
{
|
|
779
|
+
style: {
|
|
780
|
+
padding: "20px",
|
|
781
|
+
margin: "20px",
|
|
782
|
+
backgroundColor: "#fef2f2",
|
|
783
|
+
border: "1px solid #fecaca",
|
|
784
|
+
borderRadius: "8px",
|
|
785
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
|
786
|
+
},
|
|
787
|
+
children: [
|
|
788
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "12px" }, children: [
|
|
789
|
+
/* @__PURE__ */ jsx3("img", { src: BUGBEAR_LOGO_BASE64, alt: "BugBear", width: 28, height: 28, style: { objectFit: "contain" } }),
|
|
790
|
+
/* @__PURE__ */ jsx3("h3", { style: { margin: 0, color: "#991b1b", fontSize: "16px" }, children: "Something went wrong" })
|
|
791
|
+
] }),
|
|
792
|
+
/* @__PURE__ */ jsx3("p", { style: { color: "#7f1d1d", fontSize: "14px", margin: "0 0 12px 0" }, children: error.message }),
|
|
793
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
794
|
+
/* @__PURE__ */ jsx3(
|
|
795
|
+
"button",
|
|
796
|
+
{
|
|
797
|
+
onClick: this.reset,
|
|
798
|
+
style: {
|
|
799
|
+
padding: "8px 16px",
|
|
800
|
+
backgroundColor: "#dc2626",
|
|
801
|
+
color: "white",
|
|
802
|
+
border: "none",
|
|
803
|
+
borderRadius: "6px",
|
|
804
|
+
fontSize: "14px",
|
|
805
|
+
fontWeight: "500",
|
|
806
|
+
cursor: "pointer"
|
|
807
|
+
},
|
|
808
|
+
children: "Try Again"
|
|
809
|
+
}
|
|
810
|
+
),
|
|
811
|
+
/* @__PURE__ */ jsx3(
|
|
812
|
+
"button",
|
|
813
|
+
{
|
|
814
|
+
onClick: () => window.location.reload(),
|
|
815
|
+
style: {
|
|
816
|
+
padding: "8px 16px",
|
|
817
|
+
backgroundColor: "#f3f4f6",
|
|
818
|
+
color: "#374151",
|
|
819
|
+
border: "1px solid #d1d5db",
|
|
820
|
+
borderRadius: "6px",
|
|
821
|
+
fontSize: "14px",
|
|
822
|
+
fontWeight: "500",
|
|
823
|
+
cursor: "pointer"
|
|
824
|
+
},
|
|
825
|
+
children: "Reload Page"
|
|
826
|
+
}
|
|
827
|
+
)
|
|
828
|
+
] }),
|
|
829
|
+
/* @__PURE__ */ jsx3("p", { style: { color: "#9ca3af", fontSize: "12px", marginTop: "12px" }, children: "The error has been captured by BugBear" })
|
|
830
|
+
]
|
|
831
|
+
}
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
return children;
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
function useErrorContext() {
|
|
838
|
+
return {
|
|
839
|
+
captureError,
|
|
840
|
+
getEnhancedContext: () => contextCapture.getEnhancedContext()
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/index.tsx
|
|
845
|
+
import { contextCapture as contextCapture2, captureError as captureError2 } from "@bbearai/core";
|
|
846
|
+
export {
|
|
847
|
+
BugBearErrorBoundary,
|
|
848
|
+
BugBearPanel,
|
|
849
|
+
BugBearProvider,
|
|
850
|
+
captureError2 as captureError,
|
|
851
|
+
contextCapture2 as contextCapture,
|
|
852
|
+
useBugBear,
|
|
853
|
+
useErrorContext
|
|
854
|
+
};
|