@bbearai/react 0.1.9 → 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
@@ -265,6 +265,7 @@ function BugBearProvider({ config, children, enabled = true }) {
265
265
 
266
266
  // src/BugBearPanel.tsx
267
267
  var import_react2 = require("react");
268
+ var import_react_dom = require("react-dom");
268
269
  var import_jsx_runtime2 = require("react/jsx-runtime");
269
270
  function BugBearIcon({ size = 24, className = "" }) {
270
271
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -948,614 +949,905 @@ function BugBearPanel({
948
949
  }
949
950
  setSendingNewMessage(false);
950
951
  };
951
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
952
- "div",
953
- {
954
- ref: panelRef,
955
- className: "fixed font-sans",
956
- style: {
957
- zIndex: 2147483647,
958
- // Max z-index to stay above all modals
959
- left: panelPosition.x,
960
- top: panelPosition.y,
961
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
962
- cursor: isDragging ? "grabbing" : void 0,
963
- userSelect: isDragging ? "none" : void 0
964
- },
965
- onMouseDown: handleMouseDown,
966
- children: [
967
- collapsed && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
968
- "button",
969
- {
970
- onClick: () => setCollapsed(false),
971
- "data-drag-handle": true,
972
- onDoubleClick: handleDoubleClick,
973
- 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",
974
- style: { cursor: draggable ? "grab" : "pointer" },
975
- children: [
976
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BugBearIcon, { size: 24 }),
977
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: "BugBear" }),
978
- 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 })
979
- ]
980
- }
981
- ),
982
- !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: [
983
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
984
- "div",
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",
985
972
  {
973
+ onClick: () => setCollapsed(false),
986
974
  "data-drag-handle": true,
987
975
  onDoubleClick: handleDoubleClick,
988
- className: "bg-zinc-950 text-white px-4 py-3 flex items-center justify-between border-b border-zinc-800",
989
- 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" },
990
978
  children: [
991
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
992
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BugBearIcon, { size: 28 }),
993
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
994
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h3", { className: "font-semibold text-sm flex items-center gap-2", children: [
995
- "BugBear",
996
- 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" })
997
- ] }),
998
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
999
- "button",
1000
- {
1001
- onClick: handleOpenProfile,
1002
- className: "text-zinc-400 text-xs flex items-center gap-1 hover:text-white transition-colors",
1003
- children: [
1004
- testerInfo?.name,
1005
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px]", children: "\u270E" })
1006
- ]
1007
- }
1008
- )
1009
- ] })
1010
- ] }),
1011
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1012
- "button",
1013
- {
1014
- onClick: () => setCollapsed(true),
1015
- className: "p-1 hover:bg-zinc-800 rounded",
1016
- 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" }) })
1017
- }
1018
- )
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 })
1019
982
  ]
1020
983
  }
1021
984
  ),
1022
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex border-b border-zinc-800 bg-zinc-900", children: [
1023
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1024
- "button",
1025
- {
1026
- onClick: () => setActiveTab("tests"),
1027
- 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"}`,
1028
- children: [
1029
- "Tests ",
1030
- pendingCount > 0 && `(${pendingCount})`
1031
- ]
1032
- }
1033
- ),
1034
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1035
- "button",
1036
- {
1037
- onClick: () => setActiveTab("messages"),
1038
- 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"}`,
1039
- children: [
1040
- "Messages",
1041
- 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 })
1042
- ]
1043
- }
1044
- ),
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: [
1045
986
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1046
- "button",
987
+ "div",
1047
988
  {
1048
- onClick: () => setActiveTab("session"),
1049
- 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"}`,
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" },
1050
993
  children: [
1051
- "Explore",
1052
- 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" })
1053
- ]
1054
- }
1055
- ),
1056
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1057
- "button",
1058
- {
1059
- onClick: () => setActiveTab("report"),
1060
- 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"}`,
1061
- children: "Report"
1062
- }
1063
- )
1064
- ] }),
1065
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-4 max-h-96 overflow-y-auto", children: [
1066
- 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: [
1067
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u2705" }),
1068
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "All caught up!" }),
1069
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-sm", children: "No tests assigned" })
1070
- ] }) : testView === "list" ? (
1071
- /* List View - Show tests grouped by folder */
1072
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
1073
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-2 px-1", children: [
1074
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs font-medium text-zinc-500", children: [
1075
- assignments.length,
1076
- " test",
1077
- assignments.length !== 1 ? "s" : "",
1078
- " assigned"
1079
- ] }),
1080
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
1081
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-green-400", children: [
1082
- "\u2705 ",
1083
- assignments.filter((a) => a.status === "passed").length
1084
- ] }),
1085
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-red-400", children: [
1086
- "\u274C ",
1087
- assignments.filter((a) => a.status === "failed").length
1088
- ] }),
1089
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-zinc-500", children: [
1090
- "\u23F3 ",
1091
- assignments.filter((a) => a.status === "pending" || a.status === "in_progress").length
1092
- ] })
1093
- ] })
1094
- ] }),
1095
- groupedAssignments.map((folder) => {
1096
- const groupId = folder.group?.id || "ungrouped";
1097
- const isCollapsed = collapsedFolders.has(groupId);
1098
- const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
1099
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "border border-zinc-700 rounded-lg overflow-hidden", children: [
1100
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1101
- "button",
1102
- {
1103
- onClick: () => toggleFolderCollapse(groupId),
1104
- className: "w-full flex items-center justify-between p-2.5 bg-zinc-800 hover:bg-zinc-700 transition-colors",
1105
- children: [
1106
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1107
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-sm", children: isCollapsed ? "\u{1F4C1}" : "\u{1F4C2}" }),
1108
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium text-sm text-zinc-100", children: folder.group?.name || "Other Tests" }),
1109
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs text-zinc-500", children: [
1110
- "(",
1111
- completedCount,
1112
- "/",
1113
- folder.stats.total,
1114
- ")"
1115
- ] })
1116
- ] }),
1117
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1118
- /* @__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)(
1119
- "div",
1120
- {
1121
- className: "h-full bg-green-500 transition-all",
1122
- style: { width: `${completedCount / folder.stats.total * 100}%` }
1123
- }
1124
- ) }),
1125
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-zinc-500 text-xs", children: isCollapsed ? "\u25B6" : "\u25BC" })
1126
- ] })
1127
- ]
1128
- }
1129
- ),
1130
- !isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "divide-y divide-zinc-800", children: folder.assignments.map((assignment) => {
1131
- const statusBadge = getStatusBadge(assignment.status);
1132
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
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" })
1000
+ ] }),
1001
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1133
1002
  "button",
1134
1003
  {
1135
- onClick: () => {
1136
- setSelectedTestId(assignment.id);
1137
- setTestView("detail");
1138
- setShowSteps(false);
1139
- },
1140
- className: `w-full text-left p-3 transition-colors ${assignment.id === currentAssignment?.id ? "bg-blue-950/30" : "bg-zinc-900 hover:bg-zinc-800"}`,
1004
+ onClick: handleOpenProfile,
1005
+ className: "text-zinc-400 text-xs flex items-center gap-1 hover:text-white transition-colors",
1141
1006
  children: [
1142
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start justify-between mb-1", children: [
1143
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1144
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-mono text-zinc-500", children: assignment.testCase.testKey }),
1145
- 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" })
1146
- ] }),
1147
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1.5", children: [
1148
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: `text-xs px-1.5 py-0.5 rounded font-medium ${statusBadge.className}`, children: [
1149
- statusBadge.icon,
1150
- " ",
1151
- statusBadge.label
1152
- ] }),
1153
- /* @__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 })
1154
- ] })
1155
- ] }),
1156
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium text-zinc-100 text-sm line-clamp-2", children: assignment.testCase.title }),
1157
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mt-1 text-xs text-zinc-500", children: [
1158
- assignment.testCase.track && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1159
- "span",
1160
- {
1161
- className: "px-1 py-0.5 rounded text-white",
1162
- style: { backgroundColor: assignment.testCase.track.color },
1163
- children: templateInfo[assignment.testCase.track.testTemplate || "steps"].icon
1164
- }
1165
- ),
1166
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1167
- assignment.testCase.steps.length,
1168
- " ",
1169
- assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"
1170
- ] }),
1171
- assignment.id === currentAssignment?.id && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-blue-400 font-medium", children: "\u2022 Current" })
1172
- ] })
1007
+ testerInfo?.name,
1008
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px]", children: "\u270E" })
1173
1009
  ]
1174
- },
1175
- assignment.id
1176
- );
1177
- }) })
1178
- ] }, groupId);
1179
- })
1180
- ] })
1181
- ) : showFeedbackPrompt && displayedAssignment ? (
1182
- /* Feedback prompt after completing a test */
1183
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "p-3", children: [
1184
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1185
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-3xl", children: pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717" }),
1186
- /* @__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" })
1187
- ] }),
1188
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-blue-950/30 border border-blue-900 rounded-lg p-3 mb-4", children: [
1189
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-blue-300 text-sm font-medium mb-1", children: "Help us improve this test" }),
1190
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-blue-400 text-xs", children: "Your feedback shapes better tests for everyone." })
1191
- ] }),
1192
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1193
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-2", children: "How was this test?" }),
1194
- /* @__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)(
1195
- "button",
1196
- {
1197
- type: "button",
1198
- onClick: () => setFeedbackRating(star),
1199
- className: `text-2xl transition-colors ${star <= feedbackRating ? "text-yellow-400" : "text-zinc-600"} hover:text-yellow-400`,
1200
- children: "\u2605"
1201
- },
1202
- star
1203
- )) }),
1204
- /* @__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!" })
1205
- ] }),
1206
- feedbackRating < 4 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1207
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-2", children: "What could be improved?" }),
1208
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "grid grid-cols-2 gap-2", children: [
1209
- { key: "stepsUnclear", label: "Steps unclear" },
1210
- { key: "expectedResultUnclear", label: "Expected result unclear" },
1211
- { key: "needsMoreDetail", label: "Needs more detail" },
1212
- { key: "isOutdated", label: "Seems outdated" }
1213
- ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1214
- "button",
1215
- {
1216
- type: "button",
1217
- onClick: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
1218
- 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"}`,
1219
- children: label
1220
- },
1221
- key
1222
- )) })
1223
- ] }),
1224
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1225
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-1", children: "Suggestions? (optional)" }),
1226
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1227
- "textarea",
1228
- {
1229
- value: feedbackNote,
1230
- onChange: (e) => setFeedbackNote(e.target.value),
1231
- placeholder: "How could this test be improved?",
1232
- 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",
1233
- rows: 2
1234
- }
1235
- )
1236
- ] }),
1237
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1238
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1239
- "button",
1240
- {
1241
- onClick: handleSkipFeedback,
1242
- disabled: submitting,
1243
- 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",
1244
- children: "Skip"
1245
- }
1246
- ),
1010
+ }
1011
+ )
1012
+ ] })
1013
+ ] }),
1247
1014
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1248
1015
  "button",
1249
1016
  {
1250
- onClick: () => handleSubmitFeedback(false),
1251
- disabled: submitting,
1252
- 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",
1253
- 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" }) })
1254
1020
  }
1255
1021
  )
1256
- ] })
1257
- ] })
1258
- ) : justPassed ? (
1259
- /* Success state after passing */
1260
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
1261
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-5xl", children: "\u2713" }),
1262
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-green-400 mt-3 font-semibold text-lg", children: "Passed!" }),
1263
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-sm mt-1", children: "Loading next test..." })
1264
- ] })
1265
- ) : displayedAssignment ? (
1266
- /* Detail View - Show single test */
1267
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1268
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1269
- "button",
1270
- {
1271
- onClick: () => {
1272
- setTestView("list");
1273
- setSelectedTestId(null);
1274
- },
1275
- className: "flex items-center gap-1 text-xs text-blue-400 font-medium hover:text-blue-300 mb-2",
1276
- children: [
1277
- "\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: [
1278
1078
  assignments.length,
1279
- ")"
1280
- ]
1281
- }
1282
- ),
1283
- (() => {
1284
- const currentGroup = displayedAssignment.testCase.group;
1285
- const groupAssignments = currentGroup ? assignments.filter((a) => a.testCase.group?.id === currentGroup.id) : assignments;
1286
- const completed = groupAssignments.filter(
1287
- (a) => a.status === "passed" || a.status === "failed" || a.status === "skipped"
1288
- ).length;
1289
- const total = groupAssignments.length;
1290
- const progressPercent = total > 0 ? completed / total * 100 : 0;
1291
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3 p-2 bg-blue-950/30 rounded-lg", children: [
1292
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-1.5", children: [
1293
- /* @__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" }),
1294
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs text-blue-400", children: [
1295
- completed,
1296
- "/",
1297
- total,
1298
- " complete"
1299
- ] })
1079
+ " test",
1080
+ assignments.length !== 1 ? "s" : "",
1081
+ " assigned"
1300
1082
  ] }),
1301
- /* @__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)(
1302
- "div",
1303
- {
1304
- className: "h-full bg-blue-500 transition-all duration-300",
1305
- style: { width: `${progressPercent}%` }
1306
- }
1307
- ) }),
1308
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex justify-between mt-1 text-[10px] text-blue-400", children: [
1309
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
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: [
1310
1085
  "\u2705 ",
1311
- groupAssignments.filter((a) => a.status === "passed").length,
1312
- " passed"
1086
+ assignments.filter((a) => a.status === "passed").length
1313
1087
  ] }),
1314
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1088
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-red-400", children: [
1315
1089
  "\u274C ",
1316
- groupAssignments.filter((a) => a.status === "failed").length,
1317
- " failed"
1090
+ assignments.filter((a) => a.status === "failed").length
1318
1091
  ] }),
1319
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
1320
- "\u23ED\uFE0F ",
1321
- groupAssignments.filter((a) => a.status === "skipped").length,
1322
- " skipped"
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
1323
1095
  ] })
1324
1096
  ] })
1325
- ] });
1326
- })(),
1327
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
1328
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start justify-between mb-2", children: [
1329
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs font-mono text-zinc-500", children: displayedAssignment.testCase.testKey }),
1330
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1", children: [
1331
- displayedAssignment.testCase.track && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1332
- "span",
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",
1333
1105
  {
1334
- className: "text-xs px-1.5 py-0.5 rounded text-white",
1335
- style: { backgroundColor: displayedAssignment.testCase.track.color },
1336
- 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
+ ]
1337
1131
  }
1338
1132
  ),
1339
- /* @__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 })
1340
- ] })
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" })
1341
1190
  ] }),
1342
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-medium text-zinc-100 text-sm mb-1", children: displayedAssignment.testCase.title }),
1343
- 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: [
1344
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "relative flex h-2 w-2", children: [
1345
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
1346
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500" })
1347
- ] }),
1348
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: "Testing" }),
1349
- /* @__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
+ )
1350
1239
  ] }),
1351
- displayedAssignment.testCase.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs mb-2", children: displayedAssignment.testCase.description }),
1352
- 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)(
1353
1272
  "button",
1354
1273
  {
1355
- onClick: () => onNavigate(displayedAssignment.testCase.targetRoute),
1356
- 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",
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",
1357
1279
  children: [
1358
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Go to test location" }),
1359
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u2192" })
1280
+ "\u2190 All Tests (",
1281
+ assignments.length,
1282
+ ")"
1360
1283
  ]
1361
1284
  }
1362
1285
  ),
1363
1286
  (() => {
1364
- const template = displayedAssignment.testCase.track?.testTemplate || "steps";
1365
- const steps = displayedAssignment.testCase.steps;
1366
- const info = templateInfo[template];
1367
- const rubricMode = displayedAssignment.testCase.track?.rubricMode || "pass_fail";
1368
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1369
- /* @__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)(
1370
1305
  "div",
1371
1306
  {
1372
- className: "flex items-center gap-2 text-xs px-2 py-1 rounded mb-2",
1373
- style: {
1374
- backgroundColor: displayedAssignment.testCase.track ? `${displayedAssignment.testCase.track.color}15` : "#f3f4f6"
1375
- },
1376
- children: [
1377
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: info.icon }),
1378
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: info.name }),
1379
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-zinc-500", children: [
1380
- "\u2022 ",
1381
- info.action
1382
- ] })
1383
- ]
1384
- }
1385
- ),
1386
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1387
- "button",
1388
- {
1389
- onClick: () => setShowSteps(!showSteps),
1390
- className: "text-blue-400 text-xs font-medium hover:text-blue-300 flex items-center gap-1",
1391
- children: [
1392
- showSteps ? "\u25BC" : "\u25B6",
1393
- " ",
1394
- template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`
1395
- ]
1307
+ className: "h-full bg-blue-500 transition-all duration-300",
1308
+ style: { width: `${progressPercent}%` }
1396
1309
  }
1397
- ),
1398
- 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: [
1399
- /* @__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 }),
1400
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1401
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-300", children: step.action }),
1402
- step.expectedResult && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-zinc-500 mt-0.5", children: [
1403
- "\u2192 ",
1404
- step.expectedResult
1405
- ] })
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"
1406
1326
  ] })
1407
- ] }, idx)) }),
1408
- showSteps && template === "checklist" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 space-y-2", children: [
1409
- 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)(
1410
1390
  "button",
1411
1391
  {
1412
- onClick: () => setCriteriaResults((prev) => {
1413
- const newResults = { ...prev };
1414
- if (prev[idx] === true) {
1415
- delete newResults[idx];
1416
- } else {
1417
- newResults[idx] = true;
1418
- }
1419
- return newResults;
1420
- }),
1421
- 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"}`,
1392
+ onClick: () => setShowSteps(!showSteps),
1393
+ className: "text-blue-400 text-xs font-medium hover:text-blue-300 flex items-center gap-1",
1422
1394
  children: [
1423
- /* @__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" : "" }),
1424
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `flex-1 ${criteriaResults[idx] === true ? "text-green-400" : "text-zinc-300"}`, children: step.action })
1395
+ showSteps ? "\u25BC" : "\u25B6",
1396
+ " ",
1397
+ template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`
1425
1398
  ]
1426
- },
1427
- idx
1428
- )),
1429
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
1430
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500", children: "Tap to check off each item." }),
1431
- 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)(
1432
1413
  "button",
1433
1414
  {
1434
- onClick: () => setCriteriaResults({}),
1435
- className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
1436
- children: "\u21BA Reset"
1437
- }
1438
- )
1439
- ] })
1440
- ] }),
1441
- showSteps && template === "rubric" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-2 space-y-2", children: [
1442
- steps.map((step, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 p-2 rounded border border-zinc-700", children: [
1443
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 text-xs mb-1", children: [
1444
- /* @__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 }),
1445
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-100 font-medium flex-1", children: step.action })
1446
- ] }),
1447
- step.expectedResult && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 ml-7 mb-2", children: step.expectedResult }),
1448
- rubricMode === "pass_fail" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 ml-7", children: [
1449
- /* @__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)(
1450
1435
  "button",
1451
1436
  {
1452
- onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: true })),
1453
- 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"}`,
1454
- children: "\u2713 Pass"
1437
+ onClick: () => setCriteriaResults({}),
1438
+ className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
1439
+ children: "\u21BA Reset"
1455
1440
  }
1456
- ),
1457
- /* @__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)(
1458
1482
  "button",
1459
1483
  {
1460
- onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: false })),
1461
- 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"}`,
1462
- children: "\u2717 Fail"
1484
+ onClick: () => setCriteriaResults({}),
1485
+ className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
1486
+ children: "\u21BA Reset"
1463
1487
  }
1464
1488
  )
1465
- ] }),
1466
- 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)(
1467
- "button",
1468
- {
1469
- onClick: () => setCriteriaResults((prev) => ({ ...prev, [idx]: n })),
1470
- 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"}`,
1471
- children: n
1472
- },
1473
- n
1474
- )) })
1475
- ] }, idx)),
1476
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-2", children: [
1477
- /* @__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." }),
1478
- Object.keys(criteriaResults).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1479
- "button",
1480
- {
1481
- onClick: () => setCriteriaResults({}),
1482
- className: "text-xs text-zinc-500 hover:text-red-500 transition-colors",
1483
- children: "\u21BA Reset"
1484
- }
1485
- )
1486
- ] })
1487
- ] }),
1488
- 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: [
1489
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-amber-300 font-medium mb-1", children: "\u{1F4AD} Open Observation" }),
1490
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-amber-400", children: "Review the area described above and note:" }),
1491
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("ul", { className: "text-amber-400 mt-1 ml-4 list-disc", children: [
1492
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "What works well" }),
1493
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "Issues or concerns" }),
1494
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: "Suggestions" })
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
+ ] })
1495
1499
  ] })
1496
- ] })
1497
- ] });
1498
- })(),
1499
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-3 p-2 bg-green-900/20 rounded text-xs text-green-400", children: [
1500
- /* @__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:" }),
1501
- " ",
1502
- displayedAssignment.testCase.expectedResult
1503
- ] })
1504
- ] }),
1505
- /* @__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: [
1506
1590
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1507
1591
  "button",
1508
1592
  {
1509
- onClick: handleFail,
1510
- disabled: submitting || skipping,
1511
- 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",
1512
- 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"
1513
1596
  }
1514
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: [
1515
1645
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1516
1646
  "button",
1517
1647
  {
1518
- onClick: handleOpenSkipModal,
1519
- disabled: submitting || skipping,
1520
- 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",
1521
- children: "\u23ED\uFE0F Skip"
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"
1522
1651
  }
1523
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" })
1656
+ ] }),
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",
1659
+ {
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"}`,
1661
+ children: [
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) })
1665
+ ]
1666
+ },
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: [
1524
1696
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1525
1697
  "button",
1526
1698
  {
1527
- onClick: handlePass,
1528
- disabled: submitting || skipping,
1529
- 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",
1530
- children: submitting ? "..." : "\u2713 Pass"
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"
1531
1702
  }
1532
- )
1533
- ] }),
1534
- 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: [
1535
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 mb-3", children: "Skip Test" }),
1536
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 mb-3", children: "Please select a reason for skipping this test." }),
1537
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2 mb-4", children: skipReasonOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
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)(
1538
1709
  "button",
1539
1710
  {
1540
- onClick: () => setSelectedSkipReason(option.value),
1541
- 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"}`,
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"}`,
1542
1713
  children: [
1543
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "font-medium text-sm", children: option.label }),
1544
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-xs text-zinc-500", children: option.description })
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
+ ] })
1545
1734
  ]
1546
1735
  },
1547
- option.value
1548
- )) }),
1549
- selectedSkipReason === "other" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1550
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-400 mb-1", children: "Notes (required)" }),
1736
+ thread.id
1737
+ )) })
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
+ ] }),
1813
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1814
+ "button",
1815
+ {
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
+ ] })
1823
+ }
1824
+ )
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)" }),
1551
1843
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1552
1844
  "textarea",
1553
1845
  {
1554
- value: skipNotes,
1555
- onChange: (e) => setSkipNotes(e.target.value),
1556
- placeholder: "Please explain why you're skipping...",
1557
- 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",
1558
- rows: 2
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"
1559
1851
  }
1560
1852
  )
1561
1853
  ] }),
@@ -1563,64 +1855,84 @@ function BugBearPanel({
1563
1855
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1564
1856
  "button",
1565
1857
  {
1566
- onClick: () => setShowSkipModal(false),
1567
- 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",
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",
1568
1860
  children: "Cancel"
1569
1861
  }
1570
1862
  ),
1571
1863
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1572
1864
  "button",
1573
1865
  {
1574
- onClick: handleSkip,
1575
- disabled: !selectedSkipReason || selectedSkipReason === "other" && !skipNotes.trim() || skipping,
1576
- 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",
1577
- children: skipping ? "Skipping..." : "Skip Test"
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"
1578
1885
  }
1579
1886
  )
1580
- ] })
1581
- ] }) })
1582
- ] })
1583
- ) : null }),
1584
- activeTab === "messages" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: messageView === "compose" ? (
1585
- /* Compose New Message */
1586
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1587
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1588
- "button",
1589
- {
1590
- onClick: handleBackToThreadList,
1591
- className: "text-sm text-zinc-400 hover:text-zinc-200 mb-3 flex items-center gap-1",
1592
- children: "\u2190 Back to Messages"
1593
- }
1594
- ),
1595
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1596
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100", children: "New Message" }),
1597
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs mt-1", children: "Send a message to the QA team" })
1598
- ] }),
1599
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-3", children: [
1600
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1601
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Subject" }),
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)(
1894
+ "button",
1895
+ {
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"}`,
1898
+ children: label
1899
+ },
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 *" }),
1602
1916
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1603
1917
  "input",
1604
1918
  {
1605
1919
  type: "text",
1606
- value: composeSubject,
1607
- onChange: (e) => setComposeSubject(e.target.value),
1608
- placeholder: "What's this about?",
1609
- maxLength: 100,
1920
+ value: findingTitle,
1921
+ onChange: (e) => setFindingTitle(e.target.value),
1922
+ placeholder: "Brief description of what you found",
1610
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"
1611
1924
  }
1612
1925
  )
1613
1926
  ] }),
1614
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1615
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Message" }),
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)" }),
1616
1929
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1617
1930
  "textarea",
1618
1931
  {
1619
- value: composeMessage,
1620
- onChange: (e) => setComposeMessage(e.target.value),
1621
- placeholder: "Write your message...",
1622
- maxLength: 2e3,
1623
- rows: 6,
1932
+ value: findingDescription,
1933
+ onChange: (e) => setFindingDescription(e.target.value),
1934
+ placeholder: "Steps to reproduce, expected behavior, etc.",
1935
+ rows: 2,
1624
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"
1625
1937
  }
1626
1938
  )
@@ -1628,308 +1940,112 @@ function BugBearPanel({
1628
1940
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1629
1941
  "button",
1630
1942
  {
1631
- onClick: handleSendNewMessage,
1632
- disabled: !composeSubject.trim() || !composeMessage.trim() || sendingNewMessage,
1943
+ onClick: handleAddFinding,
1944
+ disabled: addingFinding || !findingTitle.trim(),
1633
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",
1634
- children: sendingNewMessage ? "Sending..." : "Send Message"
1635
- }
1636
- )
1637
- ] })
1638
- ] })
1639
- ) : messageView === "thread" && selectedThread ? (
1640
- /* Thread Detail View */
1641
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1642
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1643
- "button",
1644
- {
1645
- onClick: handleBackToThreadList,
1646
- className: "text-sm text-zinc-400 hover:text-zinc-200 mb-3 flex items-center gap-1",
1647
- children: "\u2190 Back to Messages"
1648
- }
1649
- ),
1650
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mb-4 pb-3 border-b border-zinc-700", children: [
1651
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-lg", children: getThreadTypeIcon(selectedThread.threadType) }),
1652
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 text-sm leading-tight", children: selectedThread.subject || "No subject" })
1653
- ] }),
1654
- 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)(
1655
- "div",
1656
- {
1657
- 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"}`,
1658
- children: [
1659
- /* @__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 }),
1660
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: `text-sm ${message.senderType === "tester" ? "text-blue-100" : "text-zinc-200"}`, children: message.content }),
1661
- /* @__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) })
1662
- ]
1663
- },
1664
- message.id
1665
- )) }),
1666
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2 pt-3 border-t border-zinc-700", children: [
1667
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1668
- "input",
1669
- {
1670
- type: "text",
1671
- value: replyText,
1672
- onChange: (e) => setReplyText(e.target.value),
1673
- placeholder: "Type a reply...",
1674
- maxLength: 1e3,
1675
- 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",
1676
- onKeyDown: (e) => e.key === "Enter" && !e.shiftKey && handleSendReply()
1677
- }
1678
- ),
1679
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1680
- "button",
1681
- {
1682
- onClick: handleSendReply,
1683
- disabled: !replyText.trim() || sendingReply,
1684
- 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",
1685
- children: sendingReply ? "..." : "Send"
1946
+ children: addingFinding ? "Adding..." : "Add Finding"
1686
1947
  }
1687
1948
  )
1688
1949
  ] })
1689
- ] })
1690
- ) : (
1691
- /* Thread List View */
1692
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1693
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1694
- "button",
1695
- {
1696
- onClick: handleStartNewMessage,
1697
- 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",
1698
- children: "\u2709\uFE0F New Message"
1699
- }
1700
- ),
1701
- threads.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
1702
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F4AC}" }),
1703
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "No messages yet" }),
1704
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-sm", children: "Start a conversation or wait for messages from admins" })
1705
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1706
- "button",
1707
- {
1708
- onClick: () => handleOpenThread(thread),
1709
- 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"}`,
1710
- children: [
1711
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-1", children: [
1712
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1.5 min-w-0 flex-1", children: [
1713
- thread.isPinned && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs", children: "\u{1F4CC}" }),
1714
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs", children: getThreadTypeIcon(thread.threadType) }),
1715
- /* @__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" })
1716
- ] }),
1717
- (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"}` })
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" })
1718
1958
  ] }),
1719
- thread.lastMessage && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-xs text-zinc-500 truncate", children: [
1720
- thread.lastMessage.senderName,
1721
- ": ",
1722
- thread.lastMessage.content
1723
- ] }),
1724
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mt-1.5", children: [
1725
- 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: [
1726
- thread.unreadCount,
1727
- " new"
1728
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px] text-zinc-600", children: "Read" }),
1729
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px] text-zinc-600", children: formatRelativeTime(thread.lastMessageAt) })
1730
- ] })
1731
- ]
1732
- },
1733
- thread.id
1734
- )) })
1735
- ] })
1736
- ) }),
1737
- activeTab === "session" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: !activeSession ? (
1738
- /* Start Session View */
1739
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1740
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1741
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F50D}" }),
1742
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 mt-2", children: "Exploratory QA Session" }),
1743
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs mt-1", children: "Explore freely and capture findings as you go" })
1744
- ] }),
1745
- focusAreas.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1746
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "block text-xs font-medium text-zinc-300 mb-2", children: [
1747
- "\u{1F4CC} Focus Areas",
1748
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-1 text-[10px] text-zinc-500 font-normal", children: "from your team" })
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
+ ] })
1749
1965
  ] }),
1750
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-1.5", children: focusAreas.map((area) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1966
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1751
1967
  "button",
1752
1968
  {
1753
- onClick: () => setSessionFocusArea(area.name),
1754
- 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"}`,
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",
1755
1971
  children: [
1756
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1757
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium", children: area.name }),
1758
- /* @__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" })
1759
- ] }),
1760
- area.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-[10px] text-zinc-500 mt-0.5 line-clamp-2", children: area.description })
1972
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "+" }),
1973
+ " Add Finding"
1761
1974
  ]
1762
- },
1763
- area.id
1764
- )) })
1765
- ] }),
1766
- suggestedRoutes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1767
- /* @__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" }),
1768
- /* @__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)(
1769
- "button",
1770
- {
1771
- onClick: () => setSessionFocusArea(suggestion.route),
1772
- 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"}`,
1773
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1774
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium truncate", children: suggestion.route }),
1775
- /* @__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 })
1776
- ] })
1777
- },
1778
- idx
1779
- )) })
1780
- ] }),
1781
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1782
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Focus Area (optional)" }),
1783
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1784
- "input",
1785
- {
1786
- type: "text",
1787
- value: sessionFocusArea,
1788
- onChange: (e) => setSessionFocusArea(e.target.value),
1789
- placeholder: "e.g., checkout flow, settings page",
1790
- 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"
1791
- }
1792
- )
1793
- ] }),
1794
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1795
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Platform" }),
1796
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2", children: [
1797
- { key: "web", label: "\u{1F310} Web" },
1798
- { key: "ios", label: "\u{1F4F1} iOS" },
1799
- { key: "android", label: "\u{1F916} Android" }
1800
- ].map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1801
- "button",
1802
- {
1803
- onClick: () => setSessionPlatform(key),
1804
- 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"}`,
1805
- children: label
1806
- },
1807
- key
1808
- )) })
1809
- ] }),
1810
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1811
- "button",
1812
- {
1813
- onClick: handleStartSession,
1814
- disabled: startingSession,
1815
- 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",
1816
- children: startingSession ? "Starting..." : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1817
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u25B6" }),
1818
- " Start Session"
1819
- ] })
1820
- }
1821
- )
1822
- ] })
1823
- ) : showEndConfirm ? (
1824
- /* End Session Confirmation */
1825
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1826
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center mb-4", children: [
1827
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u270B" }),
1828
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 mt-2", children: "End Session?" }),
1829
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-zinc-500 text-xs mt-1", children: [
1830
- "Duration: ",
1831
- formatElapsedTime(sessionElapsedTime),
1832
- " \u2022 ",
1833
- sessionFindings.length,
1834
- " finding",
1835
- sessionFindings.length !== 1 ? "s" : ""
1836
- ] })
1837
- ] }),
1838
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
1839
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Session Notes (optional)" }),
1840
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1841
- "textarea",
1842
- {
1843
- value: sessionNotes,
1844
- onChange: (e) => setSessionNotes(e.target.value),
1845
- placeholder: "Any overall observations from this session...",
1846
- rows: 3,
1847
- 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"
1848
- }
1849
- )
1850
- ] }),
1851
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
1852
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1853
- "button",
1854
- {
1855
- onClick: () => setShowEndConfirm(false),
1856
- 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",
1857
- children: "Cancel"
1858
1975
  }
1859
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
+ ] }),
1860
2001
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1861
2002
  "button",
1862
2003
  {
1863
- onClick: handleEndSession,
1864
- disabled: endingSession,
1865
- 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",
1866
- 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"
1867
2007
  }
1868
2008
  )
1869
2009
  ] })
1870
- ] })
1871
- ) : showAddFinding ? (
1872
- /* Add Finding Form */
1873
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1874
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [
1875
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100 text-sm", children: "Add Finding" }),
1876
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1877
- "button",
1878
- {
1879
- onClick: () => setShowAddFinding(false),
1880
- className: "text-zinc-500 hover:text-zinc-400",
1881
- children: "\u2715"
1882
- }
1883
- )
1884
- ] }),
1885
- /* @__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: [
1886
2016
  { type: "bug", label: "\u{1F41B} Bug", color: "red" },
1887
- { type: "concern", label: "\u26A0\uFE0F Concern", color: "orange" },
1888
- { type: "suggestion", label: "\u{1F4A1} Idea", color: "blue" },
1889
- { type: "question", label: "\u2753 Question", color: "purple" }
2017
+ { type: "feedback", label: "\u{1F4A1} Feedback", color: "blue" },
2018
+ { type: "suggestion", label: "\u2728 Idea", color: "purple" }
1890
2019
  ].map(({ type, label, color }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1891
2020
  "button",
1892
2021
  {
1893
- onClick: () => setFindingType(type),
1894
- 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"}`,
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"}`,
1895
2024
  children: label
1896
2025
  },
1897
2026
  type
1898
2027
  )) }),
1899
- findingType === "bug" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
2028
+ (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1900
2029
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Severity" }),
1901
- /* @__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)(
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)(
1902
2031
  "button",
1903
2032
  {
1904
- onClick: () => setFindingSeverity(sev),
1905
- 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"}`,
1906
- 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
1907
2036
  },
1908
2037
  sev
1909
2038
  )) })
1910
2039
  ] }),
1911
2040
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1912
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Title *" }),
1913
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1914
- "input",
1915
- {
1916
- type: "text",
1917
- value: findingTitle,
1918
- onChange: (e) => setFindingTitle(e.target.value),
1919
- placeholder: "Brief description of what you found",
1920
- 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"
1921
- }
1922
- )
1923
- ] }),
1924
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1925
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 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?" }),
1926
2042
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1927
2043
  "textarea",
1928
2044
  {
1929
- value: findingDescription,
1930
- onChange: (e) => setFindingDescription(e.target.value),
1931
- placeholder: "Steps to reproduce, expected behavior, etc.",
1932
- rows: 2,
2045
+ value: description,
2046
+ onChange: (e) => setDescription(e.target.value),
2047
+ placeholder: "Describe the issue...",
2048
+ rows: 3,
1933
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"
1934
2050
  }
1935
2051
  )
@@ -1937,322 +2053,211 @@ function BugBearPanel({
1937
2053
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1938
2054
  "button",
1939
2055
  {
1940
- onClick: handleAddFinding,
1941
- disabled: addingFinding || !findingTitle.trim(),
2056
+ onClick: handleSubmitReport,
2057
+ disabled: submitting || !description.trim(),
1942
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",
1943
- children: addingFinding ? "Adding..." : "Add Finding"
2059
+ children: submitting ? "Submitting..." : "Submit Report"
1944
2060
  }
1945
2061
  )
1946
- ] })
1947
- ) : (
1948
- /* Active Session View */
1949
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1950
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-green-900/20 rounded-lg p-3 mb-3 border border-green-800", children: [
1951
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between", children: [
1952
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
1953
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-2 h-2 bg-green-500 rounded-full animate-pulse" }),
1954
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-medium text-green-300 text-sm", children: "Session Active" })
1955
- ] }),
1956
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-mono text-green-400 text-lg font-semibold", children: formatElapsedTime(sessionElapsedTime) })
1957
- ] }),
1958
- activeSession.focusArea && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-green-400 text-xs mt-1", children: [
1959
- "Focus: ",
1960
- activeSession.focusArea
1961
- ] })
1962
- ] }),
1963
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1964
- "button",
1965
- {
1966
- onClick: () => setShowAddFinding(true),
1967
- 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",
1968
- children: [
1969
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "+" }),
1970
- " Add Finding"
1971
- ]
1972
- }
1973
- ),
1974
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
1975
- /* @__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: [
1976
- "Findings (",
1977
- sessionFindings.length,
1978
- ")"
1979
- ] }) }),
1980
- sessionFindings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-4 bg-zinc-800 rounded-lg", children: [
1981
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs", children: "No findings yet" }),
1982
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-500 text-xs", children: "Explore and add findings as you go" })
1983
- ] }) : /* @__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)(
1984
- "div",
1985
- {
1986
- 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"}`,
1987
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start gap-2", children: [
1988
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753" }),
1989
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 min-w-0", children: [
1990
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-medium text-zinc-100 truncate", children: finding.title }),
1991
- 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 })
1992
- ] })
1993
- ] })
1994
- },
1995
- finding.id
1996
- )) })
1997
- ] }),
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: [
1998
2066
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1999
2067
  "button",
2000
2068
  {
2001
- onClick: () => setShowEndConfirm(true),
2002
- 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",
2003
- children: "End Session"
2004
- }
2005
- )
2006
- ] })
2007
- ) }),
2008
- activeTab === "report" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center py-8", children: [
2009
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u{1F389}" }),
2010
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "Report submitted!" })
2011
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2012
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2 mb-4", children: [
2013
- { type: "bug", label: "\u{1F41B} Bug", color: "red" },
2014
- { type: "feedback", label: "\u{1F4A1} Feedback", color: "blue" },
2015
- { type: "suggestion", label: "\u2728 Idea", color: "purple" }
2016
- ].map(({ type, label, color }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2017
- "button",
2018
- {
2019
- onClick: () => setReportType(type),
2020
- 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"}`,
2021
- children: label
2022
- },
2023
- type
2024
- )) }),
2025
- (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
2026
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Severity" }),
2027
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-1", children: ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2028
- "button",
2029
- {
2030
- onClick: () => setSeverity(sev),
2031
- 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"}`,
2032
- children: sev
2033
- },
2034
- sev
2035
- )) })
2036
- ] }),
2037
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-3", children: [
2038
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "What happened?" }),
2039
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2040
- "textarea",
2041
- {
2042
- value: description,
2043
- onChange: (e) => setDescription(e.target.value),
2044
- placeholder: "Describe the issue...",
2045
- rows: 3,
2046
- 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"
2069
+ onClick: handleCloseProfile,
2070
+ className: "text-sm text-zinc-400 hover:text-white transition-colors",
2071
+ children: "\u2190 Back"
2047
2072
  }
2048
- )
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
+ " "
2049
2077
  ] }),
2050
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2051
- "button",
2052
- {
2053
- onClick: handleSubmitReport,
2054
- disabled: submitting || !description.trim(),
2055
- 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",
2056
- children: submitting ? "Submitting..." : "Submit Report"
2057
- }
2058
- )
2059
- ] }) })
2060
- ] }),
2061
- 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: [
2062
- /* @__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: [
2063
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2064
- "button",
2065
- {
2066
- onClick: handleCloseProfile,
2067
- className: "text-sm text-zinc-400 hover:text-white transition-colors",
2068
- children: "\u2190 Back"
2069
- }
2070
- ),
2071
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-semibold text-sm", children: "Profile" }),
2072
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-12" }),
2073
- " "
2074
- ] }),
2075
- /* @__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: [
2076
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-4xl", children: "\u2705" }),
2077
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-zinc-400 mt-2 font-medium", children: "Profile saved!" })
2078
- ] }) : profileEditing ? (
2079
- /* Edit Profile Form */
2080
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
2081
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [
2082
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100", children: "Edit Profile" }),
2083
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2084
- "button",
2085
- {
2086
- onClick: handleCancelEditProfile,
2087
- className: "text-sm text-zinc-500 hover:text-zinc-300",
2088
- children: "Cancel"
2089
- }
2090
- )
2091
- ] }),
2092
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2093
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Name" }),
2094
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2095
- "input",
2096
- {
2097
- type: "text",
2098
- value: profileName,
2099
- onChange: (e) => setProfileName(e.target.value),
2100
- placeholder: "Your name",
2101
- 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"
2102
- }
2103
- )
2104
- ] }),
2105
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2106
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Primary Email" }),
2107
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-3 py-2 bg-zinc-800 rounded-lg", children: [
2108
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-zinc-300", children: testerInfo?.email }),
2109
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 mt-0.5", children: "Main communication email" })
2110
- ] })
2111
- ] }),
2112
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2113
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Additional Testing Emails" }),
2114
- /* @__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" }),
2115
- profileAdditionalEmails.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [
2116
- /* @__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 }),
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" }),
2117
2086
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2118
2087
  "button",
2119
2088
  {
2120
- onClick: () => handleRemoveEmail(email),
2121
- className: "text-blue-400 hover:text-red-500 text-sm",
2122
- children: "\u2715"
2089
+ onClick: handleCancelEditProfile,
2090
+ className: "text-sm text-zinc-500 hover:text-zinc-300",
2091
+ children: "Cancel"
2123
2092
  }
2124
2093
  )
2125
- ] }, email)),
2126
- /* @__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" }),
2127
2097
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2128
2098
  "input",
2129
2099
  {
2130
- type: "email",
2131
- value: newEmailInput,
2132
- onChange: (e) => setNewEmailInput(e.target.value),
2133
- placeholder: "email@example.com",
2134
- 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",
2135
- 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"
2136
2105
  }
2137
- ),
2138
- /* @__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)(
2139
2160
  "button",
2140
2161
  {
2141
- onClick: handleAddEmail,
2142
- disabled: !newEmailInput.trim(),
2143
- 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",
2144
- children: "Add"
2145
- }
2146
- )
2147
- ] })
2148
- ] }),
2149
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mb-4", children: [
2150
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "block text-xs font-medium text-zinc-300 mb-1", children: "Testing Platforms" }),
2151
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500 mb-2", children: "Select the platforms you can test on" }),
2152
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex gap-2", children: [
2153
- { key: "ios", label: "\u{1F4F1} iOS" },
2154
- { key: "android", label: "\u{1F916} Android" },
2155
- { key: "web", label: "\u{1F310} Web" }
2156
- ].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)(
2157
2170
  "button",
2158
2171
  {
2159
- onClick: () => handleTogglePlatform(key),
2160
- 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"}`,
2161
- children: label
2162
- },
2163
- key
2164
- )) })
2165
- ] }),
2166
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2167
- "button",
2168
- {
2169
- onClick: handleSaveProfile,
2170
- disabled: savingProfile,
2171
- 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",
2172
- children: savingProfile ? "Saving..." : "Save Profile"
2173
- }
2174
- )
2175
- ] })
2176
- ) : (
2177
- /* Profile View */
2178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
2179
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-4 text-center mb-4", children: [
2180
- /* @__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() || "?" }) }),
2181
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "font-semibold text-zinc-100", children: testerInfo?.name }),
2182
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-zinc-500", children: testerInfo?.email }),
2183
- /* @__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: [
2184
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
2185
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-blue-400", children: testerInfo?.assignedTests || 0 }),
2186
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-500", children: "Assigned" })
2187
- ] }),
2188
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "text-center", children: [
2189
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xl font-bold text-blue-400", children: testerInfo?.completedTests || 0 }),
2190
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-zinc-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
+ ] })
2191
2195
  ] })
2192
- ] })
2193
- ] }),
2194
- (testerInfo?.additionalEmails?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
2195
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-zinc-500 uppercase tracking-wide mb-2", children: "Additional Emails" }),
2196
- testerInfo?.additionalEmails?.map((email) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-sm text-zinc-300", children: email }, email))
2197
- ] }),
2198
- (testerInfo?.platforms?.length || 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bg-zinc-800 rounded-lg p-3 mb-3", children: [
2199
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-zinc-500 uppercase tracking-wide mb-2", children: "Testing Platforms" }),
2200
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex flex-wrap gap-2", children: testerInfo?.platforms?.map((platform) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2201
- "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",
2202
2214
  {
2203
- className: "px-2 py-1 bg-blue-900/50 text-blue-300 text-xs rounded-full font-medium",
2204
- children: platform === "ios" ? "\u{1F4F1} iOS" : platform === "android" ? "\u{1F916} Android" : "\u{1F310} Web"
2205
- },
2206
- platform
2207
- )) })
2208
- ] }),
2209
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2210
- "button",
2211
- {
2212
- onClick: handleStartEditProfile,
2213
- className: "w-full py-2 px-4 bg-blue-500 text-white rounded-lg font-medium text-sm hover:bg-blue-600 transition-colors",
2214
- children: "Edit Profile"
2215
- }
2216
- )
2217
- ] })
2218
- ) })
2219
- ] }),
2220
- /* @__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: [
2221
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
2222
- threads.length,
2223
- " thread",
2224
- threads.length !== 1 ? "s" : "",
2225
- " \xB7 ",
2226
- unreadCount,
2227
- " unread"
2228
- ] }),
2229
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2230
- "button",
2231
- {
2232
- onClick: refreshThreads,
2233
- className: "hover:text-zinc-300",
2234
- children: "\u21BB Refresh"
2235
- }
2236
- )
2237
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2238
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
2239
- pendingCount,
2240
- " pending \xB7 ",
2241
- inProgressCount,
2242
- " 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
+ ) })
2243
2222
  ] }),
2244
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2245
- "button",
2246
- {
2247
- onClick: refreshAssignments,
2248
- className: "hover:text-zinc-300",
2249
- children: "\u21BB Refresh"
2250
- }
2251
- )
2252
- ] }) })
2253
- ] })
2254
- ]
2255
- }
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
+ ] }) })
2256
+ ] })
2257
+ ]
2258
+ }
2259
+ ),
2260
+ document.body
2256
2261
  );
2257
2262
  }
2258
2263