@bbearai/react 0.1.8 → 0.1.10

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.js CHANGED
@@ -58,7 +58,17 @@ var BugBearContext = (0, import_react.createContext)({
58
58
  endSession: async () => ({ success: false }),
59
59
  addFinding: async () => ({ success: false }),
60
60
  refreshSession: async () => {
61
- }
61
+ },
62
+ // Messaging
63
+ threads: [],
64
+ unreadCount: 0,
65
+ refreshThreads: async () => {
66
+ },
67
+ getThreadMessages: async () => [],
68
+ sendMessage: async () => false,
69
+ markAsRead: async () => {
70
+ },
71
+ createThread: async () => ({ success: false })
62
72
  });
63
73
  function useBugBear() {
64
74
  return (0, import_react.useContext)(BugBearContext);
@@ -73,6 +83,8 @@ function BugBearProvider({ config, children, enabled = true }) {
73
83
  const hasInitialized = (0, import_react.useRef)(false);
74
84
  const [activeSession, setActiveSession] = (0, import_react.useState)(null);
75
85
  const [sessionFindings, setSessionFindings] = (0, import_react.useState)([]);
86
+ const [threads, setThreads] = (0, import_react.useState)([]);
87
+ const [unreadCount, setUnreadCount] = (0, import_react.useState)(0);
76
88
  const refreshAssignments = (0, import_react.useCallback)(async () => {
77
89
  if (!client) return;
78
90
  const newAssignments = await client.getAssignedTests();
@@ -117,6 +129,38 @@ function BugBearProvider({ config, children, enabled = true }) {
117
129
  }
118
130
  return result;
119
131
  }, [client, activeSession]);
132
+ const refreshThreads = (0, import_react.useCallback)(async () => {
133
+ if (!client) return;
134
+ const newThreads = await client.getThreadsForTester();
135
+ setThreads(newThreads);
136
+ const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
137
+ setUnreadCount(totalUnread);
138
+ }, [client]);
139
+ const getThreadMessages = (0, import_react.useCallback)(async (threadId) => {
140
+ if (!client) return [];
141
+ return client.getThreadMessages(threadId);
142
+ }, [client]);
143
+ const sendMessage = (0, import_react.useCallback)(async (threadId, content) => {
144
+ if (!client) return false;
145
+ const success = await client.sendMessage(threadId, content);
146
+ if (success) {
147
+ await refreshThreads();
148
+ }
149
+ return success;
150
+ }, [client, refreshThreads]);
151
+ const markAsRead = (0, import_react.useCallback)(async (threadId) => {
152
+ if (!client) return;
153
+ await client.markThreadAsRead(threadId);
154
+ await refreshThreads();
155
+ }, [client, refreshThreads]);
156
+ const createThread = (0, import_react.useCallback)(async (options) => {
157
+ if (!client) return { success: false, error: "Client not initialized" };
158
+ const result = await client.createThread(options);
159
+ if (result.success) {
160
+ await refreshThreads();
161
+ }
162
+ return result;
163
+ }, [client, refreshThreads]);
120
164
  const initializeBugBear = (0, import_react.useCallback)(async (bugBearClient) => {
121
165
  setIsLoading(true);
122
166
  try {
@@ -129,12 +173,16 @@ function BugBearProvider({ config, children, enabled = true }) {
129
173
  setTesterInfo(info);
130
174
  setIsTester(!!info);
131
175
  if (info && qaEnabled) {
132
- const [newAssignments, session] = await Promise.all([
176
+ const [newAssignments, session, newThreads] = await Promise.all([
133
177
  bugBearClient.getAssignedTests(),
134
- bugBearClient.getActiveSession()
178
+ bugBearClient.getActiveSession(),
179
+ bugBearClient.getThreadsForTester()
135
180
  ]);
136
181
  setAssignments(newAssignments);
137
182
  setActiveSession(session);
183
+ setThreads(newThreads);
184
+ const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
185
+ setUnreadCount(totalUnread);
138
186
  if (session) {
139
187
  const findings = await bugBearClient.getSessionFindings(session.id);
140
188
  setSessionFindings(findings);
@@ -200,7 +248,15 @@ function BugBearProvider({ config, children, enabled = true }) {
200
248
  startSession,
201
249
  endSession,
202
250
  addFinding,
203
- refreshSession
251
+ refreshSession,
252
+ // Messaging
253
+ threads,
254
+ unreadCount,
255
+ refreshThreads,
256
+ getThreadMessages,
257
+ sendMessage,
258
+ markAsRead,
259
+ createThread
204
260
  },
205
261
  children
206
262
  }
@@ -209,6 +265,7 @@ function BugBearProvider({ config, children, enabled = true }) {
209
265
 
210
266
  // src/BugBearPanel.tsx
211
267
  var import_react2 = require("react");
268
+ var import_react_dom = require("react-dom");
212
269
  var import_jsx_runtime2 = require("react/jsx-runtime");
213
270
  function BugBearIcon({ size = 24, className = "" }) {
214
271
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -279,13 +336,77 @@ function BugBearPanel({
279
336
  defaultCollapsed = false,
280
337
  draggable = true
281
338
  }) {
282
- const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate, updateTesterProfile, refreshTesterInfo, activeSession, sessionFindings, startSession, endSession, addFinding } = useBugBear();
339
+ const { client, shouldShowWidget, testerInfo, assignments, currentAssignment, refreshAssignments, isLoading, onNavigate, updateTesterProfile, refreshTesterInfo, activeSession, sessionFindings, startSession, endSession, addFinding, threads, unreadCount, refreshThreads, getThreadMessages, sendMessage, markAsRead, createThread } = useBugBear();
283
340
  const [collapsed, setCollapsed] = (0, import_react2.useState)(defaultCollapsed);
284
341
  const [activeTab, setActiveTab] = (0, import_react2.useState)("tests");
285
342
  const [showSteps, setShowSteps] = (0, import_react2.useState)(false);
286
343
  const [testView, setTestView] = (0, import_react2.useState)("detail");
287
344
  const [selectedTestId, setSelectedTestId] = (0, import_react2.useState)(null);
345
+ const [messageView, setMessageView] = (0, import_react2.useState)("list");
346
+ const [selectedThread, setSelectedThread] = (0, import_react2.useState)(null);
347
+ const [threadMessages, setThreadMessages] = (0, import_react2.useState)([]);
348
+ const [replyText, setReplyText] = (0, import_react2.useState)("");
349
+ const [sendingReply, setSendingReply] = (0, import_react2.useState)(false);
350
+ const [loadingMessages, setLoadingMessages] = (0, import_react2.useState)(false);
351
+ const [composeSubject, setComposeSubject] = (0, import_react2.useState)("");
352
+ const [composeMessage, setComposeMessage] = (0, import_react2.useState)("");
353
+ const [sendingNewMessage, setSendingNewMessage] = (0, import_react2.useState)(false);
288
354
  const displayedAssignment = selectedTestId ? assignments.find((a) => a.id === selectedTestId) || currentAssignment : currentAssignment;
355
+ const groupedAssignments = (0, import_react2.useMemo)(() => {
356
+ const groups = /* @__PURE__ */ new Map();
357
+ for (const assignment of assignments) {
358
+ const groupId = assignment.testCase.group?.id || "ungrouped";
359
+ const group = assignment.testCase.group || null;
360
+ if (!groups.has(groupId)) {
361
+ groups.set(groupId, {
362
+ group,
363
+ assignments: [],
364
+ stats: { total: 0, passed: 0, failed: 0, pending: 0, skipped: 0 }
365
+ });
366
+ }
367
+ const folder = groups.get(groupId);
368
+ folder.assignments.push(assignment);
369
+ folder.stats.total++;
370
+ if (assignment.status === "passed") folder.stats.passed++;
371
+ else if (assignment.status === "failed") folder.stats.failed++;
372
+ else if (assignment.status === "skipped") folder.stats.skipped++;
373
+ else folder.stats.pending++;
374
+ }
375
+ const sortedGroups = Array.from(groups.values()).sort((a, b) => {
376
+ if (!a.group && !b.group) return 0;
377
+ if (!a.group) return 1;
378
+ if (!b.group) return -1;
379
+ return a.group.sortOrder - b.group.sortOrder;
380
+ });
381
+ return sortedGroups;
382
+ }, [assignments]);
383
+ const toggleFolderCollapse = (0, import_react2.useCallback)((groupId) => {
384
+ setCollapsedFolders((prev) => {
385
+ const next = new Set(prev);
386
+ if (next.has(groupId)) {
387
+ next.delete(groupId);
388
+ } else {
389
+ next.add(groupId);
390
+ }
391
+ return next;
392
+ });
393
+ }, []);
394
+ const getStatusBadge = (status) => {
395
+ switch (status) {
396
+ case "passed":
397
+ return { icon: "\u2705", label: "Passed", className: "bg-green-900/30 text-green-400" };
398
+ case "failed":
399
+ return { icon: "\u274C", label: "Failed", className: "bg-red-900/30 text-red-400" };
400
+ case "skipped":
401
+ return { icon: "\u23ED\uFE0F", label: "Skipped", className: "bg-yellow-900/30 text-yellow-400" };
402
+ case "in_progress":
403
+ return { icon: "\u{1F504}", label: "In Progress", className: "bg-blue-900/30 text-blue-400" };
404
+ case "blocked":
405
+ return { icon: "\u{1F6AB}", label: "Blocked", className: "bg-orange-900/30 text-orange-400" };
406
+ default:
407
+ return { icon: "\u23F3", label: "Pending", className: "bg-zinc-700 text-zinc-400" };
408
+ }
409
+ };
289
410
  const [panelPosition, setPanelPosition] = (0, import_react2.useState)(null);
290
411
  const [isDragging, setIsDragging] = (0, import_react2.useState)(false);
291
412
  const dragStartRef = (0, import_react2.useRef)(null);
@@ -307,6 +428,10 @@ function BugBearPanel({
307
428
  expectedResultUnclear: false
308
429
  });
309
430
  const [criteriaResults, setCriteriaResults] = (0, import_react2.useState)({});
431
+ const [showSkipModal, setShowSkipModal] = (0, import_react2.useState)(false);
432
+ const [selectedSkipReason, setSelectedSkipReason] = (0, import_react2.useState)(null);
433
+ const [skipNotes, setSkipNotes] = (0, import_react2.useState)("");
434
+ const [skipping, setSkipping] = (0, import_react2.useState)(false);
310
435
  const [profileEditing, setProfileEditing] = (0, import_react2.useState)(false);
311
436
  const [profileName, setProfileName] = (0, import_react2.useState)("");
312
437
  const [profileAdditionalEmails, setProfileAdditionalEmails] = (0, import_react2.useState)([]);
@@ -315,6 +440,7 @@ function BugBearPanel({
315
440
  const [savingProfile, setSavingProfile] = (0, import_react2.useState)(false);
316
441
  const [profileSaved, setProfileSaved] = (0, import_react2.useState)(false);
317
442
  const [showProfileOverlay, setShowProfileOverlay] = (0, import_react2.useState)(false);
443
+ const [collapsedFolders, setCollapsedFolders] = (0, import_react2.useState)(/* @__PURE__ */ new Set());
318
444
  const [startingSession, setStartingSession] = (0, import_react2.useState)(false);
319
445
  const [sessionFocusArea, setSessionFocusArea] = (0, import_react2.useState)("");
320
446
  const [sessionPlatform, setSessionPlatform] = (0, import_react2.useState)("web");
@@ -518,6 +644,35 @@ function BugBearPanel({
518
644
  expectedResultUnclear: false
519
645
  });
520
646
  };
647
+ const handleOpenSkipModal = () => {
648
+ setShowSkipModal(true);
649
+ setSelectedSkipReason(null);
650
+ setSkipNotes("");
651
+ };
652
+ const handleSkip = async () => {
653
+ if (!client || !displayedAssignment || !selectedSkipReason) return;
654
+ setSkipping(true);
655
+ const result = await client.skipAssignment(
656
+ displayedAssignment.id,
657
+ selectedSkipReason,
658
+ skipNotes.trim() || void 0
659
+ );
660
+ if (result.success) {
661
+ await refreshAssignments();
662
+ setShowSkipModal(false);
663
+ setSelectedSkipReason(null);
664
+ setSkipNotes("");
665
+ setSelectedTestId(null);
666
+ setTestView("detail");
667
+ }
668
+ setSkipping(false);
669
+ };
670
+ const skipReasonOptions = [
671
+ { value: "blocked", label: "Blocked", description: "Environment issue or external blocker" },
672
+ { value: "not_ready", label: "Not Ready", description: "Feature not yet implemented" },
673
+ { value: "dependency", label: "Dependency", description: "Waiting on another test or task" },
674
+ { value: "other", label: "Other", description: "Other reason (please specify)" }
675
+ ];
521
676
  const handleSubmitFeedback = async (skipFeedback = false) => {
522
677
  if (!client || !displayedAssignment) return;
523
678
  setSubmitting(true);
@@ -713,965 +868,1396 @@ function BugBearPanel({
713
868
  }
714
869
  return `${m}:${s.toString().padStart(2, "0")}`;
715
870
  };
716
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
717
- "div",
718
- {
719
- ref: panelRef,
720
- className: "fixed font-sans",
721
- style: {
722
- zIndex: 2147483647,
723
- // Max z-index to stay above all modals
724
- left: panelPosition.x,
725
- top: panelPosition.y,
726
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
727
- cursor: isDragging ? "grabbing" : void 0,
728
- userSelect: isDragging ? "none" : void 0
729
- },
730
- onMouseDown: handleMouseDown,
731
- children: [
732
- collapsed && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
733
- "button",
734
- {
735
- onClick: () => setCollapsed(false),
736
- "data-drag-handle": true,
737
- onDoubleClick: handleDoubleClick,
738
- className: "flex items-center gap-2 px-3 py-2 bg-purple-600 text-white rounded-full shadow-lg hover:bg-purple-700 transition-colors",
739
- style: { cursor: draggable ? "grab" : "pointer" },
740
- children: [
741
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BugBearIcon, { size: 24 }),
742
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: "BugBear" }),
743
- pendingCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "bg-white text-purple-600 text-xs font-bold px-1.5 py-0.5 rounded-full", children: pendingCount })
744
- ]
745
- }
746
- ),
747
- !collapsed && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-80 bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden", children: [
748
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
749
- "div",
871
+ const formatRelativeTime = (dateString) => {
872
+ const date = new Date(dateString);
873
+ const now = /* @__PURE__ */ new Date();
874
+ const diffMs = now.getTime() - date.getTime();
875
+ const diffMins = Math.floor(diffMs / 6e4);
876
+ const diffHours = Math.floor(diffMs / 36e5);
877
+ const diffDays = Math.floor(diffMs / 864e5);
878
+ if (diffMins < 1) return "Just now";
879
+ if (diffMins < 60) return `${diffMins}m ago`;
880
+ if (diffHours < 24) return `${diffHours}h ago`;
881
+ if (diffDays === 1) return "Yesterday";
882
+ if (diffDays < 7) return `${diffDays}d ago`;
883
+ return date.toLocaleDateString();
884
+ };
885
+ const formatMessageTime = (dateString) => {
886
+ const date = new Date(dateString);
887
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
888
+ };
889
+ const getThreadTypeIcon = (type) => {
890
+ switch (type) {
891
+ case "announcement":
892
+ return "\u{1F4E2}";
893
+ case "direct":
894
+ return "\u{1F4AC}";
895
+ case "report":
896
+ return "\u{1F41B}";
897
+ case "general_note":
898
+ return "\u{1F4DD}";
899
+ default:
900
+ return "\u{1F4AC}";
901
+ }
902
+ };
903
+ const handleOpenThread = async (thread) => {
904
+ setSelectedThread(thread);
905
+ setMessageView("thread");
906
+ setLoadingMessages(true);
907
+ const messages = await getThreadMessages(thread.id);
908
+ setThreadMessages(messages);
909
+ setLoadingMessages(false);
910
+ if (thread.unreadCount > 0) {
911
+ await markAsRead(thread.id);
912
+ }
913
+ };
914
+ const handleSendReply = async () => {
915
+ if (!selectedThread || !replyText.trim()) return;
916
+ setSendingReply(true);
917
+ const success = await sendMessage(selectedThread.id, replyText.trim());
918
+ if (success) {
919
+ setReplyText("");
920
+ const messages = await getThreadMessages(selectedThread.id);
921
+ setThreadMessages(messages);
922
+ }
923
+ setSendingReply(false);
924
+ };
925
+ const handleBackToThreadList = () => {
926
+ setMessageView("list");
927
+ setSelectedThread(null);
928
+ setThreadMessages([]);
929
+ setReplyText("");
930
+ setComposeSubject("");
931
+ setComposeMessage("");
932
+ };
933
+ const handleStartNewMessage = () => {
934
+ setMessageView("compose");
935
+ setComposeSubject("");
936
+ setComposeMessage("");
937
+ };
938
+ const handleSendNewMessage = async () => {
939
+ if (!composeSubject.trim() || !composeMessage.trim()) return;
940
+ setSendingNewMessage(true);
941
+ const result = await createThread({
942
+ subject: composeSubject.trim(),
943
+ message: composeMessage.trim()
944
+ });
945
+ if (result.success) {
946
+ setComposeSubject("");
947
+ setComposeMessage("");
948
+ setMessageView("list");
949
+ }
950
+ setSendingNewMessage(false);
951
+ };
952
+ if (typeof document === "undefined") return null;
953
+ return (0, import_react_dom.createPortal)(
954
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
955
+ "div",
956
+ {
957
+ ref: panelRef,
958
+ className: "fixed font-sans",
959
+ style: {
960
+ zIndex: 2147483647,
961
+ // Max z-index to stay above all modals
962
+ left: panelPosition.x,
963
+ top: panelPosition.y,
964
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
965
+ cursor: isDragging ? "grabbing" : void 0,
966
+ userSelect: isDragging ? "none" : void 0
967
+ },
968
+ onMouseDown: handleMouseDown,
969
+ children: [
970
+ collapsed && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
971
+ "button",
750
972
  {
973
+ onClick: () => setCollapsed(false),
751
974
  "data-drag-handle": true,
752
975
  onDoubleClick: handleDoubleClick,
753
- className: "bg-purple-600 text-white px-4 py-3 flex items-center justify-between",
754
- style: { cursor: draggable ? isDragging ? "grabbing" : "grab" : "default" },
976
+ 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",
977
+ style: { cursor: draggable ? "grab" : "pointer" },
755
978
  children: [
756
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
757
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BugBearIcon, { size: 28 }),
758
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
759
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { className: "font-semibold text-sm flex items-center gap-2", children: [
760
- "BugBear",
761
- draggable && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-purple-300 text-xs", title: "Drag to move, double-click to reset", children: "\u22EE\u22EE" })
762
- ] }),
763
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
764
- "button",
765
- {
766
- onClick: handleOpenProfile,
767
- className: "text-purple-200 text-xs flex items-center gap-1 hover:text-white transition-colors",
768
- children: [
769
- testerInfo?.name,
770
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px]", children: "\u270E" })
771
- ]
772
- }
773
- )
774
- ] })
775
- ] }),
776
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
777
- "button",
778
- {
779
- onClick: () => setCollapsed(true),
780
- className: "p-1 hover:bg-purple-500 rounded",
781
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
782
- }
783
- )
979
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BugBearIcon, { size: 24 }),
980
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: "BugBear" }),
981
+ pendingCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "bg-white text-blue-400 text-xs font-bold px-1.5 py-0.5 rounded-full", children: pendingCount })
784
982
  ]
785
983
  }
786
984
  ),
787
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 p-2 bg-gray-50 border-b border-gray-200", children: [
788
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
789
- "button",
790
- {
791
- onClick: () => setActiveTab("tests"),
792
- className: `flex-1 py-2 px-3 rounded-lg text-sm font-semibold transition-all flex items-center justify-center gap-1.5 ${activeTab === "tests" ? "bg-purple-600 text-white shadow-sm" : "bg-white text-gray-600 hover:bg-gray-100 border border-gray-200"}`,
793
- children: [
794
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u{1F4CB}" }),
795
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Run Tests" }),
796
- pendingCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `ml-1 px-1.5 py-0.5 rounded-full text-xs ${activeTab === "tests" ? "bg-purple-500 text-white" : "bg-purple-100 text-purple-600"}`, children: pendingCount })
797
- ]
798
- }
799
- ),
985
+ !collapsed && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-80 bg-zinc-900 rounded-xl shadow-2xl border border-zinc-800 overflow-hidden", children: [
800
986
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
801
- "button",
987
+ "div",
802
988
  {
803
- onClick: () => setActiveTab("session"),
804
- className: `flex-1 py-2 px-3 rounded-lg text-sm font-semibold transition-all flex items-center justify-center gap-1.5 relative ${activeTab === "session" ? "bg-amber-500 text-white shadow-sm" : "bg-white text-gray-600 hover:bg-gray-100 border border-gray-200"}`,
989
+ "data-drag-handle": true,
990
+ onDoubleClick: handleDoubleClick,
991
+ className: "bg-zinc-950 text-white px-4 py-3 flex items-center justify-between border-b border-zinc-800",
992
+ style: { cursor: draggable ? isDragging ? "grabbing" : "grab" : "default" },
805
993
  children: [
806
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u{1F50D}" }),
807
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Explore" }),
808
- activeSession && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "absolute -top-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white animate-pulse" })
809
- ]
810
- }
811
- )
812
- ] }),
813
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex justify-center py-1.5 border-b border-gray-200 bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
814
- "button",
815
- {
816
- onClick: () => setActiveTab("report"),
817
- className: `px-4 py-1 text-xs font-medium transition-colors rounded-full ${activeTab === "report" ? "bg-red-50 text-red-600 border border-red-200" : "text-gray-500 hover:text-gray-700 hover:bg-gray-50"}`,
818
- children: "\u{1F41B} Report Bug / Feedback"
819
- }
820
- ) }),
821
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-4 max-h-96 overflow-y-auto", children: [
822
- activeTab === "tests" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: assignments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
823
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u2705" }),
824
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-600 mt-2 font-medium", children: "All caught up!" }),
825
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-400 text-sm", children: "No tests assigned" })
826
- ] }) : testView === "list" ? (
827
- /* List View - Show all tests */
828
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-2", children: [
829
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs font-medium text-gray-500", children: [
830
- assignments.length,
831
- " test",
832
- assignments.length !== 1 ? "s" : "",
833
- " assigned"
834
- ] }) }),
835
- assignments.map((assignment) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
836
- "button",
837
- {
838
- onClick: () => {
839
- setSelectedTestId(assignment.id);
840
- setTestView("detail");
841
- setShowSteps(false);
842
- },
843
- className: `w-full text-left p-3 rounded-lg border transition-colors ${assignment.id === currentAssignment?.id ? "bg-purple-50 border-purple-200" : "bg-gray-50 border-gray-200 hover:bg-gray-100"}`,
844
- children: [
845
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start justify-between mb-1", children: [
846
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-mono text-gray-500", children: assignment.testCase.testKey }),
847
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${assignment.testCase.priority === "P0" ? "bg-red-100 text-red-700" : assignment.testCase.priority === "P1" ? "bg-orange-100 text-orange-700" : "bg-gray-100 text-gray-600"}`, children: assignment.testCase.priority })
994
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
995
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BugBearIcon, { size: 28 }),
996
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
997
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { className: "font-semibold text-sm flex items-center gap-2", children: [
998
+ "BugBear",
999
+ draggable && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-zinc-500 text-xs", title: "Drag to move, double-click to reset", children: "\u22EE\u22EE" })
848
1000
  ] }),
849
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium text-gray-900 text-sm line-clamp-2", children: assignment.testCase.title }),
850
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mt-1 text-xs text-gray-400", children: [
851
- assignment.testCase.track && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
852
- "span",
853
- {
854
- className: "px-1 py-0.5 rounded text-white",
855
- style: { backgroundColor: assignment.testCase.track.color },
856
- children: templateInfo[assignment.testCase.track.testTemplate || "steps"].icon
857
- }
858
- ),
859
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
860
- assignment.testCase.steps.length,
861
- " ",
862
- assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"
863
- ] }),
864
- assignment.id === currentAssignment?.id && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-purple-600 font-medium", children: "\u2022 Current" })
865
- ] })
866
- ]
867
- },
868
- assignment.id
869
- ))
870
- ] })
871
- ) : showFeedbackPrompt && displayedAssignment ? (
872
- /* Feedback prompt after completing a test */
873
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-3", children: [
874
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
875
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-3xl", children: pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717" }),
876
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `font-semibold mt-1 ${pendingFeedbackStatus === "passed" ? "text-green-600" : "text-red-600"}`, children: pendingFeedbackStatus === "passed" ? "Test Passed!" : "Test Failed" })
877
- ] }),
878
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-purple-50 border border-purple-100 rounded-lg p-3 mb-4", children: [
879
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-purple-800 text-sm font-medium mb-1", children: "Help us improve this test" }),
880
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-purple-600 text-xs", children: "Your feedback shapes better tests for everyone." })
881
- ] }),
882
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
883
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-600 mb-2", children: "How was this test?" }),
884
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center gap-1 justify-center", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
885
- "button",
886
- {
887
- type: "button",
888
- onClick: () => setFeedbackRating(star),
889
- className: `text-2xl transition-colors ${star <= feedbackRating ? "text-yellow-400" : "text-gray-300"} hover:text-yellow-400`,
890
- children: "\u2605"
891
- },
892
- star
893
- )) }),
894
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-center text-xs text-gray-500 mt-1", children: feedbackRating === 1 ? "Needs work" : feedbackRating === 2 ? "Could be better" : feedbackRating === 3 ? "Okay" : feedbackRating === 4 ? "Good" : "Great!" })
895
- ] }),
896
- feedbackRating < 4 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
897
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-600 mb-2", children: "What could be improved?" }),
898
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "grid grid-cols-2 gap-2", children: [
899
- { key: "stepsUnclear", label: "Steps unclear" },
900
- { key: "expectedResultUnclear", label: "Expected result unclear" },
901
- { key: "needsMoreDetail", label: "Needs more detail" },
902
- { key: "isOutdated", label: "Seems outdated" }
903
- ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
904
- "button",
905
- {
906
- type: "button",
907
- onClick: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
908
- className: `px-2 py-1.5 rounded text-xs font-medium border transition-colors ${feedbackFlags[key] ? "bg-purple-100 border-purple-300 text-purple-700" : "bg-white border-gray-200 text-gray-600 hover:border-purple-200"}`,
909
- children: label
910
- },
911
- key
912
- )) })
913
- ] }),
914
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
915
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-600 mb-1", children: "Suggestions? (optional)" }),
916
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
917
- "textarea",
918
- {
919
- value: feedbackNote,
920
- onChange: (e) => setFeedbackNote(e.target.value),
921
- placeholder: "How could this test be improved?",
922
- className: "w-full px-3 py-2 text-sm border border-gray-200 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent",
923
- rows: 2
924
- }
925
- )
926
- ] }),
927
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
928
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
929
- "button",
930
- {
931
- onClick: handleSkipFeedback,
932
- disabled: submitting,
933
- className: "flex-1 px-3 py-2 text-sm font-medium text-gray-600 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors disabled:opacity-50",
934
- children: "Skip"
935
- }
936
- ),
1001
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1002
+ "button",
1003
+ {
1004
+ onClick: handleOpenProfile,
1005
+ className: "text-zinc-400 text-xs flex items-center gap-1 hover:text-white transition-colors",
1006
+ children: [
1007
+ testerInfo?.name,
1008
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px]", children: "\u270E" })
1009
+ ]
1010
+ }
1011
+ )
1012
+ ] })
1013
+ ] }),
937
1014
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
938
1015
  "button",
939
1016
  {
940
- onClick: () => handleSubmitFeedback(false),
941
- disabled: submitting,
942
- className: "flex-1 px-3 py-2 text-sm font-medium text-white bg-purple-600 rounded-lg hover:bg-purple-700 transition-colors disabled:opacity-50",
943
- children: submitting ? "Submitting..." : "Submit Feedback"
1017
+ onClick: () => setCollapsed(true),
1018
+ className: "p-1 hover:bg-zinc-800 rounded",
1019
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
944
1020
  }
945
1021
  )
946
- ] })
947
- ] })
948
- ) : justPassed ? (
949
- /* Success state after passing */
950
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
951
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-5xl", children: "\u2713" }),
952
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-green-600 mt-3 font-semibold text-lg", children: "Passed!" }),
953
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-400 text-sm mt-1", children: "Loading next test..." })
954
- ] })
955
- ) : displayedAssignment ? (
956
- /* Detail View - Show single test */
957
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
958
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
959
- "button",
960
- {
961
- onClick: () => {
962
- setTestView("list");
963
- setSelectedTestId(null);
964
- },
965
- className: "flex items-center gap-1 text-xs text-purple-600 font-medium hover:text-purple-700 mb-3",
966
- children: [
967
- "\u2190 All Tests (",
1022
+ ]
1023
+ }
1024
+ ),
1025
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex border-b border-zinc-800 bg-zinc-900", children: [
1026
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1027
+ "button",
1028
+ {
1029
+ onClick: () => setActiveTab("tests"),
1030
+ 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"}`,
1031
+ children: [
1032
+ "Tests ",
1033
+ pendingCount > 0 && `(${pendingCount})`
1034
+ ]
1035
+ }
1036
+ ),
1037
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1038
+ "button",
1039
+ {
1040
+ onClick: () => setActiveTab("messages"),
1041
+ 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"}`,
1042
+ children: [
1043
+ "Messages",
1044
+ unreadCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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 })
1045
+ ]
1046
+ }
1047
+ ),
1048
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1049
+ "button",
1050
+ {
1051
+ onClick: () => setActiveTab("session"),
1052
+ 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"}`,
1053
+ children: [
1054
+ "Explore",
1055
+ activeSession && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "absolute top-2 ml-14 w-2 h-2 bg-green-500 rounded-full animate-pulse" })
1056
+ ]
1057
+ }
1058
+ ),
1059
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1060
+ "button",
1061
+ {
1062
+ onClick: () => setActiveTab("report"),
1063
+ 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"}`,
1064
+ children: "Report"
1065
+ }
1066
+ )
1067
+ ] }),
1068
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-4 max-h-96 overflow-y-auto", children: [
1069
+ activeTab === "tests" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: assignments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
1070
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u2705" }),
1071
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "All caught up!" }),
1072
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-sm", children: "No tests assigned" })
1073
+ ] }) : testView === "list" ? (
1074
+ /* List View - Show tests grouped by folder */
1075
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
1076
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-2 px-1", children: [
1077
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs font-medium text-zinc-500", children: [
968
1078
  assignments.length,
969
- ")"
970
- ]
971
- }
972
- ),
973
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
974
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start justify-between mb-2", children: [
975
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-mono text-gray-500", children: displayedAssignment.testCase.testKey }),
976
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1", children: [
977
- displayedAssignment.testCase.track && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
978
- "span",
1079
+ " test",
1080
+ assignments.length !== 1 ? "s" : "",
1081
+ " assigned"
1082
+ ] }),
1083
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
1084
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-green-400", children: [
1085
+ "\u2705 ",
1086
+ assignments.filter((a) => a.status === "passed").length
1087
+ ] }),
1088
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-red-400", children: [
1089
+ "\u274C ",
1090
+ assignments.filter((a) => a.status === "failed").length
1091
+ ] }),
1092
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-zinc-500", children: [
1093
+ "\u23F3 ",
1094
+ assignments.filter((a) => a.status === "pending" || a.status === "in_progress").length
1095
+ ] })
1096
+ ] })
1097
+ ] }),
1098
+ groupedAssignments.map((folder) => {
1099
+ const groupId = folder.group?.id || "ungrouped";
1100
+ const isCollapsed = collapsedFolders.has(groupId);
1101
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
1102
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "border border-zinc-700 rounded-lg overflow-hidden", children: [
1103
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1104
+ "button",
979
1105
  {
980
- className: "text-xs px-1.5 py-0.5 rounded text-white",
981
- style: { backgroundColor: displayedAssignment.testCase.track.color },
982
- children: templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon
1106
+ onClick: () => toggleFolderCollapse(groupId),
1107
+ className: "w-full flex items-center justify-between p-2.5 bg-zinc-800 hover:bg-zinc-700 transition-colors",
1108
+ children: [
1109
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1110
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-sm", children: isCollapsed ? "\u{1F4C1}" : "\u{1F4C2}" }),
1111
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium text-sm text-zinc-100", children: folder.group?.name || "Other Tests" }),
1112
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs text-zinc-500", children: [
1113
+ "(",
1114
+ completedCount,
1115
+ "/",
1116
+ folder.stats.total,
1117
+ ")"
1118
+ ] })
1119
+ ] }),
1120
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1121
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-16 h-1.5 bg-zinc-700 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1122
+ "div",
1123
+ {
1124
+ className: "h-full bg-green-500 transition-all",
1125
+ style: { width: `${completedCount / folder.stats.total * 100}%` }
1126
+ }
1127
+ ) }),
1128
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-zinc-500 text-xs", children: isCollapsed ? "\u25B6" : "\u25BC" })
1129
+ ] })
1130
+ ]
983
1131
  }
984
1132
  ),
985
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${displayedAssignment.testCase.priority === "P0" ? "bg-red-100 text-red-700" : displayedAssignment.testCase.priority === "P1" ? "bg-orange-100 text-orange-700" : "bg-gray-100 text-gray-600"}`, children: displayedAssignment.testCase.priority })
986
- ] })
1133
+ !isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "divide-y divide-zinc-800", children: folder.assignments.map((assignment) => {
1134
+ const statusBadge = getStatusBadge(assignment.status);
1135
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1136
+ "button",
1137
+ {
1138
+ onClick: () => {
1139
+ setSelectedTestId(assignment.id);
1140
+ setTestView("detail");
1141
+ setShowSteps(false);
1142
+ },
1143
+ className: `w-full text-left p-3 transition-colors ${assignment.id === currentAssignment?.id ? "bg-blue-950/30" : "bg-zinc-900 hover:bg-zinc-800"}`,
1144
+ children: [
1145
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start justify-between mb-1", children: [
1146
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1147
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-mono text-zinc-500", children: assignment.testCase.testKey }),
1148
+ assignment.isVerification && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs px-1.5 py-0.5 rounded bg-green-900/30 text-green-400 font-medium", children: "\u{1F527} Verify" })
1149
+ ] }),
1150
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1.5", children: [
1151
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${statusBadge.className}`, children: [
1152
+ statusBadge.icon,
1153
+ " ",
1154
+ statusBadge.label
1155
+ ] }),
1156
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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 })
1157
+ ] })
1158
+ ] }),
1159
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium text-zinc-100 text-sm line-clamp-2", children: assignment.testCase.title }),
1160
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mt-1 text-xs text-zinc-500", children: [
1161
+ assignment.testCase.track && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1162
+ "span",
1163
+ {
1164
+ className: "px-1 py-0.5 rounded text-white",
1165
+ style: { backgroundColor: assignment.testCase.track.color },
1166
+ children: templateInfo[assignment.testCase.track.testTemplate || "steps"].icon
1167
+ }
1168
+ ),
1169
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1170
+ assignment.testCase.steps.length,
1171
+ " ",
1172
+ assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"
1173
+ ] }),
1174
+ assignment.id === currentAssignment?.id && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-blue-400 font-medium", children: "\u2022 Current" })
1175
+ ] })
1176
+ ]
1177
+ },
1178
+ assignment.id
1179
+ );
1180
+ }) })
1181
+ ] }, groupId);
1182
+ })
1183
+ ] })
1184
+ ) : showFeedbackPrompt && displayedAssignment ? (
1185
+ /* Feedback prompt after completing a test */
1186
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-3", children: [
1187
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1188
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-3xl", children: pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717" }),
1189
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `font-semibold mt-1 ${pendingFeedbackStatus === "passed" ? "text-green-400" : "text-red-400"}`, children: pendingFeedbackStatus === "passed" ? "Test Passed!" : "Test Failed" })
987
1190
  ] }),
988
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium text-gray-900 text-sm mb-1", children: displayedAssignment.testCase.title }),
989
- displayedAssignment.status === "in_progress" && displayedAssignment.startedAt && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1.5 mb-2 text-xs text-green-600 bg-green-50 px-2 py-1 rounded", children: [
990
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "relative flex h-2 w-2", children: [
991
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
992
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500" })
993
- ] }),
994
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: "Testing" }),
995
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-mono", children: formatElapsedTime(assignmentElapsedTime) })
1191
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-blue-950/30 border border-blue-900 rounded-lg p-3 mb-4", children: [
1192
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-blue-300 text-sm font-medium mb-1", children: "Help us improve this test" }),
1193
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-blue-400 text-xs", children: "Your feedback shapes better tests for everyone." })
1194
+ ] }),
1195
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1196
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-2", children: "How was this test?" }),
1197
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center gap-1 justify-center", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1198
+ "button",
1199
+ {
1200
+ type: "button",
1201
+ onClick: () => setFeedbackRating(star),
1202
+ className: `text-2xl transition-colors ${star <= feedbackRating ? "text-yellow-400" : "text-zinc-600"} hover:text-yellow-400`,
1203
+ children: "\u2605"
1204
+ },
1205
+ star
1206
+ )) }),
1207
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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!" })
1208
+ ] }),
1209
+ feedbackRating < 4 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1210
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-2", children: "What could be improved?" }),
1211
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "grid grid-cols-2 gap-2", children: [
1212
+ { key: "stepsUnclear", label: "Steps unclear" },
1213
+ { key: "expectedResultUnclear", label: "Expected result unclear" },
1214
+ { key: "needsMoreDetail", label: "Needs more detail" },
1215
+ { key: "isOutdated", label: "Seems outdated" }
1216
+ ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1217
+ "button",
1218
+ {
1219
+ type: "button",
1220
+ onClick: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
1221
+ 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"}`,
1222
+ children: label
1223
+ },
1224
+ key
1225
+ )) })
1226
+ ] }),
1227
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1228
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-1", children: "Suggestions? (optional)" }),
1229
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1230
+ "textarea",
1231
+ {
1232
+ value: feedbackNote,
1233
+ onChange: (e) => setFeedbackNote(e.target.value),
1234
+ placeholder: "How could this test be improved?",
1235
+ 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",
1236
+ rows: 2
1237
+ }
1238
+ )
996
1239
  ] }),
997
- displayedAssignment.testCase.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-500 text-xs mb-2", children: displayedAssignment.testCase.description }),
998
- displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1240
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1242
+ "button",
1243
+ {
1244
+ onClick: handleSkipFeedback,
1245
+ disabled: submitting,
1246
+ 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",
1247
+ children: "Skip"
1248
+ }
1249
+ ),
1250
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1251
+ "button",
1252
+ {
1253
+ onClick: () => handleSubmitFeedback(false),
1254
+ disabled: submitting,
1255
+ 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",
1256
+ children: submitting ? "Submitting..." : "Submit Feedback"
1257
+ }
1258
+ )
1259
+ ] })
1260
+ ] })
1261
+ ) : justPassed ? (
1262
+ /* Success state after passing */
1263
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
1264
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-5xl", children: "\u2713" }),
1265
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-green-400 mt-3 font-semibold text-lg", children: "Passed!" }),
1266
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-sm mt-1", children: "Loading next test..." })
1267
+ ] })
1268
+ ) : displayedAssignment ? (
1269
+ /* Detail View - Show single test */
1270
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1271
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
999
1272
  "button",
1000
1273
  {
1001
- onClick: () => onNavigate(displayedAssignment.testCase.targetRoute),
1002
- className: "w-full mb-2 py-1.5 px-3 bg-blue-50 text-blue-700 border border-blue-200 rounded-lg text-xs font-medium hover:bg-blue-100 transition-colors flex items-center justify-center gap-1",
1274
+ onClick: () => {
1275
+ setTestView("list");
1276
+ setSelectedTestId(null);
1277
+ },
1278
+ className: "flex items-center gap-1 text-xs text-blue-400 font-medium hover:text-blue-300 mb-2",
1003
1279
  children: [
1004
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Go to test location" }),
1005
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u2192" })
1280
+ "\u2190 All Tests (",
1281
+ assignments.length,
1282
+ ")"
1006
1283
  ]
1007
1284
  }
1008
1285
  ),
1009
1286
  (() => {
1010
- const template = displayedAssignment.testCase.track?.testTemplate || "steps";
1011
- const steps = displayedAssignment.testCase.steps;
1012
- const info = templateInfo[template];
1013
- const rubricMode = displayedAssignment.testCase.track?.rubricMode || "pass_fail";
1014
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1015
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1287
+ const currentGroup = displayedAssignment.testCase.group;
1288
+ const groupAssignments = currentGroup ? assignments.filter((a) => a.testCase.group?.id === currentGroup.id) : assignments;
1289
+ const completed = groupAssignments.filter(
1290
+ (a) => a.status === "passed" || a.status === "failed" || a.status === "skipped"
1291
+ ).length;
1292
+ const total = groupAssignments.length;
1293
+ const progressPercent = total > 0 ? completed / total * 100 : 0;
1294
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3 p-2 bg-blue-950/30 rounded-lg", children: [
1295
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-1.5", children: [
1296
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-medium text-blue-300", children: currentGroup ? `\u{1F4C1} ${currentGroup.name}` : "\u{1F4CB} All Tests" }),
1297
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs text-blue-400", children: [
1298
+ completed,
1299
+ "/",
1300
+ total,
1301
+ " complete"
1302
+ ] })
1303
+ ] }),
1304
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-full h-2 bg-zinc-700 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1016
1305
  "div",
1017
1306
  {
1018
- className: "flex items-center gap-2 text-xs px-2 py-1 rounded mb-2",
1019
- style: {
1020
- backgroundColor: displayedAssignment.testCase.track ? `${displayedAssignment.testCase.track.color}15` : "#f3f4f6"
1021
- },
1022
- children: [
1023
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: info.icon }),
1024
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: info.name }),
1025
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-gray-500", children: [
1026
- "\u2022 ",
1027
- info.action
1028
- ] })
1029
- ]
1030
- }
1031
- ),
1032
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1033
- "button",
1034
- {
1035
- onClick: () => setShowSteps(!showSteps),
1036
- className: "text-purple-600 text-xs font-medium hover:text-purple-700 flex items-center gap-1",
1037
- children: [
1038
- showSteps ? "\u25BC" : "\u25B6",
1039
- " ",
1040
- template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`
1041
- ]
1307
+ className: "h-full bg-blue-500 transition-all duration-300",
1308
+ style: { width: `${progressPercent}%` }
1042
1309
  }
1043
- ),
1044
- showSteps && template === "steps" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mt-2 space-y-2", children: steps.map((step, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 text-xs", children: [
1045
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-5 h-5 rounded-full bg-purple-100 text-purple-700 flex items-center justify-center flex-shrink-0 font-medium", children: step.stepNumber }),
1046
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1047
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-700", children: step.action }),
1048
- step.expectedResult && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-gray-400 mt-0.5", children: [
1049
- "\u2192 ",
1050
- step.expectedResult
1051
- ] })
1310
+ ) }),
1311
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex justify-between mt-1 text-[10px] text-blue-400", children: [
1312
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1313
+ "\u2705 ",
1314
+ groupAssignments.filter((a) => a.status === "passed").length,
1315
+ " passed"
1316
+ ] }),
1317
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1318
+ "\u274C ",
1319
+ groupAssignments.filter((a) => a.status === "failed").length,
1320
+ " failed"
1321
+ ] }),
1322
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1323
+ "\u23ED\uFE0F ",
1324
+ groupAssignments.filter((a) => a.status === "skipped").length,
1325
+ " skipped"
1052
1326
  ] })
1053
- ] }, idx)) }),
1054
- showSteps && template === "checklist" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 space-y-2", children: [
1055
- steps.map((step, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1327
+ ] })
1328
+ ] });
1329
+ })(),
1330
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
1331
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start justify-between mb-2", children: [
1332
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-mono text-zinc-500", children: displayedAssignment.testCase.testKey }),
1333
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1", children: [
1334
+ displayedAssignment.testCase.track && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1335
+ "span",
1336
+ {
1337
+ className: "text-xs px-1.5 py-0.5 rounded text-white",
1338
+ style: { backgroundColor: displayedAssignment.testCase.track.color },
1339
+ children: templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon
1340
+ }
1341
+ ),
1342
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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 })
1343
+ ] })
1344
+ ] }),
1345
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium text-zinc-100 text-sm mb-1", children: displayedAssignment.testCase.title }),
1346
+ displayedAssignment.status === "in_progress" && displayedAssignment.startedAt && /* @__PURE__ */ (0, import_jsx_runtime2.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: [
1347
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "relative flex h-2 w-2", children: [
1348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
1349
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500" })
1350
+ ] }),
1351
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: "Testing" }),
1352
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-mono", children: formatElapsedTime(assignmentElapsedTime) })
1353
+ ] }),
1354
+ displayedAssignment.testCase.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs mb-2", children: displayedAssignment.testCase.description }),
1355
+ displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1356
+ "button",
1357
+ {
1358
+ onClick: () => onNavigate(displayedAssignment.testCase.targetRoute),
1359
+ 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",
1360
+ children: [
1361
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Go to test location" }),
1362
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u2192" })
1363
+ ]
1364
+ }
1365
+ ),
1366
+ (() => {
1367
+ const template = displayedAssignment.testCase.track?.testTemplate || "steps";
1368
+ const steps = displayedAssignment.testCase.steps;
1369
+ const info = templateInfo[template];
1370
+ const rubricMode = displayedAssignment.testCase.track?.rubricMode || "pass_fail";
1371
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1372
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1373
+ "div",
1374
+ {
1375
+ className: "flex items-center gap-2 text-xs px-2 py-1 rounded mb-2",
1376
+ style: {
1377
+ backgroundColor: displayedAssignment.testCase.track ? `${displayedAssignment.testCase.track.color}15` : "#f3f4f6"
1378
+ },
1379
+ children: [
1380
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: info.icon }),
1381
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: info.name }),
1382
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-zinc-500", children: [
1383
+ "\u2022 ",
1384
+ info.action
1385
+ ] })
1386
+ ]
1387
+ }
1388
+ ),
1389
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1056
1390
  "button",
1057
1391
  {
1058
- onClick: () => setCriteriaResults((prev) => {
1059
- const newResults = { ...prev };
1060
- if (prev[idx] === true) {
1061
- delete newResults[idx];
1062
- } else {
1063
- newResults[idx] = true;
1064
- }
1065
- return newResults;
1066
- }),
1067
- className: `w-full flex items-center gap-2 text-xs p-2 rounded border transition-colors text-left ${criteriaResults[idx] === true ? "bg-green-50 border-green-300" : "bg-white border-gray-200 hover:bg-gray-50"}`,
1392
+ onClick: () => setShowSteps(!showSteps),
1393
+ className: "text-blue-400 text-xs font-medium hover:text-blue-300 flex items-center gap-1",
1068
1394
  children: [
1069
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" : "" }),
1070
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `flex-1 ${criteriaResults[idx] === true ? "text-green-700" : "text-gray-700"}`, children: step.action })
1395
+ showSteps ? "\u25BC" : "\u25B6",
1396
+ " ",
1397
+ template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`
1071
1398
  ]
1072
- },
1073
- idx
1074
- )),
1075
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
1076
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-400", children: "Tap to check off each item." }),
1077
- Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1399
+ }
1400
+ ),
1401
+ showSteps && template === "steps" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mt-2 space-y-2", children: steps.map((step, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 text-xs", children: [
1402
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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 }),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1404
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-300", children: step.action }),
1405
+ step.expectedResult && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-zinc-500 mt-0.5", children: [
1406
+ "\u2192 ",
1407
+ step.expectedResult
1408
+ ] })
1409
+ ] })
1410
+ ] }, idx)) }),
1411
+ showSteps && template === "checklist" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 space-y-2", children: [
1412
+ steps.map((step, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1078
1413
  "button",
1079
1414
  {
1080
- onClick: () => setCriteriaResults({}),
1081
- className: "text-xs text-gray-400 hover:text-red-500 transition-colors",
1082
- children: "\u21BA Reset"
1083
- }
1084
- )
1085
- ] })
1086
- ] }),
1087
- showSteps && template === "rubric" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 space-y-2", children: [
1088
- steps.map((step, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-white p-2 rounded border border-gray-200", children: [
1089
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 text-xs mb-1", children: [
1090
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-5 h-5 rounded bg-purple-100 text-purple-700 flex items-center justify-center font-medium", children: idx + 1 }),
1091
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-900 font-medium flex-1", children: step.action })
1092
- ] }),
1093
- step.expectedResult && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500 ml-7 mb-2", children: step.expectedResult }),
1094
- rubricMode === "pass_fail" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 ml-7", children: [
1095
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1415
+ onClick: () => setCriteriaResults((prev) => {
1416
+ const newResults = { ...prev };
1417
+ if (prev[idx] === true) {
1418
+ delete newResults[idx];
1419
+ } else {
1420
+ newResults[idx] = true;
1421
+ }
1422
+ return newResults;
1423
+ }),
1424
+ 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"}`,
1425
+ children: [
1426
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" : "" }),
1427
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `flex-1 ${criteriaResults[idx] === true ? "text-green-400" : "text-zinc-300"}`, children: step.action })
1428
+ ]
1429
+ },
1430
+ idx
1431
+ )),
1432
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
1433
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500", children: "Tap to check off each item." }),
1434
+ Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1096
1435
  "button",
1097
1436
  {
1098
- onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: true })),
1099
- className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === true ? "bg-green-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-green-100"}`,
1100
- children: "\u2713 Pass"
1437
+ onClick: () => setCriteriaResults({}),
1438
+ className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
1439
+ children: "\u21BA Reset"
1101
1440
  }
1102
- ),
1103
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1441
+ )
1442
+ ] })
1443
+ ] }),
1444
+ showSteps && template === "rubric" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 space-y-2", children: [
1445
+ steps.map((step, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 p-2 rounded border border-zinc-700", children: [
1446
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 text-xs mb-1", children: [
1447
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-5 h-5 rounded bg-blue-900/50 text-blue-300 flex items-center justify-center font-medium", children: idx + 1 }),
1448
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-100 font-medium flex-1", children: step.action })
1449
+ ] }),
1450
+ step.expectedResult && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 ml-7 mb-2", children: step.expectedResult }),
1451
+ rubricMode === "pass_fail" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 ml-7", children: [
1452
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1453
+ "button",
1454
+ {
1455
+ onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: true })),
1456
+ 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"}`,
1457
+ children: "\u2713 Pass"
1458
+ }
1459
+ ),
1460
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1461
+ "button",
1462
+ {
1463
+ onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: false })),
1464
+ 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"}`,
1465
+ children: "\u2717 Fail"
1466
+ }
1467
+ )
1468
+ ] }),
1469
+ rubricMode === "rating" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1 ml-7", children: [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1470
+ "button",
1471
+ {
1472
+ onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: n })),
1473
+ 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"}`,
1474
+ children: n
1475
+ },
1476
+ n
1477
+ )) })
1478
+ ] }, idx)),
1479
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
1480
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500", children: rubricMode === "rating" ? "Rate 1-5 for each criterion." : "Mark each criterion as Pass or Fail." }),
1481
+ Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1104
1482
  "button",
1105
1483
  {
1106
- onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: false })),
1107
- className: `flex-1 py-1 px-2 rounded text-xs font-medium transition-colors ${criteriaResults[idx] === false ? "bg-red-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-red-100"}`,
1108
- children: "\u2717 Fail"
1484
+ onClick: () => setCriteriaResults({}),
1485
+ className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
1486
+ children: "\u21BA Reset"
1109
1487
  }
1110
1488
  )
1111
- ] }),
1112
- rubricMode === "rating" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1 ml-7", children: [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1113
- "button",
1114
- {
1115
- onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: n })),
1116
- className: `w-8 h-8 rounded font-medium text-sm transition-colors ${criteriaResults[idx] === n ? "bg-purple-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-purple-100"}`,
1117
- children: n
1118
- },
1119
- n
1120
- )) })
1121
- ] }, idx)),
1122
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
1123
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-400", children: rubricMode === "rating" ? "Rate 1-5 for each criterion." : "Mark each criterion as Pass or Fail." }),
1124
- Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1125
- "button",
1126
- {
1127
- onClick: () => setCriteriaResults({}),
1128
- className: "text-xs text-gray-400 hover:text-red-500 transition-colors",
1129
- children: "\u21BA Reset"
1130
- }
1131
- )
1489
+ ] })
1490
+ ] }),
1491
+ showSteps && template === "freeform" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 p-2 bg-amber-900/20 rounded border border-amber-800 text-xs", children: [
1492
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-amber-300 font-medium mb-1", children: "\u{1F4AD} Open Observation" }),
1493
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-amber-400", children: "Review the area described above and note:" }),
1494
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("ul", { className: "text-amber-400 mt-1 ml-4 list-disc", children: [
1495
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "What works well" }),
1496
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "Issues or concerns" }),
1497
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "Suggestions" })
1498
+ ] })
1132
1499
  ] })
1133
- ] }),
1134
- showSteps && template === "freeform" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 p-2 bg-amber-50 rounded border border-amber-200 text-xs", children: [
1135
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-amber-800 font-medium mb-1", children: "\u{1F4AD} Open Observation" }),
1136
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-amber-700", children: "Review the area described above and note:" }),
1137
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("ul", { className: "text-amber-700 mt-1 ml-4 list-disc", children: [
1138
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "What works well" }),
1139
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "Issues or concerns" }),
1140
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "Suggestions" })
1141
- ] })
1142
- ] })
1143
- ] });
1144
- })(),
1145
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-3 p-2 bg-green-50 rounded text-xs text-green-700", children: [
1146
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:" }),
1147
- " ",
1148
- displayedAssignment.testCase.expectedResult
1149
- ] })
1150
- ] }),
1151
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1500
+ ] });
1501
+ })(),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-3 p-2 bg-green-900/20 rounded text-xs text-green-400", children: [
1503
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:" }),
1504
+ " ",
1505
+ displayedAssignment.testCase.expectedResult
1506
+ ] })
1507
+ ] }),
1508
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1509
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1510
+ "button",
1511
+ {
1512
+ onClick: handleFail,
1513
+ disabled: submitting || skipping,
1514
+ 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",
1515
+ children: "\u2717 Fail"
1516
+ }
1517
+ ),
1518
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1519
+ "button",
1520
+ {
1521
+ onClick: handleOpenSkipModal,
1522
+ disabled: submitting || skipping,
1523
+ 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",
1524
+ children: "\u23ED\uFE0F Skip"
1525
+ }
1526
+ ),
1527
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1528
+ "button",
1529
+ {
1530
+ onClick: handlePass,
1531
+ disabled: submitting || skipping,
1532
+ 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",
1533
+ children: submitting ? "..." : "\u2713 Pass"
1534
+ }
1535
+ )
1536
+ ] }),
1537
+ showSkipModal && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", onClick: () => setShowSkipModal(false), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-xl p-4 w-72 shadow-xl border border-zinc-700", onClick: (e) => e.stopPropagation(), children: [
1538
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 mb-3", children: "Skip Test" }),
1539
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 mb-3", children: "Please select a reason for skipping this test." }),
1540
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2 mb-4", children: skipReasonOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1541
+ "button",
1542
+ {
1543
+ onClick: () => setSelectedSkipReason(option.value),
1544
+ 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"}`,
1545
+ children: [
1546
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "font-medium text-sm", children: option.label }),
1547
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-xs text-zinc-500", children: option.description })
1548
+ ]
1549
+ },
1550
+ option.value
1551
+ )) }),
1552
+ selectedSkipReason === "other" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1553
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-1", children: "Notes (required)" }),
1554
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1555
+ "textarea",
1556
+ {
1557
+ value: skipNotes,
1558
+ onChange: (e) => setSkipNotes(e.target.value),
1559
+ placeholder: "Please explain why you're skipping...",
1560
+ 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",
1561
+ rows: 2
1562
+ }
1563
+ )
1564
+ ] }),
1565
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1566
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1567
+ "button",
1568
+ {
1569
+ onClick: () => setShowSkipModal(false),
1570
+ 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",
1571
+ children: "Cancel"
1572
+ }
1573
+ ),
1574
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1575
+ "button",
1576
+ {
1577
+ onClick: handleSkip,
1578
+ disabled: !selectedSkipReason || selectedSkipReason === "other" && !skipNotes.trim() || skipping,
1579
+ 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",
1580
+ children: skipping ? "Skipping..." : "Skip Test"
1581
+ }
1582
+ )
1583
+ ] })
1584
+ ] }) })
1585
+ ] })
1586
+ ) : null }),
1587
+ activeTab === "messages" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: messageView === "compose" ? (
1588
+ /* Compose New Message */
1589
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1152
1590
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1153
1591
  "button",
1154
1592
  {
1155
- onClick: handleFail,
1156
- disabled: submitting,
1157
- className: "flex-1 py-2 px-3 bg-red-100 text-red-700 rounded-lg font-medium text-sm hover:bg-red-200 disabled:opacity-50 transition-colors",
1158
- children: "\u2717 Fail"
1593
+ onClick: handleBackToThreadList,
1594
+ className: "text-sm text-zinc-400 hover:text-zinc-200 mb-3 flex items-center gap-1",
1595
+ children: "\u2190 Back to Messages"
1159
1596
  }
1160
1597
  ),
1598
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1599
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100", children: "New Message" }),
1600
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs mt-1", children: "Send a message to the QA team" })
1601
+ ] }),
1602
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
1603
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1604
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Subject" }),
1605
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1606
+ "input",
1607
+ {
1608
+ type: "text",
1609
+ value: composeSubject,
1610
+ onChange: (e) => setComposeSubject(e.target.value),
1611
+ placeholder: "What's this about?",
1612
+ maxLength: 100,
1613
+ 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"
1614
+ }
1615
+ )
1616
+ ] }),
1617
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1618
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Message" }),
1619
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1620
+ "textarea",
1621
+ {
1622
+ value: composeMessage,
1623
+ onChange: (e) => setComposeMessage(e.target.value),
1624
+ placeholder: "Write your message...",
1625
+ maxLength: 2e3,
1626
+ rows: 6,
1627
+ 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"
1628
+ }
1629
+ )
1630
+ ] }),
1631
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1632
+ "button",
1633
+ {
1634
+ onClick: handleSendNewMessage,
1635
+ disabled: !composeSubject.trim() || !composeMessage.trim() || sendingNewMessage,
1636
+ 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",
1637
+ children: sendingNewMessage ? "Sending..." : "Send Message"
1638
+ }
1639
+ )
1640
+ ] })
1641
+ ] })
1642
+ ) : messageView === "thread" && selectedThread ? (
1643
+ /* Thread Detail View */
1644
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1161
1645
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1162
1646
  "button",
1163
1647
  {
1164
- onClick: handlePass,
1165
- disabled: submitting,
1166
- 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",
1167
- children: submitting ? "..." : "\u2713 Pass"
1648
+ onClick: handleBackToThreadList,
1649
+ className: "text-sm text-zinc-400 hover:text-zinc-200 mb-3 flex items-center gap-1",
1650
+ children: "\u2190 Back to Messages"
1168
1651
  }
1169
- )
1170
- ] })
1171
- ] })
1172
- ) : null }),
1173
- activeTab === "session" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: !activeSession ? (
1174
- /* Start Session View */
1175
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1176
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1177
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F50D}" }),
1178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-gray-900 mt-2", children: "Exploratory QA Session" }),
1179
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-500 text-xs mt-1", children: "Explore freely and capture findings as you go" })
1180
- ] }),
1181
- focusAreas.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1182
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "block text-xs font-medium text-gray-700 mb-2", children: [
1183
- "\u{1F4CC} Focus Areas",
1184
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-1 text-[10px] text-gray-500 font-normal", children: "from your team" })
1652
+ ),
1653
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mb-4 pb-3 border-b border-zinc-700", children: [
1654
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-lg", children: getThreadTypeIcon(selectedThread.threadType) }),
1655
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 text-sm leading-tight", children: selectedThread.subject || "No subject" })
1185
1656
  ] }),
1186
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-1.5", children: focusAreas.map((area) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1187
- "button",
1657
+ loadingMessages ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-center py-6", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-sm", children: "Loading messages..." }) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-3 mb-4", children: threadMessages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1658
+ "div",
1188
1659
  {
1189
- onClick: () => setSessionFocusArea(area.name),
1190
- className: `w-full text-left px-3 py-2 rounded-lg text-xs transition-colors border ${sessionFocusArea === area.name ? "bg-amber-50 border-amber-300 text-amber-700" : "bg-amber-50/50 border-amber-200 text-gray-700 hover:bg-amber-50"}`,
1660
+ 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"}`,
1191
1661
  children: [
1192
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1193
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: area.name }),
1194
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `text-[10px] px-1.5 py-0.5 rounded ${area.priority >= 70 ? "bg-red-100 text-red-600" : area.priority >= 50 ? "bg-amber-100 text-amber-600" : "bg-gray-100 text-gray-500"}`, children: area.priority >= 70 ? "Urgent" : area.priority >= 50 ? "Important" : "Suggested" })
1195
- ] }),
1196
- area.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-[10px] text-gray-500 mt-0.5 line-clamp-2", children: area.description })
1662
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `text-xs font-medium mb-1 ${message.senderType === "tester" ? "text-blue-300" : "text-zinc-300"}`, children: message.senderType === "tester" ? "You" : message.senderName }),
1663
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `text-sm ${message.senderType === "tester" ? "text-blue-100" : "text-zinc-200"}`, children: message.content }),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `text-[10px] mt-1 ${message.senderType === "tester" ? "text-blue-400/60" : "text-zinc-500"}`, children: formatMessageTime(message.createdAt) })
1197
1665
  ]
1198
1666
  },
1199
- area.id
1200
- )) })
1201
- ] }),
1202
- suggestedRoutes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1203
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-2", children: "\u{1F3AF} Suggested Routes to Explore" }),
1204
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-1.5 max-h-32 overflow-y-auto", children: suggestedRoutes.map((suggestion, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1667
+ message.id
1668
+ )) }),
1669
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 pt-3 border-t border-zinc-700", children: [
1670
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1671
+ "input",
1672
+ {
1673
+ type: "text",
1674
+ value: replyText,
1675
+ onChange: (e) => setReplyText(e.target.value),
1676
+ placeholder: "Type a reply...",
1677
+ maxLength: 1e3,
1678
+ 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",
1679
+ onKeyDown: (e) => e.key === "Enter" && !e.shiftKey && handleSendReply()
1680
+ }
1681
+ ),
1682
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1683
+ "button",
1684
+ {
1685
+ onClick: handleSendReply,
1686
+ disabled: !replyText.trim() || sendingReply,
1687
+ 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",
1688
+ children: sendingReply ? "..." : "Send"
1689
+ }
1690
+ )
1691
+ ] })
1692
+ ] })
1693
+ ) : (
1694
+ /* Thread List View */
1695
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1696
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1205
1697
  "button",
1206
1698
  {
1207
- onClick: () => setSessionFocusArea(suggestion.route),
1208
- className: `w-full text-left px-3 py-2 rounded-lg text-xs transition-colors border ${sessionFocusArea === suggestion.route ? "bg-purple-50 border-purple-300 text-purple-700" : "bg-gray-50 border-gray-200 text-gray-700 hover:bg-gray-100"}`,
1209
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1210
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium truncate", children: suggestion.route }),
1211
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `text-[10px] px-1.5 py-0.5 rounded ${suggestion.priorityScore >= 40 ? "bg-red-100 text-red-600" : suggestion.priorityScore >= 25 ? "bg-amber-100 text-amber-600" : "bg-gray-100 text-gray-500"}`, children: suggestion.reason })
1212
- ] })
1699
+ onClick: handleStartNewMessage,
1700
+ 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",
1701
+ children: "\u2709\uFE0F New Message"
1702
+ }
1703
+ ),
1704
+ threads.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
1705
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F4AC}" }),
1706
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "No messages yet" }),
1707
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-sm", children: "Start a conversation or wait for messages from admins" })
1708
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1709
+ "button",
1710
+ {
1711
+ onClick: () => handleOpenThread(thread),
1712
+ 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"}`,
1713
+ children: [
1714
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-1", children: [
1715
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1.5 min-w-0 flex-1", children: [
1716
+ thread.isPinned && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs", children: "\u{1F4CC}" }),
1717
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs", children: getThreadTypeIcon(thread.threadType) }),
1718
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `text-sm truncate ${thread.unreadCount > 0 ? "font-semibold text-zinc-100" : "text-zinc-300"}`, children: thread.subject || "No subject" })
1719
+ ] }),
1720
+ (thread.priority === "high" || thread.priority === "urgent") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `w-2 h-2 rounded-full flex-shrink-0 ml-2 ${thread.priority === "urgent" ? "bg-red-500" : "bg-orange-500"}` })
1721
+ ] }),
1722
+ thread.lastMessage && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-xs text-zinc-500 truncate", children: [
1723
+ thread.lastMessage.senderName,
1724
+ ": ",
1725
+ thread.lastMessage.content
1726
+ ] }),
1727
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-1.5", children: [
1728
+ thread.unreadCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-[10px] px-1.5 py-0.5 bg-blue-500 text-white rounded-full font-medium", children: [
1729
+ thread.unreadCount,
1730
+ " new"
1731
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px] text-zinc-600", children: "Read" }),
1732
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px] text-zinc-600", children: formatRelativeTime(thread.lastMessageAt) })
1733
+ ] })
1734
+ ]
1213
1735
  },
1214
- idx
1736
+ thread.id
1215
1737
  )) })
1216
- ] }),
1217
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1218
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Focus Area (optional)" }),
1738
+ ] })
1739
+ ) }),
1740
+ activeTab === "session" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: !activeSession ? (
1741
+ /* Start Session View */
1742
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1743
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1744
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F50D}" }),
1745
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 mt-2", children: "Exploratory QA Session" }),
1746
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs mt-1", children: "Explore freely and capture findings as you go" })
1747
+ ] }),
1748
+ focusAreas.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "block text-xs font-medium text-zinc-300 mb-2", children: [
1750
+ "\u{1F4CC} Focus Areas",
1751
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-1 text-[10px] text-zinc-500 font-normal", children: "from your team" })
1752
+ ] }),
1753
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-1.5", children: focusAreas.map((area) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1754
+ "button",
1755
+ {
1756
+ onClick: () => setSessionFocusArea(area.name),
1757
+ 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"}`,
1758
+ children: [
1759
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1760
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: area.name }),
1761
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" })
1762
+ ] }),
1763
+ area.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-[10px] text-zinc-500 mt-0.5 line-clamp-2", children: area.description })
1764
+ ]
1765
+ },
1766
+ area.id
1767
+ )) })
1768
+ ] }),
1769
+ suggestedRoutes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1770
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-2", children: "\u{1F3AF} Suggested Routes to Explore" }),
1771
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-1.5 max-h-32 overflow-y-auto", children: suggestedRoutes.map((suggestion, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1772
+ "button",
1773
+ {
1774
+ onClick: () => setSessionFocusArea(suggestion.route),
1775
+ 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"}`,
1776
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1777
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium truncate", children: suggestion.route }),
1778
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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 })
1779
+ ] })
1780
+ },
1781
+ idx
1782
+ )) })
1783
+ ] }),
1784
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1785
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Focus Area (optional)" }),
1786
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1787
+ "input",
1788
+ {
1789
+ type: "text",
1790
+ value: sessionFocusArea,
1791
+ onChange: (e) => setSessionFocusArea(e.target.value),
1792
+ placeholder: "e.g., checkout flow, settings page",
1793
+ 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"
1794
+ }
1795
+ )
1796
+ ] }),
1797
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1798
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Platform" }),
1799
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2", children: [
1800
+ { key: "web", label: "\u{1F310} Web" },
1801
+ { key: "ios", label: "\u{1F4F1} iOS" },
1802
+ { key: "android", label: "\u{1F916} Android" }
1803
+ ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1804
+ "button",
1805
+ {
1806
+ onClick: () => setSessionPlatform(key),
1807
+ 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"}`,
1808
+ children: label
1809
+ },
1810
+ key
1811
+ )) })
1812
+ ] }),
1219
1813
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1220
- "input",
1814
+ "button",
1221
1815
  {
1222
- type: "text",
1223
- value: sessionFocusArea,
1224
- onChange: (e) => setSessionFocusArea(e.target.value),
1225
- placeholder: "e.g., checkout flow, settings page",
1226
- className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
1816
+ onClick: handleStartSession,
1817
+ disabled: startingSession,
1818
+ 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",
1819
+ children: startingSession ? "Starting..." : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1820
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u25B6" }),
1821
+ " Start Session"
1822
+ ] })
1227
1823
  }
1228
1824
  )
1229
- ] }),
1230
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1231
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Platform" }),
1232
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2", children: [
1233
- { key: "web", label: "\u{1F310} Web" },
1234
- { key: "ios", label: "\u{1F4F1} iOS" },
1235
- { key: "android", label: "\u{1F916} Android" }
1236
- ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1825
+ ] })
1826
+ ) : showEndConfirm ? (
1827
+ /* End Session Confirmation */
1828
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1829
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1830
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u270B" }),
1831
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 mt-2", children: "End Session?" }),
1832
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-zinc-500 text-xs mt-1", children: [
1833
+ "Duration: ",
1834
+ formatElapsedTime(sessionElapsedTime),
1835
+ " \u2022 ",
1836
+ sessionFindings.length,
1837
+ " finding",
1838
+ sessionFindings.length !== 1 ? "s" : ""
1839
+ ] })
1840
+ ] }),
1841
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1842
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Session Notes (optional)" }),
1843
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1844
+ "textarea",
1845
+ {
1846
+ value: sessionNotes,
1847
+ onChange: (e) => setSessionNotes(e.target.value),
1848
+ placeholder: "Any overall observations from this session...",
1849
+ rows: 3,
1850
+ 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"
1851
+ }
1852
+ )
1853
+ ] }),
1854
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1855
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1856
+ "button",
1857
+ {
1858
+ onClick: () => setShowEndConfirm(false),
1859
+ 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",
1860
+ children: "Cancel"
1861
+ }
1862
+ ),
1863
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1864
+ "button",
1865
+ {
1866
+ onClick: handleEndSession,
1867
+ disabled: endingSession,
1868
+ 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",
1869
+ children: endingSession ? "Ending..." : "End Session"
1870
+ }
1871
+ )
1872
+ ] })
1873
+ ] })
1874
+ ) : showAddFinding ? (
1875
+ /* Add Finding Form */
1876
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1877
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [
1878
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 text-sm", children: "Add Finding" }),
1879
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1880
+ "button",
1881
+ {
1882
+ onClick: () => setShowAddFinding(false),
1883
+ className: "text-zinc-500 hover:text-zinc-400",
1884
+ children: "\u2715"
1885
+ }
1886
+ )
1887
+ ] }),
1888
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1 mb-3", children: [
1889
+ { type: "bug", label: "\u{1F41B} Bug", color: "red" },
1890
+ { type: "concern", label: "\u26A0\uFE0F Concern", color: "orange" },
1891
+ { type: "suggestion", label: "\u{1F4A1} Idea", color: "blue" },
1892
+ { type: "question", label: "\u2753 Question", color: "purple" }
1893
+ ].map(({ type, label, color }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1237
1894
  "button",
1238
1895
  {
1239
- onClick: () => setSessionPlatform(key),
1240
- className: `flex-1 py-2 px-3 rounded-lg text-xs font-medium transition-colors border-2 ${sessionPlatform === key ? "bg-purple-50 border-purple-500 text-purple-700" : "bg-gray-50 border-transparent text-gray-600 hover:bg-gray-100"}`,
1896
+ onClick: () => setFindingType(type),
1897
+ 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"}`,
1241
1898
  children: label
1242
1899
  },
1243
- key
1244
- )) })
1245
- ] }),
1246
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1247
- "button",
1248
- {
1249
- onClick: handleStartSession,
1250
- disabled: startingSession,
1251
- 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",
1252
- children: startingSession ? "Starting..." : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1253
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u25B6" }),
1254
- " Start Session"
1255
- ] })
1256
- }
1257
- )
1258
- ] })
1259
- ) : showEndConfirm ? (
1260
- /* End Session Confirmation */
1261
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1262
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1263
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u270B" }),
1264
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-gray-900 mt-2", children: "End Session?" }),
1265
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-gray-500 text-xs mt-1", children: [
1266
- "Duration: ",
1267
- formatElapsedTime(sessionElapsedTime),
1268
- " \u2022 ",
1269
- sessionFindings.length,
1270
- " finding",
1271
- sessionFindings.length !== 1 ? "s" : ""
1272
- ] })
1273
- ] }),
1274
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1275
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Session Notes (optional)" }),
1900
+ type
1901
+ )) }),
1902
+ findingType === "bug" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1903
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Severity" }),
1904
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low", "observation"].map((sev) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1905
+ "button",
1906
+ {
1907
+ onClick: () => setFindingSeverity(sev),
1908
+ 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"}`,
1909
+ children: sev === "observation" ? "obs" : sev
1910
+ },
1911
+ sev
1912
+ )) })
1913
+ ] }),
1914
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1915
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Title *" }),
1916
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1917
+ "input",
1918
+ {
1919
+ type: "text",
1920
+ value: findingTitle,
1921
+ onChange: (e) => setFindingTitle(e.target.value),
1922
+ placeholder: "Brief description of what you found",
1923
+ 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"
1924
+ }
1925
+ )
1926
+ ] }),
1927
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1928
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Details (optional)" }),
1929
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1930
+ "textarea",
1931
+ {
1932
+ value: findingDescription,
1933
+ onChange: (e) => setFindingDescription(e.target.value),
1934
+ placeholder: "Steps to reproduce, expected behavior, etc.",
1935
+ rows: 2,
1936
+ 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"
1937
+ }
1938
+ )
1939
+ ] }),
1276
1940
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1277
- "textarea",
1941
+ "button",
1278
1942
  {
1279
- value: sessionNotes,
1280
- onChange: (e) => setSessionNotes(e.target.value),
1281
- placeholder: "Any overall observations from this session...",
1282
- rows: 3,
1283
- className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 resize-none"
1943
+ onClick: handleAddFinding,
1944
+ disabled: addingFinding || !findingTitle.trim(),
1945
+ 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",
1946
+ children: addingFinding ? "Adding..." : "Add Finding"
1284
1947
  }
1285
1948
  )
1286
- ] }),
1287
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1288
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1949
+ ] })
1950
+ ) : (
1951
+ /* Active Session View */
1952
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1953
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-green-900/20 rounded-lg p-3 mb-3 border border-green-800", children: [
1954
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1955
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1956
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-2 h-2 bg-green-500 rounded-full animate-pulse" }),
1957
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium text-green-300 text-sm", children: "Session Active" })
1958
+ ] }),
1959
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-mono text-green-400 text-lg font-semibold", children: formatElapsedTime(sessionElapsedTime) })
1960
+ ] }),
1961
+ activeSession.focusArea && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-green-400 text-xs mt-1", children: [
1962
+ "Focus: ",
1963
+ activeSession.focusArea
1964
+ ] })
1965
+ ] }),
1966
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1289
1967
  "button",
1290
1968
  {
1291
- onClick: () => setShowEndConfirm(false),
1292
- className: "flex-1 py-2 px-3 bg-gray-100 text-gray-700 rounded-lg font-medium text-sm hover:bg-gray-200 transition-colors",
1293
- children: "Cancel"
1969
+ onClick: () => setShowAddFinding(true),
1970
+ 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",
1971
+ children: [
1972
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "+" }),
1973
+ " Add Finding"
1974
+ ]
1294
1975
  }
1295
1976
  ),
1977
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1978
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs font-medium text-zinc-500", children: [
1979
+ "Findings (",
1980
+ sessionFindings.length,
1981
+ ")"
1982
+ ] }) }),
1983
+ sessionFindings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-4 bg-zinc-800 rounded-lg", children: [
1984
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs", children: "No findings yet" }),
1985
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs", children: "Explore and add findings as you go" })
1986
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2 max-h-32 overflow-y-auto", children: sessionFindings.map((finding) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1987
+ "div",
1988
+ {
1989
+ 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"}`,
1990
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start gap-2", children: [
1991
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753" }),
1992
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 min-w-0", children: [
1993
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-medium text-zinc-100 truncate", children: finding.title }),
1994
+ finding.severity && finding.type === "bug" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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 })
1995
+ ] })
1996
+ ] })
1997
+ },
1998
+ finding.id
1999
+ )) })
2000
+ ] }),
1296
2001
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1297
2002
  "button",
1298
2003
  {
1299
- onClick: handleEndSession,
1300
- disabled: endingSession,
1301
- 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",
1302
- children: endingSession ? "Ending..." : "End Session"
2004
+ onClick: () => setShowEndConfirm(true),
2005
+ 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",
2006
+ children: "End Session"
1303
2007
  }
1304
2008
  )
1305
2009
  ] })
1306
- ] })
1307
- ) : showAddFinding ? (
1308
- /* Add Finding Form */
1309
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1310
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [
1311
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-gray-900 text-sm", children: "Add Finding" }),
1312
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1313
- "button",
1314
- {
1315
- onClick: () => setShowAddFinding(false),
1316
- className: "text-gray-400 hover:text-gray-600",
1317
- children: "\u2715"
1318
- }
1319
- )
1320
- ] }),
1321
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1 mb-3", children: [
2010
+ ) }),
2011
+ activeTab === "report" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
2012
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F389}" }),
2013
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "Report submitted!" })
2014
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2015
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2 mb-4", children: [
1322
2016
  { type: "bug", label: "\u{1F41B} Bug", color: "red" },
1323
- { type: "concern", label: "\u26A0\uFE0F Concern", color: "orange" },
1324
- { type: "suggestion", label: "\u{1F4A1} Idea", color: "blue" },
1325
- { type: "question", label: "\u2753 Question", color: "purple" }
2017
+ { type: "feedback", label: "\u{1F4A1} Feedback", color: "blue" },
2018
+ { type: "suggestion", label: "\u2728 Idea", color: "purple" }
1326
2019
  ].map(({ type, label, color }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1327
2020
  "button",
1328
2021
  {
1329
- onClick: () => setFindingType(type),
1330
- className: `flex-1 py-1.5 px-2 rounded text-xs font-medium transition-colors ${findingType === type ? color === "red" ? "bg-red-100 text-red-700 ring-2 ring-red-400" : color === "orange" ? "bg-orange-100 text-orange-700 ring-2 ring-orange-400" : color === "blue" ? "bg-blue-100 text-blue-700 ring-2 ring-blue-400" : "bg-purple-100 text-purple-700 ring-2 ring-purple-400" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
2022
+ onClick: () => setReportType(type),
2023
+ 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"}`,
1331
2024
  children: label
1332
2025
  },
1333
2026
  type
1334
2027
  )) }),
1335
- findingType === "bug" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1336
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Severity" }),
1337
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low", "observation"].map((sev) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2028
+ (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
2029
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Severity" }),
2030
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1338
2031
  "button",
1339
2032
  {
1340
- onClick: () => setFindingSeverity(sev),
1341
- 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-gray-500 text-white" : "bg-blue-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
1342
- children: sev === "observation" ? "obs" : sev
2033
+ onClick: () => setSeverity(sev),
2034
+ 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"}`,
2035
+ children: sev
1343
2036
  },
1344
2037
  sev
1345
2038
  )) })
1346
2039
  ] }),
1347
2040
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1348
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Title *" }),
1349
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1350
- "input",
1351
- {
1352
- type: "text",
1353
- value: findingTitle,
1354
- onChange: (e) => setFindingTitle(e.target.value),
1355
- placeholder: "Brief description of what you found",
1356
- className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
1357
- }
1358
- )
1359
- ] }),
1360
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1361
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Details (optional)" }),
2041
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "What happened?" }),
1362
2042
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1363
2043
  "textarea",
1364
2044
  {
1365
- value: findingDescription,
1366
- onChange: (e) => setFindingDescription(e.target.value),
1367
- placeholder: "Steps to reproduce, expected behavior, etc.",
1368
- rows: 2,
1369
- className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 resize-none"
2045
+ value: description,
2046
+ onChange: (e) => setDescription(e.target.value),
2047
+ placeholder: "Describe the issue...",
2048
+ rows: 3,
2049
+ 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"
1370
2050
  }
1371
2051
  )
1372
2052
  ] }),
1373
2053
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1374
2054
  "button",
1375
2055
  {
1376
- onClick: handleAddFinding,
1377
- disabled: addingFinding || !findingTitle.trim(),
1378
- className: "w-full py-2 px-4 bg-purple-600 text-white rounded-lg font-medium text-sm hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
1379
- children: addingFinding ? "Adding..." : "Add Finding"
2056
+ onClick: handleSubmitReport,
2057
+ disabled: submitting || !description.trim(),
2058
+ 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",
2059
+ children: submitting ? "Submitting..." : "Submit Report"
1380
2060
  }
1381
2061
  )
1382
- ] })
1383
- ) : (
1384
- /* Active Session View */
1385
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1386
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-green-50 rounded-lg p-3 mb-3 border border-green-200", children: [
1387
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1388
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1389
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-2 h-2 bg-green-500 rounded-full animate-pulse" }),
1390
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium text-green-800 text-sm", children: "Session Active" })
1391
- ] }),
1392
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-mono text-green-700 text-lg font-semibold", children: formatElapsedTime(sessionElapsedTime) })
1393
- ] }),
1394
- activeSession.focusArea && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-green-700 text-xs mt-1", children: [
1395
- "Focus: ",
1396
- activeSession.focusArea
1397
- ] })
1398
- ] }),
1399
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1400
- "button",
1401
- {
1402
- onClick: () => setShowAddFinding(true),
1403
- className: "w-full py-3 px-4 bg-purple-600 text-white rounded-lg font-semibold text-sm hover:bg-purple-700 transition-colors flex items-center justify-center gap-2 mb-3",
1404
- children: [
1405
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "+" }),
1406
- " Add Finding"
1407
- ]
1408
- }
1409
- ),
1410
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1411
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs font-medium text-gray-500", children: [
1412
- "Findings (",
1413
- sessionFindings.length,
1414
- ")"
1415
- ] }) }),
1416
- sessionFindings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-4 bg-gray-50 rounded-lg", children: [
1417
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-400 text-xs", children: "No findings yet" }),
1418
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-400 text-xs", children: "Explore and add findings as you go" })
1419
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2 max-h-32 overflow-y-auto", children: sessionFindings.map((finding) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1420
- "div",
1421
- {
1422
- className: `p-2 rounded-lg border text-xs ${finding.type === "bug" ? "bg-red-50 border-red-200" : finding.type === "concern" ? "bg-orange-50 border-orange-200" : finding.type === "suggestion" ? "bg-blue-50 border-blue-200" : "bg-purple-50 border-purple-200"}`,
1423
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start gap-2", children: [
1424
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753" }),
1425
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 min-w-0", children: [
1426
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-medium text-gray-900 truncate", children: finding.title }),
1427
- finding.severity && finding.type === "bug" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `inline-block mt-0.5 px-1 py-0.5 rounded text-[10px] font-medium ${finding.severity === "critical" ? "bg-red-200 text-red-800" : finding.severity === "high" ? "bg-orange-200 text-orange-800" : finding.severity === "medium" ? "bg-yellow-200 text-yellow-800" : "bg-gray-200 text-gray-700"}`, children: finding.severity })
1428
- ] })
1429
- ] })
1430
- },
1431
- finding.id
1432
- )) })
1433
- ] }),
2062
+ ] }) })
2063
+ ] }),
2064
+ showProfileOverlay && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "absolute inset-0 bg-zinc-900 z-50 flex flex-col rounded-xl overflow-hidden", children: [
2065
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-950 text-white px-4 py-3 flex items-center justify-between border-b border-zinc-800", children: [
1434
2066
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1435
2067
  "button",
1436
2068
  {
1437
- onClick: () => setShowEndConfirm(true),
1438
- className: "w-full py-2 px-4 bg-gray-100 text-gray-700 rounded-lg font-medium text-sm hover:bg-gray-200 transition-colors",
1439
- children: "End Session"
2069
+ onClick: handleCloseProfile,
2070
+ className: "text-sm text-zinc-400 hover:text-white transition-colors",
2071
+ children: "\u2190 Back"
1440
2072
  }
1441
- )
1442
- ] })
1443
- ) }),
1444
- activeTab === "report" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
1445
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F389}" }),
1446
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-600 mt-2 font-medium", children: "Report submitted!" })
1447
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1448
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2 mb-4", children: [
1449
- { type: "bug", label: "\u{1F41B} Bug", color: "red" },
1450
- { type: "feedback", label: "\u{1F4A1} Feedback", color: "blue" },
1451
- { type: "suggestion", label: "\u2728 Idea", color: "purple" }
1452
- ].map(({ type, label, color }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1453
- "button",
1454
- {
1455
- onClick: () => setReportType(type),
1456
- className: `flex-1 py-1.5 px-2 rounded-lg text-xs font-medium transition-colors ${reportType === type ? color === "red" ? "bg-red-100 text-red-700 ring-2 ring-red-500" : color === "blue" ? "bg-blue-100 text-blue-700 ring-2 ring-blue-500" : "bg-purple-100 text-purple-700 ring-2 ring-purple-500" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
1457
- children: label
1458
- },
1459
- type
1460
- )) }),
1461
- (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1462
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Severity" }),
1463
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1464
- "button",
1465
- {
1466
- onClick: () => setSeverity(sev),
1467
- className: `flex-1 py-1 px-2 rounded text-xs font-medium capitalize transition-colors ${severity === sev ? sev === "critical" ? "bg-red-600 text-white" : sev === "high" ? "bg-orange-500 text-white" : sev === "medium" ? "bg-yellow-500 text-black" : "bg-gray-500 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200"}`,
1468
- children: sev
1469
- },
1470
- sev
1471
- )) })
1472
- ] }),
1473
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1474
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "What happened?" }),
1475
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1476
- "textarea",
1477
- {
1478
- value: description,
1479
- onChange: (e) => setDescription(e.target.value),
1480
- placeholder: "Describe the issue...",
1481
- rows: 3,
1482
- className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 resize-none"
1483
- }
1484
- )
2073
+ ),
2074
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-semibold text-sm", children: "Profile" }),
2075
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-12" }),
2076
+ " "
1485
2077
  ] }),
1486
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1487
- "button",
1488
- {
1489
- onClick: handleSubmitReport,
1490
- disabled: submitting || !description.trim(),
1491
- className: "w-full py-2 px-4 bg-purple-600 text-white rounded-lg font-medium text-sm hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
1492
- children: submitting ? "Submitting..." : "Submit Report"
1493
- }
1494
- )
1495
- ] }) })
1496
- ] }),
1497
- showProfileOverlay && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "absolute inset-0 bg-white z-50 flex flex-col rounded-xl overflow-hidden", children: [
1498
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-purple-600 text-white px-4 py-3 flex items-center justify-between", children: [
1499
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1500
- "button",
1501
- {
1502
- onClick: handleCloseProfile,
1503
- className: "text-sm text-purple-200 hover:text-white transition-colors",
1504
- children: "\u2190 Back"
1505
- }
1506
- ),
1507
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-semibold text-sm", children: "Profile" }),
1508
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-12" }),
1509
- " "
1510
- ] }),
1511
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 overflow-y-auto p-4", children: profileSaved ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
1512
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u2705" }),
1513
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-gray-600 mt-2 font-medium", children: "Profile saved!" })
1514
- ] }) : profileEditing ? (
1515
- /* Edit Profile Form */
1516
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1517
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
1518
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-gray-900", children: "Edit Profile" }),
1519
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1520
- "button",
1521
- {
1522
- onClick: handleCancelEditProfile,
1523
- className: "text-sm text-gray-500 hover:text-gray-700",
1524
- children: "Cancel"
1525
- }
1526
- )
1527
- ] }),
1528
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1529
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Name" }),
1530
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1531
- "input",
1532
- {
1533
- type: "text",
1534
- value: profileName,
1535
- onChange: (e) => setProfileName(e.target.value),
1536
- placeholder: "Your name",
1537
- className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500"
1538
- }
1539
- )
1540
- ] }),
1541
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1542
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Primary Email" }),
1543
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-3 py-2 bg-gray-100 rounded-lg", children: [
1544
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-gray-700", children: testerInfo?.email }),
1545
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-400 mt-0.5", children: "Main communication email" })
1546
- ] })
1547
- ] }),
1548
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1549
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Additional Testing Emails" }),
1550
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500 mb-2", children: "Add other emails you use to test on different accounts" }),
1551
- profileAdditionalEmails.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [
1552
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "flex-1 px-3 py-1.5 bg-purple-50 text-purple-700 text-sm rounded-full", children: email }),
2078
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 overflow-y-auto p-4", children: profileSaved ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
2079
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u2705" }),
2080
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "Profile saved!" })
2081
+ ] }) : profileEditing ? (
2082
+ /* Edit Profile Form */
2083
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
2084
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
2085
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100", children: "Edit Profile" }),
1553
2086
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1554
2087
  "button",
1555
2088
  {
1556
- onClick: () => handleRemoveEmail(email),
1557
- className: "text-purple-400 hover:text-red-500 text-sm",
1558
- children: "\u2715"
2089
+ onClick: handleCancelEditProfile,
2090
+ className: "text-sm text-zinc-500 hover:text-zinc-300",
2091
+ children: "Cancel"
1559
2092
  }
1560
2093
  )
1561
- ] }, email)),
1562
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
2094
+ ] }),
2095
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2096
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Name" }),
1563
2097
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1564
2098
  "input",
1565
2099
  {
1566
- type: "email",
1567
- value: newEmailInput,
1568
- onChange: (e) => setNewEmailInput(e.target.value),
1569
- placeholder: "email@example.com",
1570
- className: "flex-1 px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500",
1571
- onKeyDown: (e) => e.key === "Enter" && handleAddEmail()
2100
+ type: "text",
2101
+ value: profileName,
2102
+ onChange: (e) => setProfileName(e.target.value),
2103
+ placeholder: "Your name",
2104
+ 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"
1572
2105
  }
1573
- ),
1574
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2106
+ )
2107
+ ] }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2109
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Primary Email" }),
2110
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-3 py-2 bg-zinc-800 rounded-lg", children: [
2111
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-zinc-300", children: testerInfo?.email }),
2112
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 mt-0.5", children: "Main communication email" })
2113
+ ] })
2114
+ ] }),
2115
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2116
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Additional Testing Emails" }),
2117
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 mb-2", children: "Add other emails you use to test on different accounts" }),
2118
+ profileAdditionalEmails.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [
2119
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "flex-1 px-3 py-1.5 bg-blue-950/30 text-blue-300 text-sm rounded-full", children: email }),
2120
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2121
+ "button",
2122
+ {
2123
+ onClick: () => handleRemoveEmail(email),
2124
+ className: "text-blue-400 hover:text-red-500 text-sm",
2125
+ children: "\u2715"
2126
+ }
2127
+ )
2128
+ ] }, email)),
2129
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
2130
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2131
+ "input",
2132
+ {
2133
+ type: "email",
2134
+ value: newEmailInput,
2135
+ onChange: (e) => setNewEmailInput(e.target.value),
2136
+ placeholder: "email@example.com",
2137
+ 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",
2138
+ onKeyDown: (e) => e.key === "Enter" && handleAddEmail()
2139
+ }
2140
+ ),
2141
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2142
+ "button",
2143
+ {
2144
+ onClick: handleAddEmail,
2145
+ disabled: !newEmailInput.trim(),
2146
+ 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",
2147
+ children: "Add"
2148
+ }
2149
+ )
2150
+ ] })
2151
+ ] }),
2152
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2153
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Testing Platforms" }),
2154
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 mb-2", children: "Select the platforms you can test on" }),
2155
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2", children: [
2156
+ { key: "ios", label: "\u{1F4F1} iOS" },
2157
+ { key: "android", label: "\u{1F916} Android" },
2158
+ { key: "web", label: "\u{1F310} Web" }
2159
+ ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1575
2160
  "button",
1576
2161
  {
1577
- onClick: handleAddEmail,
1578
- disabled: !newEmailInput.trim(),
1579
- className: "px-3 py-2 bg-purple-600 text-white text-sm rounded-lg hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",
1580
- children: "Add"
1581
- }
1582
- )
1583
- ] })
1584
- ] }),
1585
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1586
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Testing Platforms" }),
1587
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500 mb-2", children: "Select the platforms you can test on" }),
1588
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2", children: [
1589
- { key: "ios", label: "\u{1F4F1} iOS" },
1590
- { key: "android", label: "\u{1F916} Android" },
1591
- { key: "web", label: "\u{1F310} Web" }
1592
- ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2162
+ onClick: () => handleTogglePlatform(key),
2163
+ 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"}`,
2164
+ children: label
2165
+ },
2166
+ key
2167
+ )) })
2168
+ ] }),
2169
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1593
2170
  "button",
1594
2171
  {
1595
- onClick: () => handleTogglePlatform(key),
1596
- className: `flex-1 py-2 px-3 rounded-lg text-sm font-medium transition-colors border-2 ${profilePlatforms.includes(key) ? "bg-purple-50 border-purple-500 text-purple-700" : "bg-gray-50 border-transparent text-gray-600 hover:bg-gray-100"}`,
1597
- children: label
1598
- },
1599
- key
1600
- )) })
1601
- ] }),
1602
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1603
- "button",
1604
- {
1605
- onClick: handleSaveProfile,
1606
- disabled: savingProfile,
1607
- className: "w-full py-2 px-4 bg-green-600 text-white rounded-lg font-medium text-sm hover:bg-green-700 disabled:opacity-50 transition-colors",
1608
- children: savingProfile ? "Saving..." : "Save Profile"
1609
- }
1610
- )
1611
- ] })
1612
- ) : (
1613
- /* Profile View */
1614
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1615
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-gray-50 rounded-lg p-4 text-center mb-4", children: [
1616
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-16 h-16 mx-auto bg-purple-600 rounded-full flex items-center justify-center mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-2xl font-semibold text-white", children: testerInfo?.name?.charAt(0)?.toUpperCase() || "?" }) }),
1617
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-gray-900", children: testerInfo?.name }),
1618
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-gray-500", children: testerInfo?.email }),
1619
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-center gap-6 mt-4 pt-4 border-t border-gray-200", children: [
1620
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
1621
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-purple-600", children: testerInfo?.assignedTests || 0 }),
1622
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500", children: "Assigned" })
1623
- ] }),
1624
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
1625
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-purple-600", children: testerInfo?.completedTests || 0 }),
1626
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500", children: "Completed" })
2172
+ onClick: handleSaveProfile,
2173
+ disabled: savingProfile,
2174
+ className: "w-full py-2 px-4 bg-green-600 text-white rounded-lg font-medium text-sm hover:bg-green-700 disabled:opacity-50 transition-colors",
2175
+ children: savingProfile ? "Saving..." : "Save Profile"
2176
+ }
2177
+ )
2178
+ ] })
2179
+ ) : (
2180
+ /* Profile View */
2181
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
2182
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-4 text-center mb-4", children: [
2183
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-16 h-16 mx-auto bg-blue-500 rounded-full flex items-center justify-center mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-2xl font-semibold text-white", children: testerInfo?.name?.charAt(0)?.toUpperCase() || "?" }) }),
2184
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100", children: testerInfo?.name }),
2185
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-zinc-500", children: testerInfo?.email }),
2186
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-center gap-6 mt-4 pt-4 border-t border-zinc-700", children: [
2187
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
2188
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-blue-400", children: testerInfo?.assignedTests || 0 }),
2189
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500", children: "Assigned" })
2190
+ ] }),
2191
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
2192
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-blue-400", children: testerInfo?.completedTests || 0 }),
2193
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500", children: "Completed" })
2194
+ ] })
1627
2195
  ] })
1628
- ] })
1629
- ] }),
1630
- (testerInfo?.additionalEmails?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
1631
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide mb-2", children: "Additional Emails" }),
1632
- testerInfo?.additionalEmails?.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-gray-700", children: email }, email))
1633
- ] }),
1634
- (testerInfo?.platforms?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-gray-50 rounded-lg p-3 mb-3", children: [
1635
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-gray-500 uppercase tracking-wide mb-2", children: "Testing Platforms" }),
1636
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex flex-wrap gap-2", children: testerInfo?.platforms?.map((platform) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1637
- "span",
2196
+ ] }),
2197
+ (testerInfo?.additionalEmails?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
2198
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-zinc-500 uppercase tracking-wide mb-2", children: "Additional Emails" }),
2199
+ testerInfo?.additionalEmails?.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-zinc-300", children: email }, email))
2200
+ ] }),
2201
+ (testerInfo?.platforms?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
2202
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-zinc-500 uppercase tracking-wide mb-2", children: "Testing Platforms" }),
2203
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex flex-wrap gap-2", children: testerInfo?.platforms?.map((platform) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2204
+ "span",
2205
+ {
2206
+ className: "px-2 py-1 bg-blue-900/50 text-blue-300 text-xs rounded-full font-medium",
2207
+ children: platform === "ios" ? "\u{1F4F1} iOS" : platform === "android" ? "\u{1F916} Android" : "\u{1F310} Web"
2208
+ },
2209
+ platform
2210
+ )) })
2211
+ ] }),
2212
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2213
+ "button",
1638
2214
  {
1639
- className: "px-2 py-1 bg-purple-100 text-purple-700 text-xs rounded-full font-medium",
1640
- children: platform === "ios" ? "\u{1F4F1} iOS" : platform === "android" ? "\u{1F916} Android" : "\u{1F310} Web"
1641
- },
1642
- platform
1643
- )) })
1644
- ] }),
1645
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1646
- "button",
1647
- {
1648
- onClick: handleStartEditProfile,
1649
- className: "w-full py-2 px-4 bg-purple-600 text-white rounded-lg font-medium text-sm hover:bg-purple-700 transition-colors",
1650
- children: "Edit Profile"
1651
- }
1652
- )
1653
- ] })
1654
- ) })
1655
- ] }),
1656
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-4 py-2 bg-gray-50 border-t border-gray-200 flex items-center justify-between text-xs text-gray-400", children: [
1657
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1658
- pendingCount,
1659
- " pending \xB7 ",
1660
- inProgressCount,
1661
- " in progress"
2215
+ onClick: handleStartEditProfile,
2216
+ className: "w-full py-2 px-4 bg-blue-500 text-white rounded-lg font-medium text-sm hover:bg-blue-600 transition-colors",
2217
+ children: "Edit Profile"
2218
+ }
2219
+ )
2220
+ ] })
2221
+ ) })
1662
2222
  ] }),
1663
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1664
- "button",
1665
- {
1666
- onClick: refreshAssignments,
1667
- className: "hover:text-gray-600",
1668
- children: "\u21BB Refresh"
1669
- }
1670
- )
2223
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2224
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
2225
+ threads.length,
2226
+ " thread",
2227
+ threads.length !== 1 ? "s" : "",
2228
+ " \xB7 ",
2229
+ unreadCount,
2230
+ " unread"
2231
+ ] }),
2232
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2233
+ "button",
2234
+ {
2235
+ onClick: refreshThreads,
2236
+ className: "hover:text-zinc-300",
2237
+ children: "\u21BB Refresh"
2238
+ }
2239
+ )
2240
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2241
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
2242
+ pendingCount,
2243
+ " pending \xB7 ",
2244
+ inProgressCount,
2245
+ " in progress"
2246
+ ] }),
2247
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2248
+ "button",
2249
+ {
2250
+ onClick: refreshAssignments,
2251
+ className: "hover:text-zinc-300",
2252
+ children: "\u21BB Refresh"
2253
+ }
2254
+ )
2255
+ ] }) })
1671
2256
  ] })
1672
- ] })
1673
- ]
1674
- }
2257
+ ]
2258
+ }
2259
+ ),
2260
+ document.body
1675
2261
  );
1676
2262
  }
1677
2263