@bbearai/react-native 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11510,6 +11510,9 @@ var BugBearClient = class {
11510
11510
  id,
11511
11511
  status,
11512
11512
  started_at,
11513
+ skip_reason,
11514
+ is_verification,
11515
+ original_report_id,
11513
11516
  test_case:test_cases(
11514
11517
  id,
11515
11518
  title,
@@ -11527,6 +11530,12 @@ var BugBearClient = class {
11527
11530
  test_template,
11528
11531
  rubric_mode,
11529
11532
  description
11533
+ ),
11534
+ group:test_groups(
11535
+ id,
11536
+ name,
11537
+ description,
11538
+ sort_order
11530
11539
  )
11531
11540
  )
11532
11541
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true });
@@ -11538,6 +11547,9 @@ var BugBearClient = class {
11538
11547
  id: item.id,
11539
11548
  status: item.status,
11540
11549
  startedAt: item.started_at,
11550
+ skipReason: item.skip_reason,
11551
+ isVerification: item.is_verification || false,
11552
+ originalReportId: item.original_report_id,
11541
11553
  testCase: {
11542
11554
  id: item.test_case.id,
11543
11555
  title: item.test_case.title,
@@ -11555,6 +11567,12 @@ var BugBearClient = class {
11555
11567
  testTemplate: item.test_case.track.test_template,
11556
11568
  rubricMode: item.test_case.track.rubric_mode || "pass_fail",
11557
11569
  description: item.test_case.track.description
11570
+ } : void 0,
11571
+ group: item.test_case.group ? {
11572
+ id: item.test_case.group.id,
11573
+ name: item.test_case.group.name,
11574
+ description: item.test_case.group.description,
11575
+ sortOrder: item.test_case.group.sort_order
11558
11576
  } : void 0
11559
11577
  }
11560
11578
  }));
@@ -11691,6 +11709,32 @@ var BugBearClient = class {
11691
11709
  return { success: false, error: message };
11692
11710
  }
11693
11711
  }
11712
+ /**
11713
+ * Skip a test assignment with a required reason
11714
+ * Marks the assignment as 'skipped' and records why it was skipped
11715
+ */
11716
+ async skipAssignment(assignmentId, reason, notes) {
11717
+ try {
11718
+ const updateData = {
11719
+ status: "skipped",
11720
+ skip_reason: reason,
11721
+ completed_at: (/* @__PURE__ */ new Date()).toISOString()
11722
+ };
11723
+ if (notes) {
11724
+ updateData.notes = notes;
11725
+ }
11726
+ const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11727
+ if (error) {
11728
+ console.error("BugBear: Failed to skip assignment", error);
11729
+ return { success: false, error: error.message };
11730
+ }
11731
+ return { success: true };
11732
+ } catch (err) {
11733
+ const message = err instanceof Error ? err.message : "Unknown error";
11734
+ console.error("BugBear: Error skipping assignment", err);
11735
+ return { success: false, error: message };
11736
+ }
11737
+ }
11694
11738
  /**
11695
11739
  * Submit feedback on a test case to help improve test quality
11696
11740
  * This empowers testers to shape better tests over time
@@ -12789,6 +12833,14 @@ var BugBearContext = (0, import_react.createContext)({
12789
12833
  markAsRead: async () => {
12790
12834
  },
12791
12835
  createThread: async () => ({ success: false }),
12836
+ // QA Sessions
12837
+ activeSession: null,
12838
+ sessionFindings: [],
12839
+ startSession: async () => ({ success: false }),
12840
+ endSession: async () => ({ success: false }),
12841
+ addFinding: async () => ({ success: false }),
12842
+ refreshSession: async () => {
12843
+ },
12792
12844
  refreshTesterStatus: async () => {
12793
12845
  },
12794
12846
  updateTesterProfile: async () => ({ success: false }),
@@ -12807,6 +12859,8 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12807
12859
  const [isLoading, setIsLoading] = (0, import_react.useState)(true);
12808
12860
  const [threads, setThreads] = (0, import_react.useState)([]);
12809
12861
  const [unreadCount, setUnreadCount] = (0, import_react.useState)(0);
12862
+ const [activeSession, setActiveSession] = (0, import_react.useState)(null);
12863
+ const [sessionFindings, setSessionFindings] = (0, import_react.useState)([]);
12810
12864
  const hasInitialized = (0, import_react.useRef)(false);
12811
12865
  const getDeviceInfo = (0, import_react.useCallback)(() => {
12812
12866
  const { width, height } = import_react_native.Dimensions.get("window");
@@ -12854,6 +12908,45 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12854
12908
  }
12855
12909
  return result;
12856
12910
  }, [client, refreshThreads]);
12911
+ const refreshSession = (0, import_react.useCallback)(async () => {
12912
+ if (!client) return;
12913
+ const session = await client.getActiveSession();
12914
+ setActiveSession(session);
12915
+ if (session) {
12916
+ const findings = await client.getSessionFindings(session.id);
12917
+ setSessionFindings(findings);
12918
+ } else {
12919
+ setSessionFindings([]);
12920
+ }
12921
+ }, [client]);
12922
+ const startSession = (0, import_react.useCallback)(async (options = {}) => {
12923
+ if (!client) return { success: false, error: "Client not initialized" };
12924
+ const result = await client.startSession(options);
12925
+ if (result.success && result.session) {
12926
+ setActiveSession(result.session);
12927
+ setSessionFindings([]);
12928
+ }
12929
+ return { success: result.success, error: result.error };
12930
+ }, [client]);
12931
+ const endSession = (0, import_react.useCallback)(async (notes) => {
12932
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12933
+ const routesCovered = client.getNavigationHistory();
12934
+ const result = await client.endSession(activeSession.id, { notes, routesCovered });
12935
+ if (result.success) {
12936
+ setActiveSession(null);
12937
+ setSessionFindings([]);
12938
+ }
12939
+ return { success: result.success, error: result.error };
12940
+ }, [client, activeSession]);
12941
+ const addFinding = (0, import_react.useCallback)(async (options) => {
12942
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12943
+ const result = await client.addFinding(activeSession.id, options);
12944
+ if (result.success && result.finding) {
12945
+ setSessionFindings((prev) => [...prev, result.finding]);
12946
+ setActiveSession((prev) => prev ? { ...prev, findingsCount: prev.findingsCount + 1 } : null);
12947
+ }
12948
+ return result;
12949
+ }, [client, activeSession]);
12857
12950
  const updateTesterProfile = (0, import_react.useCallback)(async (updates) => {
12858
12951
  if (!client) return { success: false, error: "Client not initialized" };
12859
12952
  const result = await client.updateTesterProfile(updates);
@@ -12880,14 +12973,20 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12880
12973
  setTesterInfo(info);
12881
12974
  setIsTester(!!info);
12882
12975
  if (info && qaEnabled) {
12883
- const [newAssignments, newThreads] = await Promise.all([
12976
+ const [newAssignments, newThreads, session] = await Promise.all([
12884
12977
  bugBearClient.getAssignedTests(),
12885
- bugBearClient.getThreadsForTester()
12978
+ bugBearClient.getThreadsForTester(),
12979
+ bugBearClient.getActiveSession()
12886
12980
  ]);
12887
12981
  setAssignments(newAssignments);
12888
12982
  setThreads(newThreads);
12889
12983
  const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
12890
12984
  setUnreadCount(totalUnread);
12985
+ setActiveSession(session);
12986
+ if (session) {
12987
+ const findings = await bugBearClient.getSessionFindings(session.id);
12988
+ setSessionFindings(findings);
12989
+ }
12891
12990
  }
12892
12991
  } catch (err) {
12893
12992
  console.error("BugBear: Init error", err);
@@ -12910,6 +13009,8 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12910
13009
  }, [enabled, config, initializeBugBear]);
12911
13010
  const currentAssignment = assignments.find(
12912
13011
  (a) => a.status === "in_progress"
13012
+ ) || assignments.find(
13013
+ (a) => a.status === "pending"
12913
13014
  ) || assignments[0] || null;
12914
13015
  const shouldShowWidget = isQAEnabled && isTester;
12915
13016
  return /* @__PURE__ */ import_react.default.createElement(
@@ -12934,6 +13035,13 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12934
13035
  sendMessage,
12935
13036
  markAsRead,
12936
13037
  createThread,
13038
+ // QA Sessions
13039
+ activeSession,
13040
+ sessionFindings,
13041
+ startSession,
13042
+ endSession,
13043
+ addFinding,
13044
+ refreshSession,
12937
13045
  refreshTesterStatus,
12938
13046
  updateTesterProfile,
12939
13047
  refreshTesterInfo
@@ -12981,7 +13089,13 @@ function BugBearButton({
12981
13089
  markAsRead,
12982
13090
  createThread,
12983
13091
  updateTesterProfile,
12984
- refreshTesterInfo
13092
+ refreshTesterInfo,
13093
+ activeSession,
13094
+ sessionFindings,
13095
+ startSession,
13096
+ endSession,
13097
+ addFinding,
13098
+ refreshSession
12985
13099
  } = useBugBear();
12986
13100
  const [modalVisible, setModalVisible] = (0, import_react2.useState)(false);
12987
13101
  const [activeTab, setActiveTab] = (0, import_react2.useState)("tests");
@@ -13069,39 +13183,250 @@ function BugBearButton({
13069
13183
  const [submitting, setSubmitting] = (0, import_react2.useState)(false);
13070
13184
  const [submitted, setSubmitted] = (0, import_react2.useState)(false);
13071
13185
  const [justPassed, setJustPassed] = (0, import_react2.useState)(false);
13186
+ const [showFeedbackPrompt, setShowFeedbackPrompt] = (0, import_react2.useState)(false);
13187
+ const [pendingFeedbackStatus, setPendingFeedbackStatus] = (0, import_react2.useState)(null);
13188
+ const [feedbackRating, setFeedbackRating] = (0, import_react2.useState)(5);
13189
+ const [feedbackNote, setFeedbackNote] = (0, import_react2.useState)("");
13190
+ const [feedbackFlags, setFeedbackFlags] = (0, import_react2.useState)({
13191
+ isOutdated: false,
13192
+ needsMoreDetail: false,
13193
+ stepsUnclear: false,
13194
+ expectedResultUnclear: false
13195
+ });
13072
13196
  const [criteriaResults, setCriteriaResults] = (0, import_react2.useState)({});
13197
+ const [showSkipModal, setShowSkipModal] = (0, import_react2.useState)(false);
13198
+ const [selectedSkipReason, setSelectedSkipReason] = (0, import_react2.useState)(null);
13199
+ const [skipNotes, setSkipNotes] = (0, import_react2.useState)("");
13200
+ const [skipping, setSkipping] = (0, import_react2.useState)(false);
13201
+ const [collapsedFolders, setCollapsedFolders] = (0, import_react2.useState)(/* @__PURE__ */ new Set());
13202
+ const [startingSession, setStartingSession] = (0, import_react2.useState)(false);
13203
+ const [sessionFocusArea, setSessionFocusArea] = (0, import_react2.useState)("");
13204
+ const [sessionPlatform, setSessionPlatform] = (0, import_react2.useState)(import_react_native2.Platform.OS === "ios" ? "ios" : "android");
13205
+ const [showAddFinding, setShowAddFinding] = (0, import_react2.useState)(false);
13206
+ const [findingType, setFindingType] = (0, import_react2.useState)("bug");
13207
+ const [findingTitle, setFindingTitle] = (0, import_react2.useState)("");
13208
+ const [findingDescription, setFindingDescription] = (0, import_react2.useState)("");
13209
+ const [findingSeverity, setFindingSeverity] = (0, import_react2.useState)("medium");
13210
+ const [addingFinding, setAddingFinding] = (0, import_react2.useState)(false);
13211
+ const [endingSession, setEndingSession] = (0, import_react2.useState)(false);
13212
+ const [sessionNotes, setSessionNotes] = (0, import_react2.useState)("");
13213
+ const [showEndConfirm, setShowEndConfirm] = (0, import_react2.useState)(false);
13214
+ const [sessionElapsedTime, setSessionElapsedTime] = (0, import_react2.useState)(0);
13215
+ const [assignmentElapsedTime, setAssignmentElapsedTime] = (0, import_react2.useState)(0);
13216
+ (0, import_react2.useEffect)(() => {
13217
+ const activeAssignment = displayedAssignment?.status === "in_progress" ? displayedAssignment : null;
13218
+ if (!activeAssignment?.startedAt) {
13219
+ setAssignmentElapsedTime(0);
13220
+ return;
13221
+ }
13222
+ const startTime = new Date(activeAssignment.startedAt).getTime();
13223
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13224
+ const interval = setInterval(() => {
13225
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13226
+ }, 1e3);
13227
+ return () => clearInterval(interval);
13228
+ }, [displayedAssignment?.id, displayedAssignment?.status, displayedAssignment?.startedAt]);
13229
+ (0, import_react2.useEffect)(() => {
13230
+ if (!activeSession) {
13231
+ setSessionElapsedTime(0);
13232
+ return;
13233
+ }
13234
+ const startTime = new Date(activeSession.startedAt).getTime();
13235
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13236
+ const interval = setInterval(() => {
13237
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13238
+ }, 1e3);
13239
+ return () => clearInterval(interval);
13240
+ }, [activeSession]);
13241
+ const formatElapsedTime = (seconds) => {
13242
+ const h = Math.floor(seconds / 3600);
13243
+ const m = Math.floor(seconds % 3600 / 60);
13244
+ const s = seconds % 60;
13245
+ if (h > 0) return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
13246
+ return `${m}:${s.toString().padStart(2, "0")}`;
13247
+ };
13073
13248
  (0, import_react2.useEffect)(() => {
13074
13249
  setCriteriaResults({});
13075
13250
  setShowSteps(false);
13076
13251
  }, [displayedAssignment?.id]);
13252
+ const groupedAssignments = (0, import_react2.useMemo)(() => {
13253
+ const groups = /* @__PURE__ */ new Map();
13254
+ for (const assignment of assignments) {
13255
+ const groupId = assignment.testCase.group?.id || "ungrouped";
13256
+ const group = assignment.testCase.group || null;
13257
+ if (!groups.has(groupId)) {
13258
+ groups.set(groupId, {
13259
+ group,
13260
+ assignments: [],
13261
+ stats: { total: 0, passed: 0, failed: 0, pending: 0, skipped: 0 }
13262
+ });
13263
+ }
13264
+ const folder = groups.get(groupId);
13265
+ folder.assignments.push(assignment);
13266
+ folder.stats.total++;
13267
+ if (assignment.status === "passed") folder.stats.passed++;
13268
+ else if (assignment.status === "failed") folder.stats.failed++;
13269
+ else if (assignment.status === "skipped") folder.stats.skipped++;
13270
+ else folder.stats.pending++;
13271
+ }
13272
+ const priorityOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
13273
+ const statusOrder = { in_progress: 0, pending: 1, failed: 2, skipped: 3, passed: 4 };
13274
+ for (const folder of groups.values()) {
13275
+ folder.assignments.sort((a, b) => {
13276
+ const statusDiff = (statusOrder[a.status] ?? 5) - (statusOrder[b.status] ?? 5);
13277
+ if (statusDiff !== 0) return statusDiff;
13278
+ return (priorityOrder[a.testCase.priority] ?? 4) - (priorityOrder[b.testCase.priority] ?? 4);
13279
+ });
13280
+ }
13281
+ const sortedGroups = Array.from(groups.values()).sort((a, b) => {
13282
+ if (!a.group && !b.group) return 0;
13283
+ if (!a.group) return 1;
13284
+ if (!b.group) return -1;
13285
+ return a.group.sortOrder - b.group.sortOrder;
13286
+ });
13287
+ return sortedGroups;
13288
+ }, [assignments]);
13289
+ const toggleFolderCollapse = (0, import_react2.useCallback)((groupId) => {
13290
+ setCollapsedFolders((prev) => {
13291
+ const next = new Set(prev);
13292
+ if (next.has(groupId)) {
13293
+ next.delete(groupId);
13294
+ } else {
13295
+ next.add(groupId);
13296
+ }
13297
+ return next;
13298
+ });
13299
+ }, []);
13300
+ const getStatusBadge = (status) => {
13301
+ switch (status) {
13302
+ case "passed":
13303
+ return { icon: "\u2705", label: "Passed", color: "#22c55e" };
13304
+ case "failed":
13305
+ return { icon: "\u274C", label: "Failed", color: "#ef4444" };
13306
+ case "skipped":
13307
+ return { icon: "\u23ED\uFE0F", label: "Skipped", color: "#eab308" };
13308
+ case "in_progress":
13309
+ return { icon: "\u{1F504}", label: "In Progress", color: "#3b82f6" };
13310
+ case "blocked":
13311
+ return { icon: "\u{1F6AB}", label: "Blocked", color: "#f97316" };
13312
+ case "pending":
13313
+ default:
13314
+ return { icon: "\u23F3", label: "Pending", color: "#71717a" };
13315
+ }
13316
+ };
13077
13317
  if (isLoading || !shouldShowWidget) {
13078
13318
  return null;
13079
13319
  }
13080
13320
  const pendingCount = assignments.filter((a) => a.status === "pending").length;
13081
13321
  const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
13322
+ const passedCount = assignments.filter((a) => a.status === "passed").length;
13323
+ const failedCount = assignments.filter((a) => a.status === "failed").length;
13324
+ const [testFilter, setTestFilter] = (0, import_react2.useState)("all");
13325
+ const handleNextTest = () => {
13326
+ const nextTest = assignments.find(
13327
+ (a) => a.id !== displayedAssignment?.id && (a.status === "pending" || a.status === "in_progress")
13328
+ );
13329
+ if (nextTest) {
13330
+ setSelectedTestId(nextTest.id);
13331
+ setTestView("detail");
13332
+ setShowSteps(false);
13333
+ }
13334
+ };
13082
13335
  const handlePass = async () => {
13336
+ if (!displayedAssignment) return;
13337
+ setPendingFeedbackStatus("passed");
13338
+ setShowFeedbackPrompt(true);
13339
+ setFeedbackRating(5);
13340
+ setFeedbackNote("");
13341
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13342
+ };
13343
+ const handleFail = () => {
13344
+ if (!displayedAssignment) return;
13345
+ setPendingFeedbackStatus("failed");
13346
+ setShowFeedbackPrompt(true);
13347
+ setFeedbackRating(3);
13348
+ setFeedbackNote("");
13349
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13350
+ };
13351
+ const handleSubmitFeedback = async (skipFeedback = false) => {
13083
13352
  if (!client || !displayedAssignment) return;
13084
13353
  setSubmitting(true);
13085
- await client.submitReport({
13086
- type: "test_pass",
13087
- description: `Test passed: ${displayedAssignment.testCase.title}`,
13088
- assignmentId: displayedAssignment.id,
13089
- testCaseId: displayedAssignment.testCase.id,
13090
- appContext: getAppContext?.() || { currentRoute: "unknown" },
13091
- deviceInfo: getDeviceInfo()
13092
- });
13093
- await refreshAssignments();
13094
- setSubmitting(false);
13095
- setJustPassed(true);
13096
- setTimeout(() => {
13097
- setJustPassed(false);
13354
+ const feedback = skipFeedback ? void 0 : {
13355
+ rating: feedbackRating,
13356
+ feedbackNote: feedbackNote.trim() || void 0,
13357
+ isOutdated: feedbackFlags.isOutdated,
13358
+ needsMoreDetail: feedbackFlags.needsMoreDetail,
13359
+ stepsUnclear: feedbackFlags.stepsUnclear,
13360
+ expectedResultUnclear: feedbackFlags.expectedResultUnclear
13361
+ };
13362
+ if (pendingFeedbackStatus === "passed") {
13363
+ await client.submitReport({
13364
+ type: "test_pass",
13365
+ description: `Test passed: ${displayedAssignment.testCase.title}`,
13366
+ assignmentId: displayedAssignment.id,
13367
+ testCaseId: displayedAssignment.testCase.id,
13368
+ appContext: getAppContext?.() || { currentRoute: "unknown" },
13369
+ deviceInfo: getDeviceInfo()
13370
+ });
13371
+ if (feedback) {
13372
+ await client.submitTestFeedback({
13373
+ testCaseId: displayedAssignment.testCase.id,
13374
+ assignmentId: displayedAssignment.id,
13375
+ feedback,
13376
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13377
+ });
13378
+ }
13379
+ await refreshAssignments();
13380
+ setSubmitting(false);
13381
+ setShowFeedbackPrompt(false);
13382
+ setPendingFeedbackStatus(null);
13383
+ setJustPassed(true);
13384
+ setTimeout(() => {
13385
+ setJustPassed(false);
13386
+ setSelectedTestId(null);
13387
+ setTestView("detail");
13388
+ }, 1200);
13389
+ } else if (pendingFeedbackStatus === "failed") {
13390
+ if (feedback) {
13391
+ await client.submitTestFeedback({
13392
+ testCaseId: displayedAssignment.testCase.id,
13393
+ assignmentId: displayedAssignment.id,
13394
+ feedback,
13395
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13396
+ });
13397
+ }
13398
+ setSubmitting(false);
13399
+ setShowFeedbackPrompt(false);
13400
+ setPendingFeedbackStatus(null);
13401
+ setActiveTab("report");
13402
+ setReportType("bug");
13403
+ }
13404
+ };
13405
+ const handleSkipFeedback = () => {
13406
+ handleSubmitFeedback(true);
13407
+ };
13408
+ const handleOpenSkipModal = () => {
13409
+ setShowSkipModal(true);
13410
+ setSelectedSkipReason(null);
13411
+ setSkipNotes("");
13412
+ };
13413
+ const handleSkip = async () => {
13414
+ if (!client || !displayedAssignment || !selectedSkipReason) return;
13415
+ setSkipping(true);
13416
+ const result = await client.skipAssignment(
13417
+ displayedAssignment.id,
13418
+ selectedSkipReason,
13419
+ skipNotes || void 0
13420
+ );
13421
+ if (result.success) {
13422
+ await refreshAssignments();
13423
+ setShowSkipModal(false);
13424
+ setSelectedSkipReason(null);
13425
+ setSkipNotes("");
13098
13426
  setSelectedTestId(null);
13099
13427
  setTestView("detail");
13100
- }, 1200);
13101
- };
13102
- const handleFail = () => {
13103
- setActiveTab("report");
13104
- setReportType("test_fail");
13428
+ }
13429
+ setSkipping(false);
13105
13430
  };
13106
13431
  const handleSubmitReport = async () => {
13107
13432
  if (!client || !description.trim()) return;
@@ -13149,14 +13474,19 @@ function BugBearButton({
13149
13474
  await markAsRead(thread.id);
13150
13475
  }
13151
13476
  };
13477
+ const [messageSendError, setMessageSendError] = (0, import_react2.useState)(false);
13152
13478
  const handleSendReply = async () => {
13153
13479
  if (!selectedThread || !replyText.trim()) return;
13154
13480
  setSendingReply(true);
13481
+ setMessageSendError(false);
13155
13482
  const success = await sendMessage(selectedThread.id, replyText.trim());
13156
13483
  if (success) {
13157
13484
  setReplyText("");
13158
13485
  const messages = await getThreadMessages(selectedThread.id);
13159
13486
  setThreadMessages(messages);
13487
+ } else {
13488
+ setMessageSendError(true);
13489
+ setTimeout(() => setMessageSendError(false), 3e3);
13160
13490
  }
13161
13491
  setSendingReply(false);
13162
13492
  };
@@ -13248,6 +13578,44 @@ function BugBearButton({
13248
13578
  }
13249
13579
  setSavingProfile(false);
13250
13580
  };
13581
+ const handleStartSession = async () => {
13582
+ setStartingSession(true);
13583
+ const result = await startSession({
13584
+ focusArea: sessionFocusArea.trim() || void 0,
13585
+ platform: sessionPlatform
13586
+ });
13587
+ if (result.success) {
13588
+ setSessionFocusArea("");
13589
+ }
13590
+ setStartingSession(false);
13591
+ };
13592
+ const handleEndSession = async () => {
13593
+ setEndingSession(true);
13594
+ const result = await endSession(sessionNotes.trim() || void 0);
13595
+ if (result.success) {
13596
+ setSessionNotes("");
13597
+ setShowEndConfirm(false);
13598
+ }
13599
+ setEndingSession(false);
13600
+ };
13601
+ const handleAddFinding = async () => {
13602
+ if (!findingTitle.trim()) return;
13603
+ setAddingFinding(true);
13604
+ const result = await addFinding({
13605
+ type: findingType,
13606
+ title: findingTitle.trim(),
13607
+ description: findingDescription.trim() || void 0,
13608
+ severity: findingType === "bug" ? findingSeverity : void 0
13609
+ });
13610
+ if (result.success) {
13611
+ setFindingTitle("");
13612
+ setFindingDescription("");
13613
+ setFindingType("bug");
13614
+ setFindingSeverity("medium");
13615
+ setShowAddFinding(false);
13616
+ }
13617
+ setAddingFinding(false);
13618
+ };
13251
13619
  const formatRelativeTime = (dateString) => {
13252
13620
  const date = new Date(dateString);
13253
13621
  const now = /* @__PURE__ */ new Date();
@@ -13423,7 +13791,7 @@ function BugBearButton({
13423
13791
  style: [styles.tab, activeTab === "tests" && styles.activeTab],
13424
13792
  onPress: () => setActiveTab("tests")
13425
13793
  },
13426
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "tests" && styles.activeTabText] }, "Tests ", pendingCount > 0 && `(${pendingCount})`)
13794
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "tests" && styles.activeTabText] }, "Tests ", assignments.length > 0 && `(${passedCount + failedCount}/${assignments.length})`)
13427
13795
  ), /* @__PURE__ */ import_react2.default.createElement(
13428
13796
  import_react_native2.TouchableOpacity,
13429
13797
  {
@@ -13431,6 +13799,13 @@ function BugBearButton({
13431
13799
  onPress: () => setActiveTab("messages")
13432
13800
  },
13433
13801
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.tabWithBadge }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "messages" && styles.activeTabText] }, "Messages"), unreadCount > 0 && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.tabBadge }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.tabBadgeText }, unreadCount)))
13802
+ ), /* @__PURE__ */ import_react2.default.createElement(
13803
+ import_react_native2.TouchableOpacity,
13804
+ {
13805
+ style: [styles.tab, activeTab === "explore" && styles.activeTab],
13806
+ onPress: () => setActiveTab("explore")
13807
+ },
13808
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.tabWithBadge }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "explore" && styles.activeTabText] }, "Explore"), activeSession && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.sessionDot }))
13434
13809
  ), /* @__PURE__ */ import_react2.default.createElement(
13435
13810
  import_react_native2.TouchableOpacity,
13436
13811
  {
@@ -13439,32 +13814,126 @@ function BugBearButton({
13439
13814
  },
13440
13815
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "report" && styles.activeTabText] }, "Report")
13441
13816
  )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.ScrollView, { style: styles.content }, activeTab === "tests" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, assignments.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u2705"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "All caught up!"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "No tests assigned")) : testView === "list" ? (
13442
- /* List View - Show all tests */
13443
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"), assignments.map((assignment) => /* @__PURE__ */ import_react2.default.createElement(
13817
+ /* List View - Show tests grouped by folder */
13818
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " \xB7 ", passedCount, " passed \xB7 ", failedCount, " failed"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.filterBar }, ["all", "pending", "completed"].map((f) => /* @__PURE__ */ import_react2.default.createElement(
13444
13819
  import_react_native2.TouchableOpacity,
13445
13820
  {
13446
- key: assignment.id,
13447
- onPress: () => {
13448
- setSelectedTestId(assignment.id);
13449
- setTestView("detail");
13450
- setShowSteps(false);
13821
+ key: f,
13822
+ style: [styles.filterChip, testFilter === f && styles.filterChipActive],
13823
+ onPress: () => setTestFilter(f)
13824
+ },
13825
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.filterChipText, testFilter === f && styles.filterChipTextActive] }, f === "all" ? `All (${assignments.length})` : f === "pending" ? `To Do (${pendingCount + inProgressCount})` : `Done (${passedCount + failedCount})`)
13826
+ ))), groupedAssignments.map((folder) => {
13827
+ const groupId = folder.group?.id || "ungrouped";
13828
+ const isCollapsed = collapsedFolders.has(groupId);
13829
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13830
+ return /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { key: groupId, style: styles.folderContainer }, /* @__PURE__ */ import_react2.default.createElement(
13831
+ import_react_native2.TouchableOpacity,
13832
+ {
13833
+ onPress: () => toggleFolderCollapse(groupId),
13834
+ style: styles.folderHeader
13451
13835
  },
13836
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.folderHeaderLeft }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderIcon }, isCollapsed ? "\u{1F4C1}" : "\u{1F4C2}"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderName }, folder.group?.name || "Ungrouped Tests")),
13837
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.folderStats }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderProgress }, completedCount, "/", folder.stats.total), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderChevron }, isCollapsed ? "\u25B6" : "\u25BC"))
13838
+ ), !isCollapsed && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.folderProgressBar }, /* @__PURE__ */ import_react2.default.createElement(
13839
+ import_react_native2.View,
13840
+ {
13841
+ style: [
13842
+ styles.folderProgressFill,
13843
+ { width: `${completedCount / folder.stats.total * 100}%` }
13844
+ ]
13845
+ }
13846
+ )), !isCollapsed && folder.assignments.filter((a) => {
13847
+ if (testFilter === "pending") return a.status === "pending" || a.status === "in_progress";
13848
+ if (testFilter === "completed") return a.status === "passed" || a.status === "failed" || a.status === "skipped";
13849
+ return true;
13850
+ }).map((assignment) => {
13851
+ const statusBadge = getStatusBadge(assignment.status);
13852
+ return /* @__PURE__ */ import_react2.default.createElement(
13853
+ import_react_native2.TouchableOpacity,
13854
+ {
13855
+ key: assignment.id,
13856
+ onPress: () => {
13857
+ setSelectedTestId(assignment.id);
13858
+ setTestView("detail");
13859
+ setShowSteps(false);
13860
+ },
13861
+ style: [
13862
+ styles.listItem,
13863
+ styles.listItemInFolder,
13864
+ assignment.id === currentAssignment?.id && styles.listItemCurrent
13865
+ ]
13866
+ },
13867
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemKeyWithStatus }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.statusBadge, { backgroundColor: statusBadge.color + "20" }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.statusBadgeIcon }, statusBadge.icon), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.statusBadgeText, { color: statusBadge.color }] }, statusBadge.label))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [
13868
+ styles.priorityBadge,
13869
+ assignment.testCase.priority === "P0" && styles.priorityP0,
13870
+ assignment.testCase.priority === "P1" && styles.priorityP1
13871
+ ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, assignment.testCase.priority)))),
13872
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
13873
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemMeta }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemMetaText }, assignment.testCase.steps.length, " ", assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"), assignment.id === currentAssignment?.id && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.currentBadge }, "\u2022 Current"))
13874
+ );
13875
+ }));
13876
+ }))
13877
+ ) : justPassed ? (
13878
+ /* Success state after passing */
13879
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Loading next test..."))
13880
+ ) : showFeedbackPrompt && displayedAssignment ? (
13881
+ /* Feedback prompt after completing a test */
13882
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.container }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { alignItems: "center", marginBottom: 16 } }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: { fontSize: 28 } }, pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [feedbackStyles.statusText, pendingFeedbackStatus === "passed" ? { color: "#4ade80" } : { color: "#f87171" }] }, pendingFeedbackStatus === "passed" ? "Test Passed!" : "Test Failed")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.infoBox }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.infoTitle }, "Help us improve this test"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.infoSubtitle }, "Your feedback shapes better tests for everyone.")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.ratingSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingLabel }, "How was this test?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.starsRow }, [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ import_react2.default.createElement(
13883
+ import_react_native2.TouchableOpacity,
13884
+ {
13885
+ key: star,
13886
+ onPress: () => setFeedbackRating(star)
13887
+ },
13888
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [feedbackStyles.star, star <= feedbackRating ? feedbackStyles.starActive : feedbackStyles.starInactive] }, "\u2605")
13889
+ ))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingDesc }, feedbackRating === 1 ? "Needs work" : feedbackRating === 2 ? "Could be better" : feedbackRating === 3 ? "Okay" : feedbackRating === 4 ? "Good" : "Great!")), feedbackRating < 4 && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.flagsSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingLabel }, "What could be improved?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.flagsGrid }, [
13890
+ { key: "stepsUnclear", label: "Steps unclear" },
13891
+ { key: "expectedResultUnclear", label: "Expected result unclear" },
13892
+ { key: "needsMoreDetail", label: "Needs more detail" },
13893
+ { key: "isOutdated", label: "Seems outdated" }
13894
+ ].map(({ key, label }) => /* @__PURE__ */ import_react2.default.createElement(
13895
+ import_react_native2.TouchableOpacity,
13896
+ {
13897
+ key,
13898
+ onPress: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
13452
13899
  style: [
13453
- styles.listItem,
13454
- assignment.id === currentAssignment?.id && styles.listItemCurrent
13900
+ feedbackStyles.flagButton,
13901
+ feedbackFlags[key] && feedbackStyles.flagButtonActive
13455
13902
  ]
13456
13903
  },
13457
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [
13458
- styles.priorityBadge,
13459
- assignment.testCase.priority === "P0" && styles.priorityP0,
13460
- assignment.testCase.priority === "P1" && styles.priorityP1
13461
- ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, assignment.testCase.priority)))),
13462
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
13463
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemMeta }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemMetaText }, assignment.testCase.steps.length, " ", assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"), assignment.id === currentAssignment?.id && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.currentBadge }, "\u2022 Current"))
13904
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
13905
+ feedbackStyles.flagButtonText,
13906
+ feedbackFlags[key] && feedbackStyles.flagButtonTextActive
13907
+ ] }, label)
13908
+ )))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { marginBottom: 12 } }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingLabel }, "Suggestions? (optional)"), /* @__PURE__ */ import_react2.default.createElement(
13909
+ import_react_native2.TextInput,
13910
+ {
13911
+ style: feedbackStyles.noteInput,
13912
+ value: feedbackNote,
13913
+ onChangeText: setFeedbackNote,
13914
+ placeholder: "How could this test be improved?",
13915
+ placeholderTextColor: "#71717a",
13916
+ multiline: true,
13917
+ numberOfLines: 2,
13918
+ textAlignVertical: "top"
13919
+ }
13920
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.buttonRow }, /* @__PURE__ */ import_react2.default.createElement(
13921
+ import_react_native2.TouchableOpacity,
13922
+ {
13923
+ onPress: handleSkipFeedback,
13924
+ disabled: submitting,
13925
+ style: [feedbackStyles.skipButton, submitting && { opacity: 0.5 }]
13926
+ },
13927
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.skipButtonText }, "Skip")
13928
+ ), /* @__PURE__ */ import_react2.default.createElement(
13929
+ import_react_native2.TouchableOpacity,
13930
+ {
13931
+ onPress: () => handleSubmitFeedback(false),
13932
+ disabled: submitting,
13933
+ style: [feedbackStyles.submitButton, submitting && { opacity: 0.5 }]
13934
+ },
13935
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.submitButtonText }, submitting ? "Submitting..." : "Submit Feedback")
13464
13936
  )))
13465
- ) : justPassed ? (
13466
- /* Success state after passing */
13467
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Loading next test..."))
13468
13937
  ) : displayedAssignment ? (
13469
13938
  /* Detail View - Show single test */
13470
13939
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(
@@ -13477,27 +13946,58 @@ function BugBearButton({
13477
13946
  style: styles.backButton
13478
13947
  },
13479
13948
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.backButtonText }, "\u2190 All Tests (", assignments.length, ")")
13480
- ), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.testCard }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.testHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testKey }, displayedAssignment.testCase.testKey), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.testHeaderBadges }, displayedAssignment.testCase.track && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.trackBadge, { backgroundColor: displayedAssignment.testCase.track.color }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.trackBadgeText }, templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [
13949
+ ), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.testCard }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.testHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testKey }, displayedAssignment.testCase.testKey), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.testHeaderBadges }, (() => {
13950
+ const badge = getStatusBadge(displayedAssignment.status);
13951
+ return /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.statusBadge, { backgroundColor: badge.color + "20" }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.statusBadgeIcon }, badge.icon), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.statusBadgeText, { color: badge.color }] }, badge.label));
13952
+ })(), displayedAssignment.testCase.track && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.trackBadge, { backgroundColor: displayedAssignment.testCase.track.color }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.trackBadgeText }, templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [
13481
13953
  styles.priorityBadge,
13482
13954
  displayedAssignment.testCase.priority === "P0" && styles.priorityP0,
13483
13955
  displayedAssignment.testCase.priority === "P1" && styles.priorityP1
13484
- ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.testCase.description && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.expectedResult }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.actionButtons }, /* @__PURE__ */ import_react2.default.createElement(
13956
+ ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.status === "in_progress" && displayedAssignment.startedAt && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: timerStyles.container }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: timerStyles.dot }), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: timerStyles.label }, "Testing"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: timerStyles.time }, formatElapsedTime(assignmentElapsedTime))), displayedAssignment.testCase.description && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.expectedResult }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), displayedAssignment.testCase.group && (() => {
13957
+ const folder = groupedAssignments.find((f) => f.group?.id === displayedAssignment.testCase.group?.id);
13958
+ if (!folder) return null;
13959
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13960
+ return /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.detailProgressContainer }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.detailProgressText }, folder.group?.name, ": ", completedCount, "/", folder.stats.total, " complete"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.detailProgressBar }, /* @__PURE__ */ import_react2.default.createElement(
13961
+ import_react_native2.View,
13962
+ {
13963
+ style: [
13964
+ styles.detailProgressFill,
13965
+ { width: `${completedCount / folder.stats.total * 100}%` }
13966
+ ]
13967
+ }
13968
+ )));
13969
+ })(), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.actionButtons }, /* @__PURE__ */ import_react2.default.createElement(
13485
13970
  import_react_native2.TouchableOpacity,
13486
13971
  {
13487
13972
  style: styles.failButton,
13488
13973
  onPress: handleFail,
13489
- disabled: submitting
13974
+ disabled: submitting || skipping
13490
13975
  },
13491
13976
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.failButtonText }, "\u2717 Fail")
13977
+ ), /* @__PURE__ */ import_react2.default.createElement(
13978
+ import_react_native2.TouchableOpacity,
13979
+ {
13980
+ style: styles.skipButton,
13981
+ onPress: handleOpenSkipModal,
13982
+ disabled: submitting || skipping
13983
+ },
13984
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipButtonText }, skipping ? "..." : "\u2192 Skip")
13492
13985
  ), /* @__PURE__ */ import_react2.default.createElement(
13493
13986
  import_react_native2.TouchableOpacity,
13494
13987
  {
13495
13988
  style: styles.passButton,
13496
13989
  onPress: handlePass,
13497
- disabled: submitting
13990
+ disabled: submitting || skipping
13498
13991
  },
13499
13992
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passButtonText }, submitting ? "..." : "\u2713 Pass")
13500
- )))
13993
+ )), pendingCount > 1 || pendingCount === 1 && displayedAssignment.status !== "pending" ? /* @__PURE__ */ import_react2.default.createElement(
13994
+ import_react_native2.TouchableOpacity,
13995
+ {
13996
+ style: styles.nextTestButton,
13997
+ onPress: handleNextTest
13998
+ },
13999
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.nextTestButtonText }, "Next Test \u25B6")
14000
+ ) : null)
13501
14001
  ) : null), activeTab === "messages" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, messageView === "compose" ? (
13502
14002
  /* Compose New Message View */
13503
14003
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: handleBackToThreadList, style: styles.backButton }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.backButtonText }, "\u2190 Back to Messages")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.composeHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.composeTitle }, "New Message"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.composeSubtitle }, "Send a message to the QA team")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.composeForm }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.label }, "Subject"), /* @__PURE__ */ import_react2.default.createElement(
@@ -13582,6 +14082,166 @@ function BugBearButton({
13582
14082
  message.senderType === "tester" && styles.messageTimeTester
13583
14083
  ] }, formatMessageTime(message.createdAt))
13584
14084
  ))))
14085
+ )), activeTab === "explore" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, !activeSession ? (
14086
+ /* Start Session View */
14087
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u{1F50D}"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "Exploratory QA Session"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Explore freely and capture findings as you go")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Focus Area (optional)"), /* @__PURE__ */ import_react2.default.createElement(
14088
+ import_react_native2.TextInput,
14089
+ {
14090
+ style: exploreStyles.input,
14091
+ value: sessionFocusArea,
14092
+ onChangeText: setSessionFocusArea,
14093
+ placeholder: "e.g., checkout flow, settings page",
14094
+ placeholderTextColor: "#71717a"
14095
+ }
14096
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Platform"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.platformRow }, [
14097
+ { key: "ios", label: "\u{1F4F1} iOS" },
14098
+ { key: "android", label: "\u{1F916} Android" },
14099
+ { key: "web", label: "\u{1F310} Web" }
14100
+ ].map(({ key, label }) => /* @__PURE__ */ import_react2.default.createElement(
14101
+ import_react_native2.TouchableOpacity,
14102
+ {
14103
+ key,
14104
+ onPress: () => setSessionPlatform(key),
14105
+ style: [
14106
+ exploreStyles.platformButton,
14107
+ sessionPlatform === key && exploreStyles.platformButtonActive
14108
+ ]
14109
+ },
14110
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14111
+ exploreStyles.platformButtonText,
14112
+ sessionPlatform === key && exploreStyles.platformButtonTextActive
14113
+ ] }, label)
14114
+ )))), /* @__PURE__ */ import_react2.default.createElement(
14115
+ import_react_native2.TouchableOpacity,
14116
+ {
14117
+ onPress: handleStartSession,
14118
+ disabled: startingSession,
14119
+ style: [exploreStyles.startButton, startingSession && { opacity: 0.5 }]
14120
+ },
14121
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.startButtonText }, startingSession ? "Starting..." : "\u25B6 Start Session")
14122
+ ))
14123
+ ) : showEndConfirm ? (
14124
+ /* End Session Confirmation */
14125
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u270B"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "End Session?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Duration: ", formatElapsedTime(sessionElapsedTime), " \xB7 ", sessionFindings.length, " finding", sessionFindings.length !== 1 ? "s" : "")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Session Notes (optional)"), /* @__PURE__ */ import_react2.default.createElement(
14126
+ import_react_native2.TextInput,
14127
+ {
14128
+ style: [exploreStyles.input, { height: 80, textAlignVertical: "top" }],
14129
+ value: sessionNotes,
14130
+ onChangeText: setSessionNotes,
14131
+ placeholder: "Any overall observations from this session...",
14132
+ placeholderTextColor: "#71717a",
14133
+ multiline: true
14134
+ }
14135
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.buttonRow }, /* @__PURE__ */ import_react2.default.createElement(
14136
+ import_react_native2.TouchableOpacity,
14137
+ {
14138
+ onPress: () => setShowEndConfirm(false),
14139
+ style: exploreStyles.cancelButton
14140
+ },
14141
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.cancelButtonText }, "Cancel")
14142
+ ), /* @__PURE__ */ import_react2.default.createElement(
14143
+ import_react_native2.TouchableOpacity,
14144
+ {
14145
+ onPress: handleEndSession,
14146
+ disabled: endingSession,
14147
+ style: [exploreStyles.endButton, endingSession && { opacity: 0.5 }]
14148
+ },
14149
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.endButtonText }, endingSession ? "Ending..." : "End Session")
14150
+ )))
14151
+ ) : showAddFinding ? (
14152
+ /* Add Finding Form */
14153
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingHeaderTitle }, "Add Finding"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: () => setShowAddFinding(false) }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingHeaderClose }, "\u2715"))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingTypeRow }, [
14154
+ { type: "bug", label: "\u{1F41B} Bug" },
14155
+ { type: "concern", label: "\u26A0\uFE0F Concern" },
14156
+ { type: "suggestion", label: "\u{1F4A1} Idea" },
14157
+ { type: "question", label: "\u2753 Q" }
14158
+ ].map(({ type, label }) => /* @__PURE__ */ import_react2.default.createElement(
14159
+ import_react_native2.TouchableOpacity,
14160
+ {
14161
+ key: type,
14162
+ onPress: () => setFindingType(type),
14163
+ style: [
14164
+ exploreStyles.findingTypeButton,
14165
+ findingType === type && exploreStyles.findingTypeButtonActive
14166
+ ]
14167
+ },
14168
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14169
+ exploreStyles.findingTypeButtonText,
14170
+ findingType === type && exploreStyles.findingTypeButtonTextActive
14171
+ ] }, label)
14172
+ ))), findingType === "bug" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Severity"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.severityRow }, ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ import_react2.default.createElement(
14173
+ import_react_native2.TouchableOpacity,
14174
+ {
14175
+ key: sev,
14176
+ onPress: () => setFindingSeverity(sev),
14177
+ style: [
14178
+ exploreStyles.severityButton,
14179
+ findingSeverity === sev && (sev === "critical" ? exploreStyles.severityCritical : sev === "high" ? exploreStyles.severityHigh : sev === "medium" ? exploreStyles.severityMedium : exploreStyles.severityLow)
14180
+ ]
14181
+ },
14182
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14183
+ exploreStyles.severityButtonText,
14184
+ findingSeverity === sev && exploreStyles.severityButtonTextActive
14185
+ ] }, sev)
14186
+ )))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Title *"), /* @__PURE__ */ import_react2.default.createElement(
14187
+ import_react_native2.TextInput,
14188
+ {
14189
+ style: exploreStyles.input,
14190
+ value: findingTitle,
14191
+ onChangeText: setFindingTitle,
14192
+ placeholder: "Brief description of what you found",
14193
+ placeholderTextColor: "#71717a"
14194
+ }
14195
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Details (optional)"), /* @__PURE__ */ import_react2.default.createElement(
14196
+ import_react_native2.TextInput,
14197
+ {
14198
+ style: [exploreStyles.input, { height: 60, textAlignVertical: "top" }],
14199
+ value: findingDescription,
14200
+ onChangeText: setFindingDescription,
14201
+ placeholder: "Steps to reproduce, expected behavior, etc.",
14202
+ placeholderTextColor: "#71717a",
14203
+ multiline: true
14204
+ }
14205
+ )), /* @__PURE__ */ import_react2.default.createElement(
14206
+ import_react_native2.TouchableOpacity,
14207
+ {
14208
+ onPress: handleAddFinding,
14209
+ disabled: addingFinding || !findingTitle.trim(),
14210
+ style: [exploreStyles.addFindingButton, (addingFinding || !findingTitle.trim()) && { opacity: 0.5 }]
14211
+ },
14212
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.addFindingButtonText }, addingFinding ? "Adding..." : "Add Finding")
14213
+ ))
14214
+ ) : (
14215
+ /* Active Session View */
14216
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionBanner }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionBannerRow }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionBannerLeft }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionDotLarge }), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.sessionBannerLabel }, "Session Active")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.sessionTimer }, formatElapsedTime(sessionElapsedTime))), activeSession.focusArea && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.sessionFocus }, "Focus: ", activeSession.focusArea)), /* @__PURE__ */ import_react2.default.createElement(
14217
+ import_react_native2.TouchableOpacity,
14218
+ {
14219
+ onPress: () => setShowAddFinding(true),
14220
+ style: exploreStyles.addButton
14221
+ },
14222
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.addButtonText }, "+ Add Finding")
14223
+ ), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingsSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingsLabel }, "Findings (", sessionFindings.length, ")"), sessionFindings.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingsEmpty }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingsEmptyText }, "No findings yet"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingsEmptyText }, "Explore and add findings as you go")) : /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, sessionFindings.map((finding) => /* @__PURE__ */ import_react2.default.createElement(
14224
+ import_react_native2.View,
14225
+ {
14226
+ key: finding.id,
14227
+ style: [
14228
+ exploreStyles.findingCard,
14229
+ finding.type === "bug" ? exploreStyles.findingCardBug : finding.type === "concern" ? exploreStyles.findingCardConcern : finding.type === "suggestion" ? exploreStyles.findingCardSuggestion : exploreStyles.findingCardQuestion
14230
+ ]
14231
+ },
14232
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingCardIcon }, finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753"),
14233
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { flex: 1 } }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingCardTitle, numberOfLines: 1 }, finding.title), finding.severity && finding.type === "bug" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14234
+ exploreStyles.findingCardSeverity,
14235
+ finding.severity === "critical" ? { color: "#f87171" } : finding.severity === "high" ? { color: "#fb923c" } : finding.severity === "medium" ? { color: "#facc15" } : { color: "#a1a1aa" }
14236
+ ] }, finding.severity))
14237
+ )))), /* @__PURE__ */ import_react2.default.createElement(
14238
+ import_react_native2.TouchableOpacity,
14239
+ {
14240
+ onPress: () => setShowEndConfirm(true),
14241
+ style: exploreStyles.endSessionButton
14242
+ },
14243
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.endSessionButtonText }, "End Session")
14244
+ ))
13585
14245
  )), activeTab === "report" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, submitted ? /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u{1F389}"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "Report submitted!")) : /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.reportTypes }, [
13586
14246
  { type: "bug", label: "\u{1F41B} Bug" },
13587
14247
  { type: "feedback", label: "\u{1F4A1} Feedback" },
@@ -13721,7 +14381,7 @@ function BugBearButton({
13721
14381
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.closeProfileButtonText }, "\u2190 Back")
13722
14382
  ))), activeTab === "messages" && messageView === "thread" && selectedThread ? (
13723
14383
  /* Reply Composer */
13724
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.replyComposer }, /* @__PURE__ */ import_react2.default.createElement(
14384
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, messageSendError && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.messageSendError }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.messageSendErrorText }, "Failed to send. Tap Send to retry.")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.replyComposer }, /* @__PURE__ */ import_react2.default.createElement(
13725
14385
  import_react_native2.TextInput,
13726
14386
  {
13727
14387
  style: styles.replyInput,
@@ -13743,12 +14403,67 @@ function BugBearButton({
13743
14403
  disabled: !replyText.trim() || sendingReply
13744
14404
  },
13745
14405
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.sendButtonText }, sendingReply ? "..." : "Send")
13746
- ))
14406
+ )))
13747
14407
  ) : (
13748
14408
  /* Standard Footer */
13749
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, pendingCount, " pending \xB7 ", inProgressCount, " in progress"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))))
14409
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))) : activeTab === "explore" ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, activeSession ? `${sessionFindings.length} findings` : "No active session"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshSession }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, passedCount + failedCount, "/", assignments.length, " done \xB7 ", pendingCount, " pending"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))))
13750
14410
  ))
13751
14411
  )
14412
+ ), /* @__PURE__ */ import_react2.default.createElement(
14413
+ import_react_native2.Modal,
14414
+ {
14415
+ visible: showSkipModal,
14416
+ transparent: true,
14417
+ animationType: "fade",
14418
+ onRequestClose: () => setShowSkipModal(false)
14419
+ },
14420
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipModalOverlay }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipModalContent }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalTitle }, "Skip Test"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalSubtitle }, "Why are you skipping this test?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipReasonOptions }, [
14421
+ { value: "blocked", label: "\u{1F6AB} Blocked", desc: "Something is preventing testing" },
14422
+ { value: "not_ready", label: "\u{1F6A7} Not Ready", desc: "Feature not yet implemented" },
14423
+ { value: "dependency", label: "\u{1F517} Dependency", desc: "Waiting on another test/feature" },
14424
+ { value: "other", label: "\u{1F4DD} Other", desc: "Different reason" }
14425
+ ].map((option) => /* @__PURE__ */ import_react2.default.createElement(
14426
+ import_react_native2.TouchableOpacity,
14427
+ {
14428
+ key: option.value,
14429
+ style: [
14430
+ styles.skipReasonOption,
14431
+ selectedSkipReason === option.value && styles.skipReasonOptionSelected
14432
+ ],
14433
+ onPress: () => setSelectedSkipReason(option.value)
14434
+ },
14435
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipReasonLabel }, option.label),
14436
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipReasonDesc }, option.desc)
14437
+ ))), /* @__PURE__ */ import_react2.default.createElement(
14438
+ import_react_native2.TextInput,
14439
+ {
14440
+ style: styles.skipNotesInput,
14441
+ value: skipNotes,
14442
+ onChangeText: setSkipNotes,
14443
+ placeholder: "Add notes (optional)...",
14444
+ placeholderTextColor: "#71717a",
14445
+ multiline: true,
14446
+ numberOfLines: 2
14447
+ }
14448
+ ), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipModalActions }, /* @__PURE__ */ import_react2.default.createElement(
14449
+ import_react_native2.TouchableOpacity,
14450
+ {
14451
+ style: styles.skipModalCancel,
14452
+ onPress: () => setShowSkipModal(false)
14453
+ },
14454
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalCancelText }, "Cancel")
14455
+ ), /* @__PURE__ */ import_react2.default.createElement(
14456
+ import_react_native2.TouchableOpacity,
14457
+ {
14458
+ style: [
14459
+ styles.skipModalConfirm,
14460
+ !selectedSkipReason && styles.skipModalConfirmDisabled
14461
+ ],
14462
+ onPress: handleSkip,
14463
+ disabled: !selectedSkipReason || skipping
14464
+ },
14465
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalConfirmText }, skipping ? "Skipping..." : "Skip Test")
14466
+ ))))
13752
14467
  ));
13753
14468
  }
13754
14469
  var styles = import_react_native2.StyleSheet.create({
@@ -13881,7 +14596,8 @@ var styles = import_react_native2.StyleSheet.create({
13881
14596
  justifyContent: "space-between",
13882
14597
  alignItems: "center",
13883
14598
  paddingHorizontal: 16,
13884
- paddingVertical: 12,
14599
+ paddingTop: 12,
14600
+ paddingBottom: import_react_native2.Platform.OS === "ios" ? 34 : 12,
13885
14601
  borderTopWidth: 1,
13886
14602
  borderTopColor: "#27272a",
13887
14603
  backgroundColor: "#09090b"
@@ -14451,6 +15167,13 @@ var styles = import_react_native2.StyleSheet.create({
14451
15167
  flexDirection: "row",
14452
15168
  alignItems: "center"
14453
15169
  },
15170
+ sessionDot: {
15171
+ width: 8,
15172
+ height: 8,
15173
+ borderRadius: 4,
15174
+ backgroundColor: "#22c55e",
15175
+ marginLeft: 4
15176
+ },
14454
15177
  tabBadge: {
14455
15178
  backgroundColor: "#EF4444",
14456
15179
  borderRadius: 8,
@@ -14622,7 +15345,9 @@ var styles = import_react_native2.StyleSheet.create({
14622
15345
  replyComposer: {
14623
15346
  flexDirection: "row",
14624
15347
  alignItems: "flex-end",
14625
- padding: 12,
15348
+ paddingHorizontal: 12,
15349
+ paddingTop: 12,
15350
+ paddingBottom: import_react_native2.Platform.OS === "ios" ? 34 : 12,
14626
15351
  borderTopWidth: 1,
14627
15352
  borderTopColor: "#27272a",
14628
15353
  backgroundColor: "#18181b"
@@ -15005,6 +15730,715 @@ var styles = import_react_native2.StyleSheet.create({
15005
15730
  fontSize: 14,
15006
15731
  fontWeight: "500",
15007
15732
  color: "#3B82F6"
15733
+ },
15734
+ // Folder grouping styles
15735
+ folderContainer: {
15736
+ marginBottom: 12
15737
+ },
15738
+ folderHeader: {
15739
+ flexDirection: "row",
15740
+ justifyContent: "space-between",
15741
+ alignItems: "center",
15742
+ backgroundColor: "#27272a",
15743
+ padding: 12,
15744
+ borderRadius: 8,
15745
+ marginBottom: 4
15746
+ },
15747
+ folderHeaderLeft: {
15748
+ flexDirection: "row",
15749
+ alignItems: "center",
15750
+ flex: 1
15751
+ },
15752
+ folderIcon: {
15753
+ fontSize: 16,
15754
+ marginRight: 8
15755
+ },
15756
+ folderName: {
15757
+ fontSize: 14,
15758
+ fontWeight: "600",
15759
+ color: "#fafafa"
15760
+ },
15761
+ folderStats: {
15762
+ flexDirection: "row",
15763
+ alignItems: "center"
15764
+ },
15765
+ folderProgress: {
15766
+ fontSize: 12,
15767
+ color: "#71717a",
15768
+ marginRight: 8
15769
+ },
15770
+ folderChevron: {
15771
+ fontSize: 10,
15772
+ color: "#71717a"
15773
+ },
15774
+ folderProgressBar: {
15775
+ height: 3,
15776
+ backgroundColor: "#3f3f46",
15777
+ borderRadius: 2,
15778
+ marginBottom: 8,
15779
+ marginHorizontal: 4
15780
+ },
15781
+ folderProgressFill: {
15782
+ height: "100%",
15783
+ backgroundColor: "#22c55e",
15784
+ borderRadius: 2
15785
+ },
15786
+ listItemInFolder: {
15787
+ marginLeft: 12,
15788
+ borderLeftWidth: 2,
15789
+ borderLeftColor: "#3f3f46",
15790
+ paddingLeft: 12
15791
+ },
15792
+ listItemKeyWithStatus: {
15793
+ flexDirection: "row",
15794
+ alignItems: "center",
15795
+ flex: 1
15796
+ },
15797
+ statusBadge: {
15798
+ flexDirection: "row",
15799
+ alignItems: "center",
15800
+ paddingHorizontal: 6,
15801
+ paddingVertical: 2,
15802
+ borderRadius: 4,
15803
+ marginLeft: 8
15804
+ },
15805
+ statusBadgeIcon: {
15806
+ fontSize: 10,
15807
+ marginRight: 4
15808
+ },
15809
+ statusBadgeText: {
15810
+ fontSize: 10,
15811
+ fontWeight: "600"
15812
+ },
15813
+ // Skip button styles
15814
+ skipButton: {
15815
+ flex: 1,
15816
+ backgroundColor: "#eab308",
15817
+ paddingVertical: 14,
15818
+ borderRadius: 12,
15819
+ alignItems: "center",
15820
+ marginHorizontal: 4
15821
+ },
15822
+ skipButtonText: {
15823
+ fontSize: 15,
15824
+ fontWeight: "600",
15825
+ color: "#18181b"
15826
+ },
15827
+ // Skip modal styles
15828
+ skipModalOverlay: {
15829
+ flex: 1,
15830
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
15831
+ justifyContent: "center",
15832
+ alignItems: "center",
15833
+ padding: 20
15834
+ },
15835
+ skipModalContent: {
15836
+ backgroundColor: "#18181b",
15837
+ borderRadius: 16,
15838
+ padding: 20,
15839
+ width: "100%",
15840
+ maxWidth: 340,
15841
+ borderWidth: 1,
15842
+ borderColor: "#3f3f46"
15843
+ },
15844
+ skipModalTitle: {
15845
+ fontSize: 18,
15846
+ fontWeight: "600",
15847
+ color: "#fafafa",
15848
+ marginBottom: 4
15849
+ },
15850
+ skipModalSubtitle: {
15851
+ fontSize: 14,
15852
+ color: "#71717a",
15853
+ marginBottom: 16
15854
+ },
15855
+ skipReasonOptions: {
15856
+ marginBottom: 16
15857
+ },
15858
+ skipReasonOption: {
15859
+ backgroundColor: "#27272a",
15860
+ padding: 12,
15861
+ borderRadius: 8,
15862
+ marginBottom: 8,
15863
+ borderWidth: 2,
15864
+ borderColor: "transparent"
15865
+ },
15866
+ skipReasonOptionSelected: {
15867
+ borderColor: "#eab308",
15868
+ backgroundColor: "#422006"
15869
+ },
15870
+ skipReasonLabel: {
15871
+ fontSize: 14,
15872
+ fontWeight: "600",
15873
+ color: "#fafafa",
15874
+ marginBottom: 2
15875
+ },
15876
+ skipReasonDesc: {
15877
+ fontSize: 12,
15878
+ color: "#71717a"
15879
+ },
15880
+ skipNotesInput: {
15881
+ backgroundColor: "#27272a",
15882
+ borderWidth: 1,
15883
+ borderColor: "#3f3f46",
15884
+ borderRadius: 8,
15885
+ padding: 12,
15886
+ fontSize: 14,
15887
+ color: "#fafafa",
15888
+ minHeight: 60,
15889
+ textAlignVertical: "top",
15890
+ marginBottom: 16
15891
+ },
15892
+ skipModalActions: {
15893
+ flexDirection: "row",
15894
+ gap: 8
15895
+ },
15896
+ skipModalCancel: {
15897
+ flex: 1,
15898
+ backgroundColor: "#3f3f46",
15899
+ paddingVertical: 12,
15900
+ borderRadius: 8,
15901
+ alignItems: "center"
15902
+ },
15903
+ skipModalCancelText: {
15904
+ fontSize: 14,
15905
+ fontWeight: "600",
15906
+ color: "#e4e4e7"
15907
+ },
15908
+ skipModalConfirm: {
15909
+ flex: 1,
15910
+ backgroundColor: "#eab308",
15911
+ paddingVertical: 12,
15912
+ borderRadius: 8,
15913
+ alignItems: "center"
15914
+ },
15915
+ skipModalConfirmDisabled: {
15916
+ backgroundColor: "#713f12"
15917
+ },
15918
+ skipModalConfirmText: {
15919
+ fontSize: 14,
15920
+ fontWeight: "600",
15921
+ color: "#18181b"
15922
+ },
15923
+ // Detail progress bar styles
15924
+ detailProgressContainer: {
15925
+ backgroundColor: "#27272a",
15926
+ padding: 12,
15927
+ borderRadius: 8,
15928
+ marginTop: 16,
15929
+ marginBottom: 8
15930
+ },
15931
+ detailProgressText: {
15932
+ fontSize: 12,
15933
+ color: "#a1a1aa",
15934
+ marginBottom: 8
15935
+ },
15936
+ detailProgressBar: {
15937
+ height: 4,
15938
+ backgroundColor: "#3f3f46",
15939
+ borderRadius: 2
15940
+ },
15941
+ detailProgressFill: {
15942
+ height: "100%",
15943
+ backgroundColor: "#22c55e",
15944
+ borderRadius: 2
15945
+ },
15946
+ nextTestButton: {
15947
+ backgroundColor: "#27272a",
15948
+ paddingVertical: 10,
15949
+ borderRadius: 10,
15950
+ alignItems: "center",
15951
+ marginTop: 8,
15952
+ borderWidth: 1,
15953
+ borderColor: "#3f3f46"
15954
+ },
15955
+ nextTestButtonText: {
15956
+ fontSize: 14,
15957
+ fontWeight: "500",
15958
+ color: "#a1a1aa"
15959
+ },
15960
+ filterBar: {
15961
+ flexDirection: "row",
15962
+ gap: 6,
15963
+ marginBottom: 10
15964
+ },
15965
+ filterChip: {
15966
+ paddingHorizontal: 10,
15967
+ paddingVertical: 5,
15968
+ borderRadius: 12,
15969
+ backgroundColor: "#27272a",
15970
+ borderWidth: 1,
15971
+ borderColor: "#3f3f46"
15972
+ },
15973
+ filterChipActive: {
15974
+ backgroundColor: "#1e3a5f",
15975
+ borderColor: "#3B82F6"
15976
+ },
15977
+ filterChipText: {
15978
+ fontSize: 12,
15979
+ color: "#71717a"
15980
+ },
15981
+ filterChipTextActive: {
15982
+ color: "#93c5fd"
15983
+ },
15984
+ messageSendError: {
15985
+ backgroundColor: "#7f1d1d",
15986
+ paddingHorizontal: 12,
15987
+ paddingVertical: 6,
15988
+ borderTopWidth: 1,
15989
+ borderTopColor: "#991b1b"
15990
+ },
15991
+ messageSendErrorText: {
15992
+ fontSize: 12,
15993
+ color: "#fca5a5",
15994
+ textAlign: "center"
15995
+ }
15996
+ });
15997
+ var exploreStyles = import_react_native2.StyleSheet.create({
15998
+ formGroup: {
15999
+ marginBottom: 12
16000
+ },
16001
+ label: {
16002
+ fontSize: 12,
16003
+ fontWeight: "500",
16004
+ color: "#d4d4d8",
16005
+ marginBottom: 6
16006
+ },
16007
+ input: {
16008
+ backgroundColor: "#27272a",
16009
+ borderRadius: 8,
16010
+ paddingHorizontal: 12,
16011
+ paddingVertical: 10,
16012
+ fontSize: 14,
16013
+ color: "#fafafa",
16014
+ borderWidth: 1,
16015
+ borderColor: "#3f3f46"
16016
+ },
16017
+ platformRow: {
16018
+ flexDirection: "row",
16019
+ gap: 8
16020
+ },
16021
+ platformButton: {
16022
+ flex: 1,
16023
+ paddingVertical: 10,
16024
+ paddingHorizontal: 8,
16025
+ borderRadius: 8,
16026
+ backgroundColor: "#27272a",
16027
+ borderWidth: 2,
16028
+ borderColor: "transparent",
16029
+ alignItems: "center"
16030
+ },
16031
+ platformButtonActive: {
16032
+ backgroundColor: "#172554",
16033
+ borderColor: "#3B82F6"
16034
+ },
16035
+ platformButtonText: {
16036
+ fontSize: 12,
16037
+ fontWeight: "500",
16038
+ color: "#a1a1aa"
16039
+ },
16040
+ platformButtonTextActive: {
16041
+ color: "#93c5fd"
16042
+ },
16043
+ startButton: {
16044
+ backgroundColor: "#16a34a",
16045
+ borderRadius: 8,
16046
+ paddingVertical: 14,
16047
+ alignItems: "center",
16048
+ marginTop: 4
16049
+ },
16050
+ startButtonText: {
16051
+ color: "#fff",
16052
+ fontSize: 14,
16053
+ fontWeight: "600"
16054
+ },
16055
+ buttonRow: {
16056
+ flexDirection: "row",
16057
+ gap: 8
16058
+ },
16059
+ cancelButton: {
16060
+ flex: 1,
16061
+ backgroundColor: "#3f3f46",
16062
+ borderRadius: 8,
16063
+ paddingVertical: 10,
16064
+ alignItems: "center"
16065
+ },
16066
+ cancelButtonText: {
16067
+ color: "#d4d4d8",
16068
+ fontSize: 14,
16069
+ fontWeight: "500"
16070
+ },
16071
+ endButton: {
16072
+ flex: 1,
16073
+ backgroundColor: "#dc2626",
16074
+ borderRadius: 8,
16075
+ paddingVertical: 10,
16076
+ alignItems: "center"
16077
+ },
16078
+ endButtonText: {
16079
+ color: "#fff",
16080
+ fontSize: 14,
16081
+ fontWeight: "500"
16082
+ },
16083
+ findingHeader: {
16084
+ flexDirection: "row",
16085
+ justifyContent: "space-between",
16086
+ alignItems: "center",
16087
+ marginBottom: 12
16088
+ },
16089
+ findingHeaderTitle: {
16090
+ fontSize: 14,
16091
+ fontWeight: "600",
16092
+ color: "#fafafa"
16093
+ },
16094
+ findingHeaderClose: {
16095
+ fontSize: 16,
16096
+ color: "#71717a"
16097
+ },
16098
+ findingTypeRow: {
16099
+ flexDirection: "row",
16100
+ gap: 4,
16101
+ marginBottom: 12
16102
+ },
16103
+ findingTypeButton: {
16104
+ flex: 1,
16105
+ paddingVertical: 8,
16106
+ paddingHorizontal: 4,
16107
+ borderRadius: 6,
16108
+ backgroundColor: "#3f3f46",
16109
+ alignItems: "center"
16110
+ },
16111
+ findingTypeButtonActive: {
16112
+ backgroundColor: "#1e3a5f",
16113
+ borderWidth: 2,
16114
+ borderColor: "#3B82F6"
16115
+ },
16116
+ findingTypeButtonText: {
16117
+ fontSize: 11,
16118
+ fontWeight: "500",
16119
+ color: "#a1a1aa"
16120
+ },
16121
+ findingTypeButtonTextActive: {
16122
+ color: "#93c5fd"
16123
+ },
16124
+ severityRow: {
16125
+ flexDirection: "row",
16126
+ gap: 4
16127
+ },
16128
+ severityButton: {
16129
+ flex: 1,
16130
+ paddingVertical: 6,
16131
+ borderRadius: 6,
16132
+ backgroundColor: "#3f3f46",
16133
+ alignItems: "center"
16134
+ },
16135
+ severityCritical: {
16136
+ backgroundColor: "#dc2626"
16137
+ },
16138
+ severityHigh: {
16139
+ backgroundColor: "#f97316"
16140
+ },
16141
+ severityMedium: {
16142
+ backgroundColor: "#eab308"
16143
+ },
16144
+ severityLow: {
16145
+ backgroundColor: "#3f3f46",
16146
+ borderWidth: 1,
16147
+ borderColor: "#71717a"
16148
+ },
16149
+ severityButtonText: {
16150
+ fontSize: 11,
16151
+ fontWeight: "500",
16152
+ color: "#a1a1aa",
16153
+ textTransform: "capitalize"
16154
+ },
16155
+ severityButtonTextActive: {
16156
+ color: "#fff"
16157
+ },
16158
+ addFindingButton: {
16159
+ backgroundColor: "#3B82F6",
16160
+ borderRadius: 8,
16161
+ paddingVertical: 10,
16162
+ alignItems: "center"
16163
+ },
16164
+ addFindingButtonText: {
16165
+ color: "#fff",
16166
+ fontSize: 14,
16167
+ fontWeight: "500"
16168
+ },
16169
+ sessionBanner: {
16170
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16171
+ borderRadius: 12,
16172
+ padding: 12,
16173
+ marginBottom: 12,
16174
+ borderWidth: 1,
16175
+ borderColor: "#166534"
16176
+ },
16177
+ sessionBannerRow: {
16178
+ flexDirection: "row",
16179
+ justifyContent: "space-between",
16180
+ alignItems: "center"
16181
+ },
16182
+ sessionBannerLeft: {
16183
+ flexDirection: "row",
16184
+ alignItems: "center",
16185
+ gap: 8
16186
+ },
16187
+ sessionDotLarge: {
16188
+ width: 8,
16189
+ height: 8,
16190
+ borderRadius: 4,
16191
+ backgroundColor: "#22c55e"
16192
+ },
16193
+ sessionBannerLabel: {
16194
+ fontSize: 14,
16195
+ fontWeight: "500",
16196
+ color: "#86efac"
16197
+ },
16198
+ sessionTimer: {
16199
+ fontSize: 20,
16200
+ fontWeight: "600",
16201
+ color: "#4ade80",
16202
+ fontVariant: ["tabular-nums"]
16203
+ },
16204
+ sessionFocus: {
16205
+ fontSize: 12,
16206
+ color: "#4ade80",
16207
+ marginTop: 4
16208
+ },
16209
+ addButton: {
16210
+ backgroundColor: "#3B82F6",
16211
+ borderRadius: 8,
16212
+ paddingVertical: 14,
16213
+ alignItems: "center",
16214
+ marginBottom: 12
16215
+ },
16216
+ addButtonText: {
16217
+ color: "#fff",
16218
+ fontSize: 14,
16219
+ fontWeight: "600"
16220
+ },
16221
+ findingsSection: {
16222
+ marginBottom: 12
16223
+ },
16224
+ findingsLabel: {
16225
+ fontSize: 12,
16226
+ fontWeight: "500",
16227
+ color: "#71717a",
16228
+ marginBottom: 8
16229
+ },
16230
+ findingsEmpty: {
16231
+ backgroundColor: "#27272a",
16232
+ borderRadius: 8,
16233
+ paddingVertical: 16,
16234
+ alignItems: "center"
16235
+ },
16236
+ findingsEmptyText: {
16237
+ fontSize: 12,
16238
+ color: "#71717a"
16239
+ },
16240
+ findingCard: {
16241
+ flexDirection: "row",
16242
+ alignItems: "flex-start",
16243
+ padding: 8,
16244
+ borderRadius: 8,
16245
+ marginBottom: 6,
16246
+ borderWidth: 1,
16247
+ gap: 8
16248
+ },
16249
+ findingCardBug: {
16250
+ backgroundColor: "rgba(220, 38, 38, 0.1)",
16251
+ borderColor: "#991b1b"
16252
+ },
16253
+ findingCardConcern: {
16254
+ backgroundColor: "rgba(249, 115, 22, 0.1)",
16255
+ borderColor: "#9a3412"
16256
+ },
16257
+ findingCardSuggestion: {
16258
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16259
+ borderColor: "#1e40af"
16260
+ },
16261
+ findingCardQuestion: {
16262
+ backgroundColor: "rgba(139, 92, 246, 0.1)",
16263
+ borderColor: "#5b21b6"
16264
+ },
16265
+ findingCardIcon: {
16266
+ fontSize: 14
16267
+ },
16268
+ findingCardTitle: {
16269
+ fontSize: 12,
16270
+ fontWeight: "500",
16271
+ color: "#fafafa"
16272
+ },
16273
+ findingCardSeverity: {
16274
+ fontSize: 10,
16275
+ fontWeight: "500",
16276
+ marginTop: 2,
16277
+ textTransform: "capitalize"
16278
+ },
16279
+ endSessionButton: {
16280
+ backgroundColor: "#3f3f46",
16281
+ borderRadius: 8,
16282
+ paddingVertical: 10,
16283
+ alignItems: "center"
16284
+ },
16285
+ endSessionButtonText: {
16286
+ color: "#d4d4d8",
16287
+ fontSize: 14,
16288
+ fontWeight: "500"
16289
+ }
16290
+ });
16291
+ var feedbackStyles = import_react_native2.StyleSheet.create({
16292
+ container: {
16293
+ padding: 4
16294
+ },
16295
+ statusText: {
16296
+ fontSize: 16,
16297
+ fontWeight: "600",
16298
+ marginTop: 4
16299
+ },
16300
+ infoBox: {
16301
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16302
+ borderRadius: 8,
16303
+ padding: 12,
16304
+ marginBottom: 16,
16305
+ borderWidth: 1,
16306
+ borderColor: "#1e3a5f"
16307
+ },
16308
+ infoTitle: {
16309
+ fontSize: 14,
16310
+ fontWeight: "500",
16311
+ color: "#93c5fd",
16312
+ marginBottom: 4
16313
+ },
16314
+ infoSubtitle: {
16315
+ fontSize: 12,
16316
+ color: "#60a5fa"
16317
+ },
16318
+ ratingSection: {
16319
+ alignItems: "center",
16320
+ marginBottom: 16
16321
+ },
16322
+ ratingLabel: {
16323
+ fontSize: 12,
16324
+ fontWeight: "500",
16325
+ color: "#a1a1aa",
16326
+ marginBottom: 8
16327
+ },
16328
+ starsRow: {
16329
+ flexDirection: "row",
16330
+ gap: 4
16331
+ },
16332
+ star: {
16333
+ fontSize: 28
16334
+ },
16335
+ starActive: {
16336
+ color: "#facc15"
16337
+ },
16338
+ starInactive: {
16339
+ color: "#3f3f46"
16340
+ },
16341
+ ratingDesc: {
16342
+ fontSize: 12,
16343
+ color: "#71717a",
16344
+ marginTop: 4
16345
+ },
16346
+ flagsSection: {
16347
+ marginBottom: 12
16348
+ },
16349
+ flagsGrid: {
16350
+ flexDirection: "row",
16351
+ flexWrap: "wrap",
16352
+ gap: 8
16353
+ },
16354
+ flagButton: {
16355
+ paddingHorizontal: 10,
16356
+ paddingVertical: 6,
16357
+ borderRadius: 6,
16358
+ backgroundColor: "#27272a",
16359
+ borderWidth: 1,
16360
+ borderColor: "#3f3f46"
16361
+ },
16362
+ flagButtonActive: {
16363
+ backgroundColor: "#1e3a5f",
16364
+ borderColor: "#3B82F6"
16365
+ },
16366
+ flagButtonText: {
16367
+ fontSize: 12,
16368
+ fontWeight: "500",
16369
+ color: "#a1a1aa"
16370
+ },
16371
+ flagButtonTextActive: {
16372
+ color: "#93c5fd"
16373
+ },
16374
+ noteInput: {
16375
+ backgroundColor: "#27272a",
16376
+ borderRadius: 8,
16377
+ paddingHorizontal: 12,
16378
+ paddingVertical: 10,
16379
+ fontSize: 14,
16380
+ color: "#fafafa",
16381
+ borderWidth: 1,
16382
+ borderColor: "#3f3f46",
16383
+ minHeight: 60
16384
+ },
16385
+ buttonRow: {
16386
+ flexDirection: "row",
16387
+ gap: 8
16388
+ },
16389
+ skipButton: {
16390
+ flex: 1,
16391
+ paddingVertical: 10,
16392
+ backgroundColor: "#3f3f46",
16393
+ borderRadius: 8,
16394
+ alignItems: "center"
16395
+ },
16396
+ skipButtonText: {
16397
+ color: "#a1a1aa",
16398
+ fontSize: 14,
16399
+ fontWeight: "500"
16400
+ },
16401
+ submitButton: {
16402
+ flex: 1,
16403
+ paddingVertical: 10,
16404
+ backgroundColor: "#3B82F6",
16405
+ borderRadius: 8,
16406
+ alignItems: "center"
16407
+ },
16408
+ submitButtonText: {
16409
+ color: "#fff",
16410
+ fontSize: 14,
16411
+ fontWeight: "500"
16412
+ }
16413
+ });
16414
+ var timerStyles = import_react_native2.StyleSheet.create({
16415
+ container: {
16416
+ flexDirection: "row",
16417
+ alignItems: "center",
16418
+ gap: 6,
16419
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16420
+ paddingHorizontal: 8,
16421
+ paddingVertical: 4,
16422
+ borderRadius: 6,
16423
+ marginBottom: 8,
16424
+ alignSelf: "flex-start"
16425
+ },
16426
+ dot: {
16427
+ width: 6,
16428
+ height: 6,
16429
+ borderRadius: 3,
16430
+ backgroundColor: "#22c55e"
16431
+ },
16432
+ label: {
16433
+ fontSize: 12,
16434
+ fontWeight: "500",
16435
+ color: "#4ade80"
16436
+ },
16437
+ time: {
16438
+ fontSize: 12,
16439
+ fontWeight: "600",
16440
+ color: "#4ade80",
16441
+ fontVariant: ["tabular-nums"]
15008
16442
  }
15009
16443
  });
15010
16444
  // Annotate the CommonJS export names for ESM import in node: