@bbearai/react-native 0.1.9 → 0.2.0

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);
@@ -12896,6 +12995,13 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12896
12995
  sendMessage,
12897
12996
  markAsRead,
12898
12997
  createThread,
12998
+ // QA Sessions
12999
+ activeSession,
13000
+ sessionFindings,
13001
+ startSession,
13002
+ endSession,
13003
+ addFinding,
13004
+ refreshSession,
12899
13005
  refreshTesterStatus,
12900
13006
  updateTesterProfile,
12901
13007
  refreshTesterInfo
@@ -12906,7 +13012,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12906
13012
  }
12907
13013
 
12908
13014
  // src/BugBearButton.tsx
12909
- import React2, { useState as useState2, useEffect as useEffect2, useRef as useRef2 } from "react";
13015
+ import React2, { useState as useState2, useEffect as useEffect2, useRef as useRef2, useMemo, useCallback as useCallback2 } from "react";
12910
13016
  import {
12911
13017
  View,
12912
13018
  Text,
@@ -12956,7 +13062,13 @@ function BugBearButton({
12956
13062
  markAsRead,
12957
13063
  createThread,
12958
13064
  updateTesterProfile,
12959
- refreshTesterInfo
13065
+ refreshTesterInfo,
13066
+ activeSession,
13067
+ sessionFindings,
13068
+ startSession,
13069
+ endSession,
13070
+ addFinding,
13071
+ refreshSession
12960
13072
  } = useBugBear();
12961
13073
  const [modalVisible, setModalVisible] = useState2(false);
12962
13074
  const [activeTab, setActiveTab] = useState2("tests");
@@ -13044,39 +13156,228 @@ function BugBearButton({
13044
13156
  const [submitting, setSubmitting] = useState2(false);
13045
13157
  const [submitted, setSubmitted] = useState2(false);
13046
13158
  const [justPassed, setJustPassed] = useState2(false);
13159
+ const [showFeedbackPrompt, setShowFeedbackPrompt] = useState2(false);
13160
+ const [pendingFeedbackStatus, setPendingFeedbackStatus] = useState2(null);
13161
+ const [feedbackRating, setFeedbackRating] = useState2(5);
13162
+ const [feedbackNote, setFeedbackNote] = useState2("");
13163
+ const [feedbackFlags, setFeedbackFlags] = useState2({
13164
+ isOutdated: false,
13165
+ needsMoreDetail: false,
13166
+ stepsUnclear: false,
13167
+ expectedResultUnclear: false
13168
+ });
13047
13169
  const [criteriaResults, setCriteriaResults] = useState2({});
13170
+ const [showSkipModal, setShowSkipModal] = useState2(false);
13171
+ const [selectedSkipReason, setSelectedSkipReason] = useState2(null);
13172
+ const [skipNotes, setSkipNotes] = useState2("");
13173
+ const [skipping, setSkipping] = useState2(false);
13174
+ const [collapsedFolders, setCollapsedFolders] = useState2(/* @__PURE__ */ new Set());
13175
+ const [startingSession, setStartingSession] = useState2(false);
13176
+ const [sessionFocusArea, setSessionFocusArea] = useState2("");
13177
+ const [sessionPlatform, setSessionPlatform] = useState2(Platform2.OS === "ios" ? "ios" : "android");
13178
+ const [showAddFinding, setShowAddFinding] = useState2(false);
13179
+ const [findingType, setFindingType] = useState2("bug");
13180
+ const [findingTitle, setFindingTitle] = useState2("");
13181
+ const [findingDescription, setFindingDescription] = useState2("");
13182
+ const [findingSeverity, setFindingSeverity] = useState2("medium");
13183
+ const [addingFinding, setAddingFinding] = useState2(false);
13184
+ const [endingSession, setEndingSession] = useState2(false);
13185
+ const [sessionNotes, setSessionNotes] = useState2("");
13186
+ const [showEndConfirm, setShowEndConfirm] = useState2(false);
13187
+ const [sessionElapsedTime, setSessionElapsedTime] = useState2(0);
13188
+ const [assignmentElapsedTime, setAssignmentElapsedTime] = useState2(0);
13189
+ useEffect2(() => {
13190
+ const activeAssignment = displayedAssignment?.status === "in_progress" ? displayedAssignment : null;
13191
+ if (!activeAssignment?.startedAt) {
13192
+ setAssignmentElapsedTime(0);
13193
+ return;
13194
+ }
13195
+ const startTime = new Date(activeAssignment.startedAt).getTime();
13196
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13197
+ const interval = setInterval(() => {
13198
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13199
+ }, 1e3);
13200
+ return () => clearInterval(interval);
13201
+ }, [displayedAssignment?.id, displayedAssignment?.status, displayedAssignment?.startedAt]);
13202
+ useEffect2(() => {
13203
+ if (!activeSession) {
13204
+ setSessionElapsedTime(0);
13205
+ return;
13206
+ }
13207
+ const startTime = new Date(activeSession.startedAt).getTime();
13208
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13209
+ const interval = setInterval(() => {
13210
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13211
+ }, 1e3);
13212
+ return () => clearInterval(interval);
13213
+ }, [activeSession]);
13214
+ const formatElapsedTime = (seconds) => {
13215
+ const h = Math.floor(seconds / 3600);
13216
+ const m = Math.floor(seconds % 3600 / 60);
13217
+ const s = seconds % 60;
13218
+ if (h > 0) return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
13219
+ return `${m}:${s.toString().padStart(2, "0")}`;
13220
+ };
13048
13221
  useEffect2(() => {
13049
13222
  setCriteriaResults({});
13050
13223
  setShowSteps(false);
13051
13224
  }, [displayedAssignment?.id]);
13225
+ const groupedAssignments = useMemo(() => {
13226
+ const groups = /* @__PURE__ */ new Map();
13227
+ for (const assignment of assignments) {
13228
+ const groupId = assignment.testCase.group?.id || "ungrouped";
13229
+ const group = assignment.testCase.group || null;
13230
+ if (!groups.has(groupId)) {
13231
+ groups.set(groupId, {
13232
+ group,
13233
+ assignments: [],
13234
+ stats: { total: 0, passed: 0, failed: 0, pending: 0, skipped: 0 }
13235
+ });
13236
+ }
13237
+ const folder = groups.get(groupId);
13238
+ folder.assignments.push(assignment);
13239
+ folder.stats.total++;
13240
+ if (assignment.status === "passed") folder.stats.passed++;
13241
+ else if (assignment.status === "failed") folder.stats.failed++;
13242
+ else if (assignment.status === "skipped") folder.stats.skipped++;
13243
+ else folder.stats.pending++;
13244
+ }
13245
+ const sortedGroups = Array.from(groups.values()).sort((a, b) => {
13246
+ if (!a.group && !b.group) return 0;
13247
+ if (!a.group) return 1;
13248
+ if (!b.group) return -1;
13249
+ return a.group.sortOrder - b.group.sortOrder;
13250
+ });
13251
+ return sortedGroups;
13252
+ }, [assignments]);
13253
+ const toggleFolderCollapse = useCallback2((groupId) => {
13254
+ setCollapsedFolders((prev) => {
13255
+ const next = new Set(prev);
13256
+ if (next.has(groupId)) {
13257
+ next.delete(groupId);
13258
+ } else {
13259
+ next.add(groupId);
13260
+ }
13261
+ return next;
13262
+ });
13263
+ }, []);
13264
+ const getStatusBadge = (status) => {
13265
+ switch (status) {
13266
+ case "passed":
13267
+ return { icon: "\u2705", label: "Passed", color: "#22c55e" };
13268
+ case "failed":
13269
+ return { icon: "\u274C", label: "Failed", color: "#ef4444" };
13270
+ case "skipped":
13271
+ return { icon: "\u23ED\uFE0F", label: "Skipped", color: "#eab308" };
13272
+ case "in_progress":
13273
+ return { icon: "\u{1F504}", label: "In Progress", color: "#3b82f6" };
13274
+ case "blocked":
13275
+ return { icon: "\u{1F6AB}", label: "Blocked", color: "#f97316" };
13276
+ case "pending":
13277
+ default:
13278
+ return { icon: "\u23F3", label: "Pending", color: "#71717a" };
13279
+ }
13280
+ };
13052
13281
  if (isLoading || !shouldShowWidget) {
13053
13282
  return null;
13054
13283
  }
13055
13284
  const pendingCount = assignments.filter((a) => a.status === "pending").length;
13056
13285
  const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
13057
13286
  const handlePass = async () => {
13287
+ if (!displayedAssignment) return;
13288
+ setPendingFeedbackStatus("passed");
13289
+ setShowFeedbackPrompt(true);
13290
+ setFeedbackRating(5);
13291
+ setFeedbackNote("");
13292
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13293
+ };
13294
+ const handleFail = () => {
13295
+ if (!displayedAssignment) return;
13296
+ setPendingFeedbackStatus("failed");
13297
+ setShowFeedbackPrompt(true);
13298
+ setFeedbackRating(3);
13299
+ setFeedbackNote("");
13300
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13301
+ };
13302
+ const handleSubmitFeedback = async (skipFeedback = false) => {
13058
13303
  if (!client || !displayedAssignment) return;
13059
13304
  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);
13305
+ const feedback = skipFeedback ? void 0 : {
13306
+ rating: feedbackRating,
13307
+ feedbackNote: feedbackNote.trim() || void 0,
13308
+ isOutdated: feedbackFlags.isOutdated,
13309
+ needsMoreDetail: feedbackFlags.needsMoreDetail,
13310
+ stepsUnclear: feedbackFlags.stepsUnclear,
13311
+ expectedResultUnclear: feedbackFlags.expectedResultUnclear
13312
+ };
13313
+ if (pendingFeedbackStatus === "passed") {
13314
+ await client.submitReport({
13315
+ type: "test_pass",
13316
+ description: `Test passed: ${displayedAssignment.testCase.title}`,
13317
+ assignmentId: displayedAssignment.id,
13318
+ testCaseId: displayedAssignment.testCase.id,
13319
+ appContext: getAppContext?.() || { currentRoute: "unknown" },
13320
+ deviceInfo: getDeviceInfo()
13321
+ });
13322
+ if (feedback) {
13323
+ await client.submitTestFeedback({
13324
+ testCaseId: displayedAssignment.testCase.id,
13325
+ assignmentId: displayedAssignment.id,
13326
+ feedback,
13327
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13328
+ });
13329
+ }
13330
+ await refreshAssignments();
13331
+ setSubmitting(false);
13332
+ setShowFeedbackPrompt(false);
13333
+ setPendingFeedbackStatus(null);
13334
+ setJustPassed(true);
13335
+ setTimeout(() => {
13336
+ setJustPassed(false);
13337
+ setSelectedTestId(null);
13338
+ setTestView("detail");
13339
+ }, 1200);
13340
+ } else if (pendingFeedbackStatus === "failed") {
13341
+ if (feedback) {
13342
+ await client.submitTestFeedback({
13343
+ testCaseId: displayedAssignment.testCase.id,
13344
+ assignmentId: displayedAssignment.id,
13345
+ feedback,
13346
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13347
+ });
13348
+ }
13349
+ setSubmitting(false);
13350
+ setShowFeedbackPrompt(false);
13351
+ setPendingFeedbackStatus(null);
13352
+ setActiveTab("report");
13353
+ setReportType("test_fail");
13354
+ }
13355
+ };
13356
+ const handleSkipFeedback = () => {
13357
+ handleSubmitFeedback(true);
13358
+ };
13359
+ const handleOpenSkipModal = () => {
13360
+ setShowSkipModal(true);
13361
+ setSelectedSkipReason(null);
13362
+ setSkipNotes("");
13363
+ };
13364
+ const handleSkip = async () => {
13365
+ if (!client || !displayedAssignment || !selectedSkipReason) return;
13366
+ setSkipping(true);
13367
+ const result = await client.skipAssignment(
13368
+ displayedAssignment.id,
13369
+ selectedSkipReason,
13370
+ skipNotes || void 0
13371
+ );
13372
+ if (result.success) {
13373
+ await refreshAssignments();
13374
+ setShowSkipModal(false);
13375
+ setSelectedSkipReason(null);
13376
+ setSkipNotes("");
13073
13377
  setSelectedTestId(null);
13074
13378
  setTestView("detail");
13075
- }, 1200);
13076
- };
13077
- const handleFail = () => {
13078
- setActiveTab("report");
13079
- setReportType("test_fail");
13379
+ }
13380
+ setSkipping(false);
13080
13381
  };
13081
13382
  const handleSubmitReport = async () => {
13082
13383
  if (!client || !description.trim()) return;
@@ -13223,6 +13524,44 @@ function BugBearButton({
13223
13524
  }
13224
13525
  setSavingProfile(false);
13225
13526
  };
13527
+ const handleStartSession = async () => {
13528
+ setStartingSession(true);
13529
+ const result = await startSession({
13530
+ focusArea: sessionFocusArea.trim() || void 0,
13531
+ platform: sessionPlatform
13532
+ });
13533
+ if (result.success) {
13534
+ setSessionFocusArea("");
13535
+ }
13536
+ setStartingSession(false);
13537
+ };
13538
+ const handleEndSession = async () => {
13539
+ setEndingSession(true);
13540
+ const result = await endSession(sessionNotes.trim() || void 0);
13541
+ if (result.success) {
13542
+ setSessionNotes("");
13543
+ setShowEndConfirm(false);
13544
+ }
13545
+ setEndingSession(false);
13546
+ };
13547
+ const handleAddFinding = async () => {
13548
+ if (!findingTitle.trim()) return;
13549
+ setAddingFinding(true);
13550
+ const result = await addFinding({
13551
+ type: findingType,
13552
+ title: findingTitle.trim(),
13553
+ description: findingDescription.trim() || void 0,
13554
+ severity: findingType === "bug" ? findingSeverity : void 0
13555
+ });
13556
+ if (result.success) {
13557
+ setFindingTitle("");
13558
+ setFindingDescription("");
13559
+ setFindingType("bug");
13560
+ setFindingSeverity("medium");
13561
+ setShowAddFinding(false);
13562
+ }
13563
+ setAddingFinding(false);
13564
+ };
13226
13565
  const formatRelativeTime = (dateString) => {
13227
13566
  const date = new Date(dateString);
13228
13567
  const now = /* @__PURE__ */ new Date();
@@ -13406,6 +13745,13 @@ function BugBearButton({
13406
13745
  onPress: () => setActiveTab("messages")
13407
13746
  },
13408
13747
  /* @__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)))
13748
+ ), /* @__PURE__ */ React2.createElement(
13749
+ TouchableOpacity,
13750
+ {
13751
+ style: [styles.tab, activeTab === "explore" && styles.activeTab],
13752
+ onPress: () => setActiveTab("explore")
13753
+ },
13754
+ /* @__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
13755
  ), /* @__PURE__ */ React2.createElement(
13410
13756
  TouchableOpacity,
13411
13757
  {
@@ -13414,32 +13760,114 @@ function BugBearButton({
13414
13760
  },
13415
13761
  /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "report" && styles.activeTabText] }, "Report")
13416
13762
  )), /* @__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(
13763
+ /* List View - Show tests grouped by folder */
13764
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"), groupedAssignments.map((folder) => {
13765
+ const groupId = folder.group?.id || "ungrouped";
13766
+ const isCollapsed = collapsedFolders.has(groupId);
13767
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13768
+ return /* @__PURE__ */ React2.createElement(View, { key: groupId, style: styles.folderContainer }, /* @__PURE__ */ React2.createElement(
13769
+ TouchableOpacity,
13770
+ {
13771
+ onPress: () => toggleFolderCollapse(groupId),
13772
+ style: styles.folderHeader
13773
+ },
13774
+ /* @__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")),
13775
+ /* @__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"))
13776
+ ), !isCollapsed && /* @__PURE__ */ React2.createElement(View, { style: styles.folderProgressBar }, /* @__PURE__ */ React2.createElement(
13777
+ View,
13778
+ {
13779
+ style: [
13780
+ styles.folderProgressFill,
13781
+ { width: `${completedCount / folder.stats.total * 100}%` }
13782
+ ]
13783
+ }
13784
+ )), !isCollapsed && folder.assignments.map((assignment) => {
13785
+ const statusBadge = getStatusBadge(assignment.status);
13786
+ return /* @__PURE__ */ React2.createElement(
13787
+ TouchableOpacity,
13788
+ {
13789
+ key: assignment.id,
13790
+ onPress: () => {
13791
+ setSelectedTestId(assignment.id);
13792
+ setTestView("detail");
13793
+ setShowSteps(false);
13794
+ },
13795
+ style: [
13796
+ styles.listItem,
13797
+ styles.listItemInFolder,
13798
+ assignment.id === currentAssignment?.id && styles.listItemCurrent
13799
+ ]
13800
+ },
13801
+ /* @__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: [
13802
+ styles.priorityBadge,
13803
+ assignment.testCase.priority === "P0" && styles.priorityP0,
13804
+ assignment.testCase.priority === "P1" && styles.priorityP1
13805
+ ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, assignment.testCase.priority)))),
13806
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
13807
+ /* @__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"))
13808
+ );
13809
+ }));
13810
+ }))
13811
+ ) : justPassed ? (
13812
+ /* Success state after passing */
13813
+ /* @__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..."))
13814
+ ) : showFeedbackPrompt && displayedAssignment ? (
13815
+ /* Feedback prompt after completing a test */
13816
+ /* @__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(
13419
13817
  TouchableOpacity,
13420
13818
  {
13421
- key: assignment.id,
13422
- onPress: () => {
13423
- setSelectedTestId(assignment.id);
13424
- setTestView("detail");
13425
- setShowSteps(false);
13426
- },
13819
+ key: star,
13820
+ onPress: () => setFeedbackRating(star)
13821
+ },
13822
+ /* @__PURE__ */ React2.createElement(Text, { style: [feedbackStyles.star, star <= feedbackRating ? feedbackStyles.starActive : feedbackStyles.starInactive] }, "\u2605")
13823
+ ))), /* @__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 }, [
13824
+ { key: "stepsUnclear", label: "Steps unclear" },
13825
+ { key: "expectedResultUnclear", label: "Expected result unclear" },
13826
+ { key: "needsMoreDetail", label: "Needs more detail" },
13827
+ { key: "isOutdated", label: "Seems outdated" }
13828
+ ].map(({ key, label }) => /* @__PURE__ */ React2.createElement(
13829
+ TouchableOpacity,
13830
+ {
13831
+ key,
13832
+ onPress: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
13427
13833
  style: [
13428
- styles.listItem,
13429
- assignment.id === currentAssignment?.id && styles.listItemCurrent
13834
+ feedbackStyles.flagButton,
13835
+ feedbackFlags[key] && feedbackStyles.flagButtonActive
13430
13836
  ]
13431
13837
  },
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"))
13838
+ /* @__PURE__ */ React2.createElement(Text, { style: [
13839
+ feedbackStyles.flagButtonText,
13840
+ feedbackFlags[key] && feedbackStyles.flagButtonTextActive
13841
+ ] }, label)
13842
+ )))), /* @__PURE__ */ React2.createElement(View, { style: { marginBottom: 12 } }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingLabel }, "Suggestions? (optional)"), /* @__PURE__ */ React2.createElement(
13843
+ TextInput,
13844
+ {
13845
+ style: feedbackStyles.noteInput,
13846
+ value: feedbackNote,
13847
+ onChangeText: setFeedbackNote,
13848
+ placeholder: "How could this test be improved?",
13849
+ placeholderTextColor: "#71717a",
13850
+ multiline: true,
13851
+ numberOfLines: 2,
13852
+ textAlignVertical: "top"
13853
+ }
13854
+ )), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.buttonRow }, /* @__PURE__ */ React2.createElement(
13855
+ TouchableOpacity,
13856
+ {
13857
+ onPress: handleSkipFeedback,
13858
+ disabled: submitting,
13859
+ style: [feedbackStyles.skipButton, submitting && { opacity: 0.5 }]
13860
+ },
13861
+ /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.skipButtonText }, "Skip")
13862
+ ), /* @__PURE__ */ React2.createElement(
13863
+ TouchableOpacity,
13864
+ {
13865
+ onPress: () => handleSubmitFeedback(false),
13866
+ disabled: submitting,
13867
+ style: [feedbackStyles.submitButton, submitting && { opacity: 0.5 }]
13868
+ },
13869
+ /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.submitButtonText }, submitting ? "Submitting..." : "Submit Feedback")
13439
13870
  )))
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
13871
  ) : displayedAssignment ? (
13444
13872
  /* Detail View - Show single test */
13445
13873
  /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(
@@ -13456,20 +13884,41 @@ function BugBearButton({
13456
13884
  styles.priorityBadge,
13457
13885
  displayedAssignment.testCase.priority === "P0" && styles.priorityP0,
13458
13886
  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(
13887
+ ] }, /* @__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 && (() => {
13888
+ const folder = groupedAssignments.find((f) => f.group?.id === displayedAssignment.testCase.group?.id);
13889
+ if (!folder) return null;
13890
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13891
+ 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(
13892
+ View,
13893
+ {
13894
+ style: [
13895
+ styles.detailProgressFill,
13896
+ { width: `${completedCount / folder.stats.total * 100}%` }
13897
+ ]
13898
+ }
13899
+ )));
13900
+ })(), /* @__PURE__ */ React2.createElement(View, { style: styles.actionButtons }, /* @__PURE__ */ React2.createElement(
13460
13901
  TouchableOpacity,
13461
13902
  {
13462
13903
  style: styles.failButton,
13463
13904
  onPress: handleFail,
13464
- disabled: submitting
13905
+ disabled: submitting || skipping
13465
13906
  },
13466
13907
  /* @__PURE__ */ React2.createElement(Text, { style: styles.failButtonText }, "\u2717 Fail")
13908
+ ), /* @__PURE__ */ React2.createElement(
13909
+ TouchableOpacity,
13910
+ {
13911
+ style: styles.skipButton,
13912
+ onPress: handleOpenSkipModal,
13913
+ disabled: submitting || skipping
13914
+ },
13915
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipButtonText }, skipping ? "..." : "\u2192 Skip")
13467
13916
  ), /* @__PURE__ */ React2.createElement(
13468
13917
  TouchableOpacity,
13469
13918
  {
13470
13919
  style: styles.passButton,
13471
13920
  onPress: handlePass,
13472
- disabled: submitting
13921
+ disabled: submitting || skipping
13473
13922
  },
13474
13923
  /* @__PURE__ */ React2.createElement(Text, { style: styles.passButtonText }, submitting ? "..." : "\u2713 Pass")
13475
13924
  )))
@@ -13557,6 +14006,166 @@ function BugBearButton({
13557
14006
  message.senderType === "tester" && styles.messageTimeTester
13558
14007
  ] }, formatMessageTime(message.createdAt))
13559
14008
  ))))
14009
+ )), activeTab === "explore" && /* @__PURE__ */ React2.createElement(View, null, !activeSession ? (
14010
+ /* Start Session View */
14011
+ /* @__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(
14012
+ TextInput,
14013
+ {
14014
+ style: exploreStyles.input,
14015
+ value: sessionFocusArea,
14016
+ onChangeText: setSessionFocusArea,
14017
+ placeholder: "e.g., checkout flow, settings page",
14018
+ placeholderTextColor: "#71717a"
14019
+ }
14020
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Platform"), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.platformRow }, [
14021
+ { key: "ios", label: "\u{1F4F1} iOS" },
14022
+ { key: "android", label: "\u{1F916} Android" },
14023
+ { key: "web", label: "\u{1F310} Web" }
14024
+ ].map(({ key, label }) => /* @__PURE__ */ React2.createElement(
14025
+ TouchableOpacity,
14026
+ {
14027
+ key,
14028
+ onPress: () => setSessionPlatform(key),
14029
+ style: [
14030
+ exploreStyles.platformButton,
14031
+ sessionPlatform === key && exploreStyles.platformButtonActive
14032
+ ]
14033
+ },
14034
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14035
+ exploreStyles.platformButtonText,
14036
+ sessionPlatform === key && exploreStyles.platformButtonTextActive
14037
+ ] }, label)
14038
+ )))), /* @__PURE__ */ React2.createElement(
14039
+ TouchableOpacity,
14040
+ {
14041
+ onPress: handleStartSession,
14042
+ disabled: startingSession,
14043
+ style: [exploreStyles.startButton, startingSession && { opacity: 0.5 }]
14044
+ },
14045
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.startButtonText }, startingSession ? "Starting..." : "\u25B6 Start Session")
14046
+ ))
14047
+ ) : showEndConfirm ? (
14048
+ /* End Session Confirmation */
14049
+ /* @__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(
14050
+ TextInput,
14051
+ {
14052
+ style: [exploreStyles.input, { height: 80, textAlignVertical: "top" }],
14053
+ value: sessionNotes,
14054
+ onChangeText: setSessionNotes,
14055
+ placeholder: "Any overall observations from this session...",
14056
+ placeholderTextColor: "#71717a",
14057
+ multiline: true
14058
+ }
14059
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.buttonRow }, /* @__PURE__ */ React2.createElement(
14060
+ TouchableOpacity,
14061
+ {
14062
+ onPress: () => setShowEndConfirm(false),
14063
+ style: exploreStyles.cancelButton
14064
+ },
14065
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.cancelButtonText }, "Cancel")
14066
+ ), /* @__PURE__ */ React2.createElement(
14067
+ TouchableOpacity,
14068
+ {
14069
+ onPress: handleEndSession,
14070
+ disabled: endingSession,
14071
+ style: [exploreStyles.endButton, endingSession && { opacity: 0.5 }]
14072
+ },
14073
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.endButtonText }, endingSession ? "Ending..." : "End Session")
14074
+ )))
14075
+ ) : showAddFinding ? (
14076
+ /* Add Finding Form */
14077
+ /* @__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 }, [
14078
+ { type: "bug", label: "\u{1F41B} Bug" },
14079
+ { type: "concern", label: "\u26A0\uFE0F Concern" },
14080
+ { type: "suggestion", label: "\u{1F4A1} Idea" },
14081
+ { type: "question", label: "\u2753 Q" }
14082
+ ].map(({ type, label }) => /* @__PURE__ */ React2.createElement(
14083
+ TouchableOpacity,
14084
+ {
14085
+ key: type,
14086
+ onPress: () => setFindingType(type),
14087
+ style: [
14088
+ exploreStyles.findingTypeButton,
14089
+ findingType === type && exploreStyles.findingTypeButtonActive
14090
+ ]
14091
+ },
14092
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14093
+ exploreStyles.findingTypeButtonText,
14094
+ findingType === type && exploreStyles.findingTypeButtonTextActive
14095
+ ] }, label)
14096
+ ))), 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(
14097
+ TouchableOpacity,
14098
+ {
14099
+ key: sev,
14100
+ onPress: () => setFindingSeverity(sev),
14101
+ style: [
14102
+ exploreStyles.severityButton,
14103
+ findingSeverity === sev && (sev === "critical" ? exploreStyles.severityCritical : sev === "high" ? exploreStyles.severityHigh : sev === "medium" ? exploreStyles.severityMedium : exploreStyles.severityLow)
14104
+ ]
14105
+ },
14106
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14107
+ exploreStyles.severityButtonText,
14108
+ findingSeverity === sev && exploreStyles.severityButtonTextActive
14109
+ ] }, sev)
14110
+ )))), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Title *"), /* @__PURE__ */ React2.createElement(
14111
+ TextInput,
14112
+ {
14113
+ style: exploreStyles.input,
14114
+ value: findingTitle,
14115
+ onChangeText: setFindingTitle,
14116
+ placeholder: "Brief description of what you found",
14117
+ placeholderTextColor: "#71717a"
14118
+ }
14119
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Details (optional)"), /* @__PURE__ */ React2.createElement(
14120
+ TextInput,
14121
+ {
14122
+ style: [exploreStyles.input, { height: 60, textAlignVertical: "top" }],
14123
+ value: findingDescription,
14124
+ onChangeText: setFindingDescription,
14125
+ placeholder: "Steps to reproduce, expected behavior, etc.",
14126
+ placeholderTextColor: "#71717a",
14127
+ multiline: true
14128
+ }
14129
+ )), /* @__PURE__ */ React2.createElement(
14130
+ TouchableOpacity,
14131
+ {
14132
+ onPress: handleAddFinding,
14133
+ disabled: addingFinding || !findingTitle.trim(),
14134
+ style: [exploreStyles.addFindingButton, (addingFinding || !findingTitle.trim()) && { opacity: 0.5 }]
14135
+ },
14136
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.addFindingButtonText }, addingFinding ? "Adding..." : "Add Finding")
14137
+ ))
14138
+ ) : (
14139
+ /* Active Session View */
14140
+ /* @__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(
14141
+ TouchableOpacity,
14142
+ {
14143
+ onPress: () => setShowAddFinding(true),
14144
+ style: exploreStyles.addButton
14145
+ },
14146
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.addButtonText }, "+ Add Finding")
14147
+ ), /* @__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(
14148
+ View,
14149
+ {
14150
+ key: finding.id,
14151
+ style: [
14152
+ exploreStyles.findingCard,
14153
+ finding.type === "bug" ? exploreStyles.findingCardBug : finding.type === "concern" ? exploreStyles.findingCardConcern : finding.type === "suggestion" ? exploreStyles.findingCardSuggestion : exploreStyles.findingCardQuestion
14154
+ ]
14155
+ },
14156
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingCardIcon }, finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753"),
14157
+ /* @__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: [
14158
+ exploreStyles.findingCardSeverity,
14159
+ finding.severity === "critical" ? { color: "#f87171" } : finding.severity === "high" ? { color: "#fb923c" } : finding.severity === "medium" ? { color: "#facc15" } : { color: "#a1a1aa" }
14160
+ ] }, finding.severity))
14161
+ )))), /* @__PURE__ */ React2.createElement(
14162
+ TouchableOpacity,
14163
+ {
14164
+ onPress: () => setShowEndConfirm(true),
14165
+ style: exploreStyles.endSessionButton
14166
+ },
14167
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.endSessionButtonText }, "End Session")
14168
+ ))
13560
14169
  )), 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
14170
  { type: "bug", label: "\u{1F41B} Bug" },
13562
14171
  { type: "feedback", label: "\u{1F4A1} Feedback" },
@@ -13721,9 +14330,64 @@ function BugBearButton({
13721
14330
  ))
13722
14331
  ) : (
13723
14332
  /* 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"))))
14333
+ /* @__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 }, pendingCount, " pending \xB7 ", inProgressCount, " in progress"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))))
13725
14334
  ))
13726
14335
  )
14336
+ ), /* @__PURE__ */ React2.createElement(
14337
+ Modal,
14338
+ {
14339
+ visible: showSkipModal,
14340
+ transparent: true,
14341
+ animationType: "fade",
14342
+ onRequestClose: () => setShowSkipModal(false)
14343
+ },
14344
+ /* @__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 }, [
14345
+ { value: "blocked", label: "\u{1F6AB} Blocked", desc: "Something is preventing testing" },
14346
+ { value: "not_ready", label: "\u{1F6A7} Not Ready", desc: "Feature not yet implemented" },
14347
+ { value: "dependency", label: "\u{1F517} Dependency", desc: "Waiting on another test/feature" },
14348
+ { value: "other", label: "\u{1F4DD} Other", desc: "Different reason" }
14349
+ ].map((option) => /* @__PURE__ */ React2.createElement(
14350
+ TouchableOpacity,
14351
+ {
14352
+ key: option.value,
14353
+ style: [
14354
+ styles.skipReasonOption,
14355
+ selectedSkipReason === option.value && styles.skipReasonOptionSelected
14356
+ ],
14357
+ onPress: () => setSelectedSkipReason(option.value)
14358
+ },
14359
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipReasonLabel }, option.label),
14360
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipReasonDesc }, option.desc)
14361
+ ))), /* @__PURE__ */ React2.createElement(
14362
+ TextInput,
14363
+ {
14364
+ style: styles.skipNotesInput,
14365
+ value: skipNotes,
14366
+ onChangeText: setSkipNotes,
14367
+ placeholder: "Add notes (optional)...",
14368
+ placeholderTextColor: "#71717a",
14369
+ multiline: true,
14370
+ numberOfLines: 2
14371
+ }
14372
+ ), /* @__PURE__ */ React2.createElement(View, { style: styles.skipModalActions }, /* @__PURE__ */ React2.createElement(
14373
+ TouchableOpacity,
14374
+ {
14375
+ style: styles.skipModalCancel,
14376
+ onPress: () => setShowSkipModal(false)
14377
+ },
14378
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalCancelText }, "Cancel")
14379
+ ), /* @__PURE__ */ React2.createElement(
14380
+ TouchableOpacity,
14381
+ {
14382
+ style: [
14383
+ styles.skipModalConfirm,
14384
+ !selectedSkipReason && styles.skipModalConfirmDisabled
14385
+ ],
14386
+ onPress: handleSkip,
14387
+ disabled: !selectedSkipReason || skipping
14388
+ },
14389
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalConfirmText }, skipping ? "Skipping..." : "Skip Test")
14390
+ ))))
13727
14391
  ));
13728
14392
  }
13729
14393
  var styles = StyleSheet.create({
@@ -14426,6 +15090,13 @@ var styles = StyleSheet.create({
14426
15090
  flexDirection: "row",
14427
15091
  alignItems: "center"
14428
15092
  },
15093
+ sessionDot: {
15094
+ width: 8,
15095
+ height: 8,
15096
+ borderRadius: 4,
15097
+ backgroundColor: "#22c55e",
15098
+ marginLeft: 4
15099
+ },
14429
15100
  tabBadge: {
14430
15101
  backgroundColor: "#EF4444",
14431
15102
  borderRadius: 8,
@@ -14980,6 +15651,665 @@ var styles = StyleSheet.create({
14980
15651
  fontSize: 14,
14981
15652
  fontWeight: "500",
14982
15653
  color: "#3B82F6"
15654
+ },
15655
+ // Folder grouping styles
15656
+ folderContainer: {
15657
+ marginBottom: 12
15658
+ },
15659
+ folderHeader: {
15660
+ flexDirection: "row",
15661
+ justifyContent: "space-between",
15662
+ alignItems: "center",
15663
+ backgroundColor: "#27272a",
15664
+ padding: 12,
15665
+ borderRadius: 8,
15666
+ marginBottom: 4
15667
+ },
15668
+ folderHeaderLeft: {
15669
+ flexDirection: "row",
15670
+ alignItems: "center",
15671
+ flex: 1
15672
+ },
15673
+ folderIcon: {
15674
+ fontSize: 16,
15675
+ marginRight: 8
15676
+ },
15677
+ folderName: {
15678
+ fontSize: 14,
15679
+ fontWeight: "600",
15680
+ color: "#fafafa"
15681
+ },
15682
+ folderStats: {
15683
+ flexDirection: "row",
15684
+ alignItems: "center"
15685
+ },
15686
+ folderProgress: {
15687
+ fontSize: 12,
15688
+ color: "#71717a",
15689
+ marginRight: 8
15690
+ },
15691
+ folderChevron: {
15692
+ fontSize: 10,
15693
+ color: "#71717a"
15694
+ },
15695
+ folderProgressBar: {
15696
+ height: 3,
15697
+ backgroundColor: "#3f3f46",
15698
+ borderRadius: 2,
15699
+ marginBottom: 8,
15700
+ marginHorizontal: 4
15701
+ },
15702
+ folderProgressFill: {
15703
+ height: "100%",
15704
+ backgroundColor: "#22c55e",
15705
+ borderRadius: 2
15706
+ },
15707
+ listItemInFolder: {
15708
+ marginLeft: 12,
15709
+ borderLeftWidth: 2,
15710
+ borderLeftColor: "#3f3f46",
15711
+ paddingLeft: 12
15712
+ },
15713
+ listItemKeyWithStatus: {
15714
+ flexDirection: "row",
15715
+ alignItems: "center",
15716
+ flex: 1
15717
+ },
15718
+ statusBadge: {
15719
+ flexDirection: "row",
15720
+ alignItems: "center",
15721
+ paddingHorizontal: 6,
15722
+ paddingVertical: 2,
15723
+ borderRadius: 4,
15724
+ marginLeft: 8
15725
+ },
15726
+ statusBadgeIcon: {
15727
+ fontSize: 10,
15728
+ marginRight: 4
15729
+ },
15730
+ statusBadgeText: {
15731
+ fontSize: 10,
15732
+ fontWeight: "600"
15733
+ },
15734
+ // Skip button styles
15735
+ skipButton: {
15736
+ flex: 1,
15737
+ backgroundColor: "#eab308",
15738
+ paddingVertical: 14,
15739
+ borderRadius: 12,
15740
+ alignItems: "center",
15741
+ marginHorizontal: 4
15742
+ },
15743
+ skipButtonText: {
15744
+ fontSize: 15,
15745
+ fontWeight: "600",
15746
+ color: "#18181b"
15747
+ },
15748
+ // Skip modal styles
15749
+ skipModalOverlay: {
15750
+ flex: 1,
15751
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
15752
+ justifyContent: "center",
15753
+ alignItems: "center",
15754
+ padding: 20
15755
+ },
15756
+ skipModalContent: {
15757
+ backgroundColor: "#18181b",
15758
+ borderRadius: 16,
15759
+ padding: 20,
15760
+ width: "100%",
15761
+ maxWidth: 340,
15762
+ borderWidth: 1,
15763
+ borderColor: "#3f3f46"
15764
+ },
15765
+ skipModalTitle: {
15766
+ fontSize: 18,
15767
+ fontWeight: "600",
15768
+ color: "#fafafa",
15769
+ marginBottom: 4
15770
+ },
15771
+ skipModalSubtitle: {
15772
+ fontSize: 14,
15773
+ color: "#71717a",
15774
+ marginBottom: 16
15775
+ },
15776
+ skipReasonOptions: {
15777
+ marginBottom: 16
15778
+ },
15779
+ skipReasonOption: {
15780
+ backgroundColor: "#27272a",
15781
+ padding: 12,
15782
+ borderRadius: 8,
15783
+ marginBottom: 8,
15784
+ borderWidth: 2,
15785
+ borderColor: "transparent"
15786
+ },
15787
+ skipReasonOptionSelected: {
15788
+ borderColor: "#eab308",
15789
+ backgroundColor: "#422006"
15790
+ },
15791
+ skipReasonLabel: {
15792
+ fontSize: 14,
15793
+ fontWeight: "600",
15794
+ color: "#fafafa",
15795
+ marginBottom: 2
15796
+ },
15797
+ skipReasonDesc: {
15798
+ fontSize: 12,
15799
+ color: "#71717a"
15800
+ },
15801
+ skipNotesInput: {
15802
+ backgroundColor: "#27272a",
15803
+ borderWidth: 1,
15804
+ borderColor: "#3f3f46",
15805
+ borderRadius: 8,
15806
+ padding: 12,
15807
+ fontSize: 14,
15808
+ color: "#fafafa",
15809
+ minHeight: 60,
15810
+ textAlignVertical: "top",
15811
+ marginBottom: 16
15812
+ },
15813
+ skipModalActions: {
15814
+ flexDirection: "row",
15815
+ gap: 8
15816
+ },
15817
+ skipModalCancel: {
15818
+ flex: 1,
15819
+ backgroundColor: "#3f3f46",
15820
+ paddingVertical: 12,
15821
+ borderRadius: 8,
15822
+ alignItems: "center"
15823
+ },
15824
+ skipModalCancelText: {
15825
+ fontSize: 14,
15826
+ fontWeight: "600",
15827
+ color: "#e4e4e7"
15828
+ },
15829
+ skipModalConfirm: {
15830
+ flex: 1,
15831
+ backgroundColor: "#eab308",
15832
+ paddingVertical: 12,
15833
+ borderRadius: 8,
15834
+ alignItems: "center"
15835
+ },
15836
+ skipModalConfirmDisabled: {
15837
+ backgroundColor: "#713f12"
15838
+ },
15839
+ skipModalConfirmText: {
15840
+ fontSize: 14,
15841
+ fontWeight: "600",
15842
+ color: "#18181b"
15843
+ },
15844
+ // Detail progress bar styles
15845
+ detailProgressContainer: {
15846
+ backgroundColor: "#27272a",
15847
+ padding: 12,
15848
+ borderRadius: 8,
15849
+ marginTop: 16,
15850
+ marginBottom: 8
15851
+ },
15852
+ detailProgressText: {
15853
+ fontSize: 12,
15854
+ color: "#a1a1aa",
15855
+ marginBottom: 8
15856
+ },
15857
+ detailProgressBar: {
15858
+ height: 4,
15859
+ backgroundColor: "#3f3f46",
15860
+ borderRadius: 2
15861
+ },
15862
+ detailProgressFill: {
15863
+ height: "100%",
15864
+ backgroundColor: "#22c55e",
15865
+ borderRadius: 2
15866
+ }
15867
+ });
15868
+ var exploreStyles = StyleSheet.create({
15869
+ formGroup: {
15870
+ marginBottom: 12
15871
+ },
15872
+ label: {
15873
+ fontSize: 12,
15874
+ fontWeight: "500",
15875
+ color: "#d4d4d8",
15876
+ marginBottom: 6
15877
+ },
15878
+ input: {
15879
+ backgroundColor: "#27272a",
15880
+ borderRadius: 8,
15881
+ paddingHorizontal: 12,
15882
+ paddingVertical: 10,
15883
+ fontSize: 14,
15884
+ color: "#fafafa",
15885
+ borderWidth: 1,
15886
+ borderColor: "#3f3f46"
15887
+ },
15888
+ platformRow: {
15889
+ flexDirection: "row",
15890
+ gap: 8
15891
+ },
15892
+ platformButton: {
15893
+ flex: 1,
15894
+ paddingVertical: 10,
15895
+ paddingHorizontal: 8,
15896
+ borderRadius: 8,
15897
+ backgroundColor: "#27272a",
15898
+ borderWidth: 2,
15899
+ borderColor: "transparent",
15900
+ alignItems: "center"
15901
+ },
15902
+ platformButtonActive: {
15903
+ backgroundColor: "#172554",
15904
+ borderColor: "#3B82F6"
15905
+ },
15906
+ platformButtonText: {
15907
+ fontSize: 12,
15908
+ fontWeight: "500",
15909
+ color: "#a1a1aa"
15910
+ },
15911
+ platformButtonTextActive: {
15912
+ color: "#93c5fd"
15913
+ },
15914
+ startButton: {
15915
+ backgroundColor: "#16a34a",
15916
+ borderRadius: 8,
15917
+ paddingVertical: 14,
15918
+ alignItems: "center",
15919
+ marginTop: 4
15920
+ },
15921
+ startButtonText: {
15922
+ color: "#fff",
15923
+ fontSize: 14,
15924
+ fontWeight: "600"
15925
+ },
15926
+ buttonRow: {
15927
+ flexDirection: "row",
15928
+ gap: 8
15929
+ },
15930
+ cancelButton: {
15931
+ flex: 1,
15932
+ backgroundColor: "#3f3f46",
15933
+ borderRadius: 8,
15934
+ paddingVertical: 10,
15935
+ alignItems: "center"
15936
+ },
15937
+ cancelButtonText: {
15938
+ color: "#d4d4d8",
15939
+ fontSize: 14,
15940
+ fontWeight: "500"
15941
+ },
15942
+ endButton: {
15943
+ flex: 1,
15944
+ backgroundColor: "#dc2626",
15945
+ borderRadius: 8,
15946
+ paddingVertical: 10,
15947
+ alignItems: "center"
15948
+ },
15949
+ endButtonText: {
15950
+ color: "#fff",
15951
+ fontSize: 14,
15952
+ fontWeight: "500"
15953
+ },
15954
+ findingHeader: {
15955
+ flexDirection: "row",
15956
+ justifyContent: "space-between",
15957
+ alignItems: "center",
15958
+ marginBottom: 12
15959
+ },
15960
+ findingHeaderTitle: {
15961
+ fontSize: 14,
15962
+ fontWeight: "600",
15963
+ color: "#fafafa"
15964
+ },
15965
+ findingHeaderClose: {
15966
+ fontSize: 16,
15967
+ color: "#71717a"
15968
+ },
15969
+ findingTypeRow: {
15970
+ flexDirection: "row",
15971
+ gap: 4,
15972
+ marginBottom: 12
15973
+ },
15974
+ findingTypeButton: {
15975
+ flex: 1,
15976
+ paddingVertical: 8,
15977
+ paddingHorizontal: 4,
15978
+ borderRadius: 6,
15979
+ backgroundColor: "#3f3f46",
15980
+ alignItems: "center"
15981
+ },
15982
+ findingTypeButtonActive: {
15983
+ backgroundColor: "#1e3a5f",
15984
+ borderWidth: 2,
15985
+ borderColor: "#3B82F6"
15986
+ },
15987
+ findingTypeButtonText: {
15988
+ fontSize: 11,
15989
+ fontWeight: "500",
15990
+ color: "#a1a1aa"
15991
+ },
15992
+ findingTypeButtonTextActive: {
15993
+ color: "#93c5fd"
15994
+ },
15995
+ severityRow: {
15996
+ flexDirection: "row",
15997
+ gap: 4
15998
+ },
15999
+ severityButton: {
16000
+ flex: 1,
16001
+ paddingVertical: 6,
16002
+ borderRadius: 6,
16003
+ backgroundColor: "#3f3f46",
16004
+ alignItems: "center"
16005
+ },
16006
+ severityCritical: {
16007
+ backgroundColor: "#dc2626"
16008
+ },
16009
+ severityHigh: {
16010
+ backgroundColor: "#f97316"
16011
+ },
16012
+ severityMedium: {
16013
+ backgroundColor: "#eab308"
16014
+ },
16015
+ severityLow: {
16016
+ backgroundColor: "#3f3f46",
16017
+ borderWidth: 1,
16018
+ borderColor: "#71717a"
16019
+ },
16020
+ severityButtonText: {
16021
+ fontSize: 11,
16022
+ fontWeight: "500",
16023
+ color: "#a1a1aa",
16024
+ textTransform: "capitalize"
16025
+ },
16026
+ severityButtonTextActive: {
16027
+ color: "#fff"
16028
+ },
16029
+ addFindingButton: {
16030
+ backgroundColor: "#3B82F6",
16031
+ borderRadius: 8,
16032
+ paddingVertical: 10,
16033
+ alignItems: "center"
16034
+ },
16035
+ addFindingButtonText: {
16036
+ color: "#fff",
16037
+ fontSize: 14,
16038
+ fontWeight: "500"
16039
+ },
16040
+ sessionBanner: {
16041
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16042
+ borderRadius: 12,
16043
+ padding: 12,
16044
+ marginBottom: 12,
16045
+ borderWidth: 1,
16046
+ borderColor: "#166534"
16047
+ },
16048
+ sessionBannerRow: {
16049
+ flexDirection: "row",
16050
+ justifyContent: "space-between",
16051
+ alignItems: "center"
16052
+ },
16053
+ sessionBannerLeft: {
16054
+ flexDirection: "row",
16055
+ alignItems: "center",
16056
+ gap: 8
16057
+ },
16058
+ sessionDotLarge: {
16059
+ width: 8,
16060
+ height: 8,
16061
+ borderRadius: 4,
16062
+ backgroundColor: "#22c55e"
16063
+ },
16064
+ sessionBannerLabel: {
16065
+ fontSize: 14,
16066
+ fontWeight: "500",
16067
+ color: "#86efac"
16068
+ },
16069
+ sessionTimer: {
16070
+ fontSize: 20,
16071
+ fontWeight: "600",
16072
+ color: "#4ade80",
16073
+ fontVariant: ["tabular-nums"]
16074
+ },
16075
+ sessionFocus: {
16076
+ fontSize: 12,
16077
+ color: "#4ade80",
16078
+ marginTop: 4
16079
+ },
16080
+ addButton: {
16081
+ backgroundColor: "#3B82F6",
16082
+ borderRadius: 8,
16083
+ paddingVertical: 14,
16084
+ alignItems: "center",
16085
+ marginBottom: 12
16086
+ },
16087
+ addButtonText: {
16088
+ color: "#fff",
16089
+ fontSize: 14,
16090
+ fontWeight: "600"
16091
+ },
16092
+ findingsSection: {
16093
+ marginBottom: 12
16094
+ },
16095
+ findingsLabel: {
16096
+ fontSize: 12,
16097
+ fontWeight: "500",
16098
+ color: "#71717a",
16099
+ marginBottom: 8
16100
+ },
16101
+ findingsEmpty: {
16102
+ backgroundColor: "#27272a",
16103
+ borderRadius: 8,
16104
+ paddingVertical: 16,
16105
+ alignItems: "center"
16106
+ },
16107
+ findingsEmptyText: {
16108
+ fontSize: 12,
16109
+ color: "#71717a"
16110
+ },
16111
+ findingCard: {
16112
+ flexDirection: "row",
16113
+ alignItems: "flex-start",
16114
+ padding: 8,
16115
+ borderRadius: 8,
16116
+ marginBottom: 6,
16117
+ borderWidth: 1,
16118
+ gap: 8
16119
+ },
16120
+ findingCardBug: {
16121
+ backgroundColor: "rgba(220, 38, 38, 0.1)",
16122
+ borderColor: "#991b1b"
16123
+ },
16124
+ findingCardConcern: {
16125
+ backgroundColor: "rgba(249, 115, 22, 0.1)",
16126
+ borderColor: "#9a3412"
16127
+ },
16128
+ findingCardSuggestion: {
16129
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16130
+ borderColor: "#1e40af"
16131
+ },
16132
+ findingCardQuestion: {
16133
+ backgroundColor: "rgba(139, 92, 246, 0.1)",
16134
+ borderColor: "#5b21b6"
16135
+ },
16136
+ findingCardIcon: {
16137
+ fontSize: 14
16138
+ },
16139
+ findingCardTitle: {
16140
+ fontSize: 12,
16141
+ fontWeight: "500",
16142
+ color: "#fafafa"
16143
+ },
16144
+ findingCardSeverity: {
16145
+ fontSize: 10,
16146
+ fontWeight: "500",
16147
+ marginTop: 2,
16148
+ textTransform: "capitalize"
16149
+ },
16150
+ endSessionButton: {
16151
+ backgroundColor: "#3f3f46",
16152
+ borderRadius: 8,
16153
+ paddingVertical: 10,
16154
+ alignItems: "center"
16155
+ },
16156
+ endSessionButtonText: {
16157
+ color: "#d4d4d8",
16158
+ fontSize: 14,
16159
+ fontWeight: "500"
16160
+ }
16161
+ });
16162
+ var feedbackStyles = StyleSheet.create({
16163
+ container: {
16164
+ padding: 4
16165
+ },
16166
+ statusText: {
16167
+ fontSize: 16,
16168
+ fontWeight: "600",
16169
+ marginTop: 4
16170
+ },
16171
+ infoBox: {
16172
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16173
+ borderRadius: 8,
16174
+ padding: 12,
16175
+ marginBottom: 16,
16176
+ borderWidth: 1,
16177
+ borderColor: "#1e3a5f"
16178
+ },
16179
+ infoTitle: {
16180
+ fontSize: 14,
16181
+ fontWeight: "500",
16182
+ color: "#93c5fd",
16183
+ marginBottom: 4
16184
+ },
16185
+ infoSubtitle: {
16186
+ fontSize: 12,
16187
+ color: "#60a5fa"
16188
+ },
16189
+ ratingSection: {
16190
+ alignItems: "center",
16191
+ marginBottom: 16
16192
+ },
16193
+ ratingLabel: {
16194
+ fontSize: 12,
16195
+ fontWeight: "500",
16196
+ color: "#a1a1aa",
16197
+ marginBottom: 8
16198
+ },
16199
+ starsRow: {
16200
+ flexDirection: "row",
16201
+ gap: 4
16202
+ },
16203
+ star: {
16204
+ fontSize: 28
16205
+ },
16206
+ starActive: {
16207
+ color: "#facc15"
16208
+ },
16209
+ starInactive: {
16210
+ color: "#3f3f46"
16211
+ },
16212
+ ratingDesc: {
16213
+ fontSize: 12,
16214
+ color: "#71717a",
16215
+ marginTop: 4
16216
+ },
16217
+ flagsSection: {
16218
+ marginBottom: 12
16219
+ },
16220
+ flagsGrid: {
16221
+ flexDirection: "row",
16222
+ flexWrap: "wrap",
16223
+ gap: 8
16224
+ },
16225
+ flagButton: {
16226
+ paddingHorizontal: 10,
16227
+ paddingVertical: 6,
16228
+ borderRadius: 6,
16229
+ backgroundColor: "#27272a",
16230
+ borderWidth: 1,
16231
+ borderColor: "#3f3f46"
16232
+ },
16233
+ flagButtonActive: {
16234
+ backgroundColor: "#1e3a5f",
16235
+ borderColor: "#3B82F6"
16236
+ },
16237
+ flagButtonText: {
16238
+ fontSize: 12,
16239
+ fontWeight: "500",
16240
+ color: "#a1a1aa"
16241
+ },
16242
+ flagButtonTextActive: {
16243
+ color: "#93c5fd"
16244
+ },
16245
+ noteInput: {
16246
+ backgroundColor: "#27272a",
16247
+ borderRadius: 8,
16248
+ paddingHorizontal: 12,
16249
+ paddingVertical: 10,
16250
+ fontSize: 14,
16251
+ color: "#fafafa",
16252
+ borderWidth: 1,
16253
+ borderColor: "#3f3f46",
16254
+ minHeight: 60
16255
+ },
16256
+ buttonRow: {
16257
+ flexDirection: "row",
16258
+ gap: 8
16259
+ },
16260
+ skipButton: {
16261
+ flex: 1,
16262
+ paddingVertical: 10,
16263
+ backgroundColor: "#3f3f46",
16264
+ borderRadius: 8,
16265
+ alignItems: "center"
16266
+ },
16267
+ skipButtonText: {
16268
+ color: "#a1a1aa",
16269
+ fontSize: 14,
16270
+ fontWeight: "500"
16271
+ },
16272
+ submitButton: {
16273
+ flex: 1,
16274
+ paddingVertical: 10,
16275
+ backgroundColor: "#3B82F6",
16276
+ borderRadius: 8,
16277
+ alignItems: "center"
16278
+ },
16279
+ submitButtonText: {
16280
+ color: "#fff",
16281
+ fontSize: 14,
16282
+ fontWeight: "500"
16283
+ }
16284
+ });
16285
+ var timerStyles = StyleSheet.create({
16286
+ container: {
16287
+ flexDirection: "row",
16288
+ alignItems: "center",
16289
+ gap: 6,
16290
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16291
+ paddingHorizontal: 8,
16292
+ paddingVertical: 4,
16293
+ borderRadius: 6,
16294
+ marginBottom: 8,
16295
+ alignSelf: "flex-start"
16296
+ },
16297
+ dot: {
16298
+ width: 6,
16299
+ height: 6,
16300
+ borderRadius: 3,
16301
+ backgroundColor: "#22c55e"
16302
+ },
16303
+ label: {
16304
+ fontSize: 12,
16305
+ fontWeight: "500",
16306
+ color: "#4ade80"
16307
+ },
16308
+ time: {
16309
+ fontSize: 12,
16310
+ fontWeight: "600",
16311
+ color: "#4ade80",
16312
+ fontVariant: ["tabular-nums"]
14983
16313
  }
14984
16314
  });
14985
16315
  export {