@bbearai/react 0.1.7 → 0.1.9
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 +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +1383 -158
- package/dist/index.mjs +1384 -159
- package/package.json +11 -3
package/dist/index.mjs
CHANGED
|
@@ -20,7 +20,25 @@ var BugBearContext = createContext({
|
|
|
20
20
|
},
|
|
21
21
|
updateTesterProfile: async () => ({ success: false }),
|
|
22
22
|
refreshTesterInfo: async () => {
|
|
23
|
-
}
|
|
23
|
+
},
|
|
24
|
+
// QA Sessions
|
|
25
|
+
activeSession: null,
|
|
26
|
+
sessionFindings: [],
|
|
27
|
+
startSession: async () => ({ success: false }),
|
|
28
|
+
endSession: async () => ({ success: false }),
|
|
29
|
+
addFinding: async () => ({ success: false }),
|
|
30
|
+
refreshSession: async () => {
|
|
31
|
+
},
|
|
32
|
+
// Messaging
|
|
33
|
+
threads: [],
|
|
34
|
+
unreadCount: 0,
|
|
35
|
+
refreshThreads: async () => {
|
|
36
|
+
},
|
|
37
|
+
getThreadMessages: async () => [],
|
|
38
|
+
sendMessage: async () => false,
|
|
39
|
+
markAsRead: async () => {
|
|
40
|
+
},
|
|
41
|
+
createThread: async () => ({ success: false })
|
|
24
42
|
});
|
|
25
43
|
function useBugBear() {
|
|
26
44
|
return useContext(BugBearContext);
|
|
@@ -33,11 +51,86 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
33
51
|
const [assignments, setAssignments] = useState([]);
|
|
34
52
|
const [isLoading, setIsLoading] = useState(true);
|
|
35
53
|
const hasInitialized = useRef(false);
|
|
54
|
+
const [activeSession, setActiveSession] = useState(null);
|
|
55
|
+
const [sessionFindings, setSessionFindings] = useState([]);
|
|
56
|
+
const [threads, setThreads] = useState([]);
|
|
57
|
+
const [unreadCount, setUnreadCount] = useState(0);
|
|
36
58
|
const refreshAssignments = useCallback(async () => {
|
|
37
59
|
if (!client) return;
|
|
38
60
|
const newAssignments = await client.getAssignedTests();
|
|
39
61
|
setAssignments(newAssignments);
|
|
40
62
|
}, [client]);
|
|
63
|
+
const refreshSession = useCallback(async () => {
|
|
64
|
+
if (!client) return;
|
|
65
|
+
const session = await client.getActiveSession();
|
|
66
|
+
setActiveSession(session);
|
|
67
|
+
if (session) {
|
|
68
|
+
const findings = await client.getSessionFindings(session.id);
|
|
69
|
+
setSessionFindings(findings);
|
|
70
|
+
} else {
|
|
71
|
+
setSessionFindings([]);
|
|
72
|
+
}
|
|
73
|
+
}, [client]);
|
|
74
|
+
const startSession = useCallback(async (options = {}) => {
|
|
75
|
+
if (!client) return { success: false, error: "Client not initialized" };
|
|
76
|
+
const result = await client.startSession(options);
|
|
77
|
+
if (result.success && result.session) {
|
|
78
|
+
setActiveSession(result.session);
|
|
79
|
+
setSessionFindings([]);
|
|
80
|
+
}
|
|
81
|
+
return { success: result.success, error: result.error };
|
|
82
|
+
}, [client]);
|
|
83
|
+
const endSession = useCallback(async (notes) => {
|
|
84
|
+
if (!client || !activeSession) return { success: false, error: "No active session" };
|
|
85
|
+
const routesCovered = client.getNavigationHistory();
|
|
86
|
+
const result = await client.endSession(activeSession.id, { notes, routesCovered });
|
|
87
|
+
if (result.success) {
|
|
88
|
+
setActiveSession(null);
|
|
89
|
+
setSessionFindings([]);
|
|
90
|
+
}
|
|
91
|
+
return { success: result.success, error: result.error };
|
|
92
|
+
}, [client, activeSession]);
|
|
93
|
+
const addFinding = useCallback(async (options) => {
|
|
94
|
+
if (!client || !activeSession) return { success: false, error: "No active session" };
|
|
95
|
+
const result = await client.addFinding(activeSession.id, options);
|
|
96
|
+
if (result.success && result.finding) {
|
|
97
|
+
setSessionFindings((prev) => [...prev, result.finding]);
|
|
98
|
+
setActiveSession((prev) => prev ? { ...prev, findingsCount: prev.findingsCount + 1 } : null);
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}, [client, activeSession]);
|
|
102
|
+
const refreshThreads = useCallback(async () => {
|
|
103
|
+
if (!client) return;
|
|
104
|
+
const newThreads = await client.getThreadsForTester();
|
|
105
|
+
setThreads(newThreads);
|
|
106
|
+
const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
|
|
107
|
+
setUnreadCount(totalUnread);
|
|
108
|
+
}, [client]);
|
|
109
|
+
const getThreadMessages = useCallback(async (threadId) => {
|
|
110
|
+
if (!client) return [];
|
|
111
|
+
return client.getThreadMessages(threadId);
|
|
112
|
+
}, [client]);
|
|
113
|
+
const sendMessage = useCallback(async (threadId, content) => {
|
|
114
|
+
if (!client) return false;
|
|
115
|
+
const success = await client.sendMessage(threadId, content);
|
|
116
|
+
if (success) {
|
|
117
|
+
await refreshThreads();
|
|
118
|
+
}
|
|
119
|
+
return success;
|
|
120
|
+
}, [client, refreshThreads]);
|
|
121
|
+
const markAsRead = useCallback(async (threadId) => {
|
|
122
|
+
if (!client) return;
|
|
123
|
+
await client.markThreadAsRead(threadId);
|
|
124
|
+
await refreshThreads();
|
|
125
|
+
}, [client, refreshThreads]);
|
|
126
|
+
const createThread = useCallback(async (options) => {
|
|
127
|
+
if (!client) return { success: false, error: "Client not initialized" };
|
|
128
|
+
const result = await client.createThread(options);
|
|
129
|
+
if (result.success) {
|
|
130
|
+
await refreshThreads();
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
}, [client, refreshThreads]);
|
|
41
134
|
const initializeBugBear = useCallback(async (bugBearClient) => {
|
|
42
135
|
setIsLoading(true);
|
|
43
136
|
try {
|
|
@@ -50,8 +143,20 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
50
143
|
setTesterInfo(info);
|
|
51
144
|
setIsTester(!!info);
|
|
52
145
|
if (info && qaEnabled) {
|
|
53
|
-
const newAssignments = await
|
|
146
|
+
const [newAssignments, session, newThreads] = await Promise.all([
|
|
147
|
+
bugBearClient.getAssignedTests(),
|
|
148
|
+
bugBearClient.getActiveSession(),
|
|
149
|
+
bugBearClient.getThreadsForTester()
|
|
150
|
+
]);
|
|
54
151
|
setAssignments(newAssignments);
|
|
152
|
+
setActiveSession(session);
|
|
153
|
+
setThreads(newThreads);
|
|
154
|
+
const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
|
|
155
|
+
setUnreadCount(totalUnread);
|
|
156
|
+
if (session) {
|
|
157
|
+
const findings = await bugBearClient.getSessionFindings(session.id);
|
|
158
|
+
setSessionFindings(findings);
|
|
159
|
+
}
|
|
55
160
|
}
|
|
56
161
|
} catch (err) {
|
|
57
162
|
console.error("BugBear: Init error", err);
|
|
@@ -106,7 +211,22 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
106
211
|
onNavigate: config.onNavigate,
|
|
107
212
|
refreshTesterStatus,
|
|
108
213
|
updateTesterProfile,
|
|
109
|
-
refreshTesterInfo
|
|
214
|
+
refreshTesterInfo,
|
|
215
|
+
// QA Sessions
|
|
216
|
+
activeSession,
|
|
217
|
+
sessionFindings,
|
|
218
|
+
startSession,
|
|
219
|
+
endSession,
|
|
220
|
+
addFinding,
|
|
221
|
+
refreshSession,
|
|
222
|
+
// Messaging
|
|
223
|
+
threads,
|
|
224
|
+
unreadCount,
|
|
225
|
+
refreshThreads,
|
|
226
|
+
getThreadMessages,
|
|
227
|
+
sendMessage,
|
|
228
|
+
markAsRead,
|
|
229
|
+
createThread
|
|
110
230
|
},
|
|
111
231
|
children
|
|
112
232
|
}
|
|
@@ -114,7 +234,7 @@ function BugBearProvider({ config, children, enabled = true }) {
|
|
|
114
234
|
}
|
|
115
235
|
|
|
116
236
|
// src/BugBearPanel.tsx
|
|
117
|
-
import { useState as useState2, useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
|
|
237
|
+
import { useState as useState2, useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2, useMemo } from "react";
|
|
118
238
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
119
239
|
function BugBearIcon({ size = 24, className = "" }) {
|
|
120
240
|
return /* @__PURE__ */ jsxs(
|
|
@@ -185,13 +305,77 @@ function BugBearPanel({
|
|
|
185
305
|
defaultCollapsed = false,
|
|
186
306
|
draggable = true
|
|
187
307
|
}) {
|
|
188
|
-
const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate, updateTesterProfile, refreshTesterInfo } = useBugBear();
|
|
308
|
+
const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate, updateTesterProfile, refreshTesterInfo, activeSession, sessionFindings, startSession, endSession, addFinding, threads, unreadCount, refreshThreads, getThreadMessages, sendMessage, markAsRead, createThread } = useBugBear();
|
|
189
309
|
const [collapsed, setCollapsed] = useState2(defaultCollapsed);
|
|
190
310
|
const [activeTab, setActiveTab] = useState2("tests");
|
|
191
311
|
const [showSteps, setShowSteps] = useState2(false);
|
|
192
312
|
const [testView, setTestView] = useState2("detail");
|
|
193
313
|
const [selectedTestId, setSelectedTestId] = useState2(null);
|
|
314
|
+
const [messageView, setMessageView] = useState2("list");
|
|
315
|
+
const [selectedThread, setSelectedThread] = useState2(null);
|
|
316
|
+
const [threadMessages, setThreadMessages] = useState2([]);
|
|
317
|
+
const [replyText, setReplyText] = useState2("");
|
|
318
|
+
const [sendingReply, setSendingReply] = useState2(false);
|
|
319
|
+
const [loadingMessages, setLoadingMessages] = useState2(false);
|
|
320
|
+
const [composeSubject, setComposeSubject] = useState2("");
|
|
321
|
+
const [composeMessage, setComposeMessage] = useState2("");
|
|
322
|
+
const [sendingNewMessage, setSendingNewMessage] = useState2(false);
|
|
194
323
|
const displayedAssignment = selectedTestId ? assignments.find((a) => a.id === selectedTestId) || currentAssignment : currentAssignment;
|
|
324
|
+
const groupedAssignments = useMemo(() => {
|
|
325
|
+
const groups = /* @__PURE__ */ new Map();
|
|
326
|
+
for (const assignment of assignments) {
|
|
327
|
+
const groupId = assignment.testCase.group?.id || "ungrouped";
|
|
328
|
+
const group = assignment.testCase.group || null;
|
|
329
|
+
if (!groups.has(groupId)) {
|
|
330
|
+
groups.set(groupId, {
|
|
331
|
+
group,
|
|
332
|
+
assignments: [],
|
|
333
|
+
stats: { total: 0, passed: 0, failed: 0, pending: 0, skipped: 0 }
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
const folder = groups.get(groupId);
|
|
337
|
+
folder.assignments.push(assignment);
|
|
338
|
+
folder.stats.total++;
|
|
339
|
+
if (assignment.status === "passed") folder.stats.passed++;
|
|
340
|
+
else if (assignment.status === "failed") folder.stats.failed++;
|
|
341
|
+
else if (assignment.status === "skipped") folder.stats.skipped++;
|
|
342
|
+
else folder.stats.pending++;
|
|
343
|
+
}
|
|
344
|
+
const sortedGroups = Array.from(groups.values()).sort((a, b) => {
|
|
345
|
+
if (!a.group && !b.group) return 0;
|
|
346
|
+
if (!a.group) return 1;
|
|
347
|
+
if (!b.group) return -1;
|
|
348
|
+
return a.group.sortOrder - b.group.sortOrder;
|
|
349
|
+
});
|
|
350
|
+
return sortedGroups;
|
|
351
|
+
}, [assignments]);
|
|
352
|
+
const toggleFolderCollapse = useCallback2((groupId) => {
|
|
353
|
+
setCollapsedFolders((prev) => {
|
|
354
|
+
const next = new Set(prev);
|
|
355
|
+
if (next.has(groupId)) {
|
|
356
|
+
next.delete(groupId);
|
|
357
|
+
} else {
|
|
358
|
+
next.add(groupId);
|
|
359
|
+
}
|
|
360
|
+
return next;
|
|
361
|
+
});
|
|
362
|
+
}, []);
|
|
363
|
+
const getStatusBadge = (status) => {
|
|
364
|
+
switch (status) {
|
|
365
|
+
case "passed":
|
|
366
|
+
return { icon: "\u2705", label: "Passed", className: "bg-green-900/30 text-green-400" };
|
|
367
|
+
case "failed":
|
|
368
|
+
return { icon: "\u274C", label: "Failed", className: "bg-red-900/30 text-red-400" };
|
|
369
|
+
case "skipped":
|
|
370
|
+
return { icon: "\u23ED\uFE0F", label: "Skipped", className: "bg-yellow-900/30 text-yellow-400" };
|
|
371
|
+
case "in_progress":
|
|
372
|
+
return { icon: "\u{1F504}", label: "In Progress", className: "bg-blue-900/30 text-blue-400" };
|
|
373
|
+
case "blocked":
|
|
374
|
+
return { icon: "\u{1F6AB}", label: "Blocked", className: "bg-orange-900/30 text-orange-400" };
|
|
375
|
+
default:
|
|
376
|
+
return { icon: "\u23F3", label: "Pending", className: "bg-zinc-700 text-zinc-400" };
|
|
377
|
+
}
|
|
378
|
+
};
|
|
195
379
|
const [panelPosition, setPanelPosition] = useState2(null);
|
|
196
380
|
const [isDragging, setIsDragging] = useState2(false);
|
|
197
381
|
const dragStartRef = useRef2(null);
|
|
@@ -202,7 +386,21 @@ function BugBearPanel({
|
|
|
202
386
|
const [submitting, setSubmitting] = useState2(false);
|
|
203
387
|
const [submitted, setSubmitted] = useState2(false);
|
|
204
388
|
const [justPassed, setJustPassed] = useState2(false);
|
|
389
|
+
const [showFeedbackPrompt, setShowFeedbackPrompt] = useState2(false);
|
|
390
|
+
const [pendingFeedbackStatus, setPendingFeedbackStatus] = useState2(null);
|
|
391
|
+
const [feedbackRating, setFeedbackRating] = useState2(5);
|
|
392
|
+
const [feedbackNote, setFeedbackNote] = useState2("");
|
|
393
|
+
const [feedbackFlags, setFeedbackFlags] = useState2({
|
|
394
|
+
isOutdated: false,
|
|
395
|
+
needsMoreDetail: false,
|
|
396
|
+
stepsUnclear: false,
|
|
397
|
+
expectedResultUnclear: false
|
|
398
|
+
});
|
|
205
399
|
const [criteriaResults, setCriteriaResults] = useState2({});
|
|
400
|
+
const [showSkipModal, setShowSkipModal] = useState2(false);
|
|
401
|
+
const [selectedSkipReason, setSelectedSkipReason] = useState2(null);
|
|
402
|
+
const [skipNotes, setSkipNotes] = useState2("");
|
|
403
|
+
const [skipping, setSkipping] = useState2(false);
|
|
206
404
|
const [profileEditing, setProfileEditing] = useState2(false);
|
|
207
405
|
const [profileName, setProfileName] = useState2("");
|
|
208
406
|
const [profileAdditionalEmails, setProfileAdditionalEmails] = useState2([]);
|
|
@@ -211,6 +409,23 @@ function BugBearPanel({
|
|
|
211
409
|
const [savingProfile, setSavingProfile] = useState2(false);
|
|
212
410
|
const [profileSaved, setProfileSaved] = useState2(false);
|
|
213
411
|
const [showProfileOverlay, setShowProfileOverlay] = useState2(false);
|
|
412
|
+
const [collapsedFolders, setCollapsedFolders] = useState2(/* @__PURE__ */ new Set());
|
|
413
|
+
const [startingSession, setStartingSession] = useState2(false);
|
|
414
|
+
const [sessionFocusArea, setSessionFocusArea] = useState2("");
|
|
415
|
+
const [sessionPlatform, setSessionPlatform] = useState2("web");
|
|
416
|
+
const [suggestedRoutes, setSuggestedRoutes] = useState2([]);
|
|
417
|
+
const [focusAreas, setFocusAreas] = useState2([]);
|
|
418
|
+
const [showAddFinding, setShowAddFinding] = useState2(false);
|
|
419
|
+
const [findingType, setFindingType] = useState2("bug");
|
|
420
|
+
const [findingTitle, setFindingTitle] = useState2("");
|
|
421
|
+
const [findingDescription, setFindingDescription] = useState2("");
|
|
422
|
+
const [findingSeverity, setFindingSeverity] = useState2("medium");
|
|
423
|
+
const [addingFinding, setAddingFinding] = useState2(false);
|
|
424
|
+
const [endingSession, setEndingSession] = useState2(false);
|
|
425
|
+
const [sessionNotes, setSessionNotes] = useState2("");
|
|
426
|
+
const [showEndConfirm, setShowEndConfirm] = useState2(false);
|
|
427
|
+
const [sessionElapsedTime, setSessionElapsedTime] = useState2(0);
|
|
428
|
+
const [assignmentElapsedTime, setAssignmentElapsedTime] = useState2(0);
|
|
214
429
|
useEffect2(() => {
|
|
215
430
|
if (typeof window === "undefined") return;
|
|
216
431
|
try {
|
|
@@ -245,6 +460,84 @@ function BugBearPanel({
|
|
|
245
460
|
setCriteriaResults({});
|
|
246
461
|
setShowSteps(false);
|
|
247
462
|
}, [displayedAssignment?.id]);
|
|
463
|
+
useEffect2(() => {
|
|
464
|
+
if (!activeSession) {
|
|
465
|
+
setSessionElapsedTime(0);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const startTime = new Date(activeSession.startedAt).getTime();
|
|
469
|
+
const now = Date.now();
|
|
470
|
+
setSessionElapsedTime(Math.floor((now - startTime) / 1e3));
|
|
471
|
+
const interval = setInterval(() => {
|
|
472
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1e3);
|
|
473
|
+
setSessionElapsedTime(elapsed);
|
|
474
|
+
}, 1e3);
|
|
475
|
+
return () => clearInterval(interval);
|
|
476
|
+
}, [activeSession]);
|
|
477
|
+
useEffect2(() => {
|
|
478
|
+
const activeAssignment = displayedAssignment?.status === "in_progress" ? displayedAssignment : null;
|
|
479
|
+
if (!activeAssignment?.startedAt) {
|
|
480
|
+
setAssignmentElapsedTime(0);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
const startTime = new Date(activeAssignment.startedAt).getTime();
|
|
484
|
+
const now = Date.now();
|
|
485
|
+
setAssignmentElapsedTime(Math.floor((now - startTime) / 1e3));
|
|
486
|
+
const interval = setInterval(() => {
|
|
487
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1e3);
|
|
488
|
+
setAssignmentElapsedTime(elapsed);
|
|
489
|
+
}, 1e3);
|
|
490
|
+
return () => clearInterval(interval);
|
|
491
|
+
}, [displayedAssignment?.id, displayedAssignment?.status, displayedAssignment?.startedAt]);
|
|
492
|
+
useEffect2(() => {
|
|
493
|
+
if (!client || activeSession) {
|
|
494
|
+
setSuggestedRoutes([]);
|
|
495
|
+
setFocusAreas([]);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const loadSuggestions = async () => {
|
|
499
|
+
try {
|
|
500
|
+
const supabase = client.supabase;
|
|
501
|
+
if (!supabase) return;
|
|
502
|
+
const projectId = client.config.projectId;
|
|
503
|
+
const [routeStatsRes, focusAreasRes] = await Promise.all([
|
|
504
|
+
supabase.from("route_test_stats").select("route, priority_score, open_bugs, exploratory_issues, last_tested_at, test_case_count").eq("project_id", projectId).order("priority_score", { ascending: false }).limit(10),
|
|
505
|
+
supabase.rpc("get_active_focus_areas", { p_project_id: projectId })
|
|
506
|
+
]);
|
|
507
|
+
if (routeStatsRes.data && routeStatsRes.data.length > 0) {
|
|
508
|
+
const suggestions = routeStatsRes.data.filter((r) => r.route && r.priority_score > 0).slice(0, 5).map((r) => {
|
|
509
|
+
let reason = "";
|
|
510
|
+
if (r.open_bugs > 0) {
|
|
511
|
+
reason = `${r.open_bugs} open bug${r.open_bugs > 1 ? "s" : ""}`;
|
|
512
|
+
} else if (!r.last_tested_at) {
|
|
513
|
+
reason = "Never tested";
|
|
514
|
+
} else if (r.test_case_count === 0) {
|
|
515
|
+
reason = "No test coverage";
|
|
516
|
+
} else {
|
|
517
|
+
reason = `Priority: ${r.priority_score}`;
|
|
518
|
+
}
|
|
519
|
+
return {
|
|
520
|
+
route: r.route,
|
|
521
|
+
reason,
|
|
522
|
+
priorityScore: r.priority_score
|
|
523
|
+
};
|
|
524
|
+
});
|
|
525
|
+
setSuggestedRoutes(suggestions);
|
|
526
|
+
}
|
|
527
|
+
if (focusAreasRes.data && focusAreasRes.data.length > 0) {
|
|
528
|
+
setFocusAreas(focusAreasRes.data.slice(0, 3).map((fa) => ({
|
|
529
|
+
id: fa.id,
|
|
530
|
+
name: fa.name,
|
|
531
|
+
description: fa.description,
|
|
532
|
+
priority: fa.priority
|
|
533
|
+
})));
|
|
534
|
+
}
|
|
535
|
+
} catch (err) {
|
|
536
|
+
console.error("BugBear: Failed to load suggestions", err);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
loadSuggestions();
|
|
540
|
+
}, [client, activeSession]);
|
|
248
541
|
const handleMouseDown = useCallback2((e) => {
|
|
249
542
|
if (!draggable || !panelPosition) return;
|
|
250
543
|
const target = e.target;
|
|
@@ -295,27 +588,115 @@ function BugBearPanel({
|
|
|
295
588
|
return null;
|
|
296
589
|
}
|
|
297
590
|
const handlePass = async () => {
|
|
298
|
-
if (!
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
591
|
+
if (!displayedAssignment) return;
|
|
592
|
+
setPendingFeedbackStatus("passed");
|
|
593
|
+
setShowFeedbackPrompt(true);
|
|
594
|
+
setFeedbackRating(5);
|
|
595
|
+
setFeedbackNote("");
|
|
596
|
+
setFeedbackFlags({
|
|
597
|
+
isOutdated: false,
|
|
598
|
+
needsMoreDetail: false,
|
|
599
|
+
stepsUnclear: false,
|
|
600
|
+
expectedResultUnclear: false
|
|
306
601
|
});
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
602
|
+
};
|
|
603
|
+
const handleFail = async () => {
|
|
604
|
+
if (!displayedAssignment) return;
|
|
605
|
+
setPendingFeedbackStatus("failed");
|
|
606
|
+
setShowFeedbackPrompt(true);
|
|
607
|
+
setFeedbackRating(3);
|
|
608
|
+
setFeedbackNote("");
|
|
609
|
+
setFeedbackFlags({
|
|
610
|
+
isOutdated: false,
|
|
611
|
+
needsMoreDetail: false,
|
|
612
|
+
stepsUnclear: false,
|
|
613
|
+
expectedResultUnclear: false
|
|
614
|
+
});
|
|
615
|
+
};
|
|
616
|
+
const handleOpenSkipModal = () => {
|
|
617
|
+
setShowSkipModal(true);
|
|
618
|
+
setSelectedSkipReason(null);
|
|
619
|
+
setSkipNotes("");
|
|
620
|
+
};
|
|
621
|
+
const handleSkip = async () => {
|
|
622
|
+
if (!client || !displayedAssignment || !selectedSkipReason) return;
|
|
623
|
+
setSkipping(true);
|
|
624
|
+
const result = await client.skipAssignment(
|
|
625
|
+
displayedAssignment.id,
|
|
626
|
+
selectedSkipReason,
|
|
627
|
+
skipNotes.trim() || void 0
|
|
628
|
+
);
|
|
629
|
+
if (result.success) {
|
|
630
|
+
await refreshAssignments();
|
|
631
|
+
setShowSkipModal(false);
|
|
632
|
+
setSelectedSkipReason(null);
|
|
633
|
+
setSkipNotes("");
|
|
312
634
|
setSelectedTestId(null);
|
|
313
635
|
setTestView("detail");
|
|
314
|
-
}
|
|
636
|
+
}
|
|
637
|
+
setSkipping(false);
|
|
315
638
|
};
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
639
|
+
const skipReasonOptions = [
|
|
640
|
+
{ value: "blocked", label: "Blocked", description: "Environment issue or external blocker" },
|
|
641
|
+
{ value: "not_ready", label: "Not Ready", description: "Feature not yet implemented" },
|
|
642
|
+
{ value: "dependency", label: "Dependency", description: "Waiting on another test or task" },
|
|
643
|
+
{ value: "other", label: "Other", description: "Other reason (please specify)" }
|
|
644
|
+
];
|
|
645
|
+
const handleSubmitFeedback = async (skipFeedback = false) => {
|
|
646
|
+
if (!client || !displayedAssignment) return;
|
|
647
|
+
setSubmitting(true);
|
|
648
|
+
const feedback = skipFeedback ? void 0 : {
|
|
649
|
+
rating: feedbackRating,
|
|
650
|
+
feedbackNote: feedbackNote.trim() || void 0,
|
|
651
|
+
isOutdated: feedbackFlags.isOutdated,
|
|
652
|
+
needsMoreDetail: feedbackFlags.needsMoreDetail,
|
|
653
|
+
stepsUnclear: feedbackFlags.stepsUnclear,
|
|
654
|
+
expectedResultUnclear: feedbackFlags.expectedResultUnclear
|
|
655
|
+
};
|
|
656
|
+
if (pendingFeedbackStatus === "passed") {
|
|
657
|
+
await client.submitReport({
|
|
658
|
+
type: "test_pass",
|
|
659
|
+
description: `Test passed: ${displayedAssignment.testCase.title}`,
|
|
660
|
+
assignmentId: displayedAssignment.id,
|
|
661
|
+
testCaseId: displayedAssignment.testCase.id,
|
|
662
|
+
appContext: getAppContext?.() || { currentRoute: window.location.pathname }
|
|
663
|
+
});
|
|
664
|
+
if (feedback) {
|
|
665
|
+
await client.submitTestFeedback({
|
|
666
|
+
testCaseId: displayedAssignment.testCase.id,
|
|
667
|
+
assignmentId: displayedAssignment.id,
|
|
668
|
+
feedback,
|
|
669
|
+
timeToCompleteSeconds: assignmentElapsedTime || void 0
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
await refreshAssignments();
|
|
673
|
+
setSubmitting(false);
|
|
674
|
+
setShowFeedbackPrompt(false);
|
|
675
|
+
setPendingFeedbackStatus(null);
|
|
676
|
+
setJustPassed(true);
|
|
677
|
+
setTimeout(() => {
|
|
678
|
+
setJustPassed(false);
|
|
679
|
+
setSelectedTestId(null);
|
|
680
|
+
setTestView("detail");
|
|
681
|
+
}, 1200);
|
|
682
|
+
} else if (pendingFeedbackStatus === "failed") {
|
|
683
|
+
if (feedback) {
|
|
684
|
+
await client.submitTestFeedback({
|
|
685
|
+
testCaseId: displayedAssignment.testCase.id,
|
|
686
|
+
assignmentId: displayedAssignment.id,
|
|
687
|
+
feedback,
|
|
688
|
+
timeToCompleteSeconds: assignmentElapsedTime || void 0
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
setSubmitting(false);
|
|
692
|
+
setShowFeedbackPrompt(false);
|
|
693
|
+
setPendingFeedbackStatus(null);
|
|
694
|
+
setActiveTab("report");
|
|
695
|
+
setReportType("test_fail");
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
const handleSkipFeedback = () => {
|
|
699
|
+
handleSubmitFeedback(true);
|
|
319
700
|
};
|
|
320
701
|
const handleSubmitReport = async () => {
|
|
321
702
|
if (!client || !description.trim()) return;
|
|
@@ -408,6 +789,135 @@ function BugBearPanel({
|
|
|
408
789
|
}
|
|
409
790
|
setSavingProfile(false);
|
|
410
791
|
};
|
|
792
|
+
const handleStartSession = async () => {
|
|
793
|
+
setStartingSession(true);
|
|
794
|
+
const result = await startSession({
|
|
795
|
+
focusArea: sessionFocusArea.trim() || void 0,
|
|
796
|
+
platform: sessionPlatform
|
|
797
|
+
});
|
|
798
|
+
if (result.success) {
|
|
799
|
+
setSessionFocusArea("");
|
|
800
|
+
}
|
|
801
|
+
setStartingSession(false);
|
|
802
|
+
};
|
|
803
|
+
const handleEndSession = async () => {
|
|
804
|
+
setEndingSession(true);
|
|
805
|
+
const result = await endSession(sessionNotes.trim() || void 0);
|
|
806
|
+
if (result.success) {
|
|
807
|
+
setSessionNotes("");
|
|
808
|
+
setShowEndConfirm(false);
|
|
809
|
+
}
|
|
810
|
+
setEndingSession(false);
|
|
811
|
+
};
|
|
812
|
+
const handleAddFinding = async () => {
|
|
813
|
+
if (!findingTitle.trim()) return;
|
|
814
|
+
setAddingFinding(true);
|
|
815
|
+
const result = await addFinding({
|
|
816
|
+
type: findingType,
|
|
817
|
+
title: findingTitle.trim(),
|
|
818
|
+
description: findingDescription.trim() || void 0,
|
|
819
|
+
severity: findingType === "bug" ? findingSeverity : void 0,
|
|
820
|
+
route: typeof window !== "undefined" ? window.location.pathname : void 0
|
|
821
|
+
});
|
|
822
|
+
if (result.success) {
|
|
823
|
+
setFindingTitle("");
|
|
824
|
+
setFindingDescription("");
|
|
825
|
+
setFindingType("bug");
|
|
826
|
+
setFindingSeverity("medium");
|
|
827
|
+
setShowAddFinding(false);
|
|
828
|
+
}
|
|
829
|
+
setAddingFinding(false);
|
|
830
|
+
};
|
|
831
|
+
const formatElapsedTime = (seconds) => {
|
|
832
|
+
const h = Math.floor(seconds / 3600);
|
|
833
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
834
|
+
const s = seconds % 60;
|
|
835
|
+
if (h > 0) {
|
|
836
|
+
return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
|
|
837
|
+
}
|
|
838
|
+
return `${m}:${s.toString().padStart(2, "0")}`;
|
|
839
|
+
};
|
|
840
|
+
const formatRelativeTime = (dateString) => {
|
|
841
|
+
const date = new Date(dateString);
|
|
842
|
+
const now = /* @__PURE__ */ new Date();
|
|
843
|
+
const diffMs = now.getTime() - date.getTime();
|
|
844
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
845
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
846
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
847
|
+
if (diffMins < 1) return "Just now";
|
|
848
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
849
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
850
|
+
if (diffDays === 1) return "Yesterday";
|
|
851
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
852
|
+
return date.toLocaleDateString();
|
|
853
|
+
};
|
|
854
|
+
const formatMessageTime = (dateString) => {
|
|
855
|
+
const date = new Date(dateString);
|
|
856
|
+
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
857
|
+
};
|
|
858
|
+
const getThreadTypeIcon = (type) => {
|
|
859
|
+
switch (type) {
|
|
860
|
+
case "announcement":
|
|
861
|
+
return "\u{1F4E2}";
|
|
862
|
+
case "direct":
|
|
863
|
+
return "\u{1F4AC}";
|
|
864
|
+
case "report":
|
|
865
|
+
return "\u{1F41B}";
|
|
866
|
+
case "general_note":
|
|
867
|
+
return "\u{1F4DD}";
|
|
868
|
+
default:
|
|
869
|
+
return "\u{1F4AC}";
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
const handleOpenThread = async (thread) => {
|
|
873
|
+
setSelectedThread(thread);
|
|
874
|
+
setMessageView("thread");
|
|
875
|
+
setLoadingMessages(true);
|
|
876
|
+
const messages = await getThreadMessages(thread.id);
|
|
877
|
+
setThreadMessages(messages);
|
|
878
|
+
setLoadingMessages(false);
|
|
879
|
+
if (thread.unreadCount > 0) {
|
|
880
|
+
await markAsRead(thread.id);
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
const handleSendReply = async () => {
|
|
884
|
+
if (!selectedThread || !replyText.trim()) return;
|
|
885
|
+
setSendingReply(true);
|
|
886
|
+
const success = await sendMessage(selectedThread.id, replyText.trim());
|
|
887
|
+
if (success) {
|
|
888
|
+
setReplyText("");
|
|
889
|
+
const messages = await getThreadMessages(selectedThread.id);
|
|
890
|
+
setThreadMessages(messages);
|
|
891
|
+
}
|
|
892
|
+
setSendingReply(false);
|
|
893
|
+
};
|
|
894
|
+
const handleBackToThreadList = () => {
|
|
895
|
+
setMessageView("list");
|
|
896
|
+
setSelectedThread(null);
|
|
897
|
+
setThreadMessages([]);
|
|
898
|
+
setReplyText("");
|
|
899
|
+
setComposeSubject("");
|
|
900
|
+
setComposeMessage("");
|
|
901
|
+
};
|
|
902
|
+
const handleStartNewMessage = () => {
|
|
903
|
+
setMessageView("compose");
|
|
904
|
+
setComposeSubject("");
|
|
905
|
+
setComposeMessage("");
|
|
906
|
+
};
|
|
907
|
+
const handleSendNewMessage = async () => {
|
|
908
|
+
if (!composeSubject.trim() || !composeMessage.trim()) return;
|
|
909
|
+
setSendingNewMessage(true);
|
|
910
|
+
const result = await createThread({
|
|
911
|
+
subject: composeSubject.trim(),
|
|
912
|
+
message: composeMessage.trim()
|
|
913
|
+
});
|
|
914
|
+
if (result.success) {
|
|
915
|
+
setComposeSubject("");
|
|
916
|
+
setComposeMessage("");
|
|
917
|
+
setMessageView("list");
|
|
918
|
+
}
|
|
919
|
+
setSendingNewMessage(false);
|
|
920
|
+
};
|
|
411
921
|
return /* @__PURE__ */ jsxs(
|
|
412
922
|
"div",
|
|
413
923
|
{
|
|
@@ -430,22 +940,22 @@ function BugBearPanel({
|
|
|
430
940
|
onClick: () => setCollapsed(false),
|
|
431
941
|
"data-drag-handle": true,
|
|
432
942
|
onDoubleClick: handleDoubleClick,
|
|
433
|
-
className: "flex items-center gap-2 px-3 py-2 bg-
|
|
943
|
+
className: "flex items-center gap-2 px-3 py-2 bg-blue-500 text-white rounded-full shadow-lg hover:bg-blue-600 transition-colors",
|
|
434
944
|
style: { cursor: draggable ? "grab" : "pointer" },
|
|
435
945
|
children: [
|
|
436
946
|
/* @__PURE__ */ jsx2(BugBearIcon, { size: 24 }),
|
|
437
947
|
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: "BugBear" }),
|
|
438
|
-
pendingCount > 0 && /* @__PURE__ */ jsx2("span", { className: "bg-white text-
|
|
948
|
+
pendingCount > 0 && /* @__PURE__ */ jsx2("span", { className: "bg-white text-blue-400 text-xs font-bold px-1.5 py-0.5 rounded-full", children: pendingCount })
|
|
439
949
|
]
|
|
440
950
|
}
|
|
441
951
|
),
|
|
442
|
-
!collapsed && /* @__PURE__ */ jsxs("div", { className: "w-80 bg-
|
|
952
|
+
!collapsed && /* @__PURE__ */ jsxs("div", { className: "w-80 bg-zinc-900 rounded-xl shadow-2xl border border-zinc-800 overflow-hidden", children: [
|
|
443
953
|
/* @__PURE__ */ jsxs(
|
|
444
954
|
"div",
|
|
445
955
|
{
|
|
446
956
|
"data-drag-handle": true,
|
|
447
957
|
onDoubleClick: handleDoubleClick,
|
|
448
|
-
className: "bg-
|
|
958
|
+
className: "bg-zinc-950 text-white px-4 py-3 flex items-center justify-between border-b border-zinc-800",
|
|
449
959
|
style: { cursor: draggable ? isDragging ? "grabbing" : "grab" : "default" },
|
|
450
960
|
children: [
|
|
451
961
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -453,13 +963,13 @@ function BugBearPanel({
|
|
|
453
963
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
454
964
|
/* @__PURE__ */ jsxs("h3", { className: "font-semibold text-sm flex items-center gap-2", children: [
|
|
455
965
|
"BugBear",
|
|
456
|
-
draggable && /* @__PURE__ */ jsx2("span", { className: "text-
|
|
966
|
+
draggable && /* @__PURE__ */ jsx2("span", { className: "text-zinc-500 text-xs", title: "Drag to move, double-click to reset", children: "\u22EE\u22EE" })
|
|
457
967
|
] }),
|
|
458
968
|
/* @__PURE__ */ jsxs(
|
|
459
969
|
"button",
|
|
460
970
|
{
|
|
461
971
|
onClick: handleOpenProfile,
|
|
462
|
-
className: "text-
|
|
972
|
+
className: "text-zinc-400 text-xs flex items-center gap-1 hover:text-white transition-colors",
|
|
463
973
|
children: [
|
|
464
974
|
testerInfo?.name,
|
|
465
975
|
/* @__PURE__ */ jsx2("span", { className: "text-[10px]", children: "\u270E" })
|
|
@@ -472,30 +982,52 @@ function BugBearPanel({
|
|
|
472
982
|
"button",
|
|
473
983
|
{
|
|
474
984
|
onClick: () => setCollapsed(true),
|
|
475
|
-
className: "p-1 hover:bg-
|
|
985
|
+
className: "p-1 hover:bg-zinc-800 rounded",
|
|
476
986
|
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" }) })
|
|
477
987
|
}
|
|
478
988
|
)
|
|
479
989
|
]
|
|
480
990
|
}
|
|
481
991
|
),
|
|
482
|
-
/* @__PURE__ */ jsxs("div", { className: "flex border-b border-
|
|
992
|
+
/* @__PURE__ */ jsxs("div", { className: "flex border-b border-zinc-800 bg-zinc-900", children: [
|
|
483
993
|
/* @__PURE__ */ jsxs(
|
|
484
994
|
"button",
|
|
485
995
|
{
|
|
486
996
|
onClick: () => setActiveTab("tests"),
|
|
487
|
-
className: `flex-1
|
|
997
|
+
className: `flex-1 py-3 text-sm font-medium transition-all flex items-center justify-center gap-1.5 border-b-2 ${activeTab === "tests" ? "border-blue-500 text-blue-400" : "border-transparent text-zinc-500 hover:text-zinc-300"}`,
|
|
488
998
|
children: [
|
|
489
999
|
"Tests ",
|
|
490
1000
|
pendingCount > 0 && `(${pendingCount})`
|
|
491
1001
|
]
|
|
492
1002
|
}
|
|
493
1003
|
),
|
|
1004
|
+
/* @__PURE__ */ jsxs(
|
|
1005
|
+
"button",
|
|
1006
|
+
{
|
|
1007
|
+
onClick: () => setActiveTab("messages"),
|
|
1008
|
+
className: `flex-1 py-3 text-sm font-medium transition-all flex items-center justify-center gap-1.5 relative border-b-2 ${activeTab === "messages" ? "border-blue-500 text-blue-400" : "border-transparent text-zinc-500 hover:text-zinc-300"}`,
|
|
1009
|
+
children: [
|
|
1010
|
+
"Messages",
|
|
1011
|
+
unreadCount > 0 && /* @__PURE__ */ jsx2("span", { className: "absolute top-1.5 ml-16 min-w-[18px] h-[18px] px-1 bg-blue-500 rounded-full text-[10px] text-white font-bold flex items-center justify-center", children: unreadCount })
|
|
1012
|
+
]
|
|
1013
|
+
}
|
|
1014
|
+
),
|
|
1015
|
+
/* @__PURE__ */ jsxs(
|
|
1016
|
+
"button",
|
|
1017
|
+
{
|
|
1018
|
+
onClick: () => setActiveTab("session"),
|
|
1019
|
+
className: `flex-1 py-3 text-sm font-medium transition-all flex items-center justify-center gap-1.5 relative border-b-2 ${activeTab === "session" ? "border-blue-500 text-blue-400" : "border-transparent text-zinc-500 hover:text-zinc-300"}`,
|
|
1020
|
+
children: [
|
|
1021
|
+
"Explore",
|
|
1022
|
+
activeSession && /* @__PURE__ */ jsx2("span", { className: "absolute top-2 ml-14 w-2 h-2 bg-green-500 rounded-full animate-pulse" })
|
|
1023
|
+
]
|
|
1024
|
+
}
|
|
1025
|
+
),
|
|
494
1026
|
/* @__PURE__ */ jsx2(
|
|
495
1027
|
"button",
|
|
496
1028
|
{
|
|
497
1029
|
onClick: () => setActiveTab("report"),
|
|
498
|
-
className: `flex-1
|
|
1030
|
+
className: `flex-1 py-3 text-sm font-medium transition-all flex items-center justify-center gap-1.5 border-b-2 ${activeTab === "report" ? "border-blue-500 text-blue-400" : "border-transparent text-zinc-500 hover:text-zinc-300"}`,
|
|
499
1031
|
children: "Report"
|
|
500
1032
|
}
|
|
501
1033
|
)
|
|
@@ -503,59 +1035,202 @@ function BugBearPanel({
|
|
|
503
1035
|
/* @__PURE__ */ jsxs("div", { className: "p-4 max-h-96 overflow-y-auto", children: [
|
|
504
1036
|
activeTab === "tests" && /* @__PURE__ */ jsx2("div", { children: assignments.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
505
1037
|
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u2705" }),
|
|
506
|
-
/* @__PURE__ */ jsx2("p", { className: "text-
|
|
507
|
-
/* @__PURE__ */ jsx2("p", { className: "text-
|
|
1038
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-400 mt-2 font-medium", children: "All caught up!" }),
|
|
1039
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-sm", children: "No tests assigned" })
|
|
508
1040
|
] }) : testView === "list" ? (
|
|
509
|
-
/* List View - Show
|
|
510
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-
|
|
511
|
-
/* @__PURE__ */
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
"
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
1041
|
+
/* List View - Show tests grouped by folder */
|
|
1042
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1043
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2 px-1", children: [
|
|
1044
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-zinc-500", children: [
|
|
1045
|
+
assignments.length,
|
|
1046
|
+
" test",
|
|
1047
|
+
assignments.length !== 1 ? "s" : "",
|
|
1048
|
+
" assigned"
|
|
1049
|
+
] }),
|
|
1050
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
1051
|
+
/* @__PURE__ */ jsxs("span", { className: "text-green-400", children: [
|
|
1052
|
+
"\u2705 ",
|
|
1053
|
+
assignments.filter((a) => a.status === "passed").length
|
|
1054
|
+
] }),
|
|
1055
|
+
/* @__PURE__ */ jsxs("span", { className: "text-red-400", children: [
|
|
1056
|
+
"\u274C ",
|
|
1057
|
+
assignments.filter((a) => a.status === "failed").length
|
|
1058
|
+
] }),
|
|
1059
|
+
/* @__PURE__ */ jsxs("span", { className: "text-zinc-500", children: [
|
|
1060
|
+
"\u23F3 ",
|
|
1061
|
+
assignments.filter((a) => a.status === "pending" || a.status === "in_progress").length
|
|
1062
|
+
] })
|
|
1063
|
+
] })
|
|
1064
|
+
] }),
|
|
1065
|
+
groupedAssignments.map((folder) => {
|
|
1066
|
+
const groupId = folder.group?.id || "ungrouped";
|
|
1067
|
+
const isCollapsed = collapsedFolders.has(groupId);
|
|
1068
|
+
const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
|
|
1069
|
+
return /* @__PURE__ */ jsxs("div", { className: "border border-zinc-700 rounded-lg overflow-hidden", children: [
|
|
1070
|
+
/* @__PURE__ */ jsxs(
|
|
1071
|
+
"button",
|
|
1072
|
+
{
|
|
1073
|
+
onClick: () => toggleFolderCollapse(groupId),
|
|
1074
|
+
className: "w-full flex items-center justify-between p-2.5 bg-zinc-800 hover:bg-zinc-700 transition-colors",
|
|
1075
|
+
children: [
|
|
1076
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1077
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm", children: isCollapsed ? "\u{1F4C1}" : "\u{1F4C2}" }),
|
|
1078
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium text-sm text-zinc-100", children: folder.group?.name || "Other Tests" }),
|
|
1079
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-zinc-500", children: [
|
|
1080
|
+
"(",
|
|
1081
|
+
completedCount,
|
|
1082
|
+
"/",
|
|
1083
|
+
folder.stats.total,
|
|
1084
|
+
")"
|
|
1085
|
+
] })
|
|
1086
|
+
] }),
|
|
1087
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1088
|
+
/* @__PURE__ */ jsx2("div", { className: "w-16 h-1.5 bg-zinc-700 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx2(
|
|
1089
|
+
"div",
|
|
1090
|
+
{
|
|
1091
|
+
className: "h-full bg-green-500 transition-all",
|
|
1092
|
+
style: { width: `${completedCount / folder.stats.total * 100}%` }
|
|
1093
|
+
}
|
|
1094
|
+
) }),
|
|
1095
|
+
/* @__PURE__ */ jsx2("span", { className: "text-zinc-500 text-xs", children: isCollapsed ? "\u25B6" : "\u25BC" })
|
|
1096
|
+
] })
|
|
1097
|
+
]
|
|
1098
|
+
}
|
|
1099
|
+
),
|
|
1100
|
+
!isCollapsed && /* @__PURE__ */ jsx2("div", { className: "divide-y divide-zinc-800", children: folder.assignments.map((assignment) => {
|
|
1101
|
+
const statusBadge = getStatusBadge(assignment.status);
|
|
1102
|
+
return /* @__PURE__ */ jsxs(
|
|
1103
|
+
"button",
|
|
1104
|
+
{
|
|
1105
|
+
onClick: () => {
|
|
1106
|
+
setSelectedTestId(assignment.id);
|
|
1107
|
+
setTestView("detail");
|
|
1108
|
+
setShowSteps(false);
|
|
1109
|
+
},
|
|
1110
|
+
className: `w-full text-left p-3 transition-colors ${assignment.id === currentAssignment?.id ? "bg-blue-950/30" : "bg-zinc-900 hover:bg-zinc-800"}`,
|
|
1111
|
+
children: [
|
|
1112
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-1", children: [
|
|
1113
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1114
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-mono text-zinc-500", children: assignment.testCase.testKey }),
|
|
1115
|
+
assignment.isVerification && /* @__PURE__ */ jsx2("span", { className: "text-xs px-1.5 py-0.5 rounded bg-green-900/30 text-green-400 font-medium", children: "\u{1F527} Verify" })
|
|
1116
|
+
] }),
|
|
1117
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
1118
|
+
/* @__PURE__ */ jsxs("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${statusBadge.className}`, children: [
|
|
1119
|
+
statusBadge.icon,
|
|
1120
|
+
" ",
|
|
1121
|
+
statusBadge.label
|
|
1122
|
+
] }),
|
|
1123
|
+
/* @__PURE__ */ jsx2("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${assignment.testCase.priority === "P0" ? "bg-red-900/30 text-red-400" : assignment.testCase.priority === "P1" ? "bg-orange-900/30 text-orange-400" : "bg-zinc-700 text-zinc-400"}`, children: assignment.testCase.priority })
|
|
1124
|
+
] })
|
|
1125
|
+
] }),
|
|
1126
|
+
/* @__PURE__ */ jsx2("h4", { className: "font-medium text-zinc-100 text-sm line-clamp-2", children: assignment.testCase.title }),
|
|
1127
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1 text-xs text-zinc-500", children: [
|
|
1128
|
+
assignment.testCase.track && /* @__PURE__ */ jsx2(
|
|
1129
|
+
"span",
|
|
1130
|
+
{
|
|
1131
|
+
className: "px-1 py-0.5 rounded text-white",
|
|
1132
|
+
style: { backgroundColor: assignment.testCase.track.color },
|
|
1133
|
+
children: templateInfo[assignment.testCase.track.testTemplate || "steps"].icon
|
|
1134
|
+
}
|
|
1135
|
+
),
|
|
1136
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1137
|
+
assignment.testCase.steps.length,
|
|
1138
|
+
" ",
|
|
1139
|
+
assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"
|
|
1140
|
+
] }),
|
|
1141
|
+
assignment.id === currentAssignment?.id && /* @__PURE__ */ jsx2("span", { className: "text-blue-400 font-medium", children: "\u2022 Current" })
|
|
1142
|
+
] })
|
|
1143
|
+
]
|
|
1144
|
+
},
|
|
1145
|
+
assignment.id
|
|
1146
|
+
);
|
|
1147
|
+
}) })
|
|
1148
|
+
] }, groupId);
|
|
1149
|
+
})
|
|
1150
|
+
] })
|
|
1151
|
+
) : showFeedbackPrompt && displayedAssignment ? (
|
|
1152
|
+
/* Feedback prompt after completing a test */
|
|
1153
|
+
/* @__PURE__ */ jsxs("div", { className: "p-3", children: [
|
|
1154
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center mb-4", children: [
|
|
1155
|
+
/* @__PURE__ */ jsx2("span", { className: "text-3xl", children: pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717" }),
|
|
1156
|
+
/* @__PURE__ */ jsx2("p", { className: `font-semibold mt-1 ${pendingFeedbackStatus === "passed" ? "text-green-400" : "text-red-400"}`, children: pendingFeedbackStatus === "passed" ? "Test Passed!" : "Test Failed" })
|
|
1157
|
+
] }),
|
|
1158
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-blue-950/30 border border-blue-900 rounded-lg p-3 mb-4", children: [
|
|
1159
|
+
/* @__PURE__ */ jsx2("p", { className: "text-blue-300 text-sm font-medium mb-1", children: "Help us improve this test" }),
|
|
1160
|
+
/* @__PURE__ */ jsx2("p", { className: "text-blue-400 text-xs", children: "Your feedback shapes better tests for everyone." })
|
|
1161
|
+
] }),
|
|
1162
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1163
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-400 mb-2", children: "How was this test?" }),
|
|
1164
|
+
/* @__PURE__ */ jsx2("div", { className: "flex items-center gap-1 justify-center", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx2(
|
|
1165
|
+
"button",
|
|
1166
|
+
{
|
|
1167
|
+
type: "button",
|
|
1168
|
+
onClick: () => setFeedbackRating(star),
|
|
1169
|
+
className: `text-2xl transition-colors ${star <= feedbackRating ? "text-yellow-400" : "text-zinc-600"} hover:text-yellow-400`,
|
|
1170
|
+
children: "\u2605"
|
|
524
1171
|
},
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
1172
|
+
star
|
|
1173
|
+
)) }),
|
|
1174
|
+
/* @__PURE__ */ jsx2("p", { className: "text-center text-xs text-zinc-500 mt-1", children: feedbackRating === 1 ? "Needs work" : feedbackRating === 2 ? "Could be better" : feedbackRating === 3 ? "Okay" : feedbackRating === 4 ? "Good" : "Great!" })
|
|
1175
|
+
] }),
|
|
1176
|
+
feedbackRating < 4 && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1177
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-400 mb-2", children: "What could be improved?" }),
|
|
1178
|
+
/* @__PURE__ */ jsx2("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
1179
|
+
{ key: "stepsUnclear", label: "Steps unclear" },
|
|
1180
|
+
{ key: "expectedResultUnclear", label: "Expected result unclear" },
|
|
1181
|
+
{ key: "needsMoreDetail", label: "Needs more detail" },
|
|
1182
|
+
{ key: "isOutdated", label: "Seems outdated" }
|
|
1183
|
+
].map(({ key, label }) => /* @__PURE__ */ jsx2(
|
|
1184
|
+
"button",
|
|
1185
|
+
{
|
|
1186
|
+
type: "button",
|
|
1187
|
+
onClick: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
|
|
1188
|
+
className: `px-2 py-1.5 rounded text-xs font-medium border transition-colors ${feedbackFlags[key] ? "bg-blue-900/50 border-blue-700 text-blue-300" : "bg-zinc-800 border-zinc-700 text-zinc-400 hover:border-blue-800"}`,
|
|
1189
|
+
children: label
|
|
1190
|
+
},
|
|
1191
|
+
key
|
|
1192
|
+
)) })
|
|
1193
|
+
] }),
|
|
1194
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1195
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-400 mb-1", children: "Suggestions? (optional)" }),
|
|
1196
|
+
/* @__PURE__ */ jsx2(
|
|
1197
|
+
"textarea",
|
|
1198
|
+
{
|
|
1199
|
+
value: feedbackNote,
|
|
1200
|
+
onChange: (e) => setFeedbackNote(e.target.value),
|
|
1201
|
+
placeholder: "How could this test be improved?",
|
|
1202
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-700 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent placeholder:text-zinc-500",
|
|
1203
|
+
rows: 2
|
|
1204
|
+
}
|
|
1205
|
+
)
|
|
1206
|
+
] }),
|
|
1207
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
1208
|
+
/* @__PURE__ */ jsx2(
|
|
1209
|
+
"button",
|
|
1210
|
+
{
|
|
1211
|
+
onClick: handleSkipFeedback,
|
|
1212
|
+
disabled: submitting,
|
|
1213
|
+
className: "flex-1 px-3 py-2 text-sm font-medium text-zinc-400 bg-zinc-700 rounded-lg hover:bg-zinc-700 transition-colors disabled:opacity-50",
|
|
1214
|
+
children: "Skip"
|
|
1215
|
+
}
|
|
1216
|
+
),
|
|
1217
|
+
/* @__PURE__ */ jsx2(
|
|
1218
|
+
"button",
|
|
1219
|
+
{
|
|
1220
|
+
onClick: () => handleSubmitFeedback(false),
|
|
1221
|
+
disabled: submitting,
|
|
1222
|
+
className: "flex-1 px-3 py-2 text-sm font-medium text-white bg-blue-500 rounded-lg hover:bg-blue-600 transition-colors disabled:opacity-50",
|
|
1223
|
+
children: submitting ? "Submitting..." : "Submit Feedback"
|
|
1224
|
+
}
|
|
1225
|
+
)
|
|
1226
|
+
] })
|
|
552
1227
|
] })
|
|
553
1228
|
) : justPassed ? (
|
|
554
1229
|
/* Success state after passing */
|
|
555
1230
|
/* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
556
1231
|
/* @__PURE__ */ jsx2("span", { className: "text-5xl", children: "\u2713" }),
|
|
557
|
-
/* @__PURE__ */ jsx2("p", { className: "text-green-
|
|
558
|
-
/* @__PURE__ */ jsx2("p", { className: "text-
|
|
1232
|
+
/* @__PURE__ */ jsx2("p", { className: "text-green-400 mt-3 font-semibold text-lg", children: "Passed!" }),
|
|
1233
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-sm mt-1", children: "Loading next test..." })
|
|
559
1234
|
] })
|
|
560
1235
|
) : displayedAssignment ? (
|
|
561
1236
|
/* Detail View - Show single test */
|
|
@@ -567,7 +1242,7 @@ function BugBearPanel({
|
|
|
567
1242
|
setTestView("list");
|
|
568
1243
|
setSelectedTestId(null);
|
|
569
1244
|
},
|
|
570
|
-
className: "flex items-center gap-1 text-xs text-
|
|
1245
|
+
className: "flex items-center gap-1 text-xs text-blue-400 font-medium hover:text-blue-300 mb-2",
|
|
571
1246
|
children: [
|
|
572
1247
|
"\u2190 All Tests (",
|
|
573
1248
|
assignments.length,
|
|
@@ -575,9 +1250,53 @@ function BugBearPanel({
|
|
|
575
1250
|
]
|
|
576
1251
|
}
|
|
577
1252
|
),
|
|
578
|
-
|
|
1253
|
+
(() => {
|
|
1254
|
+
const currentGroup = displayedAssignment.testCase.group;
|
|
1255
|
+
const groupAssignments = currentGroup ? assignments.filter((a) => a.testCase.group?.id === currentGroup.id) : assignments;
|
|
1256
|
+
const completed = groupAssignments.filter(
|
|
1257
|
+
(a) => a.status === "passed" || a.status === "failed" || a.status === "skipped"
|
|
1258
|
+
).length;
|
|
1259
|
+
const total = groupAssignments.length;
|
|
1260
|
+
const progressPercent = total > 0 ? completed / total * 100 : 0;
|
|
1261
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-3 p-2 bg-blue-950/30 rounded-lg", children: [
|
|
1262
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
|
|
1263
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-medium text-blue-300", children: currentGroup ? `\u{1F4C1} ${currentGroup.name}` : "\u{1F4CB} All Tests" }),
|
|
1264
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-blue-400", children: [
|
|
1265
|
+
completed,
|
|
1266
|
+
"/",
|
|
1267
|
+
total,
|
|
1268
|
+
" complete"
|
|
1269
|
+
] })
|
|
1270
|
+
] }),
|
|
1271
|
+
/* @__PURE__ */ jsx2("div", { className: "w-full h-2 bg-zinc-700 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx2(
|
|
1272
|
+
"div",
|
|
1273
|
+
{
|
|
1274
|
+
className: "h-full bg-blue-500 transition-all duration-300",
|
|
1275
|
+
style: { width: `${progressPercent}%` }
|
|
1276
|
+
}
|
|
1277
|
+
) }),
|
|
1278
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between mt-1 text-[10px] text-blue-400", children: [
|
|
1279
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1280
|
+
"\u2705 ",
|
|
1281
|
+
groupAssignments.filter((a) => a.status === "passed").length,
|
|
1282
|
+
" passed"
|
|
1283
|
+
] }),
|
|
1284
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1285
|
+
"\u274C ",
|
|
1286
|
+
groupAssignments.filter((a) => a.status === "failed").length,
|
|
1287
|
+
" failed"
|
|
1288
|
+
] }),
|
|
1289
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
1290
|
+
"\u23ED\uFE0F ",
|
|
1291
|
+
groupAssignments.filter((a) => a.status === "skipped").length,
|
|
1292
|
+
" skipped"
|
|
1293
|
+
] })
|
|
1294
|
+
] })
|
|
1295
|
+
] });
|
|
1296
|
+
})(),
|
|
1297
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
|
|
579
1298
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
|
|
580
|
-
/* @__PURE__ */ jsx2("span", { className: "text-xs font-mono text-
|
|
1299
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs font-mono text-zinc-500", children: displayedAssignment.testCase.testKey }),
|
|
581
1300
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
582
1301
|
displayedAssignment.testCase.track && /* @__PURE__ */ jsx2(
|
|
583
1302
|
"span",
|
|
@@ -587,16 +1306,24 @@ function BugBearPanel({
|
|
|
587
1306
|
children: templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon
|
|
588
1307
|
}
|
|
589
1308
|
),
|
|
590
|
-
/* @__PURE__ */ jsx2("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${displayedAssignment.testCase.priority === "P0" ? "bg-red-
|
|
1309
|
+
/* @__PURE__ */ jsx2("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${displayedAssignment.testCase.priority === "P0" ? "bg-red-900/30 text-red-400" : displayedAssignment.testCase.priority === "P1" ? "bg-orange-900/30 text-orange-400" : "bg-zinc-700 text-zinc-400"}`, children: displayedAssignment.testCase.priority })
|
|
591
1310
|
] })
|
|
592
1311
|
] }),
|
|
593
|
-
/* @__PURE__ */ jsx2("h4", { className: "font-medium text-
|
|
594
|
-
displayedAssignment.
|
|
1312
|
+
/* @__PURE__ */ jsx2("h4", { className: "font-medium text-zinc-100 text-sm mb-1", children: displayedAssignment.testCase.title }),
|
|
1313
|
+
displayedAssignment.status === "in_progress" && displayedAssignment.startedAt && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mb-2 text-xs text-green-400 bg-green-900/20 px-2 py-1 rounded", children: [
|
|
1314
|
+
/* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
1315
|
+
/* @__PURE__ */ jsx2("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
|
|
1316
|
+
/* @__PURE__ */ jsx2("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500" })
|
|
1317
|
+
] }),
|
|
1318
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: "Testing" }),
|
|
1319
|
+
/* @__PURE__ */ jsx2("span", { className: "font-mono", children: formatElapsedTime(assignmentElapsedTime) })
|
|
1320
|
+
] }),
|
|
1321
|
+
displayedAssignment.testCase.description && /* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-xs mb-2", children: displayedAssignment.testCase.description }),
|
|
595
1322
|
displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ jsxs(
|
|
596
1323
|
"button",
|
|
597
1324
|
{
|
|
598
1325
|
onClick: () => onNavigate(displayedAssignment.testCase.targetRoute),
|
|
599
|
-
className: "w-full mb-2 py-1.5 px-3 bg-blue-
|
|
1326
|
+
className: "w-full mb-2 py-1.5 px-3 bg-blue-900/20 text-blue-300 border border-blue-800 rounded-lg text-xs font-medium hover:bg-blue-900/30 transition-colors flex items-center justify-center gap-1",
|
|
600
1327
|
children: [
|
|
601
1328
|
/* @__PURE__ */ jsx2("span", { children: "Go to test location" }),
|
|
602
1329
|
/* @__PURE__ */ jsx2("span", { children: "\u2192" })
|
|
@@ -619,7 +1346,7 @@ function BugBearPanel({
|
|
|
619
1346
|
children: [
|
|
620
1347
|
/* @__PURE__ */ jsx2("span", { children: info.icon }),
|
|
621
1348
|
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: info.name }),
|
|
622
|
-
/* @__PURE__ */ jsxs("span", { className: "text-
|
|
1349
|
+
/* @__PURE__ */ jsxs("span", { className: "text-zinc-500", children: [
|
|
623
1350
|
"\u2022 ",
|
|
624
1351
|
info.action
|
|
625
1352
|
] })
|
|
@@ -630,7 +1357,7 @@ function BugBearPanel({
|
|
|
630
1357
|
"button",
|
|
631
1358
|
{
|
|
632
1359
|
onClick: () => setShowSteps(!showSteps),
|
|
633
|
-
className: "text-
|
|
1360
|
+
className: "text-blue-400 text-xs font-medium hover:text-blue-300 flex items-center gap-1",
|
|
634
1361
|
children: [
|
|
635
1362
|
showSteps ? "\u25BC" : "\u25B6",
|
|
636
1363
|
" ",
|
|
@@ -639,10 +1366,10 @@ function BugBearPanel({
|
|
|
639
1366
|
}
|
|
640
1367
|
),
|
|
641
1368
|
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: [
|
|
642
|
-
/* @__PURE__ */ jsx2("span", { className: "w-5 h-5 rounded-full bg-
|
|
1369
|
+
/* @__PURE__ */ jsx2("span", { className: "w-5 h-5 rounded-full bg-blue-900/50 text-blue-300 flex items-center justify-center flex-shrink-0 font-medium", children: step.stepNumber }),
|
|
643
1370
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
644
|
-
/* @__PURE__ */ jsx2("p", { className: "text-
|
|
645
|
-
step.expectedResult && /* @__PURE__ */ jsxs("p", { className: "text-
|
|
1371
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-300", children: step.action }),
|
|
1372
|
+
step.expectedResult && /* @__PURE__ */ jsxs("p", { className: "text-zinc-500 mt-0.5", children: [
|
|
646
1373
|
"\u2192 ",
|
|
647
1374
|
step.expectedResult
|
|
648
1375
|
] })
|
|
@@ -661,39 +1388,39 @@ function BugBearPanel({
|
|
|
661
1388
|
}
|
|
662
1389
|
return newResults;
|
|
663
1390
|
}),
|
|
664
|
-
className: `w-full flex items-center gap-2 text-xs p-2 rounded border transition-colors text-left ${criteriaResults[idx] === true ? "bg-green-
|
|
1391
|
+
className: `w-full flex items-center gap-2 text-xs p-2 rounded border transition-colors text-left ${criteriaResults[idx] === true ? "bg-green-900/20 border-green-700" : "bg-zinc-900 border-zinc-700 hover:bg-zinc-800"}`,
|
|
665
1392
|
children: [
|
|
666
1393
|
/* @__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" : "" }),
|
|
667
|
-
/* @__PURE__ */ jsx2("p", { className: `flex-1 ${criteriaResults[idx] === true ? "text-green-
|
|
1394
|
+
/* @__PURE__ */ jsx2("p", { className: `flex-1 ${criteriaResults[idx] === true ? "text-green-400" : "text-zinc-300"}`, children: step.action })
|
|
668
1395
|
]
|
|
669
1396
|
},
|
|
670
1397
|
idx
|
|
671
1398
|
)),
|
|
672
1399
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-2", children: [
|
|
673
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
1400
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500", children: "Tap to check off each item." }),
|
|
674
1401
|
Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ jsx2(
|
|
675
1402
|
"button",
|
|
676
1403
|
{
|
|
677
1404
|
onClick: () => setCriteriaResults({}),
|
|
678
|
-
className: "text-xs text-
|
|
1405
|
+
className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
|
|
679
1406
|
children: "\u21BA Reset"
|
|
680
1407
|
}
|
|
681
1408
|
)
|
|
682
1409
|
] })
|
|
683
1410
|
] }),
|
|
684
1411
|
showSteps && template === "rubric" && /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-2", children: [
|
|
685
|
-
steps.map((step, idx) => /* @__PURE__ */ jsxs("div", { className: "bg-
|
|
1412
|
+
steps.map((step, idx) => /* @__PURE__ */ jsxs("div", { className: "bg-zinc-800 p-2 rounded border border-zinc-700", children: [
|
|
686
1413
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs mb-1", children: [
|
|
687
|
-
/* @__PURE__ */ jsx2("span", { className: "w-5 h-5 rounded bg-
|
|
688
|
-
/* @__PURE__ */ jsx2("p", { className: "text-
|
|
1414
|
+
/* @__PURE__ */ jsx2("span", { className: "w-5 h-5 rounded bg-blue-900/50 text-blue-300 flex items-center justify-center font-medium", children: idx + 1 }),
|
|
1415
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-100 font-medium flex-1", children: step.action })
|
|
689
1416
|
] }),
|
|
690
|
-
step.expectedResult && /* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
1417
|
+
step.expectedResult && /* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500 ml-7 mb-2", children: step.expectedResult }),
|
|
691
1418
|
rubricMode === "pass_fail" && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 ml-7", children: [
|
|
692
1419
|
/* @__PURE__ */ jsx2(
|
|
693
1420
|
"button",
|
|
694
1421
|
{
|
|
695
1422
|
onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: true })),
|
|
696
|
-
className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === true ? "bg-green-500 text-white" : "bg-
|
|
1423
|
+
className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === true ? "bg-green-500 text-white" : "bg-zinc-700 text-zinc-400 hover:bg-green-900/30"}`,
|
|
697
1424
|
children: "\u2713 Pass"
|
|
698
1425
|
}
|
|
699
1426
|
),
|
|
@@ -701,7 +1428,7 @@ function BugBearPanel({
|
|
|
701
1428
|
"button",
|
|
702
1429
|
{
|
|
703
1430
|
onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: false })),
|
|
704
|
-
className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === false ? "bg-red-500 text-white" : "bg-
|
|
1431
|
+
className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === false ? "bg-red-500 text-white" : "bg-zinc-700 text-zinc-400 hover:bg-red-900/30"}`,
|
|
705
1432
|
children: "\u2717 Fail"
|
|
706
1433
|
}
|
|
707
1434
|
)
|
|
@@ -710,28 +1437,28 @@ function BugBearPanel({
|
|
|
710
1437
|
"button",
|
|
711
1438
|
{
|
|
712
1439
|
onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: n })),
|
|
713
|
-
className: `w-8 h-8 rounded font-medium text-sm transition-colors ${criteriaResults[idx] === n ? "bg-
|
|
1440
|
+
className: `w-8 h-8 rounded font-medium text-sm transition-colors ${criteriaResults[idx] === n ? "bg-blue-500 text-white" : "bg-zinc-700 text-zinc-400 hover:bg-blue-900/50"}`,
|
|
714
1441
|
children: n
|
|
715
1442
|
},
|
|
716
1443
|
n
|
|
717
1444
|
)) })
|
|
718
1445
|
] }, idx)),
|
|
719
1446
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-2", children: [
|
|
720
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
1447
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500", children: rubricMode === "rating" ? "Rate 1-5 for each criterion." : "Mark each criterion as Pass or Fail." }),
|
|
721
1448
|
Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ jsx2(
|
|
722
1449
|
"button",
|
|
723
1450
|
{
|
|
724
1451
|
onClick: () => setCriteriaResults({}),
|
|
725
|
-
className: "text-xs text-
|
|
1452
|
+
className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
|
|
726
1453
|
children: "\u21BA Reset"
|
|
727
1454
|
}
|
|
728
1455
|
)
|
|
729
1456
|
] })
|
|
730
1457
|
] }),
|
|
731
|
-
showSteps && template === "freeform" && /* @__PURE__ */ jsxs("div", { className: "mt-2 p-2 bg-amber-
|
|
732
|
-
/* @__PURE__ */ jsx2("p", { className: "text-amber-
|
|
733
|
-
/* @__PURE__ */ jsx2("p", { className: "text-amber-
|
|
734
|
-
/* @__PURE__ */ jsxs("ul", { className: "text-amber-
|
|
1458
|
+
showSteps && template === "freeform" && /* @__PURE__ */ jsxs("div", { className: "mt-2 p-2 bg-amber-900/20 rounded border border-amber-800 text-xs", children: [
|
|
1459
|
+
/* @__PURE__ */ jsx2("p", { className: "text-amber-300 font-medium mb-1", children: "\u{1F4AD} Open Observation" }),
|
|
1460
|
+
/* @__PURE__ */ jsx2("p", { className: "text-amber-400", children: "Review the area described above and note:" }),
|
|
1461
|
+
/* @__PURE__ */ jsxs("ul", { className: "text-amber-400 mt-1 ml-4 list-disc", children: [
|
|
735
1462
|
/* @__PURE__ */ jsx2("li", { children: "What works well" }),
|
|
736
1463
|
/* @__PURE__ */ jsx2("li", { children: "Issues or concerns" }),
|
|
737
1464
|
/* @__PURE__ */ jsx2("li", { children: "Suggestions" })
|
|
@@ -739,7 +1466,7 @@ function BugBearPanel({
|
|
|
739
1466
|
] })
|
|
740
1467
|
] });
|
|
741
1468
|
})(),
|
|
742
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-3 p-2 bg-green-
|
|
1469
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3 p-2 bg-green-900/20 rounded text-xs text-green-400", children: [
|
|
743
1470
|
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:" }),
|
|
744
1471
|
" ",
|
|
745
1472
|
displayedAssignment.testCase.expectedResult
|
|
@@ -750,26 +1477,507 @@ function BugBearPanel({
|
|
|
750
1477
|
"button",
|
|
751
1478
|
{
|
|
752
1479
|
onClick: handleFail,
|
|
753
|
-
disabled: submitting,
|
|
754
|
-
className: "flex-1 py-2 px-3 bg-red-
|
|
1480
|
+
disabled: submitting || skipping,
|
|
1481
|
+
className: "flex-1 py-2 px-3 bg-red-900/30 text-red-400 rounded-lg font-medium text-sm hover:bg-red-800/30 disabled:opacity-50 transition-colors",
|
|
755
1482
|
children: "\u2717 Fail"
|
|
756
1483
|
}
|
|
757
1484
|
),
|
|
1485
|
+
/* @__PURE__ */ jsx2(
|
|
1486
|
+
"button",
|
|
1487
|
+
{
|
|
1488
|
+
onClick: handleOpenSkipModal,
|
|
1489
|
+
disabled: submitting || skipping,
|
|
1490
|
+
className: "py-2 px-3 bg-yellow-900/30 text-yellow-400 rounded-lg font-medium text-sm hover:bg-yellow-800/30 disabled:opacity-50 transition-colors",
|
|
1491
|
+
children: "\u23ED\uFE0F Skip"
|
|
1492
|
+
}
|
|
1493
|
+
),
|
|
758
1494
|
/* @__PURE__ */ jsx2(
|
|
759
1495
|
"button",
|
|
760
1496
|
{
|
|
761
1497
|
onClick: handlePass,
|
|
762
|
-
disabled: submitting,
|
|
1498
|
+
disabled: submitting || skipping,
|
|
763
1499
|
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",
|
|
764
1500
|
children: submitting ? "..." : "\u2713 Pass"
|
|
765
1501
|
}
|
|
766
1502
|
)
|
|
767
|
-
] })
|
|
1503
|
+
] }),
|
|
1504
|
+
showSkipModal && /* @__PURE__ */ jsx2("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", onClick: () => setShowSkipModal(false), children: /* @__PURE__ */ jsxs("div", { className: "bg-zinc-800 rounded-xl p-4 w-72 shadow-xl border border-zinc-700", onClick: (e) => e.stopPropagation(), children: [
|
|
1505
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100 mb-3", children: "Skip Test" }),
|
|
1506
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500 mb-3", children: "Please select a reason for skipping this test." }),
|
|
1507
|
+
/* @__PURE__ */ jsx2("div", { className: "space-y-2 mb-4", children: skipReasonOptions.map((option) => /* @__PURE__ */ jsxs(
|
|
1508
|
+
"button",
|
|
1509
|
+
{
|
|
1510
|
+
onClick: () => setSelectedSkipReason(option.value),
|
|
1511
|
+
className: `w-full text-left p-2.5 rounded-lg border transition-colors ${selectedSkipReason === option.value ? "bg-yellow-900/20 border-yellow-700 text-yellow-300" : "bg-zinc-800 border-zinc-700 text-zinc-300 hover:border-yellow-800"}`,
|
|
1512
|
+
children: [
|
|
1513
|
+
/* @__PURE__ */ jsx2("div", { className: "font-medium text-sm", children: option.label }),
|
|
1514
|
+
/* @__PURE__ */ jsx2("div", { className: "text-xs text-zinc-500", children: option.description })
|
|
1515
|
+
]
|
|
1516
|
+
},
|
|
1517
|
+
option.value
|
|
1518
|
+
)) }),
|
|
1519
|
+
selectedSkipReason === "other" && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1520
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-400 mb-1", children: "Notes (required)" }),
|
|
1521
|
+
/* @__PURE__ */ jsx2(
|
|
1522
|
+
"textarea",
|
|
1523
|
+
{
|
|
1524
|
+
value: skipNotes,
|
|
1525
|
+
onChange: (e) => setSkipNotes(e.target.value),
|
|
1526
|
+
placeholder: "Please explain why you're skipping...",
|
|
1527
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-700 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-transparent placeholder:text-zinc-500",
|
|
1528
|
+
rows: 2
|
|
1529
|
+
}
|
|
1530
|
+
)
|
|
1531
|
+
] }),
|
|
1532
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
1533
|
+
/* @__PURE__ */ jsx2(
|
|
1534
|
+
"button",
|
|
1535
|
+
{
|
|
1536
|
+
onClick: () => setShowSkipModal(false),
|
|
1537
|
+
className: "flex-1 py-2 px-3 text-sm font-medium text-zinc-400 bg-zinc-700 rounded-lg hover:bg-zinc-700 transition-colors",
|
|
1538
|
+
children: "Cancel"
|
|
1539
|
+
}
|
|
1540
|
+
),
|
|
1541
|
+
/* @__PURE__ */ jsx2(
|
|
1542
|
+
"button",
|
|
1543
|
+
{
|
|
1544
|
+
onClick: handleSkip,
|
|
1545
|
+
disabled: !selectedSkipReason || selectedSkipReason === "other" && !skipNotes.trim() || skipping,
|
|
1546
|
+
className: "flex-1 py-2 px-3 text-sm font-medium text-white bg-yellow-500 rounded-lg hover:bg-yellow-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
1547
|
+
children: skipping ? "Skipping..." : "Skip Test"
|
|
1548
|
+
}
|
|
1549
|
+
)
|
|
1550
|
+
] })
|
|
1551
|
+
] }) })
|
|
768
1552
|
] })
|
|
769
1553
|
) : null }),
|
|
1554
|
+
activeTab === "messages" && /* @__PURE__ */ jsx2("div", { children: messageView === "compose" ? (
|
|
1555
|
+
/* Compose New Message */
|
|
1556
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1557
|
+
/* @__PURE__ */ jsx2(
|
|
1558
|
+
"button",
|
|
1559
|
+
{
|
|
1560
|
+
onClick: handleBackToThreadList,
|
|
1561
|
+
className: "text-sm text-zinc-400 hover:text-zinc-200 mb-3 flex items-center gap-1",
|
|
1562
|
+
children: "\u2190 Back to Messages"
|
|
1563
|
+
}
|
|
1564
|
+
),
|
|
1565
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center mb-4", children: [
|
|
1566
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100", children: "New Message" }),
|
|
1567
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-xs mt-1", children: "Send a message to the QA team" })
|
|
1568
|
+
] }),
|
|
1569
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1570
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1571
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Subject" }),
|
|
1572
|
+
/* @__PURE__ */ jsx2(
|
|
1573
|
+
"input",
|
|
1574
|
+
{
|
|
1575
|
+
type: "text",
|
|
1576
|
+
value: composeSubject,
|
|
1577
|
+
onChange: (e) => setComposeSubject(e.target.value),
|
|
1578
|
+
placeholder: "What's this about?",
|
|
1579
|
+
maxLength: 100,
|
|
1580
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500"
|
|
1581
|
+
}
|
|
1582
|
+
)
|
|
1583
|
+
] }),
|
|
1584
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1585
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Message" }),
|
|
1586
|
+
/* @__PURE__ */ jsx2(
|
|
1587
|
+
"textarea",
|
|
1588
|
+
{
|
|
1589
|
+
value: composeMessage,
|
|
1590
|
+
onChange: (e) => setComposeMessage(e.target.value),
|
|
1591
|
+
placeholder: "Write your message...",
|
|
1592
|
+
maxLength: 2e3,
|
|
1593
|
+
rows: 6,
|
|
1594
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500 resize-none"
|
|
1595
|
+
}
|
|
1596
|
+
)
|
|
1597
|
+
] }),
|
|
1598
|
+
/* @__PURE__ */ jsx2(
|
|
1599
|
+
"button",
|
|
1600
|
+
{
|
|
1601
|
+
onClick: handleSendNewMessage,
|
|
1602
|
+
disabled: !composeSubject.trim() || !composeMessage.trim() || sendingNewMessage,
|
|
1603
|
+
className: "w-full py-2 px-4 bg-blue-500 text-white rounded-lg font-medium text-sm hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
1604
|
+
children: sendingNewMessage ? "Sending..." : "Send Message"
|
|
1605
|
+
}
|
|
1606
|
+
)
|
|
1607
|
+
] })
|
|
1608
|
+
] })
|
|
1609
|
+
) : messageView === "thread" && selectedThread ? (
|
|
1610
|
+
/* Thread Detail View */
|
|
1611
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1612
|
+
/* @__PURE__ */ jsx2(
|
|
1613
|
+
"button",
|
|
1614
|
+
{
|
|
1615
|
+
onClick: handleBackToThreadList,
|
|
1616
|
+
className: "text-sm text-zinc-400 hover:text-zinc-200 mb-3 flex items-center gap-1",
|
|
1617
|
+
children: "\u2190 Back to Messages"
|
|
1618
|
+
}
|
|
1619
|
+
),
|
|
1620
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-4 pb-3 border-b border-zinc-700", children: [
|
|
1621
|
+
/* @__PURE__ */ jsx2("span", { className: "text-lg", children: getThreadTypeIcon(selectedThread.threadType) }),
|
|
1622
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100 text-sm leading-tight", children: selectedThread.subject || "No subject" })
|
|
1623
|
+
] }),
|
|
1624
|
+
loadingMessages ? /* @__PURE__ */ jsx2("div", { className: "text-center py-6", children: /* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-sm", children: "Loading messages..." }) }) : /* @__PURE__ */ jsx2("div", { className: "space-y-3 mb-4", children: threadMessages.map((message) => /* @__PURE__ */ jsxs(
|
|
1625
|
+
"div",
|
|
1626
|
+
{
|
|
1627
|
+
className: `p-3 rounded-lg ${message.senderType === "tester" ? "bg-blue-900/30 border border-blue-800 ml-6" : "bg-zinc-800 border border-zinc-700 mr-6"}`,
|
|
1628
|
+
children: [
|
|
1629
|
+
/* @__PURE__ */ jsx2("p", { className: `text-xs font-medium mb-1 ${message.senderType === "tester" ? "text-blue-300" : "text-zinc-300"}`, children: message.senderType === "tester" ? "You" : message.senderName }),
|
|
1630
|
+
/* @__PURE__ */ jsx2("p", { className: `text-sm ${message.senderType === "tester" ? "text-blue-100" : "text-zinc-200"}`, children: message.content }),
|
|
1631
|
+
/* @__PURE__ */ jsx2("p", { className: `text-[10px] mt-1 ${message.senderType === "tester" ? "text-blue-400/60" : "text-zinc-500"}`, children: formatMessageTime(message.createdAt) })
|
|
1632
|
+
]
|
|
1633
|
+
},
|
|
1634
|
+
message.id
|
|
1635
|
+
)) }),
|
|
1636
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2 pt-3 border-t border-zinc-700", children: [
|
|
1637
|
+
/* @__PURE__ */ jsx2(
|
|
1638
|
+
"input",
|
|
1639
|
+
{
|
|
1640
|
+
type: "text",
|
|
1641
|
+
value: replyText,
|
|
1642
|
+
onChange: (e) => setReplyText(e.target.value),
|
|
1643
|
+
placeholder: "Type a reply...",
|
|
1644
|
+
maxLength: 1e3,
|
|
1645
|
+
className: "flex-1 px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500",
|
|
1646
|
+
onKeyDown: (e) => e.key === "Enter" && !e.shiftKey && handleSendReply()
|
|
1647
|
+
}
|
|
1648
|
+
),
|
|
1649
|
+
/* @__PURE__ */ jsx2(
|
|
1650
|
+
"button",
|
|
1651
|
+
{
|
|
1652
|
+
onClick: handleSendReply,
|
|
1653
|
+
disabled: !replyText.trim() || sendingReply,
|
|
1654
|
+
className: "px-3 py-2 bg-blue-500 text-white text-sm rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
1655
|
+
children: sendingReply ? "..." : "Send"
|
|
1656
|
+
}
|
|
1657
|
+
)
|
|
1658
|
+
] })
|
|
1659
|
+
] })
|
|
1660
|
+
) : (
|
|
1661
|
+
/* Thread List View */
|
|
1662
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1663
|
+
/* @__PURE__ */ jsx2(
|
|
1664
|
+
"button",
|
|
1665
|
+
{
|
|
1666
|
+
onClick: handleStartNewMessage,
|
|
1667
|
+
className: "w-full flex items-center justify-center gap-2 py-2 px-4 mb-3 bg-blue-500 text-white rounded-lg font-medium text-sm hover:bg-blue-600 transition-colors",
|
|
1668
|
+
children: "\u2709\uFE0F New Message"
|
|
1669
|
+
}
|
|
1670
|
+
),
|
|
1671
|
+
threads.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
1672
|
+
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u{1F4AC}" }),
|
|
1673
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-400 mt-2 font-medium", children: "No messages yet" }),
|
|
1674
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-sm", children: "Start a conversation or wait for messages from admins" })
|
|
1675
|
+
] }) : /* @__PURE__ */ jsx2("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ jsxs(
|
|
1676
|
+
"button",
|
|
1677
|
+
{
|
|
1678
|
+
onClick: () => handleOpenThread(thread),
|
|
1679
|
+
className: `w-full text-left p-3 rounded-lg border transition-colors ${thread.unreadCount > 0 ? "bg-blue-900/20 border-blue-800 hover:bg-blue-900/30" : "bg-zinc-800 border-zinc-700 hover:bg-zinc-700"}`,
|
|
1680
|
+
children: [
|
|
1681
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
1682
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 min-w-0 flex-1", children: [
|
|
1683
|
+
thread.isPinned && /* @__PURE__ */ jsx2("span", { className: "text-xs", children: "\u{1F4CC}" }),
|
|
1684
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs", children: getThreadTypeIcon(thread.threadType) }),
|
|
1685
|
+
/* @__PURE__ */ jsx2("span", { className: `text-sm truncate ${thread.unreadCount > 0 ? "font-semibold text-zinc-100" : "text-zinc-300"}`, children: thread.subject || "No subject" })
|
|
1686
|
+
] }),
|
|
1687
|
+
(thread.priority === "high" || thread.priority === "urgent") && /* @__PURE__ */ jsx2("span", { className: `w-2 h-2 rounded-full flex-shrink-0 ml-2 ${thread.priority === "urgent" ? "bg-red-500" : "bg-orange-500"}` })
|
|
1688
|
+
] }),
|
|
1689
|
+
thread.lastMessage && /* @__PURE__ */ jsxs("p", { className: "text-xs text-zinc-500 truncate", children: [
|
|
1690
|
+
thread.lastMessage.senderName,
|
|
1691
|
+
": ",
|
|
1692
|
+
thread.lastMessage.content
|
|
1693
|
+
] }),
|
|
1694
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-1.5", children: [
|
|
1695
|
+
thread.unreadCount > 0 ? /* @__PURE__ */ jsxs("span", { className: "text-[10px] px-1.5 py-0.5 bg-blue-500 text-white rounded-full font-medium", children: [
|
|
1696
|
+
thread.unreadCount,
|
|
1697
|
+
" new"
|
|
1698
|
+
] }) : /* @__PURE__ */ jsx2("span", { className: "text-[10px] text-zinc-600", children: "Read" }),
|
|
1699
|
+
/* @__PURE__ */ jsx2("span", { className: "text-[10px] text-zinc-600", children: formatRelativeTime(thread.lastMessageAt) })
|
|
1700
|
+
] })
|
|
1701
|
+
]
|
|
1702
|
+
},
|
|
1703
|
+
thread.id
|
|
1704
|
+
)) })
|
|
1705
|
+
] })
|
|
1706
|
+
) }),
|
|
1707
|
+
activeTab === "session" && /* @__PURE__ */ jsx2("div", { children: !activeSession ? (
|
|
1708
|
+
/* Start Session View */
|
|
1709
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1710
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center mb-4", children: [
|
|
1711
|
+
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u{1F50D}" }),
|
|
1712
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100 mt-2", children: "Exploratory QA Session" }),
|
|
1713
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-xs mt-1", children: "Explore freely and capture findings as you go" })
|
|
1714
|
+
] }),
|
|
1715
|
+
focusAreas.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1716
|
+
/* @__PURE__ */ jsxs("label", { className: "block text-xs font-medium text-zinc-300 mb-2", children: [
|
|
1717
|
+
"\u{1F4CC} Focus Areas",
|
|
1718
|
+
/* @__PURE__ */ jsx2("span", { className: "ml-1 text-[10px] text-zinc-500 font-normal", children: "from your team" })
|
|
1719
|
+
] }),
|
|
1720
|
+
/* @__PURE__ */ jsx2("div", { className: "space-y-1.5", children: focusAreas.map((area) => /* @__PURE__ */ jsxs(
|
|
1721
|
+
"button",
|
|
1722
|
+
{
|
|
1723
|
+
onClick: () => setSessionFocusArea(area.name),
|
|
1724
|
+
className: `w-full text-left px-3 py-2 rounded-lg text-xs transition-colors border ${sessionFocusArea === area.name ? "bg-amber-900/20 border-amber-700 text-amber-400" : "bg-amber-900/20/50 border-amber-800 text-zinc-300 hover:bg-amber-900/20"}`,
|
|
1725
|
+
children: [
|
|
1726
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1727
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium", children: area.name }),
|
|
1728
|
+
/* @__PURE__ */ jsx2("span", { className: `text-[10px] px-1.5 py-0.5 rounded ${area.priority >= 70 ? "bg-red-900/30 text-red-400" : area.priority >= 50 ? "bg-amber-900/30 text-amber-400" : "bg-zinc-700 text-zinc-500"}`, children: area.priority >= 70 ? "Urgent" : area.priority >= 50 ? "Important" : "Suggested" })
|
|
1729
|
+
] }),
|
|
1730
|
+
area.description && /* @__PURE__ */ jsx2("p", { className: "text-[10px] text-zinc-500 mt-0.5 line-clamp-2", children: area.description })
|
|
1731
|
+
]
|
|
1732
|
+
},
|
|
1733
|
+
area.id
|
|
1734
|
+
)) })
|
|
1735
|
+
] }),
|
|
1736
|
+
suggestedRoutes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1737
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-2", children: "\u{1F3AF} Suggested Routes to Explore" }),
|
|
1738
|
+
/* @__PURE__ */ jsx2("div", { className: "space-y-1.5 max-h-32 overflow-y-auto", children: suggestedRoutes.map((suggestion, idx) => /* @__PURE__ */ jsx2(
|
|
1739
|
+
"button",
|
|
1740
|
+
{
|
|
1741
|
+
onClick: () => setSessionFocusArea(suggestion.route),
|
|
1742
|
+
className: `w-full text-left px-3 py-2 rounded-lg text-xs transition-colors border ${sessionFocusArea === suggestion.route ? "bg-blue-950/30 border-blue-700 text-blue-300" : "bg-zinc-800 border-zinc-700 text-zinc-300 hover:bg-zinc-700"}`,
|
|
1743
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1744
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium truncate", children: suggestion.route }),
|
|
1745
|
+
/* @__PURE__ */ jsx2("span", { className: `text-[10px] px-1.5 py-0.5 rounded ${suggestion.priorityScore >= 40 ? "bg-red-900/30 text-red-400" : suggestion.priorityScore >= 25 ? "bg-amber-900/30 text-amber-400" : "bg-zinc-700 text-zinc-500"}`, children: suggestion.reason })
|
|
1746
|
+
] })
|
|
1747
|
+
},
|
|
1748
|
+
idx
|
|
1749
|
+
)) })
|
|
1750
|
+
] }),
|
|
1751
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
1752
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Focus Area (optional)" }),
|
|
1753
|
+
/* @__PURE__ */ jsx2(
|
|
1754
|
+
"input",
|
|
1755
|
+
{
|
|
1756
|
+
type: "text",
|
|
1757
|
+
value: sessionFocusArea,
|
|
1758
|
+
onChange: (e) => setSessionFocusArea(e.target.value),
|
|
1759
|
+
placeholder: "e.g., checkout flow, settings page",
|
|
1760
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500"
|
|
1761
|
+
}
|
|
1762
|
+
)
|
|
1763
|
+
] }),
|
|
1764
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1765
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Platform" }),
|
|
1766
|
+
/* @__PURE__ */ jsx2("div", { className: "flex gap-2", children: [
|
|
1767
|
+
{ key: "web", label: "\u{1F310} Web" },
|
|
1768
|
+
{ key: "ios", label: "\u{1F4F1} iOS" },
|
|
1769
|
+
{ key: "android", label: "\u{1F916} Android" }
|
|
1770
|
+
].map(({ key, label }) => /* @__PURE__ */ jsx2(
|
|
1771
|
+
"button",
|
|
1772
|
+
{
|
|
1773
|
+
onClick: () => setSessionPlatform(key),
|
|
1774
|
+
className: `flex-1 py-2 px-3 rounded-lg text-xs font-medium transition-colors border-2 ${sessionPlatform === key ? "bg-blue-950/30 border-blue-500 text-blue-300" : "bg-zinc-800 border-transparent text-zinc-400 hover:bg-zinc-700"}`,
|
|
1775
|
+
children: label
|
|
1776
|
+
},
|
|
1777
|
+
key
|
|
1778
|
+
)) })
|
|
1779
|
+
] }),
|
|
1780
|
+
/* @__PURE__ */ jsx2(
|
|
1781
|
+
"button",
|
|
1782
|
+
{
|
|
1783
|
+
onClick: handleStartSession,
|
|
1784
|
+
disabled: startingSession,
|
|
1785
|
+
className: "w-full py-3 px-4 bg-green-600 text-white rounded-lg font-semibold text-sm hover:bg-green-700 disabled:opacity-50 transition-colors flex items-center justify-center gap-2",
|
|
1786
|
+
children: startingSession ? "Starting..." : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1787
|
+
/* @__PURE__ */ jsx2("span", { children: "\u25B6" }),
|
|
1788
|
+
" Start Session"
|
|
1789
|
+
] })
|
|
1790
|
+
}
|
|
1791
|
+
)
|
|
1792
|
+
] })
|
|
1793
|
+
) : showEndConfirm ? (
|
|
1794
|
+
/* End Session Confirmation */
|
|
1795
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1796
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center mb-4", children: [
|
|
1797
|
+
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u270B" }),
|
|
1798
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100 mt-2", children: "End Session?" }),
|
|
1799
|
+
/* @__PURE__ */ jsxs("p", { className: "text-zinc-500 text-xs mt-1", children: [
|
|
1800
|
+
"Duration: ",
|
|
1801
|
+
formatElapsedTime(sessionElapsedTime),
|
|
1802
|
+
" \u2022 ",
|
|
1803
|
+
sessionFindings.length,
|
|
1804
|
+
" finding",
|
|
1805
|
+
sessionFindings.length !== 1 ? "s" : ""
|
|
1806
|
+
] })
|
|
1807
|
+
] }),
|
|
1808
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
1809
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Session Notes (optional)" }),
|
|
1810
|
+
/* @__PURE__ */ jsx2(
|
|
1811
|
+
"textarea",
|
|
1812
|
+
{
|
|
1813
|
+
value: sessionNotes,
|
|
1814
|
+
onChange: (e) => setSessionNotes(e.target.value),
|
|
1815
|
+
placeholder: "Any overall observations from this session...",
|
|
1816
|
+
rows: 3,
|
|
1817
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500 resize-none"
|
|
1818
|
+
}
|
|
1819
|
+
)
|
|
1820
|
+
] }),
|
|
1821
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
1822
|
+
/* @__PURE__ */ jsx2(
|
|
1823
|
+
"button",
|
|
1824
|
+
{
|
|
1825
|
+
onClick: () => setShowEndConfirm(false),
|
|
1826
|
+
className: "flex-1 py-2 px-3 bg-zinc-700 text-zinc-300 rounded-lg font-medium text-sm hover:bg-zinc-700 transition-colors",
|
|
1827
|
+
children: "Cancel"
|
|
1828
|
+
}
|
|
1829
|
+
),
|
|
1830
|
+
/* @__PURE__ */ jsx2(
|
|
1831
|
+
"button",
|
|
1832
|
+
{
|
|
1833
|
+
onClick: handleEndSession,
|
|
1834
|
+
disabled: endingSession,
|
|
1835
|
+
className: "flex-1 py-2 px-3 bg-red-600 text-white rounded-lg font-medium text-sm hover:bg-red-700 disabled:opacity-50 transition-colors",
|
|
1836
|
+
children: endingSession ? "Ending..." : "End Session"
|
|
1837
|
+
}
|
|
1838
|
+
)
|
|
1839
|
+
] })
|
|
1840
|
+
] })
|
|
1841
|
+
) : showAddFinding ? (
|
|
1842
|
+
/* Add Finding Form */
|
|
1843
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1844
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
1845
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100 text-sm", children: "Add Finding" }),
|
|
1846
|
+
/* @__PURE__ */ jsx2(
|
|
1847
|
+
"button",
|
|
1848
|
+
{
|
|
1849
|
+
onClick: () => setShowAddFinding(false),
|
|
1850
|
+
className: "text-zinc-500 hover:text-zinc-400",
|
|
1851
|
+
children: "\u2715"
|
|
1852
|
+
}
|
|
1853
|
+
)
|
|
1854
|
+
] }),
|
|
1855
|
+
/* @__PURE__ */ jsx2("div", { className: "flex gap-1 mb-3", children: [
|
|
1856
|
+
{ type: "bug", label: "\u{1F41B} Bug", color: "red" },
|
|
1857
|
+
{ type: "concern", label: "\u26A0\uFE0F Concern", color: "orange" },
|
|
1858
|
+
{ type: "suggestion", label: "\u{1F4A1} Idea", color: "blue" },
|
|
1859
|
+
{ type: "question", label: "\u2753 Question", color: "purple" }
|
|
1860
|
+
].map(({ type, label, color }) => /* @__PURE__ */ jsx2(
|
|
1861
|
+
"button",
|
|
1862
|
+
{
|
|
1863
|
+
onClick: () => setFindingType(type),
|
|
1864
|
+
className: `flex-1 py-1.5 px-2 rounded text-xs font-medium transition-colors ${findingType === type ? color === "red" ? "bg-red-900/30 text-red-400 ring-2 ring-red-400" : color === "orange" ? "bg-orange-900/30 text-orange-400 ring-2 ring-orange-400" : color === "blue" ? "bg-blue-900/30 text-blue-300 ring-2 ring-blue-400" : "bg-blue-900/50 text-blue-300 ring-2 ring-blue-400" : "bg-zinc-700 text-zinc-400 hover:bg-zinc-700"}`,
|
|
1865
|
+
children: label
|
|
1866
|
+
},
|
|
1867
|
+
type
|
|
1868
|
+
)) }),
|
|
1869
|
+
findingType === "bug" && /* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
1870
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Severity" }),
|
|
1871
|
+
/* @__PURE__ */ jsx2("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low", "observation"].map((sev) => /* @__PURE__ */ jsx2(
|
|
1872
|
+
"button",
|
|
1873
|
+
{
|
|
1874
|
+
onClick: () => setFindingSeverity(sev),
|
|
1875
|
+
className: `flex-1 py-1 px-1 rounded text-xs font-medium capitalize transition-colors ${findingSeverity === sev ? sev === "critical" ? "bg-red-600 text-white" : sev === "high" ? "bg-orange-500 text-white" : sev === "medium" ? "bg-yellow-500 text-black" : sev === "low" ? "bg-zinc-8000 text-white" : "bg-blue-500 text-white" : "bg-zinc-700 text-zinc-400 hover:bg-zinc-700"}`,
|
|
1876
|
+
children: sev === "observation" ? "obs" : sev
|
|
1877
|
+
},
|
|
1878
|
+
sev
|
|
1879
|
+
)) })
|
|
1880
|
+
] }),
|
|
1881
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
1882
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Title *" }),
|
|
1883
|
+
/* @__PURE__ */ jsx2(
|
|
1884
|
+
"input",
|
|
1885
|
+
{
|
|
1886
|
+
type: "text",
|
|
1887
|
+
value: findingTitle,
|
|
1888
|
+
onChange: (e) => setFindingTitle(e.target.value),
|
|
1889
|
+
placeholder: "Brief description of what you found",
|
|
1890
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500"
|
|
1891
|
+
}
|
|
1892
|
+
)
|
|
1893
|
+
] }),
|
|
1894
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
1895
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Details (optional)" }),
|
|
1896
|
+
/* @__PURE__ */ jsx2(
|
|
1897
|
+
"textarea",
|
|
1898
|
+
{
|
|
1899
|
+
value: findingDescription,
|
|
1900
|
+
onChange: (e) => setFindingDescription(e.target.value),
|
|
1901
|
+
placeholder: "Steps to reproduce, expected behavior, etc.",
|
|
1902
|
+
rows: 2,
|
|
1903
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500 resize-none"
|
|
1904
|
+
}
|
|
1905
|
+
)
|
|
1906
|
+
] }),
|
|
1907
|
+
/* @__PURE__ */ jsx2(
|
|
1908
|
+
"button",
|
|
1909
|
+
{
|
|
1910
|
+
onClick: handleAddFinding,
|
|
1911
|
+
disabled: addingFinding || !findingTitle.trim(),
|
|
1912
|
+
className: "w-full py-2 px-4 bg-blue-500 text-white rounded-lg font-medium text-sm hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
1913
|
+
children: addingFinding ? "Adding..." : "Add Finding"
|
|
1914
|
+
}
|
|
1915
|
+
)
|
|
1916
|
+
] })
|
|
1917
|
+
) : (
|
|
1918
|
+
/* Active Session View */
|
|
1919
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1920
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-green-900/20 rounded-lg p-3 mb-3 border border-green-800", children: [
|
|
1921
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1922
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1923
|
+
/* @__PURE__ */ jsx2("span", { className: "w-2 h-2 bg-green-500 rounded-full animate-pulse" }),
|
|
1924
|
+
/* @__PURE__ */ jsx2("span", { className: "font-medium text-green-300 text-sm", children: "Session Active" })
|
|
1925
|
+
] }),
|
|
1926
|
+
/* @__PURE__ */ jsx2("span", { className: "font-mono text-green-400 text-lg font-semibold", children: formatElapsedTime(sessionElapsedTime) })
|
|
1927
|
+
] }),
|
|
1928
|
+
activeSession.focusArea && /* @__PURE__ */ jsxs("p", { className: "text-green-400 text-xs mt-1", children: [
|
|
1929
|
+
"Focus: ",
|
|
1930
|
+
activeSession.focusArea
|
|
1931
|
+
] })
|
|
1932
|
+
] }),
|
|
1933
|
+
/* @__PURE__ */ jsxs(
|
|
1934
|
+
"button",
|
|
1935
|
+
{
|
|
1936
|
+
onClick: () => setShowAddFinding(true),
|
|
1937
|
+
className: "w-full py-3 px-4 bg-blue-500 text-white rounded-lg font-semibold text-sm hover:bg-blue-600 transition-colors flex items-center justify-center gap-2 mb-3",
|
|
1938
|
+
children: [
|
|
1939
|
+
/* @__PURE__ */ jsx2("span", { children: "+" }),
|
|
1940
|
+
" Add Finding"
|
|
1941
|
+
]
|
|
1942
|
+
}
|
|
1943
|
+
),
|
|
1944
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
1945
|
+
/* @__PURE__ */ jsx2("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-zinc-500", children: [
|
|
1946
|
+
"Findings (",
|
|
1947
|
+
sessionFindings.length,
|
|
1948
|
+
")"
|
|
1949
|
+
] }) }),
|
|
1950
|
+
sessionFindings.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-4 bg-zinc-800 rounded-lg", children: [
|
|
1951
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-xs", children: "No findings yet" }),
|
|
1952
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-500 text-xs", children: "Explore and add findings as you go" })
|
|
1953
|
+
] }) : /* @__PURE__ */ jsx2("div", { className: "space-y-2 max-h-32 overflow-y-auto", children: sessionFindings.map((finding) => /* @__PURE__ */ jsx2(
|
|
1954
|
+
"div",
|
|
1955
|
+
{
|
|
1956
|
+
className: `p-2 rounded-lg border text-xs ${finding.type === "bug" ? "bg-red-900/20 border-red-800" : finding.type === "concern" ? "bg-orange-900/20 border-orange-200" : finding.type === "suggestion" ? "bg-blue-900/20 border-blue-800" : "bg-blue-950/30 border-blue-800"}`,
|
|
1957
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
1958
|
+
/* @__PURE__ */ jsx2("span", { children: finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753" }),
|
|
1959
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
1960
|
+
/* @__PURE__ */ jsx2("p", { className: "font-medium text-zinc-100 truncate", children: finding.title }),
|
|
1961
|
+
finding.severity && finding.type === "bug" && /* @__PURE__ */ jsx2("span", { className: `inline-block mt-0.5 px-1 py-0.5 rounded text-[10px] font-medium ${finding.severity === "critical" ? "bg-red-900/40 text-red-300" : finding.severity === "high" ? "bg-orange-900/40 text-orange-300" : finding.severity === "medium" ? "bg-yellow-900/40 text-yellow-300" : "bg-zinc-700 text-zinc-300"}`, children: finding.severity })
|
|
1962
|
+
] })
|
|
1963
|
+
] })
|
|
1964
|
+
},
|
|
1965
|
+
finding.id
|
|
1966
|
+
)) })
|
|
1967
|
+
] }),
|
|
1968
|
+
/* @__PURE__ */ jsx2(
|
|
1969
|
+
"button",
|
|
1970
|
+
{
|
|
1971
|
+
onClick: () => setShowEndConfirm(true),
|
|
1972
|
+
className: "w-full py-2 px-4 bg-zinc-700 text-zinc-300 rounded-lg font-medium text-sm hover:bg-zinc-700 transition-colors",
|
|
1973
|
+
children: "End Session"
|
|
1974
|
+
}
|
|
1975
|
+
)
|
|
1976
|
+
] })
|
|
1977
|
+
) }),
|
|
770
1978
|
activeTab === "report" && /* @__PURE__ */ jsx2("div", { children: submitted ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
771
1979
|
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u{1F389}" }),
|
|
772
|
-
/* @__PURE__ */ jsx2("p", { className: "text-
|
|
1980
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-400 mt-2 font-medium", children: "Report submitted!" })
|
|
773
1981
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
774
1982
|
/* @__PURE__ */ jsx2("div", { className: "flex gap-2 mb-4", children: [
|
|
775
1983
|
{ type: "bug", label: "\u{1F41B} Bug", color: "red" },
|
|
@@ -779,25 +1987,25 @@ function BugBearPanel({
|
|
|
779
1987
|
"button",
|
|
780
1988
|
{
|
|
781
1989
|
onClick: () => setReportType(type),
|
|
782
|
-
className: `flex-1 py-1.5 px-2 rounded-lg text-xs font-medium transition-colors ${reportType === type ? color === "red" ? "bg-red-
|
|
1990
|
+
className: `flex-1 py-1.5 px-2 rounded-lg text-xs font-medium transition-colors ${reportType === type ? color === "red" ? "bg-red-900/30 text-red-400 ring-2 ring-red-500" : color === "blue" ? "bg-blue-900/30 text-blue-300 ring-2 ring-blue-500" : "bg-blue-900/50 text-blue-300 ring-2 ring-blue-500" : "bg-zinc-700 text-zinc-400 hover:bg-zinc-700"}`,
|
|
783
1991
|
children: label
|
|
784
1992
|
},
|
|
785
1993
|
type
|
|
786
1994
|
)) }),
|
|
787
1995
|
(reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
788
|
-
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-
|
|
1996
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Severity" }),
|
|
789
1997
|
/* @__PURE__ */ jsx2("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ jsx2(
|
|
790
1998
|
"button",
|
|
791
1999
|
{
|
|
792
2000
|
onClick: () => setSeverity(sev),
|
|
793
|
-
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-
|
|
2001
|
+
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-zinc-8000 text-white" : "bg-zinc-700 text-zinc-400 hover:bg-zinc-700"}`,
|
|
794
2002
|
children: sev
|
|
795
2003
|
},
|
|
796
2004
|
sev
|
|
797
2005
|
)) })
|
|
798
2006
|
] }),
|
|
799
2007
|
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
800
|
-
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-
|
|
2008
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "What happened?" }),
|
|
801
2009
|
/* @__PURE__ */ jsx2(
|
|
802
2010
|
"textarea",
|
|
803
2011
|
{
|
|
@@ -805,7 +2013,7 @@ function BugBearPanel({
|
|
|
805
2013
|
onChange: (e) => setDescription(e.target.value),
|
|
806
2014
|
placeholder: "Describe the issue...",
|
|
807
2015
|
rows: 3,
|
|
808
|
-
className: "w-full px-3 py-2 text-sm border border-
|
|
2016
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500 resize-none"
|
|
809
2017
|
}
|
|
810
2018
|
)
|
|
811
2019
|
] }),
|
|
@@ -814,19 +2022,19 @@ function BugBearPanel({
|
|
|
814
2022
|
{
|
|
815
2023
|
onClick: handleSubmitReport,
|
|
816
2024
|
disabled: submitting || !description.trim(),
|
|
817
|
-
className: "w-full py-2 px-4 bg-
|
|
2025
|
+
className: "w-full py-2 px-4 bg-blue-500 text-white rounded-lg font-medium text-sm hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
818
2026
|
children: submitting ? "Submitting..." : "Submit Report"
|
|
819
2027
|
}
|
|
820
2028
|
)
|
|
821
2029
|
] }) })
|
|
822
2030
|
] }),
|
|
823
|
-
showProfileOverlay && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 bg-
|
|
824
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-
|
|
2031
|
+
showProfileOverlay && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 bg-zinc-900 z-50 flex flex-col rounded-xl overflow-hidden", children: [
|
|
2032
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-zinc-950 text-white px-4 py-3 flex items-center justify-between border-b border-zinc-800", children: [
|
|
825
2033
|
/* @__PURE__ */ jsx2(
|
|
826
2034
|
"button",
|
|
827
2035
|
{
|
|
828
2036
|
onClick: handleCloseProfile,
|
|
829
|
-
className: "text-sm text-
|
|
2037
|
+
className: "text-sm text-zinc-400 hover:text-white transition-colors",
|
|
830
2038
|
children: "\u2190 Back"
|
|
831
2039
|
}
|
|
832
2040
|
),
|
|
@@ -836,23 +2044,23 @@ function BugBearPanel({
|
|
|
836
2044
|
] }),
|
|
837
2045
|
/* @__PURE__ */ jsx2("div", { className: "flex-1 overflow-y-auto p-4", children: profileSaved ? /* @__PURE__ */ jsxs("div", { className: "text-center py-8", children: [
|
|
838
2046
|
/* @__PURE__ */ jsx2("span", { className: "text-4xl", children: "\u2705" }),
|
|
839
|
-
/* @__PURE__ */ jsx2("p", { className: "text-
|
|
2047
|
+
/* @__PURE__ */ jsx2("p", { className: "text-zinc-400 mt-2 font-medium", children: "Profile saved!" })
|
|
840
2048
|
] }) : profileEditing ? (
|
|
841
2049
|
/* Edit Profile Form */
|
|
842
2050
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
843
2051
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
844
|
-
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-
|
|
2052
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100", children: "Edit Profile" }),
|
|
845
2053
|
/* @__PURE__ */ jsx2(
|
|
846
2054
|
"button",
|
|
847
2055
|
{
|
|
848
2056
|
onClick: handleCancelEditProfile,
|
|
849
|
-
className: "text-sm text-
|
|
2057
|
+
className: "text-sm text-zinc-500 hover:text-zinc-300",
|
|
850
2058
|
children: "Cancel"
|
|
851
2059
|
}
|
|
852
2060
|
)
|
|
853
2061
|
] }),
|
|
854
2062
|
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
855
|
-
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-
|
|
2063
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Name" }),
|
|
856
2064
|
/* @__PURE__ */ jsx2(
|
|
857
2065
|
"input",
|
|
858
2066
|
{
|
|
@@ -860,27 +2068,27 @@ function BugBearPanel({
|
|
|
860
2068
|
value: profileName,
|
|
861
2069
|
onChange: (e) => setProfileName(e.target.value),
|
|
862
2070
|
placeholder: "Your name",
|
|
863
|
-
className: "w-full px-3 py-2 text-sm border border-
|
|
2071
|
+
className: "w-full px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500"
|
|
864
2072
|
}
|
|
865
2073
|
)
|
|
866
2074
|
] }),
|
|
867
2075
|
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
868
|
-
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-
|
|
869
|
-
/* @__PURE__ */ jsxs("div", { className: "px-3 py-2 bg-
|
|
870
|
-
/* @__PURE__ */ jsx2("p", { className: "text-sm text-
|
|
871
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
2076
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Primary Email" }),
|
|
2077
|
+
/* @__PURE__ */ jsxs("div", { className: "px-3 py-2 bg-zinc-800 rounded-lg", children: [
|
|
2078
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm text-zinc-300", children: testerInfo?.email }),
|
|
2079
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500 mt-0.5", children: "Main communication email" })
|
|
872
2080
|
] })
|
|
873
2081
|
] }),
|
|
874
2082
|
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
875
|
-
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-
|
|
876
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
2083
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Additional Testing Emails" }),
|
|
2084
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500 mb-2", children: "Add other emails you use to test on different accounts" }),
|
|
877
2085
|
profileAdditionalEmails.map((email) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
878
|
-
/* @__PURE__ */ jsx2("span", { className: "flex-1 px-3 py-1.5 bg-
|
|
2086
|
+
/* @__PURE__ */ jsx2("span", { className: "flex-1 px-3 py-1.5 bg-blue-950/30 text-blue-300 text-sm rounded-full", children: email }),
|
|
879
2087
|
/* @__PURE__ */ jsx2(
|
|
880
2088
|
"button",
|
|
881
2089
|
{
|
|
882
2090
|
onClick: () => handleRemoveEmail(email),
|
|
883
|
-
className: "text-
|
|
2091
|
+
className: "text-blue-400 hover:text-red-500 text-sm",
|
|
884
2092
|
children: "\u2715"
|
|
885
2093
|
}
|
|
886
2094
|
)
|
|
@@ -893,7 +2101,7 @@ function BugBearPanel({
|
|
|
893
2101
|
value: newEmailInput,
|
|
894
2102
|
onChange: (e) => setNewEmailInput(e.target.value),
|
|
895
2103
|
placeholder: "email@example.com",
|
|
896
|
-
className: "flex-1 px-3 py-2 text-sm border border-
|
|
2104
|
+
className: "flex-1 px-3 py-2 text-sm bg-zinc-800 text-zinc-100 border border-zinc-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 placeholder:text-zinc-500",
|
|
897
2105
|
onKeyDown: (e) => e.key === "Enter" && handleAddEmail()
|
|
898
2106
|
}
|
|
899
2107
|
),
|
|
@@ -902,15 +2110,15 @@ function BugBearPanel({
|
|
|
902
2110
|
{
|
|
903
2111
|
onClick: handleAddEmail,
|
|
904
2112
|
disabled: !newEmailInput.trim(),
|
|
905
|
-
className: "px-3 py-2 bg-
|
|
2113
|
+
className: "px-3 py-2 bg-blue-500 text-white text-sm rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
906
2114
|
children: "Add"
|
|
907
2115
|
}
|
|
908
2116
|
)
|
|
909
2117
|
] })
|
|
910
2118
|
] }),
|
|
911
2119
|
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
912
|
-
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-
|
|
913
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
2120
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Testing Platforms" }),
|
|
2121
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500 mb-2", children: "Select the platforms you can test on" }),
|
|
914
2122
|
/* @__PURE__ */ jsx2("div", { className: "flex gap-2", children: [
|
|
915
2123
|
{ key: "ios", label: "\u{1F4F1} iOS" },
|
|
916
2124
|
{ key: "android", label: "\u{1F916} Android" },
|
|
@@ -919,7 +2127,7 @@ function BugBearPanel({
|
|
|
919
2127
|
"button",
|
|
920
2128
|
{
|
|
921
2129
|
onClick: () => handleTogglePlatform(key),
|
|
922
|
-
className: `flex-1 py-2 px-3 rounded-lg text-sm font-medium transition-colors border-2 ${profilePlatforms.includes(key) ? "bg-
|
|
2130
|
+
className: `flex-1 py-2 px-3 rounded-lg text-sm font-medium transition-colors border-2 ${profilePlatforms.includes(key) ? "bg-blue-950/30 border-blue-500 text-blue-300" : "bg-zinc-800 border-transparent text-zinc-400 hover:bg-zinc-700"}`,
|
|
923
2131
|
children: label
|
|
924
2132
|
},
|
|
925
2133
|
key
|
|
@@ -938,31 +2146,31 @@ function BugBearPanel({
|
|
|
938
2146
|
) : (
|
|
939
2147
|
/* Profile View */
|
|
940
2148
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
941
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-
|
|
942
|
-
/* @__PURE__ */ jsx2("div", { className: "w-16 h-16 mx-auto bg-
|
|
943
|
-
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-
|
|
944
|
-
/* @__PURE__ */ jsx2("p", { className: "text-sm text-
|
|
945
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-6 mt-4 pt-4 border-t border-
|
|
2149
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-zinc-800 rounded-lg p-4 text-center mb-4", children: [
|
|
2150
|
+
/* @__PURE__ */ jsx2("div", { className: "w-16 h-16 mx-auto bg-blue-500 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() || "?" }) }),
|
|
2151
|
+
/* @__PURE__ */ jsx2("h3", { className: "font-semibold text-zinc-100", children: testerInfo?.name }),
|
|
2152
|
+
/* @__PURE__ */ jsx2("p", { className: "text-sm text-zinc-500", children: testerInfo?.email }),
|
|
2153
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-6 mt-4 pt-4 border-t border-zinc-700", children: [
|
|
946
2154
|
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
947
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-
|
|
948
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
2155
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-blue-400", children: testerInfo?.assignedTests || 0 }),
|
|
2156
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500", children: "Assigned" })
|
|
949
2157
|
] }),
|
|
950
2158
|
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
951
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-
|
|
952
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs text-
|
|
2159
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xl font-bold text-blue-400", children: testerInfo?.completedTests || 0 }),
|
|
2160
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs text-zinc-500", children: "Completed" })
|
|
953
2161
|
] })
|
|
954
2162
|
] })
|
|
955
2163
|
] }),
|
|
956
|
-
(testerInfo?.additionalEmails?.length || 0) > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-
|
|
957
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-
|
|
958
|
-
testerInfo?.additionalEmails?.map((email) => /* @__PURE__ */ jsx2("p", { className: "text-sm text-
|
|
2164
|
+
(testerInfo?.additionalEmails?.length || 0) > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
|
|
2165
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-zinc-500 uppercase tracking-wide mb-2", children: "Additional Emails" }),
|
|
2166
|
+
testerInfo?.additionalEmails?.map((email) => /* @__PURE__ */ jsx2("p", { className: "text-sm text-zinc-300", children: email }, email))
|
|
959
2167
|
] }),
|
|
960
|
-
(testerInfo?.platforms?.length || 0) > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-
|
|
961
|
-
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-
|
|
2168
|
+
(testerInfo?.platforms?.length || 0) > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
|
|
2169
|
+
/* @__PURE__ */ jsx2("p", { className: "text-xs font-medium text-zinc-500 uppercase tracking-wide mb-2", children: "Testing Platforms" }),
|
|
962
2170
|
/* @__PURE__ */ jsx2("div", { className: "flex flex-wrap gap-2", children: testerInfo?.platforms?.map((platform) => /* @__PURE__ */ jsx2(
|
|
963
2171
|
"span",
|
|
964
2172
|
{
|
|
965
|
-
className: "px-2 py-1 bg-
|
|
2173
|
+
className: "px-2 py-1 bg-blue-900/50 text-blue-300 text-xs rounded-full font-medium",
|
|
966
2174
|
children: platform === "ios" ? "\u{1F4F1} iOS" : platform === "android" ? "\u{1F916} Android" : "\u{1F310} Web"
|
|
967
2175
|
},
|
|
968
2176
|
platform
|
|
@@ -972,14 +2180,31 @@ function BugBearPanel({
|
|
|
972
2180
|
"button",
|
|
973
2181
|
{
|
|
974
2182
|
onClick: handleStartEditProfile,
|
|
975
|
-
className: "w-full py-2 px-4 bg-
|
|
2183
|
+
className: "w-full py-2 px-4 bg-blue-500 text-white rounded-lg font-medium text-sm hover:bg-blue-600 transition-colors",
|
|
976
2184
|
children: "Edit Profile"
|
|
977
2185
|
}
|
|
978
2186
|
)
|
|
979
2187
|
] })
|
|
980
2188
|
) })
|
|
981
2189
|
] }),
|
|
982
|
-
/* @__PURE__ */
|
|
2190
|
+
/* @__PURE__ */ jsx2("div", { className: "px-4 py-2 bg-zinc-950 border-t border-zinc-800 flex items-center justify-between text-xs text-zinc-500", children: activeTab === "messages" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2191
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2192
|
+
threads.length,
|
|
2193
|
+
" thread",
|
|
2194
|
+
threads.length !== 1 ? "s" : "",
|
|
2195
|
+
" \xB7 ",
|
|
2196
|
+
unreadCount,
|
|
2197
|
+
" unread"
|
|
2198
|
+
] }),
|
|
2199
|
+
/* @__PURE__ */ jsx2(
|
|
2200
|
+
"button",
|
|
2201
|
+
{
|
|
2202
|
+
onClick: refreshThreads,
|
|
2203
|
+
className: "hover:text-zinc-300",
|
|
2204
|
+
children: "\u21BB Refresh"
|
|
2205
|
+
}
|
|
2206
|
+
)
|
|
2207
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
983
2208
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
984
2209
|
pendingCount,
|
|
985
2210
|
" pending \xB7 ",
|
|
@@ -990,11 +2215,11 @@ function BugBearPanel({
|
|
|
990
2215
|
"button",
|
|
991
2216
|
{
|
|
992
2217
|
onClick: refreshAssignments,
|
|
993
|
-
className: "hover:text-
|
|
2218
|
+
className: "hover:text-zinc-300",
|
|
994
2219
|
children: "\u21BB Refresh"
|
|
995
2220
|
}
|
|
996
2221
|
)
|
|
997
|
-
] })
|
|
2222
|
+
] }) })
|
|
998
2223
|
] })
|
|
999
2224
|
]
|
|
1000
2225
|
}
|