@bbearai/react 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +224 -2
- package/dist/index.mjs +224 -2
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, Component, ErrorInfo } from 'react';
|
|
3
3
|
import * as _bbearai_core from '@bbearai/core';
|
|
4
|
-
import { BugBearConfig, BugBearClient, TesterInfo, TestAssignment, AppContext, captureError } from '@bbearai/core';
|
|
4
|
+
import { BugBearConfig, BugBearClient, TesterInfo, TestAssignment, TesterProfileUpdate, AppContext, captureError } from '@bbearai/core';
|
|
5
5
|
export { AppContext, BugBearConfig, BugBearReport, ConsoleLogEntry, DeviceInfo, EnhancedBugContext, NetworkRequest, QATrack, ReportType, Severity, TestAssignment, TestTemplate, TesterInfo, captureError, contextCapture } from '@bbearai/core';
|
|
6
6
|
|
|
7
7
|
interface BugBearContextValue {
|
|
@@ -18,6 +18,13 @@ interface BugBearContextValue {
|
|
|
18
18
|
onNavigate?: (route: string) => void;
|
|
19
19
|
/** Re-check tester status (call after auth state changes) */
|
|
20
20
|
refreshTesterStatus: () => Promise<void>;
|
|
21
|
+
/** Update tester profile */
|
|
22
|
+
updateTesterProfile: (updates: TesterProfileUpdate) => Promise<{
|
|
23
|
+
success: boolean;
|
|
24
|
+
error?: string;
|
|
25
|
+
}>;
|
|
26
|
+
/** Refresh tester info from server */
|
|
27
|
+
refreshTesterInfo: () => Promise<void>;
|
|
21
28
|
}
|
|
22
29
|
declare function useBugBear(): BugBearContextValue;
|
|
23
30
|
interface BugBearProviderProps {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, Component, ErrorInfo } from 'react';
|
|
3
3
|
import * as _bbearai_core from '@bbearai/core';
|
|
4
|
-
import { BugBearConfig, BugBearClient, TesterInfo, TestAssignment, AppContext, captureError } from '@bbearai/core';
|
|
4
|
+
import { BugBearConfig, BugBearClient, TesterInfo, TestAssignment, TesterProfileUpdate, AppContext, captureError } from '@bbearai/core';
|
|
5
5
|
export { AppContext, BugBearConfig, BugBearReport, ConsoleLogEntry, DeviceInfo, EnhancedBugContext, NetworkRequest, QATrack, ReportType, Severity, TestAssignment, TestTemplate, TesterInfo, captureError, contextCapture } from '@bbearai/core';
|
|
6
6
|
|
|
7
7
|
interface BugBearContextValue {
|
|
@@ -18,6 +18,13 @@ interface BugBearContextValue {
|
|
|
18
18
|
onNavigate?: (route: string) => void;
|
|
19
19
|
/** Re-check tester status (call after auth state changes) */
|
|
20
20
|
refreshTesterStatus: () => Promise<void>;
|
|
21
|
+
/** Update tester profile */
|
|
22
|
+
updateTesterProfile: (updates: TesterProfileUpdate) => Promise<{
|
|
23
|
+
success: boolean;
|
|
24
|
+
error?: string;
|
|
25
|
+
}>;
|
|
26
|
+
/** Refresh tester info from server */
|
|
27
|
+
refreshTesterInfo: () => Promise<void>;
|
|
21
28
|
}
|
|
22
29
|
declare function useBugBear(): BugBearContextValue;
|
|
23
30
|
interface BugBearProviderProps {
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,9 @@ var BugBearContext = (0, import_react.createContext)({
|
|
|
47
47
|
isLoading: true,
|
|
48
48
|
onNavigate: void 0,
|
|
49
49
|
refreshTesterStatus: async () => {
|
|
50
|
+
},
|
|
51
|
+
updateTesterProfile: async () => ({ success: false }),
|
|
52
|
+
refreshTesterInfo: async () => {
|
|
50
53
|
}
|
|
51
54
|
});
|
|
52
55
|
function useBugBear() {
|
|
@@ -91,6 +94,20 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
91
94
|
setClient(freshClient);
|
|
92
95
|
await initializeBugBear(freshClient);
|
|
93
96
|
}, [config, initializeBugBear]);
|
|
97
|
+
const updateTesterProfile = (0, import_react.useCallback)(async (updates) => {
|
|
98
|
+
if (!client) return { success: false, error: "Client not initialized" };
|
|
99
|
+
const result = await client.updateTesterProfile(updates);
|
|
100
|
+
if (result.success) {
|
|
101
|
+
const info = await client.getTesterInfo();
|
|
102
|
+
setTesterInfo(info);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}, [client]);
|
|
106
|
+
const refreshTesterInfo = (0, import_react.useCallback)(async () => {
|
|
107
|
+
if (!client) return;
|
|
108
|
+
const info = await client.getTesterInfo();
|
|
109
|
+
setTesterInfo(info);
|
|
110
|
+
}, [client]);
|
|
94
111
|
(0, import_react.useEffect)(() => {
|
|
95
112
|
if (enabled && !hasInitialized.current) {
|
|
96
113
|
hasInitialized.current = true;
|
|
@@ -117,7 +134,9 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
117
134
|
refreshAssignments,
|
|
118
135
|
isLoading,
|
|
119
136
|
onNavigate: config.onNavigate,
|
|
120
|
-
refreshTesterStatus
|
|
137
|
+
refreshTesterStatus,
|
|
138
|
+
updateTesterProfile,
|
|
139
|
+
refreshTesterInfo
|
|
121
140
|
},
|
|
122
141
|
children
|
|
123
142
|
}
|
|
@@ -196,7 +215,7 @@ function BugBearPanel({
|
|
|
196
215
|
defaultCollapsed = false,
|
|
197
216
|
draggable = true
|
|
198
217
|
}) {
|
|
199
|
-
const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate } = useBugBear();
|
|
218
|
+
const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate, updateTesterProfile, refreshTesterInfo } = useBugBear();
|
|
200
219
|
const [collapsed, setCollapsed] = (0, import_react2.useState)(defaultCollapsed);
|
|
201
220
|
const [activeTab, setActiveTab] = (0, import_react2.useState)("tests");
|
|
202
221
|
const [showSteps, setShowSteps] = (0, import_react2.useState)(false);
|
|
@@ -214,6 +233,13 @@ function BugBearPanel({
|
|
|
214
233
|
const [submitted, setSubmitted] = (0, import_react2.useState)(false);
|
|
215
234
|
const [justPassed, setJustPassed] = (0, import_react2.useState)(false);
|
|
216
235
|
const [criteriaResults, setCriteriaResults] = (0, import_react2.useState)({});
|
|
236
|
+
const [profileEditing, setProfileEditing] = (0, import_react2.useState)(false);
|
|
237
|
+
const [profileName, setProfileName] = (0, import_react2.useState)("");
|
|
238
|
+
const [profileAdditionalEmails, setProfileAdditionalEmails] = (0, import_react2.useState)([]);
|
|
239
|
+
const [newEmailInput, setNewEmailInput] = (0, import_react2.useState)("");
|
|
240
|
+
const [profilePlatforms, setProfilePlatforms] = (0, import_react2.useState)([]);
|
|
241
|
+
const [savingProfile, setSavingProfile] = (0, import_react2.useState)(false);
|
|
242
|
+
const [profileSaved, setProfileSaved] = (0, import_react2.useState)(false);
|
|
217
243
|
(0, import_react2.useEffect)(() => {
|
|
218
244
|
if (typeof window === "undefined") return;
|
|
219
245
|
try {
|
|
@@ -350,6 +376,50 @@ function BugBearPanel({
|
|
|
350
376
|
};
|
|
351
377
|
const pendingCount = assignments.filter((a) => a.status === "pending").length;
|
|
352
378
|
const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
|
|
379
|
+
const handleStartEditProfile = () => {
|
|
380
|
+
if (testerInfo) {
|
|
381
|
+
setProfileName(testerInfo.name);
|
|
382
|
+
setProfileAdditionalEmails(testerInfo.additionalEmails || []);
|
|
383
|
+
setProfilePlatforms(testerInfo.platforms || []);
|
|
384
|
+
}
|
|
385
|
+
setProfileEditing(true);
|
|
386
|
+
};
|
|
387
|
+
const handleCancelEditProfile = () => {
|
|
388
|
+
setProfileEditing(false);
|
|
389
|
+
setNewEmailInput("");
|
|
390
|
+
};
|
|
391
|
+
const handleAddEmail = () => {
|
|
392
|
+
const email = newEmailInput.trim().toLowerCase();
|
|
393
|
+
if (email && email.includes("@") && !profileAdditionalEmails.includes(email)) {
|
|
394
|
+
setProfileAdditionalEmails([...profileAdditionalEmails, email]);
|
|
395
|
+
setNewEmailInput("");
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
const handleRemoveEmail = (email) => {
|
|
399
|
+
setProfileAdditionalEmails(profileAdditionalEmails.filter((e) => e !== email));
|
|
400
|
+
};
|
|
401
|
+
const handleTogglePlatform = (platform) => {
|
|
402
|
+
if (profilePlatforms.includes(platform)) {
|
|
403
|
+
setProfilePlatforms(profilePlatforms.filter((p) => p !== platform));
|
|
404
|
+
} else {
|
|
405
|
+
setProfilePlatforms([...profilePlatforms, platform]);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
const handleSaveProfile = async () => {
|
|
409
|
+
setSavingProfile(true);
|
|
410
|
+
const updates = {
|
|
411
|
+
name: profileName.trim(),
|
|
412
|
+
additionalEmails: profileAdditionalEmails,
|
|
413
|
+
platforms: profilePlatforms
|
|
414
|
+
};
|
|
415
|
+
const result = await updateTesterProfile(updates);
|
|
416
|
+
if (result.success) {
|
|
417
|
+
setProfileEditing(false);
|
|
418
|
+
setProfileSaved(true);
|
|
419
|
+
setTimeout(() => setProfileSaved(false), 2e3);
|
|
420
|
+
}
|
|
421
|
+
setSavingProfile(false);
|
|
422
|
+
};
|
|
353
423
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
354
424
|
"div",
|
|
355
425
|
{
|
|
@@ -423,6 +493,14 @@ function BugBearPanel({
|
|
|
423
493
|
]
|
|
424
494
|
}
|
|
425
495
|
),
|
|
496
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
497
|
+
"button",
|
|
498
|
+
{
|
|
499
|
+
onClick: () => setActiveTab("profile"),
|
|
500
|
+
className: `flex-1 px-4 py-2 text-sm font-medium transition-colors ${activeTab === "profile" ? "text-purple-600 border-b-2 border-purple-600" : "text-gray-500 hover:text-gray-700"}`,
|
|
501
|
+
children: "Profile"
|
|
502
|
+
}
|
|
503
|
+
),
|
|
426
504
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
427
505
|
"button",
|
|
428
506
|
{
|
|
@@ -699,6 +777,150 @@ function BugBearPanel({
|
|
|
699
777
|
] })
|
|
700
778
|
] })
|
|
701
779
|
) : null }),
|
|
780
|
+
activeTab === "profile" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: profileSaved ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u2705" }),
|
|
782
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-600 mt-2 font-medium", children: "Profile saved!" })
|
|
783
|
+
] }) : profileEditing ? (
|
|
784
|
+
/* Edit Profile Form */
|
|
785
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
786
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
|
|
787
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-gray-900", children: "Edit Profile" }),
|
|
788
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
789
|
+
"button",
|
|
790
|
+
{
|
|
791
|
+
onClick: handleCancelEditProfile,
|
|
792
|
+
className: "text-sm text-gray-500 hover:text-gray-700",
|
|
793
|
+
children: "Cancel"
|
|
794
|
+
}
|
|
795
|
+
)
|
|
796
|
+
] }),
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
|
|
798
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Name" }),
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
800
|
+
"input",
|
|
801
|
+
{
|
|
802
|
+
type: "text",
|
|
803
|
+
value: profileName,
|
|
804
|
+
onChange: (e) => setProfileName(e.target.value),
|
|
805
|
+
placeholder: "Your name",
|
|
806
|
+
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"
|
|
807
|
+
}
|
|
808
|
+
)
|
|
809
|
+
] }),
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Primary Email" }),
|
|
812
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-3 py-2 bg-gray-100 rounded-lg", children: [
|
|
813
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-gray-700", children: testerInfo?.email }),
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-400 mt-0.5", children: "Main communication email" })
|
|
815
|
+
] })
|
|
816
|
+
] }),
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Additional Testing Emails" }),
|
|
819
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500 mb-2", children: "Add other emails you use to test on different accounts" }),
|
|
820
|
+
profileAdditionalEmails.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "flex-1 px-3 py-1.5 bg-purple-50 text-purple-700 text-sm rounded-full", children: email }),
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
823
|
+
"button",
|
|
824
|
+
{
|
|
825
|
+
onClick: () => handleRemoveEmail(email),
|
|
826
|
+
className: "text-purple-400 hover:text-red-500 text-sm",
|
|
827
|
+
children: "\u2715"
|
|
828
|
+
}
|
|
829
|
+
)
|
|
830
|
+
] }, email)),
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
833
|
+
"input",
|
|
834
|
+
{
|
|
835
|
+
type: "email",
|
|
836
|
+
value: newEmailInput,
|
|
837
|
+
onChange: (e) => setNewEmailInput(e.target.value),
|
|
838
|
+
placeholder: "email@example.com",
|
|
839
|
+
className: "flex-1 px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500",
|
|
840
|
+
onKeyDown: (e) => e.key === "Enter" && handleAddEmail()
|
|
841
|
+
}
|
|
842
|
+
),
|
|
843
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
844
|
+
"button",
|
|
845
|
+
{
|
|
846
|
+
onClick: handleAddEmail,
|
|
847
|
+
disabled: !newEmailInput.trim(),
|
|
848
|
+
className: "px-3 py-2 bg-purple-600 text-white text-sm rounded-lg hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
849
|
+
children: "Add"
|
|
850
|
+
}
|
|
851
|
+
)
|
|
852
|
+
] })
|
|
853
|
+
] }),
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Testing Platforms" }),
|
|
856
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500 mb-2", children: "Select the platforms you can test on" }),
|
|
857
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2", children: [
|
|
858
|
+
{ key: "ios", label: "\u{1F4F1} iOS" },
|
|
859
|
+
{ key: "android", label: "\u{1F916} Android" },
|
|
860
|
+
{ key: "web", label: "\u{1F310} Web" }
|
|
861
|
+
].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
862
|
+
"button",
|
|
863
|
+
{
|
|
864
|
+
onClick: () => handleTogglePlatform(key),
|
|
865
|
+
className: `flex-1 py-2 px-3 rounded-lg text-sm font-medium transition-colors border-2 ${profilePlatforms.includes(key) ? "bg-purple-50 border-purple-500 text-purple-700" : "bg-gray-50 border-transparent text-gray-600 hover:bg-gray-100"}`,
|
|
866
|
+
children: label
|
|
867
|
+
},
|
|
868
|
+
key
|
|
869
|
+
)) })
|
|
870
|
+
] }),
|
|
871
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
872
|
+
"button",
|
|
873
|
+
{
|
|
874
|
+
onClick: handleSaveProfile,
|
|
875
|
+
disabled: savingProfile,
|
|
876
|
+
className: "w-full py-2 px-4 bg-green-600 text-white rounded-lg font-medium text-sm hover:bg-green-700 disabled:opacity-50 transition-colors",
|
|
877
|
+
children: savingProfile ? "Saving..." : "Save Profile"
|
|
878
|
+
}
|
|
879
|
+
)
|
|
880
|
+
] })
|
|
881
|
+
) : (
|
|
882
|
+
/* Profile View */
|
|
883
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-gray-50 rounded-lg p-4 text-center mb-4", children: [
|
|
885
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-16 h-16 mx-auto bg-purple-600 rounded-full flex items-center justify-center mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-2xl font-semibold text-white", children: testerInfo?.name?.charAt(0)?.toUpperCase() || "?" }) }),
|
|
886
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-gray-900", children: testerInfo?.name }),
|
|
887
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-gray-500", children: testerInfo?.email }),
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-center gap-6 mt-4 pt-4 border-t border-gray-200", children: [
|
|
889
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-purple-600", children: testerInfo?.assignedTests || 0 }),
|
|
891
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500", children: "Assigned" })
|
|
892
|
+
] }),
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
|
|
894
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-purple-600", children: testerInfo?.completedTests || 0 }),
|
|
895
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500", children: "Completed" })
|
|
896
|
+
] })
|
|
897
|
+
] })
|
|
898
|
+
] }),
|
|
899
|
+
(testerInfo?.additionalEmails?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
|
|
900
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide mb-2", children: "Additional Emails" }),
|
|
901
|
+
testerInfo?.additionalEmails?.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-gray-700", children: email }, email))
|
|
902
|
+
] }),
|
|
903
|
+
(testerInfo?.platforms?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide mb-2", children: "Testing Platforms" }),
|
|
905
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex flex-wrap gap-2", children: testerInfo?.platforms?.map((platform) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
906
|
+
"span",
|
|
907
|
+
{
|
|
908
|
+
className: "px-2 py-1 bg-purple-100 text-purple-700 text-xs rounded-full font-medium",
|
|
909
|
+
children: platform === "ios" ? "\u{1F4F1} iOS" : platform === "android" ? "\u{1F916} Android" : "\u{1F310} Web"
|
|
910
|
+
},
|
|
911
|
+
platform
|
|
912
|
+
)) })
|
|
913
|
+
] }),
|
|
914
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
915
|
+
"button",
|
|
916
|
+
{
|
|
917
|
+
onClick: handleStartEditProfile,
|
|
918
|
+
className: "w-full py-2 px-4 bg-purple-600 text-white rounded-lg font-medium text-sm hover:bg-purple-700 transition-colors",
|
|
919
|
+
children: "Edit Profile"
|
|
920
|
+
}
|
|
921
|
+
)
|
|
922
|
+
] })
|
|
923
|
+
) }),
|
|
702
924
|
activeTab === "report" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
|
|
703
925
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F389}" }),
|
|
704
926
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-600 mt-2 font-medium", children: "Report submitted!" })
|
package/dist/index.mjs
CHANGED
|
@@ -17,6 +17,9 @@ var BugBearContext = createContext({
|
|
|
17
17
|
isLoading: true,
|
|
18
18
|
onNavigate: void 0,
|
|
19
19
|
refreshTesterStatus: async () => {
|
|
20
|
+
},
|
|
21
|
+
updateTesterProfile: async () => ({ success: false }),
|
|
22
|
+
refreshTesterInfo: async () => {
|
|
20
23
|
}
|
|
21
24
|
});
|
|
22
25
|
function useBugBear() {
|
|
@@ -61,6 +64,20 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
61
64
|
setClient(freshClient);
|
|
62
65
|
await initializeBugBear(freshClient);
|
|
63
66
|
}, [config, initializeBugBear]);
|
|
67
|
+
const updateTesterProfile = useCallback(async (updates) => {
|
|
68
|
+
if (!client) return { success: false, error: "Client not initialized" };
|
|
69
|
+
const result = await client.updateTesterProfile(updates);
|
|
70
|
+
if (result.success) {
|
|
71
|
+
const info = await client.getTesterInfo();
|
|
72
|
+
setTesterInfo(info);
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}, [client]);
|
|
76
|
+
const refreshTesterInfo = useCallback(async () => {
|
|
77
|
+
if (!client) return;
|
|
78
|
+
const info = await client.getTesterInfo();
|
|
79
|
+
setTesterInfo(info);
|
|
80
|
+
}, [client]);
|
|
64
81
|
useEffect(() => {
|
|
65
82
|
if (enabled && !hasInitialized.current) {
|
|
66
83
|
hasInitialized.current = true;
|
|
@@ -87,7 +104,9 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
87
104
|
refreshAssignments,
|
|
88
105
|
isLoading,
|
|
89
106
|
onNavigate: config.onNavigate,
|
|
90
|
-
refreshTesterStatus
|
|
107
|
+
refreshTesterStatus,
|
|
108
|
+
updateTesterProfile,
|
|
109
|
+
refreshTesterInfo
|
|
91
110
|
},
|
|
92
111
|
children
|
|
93
112
|
}
|
|
@@ -166,7 +185,7 @@ function BugBearPanel({
|
|
|
166
185
|
defaultCollapsed = false,
|
|
167
186
|
draggable = true
|
|
168
187
|
}) {
|
|
169
|
-
const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate } = useBugBear();
|
|
188
|
+
const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate, updateTesterProfile, refreshTesterInfo } = useBugBear();
|
|
170
189
|
const [collapsed, setCollapsed] = useState2(defaultCollapsed);
|
|
171
190
|
const [activeTab, setActiveTab] = useState2("tests");
|
|
172
191
|
const [showSteps, setShowSteps] = useState2(false);
|
|
@@ -184,6 +203,13 @@ function BugBearPanel({
|
|
|
184
203
|
const [submitted, setSubmitted] = useState2(false);
|
|
185
204
|
const [justPassed, setJustPassed] = useState2(false);
|
|
186
205
|
const [criteriaResults, setCriteriaResults] = useState2({});
|
|
206
|
+
const [profileEditing, setProfileEditing] = useState2(false);
|
|
207
|
+
const [profileName, setProfileName] = useState2("");
|
|
208
|
+
const [profileAdditionalEmails, setProfileAdditionalEmails] = useState2([]);
|
|
209
|
+
const [newEmailInput, setNewEmailInput] = useState2("");
|
|
210
|
+
const [profilePlatforms, setProfilePlatforms] = useState2([]);
|
|
211
|
+
const [savingProfile, setSavingProfile] = useState2(false);
|
|
212
|
+
const [profileSaved, setProfileSaved] = useState2(false);
|
|
187
213
|
useEffect2(() => {
|
|
188
214
|
if (typeof window === "undefined") return;
|
|
189
215
|
try {
|
|
@@ -320,6 +346,50 @@ function BugBearPanel({
|
|
|
320
346
|
};
|
|
321
347
|
const pendingCount = assignments.filter((a) => a.status === "pending").length;
|
|
322
348
|
const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
|
|
349
|
+
const handleStartEditProfile = () => {
|
|
350
|
+
if (testerInfo) {
|
|
351
|
+
setProfileName(testerInfo.name);
|
|
352
|
+
setProfileAdditionalEmails(testerInfo.additionalEmails || []);
|
|
353
|
+
setProfilePlatforms(testerInfo.platforms || []);
|
|
354
|
+
}
|
|
355
|
+
setProfileEditing(true);
|
|
356
|
+
};
|
|
357
|
+
const handleCancelEditProfile = () => {
|
|
358
|
+
setProfileEditing(false);
|
|
359
|
+
setNewEmailInput("");
|
|
360
|
+
};
|
|
361
|
+
const handleAddEmail = () => {
|
|
362
|
+
const email = newEmailInput.trim().toLowerCase();
|
|
363
|
+
if (email && email.includes("@") && !profileAdditionalEmails.includes(email)) {
|
|
364
|
+
setProfileAdditionalEmails([...profileAdditionalEmails, email]);
|
|
365
|
+
setNewEmailInput("");
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
const handleRemoveEmail = (email) => {
|
|
369
|
+
setProfileAdditionalEmails(profileAdditionalEmails.filter((e) => e !== email));
|
|
370
|
+
};
|
|
371
|
+
const handleTogglePlatform = (platform) => {
|
|
372
|
+
if (profilePlatforms.includes(platform)) {
|
|
373
|
+
setProfilePlatforms(profilePlatforms.filter((p) => p !== platform));
|
|
374
|
+
} else {
|
|
375
|
+
setProfilePlatforms([...profilePlatforms, platform]);
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
const handleSaveProfile = async () => {
|
|
379
|
+
setSavingProfile(true);
|
|
380
|
+
const updates = {
|
|
381
|
+
name: profileName.trim(),
|
|
382
|
+
additionalEmails: profileAdditionalEmails,
|
|
383
|
+
platforms: profilePlatforms
|
|
384
|
+
};
|
|
385
|
+
const result = await updateTesterProfile(updates);
|
|
386
|
+
if (result.success) {
|
|
387
|
+
setProfileEditing(false);
|
|
388
|
+
setProfileSaved(true);
|
|
389
|
+
setTimeout(() => setProfileSaved(false), 2e3);
|
|
390
|
+
}
|
|
391
|
+
setSavingProfile(false);
|
|
392
|
+
};
|
|
323
393
|
return /* @__PURE__ */ jsxs(
|
|
324
394
|
"div",
|
|
325
395
|
{
|
|
@@ -393,6 +463,14 @@ function BugBearPanel({
|
|
|
393
463
|
]
|
|
394
464
|
}
|
|
395
465
|
),
|
|
466
|
+
/* @__PURE__ */ jsx2(
|
|
467
|
+
"button",
|
|
468
|
+
{
|
|
469
|
+
onClick: () => setActiveTab("profile"),
|
|
470
|
+
className: `flex-1 px-4 py-2 text-sm font-medium transition-colors ${activeTab === "profile" ? "text-purple-600 border-b-2 border-purple-600" : "text-gray-500 hover:text-gray-700"}`,
|
|
471
|
+
children: "Profile"
|
|
472
|
+
}
|
|
473
|
+
),
|
|
396
474
|
/* @__PURE__ */ jsx2(
|
|
397
475
|
"button",
|
|
398
476
|
{
|
|
@@ -669,6 +747,150 @@ function BugBearPanel({
|
|
|
669
747
|
] })
|
|
670
748
|
] })
|
|
671
749
|
) : null }),
|
|
750
|
+
activeTab === "profile" && /* @__PURE__ */ jsx2("div", { children: profileSaved ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
751
|
+
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u2705" }),
|
|
752
|
+
/* @__PURE__ */ jsx2("p", { className: "text-gray-600 mt-2 font-medium", children: "Profile saved!" })
|
|
753
|
+
] }) : profileEditing ? (
|
|
754
|
+
/* Edit Profile Form */
|
|
755
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
756
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
757
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-gray-900", children: "Edit Profile" }),
|
|
758
|
+
/* @__PURE__ */ jsx2(
|
|
759
|
+
"button",
|
|
760
|
+
{
|
|
761
|
+
onClick: handleCancelEditProfile,
|
|
762
|
+
className: "text-sm text-gray-500 hover:text-gray-700",
|
|
763
|
+
children: "Cancel"
|
|
764
|
+
}
|
|
765
|
+
)
|
|
766
|
+
] }),
|
|
767
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
768
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Name" }),
|
|
769
|
+
/* @__PURE__ */ jsx2(
|
|
770
|
+
"input",
|
|
771
|
+
{
|
|
772
|
+
type: "text",
|
|
773
|
+
value: profileName,
|
|
774
|
+
onChange: (e) => setProfileName(e.target.value),
|
|
775
|
+
placeholder: "Your name",
|
|
776
|
+
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"
|
|
777
|
+
}
|
|
778
|
+
)
|
|
779
|
+
] }),
|
|
780
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
781
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Primary Email" }),
|
|
782
|
+
/* @__PURE__ */ jsxs("div", { className: "px-3 py-2 bg-gray-100 rounded-lg", children: [
|
|
783
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm text-gray-700", children: testerInfo?.email }),
|
|
784
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-400 mt-0.5", children: "Main communication email" })
|
|
785
|
+
] })
|
|
786
|
+
] }),
|
|
787
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
788
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Additional Testing Emails" }),
|
|
789
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-500 mb-2", children: "Add other emails you use to test on different accounts" }),
|
|
790
|
+
profileAdditionalEmails.map((email) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
791
|
+
/* @__PURE__ */ jsx2("span", { className: "flex-1 px-3 py-1.5 bg-purple-50 text-purple-700 text-sm rounded-full", children: email }),
|
|
792
|
+
/* @__PURE__ */ jsx2(
|
|
793
|
+
"button",
|
|
794
|
+
{
|
|
795
|
+
onClick: () => handleRemoveEmail(email),
|
|
796
|
+
className: "text-purple-400 hover:text-red-500 text-sm",
|
|
797
|
+
children: "\u2715"
|
|
798
|
+
}
|
|
799
|
+
)
|
|
800
|
+
] }, email)),
|
|
801
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
802
|
+
/* @__PURE__ */ jsx2(
|
|
803
|
+
"input",
|
|
804
|
+
{
|
|
805
|
+
type: "email",
|
|
806
|
+
value: newEmailInput,
|
|
807
|
+
onChange: (e) => setNewEmailInput(e.target.value),
|
|
808
|
+
placeholder: "email@example.com",
|
|
809
|
+
className: "flex-1 px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500",
|
|
810
|
+
onKeyDown: (e) => e.key === "Enter" && handleAddEmail()
|
|
811
|
+
}
|
|
812
|
+
),
|
|
813
|
+
/* @__PURE__ */ jsx2(
|
|
814
|
+
"button",
|
|
815
|
+
{
|
|
816
|
+
onClick: handleAddEmail,
|
|
817
|
+
disabled: !newEmailInput.trim(),
|
|
818
|
+
className: "px-3 py-2 bg-purple-600 text-white text-sm rounded-lg hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
819
|
+
children: "Add"
|
|
820
|
+
}
|
|
821
|
+
)
|
|
822
|
+
] })
|
|
823
|
+
] }),
|
|
824
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
825
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Testing Platforms" }),
|
|
826
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-500 mb-2", children: "Select the platforms you can test on" }),
|
|
827
|
+
/* @__PURE__ */ jsx2("div", { className: "flex gap-2", children: [
|
|
828
|
+
{ key: "ios", label: "\u{1F4F1} iOS" },
|
|
829
|
+
{ key: "android", label: "\u{1F916} Android" },
|
|
830
|
+
{ key: "web", label: "\u{1F310} Web" }
|
|
831
|
+
].map(({ key, label }) => /* @__PURE__ */ jsx2(
|
|
832
|
+
"button",
|
|
833
|
+
{
|
|
834
|
+
onClick: () => handleTogglePlatform(key),
|
|
835
|
+
className: `flex-1 py-2 px-3 rounded-lg text-sm font-medium transition-colors border-2 ${profilePlatforms.includes(key) ? "bg-purple-50 border-purple-500 text-purple-700" : "bg-gray-50 border-transparent text-gray-600 hover:bg-gray-100"}`,
|
|
836
|
+
children: label
|
|
837
|
+
},
|
|
838
|
+
key
|
|
839
|
+
)) })
|
|
840
|
+
] }),
|
|
841
|
+
/* @__PURE__ */ jsx2(
|
|
842
|
+
"button",
|
|
843
|
+
{
|
|
844
|
+
onClick: handleSaveProfile,
|
|
845
|
+
disabled: savingProfile,
|
|
846
|
+
className: "w-full py-2 px-4 bg-green-600 text-white rounded-lg font-medium text-sm hover:bg-green-700 disabled:opacity-50 transition-colors",
|
|
847
|
+
children: savingProfile ? "Saving..." : "Save Profile"
|
|
848
|
+
}
|
|
849
|
+
)
|
|
850
|
+
] })
|
|
851
|
+
) : (
|
|
852
|
+
/* Profile View */
|
|
853
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
854
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-gray-50 rounded-lg p-4 text-center mb-4", children: [
|
|
855
|
+
/* @__PURE__ */ jsx2("div", { className: "w-16 h-16 mx-auto bg-purple-600 rounded-full flex items-center justify-center mb-3", children: /* @__PURE__ */ jsx2("span", { className: "text-2xl font-semibold text-white", children: testerInfo?.name?.charAt(0)?.toUpperCase() || "?" }) }),
|
|
856
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-gray-900", children: testerInfo?.name }),
|
|
857
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm text-gray-500", children: testerInfo?.email }),
|
|
858
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-6 mt-4 pt-4 border-t border-gray-200", children: [
|
|
859
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
860
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-purple-600", children: testerInfo?.assignedTests || 0 }),
|
|
861
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-500", children: "Assigned" })
|
|
862
|
+
] }),
|
|
863
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
864
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-purple-600", children: testerInfo?.completedTests || 0 }),
|
|
865
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-500", children: "Completed" })
|
|
866
|
+
] })
|
|
867
|
+
] })
|
|
868
|
+
] }),
|
|
869
|
+
(testerInfo?.additionalEmails?.length || 0) > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
|
|
870
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide mb-2", children: "Additional Emails" }),
|
|
871
|
+
testerInfo?.additionalEmails?.map((email) => /* @__PURE__ */ jsx2("p", { className: "text-sm text-gray-700", children: email }, email))
|
|
872
|
+
] }),
|
|
873
|
+
(testerInfo?.platforms?.length || 0) > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
|
|
874
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide mb-2", children: "Testing Platforms" }),
|
|
875
|
+
/* @__PURE__ */ jsx2("div", { className: "flex flex-wrap gap-2", children: testerInfo?.platforms?.map((platform) => /* @__PURE__ */ jsx2(
|
|
876
|
+
"span",
|
|
877
|
+
{
|
|
878
|
+
className: "px-2 py-1 bg-purple-100 text-purple-700 text-xs rounded-full font-medium",
|
|
879
|
+
children: platform === "ios" ? "\u{1F4F1} iOS" : platform === "android" ? "\u{1F916} Android" : "\u{1F310} Web"
|
|
880
|
+
},
|
|
881
|
+
platform
|
|
882
|
+
)) })
|
|
883
|
+
] }),
|
|
884
|
+
/* @__PURE__ */ jsx2(
|
|
885
|
+
"button",
|
|
886
|
+
{
|
|
887
|
+
onClick: handleStartEditProfile,
|
|
888
|
+
className: "w-full py-2 px-4 bg-purple-600 text-white rounded-lg font-medium text-sm hover:bg-purple-700 transition-colors",
|
|
889
|
+
children: "Edit Profile"
|
|
890
|
+
}
|
|
891
|
+
)
|
|
892
|
+
] })
|
|
893
|
+
) }),
|
|
672
894
|
activeTab === "report" && /* @__PURE__ */ jsx2("div", { children: submitted ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
673
895
|
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u{1F389}" }),
|
|
674
896
|
/* @__PURE__ */ jsx2("p", { className: "text-gray-600 mt-2 font-medium", children: "Report submitted!" })
|