@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.mjs CHANGED
@@ -11472,6 +11472,9 @@ var BugBearClient = class {
11472
11472
  id,
11473
11473
  status,
11474
11474
  started_at,
11475
+ skip_reason,
11476
+ is_verification,
11477
+ original_report_id,
11475
11478
  test_case:test_cases(
11476
11479
  id,
11477
11480
  title,
@@ -11489,6 +11492,12 @@ var BugBearClient = class {
11489
11492
  test_template,
11490
11493
  rubric_mode,
11491
11494
  description
11495
+ ),
11496
+ group:test_groups(
11497
+ id,
11498
+ name,
11499
+ description,
11500
+ sort_order
11492
11501
  )
11493
11502
  )
11494
11503
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true });
@@ -11500,6 +11509,9 @@ var BugBearClient = class {
11500
11509
  id: item.id,
11501
11510
  status: item.status,
11502
11511
  startedAt: item.started_at,
11512
+ skipReason: item.skip_reason,
11513
+ isVerification: item.is_verification || false,
11514
+ originalReportId: item.original_report_id,
11503
11515
  testCase: {
11504
11516
  id: item.test_case.id,
11505
11517
  title: item.test_case.title,
@@ -11517,6 +11529,12 @@ var BugBearClient = class {
11517
11529
  testTemplate: item.test_case.track.test_template,
11518
11530
  rubricMode: item.test_case.track.rubric_mode || "pass_fail",
11519
11531
  description: item.test_case.track.description
11532
+ } : void 0,
11533
+ group: item.test_case.group ? {
11534
+ id: item.test_case.group.id,
11535
+ name: item.test_case.group.name,
11536
+ description: item.test_case.group.description,
11537
+ sortOrder: item.test_case.group.sort_order
11520
11538
  } : void 0
11521
11539
  }
11522
11540
  }));
@@ -11653,6 +11671,32 @@ var BugBearClient = class {
11653
11671
  return { success: false, error: message };
11654
11672
  }
11655
11673
  }
11674
+ /**
11675
+ * Skip a test assignment with a required reason
11676
+ * Marks the assignment as 'skipped' and records why it was skipped
11677
+ */
11678
+ async skipAssignment(assignmentId, reason, notes) {
11679
+ try {
11680
+ const updateData = {
11681
+ status: "skipped",
11682
+ skip_reason: reason,
11683
+ completed_at: (/* @__PURE__ */ new Date()).toISOString()
11684
+ };
11685
+ if (notes) {
11686
+ updateData.notes = notes;
11687
+ }
11688
+ const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11689
+ if (error) {
11690
+ console.error("BugBear: Failed to skip assignment", error);
11691
+ return { success: false, error: error.message };
11692
+ }
11693
+ return { success: true };
11694
+ } catch (err) {
11695
+ const message = err instanceof Error ? err.message : "Unknown error";
11696
+ console.error("BugBear: Error skipping assignment", err);
11697
+ return { success: false, error: message };
11698
+ }
11699
+ }
11656
11700
  /**
11657
11701
  * Submit feedback on a test case to help improve test quality
11658
11702
  * This empowers testers to shape better tests over time
@@ -12751,6 +12795,14 @@ var BugBearContext = createContext({
12751
12795
  markAsRead: async () => {
12752
12796
  },
12753
12797
  createThread: async () => ({ success: false }),
12798
+ // QA Sessions
12799
+ activeSession: null,
12800
+ sessionFindings: [],
12801
+ startSession: async () => ({ success: false }),
12802
+ endSession: async () => ({ success: false }),
12803
+ addFinding: async () => ({ success: false }),
12804
+ refreshSession: async () => {
12805
+ },
12754
12806
  refreshTesterStatus: async () => {
12755
12807
  },
12756
12808
  updateTesterProfile: async () => ({ success: false }),
@@ -12769,6 +12821,8 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12769
12821
  const [isLoading, setIsLoading] = useState(true);
12770
12822
  const [threads, setThreads] = useState([]);
12771
12823
  const [unreadCount, setUnreadCount] = useState(0);
12824
+ const [activeSession, setActiveSession] = useState(null);
12825
+ const [sessionFindings, setSessionFindings] = useState([]);
12772
12826
  const hasInitialized = useRef(false);
12773
12827
  const getDeviceInfo = useCallback(() => {
12774
12828
  const { width, height } = Dimensions.get("window");
@@ -12816,6 +12870,45 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12816
12870
  }
12817
12871
  return result;
12818
12872
  }, [client, refreshThreads]);
12873
+ const refreshSession = useCallback(async () => {
12874
+ if (!client) return;
12875
+ const session = await client.getActiveSession();
12876
+ setActiveSession(session);
12877
+ if (session) {
12878
+ const findings = await client.getSessionFindings(session.id);
12879
+ setSessionFindings(findings);
12880
+ } else {
12881
+ setSessionFindings([]);
12882
+ }
12883
+ }, [client]);
12884
+ const startSession = useCallback(async (options = {}) => {
12885
+ if (!client) return { success: false, error: "Client not initialized" };
12886
+ const result = await client.startSession(options);
12887
+ if (result.success && result.session) {
12888
+ setActiveSession(result.session);
12889
+ setSessionFindings([]);
12890
+ }
12891
+ return { success: result.success, error: result.error };
12892
+ }, [client]);
12893
+ const endSession = useCallback(async (notes) => {
12894
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12895
+ const routesCovered = client.getNavigationHistory();
12896
+ const result = await client.endSession(activeSession.id, { notes, routesCovered });
12897
+ if (result.success) {
12898
+ setActiveSession(null);
12899
+ setSessionFindings([]);
12900
+ }
12901
+ return { success: result.success, error: result.error };
12902
+ }, [client, activeSession]);
12903
+ const addFinding = useCallback(async (options) => {
12904
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12905
+ const result = await client.addFinding(activeSession.id, options);
12906
+ if (result.success && result.finding) {
12907
+ setSessionFindings((prev) => [...prev, result.finding]);
12908
+ setActiveSession((prev) => prev ? { ...prev, findingsCount: prev.findingsCount + 1 } : null);
12909
+ }
12910
+ return result;
12911
+ }, [client, activeSession]);
12819
12912
  const updateTesterProfile = useCallback(async (updates) => {
12820
12913
  if (!client) return { success: false, error: "Client not initialized" };
12821
12914
  const result = await client.updateTesterProfile(updates);
@@ -12842,14 +12935,20 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12842
12935
  setTesterInfo(info);
12843
12936
  setIsTester(!!info);
12844
12937
  if (info && qaEnabled) {
12845
- const [newAssignments, newThreads] = await Promise.all([
12938
+ const [newAssignments, newThreads, session] = await Promise.all([
12846
12939
  bugBearClient.getAssignedTests(),
12847
- bugBearClient.getThreadsForTester()
12940
+ bugBearClient.getThreadsForTester(),
12941
+ bugBearClient.getActiveSession()
12848
12942
  ]);
12849
12943
  setAssignments(newAssignments);
12850
12944
  setThreads(newThreads);
12851
12945
  const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
12852
12946
  setUnreadCount(totalUnread);
12947
+ setActiveSession(session);
12948
+ if (session) {
12949
+ const findings = await bugBearClient.getSessionFindings(session.id);
12950
+ setSessionFindings(findings);
12951
+ }
12853
12952
  }
12854
12953
  } catch (err) {
12855
12954
  console.error("BugBear: Init error", err);
@@ -12872,6 +12971,8 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12872
12971
  }, [enabled, config, initializeBugBear]);
12873
12972
  const currentAssignment = assignments.find(
12874
12973
  (a) => a.status === "in_progress"
12974
+ ) || assignments.find(
12975
+ (a) => a.status === "pending"
12875
12976
  ) || assignments[0] || null;
12876
12977
  const shouldShowWidget = isQAEnabled && isTester;
12877
12978
  return /* @__PURE__ */ React.createElement(
@@ -12896,6 +12997,13 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12896
12997
  sendMessage,
12897
12998
  markAsRead,
12898
12999
  createThread,
13000
+ // QA Sessions
13001
+ activeSession,
13002
+ sessionFindings,
13003
+ startSession,
13004
+ endSession,
13005
+ addFinding,
13006
+ refreshSession,
12899
13007
  refreshTesterStatus,
12900
13008
  updateTesterProfile,
12901
13009
  refreshTesterInfo
@@ -12906,7 +13014,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12906
13014
  }
12907
13015
 
12908
13016
  // src/BugBearButton.tsx
12909
- import React2, { useState as useState2, useEffect as useEffect2, useRef as useRef2 } from "react";
13017
+ import React2, { useState as useState2, useEffect as useEffect2, useRef as useRef2, useMemo, useCallback as useCallback2 } from "react";
12910
13018
  import {
12911
13019
  View,
12912
13020
  Text,
@@ -12956,7 +13064,13 @@ function BugBearButton({
12956
13064
  markAsRead,
12957
13065
  createThread,
12958
13066
  updateTesterProfile,
12959
- refreshTesterInfo
13067
+ refreshTesterInfo,
13068
+ activeSession,
13069
+ sessionFindings,
13070
+ startSession,
13071
+ endSession,
13072
+ addFinding,
13073
+ refreshSession
12960
13074
  } = useBugBear();
12961
13075
  const [modalVisible, setModalVisible] = useState2(false);
12962
13076
  const [activeTab, setActiveTab] = useState2("tests");
@@ -13044,39 +13158,250 @@ function BugBearButton({
13044
13158
  const [submitting, setSubmitting] = useState2(false);
13045
13159
  const [submitted, setSubmitted] = useState2(false);
13046
13160
  const [justPassed, setJustPassed] = useState2(false);
13161
+ const [showFeedbackPrompt, setShowFeedbackPrompt] = useState2(false);
13162
+ const [pendingFeedbackStatus, setPendingFeedbackStatus] = useState2(null);
13163
+ const [feedbackRating, setFeedbackRating] = useState2(5);
13164
+ const [feedbackNote, setFeedbackNote] = useState2("");
13165
+ const [feedbackFlags, setFeedbackFlags] = useState2({
13166
+ isOutdated: false,
13167
+ needsMoreDetail: false,
13168
+ stepsUnclear: false,
13169
+ expectedResultUnclear: false
13170
+ });
13047
13171
  const [criteriaResults, setCriteriaResults] = useState2({});
13172
+ const [showSkipModal, setShowSkipModal] = useState2(false);
13173
+ const [selectedSkipReason, setSelectedSkipReason] = useState2(null);
13174
+ const [skipNotes, setSkipNotes] = useState2("");
13175
+ const [skipping, setSkipping] = useState2(false);
13176
+ const [collapsedFolders, setCollapsedFolders] = useState2(/* @__PURE__ */ new Set());
13177
+ const [startingSession, setStartingSession] = useState2(false);
13178
+ const [sessionFocusArea, setSessionFocusArea] = useState2("");
13179
+ const [sessionPlatform, setSessionPlatform] = useState2(Platform2.OS === "ios" ? "ios" : "android");
13180
+ const [showAddFinding, setShowAddFinding] = useState2(false);
13181
+ const [findingType, setFindingType] = useState2("bug");
13182
+ const [findingTitle, setFindingTitle] = useState2("");
13183
+ const [findingDescription, setFindingDescription] = useState2("");
13184
+ const [findingSeverity, setFindingSeverity] = useState2("medium");
13185
+ const [addingFinding, setAddingFinding] = useState2(false);
13186
+ const [endingSession, setEndingSession] = useState2(false);
13187
+ const [sessionNotes, setSessionNotes] = useState2("");
13188
+ const [showEndConfirm, setShowEndConfirm] = useState2(false);
13189
+ const [sessionElapsedTime, setSessionElapsedTime] = useState2(0);
13190
+ const [assignmentElapsedTime, setAssignmentElapsedTime] = useState2(0);
13191
+ useEffect2(() => {
13192
+ const activeAssignment = displayedAssignment?.status === "in_progress" ? displayedAssignment : null;
13193
+ if (!activeAssignment?.startedAt) {
13194
+ setAssignmentElapsedTime(0);
13195
+ return;
13196
+ }
13197
+ const startTime = new Date(activeAssignment.startedAt).getTime();
13198
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13199
+ const interval = setInterval(() => {
13200
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13201
+ }, 1e3);
13202
+ return () => clearInterval(interval);
13203
+ }, [displayedAssignment?.id, displayedAssignment?.status, displayedAssignment?.startedAt]);
13204
+ useEffect2(() => {
13205
+ if (!activeSession) {
13206
+ setSessionElapsedTime(0);
13207
+ return;
13208
+ }
13209
+ const startTime = new Date(activeSession.startedAt).getTime();
13210
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13211
+ const interval = setInterval(() => {
13212
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13213
+ }, 1e3);
13214
+ return () => clearInterval(interval);
13215
+ }, [activeSession]);
13216
+ const formatElapsedTime = (seconds) => {
13217
+ const h = Math.floor(seconds / 3600);
13218
+ const m = Math.floor(seconds % 3600 / 60);
13219
+ const s = seconds % 60;
13220
+ if (h > 0) return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
13221
+ return `${m}:${s.toString().padStart(2, "0")}`;
13222
+ };
13048
13223
  useEffect2(() => {
13049
13224
  setCriteriaResults({});
13050
13225
  setShowSteps(false);
13051
13226
  }, [displayedAssignment?.id]);
13227
+ const groupedAssignments = useMemo(() => {
13228
+ const groups = /* @__PURE__ */ new Map();
13229
+ for (const assignment of assignments) {
13230
+ const groupId = assignment.testCase.group?.id || "ungrouped";
13231
+ const group = assignment.testCase.group || null;
13232
+ if (!groups.has(groupId)) {
13233
+ groups.set(groupId, {
13234
+ group,
13235
+ assignments: [],
13236
+ stats: { total: 0, passed: 0, failed: 0, pending: 0, skipped: 0 }
13237
+ });
13238
+ }
13239
+ const folder = groups.get(groupId);
13240
+ folder.assignments.push(assignment);
13241
+ folder.stats.total++;
13242
+ if (assignment.status === "passed") folder.stats.passed++;
13243
+ else if (assignment.status === "failed") folder.stats.failed++;
13244
+ else if (assignment.status === "skipped") folder.stats.skipped++;
13245
+ else folder.stats.pending++;
13246
+ }
13247
+ const priorityOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
13248
+ const statusOrder = { in_progress: 0, pending: 1, failed: 2, skipped: 3, passed: 4 };
13249
+ for (const folder of groups.values()) {
13250
+ folder.assignments.sort((a, b) => {
13251
+ const statusDiff = (statusOrder[a.status] ?? 5) - (statusOrder[b.status] ?? 5);
13252
+ if (statusDiff !== 0) return statusDiff;
13253
+ return (priorityOrder[a.testCase.priority] ?? 4) - (priorityOrder[b.testCase.priority] ?? 4);
13254
+ });
13255
+ }
13256
+ const sortedGroups = Array.from(groups.values()).sort((a, b) => {
13257
+ if (!a.group && !b.group) return 0;
13258
+ if (!a.group) return 1;
13259
+ if (!b.group) return -1;
13260
+ return a.group.sortOrder - b.group.sortOrder;
13261
+ });
13262
+ return sortedGroups;
13263
+ }, [assignments]);
13264
+ const toggleFolderCollapse = useCallback2((groupId) => {
13265
+ setCollapsedFolders((prev) => {
13266
+ const next = new Set(prev);
13267
+ if (next.has(groupId)) {
13268
+ next.delete(groupId);
13269
+ } else {
13270
+ next.add(groupId);
13271
+ }
13272
+ return next;
13273
+ });
13274
+ }, []);
13275
+ const getStatusBadge = (status) => {
13276
+ switch (status) {
13277
+ case "passed":
13278
+ return { icon: "\u2705", label: "Passed", color: "#22c55e" };
13279
+ case "failed":
13280
+ return { icon: "\u274C", label: "Failed", color: "#ef4444" };
13281
+ case "skipped":
13282
+ return { icon: "\u23ED\uFE0F", label: "Skipped", color: "#eab308" };
13283
+ case "in_progress":
13284
+ return { icon: "\u{1F504}", label: "In Progress", color: "#3b82f6" };
13285
+ case "blocked":
13286
+ return { icon: "\u{1F6AB}", label: "Blocked", color: "#f97316" };
13287
+ case "pending":
13288
+ default:
13289
+ return { icon: "\u23F3", label: "Pending", color: "#71717a" };
13290
+ }
13291
+ };
13052
13292
  if (isLoading || !shouldShowWidget) {
13053
13293
  return null;
13054
13294
  }
13055
13295
  const pendingCount = assignments.filter((a) => a.status === "pending").length;
13056
13296
  const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
13297
+ const passedCount = assignments.filter((a) => a.status === "passed").length;
13298
+ const failedCount = assignments.filter((a) => a.status === "failed").length;
13299
+ const [testFilter, setTestFilter] = useState2("all");
13300
+ const handleNextTest = () => {
13301
+ const nextTest = assignments.find(
13302
+ (a) => a.id !== displayedAssignment?.id && (a.status === "pending" || a.status === "in_progress")
13303
+ );
13304
+ if (nextTest) {
13305
+ setSelectedTestId(nextTest.id);
13306
+ setTestView("detail");
13307
+ setShowSteps(false);
13308
+ }
13309
+ };
13057
13310
  const handlePass = async () => {
13311
+ if (!displayedAssignment) return;
13312
+ setPendingFeedbackStatus("passed");
13313
+ setShowFeedbackPrompt(true);
13314
+ setFeedbackRating(5);
13315
+ setFeedbackNote("");
13316
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13317
+ };
13318
+ const handleFail = () => {
13319
+ if (!displayedAssignment) return;
13320
+ setPendingFeedbackStatus("failed");
13321
+ setShowFeedbackPrompt(true);
13322
+ setFeedbackRating(3);
13323
+ setFeedbackNote("");
13324
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13325
+ };
13326
+ const handleSubmitFeedback = async (skipFeedback = false) => {
13058
13327
  if (!client || !displayedAssignment) return;
13059
13328
  setSubmitting(true);
13060
- await client.submitReport({
13061
- type: "test_pass",
13062
- description: `Test passed: ${displayedAssignment.testCase.title}`,
13063
- assignmentId: displayedAssignment.id,
13064
- testCaseId: displayedAssignment.testCase.id,
13065
- appContext: getAppContext?.() || { currentRoute: "unknown" },
13066
- deviceInfo: getDeviceInfo()
13067
- });
13068
- await refreshAssignments();
13069
- setSubmitting(false);
13070
- setJustPassed(true);
13071
- setTimeout(() => {
13072
- setJustPassed(false);
13329
+ const feedback = skipFeedback ? void 0 : {
13330
+ rating: feedbackRating,
13331
+ feedbackNote: feedbackNote.trim() || void 0,
13332
+ isOutdated: feedbackFlags.isOutdated,
13333
+ needsMoreDetail: feedbackFlags.needsMoreDetail,
13334
+ stepsUnclear: feedbackFlags.stepsUnclear,
13335
+ expectedResultUnclear: feedbackFlags.expectedResultUnclear
13336
+ };
13337
+ if (pendingFeedbackStatus === "passed") {
13338
+ await client.submitReport({
13339
+ type: "test_pass",
13340
+ description: `Test passed: ${displayedAssignment.testCase.title}`,
13341
+ assignmentId: displayedAssignment.id,
13342
+ testCaseId: displayedAssignment.testCase.id,
13343
+ appContext: getAppContext?.() || { currentRoute: "unknown" },
13344
+ deviceInfo: getDeviceInfo()
13345
+ });
13346
+ if (feedback) {
13347
+ await client.submitTestFeedback({
13348
+ testCaseId: displayedAssignment.testCase.id,
13349
+ assignmentId: displayedAssignment.id,
13350
+ feedback,
13351
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13352
+ });
13353
+ }
13354
+ await refreshAssignments();
13355
+ setSubmitting(false);
13356
+ setShowFeedbackPrompt(false);
13357
+ setPendingFeedbackStatus(null);
13358
+ setJustPassed(true);
13359
+ setTimeout(() => {
13360
+ setJustPassed(false);
13361
+ setSelectedTestId(null);
13362
+ setTestView("detail");
13363
+ }, 1200);
13364
+ } else if (pendingFeedbackStatus === "failed") {
13365
+ if (feedback) {
13366
+ await client.submitTestFeedback({
13367
+ testCaseId: displayedAssignment.testCase.id,
13368
+ assignmentId: displayedAssignment.id,
13369
+ feedback,
13370
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13371
+ });
13372
+ }
13373
+ setSubmitting(false);
13374
+ setShowFeedbackPrompt(false);
13375
+ setPendingFeedbackStatus(null);
13376
+ setActiveTab("report");
13377
+ setReportType("bug");
13378
+ }
13379
+ };
13380
+ const handleSkipFeedback = () => {
13381
+ handleSubmitFeedback(true);
13382
+ };
13383
+ const handleOpenSkipModal = () => {
13384
+ setShowSkipModal(true);
13385
+ setSelectedSkipReason(null);
13386
+ setSkipNotes("");
13387
+ };
13388
+ const handleSkip = async () => {
13389
+ if (!client || !displayedAssignment || !selectedSkipReason) return;
13390
+ setSkipping(true);
13391
+ const result = await client.skipAssignment(
13392
+ displayedAssignment.id,
13393
+ selectedSkipReason,
13394
+ skipNotes || void 0
13395
+ );
13396
+ if (result.success) {
13397
+ await refreshAssignments();
13398
+ setShowSkipModal(false);
13399
+ setSelectedSkipReason(null);
13400
+ setSkipNotes("");
13073
13401
  setSelectedTestId(null);
13074
13402
  setTestView("detail");
13075
- }, 1200);
13076
- };
13077
- const handleFail = () => {
13078
- setActiveTab("report");
13079
- setReportType("test_fail");
13403
+ }
13404
+ setSkipping(false);
13080
13405
  };
13081
13406
  const handleSubmitReport = async () => {
13082
13407
  if (!client || !description.trim()) return;
@@ -13124,14 +13449,19 @@ function BugBearButton({
13124
13449
  await markAsRead(thread.id);
13125
13450
  }
13126
13451
  };
13452
+ const [messageSendError, setMessageSendError] = useState2(false);
13127
13453
  const handleSendReply = async () => {
13128
13454
  if (!selectedThread || !replyText.trim()) return;
13129
13455
  setSendingReply(true);
13456
+ setMessageSendError(false);
13130
13457
  const success = await sendMessage(selectedThread.id, replyText.trim());
13131
13458
  if (success) {
13132
13459
  setReplyText("");
13133
13460
  const messages = await getThreadMessages(selectedThread.id);
13134
13461
  setThreadMessages(messages);
13462
+ } else {
13463
+ setMessageSendError(true);
13464
+ setTimeout(() => setMessageSendError(false), 3e3);
13135
13465
  }
13136
13466
  setSendingReply(false);
13137
13467
  };
@@ -13223,6 +13553,44 @@ function BugBearButton({
13223
13553
  }
13224
13554
  setSavingProfile(false);
13225
13555
  };
13556
+ const handleStartSession = async () => {
13557
+ setStartingSession(true);
13558
+ const result = await startSession({
13559
+ focusArea: sessionFocusArea.trim() || void 0,
13560
+ platform: sessionPlatform
13561
+ });
13562
+ if (result.success) {
13563
+ setSessionFocusArea("");
13564
+ }
13565
+ setStartingSession(false);
13566
+ };
13567
+ const handleEndSession = async () => {
13568
+ setEndingSession(true);
13569
+ const result = await endSession(sessionNotes.trim() || void 0);
13570
+ if (result.success) {
13571
+ setSessionNotes("");
13572
+ setShowEndConfirm(false);
13573
+ }
13574
+ setEndingSession(false);
13575
+ };
13576
+ const handleAddFinding = async () => {
13577
+ if (!findingTitle.trim()) return;
13578
+ setAddingFinding(true);
13579
+ const result = await addFinding({
13580
+ type: findingType,
13581
+ title: findingTitle.trim(),
13582
+ description: findingDescription.trim() || void 0,
13583
+ severity: findingType === "bug" ? findingSeverity : void 0
13584
+ });
13585
+ if (result.success) {
13586
+ setFindingTitle("");
13587
+ setFindingDescription("");
13588
+ setFindingType("bug");
13589
+ setFindingSeverity("medium");
13590
+ setShowAddFinding(false);
13591
+ }
13592
+ setAddingFinding(false);
13593
+ };
13226
13594
  const formatRelativeTime = (dateString) => {
13227
13595
  const date = new Date(dateString);
13228
13596
  const now = /* @__PURE__ */ new Date();
@@ -13398,7 +13766,7 @@ function BugBearButton({
13398
13766
  style: [styles.tab, activeTab === "tests" && styles.activeTab],
13399
13767
  onPress: () => setActiveTab("tests")
13400
13768
  },
13401
- /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "tests" && styles.activeTabText] }, "Tests ", pendingCount > 0 && `(${pendingCount})`)
13769
+ /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "tests" && styles.activeTabText] }, "Tests ", assignments.length > 0 && `(${passedCount + failedCount}/${assignments.length})`)
13402
13770
  ), /* @__PURE__ */ React2.createElement(
13403
13771
  TouchableOpacity,
13404
13772
  {
@@ -13406,6 +13774,13 @@ function BugBearButton({
13406
13774
  onPress: () => setActiveTab("messages")
13407
13775
  },
13408
13776
  /* @__PURE__ */ React2.createElement(View, { style: styles.tabWithBadge }, /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "messages" && styles.activeTabText] }, "Messages"), unreadCount > 0 && /* @__PURE__ */ React2.createElement(View, { style: styles.tabBadge }, /* @__PURE__ */ React2.createElement(Text, { style: styles.tabBadgeText }, unreadCount)))
13777
+ ), /* @__PURE__ */ React2.createElement(
13778
+ TouchableOpacity,
13779
+ {
13780
+ style: [styles.tab, activeTab === "explore" && styles.activeTab],
13781
+ onPress: () => setActiveTab("explore")
13782
+ },
13783
+ /* @__PURE__ */ React2.createElement(View, { style: styles.tabWithBadge }, /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "explore" && styles.activeTabText] }, "Explore"), activeSession && /* @__PURE__ */ React2.createElement(View, { style: styles.sessionDot }))
13409
13784
  ), /* @__PURE__ */ React2.createElement(
13410
13785
  TouchableOpacity,
13411
13786
  {
@@ -13414,32 +13789,126 @@ function BugBearButton({
13414
13789
  },
13415
13790
  /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "report" && styles.activeTabText] }, "Report")
13416
13791
  )), /* @__PURE__ */ React2.createElement(ScrollView, { style: styles.content }, activeTab === "tests" && /* @__PURE__ */ React2.createElement(View, null, assignments.length === 0 ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u2705"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "All caught up!"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "No tests assigned")) : testView === "list" ? (
13417
- /* List View - Show all tests */
13418
- /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"), assignments.map((assignment) => /* @__PURE__ */ React2.createElement(
13792
+ /* List View - Show tests grouped by folder */
13793
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " \xB7 ", passedCount, " passed \xB7 ", failedCount, " failed"), /* @__PURE__ */ React2.createElement(View, { style: styles.filterBar }, ["all", "pending", "completed"].map((f) => /* @__PURE__ */ React2.createElement(
13419
13794
  TouchableOpacity,
13420
13795
  {
13421
- key: assignment.id,
13422
- onPress: () => {
13423
- setSelectedTestId(assignment.id);
13424
- setTestView("detail");
13425
- setShowSteps(false);
13796
+ key: f,
13797
+ style: [styles.filterChip, testFilter === f && styles.filterChipActive],
13798
+ onPress: () => setTestFilter(f)
13799
+ },
13800
+ /* @__PURE__ */ React2.createElement(Text, { style: [styles.filterChipText, testFilter === f && styles.filterChipTextActive] }, f === "all" ? `All (${assignments.length})` : f === "pending" ? `To Do (${pendingCount + inProgressCount})` : `Done (${passedCount + failedCount})`)
13801
+ ))), groupedAssignments.map((folder) => {
13802
+ const groupId = folder.group?.id || "ungrouped";
13803
+ const isCollapsed = collapsedFolders.has(groupId);
13804
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13805
+ return /* @__PURE__ */ React2.createElement(View, { key: groupId, style: styles.folderContainer }, /* @__PURE__ */ React2.createElement(
13806
+ TouchableOpacity,
13807
+ {
13808
+ onPress: () => toggleFolderCollapse(groupId),
13809
+ style: styles.folderHeader
13426
13810
  },
13811
+ /* @__PURE__ */ React2.createElement(View, { style: styles.folderHeaderLeft }, /* @__PURE__ */ React2.createElement(Text, { style: styles.folderIcon }, isCollapsed ? "\u{1F4C1}" : "\u{1F4C2}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.folderName }, folder.group?.name || "Ungrouped Tests")),
13812
+ /* @__PURE__ */ React2.createElement(View, { style: styles.folderStats }, /* @__PURE__ */ React2.createElement(Text, { style: styles.folderProgress }, completedCount, "/", folder.stats.total), /* @__PURE__ */ React2.createElement(Text, { style: styles.folderChevron }, isCollapsed ? "\u25B6" : "\u25BC"))
13813
+ ), !isCollapsed && /* @__PURE__ */ React2.createElement(View, { style: styles.folderProgressBar }, /* @__PURE__ */ React2.createElement(
13814
+ View,
13815
+ {
13816
+ style: [
13817
+ styles.folderProgressFill,
13818
+ { width: `${completedCount / folder.stats.total * 100}%` }
13819
+ ]
13820
+ }
13821
+ )), !isCollapsed && folder.assignments.filter((a) => {
13822
+ if (testFilter === "pending") return a.status === "pending" || a.status === "in_progress";
13823
+ if (testFilter === "completed") return a.status === "passed" || a.status === "failed" || a.status === "skipped";
13824
+ return true;
13825
+ }).map((assignment) => {
13826
+ const statusBadge = getStatusBadge(assignment.status);
13827
+ return /* @__PURE__ */ React2.createElement(
13828
+ TouchableOpacity,
13829
+ {
13830
+ key: assignment.id,
13831
+ onPress: () => {
13832
+ setSelectedTestId(assignment.id);
13833
+ setTestView("detail");
13834
+ setShowSteps(false);
13835
+ },
13836
+ style: [
13837
+ styles.listItem,
13838
+ styles.listItemInFolder,
13839
+ assignment.id === currentAssignment?.id && styles.listItemCurrent
13840
+ ]
13841
+ },
13842
+ /* @__PURE__ */ React2.createElement(View, { style: styles.listItemHeader }, /* @__PURE__ */ React2.createElement(View, { style: styles.listItemKeyWithStatus }, /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ React2.createElement(View, { style: [styles.statusBadge, { backgroundColor: statusBadge.color + "20" }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.statusBadgeIcon }, statusBadge.icon), /* @__PURE__ */ React2.createElement(Text, { style: [styles.statusBadgeText, { color: statusBadge.color }] }, statusBadge.label))), /* @__PURE__ */ React2.createElement(View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ React2.createElement(View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ React2.createElement(View, { style: [
13843
+ styles.priorityBadge,
13844
+ assignment.testCase.priority === "P0" && styles.priorityP0,
13845
+ assignment.testCase.priority === "P1" && styles.priorityP1
13846
+ ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, assignment.testCase.priority)))),
13847
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
13848
+ /* @__PURE__ */ React2.createElement(View, { style: styles.listItemMeta }, /* @__PURE__ */ React2.createElement(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__ */ React2.createElement(Text, { style: styles.currentBadge }, "\u2022 Current"))
13849
+ );
13850
+ }));
13851
+ }))
13852
+ ) : justPassed ? (
13853
+ /* Success state after passing */
13854
+ /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ React2.createElement(Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Loading next test..."))
13855
+ ) : showFeedbackPrompt && displayedAssignment ? (
13856
+ /* Feedback prompt after completing a test */
13857
+ /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.container }, /* @__PURE__ */ React2.createElement(View, { style: { alignItems: "center", marginBottom: 16 } }, /* @__PURE__ */ React2.createElement(Text, { style: { fontSize: 28 } }, pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717"), /* @__PURE__ */ React2.createElement(Text, { style: [feedbackStyles.statusText, pendingFeedbackStatus === "passed" ? { color: "#4ade80" } : { color: "#f87171" }] }, pendingFeedbackStatus === "passed" ? "Test Passed!" : "Test Failed")), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.infoBox }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.infoTitle }, "Help us improve this test"), /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.infoSubtitle }, "Your feedback shapes better tests for everyone.")), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.ratingSection }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingLabel }, "How was this test?"), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.starsRow }, [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ React2.createElement(
13858
+ TouchableOpacity,
13859
+ {
13860
+ key: star,
13861
+ onPress: () => setFeedbackRating(star)
13862
+ },
13863
+ /* @__PURE__ */ React2.createElement(Text, { style: [feedbackStyles.star, star <= feedbackRating ? feedbackStyles.starActive : feedbackStyles.starInactive] }, "\u2605")
13864
+ ))), /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingDesc }, feedbackRating === 1 ? "Needs work" : feedbackRating === 2 ? "Could be better" : feedbackRating === 3 ? "Okay" : feedbackRating === 4 ? "Good" : "Great!")), feedbackRating < 4 && /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.flagsSection }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingLabel }, "What could be improved?"), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.flagsGrid }, [
13865
+ { key: "stepsUnclear", label: "Steps unclear" },
13866
+ { key: "expectedResultUnclear", label: "Expected result unclear" },
13867
+ { key: "needsMoreDetail", label: "Needs more detail" },
13868
+ { key: "isOutdated", label: "Seems outdated" }
13869
+ ].map(({ key, label }) => /* @__PURE__ */ React2.createElement(
13870
+ TouchableOpacity,
13871
+ {
13872
+ key,
13873
+ onPress: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
13427
13874
  style: [
13428
- styles.listItem,
13429
- assignment.id === currentAssignment?.id && styles.listItemCurrent
13875
+ feedbackStyles.flagButton,
13876
+ feedbackFlags[key] && feedbackStyles.flagButtonActive
13430
13877
  ]
13431
13878
  },
13432
- /* @__PURE__ */ React2.createElement(View, { style: styles.listItemHeader }, /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ React2.createElement(View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ React2.createElement(View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ React2.createElement(View, { style: [
13433
- styles.priorityBadge,
13434
- assignment.testCase.priority === "P0" && styles.priorityP0,
13435
- assignment.testCase.priority === "P1" && styles.priorityP1
13436
- ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, assignment.testCase.priority)))),
13437
- /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
13438
- /* @__PURE__ */ React2.createElement(View, { style: styles.listItemMeta }, /* @__PURE__ */ React2.createElement(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__ */ React2.createElement(Text, { style: styles.currentBadge }, "\u2022 Current"))
13879
+ /* @__PURE__ */ React2.createElement(Text, { style: [
13880
+ feedbackStyles.flagButtonText,
13881
+ feedbackFlags[key] && feedbackStyles.flagButtonTextActive
13882
+ ] }, label)
13883
+ )))), /* @__PURE__ */ React2.createElement(View, { style: { marginBottom: 12 } }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingLabel }, "Suggestions? (optional)"), /* @__PURE__ */ React2.createElement(
13884
+ TextInput,
13885
+ {
13886
+ style: feedbackStyles.noteInput,
13887
+ value: feedbackNote,
13888
+ onChangeText: setFeedbackNote,
13889
+ placeholder: "How could this test be improved?",
13890
+ placeholderTextColor: "#71717a",
13891
+ multiline: true,
13892
+ numberOfLines: 2,
13893
+ textAlignVertical: "top"
13894
+ }
13895
+ )), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.buttonRow }, /* @__PURE__ */ React2.createElement(
13896
+ TouchableOpacity,
13897
+ {
13898
+ onPress: handleSkipFeedback,
13899
+ disabled: submitting,
13900
+ style: [feedbackStyles.skipButton, submitting && { opacity: 0.5 }]
13901
+ },
13902
+ /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.skipButtonText }, "Skip")
13903
+ ), /* @__PURE__ */ React2.createElement(
13904
+ TouchableOpacity,
13905
+ {
13906
+ onPress: () => handleSubmitFeedback(false),
13907
+ disabled: submitting,
13908
+ style: [feedbackStyles.submitButton, submitting && { opacity: 0.5 }]
13909
+ },
13910
+ /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.submitButtonText }, submitting ? "Submitting..." : "Submit Feedback")
13439
13911
  )))
13440
- ) : justPassed ? (
13441
- /* Success state after passing */
13442
- /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ React2.createElement(Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Loading next test..."))
13443
13912
  ) : displayedAssignment ? (
13444
13913
  /* Detail View - Show single test */
13445
13914
  /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(
@@ -13452,27 +13921,58 @@ function BugBearButton({
13452
13921
  style: styles.backButton
13453
13922
  },
13454
13923
  /* @__PURE__ */ React2.createElement(Text, { style: styles.backButtonText }, "\u2190 All Tests (", assignments.length, ")")
13455
- ), /* @__PURE__ */ React2.createElement(View, { style: styles.testCard }, /* @__PURE__ */ React2.createElement(View, { style: styles.testHeader }, /* @__PURE__ */ React2.createElement(Text, { style: styles.testKey }, displayedAssignment.testCase.testKey), /* @__PURE__ */ React2.createElement(View, { style: styles.testHeaderBadges }, displayedAssignment.testCase.track && /* @__PURE__ */ React2.createElement(View, { style: [styles.trackBadge, { backgroundColor: displayedAssignment.testCase.track.color }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.trackBadgeText }, templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ React2.createElement(View, { style: [
13924
+ ), /* @__PURE__ */ React2.createElement(View, { style: styles.testCard }, /* @__PURE__ */ React2.createElement(View, { style: styles.testHeader }, /* @__PURE__ */ React2.createElement(Text, { style: styles.testKey }, displayedAssignment.testCase.testKey), /* @__PURE__ */ React2.createElement(View, { style: styles.testHeaderBadges }, (() => {
13925
+ const badge = getStatusBadge(displayedAssignment.status);
13926
+ return /* @__PURE__ */ React2.createElement(View, { style: [styles.statusBadge, { backgroundColor: badge.color + "20" }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.statusBadgeIcon }, badge.icon), /* @__PURE__ */ React2.createElement(Text, { style: [styles.statusBadgeText, { color: badge.color }] }, badge.label));
13927
+ })(), displayedAssignment.testCase.track && /* @__PURE__ */ React2.createElement(View, { style: [styles.trackBadge, { backgroundColor: displayedAssignment.testCase.track.color }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.trackBadgeText }, templateInfo[displayedAssignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ React2.createElement(View, { style: [
13456
13928
  styles.priorityBadge,
13457
13929
  displayedAssignment.testCase.priority === "P0" && styles.priorityP0,
13458
13930
  displayedAssignment.testCase.priority === "P1" && styles.priorityP1
13459
- ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ React2.createElement(Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.testCase.description && /* @__PURE__ */ React2.createElement(Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ React2.createElement(Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ React2.createElement(View, { style: styles.expectedResult }, /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), /* @__PURE__ */ React2.createElement(View, { style: styles.actionButtons }, /* @__PURE__ */ React2.createElement(
13931
+ ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ React2.createElement(Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.status === "in_progress" && displayedAssignment.startedAt && /* @__PURE__ */ React2.createElement(View, { style: timerStyles.container }, /* @__PURE__ */ React2.createElement(View, { style: timerStyles.dot }), /* @__PURE__ */ React2.createElement(Text, { style: timerStyles.label }, "Testing"), /* @__PURE__ */ React2.createElement(Text, { style: timerStyles.time }, formatElapsedTime(assignmentElapsedTime))), displayedAssignment.testCase.description && /* @__PURE__ */ React2.createElement(Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ React2.createElement(Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ React2.createElement(View, { style: styles.expectedResult }, /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), displayedAssignment.testCase.group && (() => {
13932
+ const folder = groupedAssignments.find((f) => f.group?.id === displayedAssignment.testCase.group?.id);
13933
+ if (!folder) return null;
13934
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13935
+ return /* @__PURE__ */ React2.createElement(View, { style: styles.detailProgressContainer }, /* @__PURE__ */ React2.createElement(Text, { style: styles.detailProgressText }, folder.group?.name, ": ", completedCount, "/", folder.stats.total, " complete"), /* @__PURE__ */ React2.createElement(View, { style: styles.detailProgressBar }, /* @__PURE__ */ React2.createElement(
13936
+ View,
13937
+ {
13938
+ style: [
13939
+ styles.detailProgressFill,
13940
+ { width: `${completedCount / folder.stats.total * 100}%` }
13941
+ ]
13942
+ }
13943
+ )));
13944
+ })(), /* @__PURE__ */ React2.createElement(View, { style: styles.actionButtons }, /* @__PURE__ */ React2.createElement(
13460
13945
  TouchableOpacity,
13461
13946
  {
13462
13947
  style: styles.failButton,
13463
13948
  onPress: handleFail,
13464
- disabled: submitting
13949
+ disabled: submitting || skipping
13465
13950
  },
13466
13951
  /* @__PURE__ */ React2.createElement(Text, { style: styles.failButtonText }, "\u2717 Fail")
13952
+ ), /* @__PURE__ */ React2.createElement(
13953
+ TouchableOpacity,
13954
+ {
13955
+ style: styles.skipButton,
13956
+ onPress: handleOpenSkipModal,
13957
+ disabled: submitting || skipping
13958
+ },
13959
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipButtonText }, skipping ? "..." : "\u2192 Skip")
13467
13960
  ), /* @__PURE__ */ React2.createElement(
13468
13961
  TouchableOpacity,
13469
13962
  {
13470
13963
  style: styles.passButton,
13471
13964
  onPress: handlePass,
13472
- disabled: submitting
13965
+ disabled: submitting || skipping
13473
13966
  },
13474
13967
  /* @__PURE__ */ React2.createElement(Text, { style: styles.passButtonText }, submitting ? "..." : "\u2713 Pass")
13475
- )))
13968
+ )), pendingCount > 1 || pendingCount === 1 && displayedAssignment.status !== "pending" ? /* @__PURE__ */ React2.createElement(
13969
+ TouchableOpacity,
13970
+ {
13971
+ style: styles.nextTestButton,
13972
+ onPress: handleNextTest
13973
+ },
13974
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.nextTestButtonText }, "Next Test \u25B6")
13975
+ ) : null)
13476
13976
  ) : null), activeTab === "messages" && /* @__PURE__ */ React2.createElement(View, null, messageView === "compose" ? (
13477
13977
  /* Compose New Message View */
13478
13978
  /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: handleBackToThreadList, style: styles.backButton }, /* @__PURE__ */ React2.createElement(Text, { style: styles.backButtonText }, "\u2190 Back to Messages")), /* @__PURE__ */ React2.createElement(View, { style: styles.composeHeader }, /* @__PURE__ */ React2.createElement(Text, { style: styles.composeTitle }, "New Message"), /* @__PURE__ */ React2.createElement(Text, { style: styles.composeSubtitle }, "Send a message to the QA team")), /* @__PURE__ */ React2.createElement(View, { style: styles.composeForm }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "Subject"), /* @__PURE__ */ React2.createElement(
@@ -13557,6 +14057,166 @@ function BugBearButton({
13557
14057
  message.senderType === "tester" && styles.messageTimeTester
13558
14058
  ] }, formatMessageTime(message.createdAt))
13559
14059
  ))))
14060
+ )), activeTab === "explore" && /* @__PURE__ */ React2.createElement(View, null, !activeSession ? (
14061
+ /* Start Session View */
14062
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u{1F50D}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Exploratory QA Session"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Explore freely and capture findings as you go")), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Focus Area (optional)"), /* @__PURE__ */ React2.createElement(
14063
+ TextInput,
14064
+ {
14065
+ style: exploreStyles.input,
14066
+ value: sessionFocusArea,
14067
+ onChangeText: setSessionFocusArea,
14068
+ placeholder: "e.g., checkout flow, settings page",
14069
+ placeholderTextColor: "#71717a"
14070
+ }
14071
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Platform"), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.platformRow }, [
14072
+ { key: "ios", label: "\u{1F4F1} iOS" },
14073
+ { key: "android", label: "\u{1F916} Android" },
14074
+ { key: "web", label: "\u{1F310} Web" }
14075
+ ].map(({ key, label }) => /* @__PURE__ */ React2.createElement(
14076
+ TouchableOpacity,
14077
+ {
14078
+ key,
14079
+ onPress: () => setSessionPlatform(key),
14080
+ style: [
14081
+ exploreStyles.platformButton,
14082
+ sessionPlatform === key && exploreStyles.platformButtonActive
14083
+ ]
14084
+ },
14085
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14086
+ exploreStyles.platformButtonText,
14087
+ sessionPlatform === key && exploreStyles.platformButtonTextActive
14088
+ ] }, label)
14089
+ )))), /* @__PURE__ */ React2.createElement(
14090
+ TouchableOpacity,
14091
+ {
14092
+ onPress: handleStartSession,
14093
+ disabled: startingSession,
14094
+ style: [exploreStyles.startButton, startingSession && { opacity: 0.5 }]
14095
+ },
14096
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.startButtonText }, startingSession ? "Starting..." : "\u25B6 Start Session")
14097
+ ))
14098
+ ) : showEndConfirm ? (
14099
+ /* End Session Confirmation */
14100
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u270B"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "End Session?"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Duration: ", formatElapsedTime(sessionElapsedTime), " \xB7 ", sessionFindings.length, " finding", sessionFindings.length !== 1 ? "s" : "")), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Session Notes (optional)"), /* @__PURE__ */ React2.createElement(
14101
+ TextInput,
14102
+ {
14103
+ style: [exploreStyles.input, { height: 80, textAlignVertical: "top" }],
14104
+ value: sessionNotes,
14105
+ onChangeText: setSessionNotes,
14106
+ placeholder: "Any overall observations from this session...",
14107
+ placeholderTextColor: "#71717a",
14108
+ multiline: true
14109
+ }
14110
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.buttonRow }, /* @__PURE__ */ React2.createElement(
14111
+ TouchableOpacity,
14112
+ {
14113
+ onPress: () => setShowEndConfirm(false),
14114
+ style: exploreStyles.cancelButton
14115
+ },
14116
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.cancelButtonText }, "Cancel")
14117
+ ), /* @__PURE__ */ React2.createElement(
14118
+ TouchableOpacity,
14119
+ {
14120
+ onPress: handleEndSession,
14121
+ disabled: endingSession,
14122
+ style: [exploreStyles.endButton, endingSession && { opacity: 0.5 }]
14123
+ },
14124
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.endButtonText }, endingSession ? "Ending..." : "End Session")
14125
+ )))
14126
+ ) : showAddFinding ? (
14127
+ /* Add Finding Form */
14128
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingHeader }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingHeaderTitle }, "Add Finding"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: () => setShowAddFinding(false) }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingHeaderClose }, "\u2715"))), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingTypeRow }, [
14129
+ { type: "bug", label: "\u{1F41B} Bug" },
14130
+ { type: "concern", label: "\u26A0\uFE0F Concern" },
14131
+ { type: "suggestion", label: "\u{1F4A1} Idea" },
14132
+ { type: "question", label: "\u2753 Q" }
14133
+ ].map(({ type, label }) => /* @__PURE__ */ React2.createElement(
14134
+ TouchableOpacity,
14135
+ {
14136
+ key: type,
14137
+ onPress: () => setFindingType(type),
14138
+ style: [
14139
+ exploreStyles.findingTypeButton,
14140
+ findingType === type && exploreStyles.findingTypeButtonActive
14141
+ ]
14142
+ },
14143
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14144
+ exploreStyles.findingTypeButtonText,
14145
+ findingType === type && exploreStyles.findingTypeButtonTextActive
14146
+ ] }, label)
14147
+ ))), findingType === "bug" && /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Severity"), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.severityRow }, ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ React2.createElement(
14148
+ TouchableOpacity,
14149
+ {
14150
+ key: sev,
14151
+ onPress: () => setFindingSeverity(sev),
14152
+ style: [
14153
+ exploreStyles.severityButton,
14154
+ findingSeverity === sev && (sev === "critical" ? exploreStyles.severityCritical : sev === "high" ? exploreStyles.severityHigh : sev === "medium" ? exploreStyles.severityMedium : exploreStyles.severityLow)
14155
+ ]
14156
+ },
14157
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14158
+ exploreStyles.severityButtonText,
14159
+ findingSeverity === sev && exploreStyles.severityButtonTextActive
14160
+ ] }, sev)
14161
+ )))), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Title *"), /* @__PURE__ */ React2.createElement(
14162
+ TextInput,
14163
+ {
14164
+ style: exploreStyles.input,
14165
+ value: findingTitle,
14166
+ onChangeText: setFindingTitle,
14167
+ placeholder: "Brief description of what you found",
14168
+ placeholderTextColor: "#71717a"
14169
+ }
14170
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Details (optional)"), /* @__PURE__ */ React2.createElement(
14171
+ TextInput,
14172
+ {
14173
+ style: [exploreStyles.input, { height: 60, textAlignVertical: "top" }],
14174
+ value: findingDescription,
14175
+ onChangeText: setFindingDescription,
14176
+ placeholder: "Steps to reproduce, expected behavior, etc.",
14177
+ placeholderTextColor: "#71717a",
14178
+ multiline: true
14179
+ }
14180
+ )), /* @__PURE__ */ React2.createElement(
14181
+ TouchableOpacity,
14182
+ {
14183
+ onPress: handleAddFinding,
14184
+ disabled: addingFinding || !findingTitle.trim(),
14185
+ style: [exploreStyles.addFindingButton, (addingFinding || !findingTitle.trim()) && { opacity: 0.5 }]
14186
+ },
14187
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.addFindingButtonText }, addingFinding ? "Adding..." : "Add Finding")
14188
+ ))
14189
+ ) : (
14190
+ /* Active Session View */
14191
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionBanner }, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionBannerRow }, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionBannerLeft }, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionDotLarge }), /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.sessionBannerLabel }, "Session Active")), /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.sessionTimer }, formatElapsedTime(sessionElapsedTime))), activeSession.focusArea && /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.sessionFocus }, "Focus: ", activeSession.focusArea)), /* @__PURE__ */ React2.createElement(
14192
+ TouchableOpacity,
14193
+ {
14194
+ onPress: () => setShowAddFinding(true),
14195
+ style: exploreStyles.addButton
14196
+ },
14197
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.addButtonText }, "+ Add Finding")
14198
+ ), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingsSection }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingsLabel }, "Findings (", sessionFindings.length, ")"), sessionFindings.length === 0 ? /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingsEmpty }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingsEmptyText }, "No findings yet"), /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingsEmptyText }, "Explore and add findings as you go")) : /* @__PURE__ */ React2.createElement(View, null, sessionFindings.map((finding) => /* @__PURE__ */ React2.createElement(
14199
+ View,
14200
+ {
14201
+ key: finding.id,
14202
+ style: [
14203
+ exploreStyles.findingCard,
14204
+ finding.type === "bug" ? exploreStyles.findingCardBug : finding.type === "concern" ? exploreStyles.findingCardConcern : finding.type === "suggestion" ? exploreStyles.findingCardSuggestion : exploreStyles.findingCardQuestion
14205
+ ]
14206
+ },
14207
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingCardIcon }, finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753"),
14208
+ /* @__PURE__ */ React2.createElement(View, { style: { flex: 1 } }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingCardTitle, numberOfLines: 1 }, finding.title), finding.severity && finding.type === "bug" && /* @__PURE__ */ React2.createElement(Text, { style: [
14209
+ exploreStyles.findingCardSeverity,
14210
+ finding.severity === "critical" ? { color: "#f87171" } : finding.severity === "high" ? { color: "#fb923c" } : finding.severity === "medium" ? { color: "#facc15" } : { color: "#a1a1aa" }
14211
+ ] }, finding.severity))
14212
+ )))), /* @__PURE__ */ React2.createElement(
14213
+ TouchableOpacity,
14214
+ {
14215
+ onPress: () => setShowEndConfirm(true),
14216
+ style: exploreStyles.endSessionButton
14217
+ },
14218
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.endSessionButtonText }, "End Session")
14219
+ ))
13560
14220
  )), activeTab === "report" && /* @__PURE__ */ React2.createElement(View, null, submitted ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u{1F389}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Report submitted!")) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(View, { style: styles.reportTypes }, [
13561
14221
  { type: "bug", label: "\u{1F41B} Bug" },
13562
14222
  { type: "feedback", label: "\u{1F4A1} Feedback" },
@@ -13696,7 +14356,7 @@ function BugBearButton({
13696
14356
  /* @__PURE__ */ React2.createElement(Text, { style: styles.closeProfileButtonText }, "\u2190 Back")
13697
14357
  ))), activeTab === "messages" && messageView === "thread" && selectedThread ? (
13698
14358
  /* Reply Composer */
13699
- /* @__PURE__ */ React2.createElement(View, { style: styles.replyComposer }, /* @__PURE__ */ React2.createElement(
14359
+ /* @__PURE__ */ React2.createElement(View, null, messageSendError && /* @__PURE__ */ React2.createElement(View, { style: styles.messageSendError }, /* @__PURE__ */ React2.createElement(Text, { style: styles.messageSendErrorText }, "Failed to send. Tap Send to retry.")), /* @__PURE__ */ React2.createElement(View, { style: styles.replyComposer }, /* @__PURE__ */ React2.createElement(
13700
14360
  TextInput,
13701
14361
  {
13702
14362
  style: styles.replyInput,
@@ -13718,12 +14378,67 @@ function BugBearButton({
13718
14378
  disabled: !replyText.trim() || sendingReply
13719
14379
  },
13720
14380
  /* @__PURE__ */ React2.createElement(Text, { style: styles.sendButtonText }, sendingReply ? "..." : "Send")
13721
- ))
14381
+ )))
13722
14382
  ) : (
13723
14383
  /* Standard Footer */
13724
- /* @__PURE__ */ React2.createElement(View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, pendingCount, " pending \xB7 ", inProgressCount, " in progress"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))))
14384
+ /* @__PURE__ */ React2.createElement(View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))) : activeTab === "explore" ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, activeSession ? `${sessionFindings.length} findings` : "No active session"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshSession }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, passedCount + failedCount, "/", assignments.length, " done \xB7 ", pendingCount, " pending"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))))
13725
14385
  ))
13726
14386
  )
14387
+ ), /* @__PURE__ */ React2.createElement(
14388
+ Modal,
14389
+ {
14390
+ visible: showSkipModal,
14391
+ transparent: true,
14392
+ animationType: "fade",
14393
+ onRequestClose: () => setShowSkipModal(false)
14394
+ },
14395
+ /* @__PURE__ */ React2.createElement(View, { style: styles.skipModalOverlay }, /* @__PURE__ */ React2.createElement(View, { style: styles.skipModalContent }, /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalTitle }, "Skip Test"), /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalSubtitle }, "Why are you skipping this test?"), /* @__PURE__ */ React2.createElement(View, { style: styles.skipReasonOptions }, [
14396
+ { value: "blocked", label: "\u{1F6AB} Blocked", desc: "Something is preventing testing" },
14397
+ { value: "not_ready", label: "\u{1F6A7} Not Ready", desc: "Feature not yet implemented" },
14398
+ { value: "dependency", label: "\u{1F517} Dependency", desc: "Waiting on another test/feature" },
14399
+ { value: "other", label: "\u{1F4DD} Other", desc: "Different reason" }
14400
+ ].map((option) => /* @__PURE__ */ React2.createElement(
14401
+ TouchableOpacity,
14402
+ {
14403
+ key: option.value,
14404
+ style: [
14405
+ styles.skipReasonOption,
14406
+ selectedSkipReason === option.value && styles.skipReasonOptionSelected
14407
+ ],
14408
+ onPress: () => setSelectedSkipReason(option.value)
14409
+ },
14410
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipReasonLabel }, option.label),
14411
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipReasonDesc }, option.desc)
14412
+ ))), /* @__PURE__ */ React2.createElement(
14413
+ TextInput,
14414
+ {
14415
+ style: styles.skipNotesInput,
14416
+ value: skipNotes,
14417
+ onChangeText: setSkipNotes,
14418
+ placeholder: "Add notes (optional)...",
14419
+ placeholderTextColor: "#71717a",
14420
+ multiline: true,
14421
+ numberOfLines: 2
14422
+ }
14423
+ ), /* @__PURE__ */ React2.createElement(View, { style: styles.skipModalActions }, /* @__PURE__ */ React2.createElement(
14424
+ TouchableOpacity,
14425
+ {
14426
+ style: styles.skipModalCancel,
14427
+ onPress: () => setShowSkipModal(false)
14428
+ },
14429
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalCancelText }, "Cancel")
14430
+ ), /* @__PURE__ */ React2.createElement(
14431
+ TouchableOpacity,
14432
+ {
14433
+ style: [
14434
+ styles.skipModalConfirm,
14435
+ !selectedSkipReason && styles.skipModalConfirmDisabled
14436
+ ],
14437
+ onPress: handleSkip,
14438
+ disabled: !selectedSkipReason || skipping
14439
+ },
14440
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalConfirmText }, skipping ? "Skipping..." : "Skip Test")
14441
+ ))))
13727
14442
  ));
13728
14443
  }
13729
14444
  var styles = StyleSheet.create({
@@ -13856,7 +14571,8 @@ var styles = StyleSheet.create({
13856
14571
  justifyContent: "space-between",
13857
14572
  alignItems: "center",
13858
14573
  paddingHorizontal: 16,
13859
- paddingVertical: 12,
14574
+ paddingTop: 12,
14575
+ paddingBottom: Platform2.OS === "ios" ? 34 : 12,
13860
14576
  borderTopWidth: 1,
13861
14577
  borderTopColor: "#27272a",
13862
14578
  backgroundColor: "#09090b"
@@ -14426,6 +15142,13 @@ var styles = StyleSheet.create({
14426
15142
  flexDirection: "row",
14427
15143
  alignItems: "center"
14428
15144
  },
15145
+ sessionDot: {
15146
+ width: 8,
15147
+ height: 8,
15148
+ borderRadius: 4,
15149
+ backgroundColor: "#22c55e",
15150
+ marginLeft: 4
15151
+ },
14429
15152
  tabBadge: {
14430
15153
  backgroundColor: "#EF4444",
14431
15154
  borderRadius: 8,
@@ -14597,7 +15320,9 @@ var styles = StyleSheet.create({
14597
15320
  replyComposer: {
14598
15321
  flexDirection: "row",
14599
15322
  alignItems: "flex-end",
14600
- padding: 12,
15323
+ paddingHorizontal: 12,
15324
+ paddingTop: 12,
15325
+ paddingBottom: Platform2.OS === "ios" ? 34 : 12,
14601
15326
  borderTopWidth: 1,
14602
15327
  borderTopColor: "#27272a",
14603
15328
  backgroundColor: "#18181b"
@@ -14980,6 +15705,715 @@ var styles = StyleSheet.create({
14980
15705
  fontSize: 14,
14981
15706
  fontWeight: "500",
14982
15707
  color: "#3B82F6"
15708
+ },
15709
+ // Folder grouping styles
15710
+ folderContainer: {
15711
+ marginBottom: 12
15712
+ },
15713
+ folderHeader: {
15714
+ flexDirection: "row",
15715
+ justifyContent: "space-between",
15716
+ alignItems: "center",
15717
+ backgroundColor: "#27272a",
15718
+ padding: 12,
15719
+ borderRadius: 8,
15720
+ marginBottom: 4
15721
+ },
15722
+ folderHeaderLeft: {
15723
+ flexDirection: "row",
15724
+ alignItems: "center",
15725
+ flex: 1
15726
+ },
15727
+ folderIcon: {
15728
+ fontSize: 16,
15729
+ marginRight: 8
15730
+ },
15731
+ folderName: {
15732
+ fontSize: 14,
15733
+ fontWeight: "600",
15734
+ color: "#fafafa"
15735
+ },
15736
+ folderStats: {
15737
+ flexDirection: "row",
15738
+ alignItems: "center"
15739
+ },
15740
+ folderProgress: {
15741
+ fontSize: 12,
15742
+ color: "#71717a",
15743
+ marginRight: 8
15744
+ },
15745
+ folderChevron: {
15746
+ fontSize: 10,
15747
+ color: "#71717a"
15748
+ },
15749
+ folderProgressBar: {
15750
+ height: 3,
15751
+ backgroundColor: "#3f3f46",
15752
+ borderRadius: 2,
15753
+ marginBottom: 8,
15754
+ marginHorizontal: 4
15755
+ },
15756
+ folderProgressFill: {
15757
+ height: "100%",
15758
+ backgroundColor: "#22c55e",
15759
+ borderRadius: 2
15760
+ },
15761
+ listItemInFolder: {
15762
+ marginLeft: 12,
15763
+ borderLeftWidth: 2,
15764
+ borderLeftColor: "#3f3f46",
15765
+ paddingLeft: 12
15766
+ },
15767
+ listItemKeyWithStatus: {
15768
+ flexDirection: "row",
15769
+ alignItems: "center",
15770
+ flex: 1
15771
+ },
15772
+ statusBadge: {
15773
+ flexDirection: "row",
15774
+ alignItems: "center",
15775
+ paddingHorizontal: 6,
15776
+ paddingVertical: 2,
15777
+ borderRadius: 4,
15778
+ marginLeft: 8
15779
+ },
15780
+ statusBadgeIcon: {
15781
+ fontSize: 10,
15782
+ marginRight: 4
15783
+ },
15784
+ statusBadgeText: {
15785
+ fontSize: 10,
15786
+ fontWeight: "600"
15787
+ },
15788
+ // Skip button styles
15789
+ skipButton: {
15790
+ flex: 1,
15791
+ backgroundColor: "#eab308",
15792
+ paddingVertical: 14,
15793
+ borderRadius: 12,
15794
+ alignItems: "center",
15795
+ marginHorizontal: 4
15796
+ },
15797
+ skipButtonText: {
15798
+ fontSize: 15,
15799
+ fontWeight: "600",
15800
+ color: "#18181b"
15801
+ },
15802
+ // Skip modal styles
15803
+ skipModalOverlay: {
15804
+ flex: 1,
15805
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
15806
+ justifyContent: "center",
15807
+ alignItems: "center",
15808
+ padding: 20
15809
+ },
15810
+ skipModalContent: {
15811
+ backgroundColor: "#18181b",
15812
+ borderRadius: 16,
15813
+ padding: 20,
15814
+ width: "100%",
15815
+ maxWidth: 340,
15816
+ borderWidth: 1,
15817
+ borderColor: "#3f3f46"
15818
+ },
15819
+ skipModalTitle: {
15820
+ fontSize: 18,
15821
+ fontWeight: "600",
15822
+ color: "#fafafa",
15823
+ marginBottom: 4
15824
+ },
15825
+ skipModalSubtitle: {
15826
+ fontSize: 14,
15827
+ color: "#71717a",
15828
+ marginBottom: 16
15829
+ },
15830
+ skipReasonOptions: {
15831
+ marginBottom: 16
15832
+ },
15833
+ skipReasonOption: {
15834
+ backgroundColor: "#27272a",
15835
+ padding: 12,
15836
+ borderRadius: 8,
15837
+ marginBottom: 8,
15838
+ borderWidth: 2,
15839
+ borderColor: "transparent"
15840
+ },
15841
+ skipReasonOptionSelected: {
15842
+ borderColor: "#eab308",
15843
+ backgroundColor: "#422006"
15844
+ },
15845
+ skipReasonLabel: {
15846
+ fontSize: 14,
15847
+ fontWeight: "600",
15848
+ color: "#fafafa",
15849
+ marginBottom: 2
15850
+ },
15851
+ skipReasonDesc: {
15852
+ fontSize: 12,
15853
+ color: "#71717a"
15854
+ },
15855
+ skipNotesInput: {
15856
+ backgroundColor: "#27272a",
15857
+ borderWidth: 1,
15858
+ borderColor: "#3f3f46",
15859
+ borderRadius: 8,
15860
+ padding: 12,
15861
+ fontSize: 14,
15862
+ color: "#fafafa",
15863
+ minHeight: 60,
15864
+ textAlignVertical: "top",
15865
+ marginBottom: 16
15866
+ },
15867
+ skipModalActions: {
15868
+ flexDirection: "row",
15869
+ gap: 8
15870
+ },
15871
+ skipModalCancel: {
15872
+ flex: 1,
15873
+ backgroundColor: "#3f3f46",
15874
+ paddingVertical: 12,
15875
+ borderRadius: 8,
15876
+ alignItems: "center"
15877
+ },
15878
+ skipModalCancelText: {
15879
+ fontSize: 14,
15880
+ fontWeight: "600",
15881
+ color: "#e4e4e7"
15882
+ },
15883
+ skipModalConfirm: {
15884
+ flex: 1,
15885
+ backgroundColor: "#eab308",
15886
+ paddingVertical: 12,
15887
+ borderRadius: 8,
15888
+ alignItems: "center"
15889
+ },
15890
+ skipModalConfirmDisabled: {
15891
+ backgroundColor: "#713f12"
15892
+ },
15893
+ skipModalConfirmText: {
15894
+ fontSize: 14,
15895
+ fontWeight: "600",
15896
+ color: "#18181b"
15897
+ },
15898
+ // Detail progress bar styles
15899
+ detailProgressContainer: {
15900
+ backgroundColor: "#27272a",
15901
+ padding: 12,
15902
+ borderRadius: 8,
15903
+ marginTop: 16,
15904
+ marginBottom: 8
15905
+ },
15906
+ detailProgressText: {
15907
+ fontSize: 12,
15908
+ color: "#a1a1aa",
15909
+ marginBottom: 8
15910
+ },
15911
+ detailProgressBar: {
15912
+ height: 4,
15913
+ backgroundColor: "#3f3f46",
15914
+ borderRadius: 2
15915
+ },
15916
+ detailProgressFill: {
15917
+ height: "100%",
15918
+ backgroundColor: "#22c55e",
15919
+ borderRadius: 2
15920
+ },
15921
+ nextTestButton: {
15922
+ backgroundColor: "#27272a",
15923
+ paddingVertical: 10,
15924
+ borderRadius: 10,
15925
+ alignItems: "center",
15926
+ marginTop: 8,
15927
+ borderWidth: 1,
15928
+ borderColor: "#3f3f46"
15929
+ },
15930
+ nextTestButtonText: {
15931
+ fontSize: 14,
15932
+ fontWeight: "500",
15933
+ color: "#a1a1aa"
15934
+ },
15935
+ filterBar: {
15936
+ flexDirection: "row",
15937
+ gap: 6,
15938
+ marginBottom: 10
15939
+ },
15940
+ filterChip: {
15941
+ paddingHorizontal: 10,
15942
+ paddingVertical: 5,
15943
+ borderRadius: 12,
15944
+ backgroundColor: "#27272a",
15945
+ borderWidth: 1,
15946
+ borderColor: "#3f3f46"
15947
+ },
15948
+ filterChipActive: {
15949
+ backgroundColor: "#1e3a5f",
15950
+ borderColor: "#3B82F6"
15951
+ },
15952
+ filterChipText: {
15953
+ fontSize: 12,
15954
+ color: "#71717a"
15955
+ },
15956
+ filterChipTextActive: {
15957
+ color: "#93c5fd"
15958
+ },
15959
+ messageSendError: {
15960
+ backgroundColor: "#7f1d1d",
15961
+ paddingHorizontal: 12,
15962
+ paddingVertical: 6,
15963
+ borderTopWidth: 1,
15964
+ borderTopColor: "#991b1b"
15965
+ },
15966
+ messageSendErrorText: {
15967
+ fontSize: 12,
15968
+ color: "#fca5a5",
15969
+ textAlign: "center"
15970
+ }
15971
+ });
15972
+ var exploreStyles = StyleSheet.create({
15973
+ formGroup: {
15974
+ marginBottom: 12
15975
+ },
15976
+ label: {
15977
+ fontSize: 12,
15978
+ fontWeight: "500",
15979
+ color: "#d4d4d8",
15980
+ marginBottom: 6
15981
+ },
15982
+ input: {
15983
+ backgroundColor: "#27272a",
15984
+ borderRadius: 8,
15985
+ paddingHorizontal: 12,
15986
+ paddingVertical: 10,
15987
+ fontSize: 14,
15988
+ color: "#fafafa",
15989
+ borderWidth: 1,
15990
+ borderColor: "#3f3f46"
15991
+ },
15992
+ platformRow: {
15993
+ flexDirection: "row",
15994
+ gap: 8
15995
+ },
15996
+ platformButton: {
15997
+ flex: 1,
15998
+ paddingVertical: 10,
15999
+ paddingHorizontal: 8,
16000
+ borderRadius: 8,
16001
+ backgroundColor: "#27272a",
16002
+ borderWidth: 2,
16003
+ borderColor: "transparent",
16004
+ alignItems: "center"
16005
+ },
16006
+ platformButtonActive: {
16007
+ backgroundColor: "#172554",
16008
+ borderColor: "#3B82F6"
16009
+ },
16010
+ platformButtonText: {
16011
+ fontSize: 12,
16012
+ fontWeight: "500",
16013
+ color: "#a1a1aa"
16014
+ },
16015
+ platformButtonTextActive: {
16016
+ color: "#93c5fd"
16017
+ },
16018
+ startButton: {
16019
+ backgroundColor: "#16a34a",
16020
+ borderRadius: 8,
16021
+ paddingVertical: 14,
16022
+ alignItems: "center",
16023
+ marginTop: 4
16024
+ },
16025
+ startButtonText: {
16026
+ color: "#fff",
16027
+ fontSize: 14,
16028
+ fontWeight: "600"
16029
+ },
16030
+ buttonRow: {
16031
+ flexDirection: "row",
16032
+ gap: 8
16033
+ },
16034
+ cancelButton: {
16035
+ flex: 1,
16036
+ backgroundColor: "#3f3f46",
16037
+ borderRadius: 8,
16038
+ paddingVertical: 10,
16039
+ alignItems: "center"
16040
+ },
16041
+ cancelButtonText: {
16042
+ color: "#d4d4d8",
16043
+ fontSize: 14,
16044
+ fontWeight: "500"
16045
+ },
16046
+ endButton: {
16047
+ flex: 1,
16048
+ backgroundColor: "#dc2626",
16049
+ borderRadius: 8,
16050
+ paddingVertical: 10,
16051
+ alignItems: "center"
16052
+ },
16053
+ endButtonText: {
16054
+ color: "#fff",
16055
+ fontSize: 14,
16056
+ fontWeight: "500"
16057
+ },
16058
+ findingHeader: {
16059
+ flexDirection: "row",
16060
+ justifyContent: "space-between",
16061
+ alignItems: "center",
16062
+ marginBottom: 12
16063
+ },
16064
+ findingHeaderTitle: {
16065
+ fontSize: 14,
16066
+ fontWeight: "600",
16067
+ color: "#fafafa"
16068
+ },
16069
+ findingHeaderClose: {
16070
+ fontSize: 16,
16071
+ color: "#71717a"
16072
+ },
16073
+ findingTypeRow: {
16074
+ flexDirection: "row",
16075
+ gap: 4,
16076
+ marginBottom: 12
16077
+ },
16078
+ findingTypeButton: {
16079
+ flex: 1,
16080
+ paddingVertical: 8,
16081
+ paddingHorizontal: 4,
16082
+ borderRadius: 6,
16083
+ backgroundColor: "#3f3f46",
16084
+ alignItems: "center"
16085
+ },
16086
+ findingTypeButtonActive: {
16087
+ backgroundColor: "#1e3a5f",
16088
+ borderWidth: 2,
16089
+ borderColor: "#3B82F6"
16090
+ },
16091
+ findingTypeButtonText: {
16092
+ fontSize: 11,
16093
+ fontWeight: "500",
16094
+ color: "#a1a1aa"
16095
+ },
16096
+ findingTypeButtonTextActive: {
16097
+ color: "#93c5fd"
16098
+ },
16099
+ severityRow: {
16100
+ flexDirection: "row",
16101
+ gap: 4
16102
+ },
16103
+ severityButton: {
16104
+ flex: 1,
16105
+ paddingVertical: 6,
16106
+ borderRadius: 6,
16107
+ backgroundColor: "#3f3f46",
16108
+ alignItems: "center"
16109
+ },
16110
+ severityCritical: {
16111
+ backgroundColor: "#dc2626"
16112
+ },
16113
+ severityHigh: {
16114
+ backgroundColor: "#f97316"
16115
+ },
16116
+ severityMedium: {
16117
+ backgroundColor: "#eab308"
16118
+ },
16119
+ severityLow: {
16120
+ backgroundColor: "#3f3f46",
16121
+ borderWidth: 1,
16122
+ borderColor: "#71717a"
16123
+ },
16124
+ severityButtonText: {
16125
+ fontSize: 11,
16126
+ fontWeight: "500",
16127
+ color: "#a1a1aa",
16128
+ textTransform: "capitalize"
16129
+ },
16130
+ severityButtonTextActive: {
16131
+ color: "#fff"
16132
+ },
16133
+ addFindingButton: {
16134
+ backgroundColor: "#3B82F6",
16135
+ borderRadius: 8,
16136
+ paddingVertical: 10,
16137
+ alignItems: "center"
16138
+ },
16139
+ addFindingButtonText: {
16140
+ color: "#fff",
16141
+ fontSize: 14,
16142
+ fontWeight: "500"
16143
+ },
16144
+ sessionBanner: {
16145
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16146
+ borderRadius: 12,
16147
+ padding: 12,
16148
+ marginBottom: 12,
16149
+ borderWidth: 1,
16150
+ borderColor: "#166534"
16151
+ },
16152
+ sessionBannerRow: {
16153
+ flexDirection: "row",
16154
+ justifyContent: "space-between",
16155
+ alignItems: "center"
16156
+ },
16157
+ sessionBannerLeft: {
16158
+ flexDirection: "row",
16159
+ alignItems: "center",
16160
+ gap: 8
16161
+ },
16162
+ sessionDotLarge: {
16163
+ width: 8,
16164
+ height: 8,
16165
+ borderRadius: 4,
16166
+ backgroundColor: "#22c55e"
16167
+ },
16168
+ sessionBannerLabel: {
16169
+ fontSize: 14,
16170
+ fontWeight: "500",
16171
+ color: "#86efac"
16172
+ },
16173
+ sessionTimer: {
16174
+ fontSize: 20,
16175
+ fontWeight: "600",
16176
+ color: "#4ade80",
16177
+ fontVariant: ["tabular-nums"]
16178
+ },
16179
+ sessionFocus: {
16180
+ fontSize: 12,
16181
+ color: "#4ade80",
16182
+ marginTop: 4
16183
+ },
16184
+ addButton: {
16185
+ backgroundColor: "#3B82F6",
16186
+ borderRadius: 8,
16187
+ paddingVertical: 14,
16188
+ alignItems: "center",
16189
+ marginBottom: 12
16190
+ },
16191
+ addButtonText: {
16192
+ color: "#fff",
16193
+ fontSize: 14,
16194
+ fontWeight: "600"
16195
+ },
16196
+ findingsSection: {
16197
+ marginBottom: 12
16198
+ },
16199
+ findingsLabel: {
16200
+ fontSize: 12,
16201
+ fontWeight: "500",
16202
+ color: "#71717a",
16203
+ marginBottom: 8
16204
+ },
16205
+ findingsEmpty: {
16206
+ backgroundColor: "#27272a",
16207
+ borderRadius: 8,
16208
+ paddingVertical: 16,
16209
+ alignItems: "center"
16210
+ },
16211
+ findingsEmptyText: {
16212
+ fontSize: 12,
16213
+ color: "#71717a"
16214
+ },
16215
+ findingCard: {
16216
+ flexDirection: "row",
16217
+ alignItems: "flex-start",
16218
+ padding: 8,
16219
+ borderRadius: 8,
16220
+ marginBottom: 6,
16221
+ borderWidth: 1,
16222
+ gap: 8
16223
+ },
16224
+ findingCardBug: {
16225
+ backgroundColor: "rgba(220, 38, 38, 0.1)",
16226
+ borderColor: "#991b1b"
16227
+ },
16228
+ findingCardConcern: {
16229
+ backgroundColor: "rgba(249, 115, 22, 0.1)",
16230
+ borderColor: "#9a3412"
16231
+ },
16232
+ findingCardSuggestion: {
16233
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16234
+ borderColor: "#1e40af"
16235
+ },
16236
+ findingCardQuestion: {
16237
+ backgroundColor: "rgba(139, 92, 246, 0.1)",
16238
+ borderColor: "#5b21b6"
16239
+ },
16240
+ findingCardIcon: {
16241
+ fontSize: 14
16242
+ },
16243
+ findingCardTitle: {
16244
+ fontSize: 12,
16245
+ fontWeight: "500",
16246
+ color: "#fafafa"
16247
+ },
16248
+ findingCardSeverity: {
16249
+ fontSize: 10,
16250
+ fontWeight: "500",
16251
+ marginTop: 2,
16252
+ textTransform: "capitalize"
16253
+ },
16254
+ endSessionButton: {
16255
+ backgroundColor: "#3f3f46",
16256
+ borderRadius: 8,
16257
+ paddingVertical: 10,
16258
+ alignItems: "center"
16259
+ },
16260
+ endSessionButtonText: {
16261
+ color: "#d4d4d8",
16262
+ fontSize: 14,
16263
+ fontWeight: "500"
16264
+ }
16265
+ });
16266
+ var feedbackStyles = StyleSheet.create({
16267
+ container: {
16268
+ padding: 4
16269
+ },
16270
+ statusText: {
16271
+ fontSize: 16,
16272
+ fontWeight: "600",
16273
+ marginTop: 4
16274
+ },
16275
+ infoBox: {
16276
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16277
+ borderRadius: 8,
16278
+ padding: 12,
16279
+ marginBottom: 16,
16280
+ borderWidth: 1,
16281
+ borderColor: "#1e3a5f"
16282
+ },
16283
+ infoTitle: {
16284
+ fontSize: 14,
16285
+ fontWeight: "500",
16286
+ color: "#93c5fd",
16287
+ marginBottom: 4
16288
+ },
16289
+ infoSubtitle: {
16290
+ fontSize: 12,
16291
+ color: "#60a5fa"
16292
+ },
16293
+ ratingSection: {
16294
+ alignItems: "center",
16295
+ marginBottom: 16
16296
+ },
16297
+ ratingLabel: {
16298
+ fontSize: 12,
16299
+ fontWeight: "500",
16300
+ color: "#a1a1aa",
16301
+ marginBottom: 8
16302
+ },
16303
+ starsRow: {
16304
+ flexDirection: "row",
16305
+ gap: 4
16306
+ },
16307
+ star: {
16308
+ fontSize: 28
16309
+ },
16310
+ starActive: {
16311
+ color: "#facc15"
16312
+ },
16313
+ starInactive: {
16314
+ color: "#3f3f46"
16315
+ },
16316
+ ratingDesc: {
16317
+ fontSize: 12,
16318
+ color: "#71717a",
16319
+ marginTop: 4
16320
+ },
16321
+ flagsSection: {
16322
+ marginBottom: 12
16323
+ },
16324
+ flagsGrid: {
16325
+ flexDirection: "row",
16326
+ flexWrap: "wrap",
16327
+ gap: 8
16328
+ },
16329
+ flagButton: {
16330
+ paddingHorizontal: 10,
16331
+ paddingVertical: 6,
16332
+ borderRadius: 6,
16333
+ backgroundColor: "#27272a",
16334
+ borderWidth: 1,
16335
+ borderColor: "#3f3f46"
16336
+ },
16337
+ flagButtonActive: {
16338
+ backgroundColor: "#1e3a5f",
16339
+ borderColor: "#3B82F6"
16340
+ },
16341
+ flagButtonText: {
16342
+ fontSize: 12,
16343
+ fontWeight: "500",
16344
+ color: "#a1a1aa"
16345
+ },
16346
+ flagButtonTextActive: {
16347
+ color: "#93c5fd"
16348
+ },
16349
+ noteInput: {
16350
+ backgroundColor: "#27272a",
16351
+ borderRadius: 8,
16352
+ paddingHorizontal: 12,
16353
+ paddingVertical: 10,
16354
+ fontSize: 14,
16355
+ color: "#fafafa",
16356
+ borderWidth: 1,
16357
+ borderColor: "#3f3f46",
16358
+ minHeight: 60
16359
+ },
16360
+ buttonRow: {
16361
+ flexDirection: "row",
16362
+ gap: 8
16363
+ },
16364
+ skipButton: {
16365
+ flex: 1,
16366
+ paddingVertical: 10,
16367
+ backgroundColor: "#3f3f46",
16368
+ borderRadius: 8,
16369
+ alignItems: "center"
16370
+ },
16371
+ skipButtonText: {
16372
+ color: "#a1a1aa",
16373
+ fontSize: 14,
16374
+ fontWeight: "500"
16375
+ },
16376
+ submitButton: {
16377
+ flex: 1,
16378
+ paddingVertical: 10,
16379
+ backgroundColor: "#3B82F6",
16380
+ borderRadius: 8,
16381
+ alignItems: "center"
16382
+ },
16383
+ submitButtonText: {
16384
+ color: "#fff",
16385
+ fontSize: 14,
16386
+ fontWeight: "500"
16387
+ }
16388
+ });
16389
+ var timerStyles = StyleSheet.create({
16390
+ container: {
16391
+ flexDirection: "row",
16392
+ alignItems: "center",
16393
+ gap: 6,
16394
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16395
+ paddingHorizontal: 8,
16396
+ paddingVertical: 4,
16397
+ borderRadius: 6,
16398
+ marginBottom: 8,
16399
+ alignSelf: "flex-start"
16400
+ },
16401
+ dot: {
16402
+ width: 6,
16403
+ height: 6,
16404
+ borderRadius: 3,
16405
+ backgroundColor: "#22c55e"
16406
+ },
16407
+ label: {
16408
+ fontSize: 12,
16409
+ fontWeight: "500",
16410
+ color: "#4ade80"
16411
+ },
16412
+ time: {
16413
+ fontSize: 12,
16414
+ fontWeight: "600",
16415
+ color: "#4ade80",
16416
+ fontVariant: ["tabular-nums"]
14983
16417
  }
14984
16418
  });
14985
16419
  export {