@bbearai/react-native 0.1.8 → 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.js CHANGED
@@ -11449,7 +11449,16 @@ var BugBearClient = class {
11449
11449
  */
11450
11450
  async submitReport(report) {
11451
11451
  try {
11452
+ const validationError = this.validateReport(report);
11453
+ if (validationError) {
11454
+ return { success: false, error: validationError };
11455
+ }
11452
11456
  const userInfo = await this.getCurrentUserInfo();
11457
+ const rateLimitId = userInfo?.email || this.config.projectId;
11458
+ const rateLimit = await this.checkRateLimit(rateLimitId, "report_submit");
11459
+ if (!rateLimit.allowed) {
11460
+ return { success: false, error: rateLimit.error };
11461
+ }
11453
11462
  if (!userInfo) {
11454
11463
  console.error("BugBear: No user info available, cannot submit report");
11455
11464
  return { success: false, error: "User not authenticated" };
@@ -11500,6 +11509,10 @@ var BugBearClient = class {
11500
11509
  const { data, error } = await this.supabase.from("test_assignments").select(`
11501
11510
  id,
11502
11511
  status,
11512
+ started_at,
11513
+ skip_reason,
11514
+ is_verification,
11515
+ original_report_id,
11503
11516
  test_case:test_cases(
11504
11517
  id,
11505
11518
  title,
@@ -11517,6 +11530,12 @@ var BugBearClient = class {
11517
11530
  test_template,
11518
11531
  rubric_mode,
11519
11532
  description
11533
+ ),
11534
+ group:test_groups(
11535
+ id,
11536
+ name,
11537
+ description,
11538
+ sort_order
11520
11539
  )
11521
11540
  )
11522
11541
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true });
@@ -11527,6 +11546,10 @@ var BugBearClient = class {
11527
11546
  return (data || []).map((item) => ({
11528
11547
  id: item.id,
11529
11548
  status: item.status,
11549
+ startedAt: item.started_at,
11550
+ skipReason: item.skip_reason,
11551
+ isVerification: item.is_verification || false,
11552
+ originalReportId: item.original_report_id,
11530
11553
  testCase: {
11531
11554
  id: item.test_case.id,
11532
11555
  title: item.test_case.title,
@@ -11544,6 +11567,12 @@ var BugBearClient = class {
11544
11567
  testTemplate: item.test_case.track.test_template,
11545
11568
  rubricMode: item.test_case.track.rubric_mode || "pass_fail",
11546
11569
  description: item.test_case.track.description
11570
+ } : void 0,
11571
+ group: item.test_case.group ? {
11572
+ id: item.test_case.group.id,
11573
+ name: item.test_case.group.name,
11574
+ description: item.test_case.group.description,
11575
+ sortOrder: item.test_case.group.sort_order
11547
11576
  } : void 0
11548
11577
  }
11549
11578
  }));
@@ -11552,47 +11581,456 @@ var BugBearClient = class {
11552
11581
  return [];
11553
11582
  }
11554
11583
  }
11584
+ /**
11585
+ * Get assignment by ID with time tracking fields
11586
+ */
11587
+ async getAssignment(assignmentId) {
11588
+ try {
11589
+ const { data, error } = await this.supabase.from("test_assignments").select(`
11590
+ id,
11591
+ status,
11592
+ started_at,
11593
+ completed_at,
11594
+ duration_seconds,
11595
+ test_case:test_cases(
11596
+ id,
11597
+ title,
11598
+ test_key,
11599
+ description,
11600
+ steps,
11601
+ expected_result,
11602
+ priority,
11603
+ target_route,
11604
+ track:qa_tracks(
11605
+ id,
11606
+ name,
11607
+ icon,
11608
+ color,
11609
+ test_template,
11610
+ rubric_mode,
11611
+ description
11612
+ )
11613
+ )
11614
+ `).eq("id", assignmentId).single();
11615
+ if (error || !data) return null;
11616
+ const testCase = data.test_case;
11617
+ if (!testCase) {
11618
+ console.error("BugBear: Assignment returned without test_case");
11619
+ return null;
11620
+ }
11621
+ const track = testCase.track;
11622
+ return {
11623
+ id: data.id,
11624
+ status: data.status,
11625
+ startedAt: data.started_at,
11626
+ durationSeconds: data.duration_seconds,
11627
+ testCase: {
11628
+ id: testCase.id,
11629
+ title: testCase.title,
11630
+ testKey: testCase.test_key,
11631
+ description: testCase.description,
11632
+ steps: testCase.steps,
11633
+ expectedResult: testCase.expected_result,
11634
+ priority: testCase.priority,
11635
+ targetRoute: testCase.target_route,
11636
+ track: track ? {
11637
+ id: track.id,
11638
+ name: track.name,
11639
+ icon: track.icon,
11640
+ color: track.color,
11641
+ testTemplate: track.test_template,
11642
+ rubricMode: track.rubric_mode || "pass_fail",
11643
+ description: track.description
11644
+ } : void 0
11645
+ }
11646
+ };
11647
+ } catch (err) {
11648
+ console.error("BugBear: Error fetching assignment", err);
11649
+ return null;
11650
+ }
11651
+ }
11652
+ /**
11653
+ * Update assignment status with automatic time tracking
11654
+ * - Sets started_at when status changes to 'in_progress'
11655
+ * - Calculates duration_seconds when status changes to 'passed'/'failed'/'blocked'
11656
+ * - Optionally include feedback when completing a test
11657
+ */
11658
+ async updateAssignmentStatus(assignmentId, status, options) {
11659
+ try {
11660
+ const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at").eq("id", assignmentId).single();
11661
+ if (fetchError || !currentAssignment) {
11662
+ return { success: false, error: "Assignment not found" };
11663
+ }
11664
+ const updateData = { status };
11665
+ let durationSeconds;
11666
+ if (status === "in_progress" && currentAssignment.status !== "in_progress") {
11667
+ updateData.started_at = (/* @__PURE__ */ new Date()).toISOString();
11668
+ }
11669
+ if (["passed", "failed", "blocked"].includes(status)) {
11670
+ updateData.completed_at = (/* @__PURE__ */ new Date()).toISOString();
11671
+ if (currentAssignment.started_at) {
11672
+ const startedAt = new Date(currentAssignment.started_at);
11673
+ const completedAt = /* @__PURE__ */ new Date();
11674
+ durationSeconds = Math.round((completedAt.getTime() - startedAt.getTime()) / 1e3);
11675
+ updateData.duration_seconds = durationSeconds;
11676
+ }
11677
+ }
11678
+ if (options?.notes) {
11679
+ updateData.notes = options.notes;
11680
+ }
11681
+ if (options?.testResult) {
11682
+ updateData.test_result = options.testResult;
11683
+ }
11684
+ const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11685
+ if (error) {
11686
+ console.error("BugBear: Failed to update assignment status", error);
11687
+ return { success: false, error: error.message };
11688
+ }
11689
+ if (options?.feedback && ["passed", "failed", "blocked"].includes(status)) {
11690
+ const { data: assignmentData, error: fetchError2 } = await this.supabase.from("test_assignments").select("test_case_id").eq("id", assignmentId).single();
11691
+ if (fetchError2) {
11692
+ console.error("BugBear: Failed to fetch assignment for feedback", fetchError2);
11693
+ } else if (assignmentData?.test_case_id) {
11694
+ const feedbackResult = await this.submitTestFeedback({
11695
+ testCaseId: assignmentData.test_case_id,
11696
+ assignmentId,
11697
+ feedback: options.feedback,
11698
+ timeToCompleteSeconds: durationSeconds
11699
+ });
11700
+ if (!feedbackResult.success) {
11701
+ console.error("BugBear: Failed to submit feedback", feedbackResult.error);
11702
+ }
11703
+ }
11704
+ }
11705
+ return { success: true, durationSeconds };
11706
+ } catch (err) {
11707
+ const message = err instanceof Error ? err.message : "Unknown error";
11708
+ console.error("BugBear: Error updating assignment status", err);
11709
+ return { success: false, error: message };
11710
+ }
11711
+ }
11712
+ /**
11713
+ * Skip a test assignment with a required reason
11714
+ * Marks the assignment as 'skipped' and records why it was skipped
11715
+ */
11716
+ async skipAssignment(assignmentId, reason, notes) {
11717
+ try {
11718
+ const updateData = {
11719
+ status: "skipped",
11720
+ skip_reason: reason,
11721
+ completed_at: (/* @__PURE__ */ new Date()).toISOString()
11722
+ };
11723
+ if (notes) {
11724
+ updateData.notes = notes;
11725
+ }
11726
+ const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11727
+ if (error) {
11728
+ console.error("BugBear: Failed to skip assignment", error);
11729
+ return { success: false, error: error.message };
11730
+ }
11731
+ return { success: true };
11732
+ } catch (err) {
11733
+ const message = err instanceof Error ? err.message : "Unknown error";
11734
+ console.error("BugBear: Error skipping assignment", err);
11735
+ return { success: false, error: message };
11736
+ }
11737
+ }
11738
+ /**
11739
+ * Submit feedback on a test case to help improve test quality
11740
+ * This empowers testers to shape better tests over time
11741
+ */
11742
+ async submitTestFeedback(options) {
11743
+ try {
11744
+ const testerInfo = await this.getTesterInfo();
11745
+ if (!testerInfo) {
11746
+ return { success: false, error: "Not authenticated as tester" };
11747
+ }
11748
+ const { testCaseId, assignmentId, feedback, timeToCompleteSeconds } = options;
11749
+ if (feedback.rating < 1 || feedback.rating > 5) {
11750
+ return { success: false, error: "Rating must be between 1 and 5" };
11751
+ }
11752
+ const { error: feedbackError } = await this.supabase.from("test_feedback").insert({
11753
+ project_id: this.config.projectId,
11754
+ test_case_id: testCaseId,
11755
+ assignment_id: assignmentId || null,
11756
+ tester_id: testerInfo.id,
11757
+ rating: feedback.rating,
11758
+ clarity_rating: feedback.clarityRating || null,
11759
+ steps_rating: feedback.stepsRating || null,
11760
+ relevance_rating: feedback.relevanceRating || null,
11761
+ feedback_note: feedback.feedbackNote?.trim() || null,
11762
+ suggested_improvement: feedback.suggestedImprovement?.trim() || null,
11763
+ is_outdated: feedback.isOutdated || false,
11764
+ needs_more_detail: feedback.needsMoreDetail || false,
11765
+ steps_unclear: feedback.stepsUnclear || false,
11766
+ expected_result_unclear: feedback.expectedResultUnclear || false,
11767
+ platform: this.getDeviceInfo().platform,
11768
+ time_to_complete_seconds: timeToCompleteSeconds || null
11769
+ });
11770
+ if (feedbackError) {
11771
+ console.error("BugBear: Failed to submit feedback", feedbackError);
11772
+ return { success: false, error: feedbackError.message };
11773
+ }
11774
+ if (assignmentId) {
11775
+ const { error: assignmentError } = await this.supabase.from("test_assignments").update({
11776
+ feedback_rating: feedback.rating,
11777
+ feedback_note: feedback.feedbackNote?.trim() || null,
11778
+ feedback_submitted_at: (/* @__PURE__ */ new Date()).toISOString()
11779
+ }).eq("id", assignmentId);
11780
+ if (assignmentError) {
11781
+ console.error("BugBear: Failed to update assignment feedback fields", assignmentError);
11782
+ }
11783
+ }
11784
+ return { success: true };
11785
+ } catch (err) {
11786
+ const message = err instanceof Error ? err.message : "Unknown error";
11787
+ console.error("BugBear: Error submitting feedback", err);
11788
+ return { success: false, error: message };
11789
+ }
11790
+ }
11791
+ /**
11792
+ * Get the currently active (in_progress) assignment for the tester
11793
+ */
11794
+ async getActiveAssignment() {
11795
+ try {
11796
+ const testerInfo = await this.getTesterInfo();
11797
+ if (!testerInfo) return null;
11798
+ const { data, error } = await this.supabase.from("test_assignments").select(`
11799
+ id,
11800
+ status,
11801
+ started_at,
11802
+ test_case:test_cases(
11803
+ id,
11804
+ title,
11805
+ test_key,
11806
+ description,
11807
+ steps,
11808
+ expected_result,
11809
+ priority,
11810
+ target_route,
11811
+ track:qa_tracks(
11812
+ id,
11813
+ name,
11814
+ icon,
11815
+ color,
11816
+ test_template,
11817
+ rubric_mode,
11818
+ description
11819
+ )
11820
+ )
11821
+ `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).eq("status", "in_progress").order("started_at", { ascending: false }).limit(1).maybeSingle();
11822
+ if (error || !data) return null;
11823
+ const testCase = data.test_case;
11824
+ if (!testCase) {
11825
+ console.error("BugBear: Active assignment returned without test_case");
11826
+ return null;
11827
+ }
11828
+ const track = testCase.track;
11829
+ return {
11830
+ id: data.id,
11831
+ status: data.status,
11832
+ startedAt: data.started_at,
11833
+ testCase: {
11834
+ id: testCase.id,
11835
+ title: testCase.title,
11836
+ testKey: testCase.test_key,
11837
+ description: testCase.description,
11838
+ steps: testCase.steps,
11839
+ expectedResult: testCase.expected_result,
11840
+ priority: testCase.priority,
11841
+ targetRoute: testCase.target_route,
11842
+ track: track ? {
11843
+ id: track.id,
11844
+ name: track.name,
11845
+ icon: track.icon,
11846
+ color: track.color,
11847
+ testTemplate: track.test_template,
11848
+ rubricMode: track.rubric_mode || "pass_fail",
11849
+ description: track.description
11850
+ } : void 0
11851
+ }
11852
+ };
11853
+ } catch (err) {
11854
+ console.error("BugBear: Error fetching active assignment", err);
11855
+ return null;
11856
+ }
11857
+ }
11555
11858
  /**
11556
11859
  * Get current tester info
11557
11860
  * Looks up tester by email from the host app's authenticated user
11861
+ * Checks both primary email AND additional_emails array
11862
+ * Uses parameterized RPC function to prevent SQL injection
11558
11863
  */
11559
11864
  async getTesterInfo() {
11560
11865
  try {
11561
11866
  const userInfo = await this.getCurrentUserInfo();
11562
- if (!userInfo) return null;
11563
- const { data, error } = await this.supabase.from("testers").select("*").eq("project_id", this.config.projectId).eq("email", userInfo.email).eq("status", "active").single();
11867
+ if (!userInfo?.email) return null;
11868
+ if (!this.isValidEmail(userInfo.email)) {
11869
+ console.warn("BugBear: Invalid email format");
11870
+ return null;
11871
+ }
11872
+ const { data, error } = await this.supabase.rpc("lookup_tester_by_email", {
11873
+ p_project_id: this.config.projectId,
11874
+ p_email: userInfo.email
11875
+ }).maybeSingle();
11564
11876
  if (error || !data) return null;
11877
+ const tester = data;
11565
11878
  return {
11566
- id: data.id,
11567
- name: data.name,
11568
- email: data.email,
11569
- additionalEmails: data.additional_emails || [],
11570
- avatarUrl: data.avatar_url || void 0,
11571
- platforms: data.platforms || [],
11572
- assignedTests: data.assigned_count || 0,
11573
- completedTests: data.completed_count || 0
11879
+ id: tester.id,
11880
+ name: tester.name,
11881
+ email: tester.email,
11882
+ additionalEmails: tester.additional_emails || [],
11883
+ avatarUrl: tester.avatar_url || void 0,
11884
+ platforms: tester.platforms || [],
11885
+ assignedTests: tester.assigned_count || 0,
11886
+ completedTests: tester.completed_count || 0
11574
11887
  };
11575
11888
  } catch (err) {
11576
11889
  console.error("BugBear: getTesterInfo error", err);
11577
11890
  return null;
11578
11891
  }
11579
11892
  }
11893
+ /**
11894
+ * Basic email format validation (defense in depth)
11895
+ */
11896
+ isValidEmail(email) {
11897
+ if (!email || email.length > 254) return false;
11898
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11899
+ return emailRegex.test(email);
11900
+ }
11901
+ /**
11902
+ * Validate report input before submission
11903
+ * Returns error message if invalid, null if valid
11904
+ */
11905
+ validateReport(report) {
11906
+ const validTypes = ["bug", "feedback", "suggestion", "test_pass", "test_fail"];
11907
+ if (report.type && !validTypes.includes(report.type)) {
11908
+ return `Invalid report type: ${report.type}. Must be one of: ${validTypes.join(", ")}`;
11909
+ }
11910
+ const validSeverities = ["critical", "high", "medium", "low"];
11911
+ if (report.severity && !validSeverities.includes(report.severity)) {
11912
+ return `Invalid severity: ${report.severity}. Must be one of: ${validSeverities.join(", ")}`;
11913
+ }
11914
+ if (report.title && report.title.length > 500) {
11915
+ return "Title must be 500 characters or less";
11916
+ }
11917
+ if (report.description && report.description.length > 1e4) {
11918
+ return "Description must be 10,000 characters or less";
11919
+ }
11920
+ if (report.screenshots && Array.isArray(report.screenshots)) {
11921
+ if (report.screenshots.length > 10) {
11922
+ return "Maximum 10 screenshots allowed";
11923
+ }
11924
+ for (const url of report.screenshots) {
11925
+ if (typeof url !== "string" || url.length > 2e3) {
11926
+ return "Invalid screenshot URL";
11927
+ }
11928
+ }
11929
+ }
11930
+ return null;
11931
+ }
11932
+ /**
11933
+ * Validate profile update input
11934
+ * Returns error message if invalid, null if valid
11935
+ */
11936
+ validateProfileUpdate(updates) {
11937
+ if (updates.name !== void 0) {
11938
+ if (typeof updates.name !== "string" || updates.name.length > 100) {
11939
+ return "Name must be 100 characters or less";
11940
+ }
11941
+ }
11942
+ if (updates.additionalEmails !== void 0) {
11943
+ if (!Array.isArray(updates.additionalEmails)) {
11944
+ return "Additional emails must be an array";
11945
+ }
11946
+ if (updates.additionalEmails.length > 5) {
11947
+ return "Maximum 5 additional emails allowed";
11948
+ }
11949
+ for (const email of updates.additionalEmails) {
11950
+ if (!this.isValidEmail(email)) {
11951
+ return `Invalid email format: ${email}`;
11952
+ }
11953
+ }
11954
+ }
11955
+ if (updates.avatarUrl !== void 0 && updates.avatarUrl !== null) {
11956
+ if (typeof updates.avatarUrl !== "string" || updates.avatarUrl.length > 2e3) {
11957
+ return "Invalid avatar URL";
11958
+ }
11959
+ }
11960
+ if (updates.platforms !== void 0) {
11961
+ if (!Array.isArray(updates.platforms)) {
11962
+ return "Platforms must be an array";
11963
+ }
11964
+ const validPlatforms = ["ios", "android", "web", "desktop", "other"];
11965
+ for (const platform of updates.platforms) {
11966
+ if (!validPlatforms.includes(platform)) {
11967
+ return `Invalid platform: ${platform}. Must be one of: ${validPlatforms.join(", ")}`;
11968
+ }
11969
+ }
11970
+ }
11971
+ return null;
11972
+ }
11973
+ /**
11974
+ * Check rate limit for an action
11975
+ * Returns { allowed: boolean, error?: string, remaining?: number }
11976
+ */
11977
+ async checkRateLimit(identifier, action) {
11978
+ try {
11979
+ const { data, error } = await this.supabase.rpc("check_rate_limit", {
11980
+ p_identifier: identifier,
11981
+ p_action: action,
11982
+ p_project_id: this.config.projectId
11983
+ });
11984
+ if (error) {
11985
+ console.warn("BugBear: Rate limit check failed, allowing request", error.message);
11986
+ return { allowed: true };
11987
+ }
11988
+ if (!data.allowed) {
11989
+ return {
11990
+ allowed: false,
11991
+ error: `Rate limit exceeded. Try again in ${Math.ceil((new Date(data.reset_at).getTime() - Date.now()) / 1e3)} seconds.`,
11992
+ remaining: 0,
11993
+ resetAt: data.reset_at
11994
+ };
11995
+ }
11996
+ return {
11997
+ allowed: true,
11998
+ remaining: data.remaining,
11999
+ resetAt: data.reset_at
12000
+ };
12001
+ } catch (err) {
12002
+ console.warn("BugBear: Rate limit check error", err);
12003
+ return { allowed: true };
12004
+ }
12005
+ }
11580
12006
  /**
11581
12007
  * Update tester profile
11582
12008
  * Allows testers to update their name, additional emails, avatar, and platforms
11583
12009
  */
11584
12010
  async updateTesterProfile(updates) {
11585
12011
  try {
12012
+ const validationError = this.validateProfileUpdate(updates);
12013
+ if (validationError) {
12014
+ return { success: false, error: validationError };
12015
+ }
11586
12016
  const userInfo = await this.getCurrentUserInfo();
11587
12017
  if (!userInfo) {
11588
12018
  return { success: false, error: "Not authenticated" };
11589
12019
  }
12020
+ const rateLimit = await this.checkRateLimit(userInfo.email, "profile_update");
12021
+ if (!rateLimit.allowed) {
12022
+ return { success: false, error: rateLimit.error };
12023
+ }
12024
+ const testerInfo = await this.getTesterInfo();
12025
+ if (!testerInfo) {
12026
+ return { success: false, error: "Not a registered tester" };
12027
+ }
11590
12028
  const updateData = {};
11591
12029
  if (updates.name !== void 0) updateData.name = updates.name;
11592
12030
  if (updates.additionalEmails !== void 0) updateData.additional_emails = updates.additionalEmails;
11593
12031
  if (updates.avatarUrl !== void 0) updateData.avatar_url = updates.avatarUrl;
11594
12032
  if (updates.platforms !== void 0) updateData.platforms = updates.platforms;
11595
- const { error } = await this.supabase.from("testers").update(updateData).eq("project_id", this.config.projectId).eq("email", userInfo.email);
12033
+ const { error } = await this.supabase.from("testers").update(updateData).eq("id", testerInfo.id);
11596
12034
  if (error) {
11597
12035
  console.error("BugBear: updateTesterProfile error", error);
11598
12036
  return { success: false, error: error.message };
@@ -11868,6 +12306,11 @@ var BugBearClient = class {
11868
12306
  console.error("BugBear: No tester info, cannot send message");
11869
12307
  return false;
11870
12308
  }
12309
+ const rateLimit = await this.checkRateLimit(testerInfo.email, "message_send");
12310
+ if (!rateLimit.allowed) {
12311
+ console.error("BugBear: Rate limit exceeded for messages");
12312
+ return false;
12313
+ }
11871
12314
  const { error } = await this.supabase.from("discussion_messages").insert({
11872
12315
  thread_id: threadId,
11873
12316
  sender_type: "tester",
@@ -11962,50 +12405,292 @@ var BugBearClient = class {
11962
12405
  return { success: false, error: message };
11963
12406
  }
11964
12407
  }
11965
- };
11966
- function createBugBear(config) {
11967
- return new BugBearClient(config);
11968
- }
11969
- var MAX_CONSOLE_LOGS = 50;
11970
- var MAX_NETWORK_REQUESTS = 20;
11971
- var ContextCaptureManager = class {
11972
- constructor() {
11973
- this.consoleLogs = [];
11974
- this.networkRequests = [];
11975
- this.originalConsole = {};
11976
- this.isCapturing = false;
12408
+ // ============================================
12409
+ // QA Sessions (Sprint 1)
12410
+ // ============================================
12411
+ /**
12412
+ * Start a new QA session for exploratory testing
12413
+ */
12414
+ async startSession(options = {}) {
12415
+ try {
12416
+ const testerInfo = await this.getTesterInfo();
12417
+ if (!testerInfo) {
12418
+ return { success: false, error: "Not authenticated as a tester" };
12419
+ }
12420
+ const activeSession = await this.getActiveSession();
12421
+ if (activeSession) {
12422
+ return { success: false, error: "You already have an active session. End it before starting a new one." };
12423
+ }
12424
+ const { data, error } = await this.supabase.rpc("start_qa_session", {
12425
+ p_project_id: this.config.projectId,
12426
+ p_tester_id: testerInfo.id,
12427
+ p_focus_area: options.focusArea || null,
12428
+ p_track: options.track || null,
12429
+ p_platform: options.platform || null
12430
+ });
12431
+ if (error) {
12432
+ console.error("BugBear: Failed to start session", error);
12433
+ return { success: false, error: error.message };
12434
+ }
12435
+ const session = await this.getSession(data);
12436
+ if (!session) {
12437
+ return { success: false, error: "Session created but could not be fetched" };
12438
+ }
12439
+ return { success: true, session };
12440
+ } catch (err) {
12441
+ const message = err instanceof Error ? err.message : "Unknown error";
12442
+ console.error("BugBear: Error starting session", err);
12443
+ return { success: false, error: message };
12444
+ }
11977
12445
  }
11978
12446
  /**
11979
- * Start capturing console logs and network requests
12447
+ * End the current QA session
11980
12448
  */
11981
- startCapture() {
11982
- if (this.isCapturing) return;
11983
- this.isCapturing = true;
11984
- this.captureConsole();
11985
- this.captureFetch();
12449
+ async endSession(sessionId, options = {}) {
12450
+ try {
12451
+ const { data, error } = await this.supabase.rpc("end_qa_session", {
12452
+ p_session_id: sessionId,
12453
+ p_notes: options.notes || null,
12454
+ p_routes_covered: options.routesCovered || null
12455
+ });
12456
+ if (error) {
12457
+ console.error("BugBear: Failed to end session", error);
12458
+ return { success: false, error: error.message };
12459
+ }
12460
+ const session = this.transformSession(data);
12461
+ return { success: true, session };
12462
+ } catch (err) {
12463
+ const message = err instanceof Error ? err.message : "Unknown error";
12464
+ console.error("BugBear: Error ending session", err);
12465
+ return { success: false, error: message };
12466
+ }
11986
12467
  }
11987
12468
  /**
11988
- * Stop capturing and restore original functions
12469
+ * Get the current active session for the tester
11989
12470
  */
11990
- stopCapture() {
11991
- if (!this.isCapturing) return;
11992
- this.isCapturing = false;
11993
- if (this.originalConsole.log) console.log = this.originalConsole.log;
11994
- if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
11995
- if (this.originalConsole.error) console.error = this.originalConsole.error;
11996
- if (this.originalConsole.info) console.info = this.originalConsole.info;
11997
- if (this.originalFetch && typeof window !== "undefined") {
11998
- window.fetch = this.originalFetch;
12471
+ async getActiveSession() {
12472
+ try {
12473
+ const testerInfo = await this.getTesterInfo();
12474
+ if (!testerInfo) return null;
12475
+ const { data, error } = await this.supabase.from("qa_sessions").select("*").eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).eq("status", "active").order("started_at", { ascending: false }).limit(1).maybeSingle();
12476
+ if (error || !data) return null;
12477
+ return this.transformSession(data);
12478
+ } catch (err) {
12479
+ console.error("BugBear: Error fetching active session", err);
12480
+ return null;
11999
12481
  }
12000
12482
  }
12001
12483
  /**
12002
- * Get captured context for a bug report
12484
+ * Get a session by ID
12003
12485
  */
12004
- getEnhancedContext() {
12005
- return {
12006
- consoleLogs: [...this.consoleLogs],
12007
- networkRequests: [...this.networkRequests],
12008
- performanceMetrics: this.getPerformanceMetrics(),
12486
+ async getSession(sessionId) {
12487
+ try {
12488
+ const { data, error } = await this.supabase.from("qa_sessions").select("*").eq("id", sessionId).single();
12489
+ if (error || !data) return null;
12490
+ return this.transformSession(data);
12491
+ } catch (err) {
12492
+ console.error("BugBear: Error fetching session", err);
12493
+ return null;
12494
+ }
12495
+ }
12496
+ /**
12497
+ * Get session history for the tester
12498
+ */
12499
+ async getSessionHistory(limit = 10) {
12500
+ try {
12501
+ const testerInfo = await this.getTesterInfo();
12502
+ if (!testerInfo) return [];
12503
+ const { data, error } = await this.supabase.from("qa_sessions").select("*").eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).order("started_at", { ascending: false }).limit(limit);
12504
+ if (error) {
12505
+ console.error("BugBear: Failed to fetch session history", error);
12506
+ return [];
12507
+ }
12508
+ return (data || []).map((s) => this.transformSession(s));
12509
+ } catch (err) {
12510
+ console.error("BugBear: Error fetching session history", err);
12511
+ return [];
12512
+ }
12513
+ }
12514
+ /**
12515
+ * Add a finding during a session
12516
+ */
12517
+ async addFinding(sessionId, options) {
12518
+ try {
12519
+ const { data, error } = await this.supabase.rpc("add_session_finding", {
12520
+ p_session_id: sessionId,
12521
+ p_type: options.type,
12522
+ p_title: options.title,
12523
+ p_description: options.description || null,
12524
+ p_severity: options.severity || "observation",
12525
+ p_route: options.route || null,
12526
+ p_screenshot_url: options.screenshotUrl || null,
12527
+ p_console_logs: options.consoleLogs || null,
12528
+ p_network_snapshot: options.networkSnapshot || null,
12529
+ p_device_info: options.deviceInfo || null,
12530
+ p_app_context: options.appContext || null
12531
+ });
12532
+ if (error) {
12533
+ console.error("BugBear: Failed to add finding", error);
12534
+ return { success: false, error: error.message };
12535
+ }
12536
+ const finding = this.transformFinding(data);
12537
+ return { success: true, finding };
12538
+ } catch (err) {
12539
+ const message = err instanceof Error ? err.message : "Unknown error";
12540
+ console.error("BugBear: Error adding finding", err);
12541
+ return { success: false, error: message };
12542
+ }
12543
+ }
12544
+ /**
12545
+ * Get findings for a session
12546
+ */
12547
+ async getSessionFindings(sessionId) {
12548
+ try {
12549
+ const { data, error } = await this.supabase.from("qa_findings").select("*").eq("session_id", sessionId).order("created_at", { ascending: true });
12550
+ if (error) {
12551
+ console.error("BugBear: Failed to fetch findings", error);
12552
+ return [];
12553
+ }
12554
+ return (data || []).map((f) => this.transformFinding(f));
12555
+ } catch (err) {
12556
+ console.error("BugBear: Error fetching findings", err);
12557
+ return [];
12558
+ }
12559
+ }
12560
+ /**
12561
+ * Convert a finding to a bug report
12562
+ */
12563
+ async convertFindingToBug(findingId) {
12564
+ try {
12565
+ const { data, error } = await this.supabase.rpc("convert_finding_to_bug", {
12566
+ p_finding_id: findingId
12567
+ });
12568
+ if (error) {
12569
+ console.error("BugBear: Failed to convert finding", error);
12570
+ return { success: false, error: error.message };
12571
+ }
12572
+ return { success: true, bugId: data };
12573
+ } catch (err) {
12574
+ const message = err instanceof Error ? err.message : "Unknown error";
12575
+ console.error("BugBear: Error converting finding", err);
12576
+ return { success: false, error: message };
12577
+ }
12578
+ }
12579
+ /**
12580
+ * Dismiss a finding
12581
+ */
12582
+ async dismissFinding(findingId, reason) {
12583
+ try {
12584
+ const { error } = await this.supabase.from("qa_findings").update({
12585
+ dismissed: true,
12586
+ dismissed_reason: reason || null,
12587
+ dismissed_at: (/* @__PURE__ */ new Date()).toISOString()
12588
+ }).eq("id", findingId);
12589
+ if (error) {
12590
+ console.error("BugBear: Failed to dismiss finding", error);
12591
+ return { success: false, error: error.message };
12592
+ }
12593
+ return { success: true };
12594
+ } catch (err) {
12595
+ const message = err instanceof Error ? err.message : "Unknown error";
12596
+ console.error("BugBear: Error dismissing finding", err);
12597
+ return { success: false, error: message };
12598
+ }
12599
+ }
12600
+ /**
12601
+ * Transform database session to QASession type
12602
+ */
12603
+ transformSession(data) {
12604
+ return {
12605
+ id: data.id,
12606
+ projectId: data.project_id,
12607
+ testerId: data.tester_id,
12608
+ focusArea: data.focus_area,
12609
+ track: data.track,
12610
+ platform: data.platform,
12611
+ startedAt: data.started_at,
12612
+ endedAt: data.ended_at,
12613
+ notes: data.notes,
12614
+ routesCovered: data.routes_covered || [],
12615
+ status: data.status,
12616
+ durationMinutes: data.duration_minutes,
12617
+ findingsCount: data.findings_count || 0,
12618
+ bugsFiled: data.bugs_filed || 0,
12619
+ createdAt: data.created_at,
12620
+ updatedAt: data.updated_at
12621
+ };
12622
+ }
12623
+ /**
12624
+ * Transform database finding to QAFinding type
12625
+ */
12626
+ transformFinding(data) {
12627
+ return {
12628
+ id: data.id,
12629
+ sessionId: data.session_id,
12630
+ projectId: data.project_id,
12631
+ type: data.type,
12632
+ severity: data.severity,
12633
+ title: data.title,
12634
+ description: data.description,
12635
+ route: data.route,
12636
+ screenshotUrl: data.screenshot_url,
12637
+ consoleLogs: data.console_logs,
12638
+ networkSnapshot: data.network_snapshot,
12639
+ deviceInfo: data.device_info,
12640
+ appContext: data.app_context,
12641
+ convertedToBugId: data.converted_to_bug_id,
12642
+ convertedToTestId: data.converted_to_test_id,
12643
+ dismissed: data.dismissed || false,
12644
+ dismissedReason: data.dismissed_reason,
12645
+ dismissedAt: data.dismissed_at,
12646
+ createdAt: data.created_at,
12647
+ updatedAt: data.updated_at
12648
+ };
12649
+ }
12650
+ };
12651
+ function createBugBear(config) {
12652
+ return new BugBearClient(config);
12653
+ }
12654
+ var MAX_CONSOLE_LOGS = 50;
12655
+ var MAX_NETWORK_REQUESTS = 20;
12656
+ var ContextCaptureManager = class {
12657
+ constructor() {
12658
+ this.consoleLogs = [];
12659
+ this.networkRequests = [];
12660
+ this.originalConsole = {};
12661
+ this.isCapturing = false;
12662
+ }
12663
+ /**
12664
+ * Start capturing console logs and network requests
12665
+ */
12666
+ startCapture() {
12667
+ if (this.isCapturing) return;
12668
+ this.isCapturing = true;
12669
+ this.captureConsole();
12670
+ this.captureFetch();
12671
+ }
12672
+ /**
12673
+ * Stop capturing and restore original functions
12674
+ */
12675
+ stopCapture() {
12676
+ if (!this.isCapturing) return;
12677
+ this.isCapturing = false;
12678
+ if (this.originalConsole.log) console.log = this.originalConsole.log;
12679
+ if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
12680
+ if (this.originalConsole.error) console.error = this.originalConsole.error;
12681
+ if (this.originalConsole.info) console.info = this.originalConsole.info;
12682
+ if (this.originalFetch && typeof window !== "undefined") {
12683
+ window.fetch = this.originalFetch;
12684
+ }
12685
+ }
12686
+ /**
12687
+ * Get captured context for a bug report
12688
+ */
12689
+ getEnhancedContext() {
12690
+ return {
12691
+ consoleLogs: [...this.consoleLogs],
12692
+ networkRequests: [...this.networkRequests],
12693
+ performanceMetrics: this.getPerformanceMetrics(),
12009
12694
  environment: this.getEnvironmentInfo()
12010
12695
  };
12011
12696
  }
@@ -12148,6 +12833,14 @@ var BugBearContext = (0, import_react.createContext)({
12148
12833
  markAsRead: async () => {
12149
12834
  },
12150
12835
  createThread: async () => ({ success: false }),
12836
+ // QA Sessions
12837
+ activeSession: null,
12838
+ sessionFindings: [],
12839
+ startSession: async () => ({ success: false }),
12840
+ endSession: async () => ({ success: false }),
12841
+ addFinding: async () => ({ success: false }),
12842
+ refreshSession: async () => {
12843
+ },
12151
12844
  refreshTesterStatus: async () => {
12152
12845
  },
12153
12846
  updateTesterProfile: async () => ({ success: false }),
@@ -12166,6 +12859,8 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12166
12859
  const [isLoading, setIsLoading] = (0, import_react.useState)(true);
12167
12860
  const [threads, setThreads] = (0, import_react.useState)([]);
12168
12861
  const [unreadCount, setUnreadCount] = (0, import_react.useState)(0);
12862
+ const [activeSession, setActiveSession] = (0, import_react.useState)(null);
12863
+ const [sessionFindings, setSessionFindings] = (0, import_react.useState)([]);
12169
12864
  const hasInitialized = (0, import_react.useRef)(false);
12170
12865
  const getDeviceInfo = (0, import_react.useCallback)(() => {
12171
12866
  const { width, height } = import_react_native.Dimensions.get("window");
@@ -12213,6 +12908,45 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12213
12908
  }
12214
12909
  return result;
12215
12910
  }, [client, refreshThreads]);
12911
+ const refreshSession = (0, import_react.useCallback)(async () => {
12912
+ if (!client) return;
12913
+ const session = await client.getActiveSession();
12914
+ setActiveSession(session);
12915
+ if (session) {
12916
+ const findings = await client.getSessionFindings(session.id);
12917
+ setSessionFindings(findings);
12918
+ } else {
12919
+ setSessionFindings([]);
12920
+ }
12921
+ }, [client]);
12922
+ const startSession = (0, import_react.useCallback)(async (options = {}) => {
12923
+ if (!client) return { success: false, error: "Client not initialized" };
12924
+ const result = await client.startSession(options);
12925
+ if (result.success && result.session) {
12926
+ setActiveSession(result.session);
12927
+ setSessionFindings([]);
12928
+ }
12929
+ return { success: result.success, error: result.error };
12930
+ }, [client]);
12931
+ const endSession = (0, import_react.useCallback)(async (notes) => {
12932
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12933
+ const routesCovered = client.getNavigationHistory();
12934
+ const result = await client.endSession(activeSession.id, { notes, routesCovered });
12935
+ if (result.success) {
12936
+ setActiveSession(null);
12937
+ setSessionFindings([]);
12938
+ }
12939
+ return { success: result.success, error: result.error };
12940
+ }, [client, activeSession]);
12941
+ const addFinding = (0, import_react.useCallback)(async (options) => {
12942
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12943
+ const result = await client.addFinding(activeSession.id, options);
12944
+ if (result.success && result.finding) {
12945
+ setSessionFindings((prev) => [...prev, result.finding]);
12946
+ setActiveSession((prev) => prev ? { ...prev, findingsCount: prev.findingsCount + 1 } : null);
12947
+ }
12948
+ return result;
12949
+ }, [client, activeSession]);
12216
12950
  const updateTesterProfile = (0, import_react.useCallback)(async (updates) => {
12217
12951
  if (!client) return { success: false, error: "Client not initialized" };
12218
12952
  const result = await client.updateTesterProfile(updates);
@@ -12239,14 +12973,20 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12239
12973
  setTesterInfo(info);
12240
12974
  setIsTester(!!info);
12241
12975
  if (info && qaEnabled) {
12242
- const [newAssignments, newThreads] = await Promise.all([
12976
+ const [newAssignments, newThreads, session] = await Promise.all([
12243
12977
  bugBearClient.getAssignedTests(),
12244
- bugBearClient.getThreadsForTester()
12978
+ bugBearClient.getThreadsForTester(),
12979
+ bugBearClient.getActiveSession()
12245
12980
  ]);
12246
12981
  setAssignments(newAssignments);
12247
12982
  setThreads(newThreads);
12248
12983
  const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
12249
12984
  setUnreadCount(totalUnread);
12985
+ setActiveSession(session);
12986
+ if (session) {
12987
+ const findings = await bugBearClient.getSessionFindings(session.id);
12988
+ setSessionFindings(findings);
12989
+ }
12250
12990
  }
12251
12991
  } catch (err) {
12252
12992
  console.error("BugBear: Init error", err);
@@ -12293,6 +13033,13 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12293
13033
  sendMessage,
12294
13034
  markAsRead,
12295
13035
  createThread,
13036
+ // QA Sessions
13037
+ activeSession,
13038
+ sessionFindings,
13039
+ startSession,
13040
+ endSession,
13041
+ addFinding,
13042
+ refreshSession,
12296
13043
  refreshTesterStatus,
12297
13044
  updateTesterProfile,
12298
13045
  refreshTesterInfo
@@ -12340,7 +13087,13 @@ function BugBearButton({
12340
13087
  markAsRead,
12341
13088
  createThread,
12342
13089
  updateTesterProfile,
12343
- refreshTesterInfo
13090
+ refreshTesterInfo,
13091
+ activeSession,
13092
+ sessionFindings,
13093
+ startSession,
13094
+ endSession,
13095
+ addFinding,
13096
+ refreshSession
12344
13097
  } = useBugBear();
12345
13098
  const [modalVisible, setModalVisible] = (0, import_react2.useState)(false);
12346
13099
  const [activeTab, setActiveTab] = (0, import_react2.useState)("tests");
@@ -12428,39 +13181,228 @@ function BugBearButton({
12428
13181
  const [submitting, setSubmitting] = (0, import_react2.useState)(false);
12429
13182
  const [submitted, setSubmitted] = (0, import_react2.useState)(false);
12430
13183
  const [justPassed, setJustPassed] = (0, import_react2.useState)(false);
13184
+ const [showFeedbackPrompt, setShowFeedbackPrompt] = (0, import_react2.useState)(false);
13185
+ const [pendingFeedbackStatus, setPendingFeedbackStatus] = (0, import_react2.useState)(null);
13186
+ const [feedbackRating, setFeedbackRating] = (0, import_react2.useState)(5);
13187
+ const [feedbackNote, setFeedbackNote] = (0, import_react2.useState)("");
13188
+ const [feedbackFlags, setFeedbackFlags] = (0, import_react2.useState)({
13189
+ isOutdated: false,
13190
+ needsMoreDetail: false,
13191
+ stepsUnclear: false,
13192
+ expectedResultUnclear: false
13193
+ });
12431
13194
  const [criteriaResults, setCriteriaResults] = (0, import_react2.useState)({});
13195
+ const [showSkipModal, setShowSkipModal] = (0, import_react2.useState)(false);
13196
+ const [selectedSkipReason, setSelectedSkipReason] = (0, import_react2.useState)(null);
13197
+ const [skipNotes, setSkipNotes] = (0, import_react2.useState)("");
13198
+ const [skipping, setSkipping] = (0, import_react2.useState)(false);
13199
+ const [collapsedFolders, setCollapsedFolders] = (0, import_react2.useState)(/* @__PURE__ */ new Set());
13200
+ const [startingSession, setStartingSession] = (0, import_react2.useState)(false);
13201
+ const [sessionFocusArea, setSessionFocusArea] = (0, import_react2.useState)("");
13202
+ const [sessionPlatform, setSessionPlatform] = (0, import_react2.useState)(import_react_native2.Platform.OS === "ios" ? "ios" : "android");
13203
+ const [showAddFinding, setShowAddFinding] = (0, import_react2.useState)(false);
13204
+ const [findingType, setFindingType] = (0, import_react2.useState)("bug");
13205
+ const [findingTitle, setFindingTitle] = (0, import_react2.useState)("");
13206
+ const [findingDescription, setFindingDescription] = (0, import_react2.useState)("");
13207
+ const [findingSeverity, setFindingSeverity] = (0, import_react2.useState)("medium");
13208
+ const [addingFinding, setAddingFinding] = (0, import_react2.useState)(false);
13209
+ const [endingSession, setEndingSession] = (0, import_react2.useState)(false);
13210
+ const [sessionNotes, setSessionNotes] = (0, import_react2.useState)("");
13211
+ const [showEndConfirm, setShowEndConfirm] = (0, import_react2.useState)(false);
13212
+ const [sessionElapsedTime, setSessionElapsedTime] = (0, import_react2.useState)(0);
13213
+ const [assignmentElapsedTime, setAssignmentElapsedTime] = (0, import_react2.useState)(0);
13214
+ (0, import_react2.useEffect)(() => {
13215
+ const activeAssignment = displayedAssignment?.status === "in_progress" ? displayedAssignment : null;
13216
+ if (!activeAssignment?.startedAt) {
13217
+ setAssignmentElapsedTime(0);
13218
+ return;
13219
+ }
13220
+ const startTime = new Date(activeAssignment.startedAt).getTime();
13221
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13222
+ const interval = setInterval(() => {
13223
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13224
+ }, 1e3);
13225
+ return () => clearInterval(interval);
13226
+ }, [displayedAssignment?.id, displayedAssignment?.status, displayedAssignment?.startedAt]);
13227
+ (0, import_react2.useEffect)(() => {
13228
+ if (!activeSession) {
13229
+ setSessionElapsedTime(0);
13230
+ return;
13231
+ }
13232
+ const startTime = new Date(activeSession.startedAt).getTime();
13233
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13234
+ const interval = setInterval(() => {
13235
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13236
+ }, 1e3);
13237
+ return () => clearInterval(interval);
13238
+ }, [activeSession]);
13239
+ const formatElapsedTime = (seconds) => {
13240
+ const h = Math.floor(seconds / 3600);
13241
+ const m = Math.floor(seconds % 3600 / 60);
13242
+ const s = seconds % 60;
13243
+ if (h > 0) return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
13244
+ return `${m}:${s.toString().padStart(2, "0")}`;
13245
+ };
12432
13246
  (0, import_react2.useEffect)(() => {
12433
13247
  setCriteriaResults({});
12434
13248
  setShowSteps(false);
12435
13249
  }, [displayedAssignment?.id]);
13250
+ const groupedAssignments = (0, import_react2.useMemo)(() => {
13251
+ const groups = /* @__PURE__ */ new Map();
13252
+ for (const assignment of assignments) {
13253
+ const groupId = assignment.testCase.group?.id || "ungrouped";
13254
+ const group = assignment.testCase.group || null;
13255
+ if (!groups.has(groupId)) {
13256
+ groups.set(groupId, {
13257
+ group,
13258
+ assignments: [],
13259
+ stats: { total: 0, passed: 0, failed: 0, pending: 0, skipped: 0 }
13260
+ });
13261
+ }
13262
+ const folder = groups.get(groupId);
13263
+ folder.assignments.push(assignment);
13264
+ folder.stats.total++;
13265
+ if (assignment.status === "passed") folder.stats.passed++;
13266
+ else if (assignment.status === "failed") folder.stats.failed++;
13267
+ else if (assignment.status === "skipped") folder.stats.skipped++;
13268
+ else folder.stats.pending++;
13269
+ }
13270
+ const sortedGroups = Array.from(groups.values()).sort((a, b) => {
13271
+ if (!a.group && !b.group) return 0;
13272
+ if (!a.group) return 1;
13273
+ if (!b.group) return -1;
13274
+ return a.group.sortOrder - b.group.sortOrder;
13275
+ });
13276
+ return sortedGroups;
13277
+ }, [assignments]);
13278
+ const toggleFolderCollapse = (0, import_react2.useCallback)((groupId) => {
13279
+ setCollapsedFolders((prev) => {
13280
+ const next = new Set(prev);
13281
+ if (next.has(groupId)) {
13282
+ next.delete(groupId);
13283
+ } else {
13284
+ next.add(groupId);
13285
+ }
13286
+ return next;
13287
+ });
13288
+ }, []);
13289
+ const getStatusBadge = (status) => {
13290
+ switch (status) {
13291
+ case "passed":
13292
+ return { icon: "\u2705", label: "Passed", color: "#22c55e" };
13293
+ case "failed":
13294
+ return { icon: "\u274C", label: "Failed", color: "#ef4444" };
13295
+ case "skipped":
13296
+ return { icon: "\u23ED\uFE0F", label: "Skipped", color: "#eab308" };
13297
+ case "in_progress":
13298
+ return { icon: "\u{1F504}", label: "In Progress", color: "#3b82f6" };
13299
+ case "blocked":
13300
+ return { icon: "\u{1F6AB}", label: "Blocked", color: "#f97316" };
13301
+ case "pending":
13302
+ default:
13303
+ return { icon: "\u23F3", label: "Pending", color: "#71717a" };
13304
+ }
13305
+ };
12436
13306
  if (isLoading || !shouldShowWidget) {
12437
13307
  return null;
12438
13308
  }
12439
13309
  const pendingCount = assignments.filter((a) => a.status === "pending").length;
12440
13310
  const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
12441
13311
  const handlePass = async () => {
13312
+ if (!displayedAssignment) return;
13313
+ setPendingFeedbackStatus("passed");
13314
+ setShowFeedbackPrompt(true);
13315
+ setFeedbackRating(5);
13316
+ setFeedbackNote("");
13317
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13318
+ };
13319
+ const handleFail = () => {
13320
+ if (!displayedAssignment) return;
13321
+ setPendingFeedbackStatus("failed");
13322
+ setShowFeedbackPrompt(true);
13323
+ setFeedbackRating(3);
13324
+ setFeedbackNote("");
13325
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13326
+ };
13327
+ const handleSubmitFeedback = async (skipFeedback = false) => {
12442
13328
  if (!client || !displayedAssignment) return;
12443
13329
  setSubmitting(true);
12444
- await client.submitReport({
12445
- type: "test_pass",
12446
- description: `Test passed: ${displayedAssignment.testCase.title}`,
12447
- assignmentId: displayedAssignment.id,
12448
- testCaseId: displayedAssignment.testCase.id,
12449
- appContext: getAppContext?.() || { currentRoute: "unknown" },
12450
- deviceInfo: getDeviceInfo()
12451
- });
12452
- await refreshAssignments();
12453
- setSubmitting(false);
12454
- setJustPassed(true);
12455
- setTimeout(() => {
12456
- setJustPassed(false);
13330
+ const feedback = skipFeedback ? void 0 : {
13331
+ rating: feedbackRating,
13332
+ feedbackNote: feedbackNote.trim() || void 0,
13333
+ isOutdated: feedbackFlags.isOutdated,
13334
+ needsMoreDetail: feedbackFlags.needsMoreDetail,
13335
+ stepsUnclear: feedbackFlags.stepsUnclear,
13336
+ expectedResultUnclear: feedbackFlags.expectedResultUnclear
13337
+ };
13338
+ if (pendingFeedbackStatus === "passed") {
13339
+ await client.submitReport({
13340
+ type: "test_pass",
13341
+ description: `Test passed: ${displayedAssignment.testCase.title}`,
13342
+ assignmentId: displayedAssignment.id,
13343
+ testCaseId: displayedAssignment.testCase.id,
13344
+ appContext: getAppContext?.() || { currentRoute: "unknown" },
13345
+ deviceInfo: getDeviceInfo()
13346
+ });
13347
+ if (feedback) {
13348
+ await client.submitTestFeedback({
13349
+ testCaseId: displayedAssignment.testCase.id,
13350
+ assignmentId: displayedAssignment.id,
13351
+ feedback,
13352
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13353
+ });
13354
+ }
13355
+ await refreshAssignments();
13356
+ setSubmitting(false);
13357
+ setShowFeedbackPrompt(false);
13358
+ setPendingFeedbackStatus(null);
13359
+ setJustPassed(true);
13360
+ setTimeout(() => {
13361
+ setJustPassed(false);
13362
+ setSelectedTestId(null);
13363
+ setTestView("detail");
13364
+ }, 1200);
13365
+ } else if (pendingFeedbackStatus === "failed") {
13366
+ if (feedback) {
13367
+ await client.submitTestFeedback({
13368
+ testCaseId: displayedAssignment.testCase.id,
13369
+ assignmentId: displayedAssignment.id,
13370
+ feedback,
13371
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13372
+ });
13373
+ }
13374
+ setSubmitting(false);
13375
+ setShowFeedbackPrompt(false);
13376
+ setPendingFeedbackStatus(null);
13377
+ setActiveTab("report");
13378
+ setReportType("test_fail");
13379
+ }
13380
+ };
13381
+ const handleSkipFeedback = () => {
13382
+ handleSubmitFeedback(true);
13383
+ };
13384
+ const handleOpenSkipModal = () => {
13385
+ setShowSkipModal(true);
13386
+ setSelectedSkipReason(null);
13387
+ setSkipNotes("");
13388
+ };
13389
+ const handleSkip = async () => {
13390
+ if (!client || !displayedAssignment || !selectedSkipReason) return;
13391
+ setSkipping(true);
13392
+ const result = await client.skipAssignment(
13393
+ displayedAssignment.id,
13394
+ selectedSkipReason,
13395
+ skipNotes || void 0
13396
+ );
13397
+ if (result.success) {
13398
+ await refreshAssignments();
13399
+ setShowSkipModal(false);
13400
+ setSelectedSkipReason(null);
13401
+ setSkipNotes("");
12457
13402
  setSelectedTestId(null);
12458
13403
  setTestView("detail");
12459
- }, 1200);
12460
- };
12461
- const handleFail = () => {
12462
- setActiveTab("report");
12463
- setReportType("test_fail");
13404
+ }
13405
+ setSkipping(false);
12464
13406
  };
12465
13407
  const handleSubmitReport = async () => {
12466
13408
  if (!client || !description.trim()) return;
@@ -12607,6 +13549,44 @@ function BugBearButton({
12607
13549
  }
12608
13550
  setSavingProfile(false);
12609
13551
  };
13552
+ const handleStartSession = async () => {
13553
+ setStartingSession(true);
13554
+ const result = await startSession({
13555
+ focusArea: sessionFocusArea.trim() || void 0,
13556
+ platform: sessionPlatform
13557
+ });
13558
+ if (result.success) {
13559
+ setSessionFocusArea("");
13560
+ }
13561
+ setStartingSession(false);
13562
+ };
13563
+ const handleEndSession = async () => {
13564
+ setEndingSession(true);
13565
+ const result = await endSession(sessionNotes.trim() || void 0);
13566
+ if (result.success) {
13567
+ setSessionNotes("");
13568
+ setShowEndConfirm(false);
13569
+ }
13570
+ setEndingSession(false);
13571
+ };
13572
+ const handleAddFinding = async () => {
13573
+ if (!findingTitle.trim()) return;
13574
+ setAddingFinding(true);
13575
+ const result = await addFinding({
13576
+ type: findingType,
13577
+ title: findingTitle.trim(),
13578
+ description: findingDescription.trim() || void 0,
13579
+ severity: findingType === "bug" ? findingSeverity : void 0
13580
+ });
13581
+ if (result.success) {
13582
+ setFindingTitle("");
13583
+ setFindingDescription("");
13584
+ setFindingType("bug");
13585
+ setFindingSeverity("medium");
13586
+ setShowAddFinding(false);
13587
+ }
13588
+ setAddingFinding(false);
13589
+ };
12610
13590
  const formatRelativeTime = (dateString) => {
12611
13591
  const date = new Date(dateString);
12612
13592
  const now = /* @__PURE__ */ new Date();
@@ -12660,7 +13640,7 @@ function BugBearButton({
12660
13640
  const steps = displayedAssignment.testCase.steps;
12661
13641
  const info = templateInfo[template];
12662
13642
  const rubricMode = displayedAssignment.testCase.track?.rubricMode || "pass_fail";
12663
- return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.templateBadge, { backgroundColor: displayedAssignment.testCase.track?.color ? `${displayedAssignment.testCase.track.color}20` : "#F3F4F6" }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.templateIcon }, info.icon), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.templateName }, info.name), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.templateAction }, "\u2022 ", info.action)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: () => setShowSteps(!showSteps), style: styles.stepsToggle }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepsToggleText }, showSteps ? "\u25BC" : "\u25B6", " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && template === "steps" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { key: idx, style: styles.step }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepNumber }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepNumberText }, step.stepNumber)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepContent }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepExpected }, "\u2192 ", step.expectedResult))))), showSteps && template === "checklist" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ import_react2.default.createElement(
13643
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.templateBadge, { backgroundColor: displayedAssignment.testCase.track?.color ? `${displayedAssignment.testCase.track.color}20` : "#3f3f46" }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.templateIcon }, info.icon), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.templateName }, info.name), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.templateAction }, "\u2022 ", info.action)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: () => setShowSteps(!showSteps), style: styles.stepsToggle }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepsToggleText }, showSteps ? "\u25BC" : "\u25B6", " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && template === "steps" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { key: idx, style: styles.step }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepNumber }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepNumberText }, step.stepNumber)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepContent }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.stepExpected }, "\u2192 ", step.expectedResult))))), showSteps && template === "checklist" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ import_react2.default.createElement(
12664
13644
  import_react_native2.TouchableOpacity,
12665
13645
  {
12666
13646
  key: idx,
@@ -12790,6 +13770,13 @@ function BugBearButton({
12790
13770
  onPress: () => setActiveTab("messages")
12791
13771
  },
12792
13772
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.tabWithBadge }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "messages" && styles.activeTabText] }, "Messages"), unreadCount > 0 && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.tabBadge }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.tabBadgeText }, unreadCount)))
13773
+ ), /* @__PURE__ */ import_react2.default.createElement(
13774
+ import_react_native2.TouchableOpacity,
13775
+ {
13776
+ style: [styles.tab, activeTab === "explore" && styles.activeTab],
13777
+ onPress: () => setActiveTab("explore")
13778
+ },
13779
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.tabWithBadge }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "explore" && styles.activeTabText] }, "Explore"), activeSession && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.sessionDot }))
12793
13780
  ), /* @__PURE__ */ import_react2.default.createElement(
12794
13781
  import_react_native2.TouchableOpacity,
12795
13782
  {
@@ -12798,32 +13785,114 @@ function BugBearButton({
12798
13785
  },
12799
13786
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.tabText, activeTab === "report" && styles.activeTabText] }, "Report")
12800
13787
  )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.ScrollView, { style: styles.content }, activeTab === "tests" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, assignments.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u2705"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "All caught up!"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "No tests assigned")) : testView === "list" ? (
12801
- /* List View - Show all tests */
12802
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"), assignments.map((assignment) => /* @__PURE__ */ import_react2.default.createElement(
13788
+ /* List View - Show tests grouped by folder */
13789
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"), groupedAssignments.map((folder) => {
13790
+ const groupId = folder.group?.id || "ungrouped";
13791
+ const isCollapsed = collapsedFolders.has(groupId);
13792
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13793
+ return /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { key: groupId, style: styles.folderContainer }, /* @__PURE__ */ import_react2.default.createElement(
13794
+ import_react_native2.TouchableOpacity,
13795
+ {
13796
+ onPress: () => toggleFolderCollapse(groupId),
13797
+ style: styles.folderHeader
13798
+ },
13799
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.folderHeaderLeft }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderIcon }, isCollapsed ? "\u{1F4C1}" : "\u{1F4C2}"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderName }, folder.group?.name || "Ungrouped Tests")),
13800
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.folderStats }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderProgress }, completedCount, "/", folder.stats.total), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.folderChevron }, isCollapsed ? "\u25B6" : "\u25BC"))
13801
+ ), !isCollapsed && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.folderProgressBar }, /* @__PURE__ */ import_react2.default.createElement(
13802
+ import_react_native2.View,
13803
+ {
13804
+ style: [
13805
+ styles.folderProgressFill,
13806
+ { width: `${completedCount / folder.stats.total * 100}%` }
13807
+ ]
13808
+ }
13809
+ )), !isCollapsed && folder.assignments.map((assignment) => {
13810
+ const statusBadge = getStatusBadge(assignment.status);
13811
+ return /* @__PURE__ */ import_react2.default.createElement(
13812
+ import_react_native2.TouchableOpacity,
13813
+ {
13814
+ key: assignment.id,
13815
+ onPress: () => {
13816
+ setSelectedTestId(assignment.id);
13817
+ setTestView("detail");
13818
+ setShowSteps(false);
13819
+ },
13820
+ style: [
13821
+ styles.listItem,
13822
+ styles.listItemInFolder,
13823
+ assignment.id === currentAssignment?.id && styles.listItemCurrent
13824
+ ]
13825
+ },
13826
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemKeyWithStatus }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.statusBadge, { backgroundColor: statusBadge.color + "20" }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.statusBadgeIcon }, statusBadge.icon), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.statusBadgeText, { color: statusBadge.color }] }, statusBadge.label))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [
13827
+ styles.priorityBadge,
13828
+ assignment.testCase.priority === "P0" && styles.priorityP0,
13829
+ assignment.testCase.priority === "P1" && styles.priorityP1
13830
+ ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, assignment.testCase.priority)))),
13831
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
13832
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemMeta }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemMetaText }, assignment.testCase.steps.length, " ", assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"), assignment.id === currentAssignment?.id && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.currentBadge }, "\u2022 Current"))
13833
+ );
13834
+ }));
13835
+ }))
13836
+ ) : justPassed ? (
13837
+ /* Success state after passing */
13838
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Loading next test..."))
13839
+ ) : showFeedbackPrompt && displayedAssignment ? (
13840
+ /* Feedback prompt after completing a test */
13841
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.container }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { alignItems: "center", marginBottom: 16 } }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: { fontSize: 28 } }, pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [feedbackStyles.statusText, pendingFeedbackStatus === "passed" ? { color: "#4ade80" } : { color: "#f87171" }] }, pendingFeedbackStatus === "passed" ? "Test Passed!" : "Test Failed")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.infoBox }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.infoTitle }, "Help us improve this test"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.infoSubtitle }, "Your feedback shapes better tests for everyone.")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.ratingSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingLabel }, "How was this test?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.starsRow }, [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ import_react2.default.createElement(
12803
13842
  import_react_native2.TouchableOpacity,
12804
13843
  {
12805
- key: assignment.id,
12806
- onPress: () => {
12807
- setSelectedTestId(assignment.id);
12808
- setTestView("detail");
12809
- setShowSteps(false);
12810
- },
13844
+ key: star,
13845
+ onPress: () => setFeedbackRating(star)
13846
+ },
13847
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [feedbackStyles.star, star <= feedbackRating ? feedbackStyles.starActive : feedbackStyles.starInactive] }, "\u2605")
13848
+ ))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingDesc }, feedbackRating === 1 ? "Needs work" : feedbackRating === 2 ? "Could be better" : feedbackRating === 3 ? "Okay" : feedbackRating === 4 ? "Good" : "Great!")), feedbackRating < 4 && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.flagsSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingLabel }, "What could be improved?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.flagsGrid }, [
13849
+ { key: "stepsUnclear", label: "Steps unclear" },
13850
+ { key: "expectedResultUnclear", label: "Expected result unclear" },
13851
+ { key: "needsMoreDetail", label: "Needs more detail" },
13852
+ { key: "isOutdated", label: "Seems outdated" }
13853
+ ].map(({ key, label }) => /* @__PURE__ */ import_react2.default.createElement(
13854
+ import_react_native2.TouchableOpacity,
13855
+ {
13856
+ key,
13857
+ onPress: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
12811
13858
  style: [
12812
- styles.listItem,
12813
- assignment.id === currentAssignment?.id && styles.listItemCurrent
13859
+ feedbackStyles.flagButton,
13860
+ feedbackFlags[key] && feedbackStyles.flagButtonActive
12814
13861
  ]
12815
13862
  },
12816
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: [
12817
- styles.priorityBadge,
12818
- assignment.testCase.priority === "P0" && styles.priorityP0,
12819
- assignment.testCase.priority === "P1" && styles.priorityP1
12820
- ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, assignment.testCase.priority)))),
12821
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
12822
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.listItemMeta }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.listItemMetaText }, assignment.testCase.steps.length, " ", assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"), assignment.id === currentAssignment?.id && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.currentBadge }, "\u2022 Current"))
13863
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
13864
+ feedbackStyles.flagButtonText,
13865
+ feedbackFlags[key] && feedbackStyles.flagButtonTextActive
13866
+ ] }, label)
13867
+ )))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { marginBottom: 12 } }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.ratingLabel }, "Suggestions? (optional)"), /* @__PURE__ */ import_react2.default.createElement(
13868
+ import_react_native2.TextInput,
13869
+ {
13870
+ style: feedbackStyles.noteInput,
13871
+ value: feedbackNote,
13872
+ onChangeText: setFeedbackNote,
13873
+ placeholder: "How could this test be improved?",
13874
+ placeholderTextColor: "#71717a",
13875
+ multiline: true,
13876
+ numberOfLines: 2,
13877
+ textAlignVertical: "top"
13878
+ }
13879
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: feedbackStyles.buttonRow }, /* @__PURE__ */ import_react2.default.createElement(
13880
+ import_react_native2.TouchableOpacity,
13881
+ {
13882
+ onPress: handleSkipFeedback,
13883
+ disabled: submitting,
13884
+ style: [feedbackStyles.skipButton, submitting && { opacity: 0.5 }]
13885
+ },
13886
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.skipButtonText }, "Skip")
13887
+ ), /* @__PURE__ */ import_react2.default.createElement(
13888
+ import_react_native2.TouchableOpacity,
13889
+ {
13890
+ onPress: () => handleSubmitFeedback(false),
13891
+ disabled: submitting,
13892
+ style: [feedbackStyles.submitButton, submitting && { opacity: 0.5 }]
13893
+ },
13894
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: feedbackStyles.submitButtonText }, submitting ? "Submitting..." : "Submit Feedback")
12823
13895
  )))
12824
- ) : justPassed ? (
12825
- /* Success state after passing */
12826
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Loading next test..."))
12827
13896
  ) : displayedAssignment ? (
12828
13897
  /* Detail View - Show single test */
12829
13898
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(
@@ -12840,20 +13909,41 @@ function BugBearButton({
12840
13909
  styles.priorityBadge,
12841
13910
  displayedAssignment.testCase.priority === "P0" && styles.priorityP0,
12842
13911
  displayedAssignment.testCase.priority === "P1" && styles.priorityP1
12843
- ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.testCase.description && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.expectedResult }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.actionButtons }, /* @__PURE__ */ import_react2.default.createElement(
13912
+ ] }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.status === "in_progress" && displayedAssignment.startedAt && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: timerStyles.container }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: timerStyles.dot }), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: timerStyles.label }, "Testing"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: timerStyles.time }, formatElapsedTime(assignmentElapsedTime))), displayedAssignment.testCase.description && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.expectedResult }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), displayedAssignment.testCase.group && (() => {
13913
+ const folder = groupedAssignments.find((f) => f.group?.id === displayedAssignment.testCase.group?.id);
13914
+ if (!folder) return null;
13915
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13916
+ return /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.detailProgressContainer }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.detailProgressText }, folder.group?.name, ": ", completedCount, "/", folder.stats.total, " complete"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.detailProgressBar }, /* @__PURE__ */ import_react2.default.createElement(
13917
+ import_react_native2.View,
13918
+ {
13919
+ style: [
13920
+ styles.detailProgressFill,
13921
+ { width: `${completedCount / folder.stats.total * 100}%` }
13922
+ ]
13923
+ }
13924
+ )));
13925
+ })(), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.actionButtons }, /* @__PURE__ */ import_react2.default.createElement(
12844
13926
  import_react_native2.TouchableOpacity,
12845
13927
  {
12846
13928
  style: styles.failButton,
12847
13929
  onPress: handleFail,
12848
- disabled: submitting
13930
+ disabled: submitting || skipping
12849
13931
  },
12850
13932
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.failButtonText }, "\u2717 Fail")
13933
+ ), /* @__PURE__ */ import_react2.default.createElement(
13934
+ import_react_native2.TouchableOpacity,
13935
+ {
13936
+ style: styles.skipButton,
13937
+ onPress: handleOpenSkipModal,
13938
+ disabled: submitting || skipping
13939
+ },
13940
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipButtonText }, skipping ? "..." : "\u2192 Skip")
12851
13941
  ), /* @__PURE__ */ import_react2.default.createElement(
12852
13942
  import_react_native2.TouchableOpacity,
12853
13943
  {
12854
13944
  style: styles.passButton,
12855
13945
  onPress: handlePass,
12856
- disabled: submitting
13946
+ disabled: submitting || skipping
12857
13947
  },
12858
13948
  /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.passButtonText }, submitting ? "..." : "\u2713 Pass")
12859
13949
  )))
@@ -12866,7 +13956,7 @@ function BugBearButton({
12866
13956
  value: composeSubject,
12867
13957
  onChangeText: setComposeSubject,
12868
13958
  placeholder: "What's this about?",
12869
- placeholderTextColor: "#9CA3AF",
13959
+ placeholderTextColor: "#71717a",
12870
13960
  maxLength: 100
12871
13961
  }
12872
13962
  ), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [styles.label, { marginTop: 16 }] }, "Message"), /* @__PURE__ */ import_react2.default.createElement(
@@ -12876,7 +13966,7 @@ function BugBearButton({
12876
13966
  value: composeMessage,
12877
13967
  onChangeText: setComposeMessage,
12878
13968
  placeholder: "Write your message...",
12879
- placeholderTextColor: "#9CA3AF",
13969
+ placeholderTextColor: "#71717a",
12880
13970
  multiline: true,
12881
13971
  numberOfLines: 6,
12882
13972
  textAlignVertical: "top",
@@ -12941,33 +14031,193 @@ function BugBearButton({
12941
14031
  message.senderType === "tester" && styles.messageTimeTester
12942
14032
  ] }, formatMessageTime(message.createdAt))
12943
14033
  ))))
12944
- )), activeTab === "report" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, submitted ? /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u{1F389}"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "Report submitted!")) : /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.reportTypes }, [
12945
- { type: "bug", label: "\u{1F41B} Bug" },
12946
- { type: "feedback", label: "\u{1F4A1} Feedback" },
12947
- { type: "suggestion", label: "\u2728 Idea" }
12948
- ].map(({ type, label }) => /* @__PURE__ */ import_react2.default.createElement(
12949
- import_react_native2.TouchableOpacity,
12950
- {
12951
- key: type,
12952
- style: [
12953
- styles.reportTypeButton,
12954
- reportType === type && styles.reportTypeActive
12955
- ],
12956
- onPress: () => setReportType(type)
12957
- },
12958
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
12959
- styles.reportTypeText,
12960
- reportType === type && styles.reportTypeTextActive
12961
- ] }, label)
12962
- ))), (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.severitySection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.label }, "Severity"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.severityButtons }, ["critical", "high", "medium", "low"].map((sev) => {
12963
- const activeStyles = {
12964
- critical: styles.severityCriticalActive,
12965
- high: styles.severityHighActive,
12966
- medium: styles.severityMediumActive,
12967
- low: styles.severityLowActive
12968
- };
12969
- return /* @__PURE__ */ import_react2.default.createElement(
12970
- import_react_native2.TouchableOpacity,
14034
+ )), activeTab === "explore" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, !activeSession ? (
14035
+ /* Start Session View */
14036
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u{1F50D}"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "Exploratory QA Session"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Explore freely and capture findings as you go")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Focus Area (optional)"), /* @__PURE__ */ import_react2.default.createElement(
14037
+ import_react_native2.TextInput,
14038
+ {
14039
+ style: exploreStyles.input,
14040
+ value: sessionFocusArea,
14041
+ onChangeText: setSessionFocusArea,
14042
+ placeholder: "e.g., checkout flow, settings page",
14043
+ placeholderTextColor: "#71717a"
14044
+ }
14045
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Platform"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.platformRow }, [
14046
+ { key: "ios", label: "\u{1F4F1} iOS" },
14047
+ { key: "android", label: "\u{1F916} Android" },
14048
+ { key: "web", label: "\u{1F310} Web" }
14049
+ ].map(({ key, label }) => /* @__PURE__ */ import_react2.default.createElement(
14050
+ import_react_native2.TouchableOpacity,
14051
+ {
14052
+ key,
14053
+ onPress: () => setSessionPlatform(key),
14054
+ style: [
14055
+ exploreStyles.platformButton,
14056
+ sessionPlatform === key && exploreStyles.platformButtonActive
14057
+ ]
14058
+ },
14059
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14060
+ exploreStyles.platformButtonText,
14061
+ sessionPlatform === key && exploreStyles.platformButtonTextActive
14062
+ ] }, label)
14063
+ )))), /* @__PURE__ */ import_react2.default.createElement(
14064
+ import_react_native2.TouchableOpacity,
14065
+ {
14066
+ onPress: handleStartSession,
14067
+ disabled: startingSession,
14068
+ style: [exploreStyles.startButton, startingSession && { opacity: 0.5 }]
14069
+ },
14070
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.startButtonText }, startingSession ? "Starting..." : "\u25B6 Start Session")
14071
+ ))
14072
+ ) : showEndConfirm ? (
14073
+ /* End Session Confirmation */
14074
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u270B"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "End Session?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptySubtitle }, "Duration: ", formatElapsedTime(sessionElapsedTime), " \xB7 ", sessionFindings.length, " finding", sessionFindings.length !== 1 ? "s" : "")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Session Notes (optional)"), /* @__PURE__ */ import_react2.default.createElement(
14075
+ import_react_native2.TextInput,
14076
+ {
14077
+ style: [exploreStyles.input, { height: 80, textAlignVertical: "top" }],
14078
+ value: sessionNotes,
14079
+ onChangeText: setSessionNotes,
14080
+ placeholder: "Any overall observations from this session...",
14081
+ placeholderTextColor: "#71717a",
14082
+ multiline: true
14083
+ }
14084
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.buttonRow }, /* @__PURE__ */ import_react2.default.createElement(
14085
+ import_react_native2.TouchableOpacity,
14086
+ {
14087
+ onPress: () => setShowEndConfirm(false),
14088
+ style: exploreStyles.cancelButton
14089
+ },
14090
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.cancelButtonText }, "Cancel")
14091
+ ), /* @__PURE__ */ import_react2.default.createElement(
14092
+ import_react_native2.TouchableOpacity,
14093
+ {
14094
+ onPress: handleEndSession,
14095
+ disabled: endingSession,
14096
+ style: [exploreStyles.endButton, endingSession && { opacity: 0.5 }]
14097
+ },
14098
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.endButtonText }, endingSession ? "Ending..." : "End Session")
14099
+ )))
14100
+ ) : showAddFinding ? (
14101
+ /* Add Finding Form */
14102
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingHeader }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingHeaderTitle }, "Add Finding"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: () => setShowAddFinding(false) }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingHeaderClose }, "\u2715"))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingTypeRow }, [
14103
+ { type: "bug", label: "\u{1F41B} Bug" },
14104
+ { type: "concern", label: "\u26A0\uFE0F Concern" },
14105
+ { type: "suggestion", label: "\u{1F4A1} Idea" },
14106
+ { type: "question", label: "\u2753 Q" }
14107
+ ].map(({ type, label }) => /* @__PURE__ */ import_react2.default.createElement(
14108
+ import_react_native2.TouchableOpacity,
14109
+ {
14110
+ key: type,
14111
+ onPress: () => setFindingType(type),
14112
+ style: [
14113
+ exploreStyles.findingTypeButton,
14114
+ findingType === type && exploreStyles.findingTypeButtonActive
14115
+ ]
14116
+ },
14117
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14118
+ exploreStyles.findingTypeButtonText,
14119
+ findingType === type && exploreStyles.findingTypeButtonTextActive
14120
+ ] }, label)
14121
+ ))), findingType === "bug" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Severity"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.severityRow }, ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ import_react2.default.createElement(
14122
+ import_react_native2.TouchableOpacity,
14123
+ {
14124
+ key: sev,
14125
+ onPress: () => setFindingSeverity(sev),
14126
+ style: [
14127
+ exploreStyles.severityButton,
14128
+ findingSeverity === sev && (sev === "critical" ? exploreStyles.severityCritical : sev === "high" ? exploreStyles.severityHigh : sev === "medium" ? exploreStyles.severityMedium : exploreStyles.severityLow)
14129
+ ]
14130
+ },
14131
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14132
+ exploreStyles.severityButtonText,
14133
+ findingSeverity === sev && exploreStyles.severityButtonTextActive
14134
+ ] }, sev)
14135
+ )))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Title *"), /* @__PURE__ */ import_react2.default.createElement(
14136
+ import_react_native2.TextInput,
14137
+ {
14138
+ style: exploreStyles.input,
14139
+ value: findingTitle,
14140
+ onChangeText: setFindingTitle,
14141
+ placeholder: "Brief description of what you found",
14142
+ placeholderTextColor: "#71717a"
14143
+ }
14144
+ )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.formGroup }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.label }, "Details (optional)"), /* @__PURE__ */ import_react2.default.createElement(
14145
+ import_react_native2.TextInput,
14146
+ {
14147
+ style: [exploreStyles.input, { height: 60, textAlignVertical: "top" }],
14148
+ value: findingDescription,
14149
+ onChangeText: setFindingDescription,
14150
+ placeholder: "Steps to reproduce, expected behavior, etc.",
14151
+ placeholderTextColor: "#71717a",
14152
+ multiline: true
14153
+ }
14154
+ )), /* @__PURE__ */ import_react2.default.createElement(
14155
+ import_react_native2.TouchableOpacity,
14156
+ {
14157
+ onPress: handleAddFinding,
14158
+ disabled: addingFinding || !findingTitle.trim(),
14159
+ style: [exploreStyles.addFindingButton, (addingFinding || !findingTitle.trim()) && { opacity: 0.5 }]
14160
+ },
14161
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.addFindingButtonText }, addingFinding ? "Adding..." : "Add Finding")
14162
+ ))
14163
+ ) : (
14164
+ /* Active Session View */
14165
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionBanner }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionBannerRow }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionBannerLeft }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.sessionDotLarge }), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.sessionBannerLabel }, "Session Active")), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.sessionTimer }, formatElapsedTime(sessionElapsedTime))), activeSession.focusArea && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.sessionFocus }, "Focus: ", activeSession.focusArea)), /* @__PURE__ */ import_react2.default.createElement(
14166
+ import_react_native2.TouchableOpacity,
14167
+ {
14168
+ onPress: () => setShowAddFinding(true),
14169
+ style: exploreStyles.addButton
14170
+ },
14171
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.addButtonText }, "+ Add Finding")
14172
+ ), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingsSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingsLabel }, "Findings (", sessionFindings.length, ")"), sessionFindings.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: exploreStyles.findingsEmpty }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingsEmptyText }, "No findings yet"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingsEmptyText }, "Explore and add findings as you go")) : /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, sessionFindings.map((finding) => /* @__PURE__ */ import_react2.default.createElement(
14173
+ import_react_native2.View,
14174
+ {
14175
+ key: finding.id,
14176
+ style: [
14177
+ exploreStyles.findingCard,
14178
+ finding.type === "bug" ? exploreStyles.findingCardBug : finding.type === "concern" ? exploreStyles.findingCardConcern : finding.type === "suggestion" ? exploreStyles.findingCardSuggestion : exploreStyles.findingCardQuestion
14179
+ ]
14180
+ },
14181
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingCardIcon }, finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753"),
14182
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: { flex: 1 } }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.findingCardTitle, numberOfLines: 1 }, finding.title), finding.severity && finding.type === "bug" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14183
+ exploreStyles.findingCardSeverity,
14184
+ finding.severity === "critical" ? { color: "#f87171" } : finding.severity === "high" ? { color: "#fb923c" } : finding.severity === "medium" ? { color: "#facc15" } : { color: "#a1a1aa" }
14185
+ ] }, finding.severity))
14186
+ )))), /* @__PURE__ */ import_react2.default.createElement(
14187
+ import_react_native2.TouchableOpacity,
14188
+ {
14189
+ onPress: () => setShowEndConfirm(true),
14190
+ style: exploreStyles.endSessionButton
14191
+ },
14192
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: exploreStyles.endSessionButtonText }, "End Session")
14193
+ ))
14194
+ )), activeTab === "report" && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, null, submitted ? /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.emptyState }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyEmoji }, "\u{1F389}"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emptyTitle }, "Report submitted!")) : /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.reportTypes }, [
14195
+ { type: "bug", label: "\u{1F41B} Bug" },
14196
+ { type: "feedback", label: "\u{1F4A1} Feedback" },
14197
+ { type: "suggestion", label: "\u2728 Idea" }
14198
+ ].map(({ type, label }) => /* @__PURE__ */ import_react2.default.createElement(
14199
+ import_react_native2.TouchableOpacity,
14200
+ {
14201
+ key: type,
14202
+ style: [
14203
+ styles.reportTypeButton,
14204
+ reportType === type && styles.reportTypeActive
14205
+ ],
14206
+ onPress: () => setReportType(type)
14207
+ },
14208
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: [
14209
+ styles.reportTypeText,
14210
+ reportType === type && styles.reportTypeTextActive
14211
+ ] }, label)
14212
+ ))), (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.severitySection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.label }, "Severity"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.severityButtons }, ["critical", "high", "medium", "low"].map((sev) => {
14213
+ const activeStyles = {
14214
+ critical: styles.severityCriticalActive,
14215
+ high: styles.severityHighActive,
14216
+ medium: styles.severityMediumActive,
14217
+ low: styles.severityLowActive
14218
+ };
14219
+ return /* @__PURE__ */ import_react2.default.createElement(
14220
+ import_react_native2.TouchableOpacity,
12971
14221
  {
12972
14222
  key: sev,
12973
14223
  style: [
@@ -12988,7 +14238,7 @@ function BugBearButton({
12988
14238
  value: description,
12989
14239
  onChangeText: setDescription,
12990
14240
  placeholder: "Describe the issue...",
12991
- placeholderTextColor: "#9CA3AF",
14241
+ placeholderTextColor: "#71717a",
12992
14242
  multiline: true,
12993
14243
  numberOfLines: 4,
12994
14244
  textAlignVertical: "top"
@@ -13013,7 +14263,7 @@ function BugBearButton({
13013
14263
  value: profileName,
13014
14264
  onChangeText: setProfileName,
13015
14265
  placeholder: "Your name",
13016
- placeholderTextColor: "#9CA3AF"
14266
+ placeholderTextColor: "#71717a"
13017
14267
  }
13018
14268
  )), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.profileSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.label }, "Primary Email"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.profileReadOnly }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.profileReadOnlyText }, testerInfo?.email), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.profileReadOnlyHint }, "Main communication email"))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.profileSection }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.label }, "Additional Testing Emails"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.profileHint }, "Add other emails you use to test on different accounts"), profileAdditionalEmails.map((email) => /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { key: email, style: styles.emailChip }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emailChipText }, email), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: () => handleRemoveEmail(email) }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.emailChipRemove }, "\u2715")))), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.addEmailRow }, /* @__PURE__ */ import_react2.default.createElement(
13019
14269
  import_react_native2.TextInput,
@@ -13022,7 +14272,7 @@ function BugBearButton({
13022
14272
  value: newEmailInput,
13023
14273
  onChangeText: setNewEmailInput,
13024
14274
  placeholder: "email@example.com",
13025
- placeholderTextColor: "#9CA3AF",
14275
+ placeholderTextColor: "#71717a",
13026
14276
  keyboardType: "email-address",
13027
14277
  autoCapitalize: "none"
13028
14278
  }
@@ -13087,7 +14337,7 @@ function BugBearButton({
13087
14337
  value: replyText,
13088
14338
  onChangeText: setReplyText,
13089
14339
  placeholder: "Type a reply...",
13090
- placeholderTextColor: "#9CA3AF",
14340
+ placeholderTextColor: "#71717a",
13091
14341
  multiline: true,
13092
14342
  maxLength: 1e3
13093
14343
  }
@@ -13105,9 +14355,64 @@ function BugBearButton({
13105
14355
  ))
13106
14356
  ) : (
13107
14357
  /* Standard Footer */
13108
- /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, pendingCount, " pending \xB7 ", inProgressCount, " in progress"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))))
14358
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))) : activeTab === "explore" ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, activeSession ? `${sessionFindings.length} findings` : "No active session"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshSession }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.footerText }, pendingCount, " pending \xB7 ", inProgressCount, " in progress"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.refreshText }, "\u21BB Refresh"))))
13109
14359
  ))
13110
14360
  )
14361
+ ), /* @__PURE__ */ import_react2.default.createElement(
14362
+ import_react_native2.Modal,
14363
+ {
14364
+ visible: showSkipModal,
14365
+ transparent: true,
14366
+ animationType: "fade",
14367
+ onRequestClose: () => setShowSkipModal(false)
14368
+ },
14369
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipModalOverlay }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipModalContent }, /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalTitle }, "Skip Test"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalSubtitle }, "Why are you skipping this test?"), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipReasonOptions }, [
14370
+ { value: "blocked", label: "\u{1F6AB} Blocked", desc: "Something is preventing testing" },
14371
+ { value: "not_ready", label: "\u{1F6A7} Not Ready", desc: "Feature not yet implemented" },
14372
+ { value: "dependency", label: "\u{1F517} Dependency", desc: "Waiting on another test/feature" },
14373
+ { value: "other", label: "\u{1F4DD} Other", desc: "Different reason" }
14374
+ ].map((option) => /* @__PURE__ */ import_react2.default.createElement(
14375
+ import_react_native2.TouchableOpacity,
14376
+ {
14377
+ key: option.value,
14378
+ style: [
14379
+ styles.skipReasonOption,
14380
+ selectedSkipReason === option.value && styles.skipReasonOptionSelected
14381
+ ],
14382
+ onPress: () => setSelectedSkipReason(option.value)
14383
+ },
14384
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipReasonLabel }, option.label),
14385
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipReasonDesc }, option.desc)
14386
+ ))), /* @__PURE__ */ import_react2.default.createElement(
14387
+ import_react_native2.TextInput,
14388
+ {
14389
+ style: styles.skipNotesInput,
14390
+ value: skipNotes,
14391
+ onChangeText: setSkipNotes,
14392
+ placeholder: "Add notes (optional)...",
14393
+ placeholderTextColor: "#71717a",
14394
+ multiline: true,
14395
+ numberOfLines: 2
14396
+ }
14397
+ ), /* @__PURE__ */ import_react2.default.createElement(import_react_native2.View, { style: styles.skipModalActions }, /* @__PURE__ */ import_react2.default.createElement(
14398
+ import_react_native2.TouchableOpacity,
14399
+ {
14400
+ style: styles.skipModalCancel,
14401
+ onPress: () => setShowSkipModal(false)
14402
+ },
14403
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalCancelText }, "Cancel")
14404
+ ), /* @__PURE__ */ import_react2.default.createElement(
14405
+ import_react_native2.TouchableOpacity,
14406
+ {
14407
+ style: [
14408
+ styles.skipModalConfirm,
14409
+ !selectedSkipReason && styles.skipModalConfirmDisabled
14410
+ ],
14411
+ onPress: handleSkip,
14412
+ disabled: !selectedSkipReason || skipping
14413
+ },
14414
+ /* @__PURE__ */ import_react2.default.createElement(import_react_native2.Text, { style: styles.skipModalConfirmText }, skipping ? "Skipping..." : "Skip Test")
14415
+ ))))
13111
14416
  ));
13112
14417
  }
13113
14418
  var styles = import_react_native2.StyleSheet.create({
@@ -13116,13 +14421,13 @@ var styles = import_react_native2.StyleSheet.create({
13116
14421
  width: 56,
13117
14422
  height: 56,
13118
14423
  borderRadius: 28,
13119
- backgroundColor: "#7C3AED",
14424
+ backgroundColor: "#3B82F6",
13120
14425
  justifyContent: "center",
13121
14426
  alignItems: "center",
13122
- shadowColor: "#000",
14427
+ shadowColor: "#3B82F6",
13123
14428
  shadowOffset: { width: 0, height: 4 },
13124
- shadowOpacity: 0.3,
13125
- shadowRadius: 8,
14429
+ shadowOpacity: 0.4,
14430
+ shadowRadius: 12,
13126
14431
  elevation: 8,
13127
14432
  zIndex: 999999
13128
14433
  },
@@ -13155,10 +14460,10 @@ var styles = import_react_native2.StyleSheet.create({
13155
14460
  modalContainer: {
13156
14461
  flex: 1,
13157
14462
  justifyContent: "flex-end",
13158
- backgroundColor: "rgba(0, 0, 0, 0.5)"
14463
+ backgroundColor: "rgba(0, 0, 0, 0.6)"
13159
14464
  },
13160
14465
  modalContent: {
13161
- backgroundColor: "#fff",
14466
+ backgroundColor: "#18181b",
13162
14467
  borderTopLeftRadius: 20,
13163
14468
  borderTopRightRadius: 20,
13164
14469
  maxHeight: "85%"
@@ -13167,11 +14472,13 @@ var styles = import_react_native2.StyleSheet.create({
13167
14472
  flexDirection: "row",
13168
14473
  alignItems: "center",
13169
14474
  justifyContent: "space-between",
13170
- backgroundColor: "#7C3AED",
14475
+ backgroundColor: "#09090b",
13171
14476
  paddingHorizontal: 16,
13172
14477
  paddingVertical: 12,
13173
14478
  borderTopLeftRadius: 20,
13174
- borderTopRightRadius: 20
14479
+ borderTopRightRadius: 20,
14480
+ borderBottomWidth: 1,
14481
+ borderBottomColor: "#27272a"
13175
14482
  },
13176
14483
  headerLeft: {
13177
14484
  flexDirection: "row",
@@ -13182,12 +14489,12 @@ var styles = import_react_native2.StyleSheet.create({
13182
14489
  marginRight: 10
13183
14490
  },
13184
14491
  headerTitle: {
13185
- color: "#fff",
14492
+ color: "#fafafa",
13186
14493
  fontSize: 16,
13187
14494
  fontWeight: "600"
13188
14495
  },
13189
14496
  headerSubtitle: {
13190
- color: "#DDD6FE",
14497
+ color: "#71717a",
13191
14498
  fontSize: 12
13192
14499
  },
13193
14500
  headerNameButton: {
@@ -13196,20 +14503,21 @@ var styles = import_react_native2.StyleSheet.create({
13196
14503
  gap: 4
13197
14504
  },
13198
14505
  headerPencil: {
13199
- color: "#DDD6FE",
14506
+ color: "#71717a",
13200
14507
  fontSize: 11
13201
14508
  },
13202
14509
  closeButton: {
13203
14510
  padding: 8
13204
14511
  },
13205
14512
  closeButtonText: {
13206
- color: "#fff",
14513
+ color: "#a1a1aa",
13207
14514
  fontSize: 18
13208
14515
  },
13209
14516
  tabs: {
13210
14517
  flexDirection: "row",
13211
14518
  borderBottomWidth: 1,
13212
- borderBottomColor: "#E5E7EB"
14519
+ borderBottomColor: "#27272a",
14520
+ backgroundColor: "#18181b"
13213
14521
  },
13214
14522
  tab: {
13215
14523
  flex: 1,
@@ -13218,15 +14526,15 @@ var styles = import_react_native2.StyleSheet.create({
13218
14526
  },
13219
14527
  activeTab: {
13220
14528
  borderBottomWidth: 2,
13221
- borderBottomColor: "#7C3AED"
14529
+ borderBottomColor: "#3B82F6"
13222
14530
  },
13223
14531
  tabText: {
13224
14532
  fontSize: 14,
13225
14533
  fontWeight: "500",
13226
- color: "#6B7280"
14534
+ color: "#71717a"
13227
14535
  },
13228
14536
  activeTabText: {
13229
- color: "#7C3AED"
14537
+ color: "#3B82F6"
13230
14538
  },
13231
14539
  content: {
13232
14540
  padding: 16,
@@ -13239,16 +14547,16 @@ var styles = import_react_native2.StyleSheet.create({
13239
14547
  paddingHorizontal: 16,
13240
14548
  paddingVertical: 12,
13241
14549
  borderTopWidth: 1,
13242
- borderTopColor: "#E5E7EB",
13243
- backgroundColor: "#F9FAFB"
14550
+ borderTopColor: "#27272a",
14551
+ backgroundColor: "#09090b"
13244
14552
  },
13245
14553
  footerText: {
13246
14554
  fontSize: 12,
13247
- color: "#9CA3AF"
14555
+ color: "#52525b"
13248
14556
  },
13249
14557
  refreshText: {
13250
14558
  fontSize: 12,
13251
- color: "#6B7280"
14559
+ color: "#71717a"
13252
14560
  },
13253
14561
  emptyState: {
13254
14562
  alignItems: "center",
@@ -13260,7 +14568,7 @@ var styles = import_react_native2.StyleSheet.create({
13260
14568
  emptyTitle: {
13261
14569
  fontSize: 18,
13262
14570
  fontWeight: "600",
13263
- color: "#374151",
14571
+ color: "#e4e4e7",
13264
14572
  marginTop: 12
13265
14573
  },
13266
14574
  passedEmoji: {
@@ -13275,26 +14583,26 @@ var styles = import_react_native2.StyleSheet.create({
13275
14583
  },
13276
14584
  emptySubtitle: {
13277
14585
  fontSize: 14,
13278
- color: "#9CA3AF",
14586
+ color: "#71717a",
13279
14587
  marginTop: 4
13280
14588
  },
13281
14589
  // List view styles
13282
14590
  listHeader: {
13283
14591
  fontSize: 12,
13284
- color: "#6B7280",
14592
+ color: "#71717a",
13285
14593
  marginBottom: 12
13286
14594
  },
13287
14595
  listItem: {
13288
- backgroundColor: "#F9FAFB",
14596
+ backgroundColor: "#27272a",
13289
14597
  borderRadius: 12,
13290
14598
  padding: 12,
13291
14599
  marginBottom: 8,
13292
14600
  borderWidth: 1,
13293
- borderColor: "#E5E7EB"
14601
+ borderColor: "#3f3f46"
13294
14602
  },
13295
14603
  listItemCurrent: {
13296
- backgroundColor: "#EDE9FE",
13297
- borderColor: "#C4B5FD"
14604
+ backgroundColor: "#1e3a5f",
14605
+ borderColor: "#3B82F6"
13298
14606
  },
13299
14607
  listItemHeader: {
13300
14608
  flexDirection: "row",
@@ -13305,7 +14613,7 @@ var styles = import_react_native2.StyleSheet.create({
13305
14613
  listItemKey: {
13306
14614
  fontSize: 12,
13307
14615
  fontFamily: import_react_native2.Platform.OS === "ios" ? "Menlo" : "monospace",
13308
- color: "#6B7280"
14616
+ color: "#71717a"
13309
14617
  },
13310
14618
  listItemBadges: {
13311
14619
  flexDirection: "row",
@@ -13314,7 +14622,7 @@ var styles = import_react_native2.StyleSheet.create({
13314
14622
  listItemTitle: {
13315
14623
  fontSize: 14,
13316
14624
  fontWeight: "600",
13317
- color: "#111827",
14625
+ color: "#fafafa",
13318
14626
  marginBottom: 4
13319
14627
  },
13320
14628
  listItemMeta: {
@@ -13323,11 +14631,11 @@ var styles = import_react_native2.StyleSheet.create({
13323
14631
  },
13324
14632
  listItemMetaText: {
13325
14633
  fontSize: 12,
13326
- color: "#9CA3AF"
14634
+ color: "#71717a"
13327
14635
  },
13328
14636
  currentBadge: {
13329
14637
  fontSize: 12,
13330
- color: "#7C3AED",
14638
+ color: "#3B82F6",
13331
14639
  fontWeight: "600",
13332
14640
  marginLeft: 8
13333
14641
  },
@@ -13337,15 +14645,17 @@ var styles = import_react_native2.StyleSheet.create({
13337
14645
  },
13338
14646
  backButtonText: {
13339
14647
  fontSize: 14,
13340
- color: "#7C3AED",
14648
+ color: "#3B82F6",
13341
14649
  fontWeight: "500"
13342
14650
  },
13343
14651
  // Test card styles
13344
14652
  testCard: {
13345
- backgroundColor: "#F9FAFB",
14653
+ backgroundColor: "#27272a",
13346
14654
  borderRadius: 12,
13347
14655
  padding: 16,
13348
- marginBottom: 16
14656
+ marginBottom: 16,
14657
+ borderWidth: 1,
14658
+ borderColor: "#3f3f46"
13349
14659
  },
13350
14660
  testHeader: {
13351
14661
  flexDirection: "row",
@@ -13360,7 +14670,7 @@ var styles = import_react_native2.StyleSheet.create({
13360
14670
  testKey: {
13361
14671
  fontSize: 12,
13362
14672
  fontFamily: import_react_native2.Platform.OS === "ios" ? "Menlo" : "monospace",
13363
- color: "#6B7280"
14673
+ color: "#71717a"
13364
14674
  },
13365
14675
  trackBadge: {
13366
14676
  paddingHorizontal: 6,
@@ -13372,38 +14682,38 @@ var styles = import_react_native2.StyleSheet.create({
13372
14682
  color: "#fff"
13373
14683
  },
13374
14684
  priorityBadge: {
13375
- backgroundColor: "#E5E7EB",
14685
+ backgroundColor: "#3f3f46",
13376
14686
  paddingHorizontal: 8,
13377
14687
  paddingVertical: 2,
13378
14688
  borderRadius: 4
13379
14689
  },
13380
14690
  priorityP0: {
13381
- backgroundColor: "#FEE2E2"
14691
+ backgroundColor: "#7f1d1d"
13382
14692
  },
13383
14693
  priorityP1: {
13384
- backgroundColor: "#FED7AA"
14694
+ backgroundColor: "#78350f"
13385
14695
  },
13386
14696
  priorityText: {
13387
14697
  fontSize: 12,
13388
14698
  fontWeight: "600",
13389
- color: "#374151"
14699
+ color: "#e4e4e7"
13390
14700
  },
13391
14701
  testTitle: {
13392
14702
  fontSize: 16,
13393
14703
  fontWeight: "600",
13394
- color: "#111827",
14704
+ color: "#fafafa",
13395
14705
  marginBottom: 4
13396
14706
  },
13397
14707
  testDescription: {
13398
14708
  fontSize: 14,
13399
- color: "#6B7280",
14709
+ color: "#a1a1aa",
13400
14710
  marginBottom: 8
13401
14711
  },
13402
14712
  // Navigate button
13403
14713
  navigateButton: {
13404
- backgroundColor: "#EFF6FF",
14714
+ backgroundColor: "#1e3a5f",
13405
14715
  borderWidth: 1,
13406
- borderColor: "#BFDBFE",
14716
+ borderColor: "#3B82F6",
13407
14717
  borderRadius: 8,
13408
14718
  paddingVertical: 10,
13409
14719
  paddingHorizontal: 16,
@@ -13413,7 +14723,7 @@ var styles = import_react_native2.StyleSheet.create({
13413
14723
  navigateButtonText: {
13414
14724
  fontSize: 14,
13415
14725
  fontWeight: "500",
13416
- color: "#1D4ED8"
14726
+ color: "#60a5fa"
13417
14727
  },
13418
14728
  // Template badge
13419
14729
  templateBadge: {
@@ -13431,12 +14741,12 @@ var styles = import_react_native2.StyleSheet.create({
13431
14741
  templateName: {
13432
14742
  fontSize: 12,
13433
14743
  fontWeight: "600",
13434
- color: "#374151",
14744
+ color: "#e4e4e7",
13435
14745
  marginRight: 4
13436
14746
  },
13437
14747
  templateAction: {
13438
14748
  fontSize: 12,
13439
- color: "#6B7280"
14749
+ color: "#71717a"
13440
14750
  },
13441
14751
  // Steps toggle
13442
14752
  stepsToggle: {
@@ -13444,7 +14754,7 @@ var styles = import_react_native2.StyleSheet.create({
13444
14754
  },
13445
14755
  stepsToggleText: {
13446
14756
  fontSize: 14,
13447
- color: "#7C3AED",
14757
+ color: "#3B82F6",
13448
14758
  fontWeight: "500"
13449
14759
  },
13450
14760
  stepsList: {
@@ -13458,7 +14768,7 @@ var styles = import_react_native2.StyleSheet.create({
13458
14768
  width: 24,
13459
14769
  height: 24,
13460
14770
  borderRadius: 12,
13461
- backgroundColor: "#EDE9FE",
14771
+ backgroundColor: "#1e3a5f",
13462
14772
  justifyContent: "center",
13463
14773
  alignItems: "center",
13464
14774
  marginRight: 12
@@ -13466,41 +14776,41 @@ var styles = import_react_native2.StyleSheet.create({
13466
14776
  stepNumberText: {
13467
14777
  fontSize: 12,
13468
14778
  fontWeight: "600",
13469
- color: "#7C3AED"
14779
+ color: "#3B82F6"
13470
14780
  },
13471
14781
  stepContent: {
13472
14782
  flex: 1
13473
14783
  },
13474
14784
  stepAction: {
13475
14785
  fontSize: 14,
13476
- color: "#374151"
14786
+ color: "#e4e4e7"
13477
14787
  },
13478
14788
  stepExpected: {
13479
14789
  fontSize: 12,
13480
- color: "#9CA3AF",
14790
+ color: "#71717a",
13481
14791
  marginTop: 2
13482
14792
  },
13483
14793
  // Checklist styles
13484
14794
  checklistItem: {
13485
14795
  flexDirection: "row",
13486
14796
  alignItems: "center",
13487
- backgroundColor: "#fff",
14797
+ backgroundColor: "#27272a",
13488
14798
  borderWidth: 1,
13489
- borderColor: "#E5E7EB",
14799
+ borderColor: "#3f3f46",
13490
14800
  borderRadius: 8,
13491
14801
  padding: 12,
13492
14802
  marginBottom: 8
13493
14803
  },
13494
14804
  checklistItemChecked: {
13495
- backgroundColor: "#ECFDF5",
13496
- borderColor: "#86EFAC"
14805
+ backgroundColor: "#14532d",
14806
+ borderColor: "#22C55E"
13497
14807
  },
13498
14808
  checkbox: {
13499
14809
  width: 24,
13500
14810
  height: 24,
13501
14811
  borderRadius: 4,
13502
14812
  borderWidth: 2,
13503
- borderColor: "#22D3EE",
14813
+ borderColor: "#3B82F6",
13504
14814
  marginRight: 12,
13505
14815
  justifyContent: "center",
13506
14816
  alignItems: "center"
@@ -13517,16 +14827,16 @@ var styles = import_react_native2.StyleSheet.create({
13517
14827
  checklistText: {
13518
14828
  flex: 1,
13519
14829
  fontSize: 14,
13520
- color: "#374151"
14830
+ color: "#e4e4e7"
13521
14831
  },
13522
14832
  checklistTextChecked: {
13523
- color: "#15803D"
14833
+ color: "#4ade80"
13524
14834
  },
13525
14835
  // Rubric styles
13526
14836
  rubricItem: {
13527
- backgroundColor: "#fff",
14837
+ backgroundColor: "#27272a",
13528
14838
  borderWidth: 1,
13529
- borderColor: "#E5E7EB",
14839
+ borderColor: "#3f3f46",
13530
14840
  borderRadius: 8,
13531
14841
  padding: 12,
13532
14842
  marginBottom: 8
@@ -13540,7 +14850,7 @@ var styles = import_react_native2.StyleSheet.create({
13540
14850
  width: 24,
13541
14851
  height: 24,
13542
14852
  borderRadius: 4,
13543
- backgroundColor: "#EDE9FE",
14853
+ backgroundColor: "#1e3a5f",
13544
14854
  justifyContent: "center",
13545
14855
  alignItems: "center",
13546
14856
  marginRight: 8
@@ -13548,17 +14858,17 @@ var styles = import_react_native2.StyleSheet.create({
13548
14858
  rubricNumberText: {
13549
14859
  fontSize: 12,
13550
14860
  fontWeight: "600",
13551
- color: "#7C3AED"
14861
+ color: "#3B82F6"
13552
14862
  },
13553
14863
  rubricTitle: {
13554
14864
  flex: 1,
13555
14865
  fontSize: 14,
13556
14866
  fontWeight: "500",
13557
- color: "#111827"
14867
+ color: "#fafafa"
13558
14868
  },
13559
14869
  rubricExpected: {
13560
14870
  fontSize: 12,
13561
- color: "#6B7280",
14871
+ color: "#71717a",
13562
14872
  marginLeft: 32,
13563
14873
  marginBottom: 8
13564
14874
  },
@@ -13572,7 +14882,7 @@ var styles = import_react_native2.StyleSheet.create({
13572
14882
  paddingVertical: 8,
13573
14883
  paddingHorizontal: 12,
13574
14884
  borderRadius: 6,
13575
- backgroundColor: "#F3F4F6",
14885
+ backgroundColor: "#3f3f46",
13576
14886
  alignItems: "center"
13577
14887
  },
13578
14888
  passButtonActive: {
@@ -13584,7 +14894,7 @@ var styles = import_react_native2.StyleSheet.create({
13584
14894
  passFailButtonText: {
13585
14895
  fontSize: 12,
13586
14896
  fontWeight: "600",
13587
- color: "#6B7280"
14897
+ color: "#a1a1aa"
13588
14898
  },
13589
14899
  passButtonTextActive: {
13590
14900
  color: "#fff"
@@ -13601,17 +14911,17 @@ var styles = import_react_native2.StyleSheet.create({
13601
14911
  width: 36,
13602
14912
  height: 36,
13603
14913
  borderRadius: 6,
13604
- backgroundColor: "#F3F4F6",
14914
+ backgroundColor: "#3f3f46",
13605
14915
  justifyContent: "center",
13606
14916
  alignItems: "center"
13607
14917
  },
13608
14918
  ratingButtonActive: {
13609
- backgroundColor: "#7C3AED"
14919
+ backgroundColor: "#3B82F6"
13610
14920
  },
13611
14921
  ratingButtonText: {
13612
14922
  fontSize: 14,
13613
14923
  fontWeight: "600",
13614
- color: "#6B7280"
14924
+ color: "#a1a1aa"
13615
14925
  },
13616
14926
  ratingButtonTextActive: {
13617
14927
  color: "#fff"
@@ -13625,17 +14935,17 @@ var styles = import_react_native2.StyleSheet.create({
13625
14935
  },
13626
14936
  helperText: {
13627
14937
  fontSize: 12,
13628
- color: "#9CA3AF"
14938
+ color: "#71717a"
13629
14939
  },
13630
14940
  resetText: {
13631
14941
  fontSize: 12,
13632
- color: "#9CA3AF"
14942
+ color: "#71717a"
13633
14943
  },
13634
14944
  // Freeform styles
13635
14945
  freeformBox: {
13636
- backgroundColor: "#FFFBEB",
14946
+ backgroundColor: "#422006",
13637
14947
  borderWidth: 1,
13638
- borderColor: "#FDE68A",
14948
+ borderColor: "#a16207",
13639
14949
  borderRadius: 8,
13640
14950
  padding: 12,
13641
14951
  marginTop: 8
@@ -13643,22 +14953,22 @@ var styles = import_react_native2.StyleSheet.create({
13643
14953
  freeformTitle: {
13644
14954
  fontSize: 14,
13645
14955
  fontWeight: "600",
13646
- color: "#92400E",
14956
+ color: "#fbbf24",
13647
14957
  marginBottom: 4
13648
14958
  },
13649
14959
  freeformText: {
13650
14960
  fontSize: 12,
13651
- color: "#A16207",
14961
+ color: "#fcd34d",
13652
14962
  marginBottom: 4
13653
14963
  },
13654
14964
  freeformBullet: {
13655
14965
  fontSize: 12,
13656
- color: "#A16207",
14966
+ color: "#fcd34d",
13657
14967
  marginLeft: 8
13658
14968
  },
13659
14969
  // Expected result
13660
14970
  expectedResult: {
13661
- backgroundColor: "#ECFDF5",
14971
+ backgroundColor: "#14532d",
13662
14972
  padding: 12,
13663
14973
  borderRadius: 8,
13664
14974
  marginTop: 12
@@ -13666,12 +14976,12 @@ var styles = import_react_native2.StyleSheet.create({
13666
14976
  expectedLabel: {
13667
14977
  fontSize: 12,
13668
14978
  fontWeight: "600",
13669
- color: "#065F46",
14979
+ color: "#4ade80",
13670
14980
  marginBottom: 4
13671
14981
  },
13672
14982
  expectedText: {
13673
14983
  fontSize: 14,
13674
- color: "#047857"
14984
+ color: "#86efac"
13675
14985
  },
13676
14986
  // Action buttons
13677
14987
  actionButtons: {
@@ -13680,7 +14990,7 @@ var styles = import_react_native2.StyleSheet.create({
13680
14990
  },
13681
14991
  failButton: {
13682
14992
  flex: 1,
13683
- backgroundColor: "#FEE2E2",
14993
+ backgroundColor: "#7f1d1d",
13684
14994
  paddingVertical: 14,
13685
14995
  borderRadius: 12,
13686
14996
  alignItems: "center"
@@ -13688,7 +14998,7 @@ var styles = import_react_native2.StyleSheet.create({
13688
14998
  failButtonText: {
13689
14999
  fontSize: 16,
13690
15000
  fontWeight: "600",
13691
- color: "#DC2626"
15001
+ color: "#fca5a5"
13692
15002
  },
13693
15003
  passButton: {
13694
15004
  flex: 1,
@@ -13710,22 +15020,22 @@ var styles = import_react_native2.StyleSheet.create({
13710
15020
  },
13711
15021
  reportTypeButton: {
13712
15022
  flex: 1,
13713
- backgroundColor: "#F3F4F6",
15023
+ backgroundColor: "#3f3f46",
13714
15024
  paddingVertical: 10,
13715
15025
  borderRadius: 8,
13716
15026
  alignItems: "center"
13717
15027
  },
13718
15028
  reportTypeActive: {
13719
- backgroundColor: "#EDE9FE",
15029
+ backgroundColor: "#1e3a5f",
13720
15030
  borderWidth: 2,
13721
- borderColor: "#7C3AED"
15031
+ borderColor: "#3B82F6"
13722
15032
  },
13723
15033
  reportTypeText: {
13724
15034
  fontSize: 14,
13725
- color: "#6B7280"
15035
+ color: "#a1a1aa"
13726
15036
  },
13727
15037
  reportTypeTextActive: {
13728
- color: "#7C3AED",
15038
+ color: "#3B82F6",
13729
15039
  fontWeight: "600"
13730
15040
  },
13731
15041
  severitySection: {
@@ -13734,7 +15044,7 @@ var styles = import_react_native2.StyleSheet.create({
13734
15044
  label: {
13735
15045
  fontSize: 14,
13736
15046
  fontWeight: "500",
13737
- color: "#374151",
15047
+ color: "#e4e4e7",
13738
15048
  marginBottom: 8
13739
15049
  },
13740
15050
  severityButtons: {
@@ -13743,7 +15053,7 @@ var styles = import_react_native2.StyleSheet.create({
13743
15053
  },
13744
15054
  severityButton: {
13745
15055
  flex: 1,
13746
- backgroundColor: "#F3F4F6",
15056
+ backgroundColor: "#3f3f46",
13747
15057
  paddingVertical: 8,
13748
15058
  borderRadius: 6,
13749
15059
  alignItems: "center"
@@ -13762,7 +15072,7 @@ var styles = import_react_native2.StyleSheet.create({
13762
15072
  },
13763
15073
  severityText: {
13764
15074
  fontSize: 12,
13765
- color: "#6B7280",
15075
+ color: "#a1a1aa",
13766
15076
  textTransform: "capitalize"
13767
15077
  },
13768
15078
  severityTextActive: {
@@ -13773,17 +15083,17 @@ var styles = import_react_native2.StyleSheet.create({
13773
15083
  marginBottom: 16
13774
15084
  },
13775
15085
  textInput: {
13776
- backgroundColor: "#F9FAFB",
15086
+ backgroundColor: "#27272a",
13777
15087
  borderWidth: 1,
13778
- borderColor: "#E5E7EB",
15088
+ borderColor: "#3f3f46",
13779
15089
  borderRadius: 12,
13780
15090
  padding: 12,
13781
15091
  fontSize: 14,
13782
15092
  minHeight: 100,
13783
- color: "#111827"
15093
+ color: "#fafafa"
13784
15094
  },
13785
15095
  submitButton: {
13786
- backgroundColor: "#7C3AED",
15096
+ backgroundColor: "#3B82F6",
13787
15097
  paddingVertical: 14,
13788
15098
  borderRadius: 12,
13789
15099
  alignItems: "center"
@@ -13805,6 +15115,13 @@ var styles = import_react_native2.StyleSheet.create({
13805
15115
  flexDirection: "row",
13806
15116
  alignItems: "center"
13807
15117
  },
15118
+ sessionDot: {
15119
+ width: 8,
15120
+ height: 8,
15121
+ borderRadius: 4,
15122
+ backgroundColor: "#22c55e",
15123
+ marginLeft: 4
15124
+ },
13808
15125
  tabBadge: {
13809
15126
  backgroundColor: "#EF4444",
13810
15127
  borderRadius: 8,
@@ -13822,16 +15139,16 @@ var styles = import_react_native2.StyleSheet.create({
13822
15139
  },
13823
15140
  // Thread list styles
13824
15141
  threadItem: {
13825
- backgroundColor: "#F9FAFB",
15142
+ backgroundColor: "#27272a",
13826
15143
  borderRadius: 12,
13827
15144
  padding: 12,
13828
15145
  marginBottom: 8,
13829
15146
  borderWidth: 1,
13830
- borderColor: "#E5E7EB"
15147
+ borderColor: "#3f3f46"
13831
15148
  },
13832
15149
  threadItemUnread: {
13833
- backgroundColor: "#EFF6FF",
13834
- borderColor: "#BFDBFE"
15150
+ backgroundColor: "#1e3a5f",
15151
+ borderColor: "#3B82F6"
13835
15152
  },
13836
15153
  threadHeader: {
13837
15154
  flexDirection: "row",
@@ -13855,12 +15172,12 @@ var styles = import_react_native2.StyleSheet.create({
13855
15172
  threadSubject: {
13856
15173
  fontSize: 14,
13857
15174
  fontWeight: "500",
13858
- color: "#374151",
15175
+ color: "#e4e4e7",
13859
15176
  flex: 1
13860
15177
  },
13861
15178
  threadSubjectUnread: {
13862
15179
  fontWeight: "600",
13863
- color: "#111827"
15180
+ color: "#fafafa"
13864
15181
  },
13865
15182
  priorityDot: {
13866
15183
  width: 8,
@@ -13870,7 +15187,7 @@ var styles = import_react_native2.StyleSheet.create({
13870
15187
  },
13871
15188
  threadPreview: {
13872
15189
  fontSize: 13,
13873
- color: "#6B7280",
15190
+ color: "#a1a1aa",
13874
15191
  marginBottom: 4
13875
15192
  },
13876
15193
  threadMeta: {
@@ -13880,7 +15197,7 @@ var styles = import_react_native2.StyleSheet.create({
13880
15197
  },
13881
15198
  threadMetaText: {
13882
15199
  fontSize: 12,
13883
- color: "#9CA3AF"
15200
+ color: "#71717a"
13884
15201
  },
13885
15202
  unreadBadge: {
13886
15203
  backgroundColor: "#3B82F6",
@@ -13895,7 +15212,7 @@ var styles = import_react_native2.StyleSheet.create({
13895
15212
  },
13896
15213
  threadTime: {
13897
15214
  fontSize: 12,
13898
- color: "#9CA3AF"
15215
+ color: "#71717a"
13899
15216
  },
13900
15217
  // Thread detail styles
13901
15218
  threadDetailContainer: {
@@ -13904,7 +15221,7 @@ var styles = import_react_native2.StyleSheet.create({
13904
15221
  threadDetailHeader: {
13905
15222
  flexDirection: "row",
13906
15223
  alignItems: "center",
13907
- backgroundColor: "#F3F4F6",
15224
+ backgroundColor: "#27272a",
13908
15225
  padding: 12,
13909
15226
  borderRadius: 8,
13910
15227
  marginBottom: 12
@@ -13917,7 +15234,7 @@ var styles = import_react_native2.StyleSheet.create({
13917
15234
  flex: 1,
13918
15235
  fontSize: 15,
13919
15236
  fontWeight: "600",
13920
- color: "#111827"
15237
+ color: "#fafafa"
13921
15238
  },
13922
15239
  loadingMessages: {
13923
15240
  padding: 20,
@@ -13925,7 +15242,7 @@ var styles = import_react_native2.StyleSheet.create({
13925
15242
  },
13926
15243
  loadingText: {
13927
15244
  fontSize: 14,
13928
- color: "#6B7280"
15245
+ color: "#71717a"
13929
15246
  },
13930
15247
  messagesContainer: {
13931
15248
  paddingBottom: 8
@@ -13938,26 +15255,26 @@ var styles = import_react_native2.StyleSheet.create({
13938
15255
  },
13939
15256
  messageBubbleAdmin: {
13940
15257
  alignSelf: "flex-start",
13941
- backgroundColor: "#F3F4F6",
15258
+ backgroundColor: "#27272a",
13942
15259
  borderBottomLeftRadius: 4
13943
15260
  },
13944
15261
  messageBubbleTester: {
13945
15262
  alignSelf: "flex-end",
13946
- backgroundColor: "#7C3AED",
15263
+ backgroundColor: "#3B82F6",
13947
15264
  borderBottomRightRadius: 4
13948
15265
  },
13949
15266
  messageSender: {
13950
15267
  fontSize: 12,
13951
15268
  fontWeight: "600",
13952
- color: "#6B7280",
15269
+ color: "#71717a",
13953
15270
  marginBottom: 2
13954
15271
  },
13955
15272
  messageSenderTester: {
13956
- color: "#DDD6FE"
15273
+ color: "#93c5fd"
13957
15274
  },
13958
15275
  messageContent: {
13959
15276
  fontSize: 14,
13960
- color: "#111827",
15277
+ color: "#fafafa",
13961
15278
  lineHeight: 20
13962
15279
  },
13963
15280
  messageContentTester: {
@@ -13965,12 +15282,12 @@ var styles = import_react_native2.StyleSheet.create({
13965
15282
  },
13966
15283
  messageTime: {
13967
15284
  fontSize: 11,
13968
- color: "#9CA3AF",
15285
+ color: "#71717a",
13969
15286
  marginTop: 4,
13970
15287
  textAlign: "right"
13971
15288
  },
13972
15289
  messageTimeTester: {
13973
- color: "#C4B5FD"
15290
+ color: "#93c5fd"
13974
15291
  },
13975
15292
  // Reply composer styles
13976
15293
  replyComposer: {
@@ -13978,24 +15295,24 @@ var styles = import_react_native2.StyleSheet.create({
13978
15295
  alignItems: "flex-end",
13979
15296
  padding: 12,
13980
15297
  borderTopWidth: 1,
13981
- borderTopColor: "#E5E7EB",
13982
- backgroundColor: "#fff"
15298
+ borderTopColor: "#27272a",
15299
+ backgroundColor: "#18181b"
13983
15300
  },
13984
15301
  replyInput: {
13985
15302
  flex: 1,
13986
- backgroundColor: "#F9FAFB",
15303
+ backgroundColor: "#27272a",
13987
15304
  borderWidth: 1,
13988
- borderColor: "#E5E7EB",
15305
+ borderColor: "#3f3f46",
13989
15306
  borderRadius: 20,
13990
15307
  paddingHorizontal: 16,
13991
15308
  paddingVertical: 10,
13992
15309
  fontSize: 14,
13993
- color: "#111827",
15310
+ color: "#fafafa",
13994
15311
  maxHeight: 100,
13995
15312
  marginRight: 8
13996
15313
  },
13997
15314
  sendButton: {
13998
- backgroundColor: "#7C3AED",
15315
+ backgroundColor: "#3B82F6",
13999
15316
  paddingHorizontal: 16,
14000
15317
  paddingVertical: 10,
14001
15318
  borderRadius: 20,
@@ -14003,7 +15320,7 @@ var styles = import_react_native2.StyleSheet.create({
14003
15320
  alignItems: "center"
14004
15321
  },
14005
15322
  sendButtonDisabled: {
14006
- backgroundColor: "#C4B5FD"
15323
+ backgroundColor: "#1e40af"
14007
15324
  },
14008
15325
  sendButtonText: {
14009
15326
  fontSize: 14,
@@ -14015,7 +15332,7 @@ var styles = import_react_native2.StyleSheet.create({
14015
15332
  flexDirection: "row",
14016
15333
  alignItems: "center",
14017
15334
  justifyContent: "center",
14018
- backgroundColor: "#7C3AED",
15335
+ backgroundColor: "#3B82F6",
14019
15336
  paddingVertical: 12,
14020
15337
  paddingHorizontal: 20,
14021
15338
  borderRadius: 12,
@@ -14037,48 +15354,50 @@ var styles = import_react_native2.StyleSheet.create({
14037
15354
  composeTitle: {
14038
15355
  fontSize: 20,
14039
15356
  fontWeight: "600",
14040
- color: "#111827",
15357
+ color: "#fafafa",
14041
15358
  marginBottom: 4
14042
15359
  },
14043
15360
  composeSubtitle: {
14044
15361
  fontSize: 14,
14045
- color: "#6B7280"
15362
+ color: "#71717a"
14046
15363
  },
14047
15364
  composeForm: {
14048
- backgroundColor: "#F9FAFB",
15365
+ backgroundColor: "#27272a",
14049
15366
  borderRadius: 12,
14050
- padding: 16
15367
+ padding: 16,
15368
+ borderWidth: 1,
15369
+ borderColor: "#3f3f46"
14051
15370
  },
14052
15371
  composeSubjectInput: {
14053
- backgroundColor: "#fff",
15372
+ backgroundColor: "#18181b",
14054
15373
  borderWidth: 1,
14055
- borderColor: "#E5E7EB",
15374
+ borderColor: "#3f3f46",
14056
15375
  borderRadius: 8,
14057
15376
  paddingHorizontal: 12,
14058
15377
  paddingVertical: 10,
14059
15378
  fontSize: 15,
14060
- color: "#111827"
15379
+ color: "#fafafa"
14061
15380
  },
14062
15381
  composeMessageInput: {
14063
- backgroundColor: "#fff",
15382
+ backgroundColor: "#18181b",
14064
15383
  borderWidth: 1,
14065
- borderColor: "#E5E7EB",
15384
+ borderColor: "#3f3f46",
14066
15385
  borderRadius: 8,
14067
15386
  paddingHorizontal: 12,
14068
15387
  paddingVertical: 10,
14069
15388
  fontSize: 15,
14070
- color: "#111827",
15389
+ color: "#fafafa",
14071
15390
  minHeight: 120
14072
15391
  },
14073
15392
  composeSendButton: {
14074
- backgroundColor: "#7C3AED",
15393
+ backgroundColor: "#3B82F6",
14075
15394
  paddingVertical: 14,
14076
15395
  borderRadius: 12,
14077
15396
  alignItems: "center",
14078
15397
  marginTop: 20
14079
15398
  },
14080
15399
  composeSendButtonDisabled: {
14081
- backgroundColor: "#C4B5FD"
15400
+ backgroundColor: "#1e40af"
14082
15401
  },
14083
15402
  composeSendButtonText: {
14084
15403
  fontSize: 16,
@@ -14087,17 +15406,19 @@ var styles = import_react_native2.StyleSheet.create({
14087
15406
  },
14088
15407
  // Profile styles
14089
15408
  profileCard: {
14090
- backgroundColor: "#F9FAFB",
15409
+ backgroundColor: "#27272a",
14091
15410
  borderRadius: 16,
14092
15411
  padding: 24,
14093
15412
  alignItems: "center",
14094
- marginBottom: 16
15413
+ marginBottom: 16,
15414
+ borderWidth: 1,
15415
+ borderColor: "#3f3f46"
14095
15416
  },
14096
15417
  avatarCircle: {
14097
15418
  width: 72,
14098
15419
  height: 72,
14099
15420
  borderRadius: 36,
14100
- backgroundColor: "#7C3AED",
15421
+ backgroundColor: "#3B82F6",
14101
15422
  justifyContent: "center",
14102
15423
  alignItems: "center",
14103
15424
  marginBottom: 12
@@ -14110,12 +15431,12 @@ var styles = import_react_native2.StyleSheet.create({
14110
15431
  profileName: {
14111
15432
  fontSize: 20,
14112
15433
  fontWeight: "600",
14113
- color: "#111827",
15434
+ color: "#fafafa",
14114
15435
  marginBottom: 4
14115
15436
  },
14116
15437
  profileEmail: {
14117
15438
  fontSize: 14,
14118
- color: "#6B7280",
15439
+ color: "#71717a",
14119
15440
  marginBottom: 16
14120
15441
  },
14121
15442
  profileStats: {
@@ -14129,35 +15450,37 @@ var styles = import_react_native2.StyleSheet.create({
14129
15450
  profileStatValue: {
14130
15451
  fontSize: 24,
14131
15452
  fontWeight: "700",
14132
- color: "#7C3AED"
15453
+ color: "#3B82F6"
14133
15454
  },
14134
15455
  profileStatLabel: {
14135
15456
  fontSize: 12,
14136
- color: "#6B7280",
15457
+ color: "#71717a",
14137
15458
  marginTop: 2
14138
15459
  },
14139
15460
  profileStatDivider: {
14140
15461
  width: 1,
14141
15462
  height: 32,
14142
- backgroundColor: "#E5E7EB"
15463
+ backgroundColor: "#3f3f46"
14143
15464
  },
14144
15465
  profileInfoSection: {
14145
- backgroundColor: "#F9FAFB",
15466
+ backgroundColor: "#27272a",
14146
15467
  borderRadius: 12,
14147
15468
  padding: 16,
14148
- marginBottom: 12
15469
+ marginBottom: 12,
15470
+ borderWidth: 1,
15471
+ borderColor: "#3f3f46"
14149
15472
  },
14150
15473
  profileInfoLabel: {
14151
15474
  fontSize: 12,
14152
15475
  fontWeight: "600",
14153
- color: "#6B7280",
15476
+ color: "#71717a",
14154
15477
  marginBottom: 8,
14155
15478
  textTransform: "uppercase",
14156
15479
  letterSpacing: 0.5
14157
15480
  },
14158
15481
  profileInfoValue: {
14159
15482
  fontSize: 14,
14160
- color: "#374151",
15483
+ color: "#e4e4e7",
14161
15484
  marginBottom: 4
14162
15485
  },
14163
15486
  platformTags: {
@@ -14166,18 +15489,18 @@ var styles = import_react_native2.StyleSheet.create({
14166
15489
  gap: 8
14167
15490
  },
14168
15491
  platformTag: {
14169
- backgroundColor: "#EDE9FE",
15492
+ backgroundColor: "#1e3a5f",
14170
15493
  paddingHorizontal: 12,
14171
15494
  paddingVertical: 6,
14172
15495
  borderRadius: 16
14173
15496
  },
14174
15497
  platformTagText: {
14175
15498
  fontSize: 13,
14176
- color: "#7C3AED",
15499
+ color: "#60a5fa",
14177
15500
  fontWeight: "500"
14178
15501
  },
14179
15502
  editProfileButton: {
14180
- backgroundColor: "#7C3AED",
15503
+ backgroundColor: "#3B82F6",
14181
15504
  paddingVertical: 14,
14182
15505
  borderRadius: 12,
14183
15506
  alignItems: "center",
@@ -14198,48 +15521,48 @@ var styles = import_react_native2.StyleSheet.create({
14198
15521
  profileEditTitle: {
14199
15522
  fontSize: 20,
14200
15523
  fontWeight: "600",
14201
- color: "#111827"
15524
+ color: "#fafafa"
14202
15525
  },
14203
15526
  cancelText: {
14204
15527
  fontSize: 14,
14205
- color: "#6B7280"
15528
+ color: "#71717a"
14206
15529
  },
14207
15530
  profileSection: {
14208
15531
  marginBottom: 20
14209
15532
  },
14210
15533
  profileInput: {
14211
- backgroundColor: "#F9FAFB",
15534
+ backgroundColor: "#27272a",
14212
15535
  borderWidth: 1,
14213
- borderColor: "#E5E7EB",
15536
+ borderColor: "#3f3f46",
14214
15537
  borderRadius: 10,
14215
15538
  paddingHorizontal: 14,
14216
15539
  paddingVertical: 12,
14217
15540
  fontSize: 15,
14218
- color: "#111827"
15541
+ color: "#fafafa"
14219
15542
  },
14220
15543
  profileReadOnly: {
14221
- backgroundColor: "#F3F4F6",
15544
+ backgroundColor: "#27272a",
14222
15545
  borderRadius: 10,
14223
15546
  padding: 14
14224
15547
  },
14225
15548
  profileReadOnlyText: {
14226
15549
  fontSize: 15,
14227
- color: "#374151"
15550
+ color: "#a1a1aa"
14228
15551
  },
14229
15552
  profileReadOnlyHint: {
14230
15553
  fontSize: 12,
14231
- color: "#9CA3AF",
15554
+ color: "#52525b",
14232
15555
  marginTop: 4
14233
15556
  },
14234
15557
  profileHint: {
14235
15558
  fontSize: 13,
14236
- color: "#6B7280",
15559
+ color: "#71717a",
14237
15560
  marginBottom: 12
14238
15561
  },
14239
15562
  emailChip: {
14240
15563
  flexDirection: "row",
14241
15564
  alignItems: "center",
14242
- backgroundColor: "#EDE9FE",
15565
+ backgroundColor: "#1e3a5f",
14243
15566
  paddingHorizontal: 12,
14244
15567
  paddingVertical: 8,
14245
15568
  borderRadius: 20,
@@ -14248,11 +15571,11 @@ var styles = import_react_native2.StyleSheet.create({
14248
15571
  emailChipText: {
14249
15572
  flex: 1,
14250
15573
  fontSize: 14,
14251
- color: "#5B21B6"
15574
+ color: "#60a5fa"
14252
15575
  },
14253
15576
  emailChipRemove: {
14254
15577
  fontSize: 14,
14255
- color: "#8B5CF6",
15578
+ color: "#93c5fd",
14256
15579
  fontWeight: "600",
14257
15580
  marginLeft: 8
14258
15581
  },
@@ -14262,23 +15585,23 @@ var styles = import_react_native2.StyleSheet.create({
14262
15585
  },
14263
15586
  addEmailInput: {
14264
15587
  flex: 1,
14265
- backgroundColor: "#F9FAFB",
15588
+ backgroundColor: "#27272a",
14266
15589
  borderWidth: 1,
14267
- borderColor: "#E5E7EB",
15590
+ borderColor: "#3f3f46",
14268
15591
  borderRadius: 10,
14269
15592
  paddingHorizontal: 14,
14270
15593
  paddingVertical: 10,
14271
15594
  fontSize: 14,
14272
- color: "#111827"
15595
+ color: "#fafafa"
14273
15596
  },
14274
15597
  addEmailButton: {
14275
- backgroundColor: "#7C3AED",
15598
+ backgroundColor: "#3B82F6",
14276
15599
  paddingHorizontal: 16,
14277
15600
  borderRadius: 10,
14278
15601
  justifyContent: "center"
14279
15602
  },
14280
15603
  addEmailButtonDisabled: {
14281
- backgroundColor: "#C4B5FD"
15604
+ backgroundColor: "#1e40af"
14282
15605
  },
14283
15606
  addEmailButtonText: {
14284
15607
  fontSize: 14,
@@ -14291,7 +15614,7 @@ var styles = import_react_native2.StyleSheet.create({
14291
15614
  },
14292
15615
  platformButton: {
14293
15616
  flex: 1,
14294
- backgroundColor: "#F3F4F6",
15617
+ backgroundColor: "#3f3f46",
14295
15618
  paddingVertical: 12,
14296
15619
  borderRadius: 10,
14297
15620
  alignItems: "center",
@@ -14299,16 +15622,16 @@ var styles = import_react_native2.StyleSheet.create({
14299
15622
  borderColor: "transparent"
14300
15623
  },
14301
15624
  platformButtonActive: {
14302
- backgroundColor: "#EDE9FE",
14303
- borderColor: "#7C3AED"
15625
+ backgroundColor: "#1e3a5f",
15626
+ borderColor: "#3B82F6"
14304
15627
  },
14305
15628
  platformButtonText: {
14306
15629
  fontSize: 13,
14307
- color: "#6B7280",
15630
+ color: "#a1a1aa",
14308
15631
  fontWeight: "500"
14309
15632
  },
14310
15633
  platformButtonTextActive: {
14311
- color: "#7C3AED"
15634
+ color: "#3B82F6"
14312
15635
  },
14313
15636
  saveProfileButton: {
14314
15637
  backgroundColor: "#16A34A",
@@ -14332,7 +15655,7 @@ var styles = import_react_native2.StyleSheet.create({
14332
15655
  left: 0,
14333
15656
  right: 0,
14334
15657
  bottom: 0,
14335
- backgroundColor: "#fff",
15658
+ backgroundColor: "#18181b",
14336
15659
  zIndex: 100
14337
15660
  },
14338
15661
  profileOverlayContent: {
@@ -14341,9 +15664,9 @@ var styles = import_react_native2.StyleSheet.create({
14341
15664
  },
14342
15665
  profileOverlayFooter: {
14343
15666
  borderTopWidth: 1,
14344
- borderTopColor: "#E5E7EB",
15667
+ borderTopColor: "#27272a",
14345
15668
  padding: 12,
14346
- backgroundColor: "#F9FAFB"
15669
+ backgroundColor: "#09090b"
14347
15670
  },
14348
15671
  closeProfileButton: {
14349
15672
  paddingVertical: 8,
@@ -14352,7 +15675,666 @@ var styles = import_react_native2.StyleSheet.create({
14352
15675
  closeProfileButtonText: {
14353
15676
  fontSize: 14,
14354
15677
  fontWeight: "500",
14355
- color: "#7C3AED"
15678
+ color: "#3B82F6"
15679
+ },
15680
+ // Folder grouping styles
15681
+ folderContainer: {
15682
+ marginBottom: 12
15683
+ },
15684
+ folderHeader: {
15685
+ flexDirection: "row",
15686
+ justifyContent: "space-between",
15687
+ alignItems: "center",
15688
+ backgroundColor: "#27272a",
15689
+ padding: 12,
15690
+ borderRadius: 8,
15691
+ marginBottom: 4
15692
+ },
15693
+ folderHeaderLeft: {
15694
+ flexDirection: "row",
15695
+ alignItems: "center",
15696
+ flex: 1
15697
+ },
15698
+ folderIcon: {
15699
+ fontSize: 16,
15700
+ marginRight: 8
15701
+ },
15702
+ folderName: {
15703
+ fontSize: 14,
15704
+ fontWeight: "600",
15705
+ color: "#fafafa"
15706
+ },
15707
+ folderStats: {
15708
+ flexDirection: "row",
15709
+ alignItems: "center"
15710
+ },
15711
+ folderProgress: {
15712
+ fontSize: 12,
15713
+ color: "#71717a",
15714
+ marginRight: 8
15715
+ },
15716
+ folderChevron: {
15717
+ fontSize: 10,
15718
+ color: "#71717a"
15719
+ },
15720
+ folderProgressBar: {
15721
+ height: 3,
15722
+ backgroundColor: "#3f3f46",
15723
+ borderRadius: 2,
15724
+ marginBottom: 8,
15725
+ marginHorizontal: 4
15726
+ },
15727
+ folderProgressFill: {
15728
+ height: "100%",
15729
+ backgroundColor: "#22c55e",
15730
+ borderRadius: 2
15731
+ },
15732
+ listItemInFolder: {
15733
+ marginLeft: 12,
15734
+ borderLeftWidth: 2,
15735
+ borderLeftColor: "#3f3f46",
15736
+ paddingLeft: 12
15737
+ },
15738
+ listItemKeyWithStatus: {
15739
+ flexDirection: "row",
15740
+ alignItems: "center",
15741
+ flex: 1
15742
+ },
15743
+ statusBadge: {
15744
+ flexDirection: "row",
15745
+ alignItems: "center",
15746
+ paddingHorizontal: 6,
15747
+ paddingVertical: 2,
15748
+ borderRadius: 4,
15749
+ marginLeft: 8
15750
+ },
15751
+ statusBadgeIcon: {
15752
+ fontSize: 10,
15753
+ marginRight: 4
15754
+ },
15755
+ statusBadgeText: {
15756
+ fontSize: 10,
15757
+ fontWeight: "600"
15758
+ },
15759
+ // Skip button styles
15760
+ skipButton: {
15761
+ flex: 1,
15762
+ backgroundColor: "#eab308",
15763
+ paddingVertical: 14,
15764
+ borderRadius: 12,
15765
+ alignItems: "center",
15766
+ marginHorizontal: 4
15767
+ },
15768
+ skipButtonText: {
15769
+ fontSize: 15,
15770
+ fontWeight: "600",
15771
+ color: "#18181b"
15772
+ },
15773
+ // Skip modal styles
15774
+ skipModalOverlay: {
15775
+ flex: 1,
15776
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
15777
+ justifyContent: "center",
15778
+ alignItems: "center",
15779
+ padding: 20
15780
+ },
15781
+ skipModalContent: {
15782
+ backgroundColor: "#18181b",
15783
+ borderRadius: 16,
15784
+ padding: 20,
15785
+ width: "100%",
15786
+ maxWidth: 340,
15787
+ borderWidth: 1,
15788
+ borderColor: "#3f3f46"
15789
+ },
15790
+ skipModalTitle: {
15791
+ fontSize: 18,
15792
+ fontWeight: "600",
15793
+ color: "#fafafa",
15794
+ marginBottom: 4
15795
+ },
15796
+ skipModalSubtitle: {
15797
+ fontSize: 14,
15798
+ color: "#71717a",
15799
+ marginBottom: 16
15800
+ },
15801
+ skipReasonOptions: {
15802
+ marginBottom: 16
15803
+ },
15804
+ skipReasonOption: {
15805
+ backgroundColor: "#27272a",
15806
+ padding: 12,
15807
+ borderRadius: 8,
15808
+ marginBottom: 8,
15809
+ borderWidth: 2,
15810
+ borderColor: "transparent"
15811
+ },
15812
+ skipReasonOptionSelected: {
15813
+ borderColor: "#eab308",
15814
+ backgroundColor: "#422006"
15815
+ },
15816
+ skipReasonLabel: {
15817
+ fontSize: 14,
15818
+ fontWeight: "600",
15819
+ color: "#fafafa",
15820
+ marginBottom: 2
15821
+ },
15822
+ skipReasonDesc: {
15823
+ fontSize: 12,
15824
+ color: "#71717a"
15825
+ },
15826
+ skipNotesInput: {
15827
+ backgroundColor: "#27272a",
15828
+ borderWidth: 1,
15829
+ borderColor: "#3f3f46",
15830
+ borderRadius: 8,
15831
+ padding: 12,
15832
+ fontSize: 14,
15833
+ color: "#fafafa",
15834
+ minHeight: 60,
15835
+ textAlignVertical: "top",
15836
+ marginBottom: 16
15837
+ },
15838
+ skipModalActions: {
15839
+ flexDirection: "row",
15840
+ gap: 8
15841
+ },
15842
+ skipModalCancel: {
15843
+ flex: 1,
15844
+ backgroundColor: "#3f3f46",
15845
+ paddingVertical: 12,
15846
+ borderRadius: 8,
15847
+ alignItems: "center"
15848
+ },
15849
+ skipModalCancelText: {
15850
+ fontSize: 14,
15851
+ fontWeight: "600",
15852
+ color: "#e4e4e7"
15853
+ },
15854
+ skipModalConfirm: {
15855
+ flex: 1,
15856
+ backgroundColor: "#eab308",
15857
+ paddingVertical: 12,
15858
+ borderRadius: 8,
15859
+ alignItems: "center"
15860
+ },
15861
+ skipModalConfirmDisabled: {
15862
+ backgroundColor: "#713f12"
15863
+ },
15864
+ skipModalConfirmText: {
15865
+ fontSize: 14,
15866
+ fontWeight: "600",
15867
+ color: "#18181b"
15868
+ },
15869
+ // Detail progress bar styles
15870
+ detailProgressContainer: {
15871
+ backgroundColor: "#27272a",
15872
+ padding: 12,
15873
+ borderRadius: 8,
15874
+ marginTop: 16,
15875
+ marginBottom: 8
15876
+ },
15877
+ detailProgressText: {
15878
+ fontSize: 12,
15879
+ color: "#a1a1aa",
15880
+ marginBottom: 8
15881
+ },
15882
+ detailProgressBar: {
15883
+ height: 4,
15884
+ backgroundColor: "#3f3f46",
15885
+ borderRadius: 2
15886
+ },
15887
+ detailProgressFill: {
15888
+ height: "100%",
15889
+ backgroundColor: "#22c55e",
15890
+ borderRadius: 2
15891
+ }
15892
+ });
15893
+ var exploreStyles = import_react_native2.StyleSheet.create({
15894
+ formGroup: {
15895
+ marginBottom: 12
15896
+ },
15897
+ label: {
15898
+ fontSize: 12,
15899
+ fontWeight: "500",
15900
+ color: "#d4d4d8",
15901
+ marginBottom: 6
15902
+ },
15903
+ input: {
15904
+ backgroundColor: "#27272a",
15905
+ borderRadius: 8,
15906
+ paddingHorizontal: 12,
15907
+ paddingVertical: 10,
15908
+ fontSize: 14,
15909
+ color: "#fafafa",
15910
+ borderWidth: 1,
15911
+ borderColor: "#3f3f46"
15912
+ },
15913
+ platformRow: {
15914
+ flexDirection: "row",
15915
+ gap: 8
15916
+ },
15917
+ platformButton: {
15918
+ flex: 1,
15919
+ paddingVertical: 10,
15920
+ paddingHorizontal: 8,
15921
+ borderRadius: 8,
15922
+ backgroundColor: "#27272a",
15923
+ borderWidth: 2,
15924
+ borderColor: "transparent",
15925
+ alignItems: "center"
15926
+ },
15927
+ platformButtonActive: {
15928
+ backgroundColor: "#172554",
15929
+ borderColor: "#3B82F6"
15930
+ },
15931
+ platformButtonText: {
15932
+ fontSize: 12,
15933
+ fontWeight: "500",
15934
+ color: "#a1a1aa"
15935
+ },
15936
+ platformButtonTextActive: {
15937
+ color: "#93c5fd"
15938
+ },
15939
+ startButton: {
15940
+ backgroundColor: "#16a34a",
15941
+ borderRadius: 8,
15942
+ paddingVertical: 14,
15943
+ alignItems: "center",
15944
+ marginTop: 4
15945
+ },
15946
+ startButtonText: {
15947
+ color: "#fff",
15948
+ fontSize: 14,
15949
+ fontWeight: "600"
15950
+ },
15951
+ buttonRow: {
15952
+ flexDirection: "row",
15953
+ gap: 8
15954
+ },
15955
+ cancelButton: {
15956
+ flex: 1,
15957
+ backgroundColor: "#3f3f46",
15958
+ borderRadius: 8,
15959
+ paddingVertical: 10,
15960
+ alignItems: "center"
15961
+ },
15962
+ cancelButtonText: {
15963
+ color: "#d4d4d8",
15964
+ fontSize: 14,
15965
+ fontWeight: "500"
15966
+ },
15967
+ endButton: {
15968
+ flex: 1,
15969
+ backgroundColor: "#dc2626",
15970
+ borderRadius: 8,
15971
+ paddingVertical: 10,
15972
+ alignItems: "center"
15973
+ },
15974
+ endButtonText: {
15975
+ color: "#fff",
15976
+ fontSize: 14,
15977
+ fontWeight: "500"
15978
+ },
15979
+ findingHeader: {
15980
+ flexDirection: "row",
15981
+ justifyContent: "space-between",
15982
+ alignItems: "center",
15983
+ marginBottom: 12
15984
+ },
15985
+ findingHeaderTitle: {
15986
+ fontSize: 14,
15987
+ fontWeight: "600",
15988
+ color: "#fafafa"
15989
+ },
15990
+ findingHeaderClose: {
15991
+ fontSize: 16,
15992
+ color: "#71717a"
15993
+ },
15994
+ findingTypeRow: {
15995
+ flexDirection: "row",
15996
+ gap: 4,
15997
+ marginBottom: 12
15998
+ },
15999
+ findingTypeButton: {
16000
+ flex: 1,
16001
+ paddingVertical: 8,
16002
+ paddingHorizontal: 4,
16003
+ borderRadius: 6,
16004
+ backgroundColor: "#3f3f46",
16005
+ alignItems: "center"
16006
+ },
16007
+ findingTypeButtonActive: {
16008
+ backgroundColor: "#1e3a5f",
16009
+ borderWidth: 2,
16010
+ borderColor: "#3B82F6"
16011
+ },
16012
+ findingTypeButtonText: {
16013
+ fontSize: 11,
16014
+ fontWeight: "500",
16015
+ color: "#a1a1aa"
16016
+ },
16017
+ findingTypeButtonTextActive: {
16018
+ color: "#93c5fd"
16019
+ },
16020
+ severityRow: {
16021
+ flexDirection: "row",
16022
+ gap: 4
16023
+ },
16024
+ severityButton: {
16025
+ flex: 1,
16026
+ paddingVertical: 6,
16027
+ borderRadius: 6,
16028
+ backgroundColor: "#3f3f46",
16029
+ alignItems: "center"
16030
+ },
16031
+ severityCritical: {
16032
+ backgroundColor: "#dc2626"
16033
+ },
16034
+ severityHigh: {
16035
+ backgroundColor: "#f97316"
16036
+ },
16037
+ severityMedium: {
16038
+ backgroundColor: "#eab308"
16039
+ },
16040
+ severityLow: {
16041
+ backgroundColor: "#3f3f46",
16042
+ borderWidth: 1,
16043
+ borderColor: "#71717a"
16044
+ },
16045
+ severityButtonText: {
16046
+ fontSize: 11,
16047
+ fontWeight: "500",
16048
+ color: "#a1a1aa",
16049
+ textTransform: "capitalize"
16050
+ },
16051
+ severityButtonTextActive: {
16052
+ color: "#fff"
16053
+ },
16054
+ addFindingButton: {
16055
+ backgroundColor: "#3B82F6",
16056
+ borderRadius: 8,
16057
+ paddingVertical: 10,
16058
+ alignItems: "center"
16059
+ },
16060
+ addFindingButtonText: {
16061
+ color: "#fff",
16062
+ fontSize: 14,
16063
+ fontWeight: "500"
16064
+ },
16065
+ sessionBanner: {
16066
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16067
+ borderRadius: 12,
16068
+ padding: 12,
16069
+ marginBottom: 12,
16070
+ borderWidth: 1,
16071
+ borderColor: "#166534"
16072
+ },
16073
+ sessionBannerRow: {
16074
+ flexDirection: "row",
16075
+ justifyContent: "space-between",
16076
+ alignItems: "center"
16077
+ },
16078
+ sessionBannerLeft: {
16079
+ flexDirection: "row",
16080
+ alignItems: "center",
16081
+ gap: 8
16082
+ },
16083
+ sessionDotLarge: {
16084
+ width: 8,
16085
+ height: 8,
16086
+ borderRadius: 4,
16087
+ backgroundColor: "#22c55e"
16088
+ },
16089
+ sessionBannerLabel: {
16090
+ fontSize: 14,
16091
+ fontWeight: "500",
16092
+ color: "#86efac"
16093
+ },
16094
+ sessionTimer: {
16095
+ fontSize: 20,
16096
+ fontWeight: "600",
16097
+ color: "#4ade80",
16098
+ fontVariant: ["tabular-nums"]
16099
+ },
16100
+ sessionFocus: {
16101
+ fontSize: 12,
16102
+ color: "#4ade80",
16103
+ marginTop: 4
16104
+ },
16105
+ addButton: {
16106
+ backgroundColor: "#3B82F6",
16107
+ borderRadius: 8,
16108
+ paddingVertical: 14,
16109
+ alignItems: "center",
16110
+ marginBottom: 12
16111
+ },
16112
+ addButtonText: {
16113
+ color: "#fff",
16114
+ fontSize: 14,
16115
+ fontWeight: "600"
16116
+ },
16117
+ findingsSection: {
16118
+ marginBottom: 12
16119
+ },
16120
+ findingsLabel: {
16121
+ fontSize: 12,
16122
+ fontWeight: "500",
16123
+ color: "#71717a",
16124
+ marginBottom: 8
16125
+ },
16126
+ findingsEmpty: {
16127
+ backgroundColor: "#27272a",
16128
+ borderRadius: 8,
16129
+ paddingVertical: 16,
16130
+ alignItems: "center"
16131
+ },
16132
+ findingsEmptyText: {
16133
+ fontSize: 12,
16134
+ color: "#71717a"
16135
+ },
16136
+ findingCard: {
16137
+ flexDirection: "row",
16138
+ alignItems: "flex-start",
16139
+ padding: 8,
16140
+ borderRadius: 8,
16141
+ marginBottom: 6,
16142
+ borderWidth: 1,
16143
+ gap: 8
16144
+ },
16145
+ findingCardBug: {
16146
+ backgroundColor: "rgba(220, 38, 38, 0.1)",
16147
+ borderColor: "#991b1b"
16148
+ },
16149
+ findingCardConcern: {
16150
+ backgroundColor: "rgba(249, 115, 22, 0.1)",
16151
+ borderColor: "#9a3412"
16152
+ },
16153
+ findingCardSuggestion: {
16154
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16155
+ borderColor: "#1e40af"
16156
+ },
16157
+ findingCardQuestion: {
16158
+ backgroundColor: "rgba(139, 92, 246, 0.1)",
16159
+ borderColor: "#5b21b6"
16160
+ },
16161
+ findingCardIcon: {
16162
+ fontSize: 14
16163
+ },
16164
+ findingCardTitle: {
16165
+ fontSize: 12,
16166
+ fontWeight: "500",
16167
+ color: "#fafafa"
16168
+ },
16169
+ findingCardSeverity: {
16170
+ fontSize: 10,
16171
+ fontWeight: "500",
16172
+ marginTop: 2,
16173
+ textTransform: "capitalize"
16174
+ },
16175
+ endSessionButton: {
16176
+ backgroundColor: "#3f3f46",
16177
+ borderRadius: 8,
16178
+ paddingVertical: 10,
16179
+ alignItems: "center"
16180
+ },
16181
+ endSessionButtonText: {
16182
+ color: "#d4d4d8",
16183
+ fontSize: 14,
16184
+ fontWeight: "500"
16185
+ }
16186
+ });
16187
+ var feedbackStyles = import_react_native2.StyleSheet.create({
16188
+ container: {
16189
+ padding: 4
16190
+ },
16191
+ statusText: {
16192
+ fontSize: 16,
16193
+ fontWeight: "600",
16194
+ marginTop: 4
16195
+ },
16196
+ infoBox: {
16197
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16198
+ borderRadius: 8,
16199
+ padding: 12,
16200
+ marginBottom: 16,
16201
+ borderWidth: 1,
16202
+ borderColor: "#1e3a5f"
16203
+ },
16204
+ infoTitle: {
16205
+ fontSize: 14,
16206
+ fontWeight: "500",
16207
+ color: "#93c5fd",
16208
+ marginBottom: 4
16209
+ },
16210
+ infoSubtitle: {
16211
+ fontSize: 12,
16212
+ color: "#60a5fa"
16213
+ },
16214
+ ratingSection: {
16215
+ alignItems: "center",
16216
+ marginBottom: 16
16217
+ },
16218
+ ratingLabel: {
16219
+ fontSize: 12,
16220
+ fontWeight: "500",
16221
+ color: "#a1a1aa",
16222
+ marginBottom: 8
16223
+ },
16224
+ starsRow: {
16225
+ flexDirection: "row",
16226
+ gap: 4
16227
+ },
16228
+ star: {
16229
+ fontSize: 28
16230
+ },
16231
+ starActive: {
16232
+ color: "#facc15"
16233
+ },
16234
+ starInactive: {
16235
+ color: "#3f3f46"
16236
+ },
16237
+ ratingDesc: {
16238
+ fontSize: 12,
16239
+ color: "#71717a",
16240
+ marginTop: 4
16241
+ },
16242
+ flagsSection: {
16243
+ marginBottom: 12
16244
+ },
16245
+ flagsGrid: {
16246
+ flexDirection: "row",
16247
+ flexWrap: "wrap",
16248
+ gap: 8
16249
+ },
16250
+ flagButton: {
16251
+ paddingHorizontal: 10,
16252
+ paddingVertical: 6,
16253
+ borderRadius: 6,
16254
+ backgroundColor: "#27272a",
16255
+ borderWidth: 1,
16256
+ borderColor: "#3f3f46"
16257
+ },
16258
+ flagButtonActive: {
16259
+ backgroundColor: "#1e3a5f",
16260
+ borderColor: "#3B82F6"
16261
+ },
16262
+ flagButtonText: {
16263
+ fontSize: 12,
16264
+ fontWeight: "500",
16265
+ color: "#a1a1aa"
16266
+ },
16267
+ flagButtonTextActive: {
16268
+ color: "#93c5fd"
16269
+ },
16270
+ noteInput: {
16271
+ backgroundColor: "#27272a",
16272
+ borderRadius: 8,
16273
+ paddingHorizontal: 12,
16274
+ paddingVertical: 10,
16275
+ fontSize: 14,
16276
+ color: "#fafafa",
16277
+ borderWidth: 1,
16278
+ borderColor: "#3f3f46",
16279
+ minHeight: 60
16280
+ },
16281
+ buttonRow: {
16282
+ flexDirection: "row",
16283
+ gap: 8
16284
+ },
16285
+ skipButton: {
16286
+ flex: 1,
16287
+ paddingVertical: 10,
16288
+ backgroundColor: "#3f3f46",
16289
+ borderRadius: 8,
16290
+ alignItems: "center"
16291
+ },
16292
+ skipButtonText: {
16293
+ color: "#a1a1aa",
16294
+ fontSize: 14,
16295
+ fontWeight: "500"
16296
+ },
16297
+ submitButton: {
16298
+ flex: 1,
16299
+ paddingVertical: 10,
16300
+ backgroundColor: "#3B82F6",
16301
+ borderRadius: 8,
16302
+ alignItems: "center"
16303
+ },
16304
+ submitButtonText: {
16305
+ color: "#fff",
16306
+ fontSize: 14,
16307
+ fontWeight: "500"
16308
+ }
16309
+ });
16310
+ var timerStyles = import_react_native2.StyleSheet.create({
16311
+ container: {
16312
+ flexDirection: "row",
16313
+ alignItems: "center",
16314
+ gap: 6,
16315
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16316
+ paddingHorizontal: 8,
16317
+ paddingVertical: 4,
16318
+ borderRadius: 6,
16319
+ marginBottom: 8,
16320
+ alignSelf: "flex-start"
16321
+ },
16322
+ dot: {
16323
+ width: 6,
16324
+ height: 6,
16325
+ borderRadius: 3,
16326
+ backgroundColor: "#22c55e"
16327
+ },
16328
+ label: {
16329
+ fontSize: 12,
16330
+ fontWeight: "500",
16331
+ color: "#4ade80"
16332
+ },
16333
+ time: {
16334
+ fontSize: 12,
16335
+ fontWeight: "600",
16336
+ color: "#4ade80",
16337
+ fontVariant: ["tabular-nums"]
14356
16338
  }
14357
16339
  });
14358
16340
  // Annotate the CommonJS export names for ESM import in node: