@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.mjs CHANGED
@@ -11411,7 +11411,16 @@ var BugBearClient = class {
11411
11411
  */
11412
11412
  async submitReport(report) {
11413
11413
  try {
11414
+ const validationError = this.validateReport(report);
11415
+ if (validationError) {
11416
+ return { success: false, error: validationError };
11417
+ }
11414
11418
  const userInfo = await this.getCurrentUserInfo();
11419
+ const rateLimitId = userInfo?.email || this.config.projectId;
11420
+ const rateLimit = await this.checkRateLimit(rateLimitId, "report_submit");
11421
+ if (!rateLimit.allowed) {
11422
+ return { success: false, error: rateLimit.error };
11423
+ }
11415
11424
  if (!userInfo) {
11416
11425
  console.error("BugBear: No user info available, cannot submit report");
11417
11426
  return { success: false, error: "User not authenticated" };
@@ -11462,6 +11471,10 @@ var BugBearClient = class {
11462
11471
  const { data, error } = await this.supabase.from("test_assignments").select(`
11463
11472
  id,
11464
11473
  status,
11474
+ started_at,
11475
+ skip_reason,
11476
+ is_verification,
11477
+ original_report_id,
11465
11478
  test_case:test_cases(
11466
11479
  id,
11467
11480
  title,
@@ -11479,6 +11492,12 @@ var BugBearClient = class {
11479
11492
  test_template,
11480
11493
  rubric_mode,
11481
11494
  description
11495
+ ),
11496
+ group:test_groups(
11497
+ id,
11498
+ name,
11499
+ description,
11500
+ sort_order
11482
11501
  )
11483
11502
  )
11484
11503
  `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).in("status", ["pending", "in_progress"]).order("created_at", { ascending: true });
@@ -11489,6 +11508,10 @@ var BugBearClient = class {
11489
11508
  return (data || []).map((item) => ({
11490
11509
  id: item.id,
11491
11510
  status: item.status,
11511
+ startedAt: item.started_at,
11512
+ skipReason: item.skip_reason,
11513
+ isVerification: item.is_verification || false,
11514
+ originalReportId: item.original_report_id,
11492
11515
  testCase: {
11493
11516
  id: item.test_case.id,
11494
11517
  title: item.test_case.title,
@@ -11506,6 +11529,12 @@ var BugBearClient = class {
11506
11529
  testTemplate: item.test_case.track.test_template,
11507
11530
  rubricMode: item.test_case.track.rubric_mode || "pass_fail",
11508
11531
  description: item.test_case.track.description
11532
+ } : void 0,
11533
+ group: item.test_case.group ? {
11534
+ id: item.test_case.group.id,
11535
+ name: item.test_case.group.name,
11536
+ description: item.test_case.group.description,
11537
+ sortOrder: item.test_case.group.sort_order
11509
11538
  } : void 0
11510
11539
  }
11511
11540
  }));
@@ -11514,47 +11543,456 @@ var BugBearClient = class {
11514
11543
  return [];
11515
11544
  }
11516
11545
  }
11546
+ /**
11547
+ * Get assignment by ID with time tracking fields
11548
+ */
11549
+ async getAssignment(assignmentId) {
11550
+ try {
11551
+ const { data, error } = await this.supabase.from("test_assignments").select(`
11552
+ id,
11553
+ status,
11554
+ started_at,
11555
+ completed_at,
11556
+ duration_seconds,
11557
+ test_case:test_cases(
11558
+ id,
11559
+ title,
11560
+ test_key,
11561
+ description,
11562
+ steps,
11563
+ expected_result,
11564
+ priority,
11565
+ target_route,
11566
+ track:qa_tracks(
11567
+ id,
11568
+ name,
11569
+ icon,
11570
+ color,
11571
+ test_template,
11572
+ rubric_mode,
11573
+ description
11574
+ )
11575
+ )
11576
+ `).eq("id", assignmentId).single();
11577
+ if (error || !data) return null;
11578
+ const testCase = data.test_case;
11579
+ if (!testCase) {
11580
+ console.error("BugBear: Assignment returned without test_case");
11581
+ return null;
11582
+ }
11583
+ const track = testCase.track;
11584
+ return {
11585
+ id: data.id,
11586
+ status: data.status,
11587
+ startedAt: data.started_at,
11588
+ durationSeconds: data.duration_seconds,
11589
+ testCase: {
11590
+ id: testCase.id,
11591
+ title: testCase.title,
11592
+ testKey: testCase.test_key,
11593
+ description: testCase.description,
11594
+ steps: testCase.steps,
11595
+ expectedResult: testCase.expected_result,
11596
+ priority: testCase.priority,
11597
+ targetRoute: testCase.target_route,
11598
+ track: track ? {
11599
+ id: track.id,
11600
+ name: track.name,
11601
+ icon: track.icon,
11602
+ color: track.color,
11603
+ testTemplate: track.test_template,
11604
+ rubricMode: track.rubric_mode || "pass_fail",
11605
+ description: track.description
11606
+ } : void 0
11607
+ }
11608
+ };
11609
+ } catch (err) {
11610
+ console.error("BugBear: Error fetching assignment", err);
11611
+ return null;
11612
+ }
11613
+ }
11614
+ /**
11615
+ * Update assignment status with automatic time tracking
11616
+ * - Sets started_at when status changes to 'in_progress'
11617
+ * - Calculates duration_seconds when status changes to 'passed'/'failed'/'blocked'
11618
+ * - Optionally include feedback when completing a test
11619
+ */
11620
+ async updateAssignmentStatus(assignmentId, status, options) {
11621
+ try {
11622
+ const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at").eq("id", assignmentId).single();
11623
+ if (fetchError || !currentAssignment) {
11624
+ return { success: false, error: "Assignment not found" };
11625
+ }
11626
+ const updateData = { status };
11627
+ let durationSeconds;
11628
+ if (status === "in_progress" && currentAssignment.status !== "in_progress") {
11629
+ updateData.started_at = (/* @__PURE__ */ new Date()).toISOString();
11630
+ }
11631
+ if (["passed", "failed", "blocked"].includes(status)) {
11632
+ updateData.completed_at = (/* @__PURE__ */ new Date()).toISOString();
11633
+ if (currentAssignment.started_at) {
11634
+ const startedAt = new Date(currentAssignment.started_at);
11635
+ const completedAt = /* @__PURE__ */ new Date();
11636
+ durationSeconds = Math.round((completedAt.getTime() - startedAt.getTime()) / 1e3);
11637
+ updateData.duration_seconds = durationSeconds;
11638
+ }
11639
+ }
11640
+ if (options?.notes) {
11641
+ updateData.notes = options.notes;
11642
+ }
11643
+ if (options?.testResult) {
11644
+ updateData.test_result = options.testResult;
11645
+ }
11646
+ const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11647
+ if (error) {
11648
+ console.error("BugBear: Failed to update assignment status", error);
11649
+ return { success: false, error: error.message };
11650
+ }
11651
+ if (options?.feedback && ["passed", "failed", "blocked"].includes(status)) {
11652
+ const { data: assignmentData, error: fetchError2 } = await this.supabase.from("test_assignments").select("test_case_id").eq("id", assignmentId).single();
11653
+ if (fetchError2) {
11654
+ console.error("BugBear: Failed to fetch assignment for feedback", fetchError2);
11655
+ } else if (assignmentData?.test_case_id) {
11656
+ const feedbackResult = await this.submitTestFeedback({
11657
+ testCaseId: assignmentData.test_case_id,
11658
+ assignmentId,
11659
+ feedback: options.feedback,
11660
+ timeToCompleteSeconds: durationSeconds
11661
+ });
11662
+ if (!feedbackResult.success) {
11663
+ console.error("BugBear: Failed to submit feedback", feedbackResult.error);
11664
+ }
11665
+ }
11666
+ }
11667
+ return { success: true, durationSeconds };
11668
+ } catch (err) {
11669
+ const message = err instanceof Error ? err.message : "Unknown error";
11670
+ console.error("BugBear: Error updating assignment status", err);
11671
+ return { success: false, error: message };
11672
+ }
11673
+ }
11674
+ /**
11675
+ * Skip a test assignment with a required reason
11676
+ * Marks the assignment as 'skipped' and records why it was skipped
11677
+ */
11678
+ async skipAssignment(assignmentId, reason, notes) {
11679
+ try {
11680
+ const updateData = {
11681
+ status: "skipped",
11682
+ skip_reason: reason,
11683
+ completed_at: (/* @__PURE__ */ new Date()).toISOString()
11684
+ };
11685
+ if (notes) {
11686
+ updateData.notes = notes;
11687
+ }
11688
+ const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11689
+ if (error) {
11690
+ console.error("BugBear: Failed to skip assignment", error);
11691
+ return { success: false, error: error.message };
11692
+ }
11693
+ return { success: true };
11694
+ } catch (err) {
11695
+ const message = err instanceof Error ? err.message : "Unknown error";
11696
+ console.error("BugBear: Error skipping assignment", err);
11697
+ return { success: false, error: message };
11698
+ }
11699
+ }
11700
+ /**
11701
+ * Submit feedback on a test case to help improve test quality
11702
+ * This empowers testers to shape better tests over time
11703
+ */
11704
+ async submitTestFeedback(options) {
11705
+ try {
11706
+ const testerInfo = await this.getTesterInfo();
11707
+ if (!testerInfo) {
11708
+ return { success: false, error: "Not authenticated as tester" };
11709
+ }
11710
+ const { testCaseId, assignmentId, feedback, timeToCompleteSeconds } = options;
11711
+ if (feedback.rating < 1 || feedback.rating > 5) {
11712
+ return { success: false, error: "Rating must be between 1 and 5" };
11713
+ }
11714
+ const { error: feedbackError } = await this.supabase.from("test_feedback").insert({
11715
+ project_id: this.config.projectId,
11716
+ test_case_id: testCaseId,
11717
+ assignment_id: assignmentId || null,
11718
+ tester_id: testerInfo.id,
11719
+ rating: feedback.rating,
11720
+ clarity_rating: feedback.clarityRating || null,
11721
+ steps_rating: feedback.stepsRating || null,
11722
+ relevance_rating: feedback.relevanceRating || null,
11723
+ feedback_note: feedback.feedbackNote?.trim() || null,
11724
+ suggested_improvement: feedback.suggestedImprovement?.trim() || null,
11725
+ is_outdated: feedback.isOutdated || false,
11726
+ needs_more_detail: feedback.needsMoreDetail || false,
11727
+ steps_unclear: feedback.stepsUnclear || false,
11728
+ expected_result_unclear: feedback.expectedResultUnclear || false,
11729
+ platform: this.getDeviceInfo().platform,
11730
+ time_to_complete_seconds: timeToCompleteSeconds || null
11731
+ });
11732
+ if (feedbackError) {
11733
+ console.error("BugBear: Failed to submit feedback", feedbackError);
11734
+ return { success: false, error: feedbackError.message };
11735
+ }
11736
+ if (assignmentId) {
11737
+ const { error: assignmentError } = await this.supabase.from("test_assignments").update({
11738
+ feedback_rating: feedback.rating,
11739
+ feedback_note: feedback.feedbackNote?.trim() || null,
11740
+ feedback_submitted_at: (/* @__PURE__ */ new Date()).toISOString()
11741
+ }).eq("id", assignmentId);
11742
+ if (assignmentError) {
11743
+ console.error("BugBear: Failed to update assignment feedback fields", assignmentError);
11744
+ }
11745
+ }
11746
+ return { success: true };
11747
+ } catch (err) {
11748
+ const message = err instanceof Error ? err.message : "Unknown error";
11749
+ console.error("BugBear: Error submitting feedback", err);
11750
+ return { success: false, error: message };
11751
+ }
11752
+ }
11753
+ /**
11754
+ * Get the currently active (in_progress) assignment for the tester
11755
+ */
11756
+ async getActiveAssignment() {
11757
+ try {
11758
+ const testerInfo = await this.getTesterInfo();
11759
+ if (!testerInfo) return null;
11760
+ const { data, error } = await this.supabase.from("test_assignments").select(`
11761
+ id,
11762
+ status,
11763
+ started_at,
11764
+ test_case:test_cases(
11765
+ id,
11766
+ title,
11767
+ test_key,
11768
+ description,
11769
+ steps,
11770
+ expected_result,
11771
+ priority,
11772
+ target_route,
11773
+ track:qa_tracks(
11774
+ id,
11775
+ name,
11776
+ icon,
11777
+ color,
11778
+ test_template,
11779
+ rubric_mode,
11780
+ description
11781
+ )
11782
+ )
11783
+ `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).eq("status", "in_progress").order("started_at", { ascending: false }).limit(1).maybeSingle();
11784
+ if (error || !data) return null;
11785
+ const testCase = data.test_case;
11786
+ if (!testCase) {
11787
+ console.error("BugBear: Active assignment returned without test_case");
11788
+ return null;
11789
+ }
11790
+ const track = testCase.track;
11791
+ return {
11792
+ id: data.id,
11793
+ status: data.status,
11794
+ startedAt: data.started_at,
11795
+ testCase: {
11796
+ id: testCase.id,
11797
+ title: testCase.title,
11798
+ testKey: testCase.test_key,
11799
+ description: testCase.description,
11800
+ steps: testCase.steps,
11801
+ expectedResult: testCase.expected_result,
11802
+ priority: testCase.priority,
11803
+ targetRoute: testCase.target_route,
11804
+ track: track ? {
11805
+ id: track.id,
11806
+ name: track.name,
11807
+ icon: track.icon,
11808
+ color: track.color,
11809
+ testTemplate: track.test_template,
11810
+ rubricMode: track.rubric_mode || "pass_fail",
11811
+ description: track.description
11812
+ } : void 0
11813
+ }
11814
+ };
11815
+ } catch (err) {
11816
+ console.error("BugBear: Error fetching active assignment", err);
11817
+ return null;
11818
+ }
11819
+ }
11517
11820
  /**
11518
11821
  * Get current tester info
11519
11822
  * Looks up tester by email from the host app's authenticated user
11823
+ * Checks both primary email AND additional_emails array
11824
+ * Uses parameterized RPC function to prevent SQL injection
11520
11825
  */
11521
11826
  async getTesterInfo() {
11522
11827
  try {
11523
11828
  const userInfo = await this.getCurrentUserInfo();
11524
- if (!userInfo) return null;
11525
- const { data, error } = await this.supabase.from("testers").select("*").eq("project_id", this.config.projectId).eq("email", userInfo.email).eq("status", "active").single();
11829
+ if (!userInfo?.email) return null;
11830
+ if (!this.isValidEmail(userInfo.email)) {
11831
+ console.warn("BugBear: Invalid email format");
11832
+ return null;
11833
+ }
11834
+ const { data, error } = await this.supabase.rpc("lookup_tester_by_email", {
11835
+ p_project_id: this.config.projectId,
11836
+ p_email: userInfo.email
11837
+ }).maybeSingle();
11526
11838
  if (error || !data) return null;
11839
+ const tester = data;
11527
11840
  return {
11528
- id: data.id,
11529
- name: data.name,
11530
- email: data.email,
11531
- additionalEmails: data.additional_emails || [],
11532
- avatarUrl: data.avatar_url || void 0,
11533
- platforms: data.platforms || [],
11534
- assignedTests: data.assigned_count || 0,
11535
- completedTests: data.completed_count || 0
11841
+ id: tester.id,
11842
+ name: tester.name,
11843
+ email: tester.email,
11844
+ additionalEmails: tester.additional_emails || [],
11845
+ avatarUrl: tester.avatar_url || void 0,
11846
+ platforms: tester.platforms || [],
11847
+ assignedTests: tester.assigned_count || 0,
11848
+ completedTests: tester.completed_count || 0
11536
11849
  };
11537
11850
  } catch (err) {
11538
11851
  console.error("BugBear: getTesterInfo error", err);
11539
11852
  return null;
11540
11853
  }
11541
11854
  }
11855
+ /**
11856
+ * Basic email format validation (defense in depth)
11857
+ */
11858
+ isValidEmail(email) {
11859
+ if (!email || email.length > 254) return false;
11860
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11861
+ return emailRegex.test(email);
11862
+ }
11863
+ /**
11864
+ * Validate report input before submission
11865
+ * Returns error message if invalid, null if valid
11866
+ */
11867
+ validateReport(report) {
11868
+ const validTypes = ["bug", "feedback", "suggestion", "test_pass", "test_fail"];
11869
+ if (report.type && !validTypes.includes(report.type)) {
11870
+ return `Invalid report type: ${report.type}. Must be one of: ${validTypes.join(", ")}`;
11871
+ }
11872
+ const validSeverities = ["critical", "high", "medium", "low"];
11873
+ if (report.severity && !validSeverities.includes(report.severity)) {
11874
+ return `Invalid severity: ${report.severity}. Must be one of: ${validSeverities.join(", ")}`;
11875
+ }
11876
+ if (report.title && report.title.length > 500) {
11877
+ return "Title must be 500 characters or less";
11878
+ }
11879
+ if (report.description && report.description.length > 1e4) {
11880
+ return "Description must be 10,000 characters or less";
11881
+ }
11882
+ if (report.screenshots && Array.isArray(report.screenshots)) {
11883
+ if (report.screenshots.length > 10) {
11884
+ return "Maximum 10 screenshots allowed";
11885
+ }
11886
+ for (const url of report.screenshots) {
11887
+ if (typeof url !== "string" || url.length > 2e3) {
11888
+ return "Invalid screenshot URL";
11889
+ }
11890
+ }
11891
+ }
11892
+ return null;
11893
+ }
11894
+ /**
11895
+ * Validate profile update input
11896
+ * Returns error message if invalid, null if valid
11897
+ */
11898
+ validateProfileUpdate(updates) {
11899
+ if (updates.name !== void 0) {
11900
+ if (typeof updates.name !== "string" || updates.name.length > 100) {
11901
+ return "Name must be 100 characters or less";
11902
+ }
11903
+ }
11904
+ if (updates.additionalEmails !== void 0) {
11905
+ if (!Array.isArray(updates.additionalEmails)) {
11906
+ return "Additional emails must be an array";
11907
+ }
11908
+ if (updates.additionalEmails.length > 5) {
11909
+ return "Maximum 5 additional emails allowed";
11910
+ }
11911
+ for (const email of updates.additionalEmails) {
11912
+ if (!this.isValidEmail(email)) {
11913
+ return `Invalid email format: ${email}`;
11914
+ }
11915
+ }
11916
+ }
11917
+ if (updates.avatarUrl !== void 0 && updates.avatarUrl !== null) {
11918
+ if (typeof updates.avatarUrl !== "string" || updates.avatarUrl.length > 2e3) {
11919
+ return "Invalid avatar URL";
11920
+ }
11921
+ }
11922
+ if (updates.platforms !== void 0) {
11923
+ if (!Array.isArray(updates.platforms)) {
11924
+ return "Platforms must be an array";
11925
+ }
11926
+ const validPlatforms = ["ios", "android", "web", "desktop", "other"];
11927
+ for (const platform of updates.platforms) {
11928
+ if (!validPlatforms.includes(platform)) {
11929
+ return `Invalid platform: ${platform}. Must be one of: ${validPlatforms.join(", ")}`;
11930
+ }
11931
+ }
11932
+ }
11933
+ return null;
11934
+ }
11935
+ /**
11936
+ * Check rate limit for an action
11937
+ * Returns { allowed: boolean, error?: string, remaining?: number }
11938
+ */
11939
+ async checkRateLimit(identifier, action) {
11940
+ try {
11941
+ const { data, error } = await this.supabase.rpc("check_rate_limit", {
11942
+ p_identifier: identifier,
11943
+ p_action: action,
11944
+ p_project_id: this.config.projectId
11945
+ });
11946
+ if (error) {
11947
+ console.warn("BugBear: Rate limit check failed, allowing request", error.message);
11948
+ return { allowed: true };
11949
+ }
11950
+ if (!data.allowed) {
11951
+ return {
11952
+ allowed: false,
11953
+ error: `Rate limit exceeded. Try again in ${Math.ceil((new Date(data.reset_at).getTime() - Date.now()) / 1e3)} seconds.`,
11954
+ remaining: 0,
11955
+ resetAt: data.reset_at
11956
+ };
11957
+ }
11958
+ return {
11959
+ allowed: true,
11960
+ remaining: data.remaining,
11961
+ resetAt: data.reset_at
11962
+ };
11963
+ } catch (err) {
11964
+ console.warn("BugBear: Rate limit check error", err);
11965
+ return { allowed: true };
11966
+ }
11967
+ }
11542
11968
  /**
11543
11969
  * Update tester profile
11544
11970
  * Allows testers to update their name, additional emails, avatar, and platforms
11545
11971
  */
11546
11972
  async updateTesterProfile(updates) {
11547
11973
  try {
11974
+ const validationError = this.validateProfileUpdate(updates);
11975
+ if (validationError) {
11976
+ return { success: false, error: validationError };
11977
+ }
11548
11978
  const userInfo = await this.getCurrentUserInfo();
11549
11979
  if (!userInfo) {
11550
11980
  return { success: false, error: "Not authenticated" };
11551
11981
  }
11982
+ const rateLimit = await this.checkRateLimit(userInfo.email, "profile_update");
11983
+ if (!rateLimit.allowed) {
11984
+ return { success: false, error: rateLimit.error };
11985
+ }
11986
+ const testerInfo = await this.getTesterInfo();
11987
+ if (!testerInfo) {
11988
+ return { success: false, error: "Not a registered tester" };
11989
+ }
11552
11990
  const updateData = {};
11553
11991
  if (updates.name !== void 0) updateData.name = updates.name;
11554
11992
  if (updates.additionalEmails !== void 0) updateData.additional_emails = updates.additionalEmails;
11555
11993
  if (updates.avatarUrl !== void 0) updateData.avatar_url = updates.avatarUrl;
11556
11994
  if (updates.platforms !== void 0) updateData.platforms = updates.platforms;
11557
- const { error } = await this.supabase.from("testers").update(updateData).eq("project_id", this.config.projectId).eq("email", userInfo.email);
11995
+ const { error } = await this.supabase.from("testers").update(updateData).eq("id", testerInfo.id);
11558
11996
  if (error) {
11559
11997
  console.error("BugBear: updateTesterProfile error", error);
11560
11998
  return { success: false, error: error.message };
@@ -11830,6 +12268,11 @@ var BugBearClient = class {
11830
12268
  console.error("BugBear: No tester info, cannot send message");
11831
12269
  return false;
11832
12270
  }
12271
+ const rateLimit = await this.checkRateLimit(testerInfo.email, "message_send");
12272
+ if (!rateLimit.allowed) {
12273
+ console.error("BugBear: Rate limit exceeded for messages");
12274
+ return false;
12275
+ }
11833
12276
  const { error } = await this.supabase.from("discussion_messages").insert({
11834
12277
  thread_id: threadId,
11835
12278
  sender_type: "tester",
@@ -11924,50 +12367,292 @@ var BugBearClient = class {
11924
12367
  return { success: false, error: message };
11925
12368
  }
11926
12369
  }
11927
- };
11928
- function createBugBear(config) {
11929
- return new BugBearClient(config);
11930
- }
11931
- var MAX_CONSOLE_LOGS = 50;
11932
- var MAX_NETWORK_REQUESTS = 20;
11933
- var ContextCaptureManager = class {
11934
- constructor() {
11935
- this.consoleLogs = [];
11936
- this.networkRequests = [];
11937
- this.originalConsole = {};
11938
- this.isCapturing = false;
12370
+ // ============================================
12371
+ // QA Sessions (Sprint 1)
12372
+ // ============================================
12373
+ /**
12374
+ * Start a new QA session for exploratory testing
12375
+ */
12376
+ async startSession(options = {}) {
12377
+ try {
12378
+ const testerInfo = await this.getTesterInfo();
12379
+ if (!testerInfo) {
12380
+ return { success: false, error: "Not authenticated as a tester" };
12381
+ }
12382
+ const activeSession = await this.getActiveSession();
12383
+ if (activeSession) {
12384
+ return { success: false, error: "You already have an active session. End it before starting a new one." };
12385
+ }
12386
+ const { data, error } = await this.supabase.rpc("start_qa_session", {
12387
+ p_project_id: this.config.projectId,
12388
+ p_tester_id: testerInfo.id,
12389
+ p_focus_area: options.focusArea || null,
12390
+ p_track: options.track || null,
12391
+ p_platform: options.platform || null
12392
+ });
12393
+ if (error) {
12394
+ console.error("BugBear: Failed to start session", error);
12395
+ return { success: false, error: error.message };
12396
+ }
12397
+ const session = await this.getSession(data);
12398
+ if (!session) {
12399
+ return { success: false, error: "Session created but could not be fetched" };
12400
+ }
12401
+ return { success: true, session };
12402
+ } catch (err) {
12403
+ const message = err instanceof Error ? err.message : "Unknown error";
12404
+ console.error("BugBear: Error starting session", err);
12405
+ return { success: false, error: message };
12406
+ }
11939
12407
  }
11940
12408
  /**
11941
- * Start capturing console logs and network requests
12409
+ * End the current QA session
11942
12410
  */
11943
- startCapture() {
11944
- if (this.isCapturing) return;
11945
- this.isCapturing = true;
11946
- this.captureConsole();
11947
- this.captureFetch();
12411
+ async endSession(sessionId, options = {}) {
12412
+ try {
12413
+ const { data, error } = await this.supabase.rpc("end_qa_session", {
12414
+ p_session_id: sessionId,
12415
+ p_notes: options.notes || null,
12416
+ p_routes_covered: options.routesCovered || null
12417
+ });
12418
+ if (error) {
12419
+ console.error("BugBear: Failed to end session", error);
12420
+ return { success: false, error: error.message };
12421
+ }
12422
+ const session = this.transformSession(data);
12423
+ return { success: true, session };
12424
+ } catch (err) {
12425
+ const message = err instanceof Error ? err.message : "Unknown error";
12426
+ console.error("BugBear: Error ending session", err);
12427
+ return { success: false, error: message };
12428
+ }
11948
12429
  }
11949
12430
  /**
11950
- * Stop capturing and restore original functions
12431
+ * Get the current active session for the tester
11951
12432
  */
11952
- stopCapture() {
11953
- if (!this.isCapturing) return;
11954
- this.isCapturing = false;
11955
- if (this.originalConsole.log) console.log = this.originalConsole.log;
11956
- if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
11957
- if (this.originalConsole.error) console.error = this.originalConsole.error;
11958
- if (this.originalConsole.info) console.info = this.originalConsole.info;
11959
- if (this.originalFetch && typeof window !== "undefined") {
11960
- window.fetch = this.originalFetch;
12433
+ async getActiveSession() {
12434
+ try {
12435
+ const testerInfo = await this.getTesterInfo();
12436
+ if (!testerInfo) return null;
12437
+ 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();
12438
+ if (error || !data) return null;
12439
+ return this.transformSession(data);
12440
+ } catch (err) {
12441
+ console.error("BugBear: Error fetching active session", err);
12442
+ return null;
11961
12443
  }
11962
12444
  }
11963
12445
  /**
11964
- * Get captured context for a bug report
12446
+ * Get a session by ID
11965
12447
  */
11966
- getEnhancedContext() {
11967
- return {
11968
- consoleLogs: [...this.consoleLogs],
11969
- networkRequests: [...this.networkRequests],
11970
- performanceMetrics: this.getPerformanceMetrics(),
12448
+ async getSession(sessionId) {
12449
+ try {
12450
+ const { data, error } = await this.supabase.from("qa_sessions").select("*").eq("id", sessionId).single();
12451
+ if (error || !data) return null;
12452
+ return this.transformSession(data);
12453
+ } catch (err) {
12454
+ console.error("BugBear: Error fetching session", err);
12455
+ return null;
12456
+ }
12457
+ }
12458
+ /**
12459
+ * Get session history for the tester
12460
+ */
12461
+ async getSessionHistory(limit = 10) {
12462
+ try {
12463
+ const testerInfo = await this.getTesterInfo();
12464
+ if (!testerInfo) return [];
12465
+ 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);
12466
+ if (error) {
12467
+ console.error("BugBear: Failed to fetch session history", error);
12468
+ return [];
12469
+ }
12470
+ return (data || []).map((s) => this.transformSession(s));
12471
+ } catch (err) {
12472
+ console.error("BugBear: Error fetching session history", err);
12473
+ return [];
12474
+ }
12475
+ }
12476
+ /**
12477
+ * Add a finding during a session
12478
+ */
12479
+ async addFinding(sessionId, options) {
12480
+ try {
12481
+ const { data, error } = await this.supabase.rpc("add_session_finding", {
12482
+ p_session_id: sessionId,
12483
+ p_type: options.type,
12484
+ p_title: options.title,
12485
+ p_description: options.description || null,
12486
+ p_severity: options.severity || "observation",
12487
+ p_route: options.route || null,
12488
+ p_screenshot_url: options.screenshotUrl || null,
12489
+ p_console_logs: options.consoleLogs || null,
12490
+ p_network_snapshot: options.networkSnapshot || null,
12491
+ p_device_info: options.deviceInfo || null,
12492
+ p_app_context: options.appContext || null
12493
+ });
12494
+ if (error) {
12495
+ console.error("BugBear: Failed to add finding", error);
12496
+ return { success: false, error: error.message };
12497
+ }
12498
+ const finding = this.transformFinding(data);
12499
+ return { success: true, finding };
12500
+ } catch (err) {
12501
+ const message = err instanceof Error ? err.message : "Unknown error";
12502
+ console.error("BugBear: Error adding finding", err);
12503
+ return { success: false, error: message };
12504
+ }
12505
+ }
12506
+ /**
12507
+ * Get findings for a session
12508
+ */
12509
+ async getSessionFindings(sessionId) {
12510
+ try {
12511
+ const { data, error } = await this.supabase.from("qa_findings").select("*").eq("session_id", sessionId).order("created_at", { ascending: true });
12512
+ if (error) {
12513
+ console.error("BugBear: Failed to fetch findings", error);
12514
+ return [];
12515
+ }
12516
+ return (data || []).map((f) => this.transformFinding(f));
12517
+ } catch (err) {
12518
+ console.error("BugBear: Error fetching findings", err);
12519
+ return [];
12520
+ }
12521
+ }
12522
+ /**
12523
+ * Convert a finding to a bug report
12524
+ */
12525
+ async convertFindingToBug(findingId) {
12526
+ try {
12527
+ const { data, error } = await this.supabase.rpc("convert_finding_to_bug", {
12528
+ p_finding_id: findingId
12529
+ });
12530
+ if (error) {
12531
+ console.error("BugBear: Failed to convert finding", error);
12532
+ return { success: false, error: error.message };
12533
+ }
12534
+ return { success: true, bugId: data };
12535
+ } catch (err) {
12536
+ const message = err instanceof Error ? err.message : "Unknown error";
12537
+ console.error("BugBear: Error converting finding", err);
12538
+ return { success: false, error: message };
12539
+ }
12540
+ }
12541
+ /**
12542
+ * Dismiss a finding
12543
+ */
12544
+ async dismissFinding(findingId, reason) {
12545
+ try {
12546
+ const { error } = await this.supabase.from("qa_findings").update({
12547
+ dismissed: true,
12548
+ dismissed_reason: reason || null,
12549
+ dismissed_at: (/* @__PURE__ */ new Date()).toISOString()
12550
+ }).eq("id", findingId);
12551
+ if (error) {
12552
+ console.error("BugBear: Failed to dismiss finding", error);
12553
+ return { success: false, error: error.message };
12554
+ }
12555
+ return { success: true };
12556
+ } catch (err) {
12557
+ const message = err instanceof Error ? err.message : "Unknown error";
12558
+ console.error("BugBear: Error dismissing finding", err);
12559
+ return { success: false, error: message };
12560
+ }
12561
+ }
12562
+ /**
12563
+ * Transform database session to QASession type
12564
+ */
12565
+ transformSession(data) {
12566
+ return {
12567
+ id: data.id,
12568
+ projectId: data.project_id,
12569
+ testerId: data.tester_id,
12570
+ focusArea: data.focus_area,
12571
+ track: data.track,
12572
+ platform: data.platform,
12573
+ startedAt: data.started_at,
12574
+ endedAt: data.ended_at,
12575
+ notes: data.notes,
12576
+ routesCovered: data.routes_covered || [],
12577
+ status: data.status,
12578
+ durationMinutes: data.duration_minutes,
12579
+ findingsCount: data.findings_count || 0,
12580
+ bugsFiled: data.bugs_filed || 0,
12581
+ createdAt: data.created_at,
12582
+ updatedAt: data.updated_at
12583
+ };
12584
+ }
12585
+ /**
12586
+ * Transform database finding to QAFinding type
12587
+ */
12588
+ transformFinding(data) {
12589
+ return {
12590
+ id: data.id,
12591
+ sessionId: data.session_id,
12592
+ projectId: data.project_id,
12593
+ type: data.type,
12594
+ severity: data.severity,
12595
+ title: data.title,
12596
+ description: data.description,
12597
+ route: data.route,
12598
+ screenshotUrl: data.screenshot_url,
12599
+ consoleLogs: data.console_logs,
12600
+ networkSnapshot: data.network_snapshot,
12601
+ deviceInfo: data.device_info,
12602
+ appContext: data.app_context,
12603
+ convertedToBugId: data.converted_to_bug_id,
12604
+ convertedToTestId: data.converted_to_test_id,
12605
+ dismissed: data.dismissed || false,
12606
+ dismissedReason: data.dismissed_reason,
12607
+ dismissedAt: data.dismissed_at,
12608
+ createdAt: data.created_at,
12609
+ updatedAt: data.updated_at
12610
+ };
12611
+ }
12612
+ };
12613
+ function createBugBear(config) {
12614
+ return new BugBearClient(config);
12615
+ }
12616
+ var MAX_CONSOLE_LOGS = 50;
12617
+ var MAX_NETWORK_REQUESTS = 20;
12618
+ var ContextCaptureManager = class {
12619
+ constructor() {
12620
+ this.consoleLogs = [];
12621
+ this.networkRequests = [];
12622
+ this.originalConsole = {};
12623
+ this.isCapturing = false;
12624
+ }
12625
+ /**
12626
+ * Start capturing console logs and network requests
12627
+ */
12628
+ startCapture() {
12629
+ if (this.isCapturing) return;
12630
+ this.isCapturing = true;
12631
+ this.captureConsole();
12632
+ this.captureFetch();
12633
+ }
12634
+ /**
12635
+ * Stop capturing and restore original functions
12636
+ */
12637
+ stopCapture() {
12638
+ if (!this.isCapturing) return;
12639
+ this.isCapturing = false;
12640
+ if (this.originalConsole.log) console.log = this.originalConsole.log;
12641
+ if (this.originalConsole.warn) console.warn = this.originalConsole.warn;
12642
+ if (this.originalConsole.error) console.error = this.originalConsole.error;
12643
+ if (this.originalConsole.info) console.info = this.originalConsole.info;
12644
+ if (this.originalFetch && typeof window !== "undefined") {
12645
+ window.fetch = this.originalFetch;
12646
+ }
12647
+ }
12648
+ /**
12649
+ * Get captured context for a bug report
12650
+ */
12651
+ getEnhancedContext() {
12652
+ return {
12653
+ consoleLogs: [...this.consoleLogs],
12654
+ networkRequests: [...this.networkRequests],
12655
+ performanceMetrics: this.getPerformanceMetrics(),
11971
12656
  environment: this.getEnvironmentInfo()
11972
12657
  };
11973
12658
  }
@@ -12110,6 +12795,14 @@ var BugBearContext = createContext({
12110
12795
  markAsRead: async () => {
12111
12796
  },
12112
12797
  createThread: async () => ({ success: false }),
12798
+ // QA Sessions
12799
+ activeSession: null,
12800
+ sessionFindings: [],
12801
+ startSession: async () => ({ success: false }),
12802
+ endSession: async () => ({ success: false }),
12803
+ addFinding: async () => ({ success: false }),
12804
+ refreshSession: async () => {
12805
+ },
12113
12806
  refreshTesterStatus: async () => {
12114
12807
  },
12115
12808
  updateTesterProfile: async () => ({ success: false }),
@@ -12128,6 +12821,8 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12128
12821
  const [isLoading, setIsLoading] = useState(true);
12129
12822
  const [threads, setThreads] = useState([]);
12130
12823
  const [unreadCount, setUnreadCount] = useState(0);
12824
+ const [activeSession, setActiveSession] = useState(null);
12825
+ const [sessionFindings, setSessionFindings] = useState([]);
12131
12826
  const hasInitialized = useRef(false);
12132
12827
  const getDeviceInfo = useCallback(() => {
12133
12828
  const { width, height } = Dimensions.get("window");
@@ -12175,6 +12870,45 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12175
12870
  }
12176
12871
  return result;
12177
12872
  }, [client, refreshThreads]);
12873
+ const refreshSession = useCallback(async () => {
12874
+ if (!client) return;
12875
+ const session = await client.getActiveSession();
12876
+ setActiveSession(session);
12877
+ if (session) {
12878
+ const findings = await client.getSessionFindings(session.id);
12879
+ setSessionFindings(findings);
12880
+ } else {
12881
+ setSessionFindings([]);
12882
+ }
12883
+ }, [client]);
12884
+ const startSession = useCallback(async (options = {}) => {
12885
+ if (!client) return { success: false, error: "Client not initialized" };
12886
+ const result = await client.startSession(options);
12887
+ if (result.success && result.session) {
12888
+ setActiveSession(result.session);
12889
+ setSessionFindings([]);
12890
+ }
12891
+ return { success: result.success, error: result.error };
12892
+ }, [client]);
12893
+ const endSession = useCallback(async (notes) => {
12894
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12895
+ const routesCovered = client.getNavigationHistory();
12896
+ const result = await client.endSession(activeSession.id, { notes, routesCovered });
12897
+ if (result.success) {
12898
+ setActiveSession(null);
12899
+ setSessionFindings([]);
12900
+ }
12901
+ return { success: result.success, error: result.error };
12902
+ }, [client, activeSession]);
12903
+ const addFinding = useCallback(async (options) => {
12904
+ if (!client || !activeSession) return { success: false, error: "No active session" };
12905
+ const result = await client.addFinding(activeSession.id, options);
12906
+ if (result.success && result.finding) {
12907
+ setSessionFindings((prev) => [...prev, result.finding]);
12908
+ setActiveSession((prev) => prev ? { ...prev, findingsCount: prev.findingsCount + 1 } : null);
12909
+ }
12910
+ return result;
12911
+ }, [client, activeSession]);
12178
12912
  const updateTesterProfile = useCallback(async (updates) => {
12179
12913
  if (!client) return { success: false, error: "Client not initialized" };
12180
12914
  const result = await client.updateTesterProfile(updates);
@@ -12201,14 +12935,20 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12201
12935
  setTesterInfo(info);
12202
12936
  setIsTester(!!info);
12203
12937
  if (info && qaEnabled) {
12204
- const [newAssignments, newThreads] = await Promise.all([
12938
+ const [newAssignments, newThreads, session] = await Promise.all([
12205
12939
  bugBearClient.getAssignedTests(),
12206
- bugBearClient.getThreadsForTester()
12940
+ bugBearClient.getThreadsForTester(),
12941
+ bugBearClient.getActiveSession()
12207
12942
  ]);
12208
12943
  setAssignments(newAssignments);
12209
12944
  setThreads(newThreads);
12210
12945
  const totalUnread = newThreads.reduce((sum, t) => sum + t.unreadCount, 0);
12211
12946
  setUnreadCount(totalUnread);
12947
+ setActiveSession(session);
12948
+ if (session) {
12949
+ const findings = await bugBearClient.getSessionFindings(session.id);
12950
+ setSessionFindings(findings);
12951
+ }
12212
12952
  }
12213
12953
  } catch (err) {
12214
12954
  console.error("BugBear: Init error", err);
@@ -12255,6 +12995,13 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12255
12995
  sendMessage,
12256
12996
  markAsRead,
12257
12997
  createThread,
12998
+ // QA Sessions
12999
+ activeSession,
13000
+ sessionFindings,
13001
+ startSession,
13002
+ endSession,
13003
+ addFinding,
13004
+ refreshSession,
12258
13005
  refreshTesterStatus,
12259
13006
  updateTesterProfile,
12260
13007
  refreshTesterInfo
@@ -12265,7 +13012,7 @@ function BugBearProvider({ config, children, appVersion, enabled = true }) {
12265
13012
  }
12266
13013
 
12267
13014
  // src/BugBearButton.tsx
12268
- import React2, { useState as useState2, useEffect as useEffect2, useRef as useRef2 } from "react";
13015
+ import React2, { useState as useState2, useEffect as useEffect2, useRef as useRef2, useMemo, useCallback as useCallback2 } from "react";
12269
13016
  import {
12270
13017
  View,
12271
13018
  Text,
@@ -12315,7 +13062,13 @@ function BugBearButton({
12315
13062
  markAsRead,
12316
13063
  createThread,
12317
13064
  updateTesterProfile,
12318
- refreshTesterInfo
13065
+ refreshTesterInfo,
13066
+ activeSession,
13067
+ sessionFindings,
13068
+ startSession,
13069
+ endSession,
13070
+ addFinding,
13071
+ refreshSession
12319
13072
  } = useBugBear();
12320
13073
  const [modalVisible, setModalVisible] = useState2(false);
12321
13074
  const [activeTab, setActiveTab] = useState2("tests");
@@ -12403,39 +13156,228 @@ function BugBearButton({
12403
13156
  const [submitting, setSubmitting] = useState2(false);
12404
13157
  const [submitted, setSubmitted] = useState2(false);
12405
13158
  const [justPassed, setJustPassed] = useState2(false);
13159
+ const [showFeedbackPrompt, setShowFeedbackPrompt] = useState2(false);
13160
+ const [pendingFeedbackStatus, setPendingFeedbackStatus] = useState2(null);
13161
+ const [feedbackRating, setFeedbackRating] = useState2(5);
13162
+ const [feedbackNote, setFeedbackNote] = useState2("");
13163
+ const [feedbackFlags, setFeedbackFlags] = useState2({
13164
+ isOutdated: false,
13165
+ needsMoreDetail: false,
13166
+ stepsUnclear: false,
13167
+ expectedResultUnclear: false
13168
+ });
12406
13169
  const [criteriaResults, setCriteriaResults] = useState2({});
13170
+ const [showSkipModal, setShowSkipModal] = useState2(false);
13171
+ const [selectedSkipReason, setSelectedSkipReason] = useState2(null);
13172
+ const [skipNotes, setSkipNotes] = useState2("");
13173
+ const [skipping, setSkipping] = useState2(false);
13174
+ const [collapsedFolders, setCollapsedFolders] = useState2(/* @__PURE__ */ new Set());
13175
+ const [startingSession, setStartingSession] = useState2(false);
13176
+ const [sessionFocusArea, setSessionFocusArea] = useState2("");
13177
+ const [sessionPlatform, setSessionPlatform] = useState2(Platform2.OS === "ios" ? "ios" : "android");
13178
+ const [showAddFinding, setShowAddFinding] = useState2(false);
13179
+ const [findingType, setFindingType] = useState2("bug");
13180
+ const [findingTitle, setFindingTitle] = useState2("");
13181
+ const [findingDescription, setFindingDescription] = useState2("");
13182
+ const [findingSeverity, setFindingSeverity] = useState2("medium");
13183
+ const [addingFinding, setAddingFinding] = useState2(false);
13184
+ const [endingSession, setEndingSession] = useState2(false);
13185
+ const [sessionNotes, setSessionNotes] = useState2("");
13186
+ const [showEndConfirm, setShowEndConfirm] = useState2(false);
13187
+ const [sessionElapsedTime, setSessionElapsedTime] = useState2(0);
13188
+ const [assignmentElapsedTime, setAssignmentElapsedTime] = useState2(0);
13189
+ useEffect2(() => {
13190
+ const activeAssignment = displayedAssignment?.status === "in_progress" ? displayedAssignment : null;
13191
+ if (!activeAssignment?.startedAt) {
13192
+ setAssignmentElapsedTime(0);
13193
+ return;
13194
+ }
13195
+ const startTime = new Date(activeAssignment.startedAt).getTime();
13196
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13197
+ const interval = setInterval(() => {
13198
+ setAssignmentElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13199
+ }, 1e3);
13200
+ return () => clearInterval(interval);
13201
+ }, [displayedAssignment?.id, displayedAssignment?.status, displayedAssignment?.startedAt]);
13202
+ useEffect2(() => {
13203
+ if (!activeSession) {
13204
+ setSessionElapsedTime(0);
13205
+ return;
13206
+ }
13207
+ const startTime = new Date(activeSession.startedAt).getTime();
13208
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13209
+ const interval = setInterval(() => {
13210
+ setSessionElapsedTime(Math.floor((Date.now() - startTime) / 1e3));
13211
+ }, 1e3);
13212
+ return () => clearInterval(interval);
13213
+ }, [activeSession]);
13214
+ const formatElapsedTime = (seconds) => {
13215
+ const h = Math.floor(seconds / 3600);
13216
+ const m = Math.floor(seconds % 3600 / 60);
13217
+ const s = seconds % 60;
13218
+ if (h > 0) return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
13219
+ return `${m}:${s.toString().padStart(2, "0")}`;
13220
+ };
12407
13221
  useEffect2(() => {
12408
13222
  setCriteriaResults({});
12409
13223
  setShowSteps(false);
12410
13224
  }, [displayedAssignment?.id]);
13225
+ const groupedAssignments = useMemo(() => {
13226
+ const groups = /* @__PURE__ */ new Map();
13227
+ for (const assignment of assignments) {
13228
+ const groupId = assignment.testCase.group?.id || "ungrouped";
13229
+ const group = assignment.testCase.group || null;
13230
+ if (!groups.has(groupId)) {
13231
+ groups.set(groupId, {
13232
+ group,
13233
+ assignments: [],
13234
+ stats: { total: 0, passed: 0, failed: 0, pending: 0, skipped: 0 }
13235
+ });
13236
+ }
13237
+ const folder = groups.get(groupId);
13238
+ folder.assignments.push(assignment);
13239
+ folder.stats.total++;
13240
+ if (assignment.status === "passed") folder.stats.passed++;
13241
+ else if (assignment.status === "failed") folder.stats.failed++;
13242
+ else if (assignment.status === "skipped") folder.stats.skipped++;
13243
+ else folder.stats.pending++;
13244
+ }
13245
+ const sortedGroups = Array.from(groups.values()).sort((a, b) => {
13246
+ if (!a.group && !b.group) return 0;
13247
+ if (!a.group) return 1;
13248
+ if (!b.group) return -1;
13249
+ return a.group.sortOrder - b.group.sortOrder;
13250
+ });
13251
+ return sortedGroups;
13252
+ }, [assignments]);
13253
+ const toggleFolderCollapse = useCallback2((groupId) => {
13254
+ setCollapsedFolders((prev) => {
13255
+ const next = new Set(prev);
13256
+ if (next.has(groupId)) {
13257
+ next.delete(groupId);
13258
+ } else {
13259
+ next.add(groupId);
13260
+ }
13261
+ return next;
13262
+ });
13263
+ }, []);
13264
+ const getStatusBadge = (status) => {
13265
+ switch (status) {
13266
+ case "passed":
13267
+ return { icon: "\u2705", label: "Passed", color: "#22c55e" };
13268
+ case "failed":
13269
+ return { icon: "\u274C", label: "Failed", color: "#ef4444" };
13270
+ case "skipped":
13271
+ return { icon: "\u23ED\uFE0F", label: "Skipped", color: "#eab308" };
13272
+ case "in_progress":
13273
+ return { icon: "\u{1F504}", label: "In Progress", color: "#3b82f6" };
13274
+ case "blocked":
13275
+ return { icon: "\u{1F6AB}", label: "Blocked", color: "#f97316" };
13276
+ case "pending":
13277
+ default:
13278
+ return { icon: "\u23F3", label: "Pending", color: "#71717a" };
13279
+ }
13280
+ };
12411
13281
  if (isLoading || !shouldShowWidget) {
12412
13282
  return null;
12413
13283
  }
12414
13284
  const pendingCount = assignments.filter((a) => a.status === "pending").length;
12415
13285
  const inProgressCount = assignments.filter((a) => a.status === "in_progress").length;
12416
13286
  const handlePass = async () => {
13287
+ if (!displayedAssignment) return;
13288
+ setPendingFeedbackStatus("passed");
13289
+ setShowFeedbackPrompt(true);
13290
+ setFeedbackRating(5);
13291
+ setFeedbackNote("");
13292
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13293
+ };
13294
+ const handleFail = () => {
13295
+ if (!displayedAssignment) return;
13296
+ setPendingFeedbackStatus("failed");
13297
+ setShowFeedbackPrompt(true);
13298
+ setFeedbackRating(3);
13299
+ setFeedbackNote("");
13300
+ setFeedbackFlags({ isOutdated: false, needsMoreDetail: false, stepsUnclear: false, expectedResultUnclear: false });
13301
+ };
13302
+ const handleSubmitFeedback = async (skipFeedback = false) => {
12417
13303
  if (!client || !displayedAssignment) return;
12418
13304
  setSubmitting(true);
12419
- await client.submitReport({
12420
- type: "test_pass",
12421
- description: `Test passed: ${displayedAssignment.testCase.title}`,
12422
- assignmentId: displayedAssignment.id,
12423
- testCaseId: displayedAssignment.testCase.id,
12424
- appContext: getAppContext?.() || { currentRoute: "unknown" },
12425
- deviceInfo: getDeviceInfo()
12426
- });
12427
- await refreshAssignments();
12428
- setSubmitting(false);
12429
- setJustPassed(true);
12430
- setTimeout(() => {
12431
- setJustPassed(false);
13305
+ const feedback = skipFeedback ? void 0 : {
13306
+ rating: feedbackRating,
13307
+ feedbackNote: feedbackNote.trim() || void 0,
13308
+ isOutdated: feedbackFlags.isOutdated,
13309
+ needsMoreDetail: feedbackFlags.needsMoreDetail,
13310
+ stepsUnclear: feedbackFlags.stepsUnclear,
13311
+ expectedResultUnclear: feedbackFlags.expectedResultUnclear
13312
+ };
13313
+ if (pendingFeedbackStatus === "passed") {
13314
+ await client.submitReport({
13315
+ type: "test_pass",
13316
+ description: `Test passed: ${displayedAssignment.testCase.title}`,
13317
+ assignmentId: displayedAssignment.id,
13318
+ testCaseId: displayedAssignment.testCase.id,
13319
+ appContext: getAppContext?.() || { currentRoute: "unknown" },
13320
+ deviceInfo: getDeviceInfo()
13321
+ });
13322
+ if (feedback) {
13323
+ await client.submitTestFeedback({
13324
+ testCaseId: displayedAssignment.testCase.id,
13325
+ assignmentId: displayedAssignment.id,
13326
+ feedback,
13327
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13328
+ });
13329
+ }
13330
+ await refreshAssignments();
13331
+ setSubmitting(false);
13332
+ setShowFeedbackPrompt(false);
13333
+ setPendingFeedbackStatus(null);
13334
+ setJustPassed(true);
13335
+ setTimeout(() => {
13336
+ setJustPassed(false);
13337
+ setSelectedTestId(null);
13338
+ setTestView("detail");
13339
+ }, 1200);
13340
+ } else if (pendingFeedbackStatus === "failed") {
13341
+ if (feedback) {
13342
+ await client.submitTestFeedback({
13343
+ testCaseId: displayedAssignment.testCase.id,
13344
+ assignmentId: displayedAssignment.id,
13345
+ feedback,
13346
+ timeToCompleteSeconds: assignmentElapsedTime || void 0
13347
+ });
13348
+ }
13349
+ setSubmitting(false);
13350
+ setShowFeedbackPrompt(false);
13351
+ setPendingFeedbackStatus(null);
13352
+ setActiveTab("report");
13353
+ setReportType("test_fail");
13354
+ }
13355
+ };
13356
+ const handleSkipFeedback = () => {
13357
+ handleSubmitFeedback(true);
13358
+ };
13359
+ const handleOpenSkipModal = () => {
13360
+ setShowSkipModal(true);
13361
+ setSelectedSkipReason(null);
13362
+ setSkipNotes("");
13363
+ };
13364
+ const handleSkip = async () => {
13365
+ if (!client || !displayedAssignment || !selectedSkipReason) return;
13366
+ setSkipping(true);
13367
+ const result = await client.skipAssignment(
13368
+ displayedAssignment.id,
13369
+ selectedSkipReason,
13370
+ skipNotes || void 0
13371
+ );
13372
+ if (result.success) {
13373
+ await refreshAssignments();
13374
+ setShowSkipModal(false);
13375
+ setSelectedSkipReason(null);
13376
+ setSkipNotes("");
12432
13377
  setSelectedTestId(null);
12433
13378
  setTestView("detail");
12434
- }, 1200);
12435
- };
12436
- const handleFail = () => {
12437
- setActiveTab("report");
12438
- setReportType("test_fail");
13379
+ }
13380
+ setSkipping(false);
12439
13381
  };
12440
13382
  const handleSubmitReport = async () => {
12441
13383
  if (!client || !description.trim()) return;
@@ -12582,6 +13524,44 @@ function BugBearButton({
12582
13524
  }
12583
13525
  setSavingProfile(false);
12584
13526
  };
13527
+ const handleStartSession = async () => {
13528
+ setStartingSession(true);
13529
+ const result = await startSession({
13530
+ focusArea: sessionFocusArea.trim() || void 0,
13531
+ platform: sessionPlatform
13532
+ });
13533
+ if (result.success) {
13534
+ setSessionFocusArea("");
13535
+ }
13536
+ setStartingSession(false);
13537
+ };
13538
+ const handleEndSession = async () => {
13539
+ setEndingSession(true);
13540
+ const result = await endSession(sessionNotes.trim() || void 0);
13541
+ if (result.success) {
13542
+ setSessionNotes("");
13543
+ setShowEndConfirm(false);
13544
+ }
13545
+ setEndingSession(false);
13546
+ };
13547
+ const handleAddFinding = async () => {
13548
+ if (!findingTitle.trim()) return;
13549
+ setAddingFinding(true);
13550
+ const result = await addFinding({
13551
+ type: findingType,
13552
+ title: findingTitle.trim(),
13553
+ description: findingDescription.trim() || void 0,
13554
+ severity: findingType === "bug" ? findingSeverity : void 0
13555
+ });
13556
+ if (result.success) {
13557
+ setFindingTitle("");
13558
+ setFindingDescription("");
13559
+ setFindingType("bug");
13560
+ setFindingSeverity("medium");
13561
+ setShowAddFinding(false);
13562
+ }
13563
+ setAddingFinding(false);
13564
+ };
12585
13565
  const formatRelativeTime = (dateString) => {
12586
13566
  const date = new Date(dateString);
12587
13567
  const now = /* @__PURE__ */ new Date();
@@ -12635,7 +13615,7 @@ function BugBearButton({
12635
13615
  const steps = displayedAssignment.testCase.steps;
12636
13616
  const info = templateInfo[template];
12637
13617
  const rubricMode = displayedAssignment.testCase.track?.rubricMode || "pass_fail";
12638
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(View, { style: [styles.templateBadge, { backgroundColor: displayedAssignment.testCase.track?.color ? `${displayedAssignment.testCase.track.color}20` : "#F3F4F6" }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.templateIcon }, info.icon), /* @__PURE__ */ React2.createElement(Text, { style: styles.templateName }, info.name), /* @__PURE__ */ React2.createElement(Text, { style: styles.templateAction }, "\u2022 ", info.action)), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: () => setShowSteps(!showSteps), style: styles.stepsToggle }, /* @__PURE__ */ React2.createElement(Text, { style: styles.stepsToggleText }, showSteps ? "\u25BC" : "\u25B6", " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && template === "steps" && /* @__PURE__ */ React2.createElement(View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ React2.createElement(View, { key: idx, style: styles.step }, /* @__PURE__ */ React2.createElement(View, { style: styles.stepNumber }, /* @__PURE__ */ React2.createElement(Text, { style: styles.stepNumberText }, step.stepNumber)), /* @__PURE__ */ React2.createElement(View, { style: styles.stepContent }, /* @__PURE__ */ React2.createElement(Text, { style: styles.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ React2.createElement(Text, { style: styles.stepExpected }, "\u2192 ", step.expectedResult))))), showSteps && template === "checklist" && /* @__PURE__ */ React2.createElement(View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ React2.createElement(
13618
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(View, { style: [styles.templateBadge, { backgroundColor: displayedAssignment.testCase.track?.color ? `${displayedAssignment.testCase.track.color}20` : "#3f3f46" }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.templateIcon }, info.icon), /* @__PURE__ */ React2.createElement(Text, { style: styles.templateName }, info.name), /* @__PURE__ */ React2.createElement(Text, { style: styles.templateAction }, "\u2022 ", info.action)), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: () => setShowSteps(!showSteps), style: styles.stepsToggle }, /* @__PURE__ */ React2.createElement(Text, { style: styles.stepsToggleText }, showSteps ? "\u25BC" : "\u25B6", " ", template === "freeform" ? "Instructions" : `${steps.length} ${template === "checklist" ? "items" : template === "rubric" ? "criteria" : "steps"}`)), showSteps && template === "steps" && /* @__PURE__ */ React2.createElement(View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ React2.createElement(View, { key: idx, style: styles.step }, /* @__PURE__ */ React2.createElement(View, { style: styles.stepNumber }, /* @__PURE__ */ React2.createElement(Text, { style: styles.stepNumberText }, step.stepNumber)), /* @__PURE__ */ React2.createElement(View, { style: styles.stepContent }, /* @__PURE__ */ React2.createElement(Text, { style: styles.stepAction }, step.action), step.expectedResult && /* @__PURE__ */ React2.createElement(Text, { style: styles.stepExpected }, "\u2192 ", step.expectedResult))))), showSteps && template === "checklist" && /* @__PURE__ */ React2.createElement(View, { style: styles.stepsList }, steps.map((step, idx) => /* @__PURE__ */ React2.createElement(
12639
13619
  TouchableOpacity,
12640
13620
  {
12641
13621
  key: idx,
@@ -12765,6 +13745,13 @@ function BugBearButton({
12765
13745
  onPress: () => setActiveTab("messages")
12766
13746
  },
12767
13747
  /* @__PURE__ */ React2.createElement(View, { style: styles.tabWithBadge }, /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "messages" && styles.activeTabText] }, "Messages"), unreadCount > 0 && /* @__PURE__ */ React2.createElement(View, { style: styles.tabBadge }, /* @__PURE__ */ React2.createElement(Text, { style: styles.tabBadgeText }, unreadCount)))
13748
+ ), /* @__PURE__ */ React2.createElement(
13749
+ TouchableOpacity,
13750
+ {
13751
+ style: [styles.tab, activeTab === "explore" && styles.activeTab],
13752
+ onPress: () => setActiveTab("explore")
13753
+ },
13754
+ /* @__PURE__ */ React2.createElement(View, { style: styles.tabWithBadge }, /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "explore" && styles.activeTabText] }, "Explore"), activeSession && /* @__PURE__ */ React2.createElement(View, { style: styles.sessionDot }))
12768
13755
  ), /* @__PURE__ */ React2.createElement(
12769
13756
  TouchableOpacity,
12770
13757
  {
@@ -12773,32 +13760,114 @@ function BugBearButton({
12773
13760
  },
12774
13761
  /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "report" && styles.activeTabText] }, "Report")
12775
13762
  )), /* @__PURE__ */ React2.createElement(ScrollView, { style: styles.content }, activeTab === "tests" && /* @__PURE__ */ React2.createElement(View, null, assignments.length === 0 ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u2705"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "All caught up!"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "No tests assigned")) : testView === "list" ? (
12776
- /* List View - Show all tests */
12777
- /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"), assignments.map((assignment) => /* @__PURE__ */ React2.createElement(
13763
+ /* List View - Show tests grouped by folder */
13764
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"), groupedAssignments.map((folder) => {
13765
+ const groupId = folder.group?.id || "ungrouped";
13766
+ const isCollapsed = collapsedFolders.has(groupId);
13767
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13768
+ return /* @__PURE__ */ React2.createElement(View, { key: groupId, style: styles.folderContainer }, /* @__PURE__ */ React2.createElement(
13769
+ TouchableOpacity,
13770
+ {
13771
+ onPress: () => toggleFolderCollapse(groupId),
13772
+ style: styles.folderHeader
13773
+ },
13774
+ /* @__PURE__ */ React2.createElement(View, { style: styles.folderHeaderLeft }, /* @__PURE__ */ React2.createElement(Text, { style: styles.folderIcon }, isCollapsed ? "\u{1F4C1}" : "\u{1F4C2}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.folderName }, folder.group?.name || "Ungrouped Tests")),
13775
+ /* @__PURE__ */ React2.createElement(View, { style: styles.folderStats }, /* @__PURE__ */ React2.createElement(Text, { style: styles.folderProgress }, completedCount, "/", folder.stats.total), /* @__PURE__ */ React2.createElement(Text, { style: styles.folderChevron }, isCollapsed ? "\u25B6" : "\u25BC"))
13776
+ ), !isCollapsed && /* @__PURE__ */ React2.createElement(View, { style: styles.folderProgressBar }, /* @__PURE__ */ React2.createElement(
13777
+ View,
13778
+ {
13779
+ style: [
13780
+ styles.folderProgressFill,
13781
+ { width: `${completedCount / folder.stats.total * 100}%` }
13782
+ ]
13783
+ }
13784
+ )), !isCollapsed && folder.assignments.map((assignment) => {
13785
+ const statusBadge = getStatusBadge(assignment.status);
13786
+ return /* @__PURE__ */ React2.createElement(
13787
+ TouchableOpacity,
13788
+ {
13789
+ key: assignment.id,
13790
+ onPress: () => {
13791
+ setSelectedTestId(assignment.id);
13792
+ setTestView("detail");
13793
+ setShowSteps(false);
13794
+ },
13795
+ style: [
13796
+ styles.listItem,
13797
+ styles.listItemInFolder,
13798
+ assignment.id === currentAssignment?.id && styles.listItemCurrent
13799
+ ]
13800
+ },
13801
+ /* @__PURE__ */ React2.createElement(View, { style: styles.listItemHeader }, /* @__PURE__ */ React2.createElement(View, { style: styles.listItemKeyWithStatus }, /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ React2.createElement(View, { style: [styles.statusBadge, { backgroundColor: statusBadge.color + "20" }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.statusBadgeIcon }, statusBadge.icon), /* @__PURE__ */ React2.createElement(Text, { style: [styles.statusBadgeText, { color: statusBadge.color }] }, statusBadge.label))), /* @__PURE__ */ React2.createElement(View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ React2.createElement(View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ React2.createElement(View, { style: [
13802
+ styles.priorityBadge,
13803
+ assignment.testCase.priority === "P0" && styles.priorityP0,
13804
+ assignment.testCase.priority === "P1" && styles.priorityP1
13805
+ ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, assignment.testCase.priority)))),
13806
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
13807
+ /* @__PURE__ */ React2.createElement(View, { style: styles.listItemMeta }, /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemMetaText }, assignment.testCase.steps.length, " ", assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"), assignment.id === currentAssignment?.id && /* @__PURE__ */ React2.createElement(Text, { style: styles.currentBadge }, "\u2022 Current"))
13808
+ );
13809
+ }));
13810
+ }))
13811
+ ) : justPassed ? (
13812
+ /* Success state after passing */
13813
+ /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ React2.createElement(Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Loading next test..."))
13814
+ ) : showFeedbackPrompt && displayedAssignment ? (
13815
+ /* Feedback prompt after completing a test */
13816
+ /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.container }, /* @__PURE__ */ React2.createElement(View, { style: { alignItems: "center", marginBottom: 16 } }, /* @__PURE__ */ React2.createElement(Text, { style: { fontSize: 28 } }, pendingFeedbackStatus === "passed" ? "\u2713" : "\u2717"), /* @__PURE__ */ React2.createElement(Text, { style: [feedbackStyles.statusText, pendingFeedbackStatus === "passed" ? { color: "#4ade80" } : { color: "#f87171" }] }, pendingFeedbackStatus === "passed" ? "Test Passed!" : "Test Failed")), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.infoBox }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.infoTitle }, "Help us improve this test"), /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.infoSubtitle }, "Your feedback shapes better tests for everyone.")), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.ratingSection }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingLabel }, "How was this test?"), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.starsRow }, [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ React2.createElement(
12778
13817
  TouchableOpacity,
12779
13818
  {
12780
- key: assignment.id,
12781
- onPress: () => {
12782
- setSelectedTestId(assignment.id);
12783
- setTestView("detail");
12784
- setShowSteps(false);
12785
- },
13819
+ key: star,
13820
+ onPress: () => setFeedbackRating(star)
13821
+ },
13822
+ /* @__PURE__ */ React2.createElement(Text, { style: [feedbackStyles.star, star <= feedbackRating ? feedbackStyles.starActive : feedbackStyles.starInactive] }, "\u2605")
13823
+ ))), /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingDesc }, feedbackRating === 1 ? "Needs work" : feedbackRating === 2 ? "Could be better" : feedbackRating === 3 ? "Okay" : feedbackRating === 4 ? "Good" : "Great!")), feedbackRating < 4 && /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.flagsSection }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingLabel }, "What could be improved?"), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.flagsGrid }, [
13824
+ { key: "stepsUnclear", label: "Steps unclear" },
13825
+ { key: "expectedResultUnclear", label: "Expected result unclear" },
13826
+ { key: "needsMoreDetail", label: "Needs more detail" },
13827
+ { key: "isOutdated", label: "Seems outdated" }
13828
+ ].map(({ key, label }) => /* @__PURE__ */ React2.createElement(
13829
+ TouchableOpacity,
13830
+ {
13831
+ key,
13832
+ onPress: () => setFeedbackFlags((prev) => ({ ...prev, [key]: !prev[key] })),
12786
13833
  style: [
12787
- styles.listItem,
12788
- assignment.id === currentAssignment?.id && styles.listItemCurrent
13834
+ feedbackStyles.flagButton,
13835
+ feedbackFlags[key] && feedbackStyles.flagButtonActive
12789
13836
  ]
12790
13837
  },
12791
- /* @__PURE__ */ React2.createElement(View, { style: styles.listItemHeader }, /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemKey }, assignment.testCase.testKey), /* @__PURE__ */ React2.createElement(View, { style: styles.listItemBadges }, assignment.testCase.track && /* @__PURE__ */ React2.createElement(View, { style: [styles.trackBadge, { backgroundColor: assignment.testCase.track.color }] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.trackBadgeText }, templateInfo[assignment.testCase.track.testTemplate || "steps"].icon)), /* @__PURE__ */ React2.createElement(View, { style: [
12792
- styles.priorityBadge,
12793
- assignment.testCase.priority === "P0" && styles.priorityP0,
12794
- assignment.testCase.priority === "P1" && styles.priorityP1
12795
- ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, assignment.testCase.priority)))),
12796
- /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemTitle, numberOfLines: 2 }, assignment.testCase.title),
12797
- /* @__PURE__ */ React2.createElement(View, { style: styles.listItemMeta }, /* @__PURE__ */ React2.createElement(Text, { style: styles.listItemMetaText }, assignment.testCase.steps.length, " ", assignment.testCase.track?.testTemplate === "checklist" ? "items" : assignment.testCase.track?.testTemplate === "rubric" ? "criteria" : "steps"), assignment.id === currentAssignment?.id && /* @__PURE__ */ React2.createElement(Text, { style: styles.currentBadge }, "\u2022 Current"))
13838
+ /* @__PURE__ */ React2.createElement(Text, { style: [
13839
+ feedbackStyles.flagButtonText,
13840
+ feedbackFlags[key] && feedbackStyles.flagButtonTextActive
13841
+ ] }, label)
13842
+ )))), /* @__PURE__ */ React2.createElement(View, { style: { marginBottom: 12 } }, /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.ratingLabel }, "Suggestions? (optional)"), /* @__PURE__ */ React2.createElement(
13843
+ TextInput,
13844
+ {
13845
+ style: feedbackStyles.noteInput,
13846
+ value: feedbackNote,
13847
+ onChangeText: setFeedbackNote,
13848
+ placeholder: "How could this test be improved?",
13849
+ placeholderTextColor: "#71717a",
13850
+ multiline: true,
13851
+ numberOfLines: 2,
13852
+ textAlignVertical: "top"
13853
+ }
13854
+ )), /* @__PURE__ */ React2.createElement(View, { style: feedbackStyles.buttonRow }, /* @__PURE__ */ React2.createElement(
13855
+ TouchableOpacity,
13856
+ {
13857
+ onPress: handleSkipFeedback,
13858
+ disabled: submitting,
13859
+ style: [feedbackStyles.skipButton, submitting && { opacity: 0.5 }]
13860
+ },
13861
+ /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.skipButtonText }, "Skip")
13862
+ ), /* @__PURE__ */ React2.createElement(
13863
+ TouchableOpacity,
13864
+ {
13865
+ onPress: () => handleSubmitFeedback(false),
13866
+ disabled: submitting,
13867
+ style: [feedbackStyles.submitButton, submitting && { opacity: 0.5 }]
13868
+ },
13869
+ /* @__PURE__ */ React2.createElement(Text, { style: feedbackStyles.submitButtonText }, submitting ? "Submitting..." : "Submit Feedback")
12798
13870
  )))
12799
- ) : justPassed ? (
12800
- /* Success state after passing */
12801
- /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.passedEmoji }, "\u2713"), /* @__PURE__ */ React2.createElement(Text, { style: styles.passedTitle }, "Passed!"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Loading next test..."))
12802
13871
  ) : displayedAssignment ? (
12803
13872
  /* Detail View - Show single test */
12804
13873
  /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(
@@ -12815,20 +13884,41 @@ function BugBearButton({
12815
13884
  styles.priorityBadge,
12816
13885
  displayedAssignment.testCase.priority === "P0" && styles.priorityP0,
12817
13886
  displayedAssignment.testCase.priority === "P1" && styles.priorityP1
12818
- ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ React2.createElement(Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.testCase.description && /* @__PURE__ */ React2.createElement(Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ React2.createElement(Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ React2.createElement(View, { style: styles.expectedResult }, /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), /* @__PURE__ */ React2.createElement(View, { style: styles.actionButtons }, /* @__PURE__ */ React2.createElement(
13887
+ ] }, /* @__PURE__ */ React2.createElement(Text, { style: styles.priorityText }, displayedAssignment.testCase.priority)))), /* @__PURE__ */ React2.createElement(Text, { style: styles.testTitle }, displayedAssignment.testCase.title), displayedAssignment.status === "in_progress" && displayedAssignment.startedAt && /* @__PURE__ */ React2.createElement(View, { style: timerStyles.container }, /* @__PURE__ */ React2.createElement(View, { style: timerStyles.dot }), /* @__PURE__ */ React2.createElement(Text, { style: timerStyles.label }, "Testing"), /* @__PURE__ */ React2.createElement(Text, { style: timerStyles.time }, formatElapsedTime(assignmentElapsedTime))), displayedAssignment.testCase.description && /* @__PURE__ */ React2.createElement(Text, { style: styles.testDescription }, displayedAssignment.testCase.description), displayedAssignment.testCase.targetRoute && onNavigate && /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: handleNavigate, style: styles.navigateButton }, /* @__PURE__ */ React2.createElement(Text, { style: styles.navigateButtonText }, "Go to test location \u2192")), renderTestContent(), /* @__PURE__ */ React2.createElement(View, { style: styles.expectedResult }, /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedLabel }, displayedAssignment.testCase.track?.testTemplate === "checklist" ? "Pass criteria:" : displayedAssignment.testCase.track?.testTemplate === "rubric" ? "Target score:" : "Expected:"), /* @__PURE__ */ React2.createElement(Text, { style: styles.expectedText }, displayedAssignment.testCase.expectedResult))), displayedAssignment.testCase.group && (() => {
13888
+ const folder = groupedAssignments.find((f) => f.group?.id === displayedAssignment.testCase.group?.id);
13889
+ if (!folder) return null;
13890
+ const completedCount = folder.stats.passed + folder.stats.failed + folder.stats.skipped;
13891
+ return /* @__PURE__ */ React2.createElement(View, { style: styles.detailProgressContainer }, /* @__PURE__ */ React2.createElement(Text, { style: styles.detailProgressText }, folder.group?.name, ": ", completedCount, "/", folder.stats.total, " complete"), /* @__PURE__ */ React2.createElement(View, { style: styles.detailProgressBar }, /* @__PURE__ */ React2.createElement(
13892
+ View,
13893
+ {
13894
+ style: [
13895
+ styles.detailProgressFill,
13896
+ { width: `${completedCount / folder.stats.total * 100}%` }
13897
+ ]
13898
+ }
13899
+ )));
13900
+ })(), /* @__PURE__ */ React2.createElement(View, { style: styles.actionButtons }, /* @__PURE__ */ React2.createElement(
12819
13901
  TouchableOpacity,
12820
13902
  {
12821
13903
  style: styles.failButton,
12822
13904
  onPress: handleFail,
12823
- disabled: submitting
13905
+ disabled: submitting || skipping
12824
13906
  },
12825
13907
  /* @__PURE__ */ React2.createElement(Text, { style: styles.failButtonText }, "\u2717 Fail")
13908
+ ), /* @__PURE__ */ React2.createElement(
13909
+ TouchableOpacity,
13910
+ {
13911
+ style: styles.skipButton,
13912
+ onPress: handleOpenSkipModal,
13913
+ disabled: submitting || skipping
13914
+ },
13915
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipButtonText }, skipping ? "..." : "\u2192 Skip")
12826
13916
  ), /* @__PURE__ */ React2.createElement(
12827
13917
  TouchableOpacity,
12828
13918
  {
12829
13919
  style: styles.passButton,
12830
13920
  onPress: handlePass,
12831
- disabled: submitting
13921
+ disabled: submitting || skipping
12832
13922
  },
12833
13923
  /* @__PURE__ */ React2.createElement(Text, { style: styles.passButtonText }, submitting ? "..." : "\u2713 Pass")
12834
13924
  )))
@@ -12841,7 +13931,7 @@ function BugBearButton({
12841
13931
  value: composeSubject,
12842
13932
  onChangeText: setComposeSubject,
12843
13933
  placeholder: "What's this about?",
12844
- placeholderTextColor: "#9CA3AF",
13934
+ placeholderTextColor: "#71717a",
12845
13935
  maxLength: 100
12846
13936
  }
12847
13937
  ), /* @__PURE__ */ React2.createElement(Text, { style: [styles.label, { marginTop: 16 }] }, "Message"), /* @__PURE__ */ React2.createElement(
@@ -12851,7 +13941,7 @@ function BugBearButton({
12851
13941
  value: composeMessage,
12852
13942
  onChangeText: setComposeMessage,
12853
13943
  placeholder: "Write your message...",
12854
- placeholderTextColor: "#9CA3AF",
13944
+ placeholderTextColor: "#71717a",
12855
13945
  multiline: true,
12856
13946
  numberOfLines: 6,
12857
13947
  textAlignVertical: "top",
@@ -12916,33 +14006,193 @@ function BugBearButton({
12916
14006
  message.senderType === "tester" && styles.messageTimeTester
12917
14007
  ] }, formatMessageTime(message.createdAt))
12918
14008
  ))))
12919
- )), activeTab === "report" && /* @__PURE__ */ React2.createElement(View, null, submitted ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u{1F389}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Report submitted!")) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(View, { style: styles.reportTypes }, [
12920
- { type: "bug", label: "\u{1F41B} Bug" },
12921
- { type: "feedback", label: "\u{1F4A1} Feedback" },
12922
- { type: "suggestion", label: "\u2728 Idea" }
12923
- ].map(({ type, label }) => /* @__PURE__ */ React2.createElement(
12924
- TouchableOpacity,
12925
- {
12926
- key: type,
12927
- style: [
12928
- styles.reportTypeButton,
12929
- reportType === type && styles.reportTypeActive
12930
- ],
12931
- onPress: () => setReportType(type)
12932
- },
12933
- /* @__PURE__ */ React2.createElement(Text, { style: [
12934
- styles.reportTypeText,
12935
- reportType === type && styles.reportTypeTextActive
12936
- ] }, label)
12937
- ))), (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ React2.createElement(View, { style: styles.severitySection }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "Severity"), /* @__PURE__ */ React2.createElement(View, { style: styles.severityButtons }, ["critical", "high", "medium", "low"].map((sev) => {
12938
- const activeStyles = {
12939
- critical: styles.severityCriticalActive,
12940
- high: styles.severityHighActive,
12941
- medium: styles.severityMediumActive,
12942
- low: styles.severityLowActive
12943
- };
12944
- return /* @__PURE__ */ React2.createElement(
12945
- TouchableOpacity,
14009
+ )), activeTab === "explore" && /* @__PURE__ */ React2.createElement(View, null, !activeSession ? (
14010
+ /* Start Session View */
14011
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u{1F50D}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Exploratory QA Session"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Explore freely and capture findings as you go")), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Focus Area (optional)"), /* @__PURE__ */ React2.createElement(
14012
+ TextInput,
14013
+ {
14014
+ style: exploreStyles.input,
14015
+ value: sessionFocusArea,
14016
+ onChangeText: setSessionFocusArea,
14017
+ placeholder: "e.g., checkout flow, settings page",
14018
+ placeholderTextColor: "#71717a"
14019
+ }
14020
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Platform"), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.platformRow }, [
14021
+ { key: "ios", label: "\u{1F4F1} iOS" },
14022
+ { key: "android", label: "\u{1F916} Android" },
14023
+ { key: "web", label: "\u{1F310} Web" }
14024
+ ].map(({ key, label }) => /* @__PURE__ */ React2.createElement(
14025
+ TouchableOpacity,
14026
+ {
14027
+ key,
14028
+ onPress: () => setSessionPlatform(key),
14029
+ style: [
14030
+ exploreStyles.platformButton,
14031
+ sessionPlatform === key && exploreStyles.platformButtonActive
14032
+ ]
14033
+ },
14034
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14035
+ exploreStyles.platformButtonText,
14036
+ sessionPlatform === key && exploreStyles.platformButtonTextActive
14037
+ ] }, label)
14038
+ )))), /* @__PURE__ */ React2.createElement(
14039
+ TouchableOpacity,
14040
+ {
14041
+ onPress: handleStartSession,
14042
+ disabled: startingSession,
14043
+ style: [exploreStyles.startButton, startingSession && { opacity: 0.5 }]
14044
+ },
14045
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.startButtonText }, startingSession ? "Starting..." : "\u25B6 Start Session")
14046
+ ))
14047
+ ) : showEndConfirm ? (
14048
+ /* End Session Confirmation */
14049
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u270B"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "End Session?"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptySubtitle }, "Duration: ", formatElapsedTime(sessionElapsedTime), " \xB7 ", sessionFindings.length, " finding", sessionFindings.length !== 1 ? "s" : "")), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Session Notes (optional)"), /* @__PURE__ */ React2.createElement(
14050
+ TextInput,
14051
+ {
14052
+ style: [exploreStyles.input, { height: 80, textAlignVertical: "top" }],
14053
+ value: sessionNotes,
14054
+ onChangeText: setSessionNotes,
14055
+ placeholder: "Any overall observations from this session...",
14056
+ placeholderTextColor: "#71717a",
14057
+ multiline: true
14058
+ }
14059
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.buttonRow }, /* @__PURE__ */ React2.createElement(
14060
+ TouchableOpacity,
14061
+ {
14062
+ onPress: () => setShowEndConfirm(false),
14063
+ style: exploreStyles.cancelButton
14064
+ },
14065
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.cancelButtonText }, "Cancel")
14066
+ ), /* @__PURE__ */ React2.createElement(
14067
+ TouchableOpacity,
14068
+ {
14069
+ onPress: handleEndSession,
14070
+ disabled: endingSession,
14071
+ style: [exploreStyles.endButton, endingSession && { opacity: 0.5 }]
14072
+ },
14073
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.endButtonText }, endingSession ? "Ending..." : "End Session")
14074
+ )))
14075
+ ) : showAddFinding ? (
14076
+ /* Add Finding Form */
14077
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingHeader }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingHeaderTitle }, "Add Finding"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: () => setShowAddFinding(false) }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingHeaderClose }, "\u2715"))), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingTypeRow }, [
14078
+ { type: "bug", label: "\u{1F41B} Bug" },
14079
+ { type: "concern", label: "\u26A0\uFE0F Concern" },
14080
+ { type: "suggestion", label: "\u{1F4A1} Idea" },
14081
+ { type: "question", label: "\u2753 Q" }
14082
+ ].map(({ type, label }) => /* @__PURE__ */ React2.createElement(
14083
+ TouchableOpacity,
14084
+ {
14085
+ key: type,
14086
+ onPress: () => setFindingType(type),
14087
+ style: [
14088
+ exploreStyles.findingTypeButton,
14089
+ findingType === type && exploreStyles.findingTypeButtonActive
14090
+ ]
14091
+ },
14092
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14093
+ exploreStyles.findingTypeButtonText,
14094
+ findingType === type && exploreStyles.findingTypeButtonTextActive
14095
+ ] }, label)
14096
+ ))), findingType === "bug" && /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Severity"), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.severityRow }, ["critical", "high", "medium", "low"].map((sev) => /* @__PURE__ */ React2.createElement(
14097
+ TouchableOpacity,
14098
+ {
14099
+ key: sev,
14100
+ onPress: () => setFindingSeverity(sev),
14101
+ style: [
14102
+ exploreStyles.severityButton,
14103
+ findingSeverity === sev && (sev === "critical" ? exploreStyles.severityCritical : sev === "high" ? exploreStyles.severityHigh : sev === "medium" ? exploreStyles.severityMedium : exploreStyles.severityLow)
14104
+ ]
14105
+ },
14106
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14107
+ exploreStyles.severityButtonText,
14108
+ findingSeverity === sev && exploreStyles.severityButtonTextActive
14109
+ ] }, sev)
14110
+ )))), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Title *"), /* @__PURE__ */ React2.createElement(
14111
+ TextInput,
14112
+ {
14113
+ style: exploreStyles.input,
14114
+ value: findingTitle,
14115
+ onChangeText: setFindingTitle,
14116
+ placeholder: "Brief description of what you found",
14117
+ placeholderTextColor: "#71717a"
14118
+ }
14119
+ )), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.formGroup }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.label }, "Details (optional)"), /* @__PURE__ */ React2.createElement(
14120
+ TextInput,
14121
+ {
14122
+ style: [exploreStyles.input, { height: 60, textAlignVertical: "top" }],
14123
+ value: findingDescription,
14124
+ onChangeText: setFindingDescription,
14125
+ placeholder: "Steps to reproduce, expected behavior, etc.",
14126
+ placeholderTextColor: "#71717a",
14127
+ multiline: true
14128
+ }
14129
+ )), /* @__PURE__ */ React2.createElement(
14130
+ TouchableOpacity,
14131
+ {
14132
+ onPress: handleAddFinding,
14133
+ disabled: addingFinding || !findingTitle.trim(),
14134
+ style: [exploreStyles.addFindingButton, (addingFinding || !findingTitle.trim()) && { opacity: 0.5 }]
14135
+ },
14136
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.addFindingButtonText }, addingFinding ? "Adding..." : "Add Finding")
14137
+ ))
14138
+ ) : (
14139
+ /* Active Session View */
14140
+ /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionBanner }, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionBannerRow }, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionBannerLeft }, /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.sessionDotLarge }), /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.sessionBannerLabel }, "Session Active")), /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.sessionTimer }, formatElapsedTime(sessionElapsedTime))), activeSession.focusArea && /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.sessionFocus }, "Focus: ", activeSession.focusArea)), /* @__PURE__ */ React2.createElement(
14141
+ TouchableOpacity,
14142
+ {
14143
+ onPress: () => setShowAddFinding(true),
14144
+ style: exploreStyles.addButton
14145
+ },
14146
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.addButtonText }, "+ Add Finding")
14147
+ ), /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingsSection }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingsLabel }, "Findings (", sessionFindings.length, ")"), sessionFindings.length === 0 ? /* @__PURE__ */ React2.createElement(View, { style: exploreStyles.findingsEmpty }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingsEmptyText }, "No findings yet"), /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingsEmptyText }, "Explore and add findings as you go")) : /* @__PURE__ */ React2.createElement(View, null, sessionFindings.map((finding) => /* @__PURE__ */ React2.createElement(
14148
+ View,
14149
+ {
14150
+ key: finding.id,
14151
+ style: [
14152
+ exploreStyles.findingCard,
14153
+ finding.type === "bug" ? exploreStyles.findingCardBug : finding.type === "concern" ? exploreStyles.findingCardConcern : finding.type === "suggestion" ? exploreStyles.findingCardSuggestion : exploreStyles.findingCardQuestion
14154
+ ]
14155
+ },
14156
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingCardIcon }, finding.type === "bug" ? "\u{1F41B}" : finding.type === "concern" ? "\u26A0\uFE0F" : finding.type === "suggestion" ? "\u{1F4A1}" : "\u2753"),
14157
+ /* @__PURE__ */ React2.createElement(View, { style: { flex: 1 } }, /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.findingCardTitle, numberOfLines: 1 }, finding.title), finding.severity && finding.type === "bug" && /* @__PURE__ */ React2.createElement(Text, { style: [
14158
+ exploreStyles.findingCardSeverity,
14159
+ finding.severity === "critical" ? { color: "#f87171" } : finding.severity === "high" ? { color: "#fb923c" } : finding.severity === "medium" ? { color: "#facc15" } : { color: "#a1a1aa" }
14160
+ ] }, finding.severity))
14161
+ )))), /* @__PURE__ */ React2.createElement(
14162
+ TouchableOpacity,
14163
+ {
14164
+ onPress: () => setShowEndConfirm(true),
14165
+ style: exploreStyles.endSessionButton
14166
+ },
14167
+ /* @__PURE__ */ React2.createElement(Text, { style: exploreStyles.endSessionButtonText }, "End Session")
14168
+ ))
14169
+ )), activeTab === "report" && /* @__PURE__ */ React2.createElement(View, null, submitted ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u{1F389}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Report submitted!")) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(View, { style: styles.reportTypes }, [
14170
+ { type: "bug", label: "\u{1F41B} Bug" },
14171
+ { type: "feedback", label: "\u{1F4A1} Feedback" },
14172
+ { type: "suggestion", label: "\u2728 Idea" }
14173
+ ].map(({ type, label }) => /* @__PURE__ */ React2.createElement(
14174
+ TouchableOpacity,
14175
+ {
14176
+ key: type,
14177
+ style: [
14178
+ styles.reportTypeButton,
14179
+ reportType === type && styles.reportTypeActive
14180
+ ],
14181
+ onPress: () => setReportType(type)
14182
+ },
14183
+ /* @__PURE__ */ React2.createElement(Text, { style: [
14184
+ styles.reportTypeText,
14185
+ reportType === type && styles.reportTypeTextActive
14186
+ ] }, label)
14187
+ ))), (reportType === "bug" || reportType === "test_fail") && /* @__PURE__ */ React2.createElement(View, { style: styles.severitySection }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "Severity"), /* @__PURE__ */ React2.createElement(View, { style: styles.severityButtons }, ["critical", "high", "medium", "low"].map((sev) => {
14188
+ const activeStyles = {
14189
+ critical: styles.severityCriticalActive,
14190
+ high: styles.severityHighActive,
14191
+ medium: styles.severityMediumActive,
14192
+ low: styles.severityLowActive
14193
+ };
14194
+ return /* @__PURE__ */ React2.createElement(
14195
+ TouchableOpacity,
12946
14196
  {
12947
14197
  key: sev,
12948
14198
  style: [
@@ -12963,7 +14213,7 @@ function BugBearButton({
12963
14213
  value: description,
12964
14214
  onChangeText: setDescription,
12965
14215
  placeholder: "Describe the issue...",
12966
- placeholderTextColor: "#9CA3AF",
14216
+ placeholderTextColor: "#71717a",
12967
14217
  multiline: true,
12968
14218
  numberOfLines: 4,
12969
14219
  textAlignVertical: "top"
@@ -12988,7 +14238,7 @@ function BugBearButton({
12988
14238
  value: profileName,
12989
14239
  onChangeText: setProfileName,
12990
14240
  placeholder: "Your name",
12991
- placeholderTextColor: "#9CA3AF"
14241
+ placeholderTextColor: "#71717a"
12992
14242
  }
12993
14243
  )), /* @__PURE__ */ React2.createElement(View, { style: styles.profileSection }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "Primary Email"), /* @__PURE__ */ React2.createElement(View, { style: styles.profileReadOnly }, /* @__PURE__ */ React2.createElement(Text, { style: styles.profileReadOnlyText }, testerInfo?.email), /* @__PURE__ */ React2.createElement(Text, { style: styles.profileReadOnlyHint }, "Main communication email"))), /* @__PURE__ */ React2.createElement(View, { style: styles.profileSection }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "Additional Testing Emails"), /* @__PURE__ */ React2.createElement(Text, { style: styles.profileHint }, "Add other emails you use to test on different accounts"), profileAdditionalEmails.map((email) => /* @__PURE__ */ React2.createElement(View, { key: email, style: styles.emailChip }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emailChipText }, email), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: () => handleRemoveEmail(email) }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emailChipRemove }, "\u2715")))), /* @__PURE__ */ React2.createElement(View, { style: styles.addEmailRow }, /* @__PURE__ */ React2.createElement(
12994
14244
  TextInput,
@@ -12997,7 +14247,7 @@ function BugBearButton({
12997
14247
  value: newEmailInput,
12998
14248
  onChangeText: setNewEmailInput,
12999
14249
  placeholder: "email@example.com",
13000
- placeholderTextColor: "#9CA3AF",
14250
+ placeholderTextColor: "#71717a",
13001
14251
  keyboardType: "email-address",
13002
14252
  autoCapitalize: "none"
13003
14253
  }
@@ -13062,7 +14312,7 @@ function BugBearButton({
13062
14312
  value: replyText,
13063
14313
  onChangeText: setReplyText,
13064
14314
  placeholder: "Type a reply...",
13065
- placeholderTextColor: "#9CA3AF",
14315
+ placeholderTextColor: "#71717a",
13066
14316
  multiline: true,
13067
14317
  maxLength: 1e3
13068
14318
  }
@@ -13080,9 +14330,64 @@ function BugBearButton({
13080
14330
  ))
13081
14331
  ) : (
13082
14332
  /* Standard Footer */
13083
- /* @__PURE__ */ React2.createElement(View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, pendingCount, " pending \xB7 ", inProgressCount, " in progress"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))))
14333
+ /* @__PURE__ */ React2.createElement(View, { style: styles.footer }, activeTab === "messages" ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, threads.length, " thread", threads.length !== 1 ? "s" : "", " \xB7 ", unreadCount, " unread"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshThreads }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))) : activeTab === "explore" ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, activeSession ? `${sessionFindings.length} findings` : "No active session"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshSession }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.footerText }, pendingCount, " pending \xB7 ", inProgressCount, " in progress"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: refreshAssignments }, /* @__PURE__ */ React2.createElement(Text, { style: styles.refreshText }, "\u21BB Refresh"))))
13084
14334
  ))
13085
14335
  )
14336
+ ), /* @__PURE__ */ React2.createElement(
14337
+ Modal,
14338
+ {
14339
+ visible: showSkipModal,
14340
+ transparent: true,
14341
+ animationType: "fade",
14342
+ onRequestClose: () => setShowSkipModal(false)
14343
+ },
14344
+ /* @__PURE__ */ React2.createElement(View, { style: styles.skipModalOverlay }, /* @__PURE__ */ React2.createElement(View, { style: styles.skipModalContent }, /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalTitle }, "Skip Test"), /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalSubtitle }, "Why are you skipping this test?"), /* @__PURE__ */ React2.createElement(View, { style: styles.skipReasonOptions }, [
14345
+ { value: "blocked", label: "\u{1F6AB} Blocked", desc: "Something is preventing testing" },
14346
+ { value: "not_ready", label: "\u{1F6A7} Not Ready", desc: "Feature not yet implemented" },
14347
+ { value: "dependency", label: "\u{1F517} Dependency", desc: "Waiting on another test/feature" },
14348
+ { value: "other", label: "\u{1F4DD} Other", desc: "Different reason" }
14349
+ ].map((option) => /* @__PURE__ */ React2.createElement(
14350
+ TouchableOpacity,
14351
+ {
14352
+ key: option.value,
14353
+ style: [
14354
+ styles.skipReasonOption,
14355
+ selectedSkipReason === option.value && styles.skipReasonOptionSelected
14356
+ ],
14357
+ onPress: () => setSelectedSkipReason(option.value)
14358
+ },
14359
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipReasonLabel }, option.label),
14360
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipReasonDesc }, option.desc)
14361
+ ))), /* @__PURE__ */ React2.createElement(
14362
+ TextInput,
14363
+ {
14364
+ style: styles.skipNotesInput,
14365
+ value: skipNotes,
14366
+ onChangeText: setSkipNotes,
14367
+ placeholder: "Add notes (optional)...",
14368
+ placeholderTextColor: "#71717a",
14369
+ multiline: true,
14370
+ numberOfLines: 2
14371
+ }
14372
+ ), /* @__PURE__ */ React2.createElement(View, { style: styles.skipModalActions }, /* @__PURE__ */ React2.createElement(
14373
+ TouchableOpacity,
14374
+ {
14375
+ style: styles.skipModalCancel,
14376
+ onPress: () => setShowSkipModal(false)
14377
+ },
14378
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalCancelText }, "Cancel")
14379
+ ), /* @__PURE__ */ React2.createElement(
14380
+ TouchableOpacity,
14381
+ {
14382
+ style: [
14383
+ styles.skipModalConfirm,
14384
+ !selectedSkipReason && styles.skipModalConfirmDisabled
14385
+ ],
14386
+ onPress: handleSkip,
14387
+ disabled: !selectedSkipReason || skipping
14388
+ },
14389
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.skipModalConfirmText }, skipping ? "Skipping..." : "Skip Test")
14390
+ ))))
13086
14391
  ));
13087
14392
  }
13088
14393
  var styles = StyleSheet.create({
@@ -13091,13 +14396,13 @@ var styles = StyleSheet.create({
13091
14396
  width: 56,
13092
14397
  height: 56,
13093
14398
  borderRadius: 28,
13094
- backgroundColor: "#7C3AED",
14399
+ backgroundColor: "#3B82F6",
13095
14400
  justifyContent: "center",
13096
14401
  alignItems: "center",
13097
- shadowColor: "#000",
14402
+ shadowColor: "#3B82F6",
13098
14403
  shadowOffset: { width: 0, height: 4 },
13099
- shadowOpacity: 0.3,
13100
- shadowRadius: 8,
14404
+ shadowOpacity: 0.4,
14405
+ shadowRadius: 12,
13101
14406
  elevation: 8,
13102
14407
  zIndex: 999999
13103
14408
  },
@@ -13130,10 +14435,10 @@ var styles = StyleSheet.create({
13130
14435
  modalContainer: {
13131
14436
  flex: 1,
13132
14437
  justifyContent: "flex-end",
13133
- backgroundColor: "rgba(0, 0, 0, 0.5)"
14438
+ backgroundColor: "rgba(0, 0, 0, 0.6)"
13134
14439
  },
13135
14440
  modalContent: {
13136
- backgroundColor: "#fff",
14441
+ backgroundColor: "#18181b",
13137
14442
  borderTopLeftRadius: 20,
13138
14443
  borderTopRightRadius: 20,
13139
14444
  maxHeight: "85%"
@@ -13142,11 +14447,13 @@ var styles = StyleSheet.create({
13142
14447
  flexDirection: "row",
13143
14448
  alignItems: "center",
13144
14449
  justifyContent: "space-between",
13145
- backgroundColor: "#7C3AED",
14450
+ backgroundColor: "#09090b",
13146
14451
  paddingHorizontal: 16,
13147
14452
  paddingVertical: 12,
13148
14453
  borderTopLeftRadius: 20,
13149
- borderTopRightRadius: 20
14454
+ borderTopRightRadius: 20,
14455
+ borderBottomWidth: 1,
14456
+ borderBottomColor: "#27272a"
13150
14457
  },
13151
14458
  headerLeft: {
13152
14459
  flexDirection: "row",
@@ -13157,12 +14464,12 @@ var styles = StyleSheet.create({
13157
14464
  marginRight: 10
13158
14465
  },
13159
14466
  headerTitle: {
13160
- color: "#fff",
14467
+ color: "#fafafa",
13161
14468
  fontSize: 16,
13162
14469
  fontWeight: "600"
13163
14470
  },
13164
14471
  headerSubtitle: {
13165
- color: "#DDD6FE",
14472
+ color: "#71717a",
13166
14473
  fontSize: 12
13167
14474
  },
13168
14475
  headerNameButton: {
@@ -13171,20 +14478,21 @@ var styles = StyleSheet.create({
13171
14478
  gap: 4
13172
14479
  },
13173
14480
  headerPencil: {
13174
- color: "#DDD6FE",
14481
+ color: "#71717a",
13175
14482
  fontSize: 11
13176
14483
  },
13177
14484
  closeButton: {
13178
14485
  padding: 8
13179
14486
  },
13180
14487
  closeButtonText: {
13181
- color: "#fff",
14488
+ color: "#a1a1aa",
13182
14489
  fontSize: 18
13183
14490
  },
13184
14491
  tabs: {
13185
14492
  flexDirection: "row",
13186
14493
  borderBottomWidth: 1,
13187
- borderBottomColor: "#E5E7EB"
14494
+ borderBottomColor: "#27272a",
14495
+ backgroundColor: "#18181b"
13188
14496
  },
13189
14497
  tab: {
13190
14498
  flex: 1,
@@ -13193,15 +14501,15 @@ var styles = StyleSheet.create({
13193
14501
  },
13194
14502
  activeTab: {
13195
14503
  borderBottomWidth: 2,
13196
- borderBottomColor: "#7C3AED"
14504
+ borderBottomColor: "#3B82F6"
13197
14505
  },
13198
14506
  tabText: {
13199
14507
  fontSize: 14,
13200
14508
  fontWeight: "500",
13201
- color: "#6B7280"
14509
+ color: "#71717a"
13202
14510
  },
13203
14511
  activeTabText: {
13204
- color: "#7C3AED"
14512
+ color: "#3B82F6"
13205
14513
  },
13206
14514
  content: {
13207
14515
  padding: 16,
@@ -13214,16 +14522,16 @@ var styles = StyleSheet.create({
13214
14522
  paddingHorizontal: 16,
13215
14523
  paddingVertical: 12,
13216
14524
  borderTopWidth: 1,
13217
- borderTopColor: "#E5E7EB",
13218
- backgroundColor: "#F9FAFB"
14525
+ borderTopColor: "#27272a",
14526
+ backgroundColor: "#09090b"
13219
14527
  },
13220
14528
  footerText: {
13221
14529
  fontSize: 12,
13222
- color: "#9CA3AF"
14530
+ color: "#52525b"
13223
14531
  },
13224
14532
  refreshText: {
13225
14533
  fontSize: 12,
13226
- color: "#6B7280"
14534
+ color: "#71717a"
13227
14535
  },
13228
14536
  emptyState: {
13229
14537
  alignItems: "center",
@@ -13235,7 +14543,7 @@ var styles = StyleSheet.create({
13235
14543
  emptyTitle: {
13236
14544
  fontSize: 18,
13237
14545
  fontWeight: "600",
13238
- color: "#374151",
14546
+ color: "#e4e4e7",
13239
14547
  marginTop: 12
13240
14548
  },
13241
14549
  passedEmoji: {
@@ -13250,26 +14558,26 @@ var styles = StyleSheet.create({
13250
14558
  },
13251
14559
  emptySubtitle: {
13252
14560
  fontSize: 14,
13253
- color: "#9CA3AF",
14561
+ color: "#71717a",
13254
14562
  marginTop: 4
13255
14563
  },
13256
14564
  // List view styles
13257
14565
  listHeader: {
13258
14566
  fontSize: 12,
13259
- color: "#6B7280",
14567
+ color: "#71717a",
13260
14568
  marginBottom: 12
13261
14569
  },
13262
14570
  listItem: {
13263
- backgroundColor: "#F9FAFB",
14571
+ backgroundColor: "#27272a",
13264
14572
  borderRadius: 12,
13265
14573
  padding: 12,
13266
14574
  marginBottom: 8,
13267
14575
  borderWidth: 1,
13268
- borderColor: "#E5E7EB"
14576
+ borderColor: "#3f3f46"
13269
14577
  },
13270
14578
  listItemCurrent: {
13271
- backgroundColor: "#EDE9FE",
13272
- borderColor: "#C4B5FD"
14579
+ backgroundColor: "#1e3a5f",
14580
+ borderColor: "#3B82F6"
13273
14581
  },
13274
14582
  listItemHeader: {
13275
14583
  flexDirection: "row",
@@ -13280,7 +14588,7 @@ var styles = StyleSheet.create({
13280
14588
  listItemKey: {
13281
14589
  fontSize: 12,
13282
14590
  fontFamily: Platform2.OS === "ios" ? "Menlo" : "monospace",
13283
- color: "#6B7280"
14591
+ color: "#71717a"
13284
14592
  },
13285
14593
  listItemBadges: {
13286
14594
  flexDirection: "row",
@@ -13289,7 +14597,7 @@ var styles = StyleSheet.create({
13289
14597
  listItemTitle: {
13290
14598
  fontSize: 14,
13291
14599
  fontWeight: "600",
13292
- color: "#111827",
14600
+ color: "#fafafa",
13293
14601
  marginBottom: 4
13294
14602
  },
13295
14603
  listItemMeta: {
@@ -13298,11 +14606,11 @@ var styles = StyleSheet.create({
13298
14606
  },
13299
14607
  listItemMetaText: {
13300
14608
  fontSize: 12,
13301
- color: "#9CA3AF"
14609
+ color: "#71717a"
13302
14610
  },
13303
14611
  currentBadge: {
13304
14612
  fontSize: 12,
13305
- color: "#7C3AED",
14613
+ color: "#3B82F6",
13306
14614
  fontWeight: "600",
13307
14615
  marginLeft: 8
13308
14616
  },
@@ -13312,15 +14620,17 @@ var styles = StyleSheet.create({
13312
14620
  },
13313
14621
  backButtonText: {
13314
14622
  fontSize: 14,
13315
- color: "#7C3AED",
14623
+ color: "#3B82F6",
13316
14624
  fontWeight: "500"
13317
14625
  },
13318
14626
  // Test card styles
13319
14627
  testCard: {
13320
- backgroundColor: "#F9FAFB",
14628
+ backgroundColor: "#27272a",
13321
14629
  borderRadius: 12,
13322
14630
  padding: 16,
13323
- marginBottom: 16
14631
+ marginBottom: 16,
14632
+ borderWidth: 1,
14633
+ borderColor: "#3f3f46"
13324
14634
  },
13325
14635
  testHeader: {
13326
14636
  flexDirection: "row",
@@ -13335,7 +14645,7 @@ var styles = StyleSheet.create({
13335
14645
  testKey: {
13336
14646
  fontSize: 12,
13337
14647
  fontFamily: Platform2.OS === "ios" ? "Menlo" : "monospace",
13338
- color: "#6B7280"
14648
+ color: "#71717a"
13339
14649
  },
13340
14650
  trackBadge: {
13341
14651
  paddingHorizontal: 6,
@@ -13347,38 +14657,38 @@ var styles = StyleSheet.create({
13347
14657
  color: "#fff"
13348
14658
  },
13349
14659
  priorityBadge: {
13350
- backgroundColor: "#E5E7EB",
14660
+ backgroundColor: "#3f3f46",
13351
14661
  paddingHorizontal: 8,
13352
14662
  paddingVertical: 2,
13353
14663
  borderRadius: 4
13354
14664
  },
13355
14665
  priorityP0: {
13356
- backgroundColor: "#FEE2E2"
14666
+ backgroundColor: "#7f1d1d"
13357
14667
  },
13358
14668
  priorityP1: {
13359
- backgroundColor: "#FED7AA"
14669
+ backgroundColor: "#78350f"
13360
14670
  },
13361
14671
  priorityText: {
13362
14672
  fontSize: 12,
13363
14673
  fontWeight: "600",
13364
- color: "#374151"
14674
+ color: "#e4e4e7"
13365
14675
  },
13366
14676
  testTitle: {
13367
14677
  fontSize: 16,
13368
14678
  fontWeight: "600",
13369
- color: "#111827",
14679
+ color: "#fafafa",
13370
14680
  marginBottom: 4
13371
14681
  },
13372
14682
  testDescription: {
13373
14683
  fontSize: 14,
13374
- color: "#6B7280",
14684
+ color: "#a1a1aa",
13375
14685
  marginBottom: 8
13376
14686
  },
13377
14687
  // Navigate button
13378
14688
  navigateButton: {
13379
- backgroundColor: "#EFF6FF",
14689
+ backgroundColor: "#1e3a5f",
13380
14690
  borderWidth: 1,
13381
- borderColor: "#BFDBFE",
14691
+ borderColor: "#3B82F6",
13382
14692
  borderRadius: 8,
13383
14693
  paddingVertical: 10,
13384
14694
  paddingHorizontal: 16,
@@ -13388,7 +14698,7 @@ var styles = StyleSheet.create({
13388
14698
  navigateButtonText: {
13389
14699
  fontSize: 14,
13390
14700
  fontWeight: "500",
13391
- color: "#1D4ED8"
14701
+ color: "#60a5fa"
13392
14702
  },
13393
14703
  // Template badge
13394
14704
  templateBadge: {
@@ -13406,12 +14716,12 @@ var styles = StyleSheet.create({
13406
14716
  templateName: {
13407
14717
  fontSize: 12,
13408
14718
  fontWeight: "600",
13409
- color: "#374151",
14719
+ color: "#e4e4e7",
13410
14720
  marginRight: 4
13411
14721
  },
13412
14722
  templateAction: {
13413
14723
  fontSize: 12,
13414
- color: "#6B7280"
14724
+ color: "#71717a"
13415
14725
  },
13416
14726
  // Steps toggle
13417
14727
  stepsToggle: {
@@ -13419,7 +14729,7 @@ var styles = StyleSheet.create({
13419
14729
  },
13420
14730
  stepsToggleText: {
13421
14731
  fontSize: 14,
13422
- color: "#7C3AED",
14732
+ color: "#3B82F6",
13423
14733
  fontWeight: "500"
13424
14734
  },
13425
14735
  stepsList: {
@@ -13433,7 +14743,7 @@ var styles = StyleSheet.create({
13433
14743
  width: 24,
13434
14744
  height: 24,
13435
14745
  borderRadius: 12,
13436
- backgroundColor: "#EDE9FE",
14746
+ backgroundColor: "#1e3a5f",
13437
14747
  justifyContent: "center",
13438
14748
  alignItems: "center",
13439
14749
  marginRight: 12
@@ -13441,41 +14751,41 @@ var styles = StyleSheet.create({
13441
14751
  stepNumberText: {
13442
14752
  fontSize: 12,
13443
14753
  fontWeight: "600",
13444
- color: "#7C3AED"
14754
+ color: "#3B82F6"
13445
14755
  },
13446
14756
  stepContent: {
13447
14757
  flex: 1
13448
14758
  },
13449
14759
  stepAction: {
13450
14760
  fontSize: 14,
13451
- color: "#374151"
14761
+ color: "#e4e4e7"
13452
14762
  },
13453
14763
  stepExpected: {
13454
14764
  fontSize: 12,
13455
- color: "#9CA3AF",
14765
+ color: "#71717a",
13456
14766
  marginTop: 2
13457
14767
  },
13458
14768
  // Checklist styles
13459
14769
  checklistItem: {
13460
14770
  flexDirection: "row",
13461
14771
  alignItems: "center",
13462
- backgroundColor: "#fff",
14772
+ backgroundColor: "#27272a",
13463
14773
  borderWidth: 1,
13464
- borderColor: "#E5E7EB",
14774
+ borderColor: "#3f3f46",
13465
14775
  borderRadius: 8,
13466
14776
  padding: 12,
13467
14777
  marginBottom: 8
13468
14778
  },
13469
14779
  checklistItemChecked: {
13470
- backgroundColor: "#ECFDF5",
13471
- borderColor: "#86EFAC"
14780
+ backgroundColor: "#14532d",
14781
+ borderColor: "#22C55E"
13472
14782
  },
13473
14783
  checkbox: {
13474
14784
  width: 24,
13475
14785
  height: 24,
13476
14786
  borderRadius: 4,
13477
14787
  borderWidth: 2,
13478
- borderColor: "#22D3EE",
14788
+ borderColor: "#3B82F6",
13479
14789
  marginRight: 12,
13480
14790
  justifyContent: "center",
13481
14791
  alignItems: "center"
@@ -13492,16 +14802,16 @@ var styles = StyleSheet.create({
13492
14802
  checklistText: {
13493
14803
  flex: 1,
13494
14804
  fontSize: 14,
13495
- color: "#374151"
14805
+ color: "#e4e4e7"
13496
14806
  },
13497
14807
  checklistTextChecked: {
13498
- color: "#15803D"
14808
+ color: "#4ade80"
13499
14809
  },
13500
14810
  // Rubric styles
13501
14811
  rubricItem: {
13502
- backgroundColor: "#fff",
14812
+ backgroundColor: "#27272a",
13503
14813
  borderWidth: 1,
13504
- borderColor: "#E5E7EB",
14814
+ borderColor: "#3f3f46",
13505
14815
  borderRadius: 8,
13506
14816
  padding: 12,
13507
14817
  marginBottom: 8
@@ -13515,7 +14825,7 @@ var styles = StyleSheet.create({
13515
14825
  width: 24,
13516
14826
  height: 24,
13517
14827
  borderRadius: 4,
13518
- backgroundColor: "#EDE9FE",
14828
+ backgroundColor: "#1e3a5f",
13519
14829
  justifyContent: "center",
13520
14830
  alignItems: "center",
13521
14831
  marginRight: 8
@@ -13523,17 +14833,17 @@ var styles = StyleSheet.create({
13523
14833
  rubricNumberText: {
13524
14834
  fontSize: 12,
13525
14835
  fontWeight: "600",
13526
- color: "#7C3AED"
14836
+ color: "#3B82F6"
13527
14837
  },
13528
14838
  rubricTitle: {
13529
14839
  flex: 1,
13530
14840
  fontSize: 14,
13531
14841
  fontWeight: "500",
13532
- color: "#111827"
14842
+ color: "#fafafa"
13533
14843
  },
13534
14844
  rubricExpected: {
13535
14845
  fontSize: 12,
13536
- color: "#6B7280",
14846
+ color: "#71717a",
13537
14847
  marginLeft: 32,
13538
14848
  marginBottom: 8
13539
14849
  },
@@ -13547,7 +14857,7 @@ var styles = StyleSheet.create({
13547
14857
  paddingVertical: 8,
13548
14858
  paddingHorizontal: 12,
13549
14859
  borderRadius: 6,
13550
- backgroundColor: "#F3F4F6",
14860
+ backgroundColor: "#3f3f46",
13551
14861
  alignItems: "center"
13552
14862
  },
13553
14863
  passButtonActive: {
@@ -13559,7 +14869,7 @@ var styles = StyleSheet.create({
13559
14869
  passFailButtonText: {
13560
14870
  fontSize: 12,
13561
14871
  fontWeight: "600",
13562
- color: "#6B7280"
14872
+ color: "#a1a1aa"
13563
14873
  },
13564
14874
  passButtonTextActive: {
13565
14875
  color: "#fff"
@@ -13576,17 +14886,17 @@ var styles = StyleSheet.create({
13576
14886
  width: 36,
13577
14887
  height: 36,
13578
14888
  borderRadius: 6,
13579
- backgroundColor: "#F3F4F6",
14889
+ backgroundColor: "#3f3f46",
13580
14890
  justifyContent: "center",
13581
14891
  alignItems: "center"
13582
14892
  },
13583
14893
  ratingButtonActive: {
13584
- backgroundColor: "#7C3AED"
14894
+ backgroundColor: "#3B82F6"
13585
14895
  },
13586
14896
  ratingButtonText: {
13587
14897
  fontSize: 14,
13588
14898
  fontWeight: "600",
13589
- color: "#6B7280"
14899
+ color: "#a1a1aa"
13590
14900
  },
13591
14901
  ratingButtonTextActive: {
13592
14902
  color: "#fff"
@@ -13600,17 +14910,17 @@ var styles = StyleSheet.create({
13600
14910
  },
13601
14911
  helperText: {
13602
14912
  fontSize: 12,
13603
- color: "#9CA3AF"
14913
+ color: "#71717a"
13604
14914
  },
13605
14915
  resetText: {
13606
14916
  fontSize: 12,
13607
- color: "#9CA3AF"
14917
+ color: "#71717a"
13608
14918
  },
13609
14919
  // Freeform styles
13610
14920
  freeformBox: {
13611
- backgroundColor: "#FFFBEB",
14921
+ backgroundColor: "#422006",
13612
14922
  borderWidth: 1,
13613
- borderColor: "#FDE68A",
14923
+ borderColor: "#a16207",
13614
14924
  borderRadius: 8,
13615
14925
  padding: 12,
13616
14926
  marginTop: 8
@@ -13618,22 +14928,22 @@ var styles = StyleSheet.create({
13618
14928
  freeformTitle: {
13619
14929
  fontSize: 14,
13620
14930
  fontWeight: "600",
13621
- color: "#92400E",
14931
+ color: "#fbbf24",
13622
14932
  marginBottom: 4
13623
14933
  },
13624
14934
  freeformText: {
13625
14935
  fontSize: 12,
13626
- color: "#A16207",
14936
+ color: "#fcd34d",
13627
14937
  marginBottom: 4
13628
14938
  },
13629
14939
  freeformBullet: {
13630
14940
  fontSize: 12,
13631
- color: "#A16207",
14941
+ color: "#fcd34d",
13632
14942
  marginLeft: 8
13633
14943
  },
13634
14944
  // Expected result
13635
14945
  expectedResult: {
13636
- backgroundColor: "#ECFDF5",
14946
+ backgroundColor: "#14532d",
13637
14947
  padding: 12,
13638
14948
  borderRadius: 8,
13639
14949
  marginTop: 12
@@ -13641,12 +14951,12 @@ var styles = StyleSheet.create({
13641
14951
  expectedLabel: {
13642
14952
  fontSize: 12,
13643
14953
  fontWeight: "600",
13644
- color: "#065F46",
14954
+ color: "#4ade80",
13645
14955
  marginBottom: 4
13646
14956
  },
13647
14957
  expectedText: {
13648
14958
  fontSize: 14,
13649
- color: "#047857"
14959
+ color: "#86efac"
13650
14960
  },
13651
14961
  // Action buttons
13652
14962
  actionButtons: {
@@ -13655,7 +14965,7 @@ var styles = StyleSheet.create({
13655
14965
  },
13656
14966
  failButton: {
13657
14967
  flex: 1,
13658
- backgroundColor: "#FEE2E2",
14968
+ backgroundColor: "#7f1d1d",
13659
14969
  paddingVertical: 14,
13660
14970
  borderRadius: 12,
13661
14971
  alignItems: "center"
@@ -13663,7 +14973,7 @@ var styles = StyleSheet.create({
13663
14973
  failButtonText: {
13664
14974
  fontSize: 16,
13665
14975
  fontWeight: "600",
13666
- color: "#DC2626"
14976
+ color: "#fca5a5"
13667
14977
  },
13668
14978
  passButton: {
13669
14979
  flex: 1,
@@ -13685,22 +14995,22 @@ var styles = StyleSheet.create({
13685
14995
  },
13686
14996
  reportTypeButton: {
13687
14997
  flex: 1,
13688
- backgroundColor: "#F3F4F6",
14998
+ backgroundColor: "#3f3f46",
13689
14999
  paddingVertical: 10,
13690
15000
  borderRadius: 8,
13691
15001
  alignItems: "center"
13692
15002
  },
13693
15003
  reportTypeActive: {
13694
- backgroundColor: "#EDE9FE",
15004
+ backgroundColor: "#1e3a5f",
13695
15005
  borderWidth: 2,
13696
- borderColor: "#7C3AED"
15006
+ borderColor: "#3B82F6"
13697
15007
  },
13698
15008
  reportTypeText: {
13699
15009
  fontSize: 14,
13700
- color: "#6B7280"
15010
+ color: "#a1a1aa"
13701
15011
  },
13702
15012
  reportTypeTextActive: {
13703
- color: "#7C3AED",
15013
+ color: "#3B82F6",
13704
15014
  fontWeight: "600"
13705
15015
  },
13706
15016
  severitySection: {
@@ -13709,7 +15019,7 @@ var styles = StyleSheet.create({
13709
15019
  label: {
13710
15020
  fontSize: 14,
13711
15021
  fontWeight: "500",
13712
- color: "#374151",
15022
+ color: "#e4e4e7",
13713
15023
  marginBottom: 8
13714
15024
  },
13715
15025
  severityButtons: {
@@ -13718,7 +15028,7 @@ var styles = StyleSheet.create({
13718
15028
  },
13719
15029
  severityButton: {
13720
15030
  flex: 1,
13721
- backgroundColor: "#F3F4F6",
15031
+ backgroundColor: "#3f3f46",
13722
15032
  paddingVertical: 8,
13723
15033
  borderRadius: 6,
13724
15034
  alignItems: "center"
@@ -13737,7 +15047,7 @@ var styles = StyleSheet.create({
13737
15047
  },
13738
15048
  severityText: {
13739
15049
  fontSize: 12,
13740
- color: "#6B7280",
15050
+ color: "#a1a1aa",
13741
15051
  textTransform: "capitalize"
13742
15052
  },
13743
15053
  severityTextActive: {
@@ -13748,17 +15058,17 @@ var styles = StyleSheet.create({
13748
15058
  marginBottom: 16
13749
15059
  },
13750
15060
  textInput: {
13751
- backgroundColor: "#F9FAFB",
15061
+ backgroundColor: "#27272a",
13752
15062
  borderWidth: 1,
13753
- borderColor: "#E5E7EB",
15063
+ borderColor: "#3f3f46",
13754
15064
  borderRadius: 12,
13755
15065
  padding: 12,
13756
15066
  fontSize: 14,
13757
15067
  minHeight: 100,
13758
- color: "#111827"
15068
+ color: "#fafafa"
13759
15069
  },
13760
15070
  submitButton: {
13761
- backgroundColor: "#7C3AED",
15071
+ backgroundColor: "#3B82F6",
13762
15072
  paddingVertical: 14,
13763
15073
  borderRadius: 12,
13764
15074
  alignItems: "center"
@@ -13780,6 +15090,13 @@ var styles = StyleSheet.create({
13780
15090
  flexDirection: "row",
13781
15091
  alignItems: "center"
13782
15092
  },
15093
+ sessionDot: {
15094
+ width: 8,
15095
+ height: 8,
15096
+ borderRadius: 4,
15097
+ backgroundColor: "#22c55e",
15098
+ marginLeft: 4
15099
+ },
13783
15100
  tabBadge: {
13784
15101
  backgroundColor: "#EF4444",
13785
15102
  borderRadius: 8,
@@ -13797,16 +15114,16 @@ var styles = StyleSheet.create({
13797
15114
  },
13798
15115
  // Thread list styles
13799
15116
  threadItem: {
13800
- backgroundColor: "#F9FAFB",
15117
+ backgroundColor: "#27272a",
13801
15118
  borderRadius: 12,
13802
15119
  padding: 12,
13803
15120
  marginBottom: 8,
13804
15121
  borderWidth: 1,
13805
- borderColor: "#E5E7EB"
15122
+ borderColor: "#3f3f46"
13806
15123
  },
13807
15124
  threadItemUnread: {
13808
- backgroundColor: "#EFF6FF",
13809
- borderColor: "#BFDBFE"
15125
+ backgroundColor: "#1e3a5f",
15126
+ borderColor: "#3B82F6"
13810
15127
  },
13811
15128
  threadHeader: {
13812
15129
  flexDirection: "row",
@@ -13830,12 +15147,12 @@ var styles = StyleSheet.create({
13830
15147
  threadSubject: {
13831
15148
  fontSize: 14,
13832
15149
  fontWeight: "500",
13833
- color: "#374151",
15150
+ color: "#e4e4e7",
13834
15151
  flex: 1
13835
15152
  },
13836
15153
  threadSubjectUnread: {
13837
15154
  fontWeight: "600",
13838
- color: "#111827"
15155
+ color: "#fafafa"
13839
15156
  },
13840
15157
  priorityDot: {
13841
15158
  width: 8,
@@ -13845,7 +15162,7 @@ var styles = StyleSheet.create({
13845
15162
  },
13846
15163
  threadPreview: {
13847
15164
  fontSize: 13,
13848
- color: "#6B7280",
15165
+ color: "#a1a1aa",
13849
15166
  marginBottom: 4
13850
15167
  },
13851
15168
  threadMeta: {
@@ -13855,7 +15172,7 @@ var styles = StyleSheet.create({
13855
15172
  },
13856
15173
  threadMetaText: {
13857
15174
  fontSize: 12,
13858
- color: "#9CA3AF"
15175
+ color: "#71717a"
13859
15176
  },
13860
15177
  unreadBadge: {
13861
15178
  backgroundColor: "#3B82F6",
@@ -13870,7 +15187,7 @@ var styles = StyleSheet.create({
13870
15187
  },
13871
15188
  threadTime: {
13872
15189
  fontSize: 12,
13873
- color: "#9CA3AF"
15190
+ color: "#71717a"
13874
15191
  },
13875
15192
  // Thread detail styles
13876
15193
  threadDetailContainer: {
@@ -13879,7 +15196,7 @@ var styles = StyleSheet.create({
13879
15196
  threadDetailHeader: {
13880
15197
  flexDirection: "row",
13881
15198
  alignItems: "center",
13882
- backgroundColor: "#F3F4F6",
15199
+ backgroundColor: "#27272a",
13883
15200
  padding: 12,
13884
15201
  borderRadius: 8,
13885
15202
  marginBottom: 12
@@ -13892,7 +15209,7 @@ var styles = StyleSheet.create({
13892
15209
  flex: 1,
13893
15210
  fontSize: 15,
13894
15211
  fontWeight: "600",
13895
- color: "#111827"
15212
+ color: "#fafafa"
13896
15213
  },
13897
15214
  loadingMessages: {
13898
15215
  padding: 20,
@@ -13900,7 +15217,7 @@ var styles = StyleSheet.create({
13900
15217
  },
13901
15218
  loadingText: {
13902
15219
  fontSize: 14,
13903
- color: "#6B7280"
15220
+ color: "#71717a"
13904
15221
  },
13905
15222
  messagesContainer: {
13906
15223
  paddingBottom: 8
@@ -13913,26 +15230,26 @@ var styles = StyleSheet.create({
13913
15230
  },
13914
15231
  messageBubbleAdmin: {
13915
15232
  alignSelf: "flex-start",
13916
- backgroundColor: "#F3F4F6",
15233
+ backgroundColor: "#27272a",
13917
15234
  borderBottomLeftRadius: 4
13918
15235
  },
13919
15236
  messageBubbleTester: {
13920
15237
  alignSelf: "flex-end",
13921
- backgroundColor: "#7C3AED",
15238
+ backgroundColor: "#3B82F6",
13922
15239
  borderBottomRightRadius: 4
13923
15240
  },
13924
15241
  messageSender: {
13925
15242
  fontSize: 12,
13926
15243
  fontWeight: "600",
13927
- color: "#6B7280",
15244
+ color: "#71717a",
13928
15245
  marginBottom: 2
13929
15246
  },
13930
15247
  messageSenderTester: {
13931
- color: "#DDD6FE"
15248
+ color: "#93c5fd"
13932
15249
  },
13933
15250
  messageContent: {
13934
15251
  fontSize: 14,
13935
- color: "#111827",
15252
+ color: "#fafafa",
13936
15253
  lineHeight: 20
13937
15254
  },
13938
15255
  messageContentTester: {
@@ -13940,12 +15257,12 @@ var styles = StyleSheet.create({
13940
15257
  },
13941
15258
  messageTime: {
13942
15259
  fontSize: 11,
13943
- color: "#9CA3AF",
15260
+ color: "#71717a",
13944
15261
  marginTop: 4,
13945
15262
  textAlign: "right"
13946
15263
  },
13947
15264
  messageTimeTester: {
13948
- color: "#C4B5FD"
15265
+ color: "#93c5fd"
13949
15266
  },
13950
15267
  // Reply composer styles
13951
15268
  replyComposer: {
@@ -13953,24 +15270,24 @@ var styles = StyleSheet.create({
13953
15270
  alignItems: "flex-end",
13954
15271
  padding: 12,
13955
15272
  borderTopWidth: 1,
13956
- borderTopColor: "#E5E7EB",
13957
- backgroundColor: "#fff"
15273
+ borderTopColor: "#27272a",
15274
+ backgroundColor: "#18181b"
13958
15275
  },
13959
15276
  replyInput: {
13960
15277
  flex: 1,
13961
- backgroundColor: "#F9FAFB",
15278
+ backgroundColor: "#27272a",
13962
15279
  borderWidth: 1,
13963
- borderColor: "#E5E7EB",
15280
+ borderColor: "#3f3f46",
13964
15281
  borderRadius: 20,
13965
15282
  paddingHorizontal: 16,
13966
15283
  paddingVertical: 10,
13967
15284
  fontSize: 14,
13968
- color: "#111827",
15285
+ color: "#fafafa",
13969
15286
  maxHeight: 100,
13970
15287
  marginRight: 8
13971
15288
  },
13972
15289
  sendButton: {
13973
- backgroundColor: "#7C3AED",
15290
+ backgroundColor: "#3B82F6",
13974
15291
  paddingHorizontal: 16,
13975
15292
  paddingVertical: 10,
13976
15293
  borderRadius: 20,
@@ -13978,7 +15295,7 @@ var styles = StyleSheet.create({
13978
15295
  alignItems: "center"
13979
15296
  },
13980
15297
  sendButtonDisabled: {
13981
- backgroundColor: "#C4B5FD"
15298
+ backgroundColor: "#1e40af"
13982
15299
  },
13983
15300
  sendButtonText: {
13984
15301
  fontSize: 14,
@@ -13990,7 +15307,7 @@ var styles = StyleSheet.create({
13990
15307
  flexDirection: "row",
13991
15308
  alignItems: "center",
13992
15309
  justifyContent: "center",
13993
- backgroundColor: "#7C3AED",
15310
+ backgroundColor: "#3B82F6",
13994
15311
  paddingVertical: 12,
13995
15312
  paddingHorizontal: 20,
13996
15313
  borderRadius: 12,
@@ -14012,48 +15329,50 @@ var styles = StyleSheet.create({
14012
15329
  composeTitle: {
14013
15330
  fontSize: 20,
14014
15331
  fontWeight: "600",
14015
- color: "#111827",
15332
+ color: "#fafafa",
14016
15333
  marginBottom: 4
14017
15334
  },
14018
15335
  composeSubtitle: {
14019
15336
  fontSize: 14,
14020
- color: "#6B7280"
15337
+ color: "#71717a"
14021
15338
  },
14022
15339
  composeForm: {
14023
- backgroundColor: "#F9FAFB",
15340
+ backgroundColor: "#27272a",
14024
15341
  borderRadius: 12,
14025
- padding: 16
15342
+ padding: 16,
15343
+ borderWidth: 1,
15344
+ borderColor: "#3f3f46"
14026
15345
  },
14027
15346
  composeSubjectInput: {
14028
- backgroundColor: "#fff",
15347
+ backgroundColor: "#18181b",
14029
15348
  borderWidth: 1,
14030
- borderColor: "#E5E7EB",
15349
+ borderColor: "#3f3f46",
14031
15350
  borderRadius: 8,
14032
15351
  paddingHorizontal: 12,
14033
15352
  paddingVertical: 10,
14034
15353
  fontSize: 15,
14035
- color: "#111827"
15354
+ color: "#fafafa"
14036
15355
  },
14037
15356
  composeMessageInput: {
14038
- backgroundColor: "#fff",
15357
+ backgroundColor: "#18181b",
14039
15358
  borderWidth: 1,
14040
- borderColor: "#E5E7EB",
15359
+ borderColor: "#3f3f46",
14041
15360
  borderRadius: 8,
14042
15361
  paddingHorizontal: 12,
14043
15362
  paddingVertical: 10,
14044
15363
  fontSize: 15,
14045
- color: "#111827",
15364
+ color: "#fafafa",
14046
15365
  minHeight: 120
14047
15366
  },
14048
15367
  composeSendButton: {
14049
- backgroundColor: "#7C3AED",
15368
+ backgroundColor: "#3B82F6",
14050
15369
  paddingVertical: 14,
14051
15370
  borderRadius: 12,
14052
15371
  alignItems: "center",
14053
15372
  marginTop: 20
14054
15373
  },
14055
15374
  composeSendButtonDisabled: {
14056
- backgroundColor: "#C4B5FD"
15375
+ backgroundColor: "#1e40af"
14057
15376
  },
14058
15377
  composeSendButtonText: {
14059
15378
  fontSize: 16,
@@ -14062,17 +15381,19 @@ var styles = StyleSheet.create({
14062
15381
  },
14063
15382
  // Profile styles
14064
15383
  profileCard: {
14065
- backgroundColor: "#F9FAFB",
15384
+ backgroundColor: "#27272a",
14066
15385
  borderRadius: 16,
14067
15386
  padding: 24,
14068
15387
  alignItems: "center",
14069
- marginBottom: 16
15388
+ marginBottom: 16,
15389
+ borderWidth: 1,
15390
+ borderColor: "#3f3f46"
14070
15391
  },
14071
15392
  avatarCircle: {
14072
15393
  width: 72,
14073
15394
  height: 72,
14074
15395
  borderRadius: 36,
14075
- backgroundColor: "#7C3AED",
15396
+ backgroundColor: "#3B82F6",
14076
15397
  justifyContent: "center",
14077
15398
  alignItems: "center",
14078
15399
  marginBottom: 12
@@ -14085,12 +15406,12 @@ var styles = StyleSheet.create({
14085
15406
  profileName: {
14086
15407
  fontSize: 20,
14087
15408
  fontWeight: "600",
14088
- color: "#111827",
15409
+ color: "#fafafa",
14089
15410
  marginBottom: 4
14090
15411
  },
14091
15412
  profileEmail: {
14092
15413
  fontSize: 14,
14093
- color: "#6B7280",
15414
+ color: "#71717a",
14094
15415
  marginBottom: 16
14095
15416
  },
14096
15417
  profileStats: {
@@ -14104,35 +15425,37 @@ var styles = StyleSheet.create({
14104
15425
  profileStatValue: {
14105
15426
  fontSize: 24,
14106
15427
  fontWeight: "700",
14107
- color: "#7C3AED"
15428
+ color: "#3B82F6"
14108
15429
  },
14109
15430
  profileStatLabel: {
14110
15431
  fontSize: 12,
14111
- color: "#6B7280",
15432
+ color: "#71717a",
14112
15433
  marginTop: 2
14113
15434
  },
14114
15435
  profileStatDivider: {
14115
15436
  width: 1,
14116
15437
  height: 32,
14117
- backgroundColor: "#E5E7EB"
15438
+ backgroundColor: "#3f3f46"
14118
15439
  },
14119
15440
  profileInfoSection: {
14120
- backgroundColor: "#F9FAFB",
15441
+ backgroundColor: "#27272a",
14121
15442
  borderRadius: 12,
14122
15443
  padding: 16,
14123
- marginBottom: 12
15444
+ marginBottom: 12,
15445
+ borderWidth: 1,
15446
+ borderColor: "#3f3f46"
14124
15447
  },
14125
15448
  profileInfoLabel: {
14126
15449
  fontSize: 12,
14127
15450
  fontWeight: "600",
14128
- color: "#6B7280",
15451
+ color: "#71717a",
14129
15452
  marginBottom: 8,
14130
15453
  textTransform: "uppercase",
14131
15454
  letterSpacing: 0.5
14132
15455
  },
14133
15456
  profileInfoValue: {
14134
15457
  fontSize: 14,
14135
- color: "#374151",
15458
+ color: "#e4e4e7",
14136
15459
  marginBottom: 4
14137
15460
  },
14138
15461
  platformTags: {
@@ -14141,18 +15464,18 @@ var styles = StyleSheet.create({
14141
15464
  gap: 8
14142
15465
  },
14143
15466
  platformTag: {
14144
- backgroundColor: "#EDE9FE",
15467
+ backgroundColor: "#1e3a5f",
14145
15468
  paddingHorizontal: 12,
14146
15469
  paddingVertical: 6,
14147
15470
  borderRadius: 16
14148
15471
  },
14149
15472
  platformTagText: {
14150
15473
  fontSize: 13,
14151
- color: "#7C3AED",
15474
+ color: "#60a5fa",
14152
15475
  fontWeight: "500"
14153
15476
  },
14154
15477
  editProfileButton: {
14155
- backgroundColor: "#7C3AED",
15478
+ backgroundColor: "#3B82F6",
14156
15479
  paddingVertical: 14,
14157
15480
  borderRadius: 12,
14158
15481
  alignItems: "center",
@@ -14173,48 +15496,48 @@ var styles = StyleSheet.create({
14173
15496
  profileEditTitle: {
14174
15497
  fontSize: 20,
14175
15498
  fontWeight: "600",
14176
- color: "#111827"
15499
+ color: "#fafafa"
14177
15500
  },
14178
15501
  cancelText: {
14179
15502
  fontSize: 14,
14180
- color: "#6B7280"
15503
+ color: "#71717a"
14181
15504
  },
14182
15505
  profileSection: {
14183
15506
  marginBottom: 20
14184
15507
  },
14185
15508
  profileInput: {
14186
- backgroundColor: "#F9FAFB",
15509
+ backgroundColor: "#27272a",
14187
15510
  borderWidth: 1,
14188
- borderColor: "#E5E7EB",
15511
+ borderColor: "#3f3f46",
14189
15512
  borderRadius: 10,
14190
15513
  paddingHorizontal: 14,
14191
15514
  paddingVertical: 12,
14192
15515
  fontSize: 15,
14193
- color: "#111827"
15516
+ color: "#fafafa"
14194
15517
  },
14195
15518
  profileReadOnly: {
14196
- backgroundColor: "#F3F4F6",
15519
+ backgroundColor: "#27272a",
14197
15520
  borderRadius: 10,
14198
15521
  padding: 14
14199
15522
  },
14200
15523
  profileReadOnlyText: {
14201
15524
  fontSize: 15,
14202
- color: "#374151"
15525
+ color: "#a1a1aa"
14203
15526
  },
14204
15527
  profileReadOnlyHint: {
14205
15528
  fontSize: 12,
14206
- color: "#9CA3AF",
15529
+ color: "#52525b",
14207
15530
  marginTop: 4
14208
15531
  },
14209
15532
  profileHint: {
14210
15533
  fontSize: 13,
14211
- color: "#6B7280",
15534
+ color: "#71717a",
14212
15535
  marginBottom: 12
14213
15536
  },
14214
15537
  emailChip: {
14215
15538
  flexDirection: "row",
14216
15539
  alignItems: "center",
14217
- backgroundColor: "#EDE9FE",
15540
+ backgroundColor: "#1e3a5f",
14218
15541
  paddingHorizontal: 12,
14219
15542
  paddingVertical: 8,
14220
15543
  borderRadius: 20,
@@ -14223,11 +15546,11 @@ var styles = StyleSheet.create({
14223
15546
  emailChipText: {
14224
15547
  flex: 1,
14225
15548
  fontSize: 14,
14226
- color: "#5B21B6"
15549
+ color: "#60a5fa"
14227
15550
  },
14228
15551
  emailChipRemove: {
14229
15552
  fontSize: 14,
14230
- color: "#8B5CF6",
15553
+ color: "#93c5fd",
14231
15554
  fontWeight: "600",
14232
15555
  marginLeft: 8
14233
15556
  },
@@ -14237,23 +15560,23 @@ var styles = StyleSheet.create({
14237
15560
  },
14238
15561
  addEmailInput: {
14239
15562
  flex: 1,
14240
- backgroundColor: "#F9FAFB",
15563
+ backgroundColor: "#27272a",
14241
15564
  borderWidth: 1,
14242
- borderColor: "#E5E7EB",
15565
+ borderColor: "#3f3f46",
14243
15566
  borderRadius: 10,
14244
15567
  paddingHorizontal: 14,
14245
15568
  paddingVertical: 10,
14246
15569
  fontSize: 14,
14247
- color: "#111827"
15570
+ color: "#fafafa"
14248
15571
  },
14249
15572
  addEmailButton: {
14250
- backgroundColor: "#7C3AED",
15573
+ backgroundColor: "#3B82F6",
14251
15574
  paddingHorizontal: 16,
14252
15575
  borderRadius: 10,
14253
15576
  justifyContent: "center"
14254
15577
  },
14255
15578
  addEmailButtonDisabled: {
14256
- backgroundColor: "#C4B5FD"
15579
+ backgroundColor: "#1e40af"
14257
15580
  },
14258
15581
  addEmailButtonText: {
14259
15582
  fontSize: 14,
@@ -14266,7 +15589,7 @@ var styles = StyleSheet.create({
14266
15589
  },
14267
15590
  platformButton: {
14268
15591
  flex: 1,
14269
- backgroundColor: "#F3F4F6",
15592
+ backgroundColor: "#3f3f46",
14270
15593
  paddingVertical: 12,
14271
15594
  borderRadius: 10,
14272
15595
  alignItems: "center",
@@ -14274,16 +15597,16 @@ var styles = StyleSheet.create({
14274
15597
  borderColor: "transparent"
14275
15598
  },
14276
15599
  platformButtonActive: {
14277
- backgroundColor: "#EDE9FE",
14278
- borderColor: "#7C3AED"
15600
+ backgroundColor: "#1e3a5f",
15601
+ borderColor: "#3B82F6"
14279
15602
  },
14280
15603
  platformButtonText: {
14281
15604
  fontSize: 13,
14282
- color: "#6B7280",
15605
+ color: "#a1a1aa",
14283
15606
  fontWeight: "500"
14284
15607
  },
14285
15608
  platformButtonTextActive: {
14286
- color: "#7C3AED"
15609
+ color: "#3B82F6"
14287
15610
  },
14288
15611
  saveProfileButton: {
14289
15612
  backgroundColor: "#16A34A",
@@ -14307,7 +15630,7 @@ var styles = StyleSheet.create({
14307
15630
  left: 0,
14308
15631
  right: 0,
14309
15632
  bottom: 0,
14310
- backgroundColor: "#fff",
15633
+ backgroundColor: "#18181b",
14311
15634
  zIndex: 100
14312
15635
  },
14313
15636
  profileOverlayContent: {
@@ -14316,9 +15639,9 @@ var styles = StyleSheet.create({
14316
15639
  },
14317
15640
  profileOverlayFooter: {
14318
15641
  borderTopWidth: 1,
14319
- borderTopColor: "#E5E7EB",
15642
+ borderTopColor: "#27272a",
14320
15643
  padding: 12,
14321
- backgroundColor: "#F9FAFB"
15644
+ backgroundColor: "#09090b"
14322
15645
  },
14323
15646
  closeProfileButton: {
14324
15647
  paddingVertical: 8,
@@ -14327,7 +15650,666 @@ var styles = StyleSheet.create({
14327
15650
  closeProfileButtonText: {
14328
15651
  fontSize: 14,
14329
15652
  fontWeight: "500",
14330
- color: "#7C3AED"
15653
+ color: "#3B82F6"
15654
+ },
15655
+ // Folder grouping styles
15656
+ folderContainer: {
15657
+ marginBottom: 12
15658
+ },
15659
+ folderHeader: {
15660
+ flexDirection: "row",
15661
+ justifyContent: "space-between",
15662
+ alignItems: "center",
15663
+ backgroundColor: "#27272a",
15664
+ padding: 12,
15665
+ borderRadius: 8,
15666
+ marginBottom: 4
15667
+ },
15668
+ folderHeaderLeft: {
15669
+ flexDirection: "row",
15670
+ alignItems: "center",
15671
+ flex: 1
15672
+ },
15673
+ folderIcon: {
15674
+ fontSize: 16,
15675
+ marginRight: 8
15676
+ },
15677
+ folderName: {
15678
+ fontSize: 14,
15679
+ fontWeight: "600",
15680
+ color: "#fafafa"
15681
+ },
15682
+ folderStats: {
15683
+ flexDirection: "row",
15684
+ alignItems: "center"
15685
+ },
15686
+ folderProgress: {
15687
+ fontSize: 12,
15688
+ color: "#71717a",
15689
+ marginRight: 8
15690
+ },
15691
+ folderChevron: {
15692
+ fontSize: 10,
15693
+ color: "#71717a"
15694
+ },
15695
+ folderProgressBar: {
15696
+ height: 3,
15697
+ backgroundColor: "#3f3f46",
15698
+ borderRadius: 2,
15699
+ marginBottom: 8,
15700
+ marginHorizontal: 4
15701
+ },
15702
+ folderProgressFill: {
15703
+ height: "100%",
15704
+ backgroundColor: "#22c55e",
15705
+ borderRadius: 2
15706
+ },
15707
+ listItemInFolder: {
15708
+ marginLeft: 12,
15709
+ borderLeftWidth: 2,
15710
+ borderLeftColor: "#3f3f46",
15711
+ paddingLeft: 12
15712
+ },
15713
+ listItemKeyWithStatus: {
15714
+ flexDirection: "row",
15715
+ alignItems: "center",
15716
+ flex: 1
15717
+ },
15718
+ statusBadge: {
15719
+ flexDirection: "row",
15720
+ alignItems: "center",
15721
+ paddingHorizontal: 6,
15722
+ paddingVertical: 2,
15723
+ borderRadius: 4,
15724
+ marginLeft: 8
15725
+ },
15726
+ statusBadgeIcon: {
15727
+ fontSize: 10,
15728
+ marginRight: 4
15729
+ },
15730
+ statusBadgeText: {
15731
+ fontSize: 10,
15732
+ fontWeight: "600"
15733
+ },
15734
+ // Skip button styles
15735
+ skipButton: {
15736
+ flex: 1,
15737
+ backgroundColor: "#eab308",
15738
+ paddingVertical: 14,
15739
+ borderRadius: 12,
15740
+ alignItems: "center",
15741
+ marginHorizontal: 4
15742
+ },
15743
+ skipButtonText: {
15744
+ fontSize: 15,
15745
+ fontWeight: "600",
15746
+ color: "#18181b"
15747
+ },
15748
+ // Skip modal styles
15749
+ skipModalOverlay: {
15750
+ flex: 1,
15751
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
15752
+ justifyContent: "center",
15753
+ alignItems: "center",
15754
+ padding: 20
15755
+ },
15756
+ skipModalContent: {
15757
+ backgroundColor: "#18181b",
15758
+ borderRadius: 16,
15759
+ padding: 20,
15760
+ width: "100%",
15761
+ maxWidth: 340,
15762
+ borderWidth: 1,
15763
+ borderColor: "#3f3f46"
15764
+ },
15765
+ skipModalTitle: {
15766
+ fontSize: 18,
15767
+ fontWeight: "600",
15768
+ color: "#fafafa",
15769
+ marginBottom: 4
15770
+ },
15771
+ skipModalSubtitle: {
15772
+ fontSize: 14,
15773
+ color: "#71717a",
15774
+ marginBottom: 16
15775
+ },
15776
+ skipReasonOptions: {
15777
+ marginBottom: 16
15778
+ },
15779
+ skipReasonOption: {
15780
+ backgroundColor: "#27272a",
15781
+ padding: 12,
15782
+ borderRadius: 8,
15783
+ marginBottom: 8,
15784
+ borderWidth: 2,
15785
+ borderColor: "transparent"
15786
+ },
15787
+ skipReasonOptionSelected: {
15788
+ borderColor: "#eab308",
15789
+ backgroundColor: "#422006"
15790
+ },
15791
+ skipReasonLabel: {
15792
+ fontSize: 14,
15793
+ fontWeight: "600",
15794
+ color: "#fafafa",
15795
+ marginBottom: 2
15796
+ },
15797
+ skipReasonDesc: {
15798
+ fontSize: 12,
15799
+ color: "#71717a"
15800
+ },
15801
+ skipNotesInput: {
15802
+ backgroundColor: "#27272a",
15803
+ borderWidth: 1,
15804
+ borderColor: "#3f3f46",
15805
+ borderRadius: 8,
15806
+ padding: 12,
15807
+ fontSize: 14,
15808
+ color: "#fafafa",
15809
+ minHeight: 60,
15810
+ textAlignVertical: "top",
15811
+ marginBottom: 16
15812
+ },
15813
+ skipModalActions: {
15814
+ flexDirection: "row",
15815
+ gap: 8
15816
+ },
15817
+ skipModalCancel: {
15818
+ flex: 1,
15819
+ backgroundColor: "#3f3f46",
15820
+ paddingVertical: 12,
15821
+ borderRadius: 8,
15822
+ alignItems: "center"
15823
+ },
15824
+ skipModalCancelText: {
15825
+ fontSize: 14,
15826
+ fontWeight: "600",
15827
+ color: "#e4e4e7"
15828
+ },
15829
+ skipModalConfirm: {
15830
+ flex: 1,
15831
+ backgroundColor: "#eab308",
15832
+ paddingVertical: 12,
15833
+ borderRadius: 8,
15834
+ alignItems: "center"
15835
+ },
15836
+ skipModalConfirmDisabled: {
15837
+ backgroundColor: "#713f12"
15838
+ },
15839
+ skipModalConfirmText: {
15840
+ fontSize: 14,
15841
+ fontWeight: "600",
15842
+ color: "#18181b"
15843
+ },
15844
+ // Detail progress bar styles
15845
+ detailProgressContainer: {
15846
+ backgroundColor: "#27272a",
15847
+ padding: 12,
15848
+ borderRadius: 8,
15849
+ marginTop: 16,
15850
+ marginBottom: 8
15851
+ },
15852
+ detailProgressText: {
15853
+ fontSize: 12,
15854
+ color: "#a1a1aa",
15855
+ marginBottom: 8
15856
+ },
15857
+ detailProgressBar: {
15858
+ height: 4,
15859
+ backgroundColor: "#3f3f46",
15860
+ borderRadius: 2
15861
+ },
15862
+ detailProgressFill: {
15863
+ height: "100%",
15864
+ backgroundColor: "#22c55e",
15865
+ borderRadius: 2
15866
+ }
15867
+ });
15868
+ var exploreStyles = StyleSheet.create({
15869
+ formGroup: {
15870
+ marginBottom: 12
15871
+ },
15872
+ label: {
15873
+ fontSize: 12,
15874
+ fontWeight: "500",
15875
+ color: "#d4d4d8",
15876
+ marginBottom: 6
15877
+ },
15878
+ input: {
15879
+ backgroundColor: "#27272a",
15880
+ borderRadius: 8,
15881
+ paddingHorizontal: 12,
15882
+ paddingVertical: 10,
15883
+ fontSize: 14,
15884
+ color: "#fafafa",
15885
+ borderWidth: 1,
15886
+ borderColor: "#3f3f46"
15887
+ },
15888
+ platformRow: {
15889
+ flexDirection: "row",
15890
+ gap: 8
15891
+ },
15892
+ platformButton: {
15893
+ flex: 1,
15894
+ paddingVertical: 10,
15895
+ paddingHorizontal: 8,
15896
+ borderRadius: 8,
15897
+ backgroundColor: "#27272a",
15898
+ borderWidth: 2,
15899
+ borderColor: "transparent",
15900
+ alignItems: "center"
15901
+ },
15902
+ platformButtonActive: {
15903
+ backgroundColor: "#172554",
15904
+ borderColor: "#3B82F6"
15905
+ },
15906
+ platformButtonText: {
15907
+ fontSize: 12,
15908
+ fontWeight: "500",
15909
+ color: "#a1a1aa"
15910
+ },
15911
+ platformButtonTextActive: {
15912
+ color: "#93c5fd"
15913
+ },
15914
+ startButton: {
15915
+ backgroundColor: "#16a34a",
15916
+ borderRadius: 8,
15917
+ paddingVertical: 14,
15918
+ alignItems: "center",
15919
+ marginTop: 4
15920
+ },
15921
+ startButtonText: {
15922
+ color: "#fff",
15923
+ fontSize: 14,
15924
+ fontWeight: "600"
15925
+ },
15926
+ buttonRow: {
15927
+ flexDirection: "row",
15928
+ gap: 8
15929
+ },
15930
+ cancelButton: {
15931
+ flex: 1,
15932
+ backgroundColor: "#3f3f46",
15933
+ borderRadius: 8,
15934
+ paddingVertical: 10,
15935
+ alignItems: "center"
15936
+ },
15937
+ cancelButtonText: {
15938
+ color: "#d4d4d8",
15939
+ fontSize: 14,
15940
+ fontWeight: "500"
15941
+ },
15942
+ endButton: {
15943
+ flex: 1,
15944
+ backgroundColor: "#dc2626",
15945
+ borderRadius: 8,
15946
+ paddingVertical: 10,
15947
+ alignItems: "center"
15948
+ },
15949
+ endButtonText: {
15950
+ color: "#fff",
15951
+ fontSize: 14,
15952
+ fontWeight: "500"
15953
+ },
15954
+ findingHeader: {
15955
+ flexDirection: "row",
15956
+ justifyContent: "space-between",
15957
+ alignItems: "center",
15958
+ marginBottom: 12
15959
+ },
15960
+ findingHeaderTitle: {
15961
+ fontSize: 14,
15962
+ fontWeight: "600",
15963
+ color: "#fafafa"
15964
+ },
15965
+ findingHeaderClose: {
15966
+ fontSize: 16,
15967
+ color: "#71717a"
15968
+ },
15969
+ findingTypeRow: {
15970
+ flexDirection: "row",
15971
+ gap: 4,
15972
+ marginBottom: 12
15973
+ },
15974
+ findingTypeButton: {
15975
+ flex: 1,
15976
+ paddingVertical: 8,
15977
+ paddingHorizontal: 4,
15978
+ borderRadius: 6,
15979
+ backgroundColor: "#3f3f46",
15980
+ alignItems: "center"
15981
+ },
15982
+ findingTypeButtonActive: {
15983
+ backgroundColor: "#1e3a5f",
15984
+ borderWidth: 2,
15985
+ borderColor: "#3B82F6"
15986
+ },
15987
+ findingTypeButtonText: {
15988
+ fontSize: 11,
15989
+ fontWeight: "500",
15990
+ color: "#a1a1aa"
15991
+ },
15992
+ findingTypeButtonTextActive: {
15993
+ color: "#93c5fd"
15994
+ },
15995
+ severityRow: {
15996
+ flexDirection: "row",
15997
+ gap: 4
15998
+ },
15999
+ severityButton: {
16000
+ flex: 1,
16001
+ paddingVertical: 6,
16002
+ borderRadius: 6,
16003
+ backgroundColor: "#3f3f46",
16004
+ alignItems: "center"
16005
+ },
16006
+ severityCritical: {
16007
+ backgroundColor: "#dc2626"
16008
+ },
16009
+ severityHigh: {
16010
+ backgroundColor: "#f97316"
16011
+ },
16012
+ severityMedium: {
16013
+ backgroundColor: "#eab308"
16014
+ },
16015
+ severityLow: {
16016
+ backgroundColor: "#3f3f46",
16017
+ borderWidth: 1,
16018
+ borderColor: "#71717a"
16019
+ },
16020
+ severityButtonText: {
16021
+ fontSize: 11,
16022
+ fontWeight: "500",
16023
+ color: "#a1a1aa",
16024
+ textTransform: "capitalize"
16025
+ },
16026
+ severityButtonTextActive: {
16027
+ color: "#fff"
16028
+ },
16029
+ addFindingButton: {
16030
+ backgroundColor: "#3B82F6",
16031
+ borderRadius: 8,
16032
+ paddingVertical: 10,
16033
+ alignItems: "center"
16034
+ },
16035
+ addFindingButtonText: {
16036
+ color: "#fff",
16037
+ fontSize: 14,
16038
+ fontWeight: "500"
16039
+ },
16040
+ sessionBanner: {
16041
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16042
+ borderRadius: 12,
16043
+ padding: 12,
16044
+ marginBottom: 12,
16045
+ borderWidth: 1,
16046
+ borderColor: "#166534"
16047
+ },
16048
+ sessionBannerRow: {
16049
+ flexDirection: "row",
16050
+ justifyContent: "space-between",
16051
+ alignItems: "center"
16052
+ },
16053
+ sessionBannerLeft: {
16054
+ flexDirection: "row",
16055
+ alignItems: "center",
16056
+ gap: 8
16057
+ },
16058
+ sessionDotLarge: {
16059
+ width: 8,
16060
+ height: 8,
16061
+ borderRadius: 4,
16062
+ backgroundColor: "#22c55e"
16063
+ },
16064
+ sessionBannerLabel: {
16065
+ fontSize: 14,
16066
+ fontWeight: "500",
16067
+ color: "#86efac"
16068
+ },
16069
+ sessionTimer: {
16070
+ fontSize: 20,
16071
+ fontWeight: "600",
16072
+ color: "#4ade80",
16073
+ fontVariant: ["tabular-nums"]
16074
+ },
16075
+ sessionFocus: {
16076
+ fontSize: 12,
16077
+ color: "#4ade80",
16078
+ marginTop: 4
16079
+ },
16080
+ addButton: {
16081
+ backgroundColor: "#3B82F6",
16082
+ borderRadius: 8,
16083
+ paddingVertical: 14,
16084
+ alignItems: "center",
16085
+ marginBottom: 12
16086
+ },
16087
+ addButtonText: {
16088
+ color: "#fff",
16089
+ fontSize: 14,
16090
+ fontWeight: "600"
16091
+ },
16092
+ findingsSection: {
16093
+ marginBottom: 12
16094
+ },
16095
+ findingsLabel: {
16096
+ fontSize: 12,
16097
+ fontWeight: "500",
16098
+ color: "#71717a",
16099
+ marginBottom: 8
16100
+ },
16101
+ findingsEmpty: {
16102
+ backgroundColor: "#27272a",
16103
+ borderRadius: 8,
16104
+ paddingVertical: 16,
16105
+ alignItems: "center"
16106
+ },
16107
+ findingsEmptyText: {
16108
+ fontSize: 12,
16109
+ color: "#71717a"
16110
+ },
16111
+ findingCard: {
16112
+ flexDirection: "row",
16113
+ alignItems: "flex-start",
16114
+ padding: 8,
16115
+ borderRadius: 8,
16116
+ marginBottom: 6,
16117
+ borderWidth: 1,
16118
+ gap: 8
16119
+ },
16120
+ findingCardBug: {
16121
+ backgroundColor: "rgba(220, 38, 38, 0.1)",
16122
+ borderColor: "#991b1b"
16123
+ },
16124
+ findingCardConcern: {
16125
+ backgroundColor: "rgba(249, 115, 22, 0.1)",
16126
+ borderColor: "#9a3412"
16127
+ },
16128
+ findingCardSuggestion: {
16129
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16130
+ borderColor: "#1e40af"
16131
+ },
16132
+ findingCardQuestion: {
16133
+ backgroundColor: "rgba(139, 92, 246, 0.1)",
16134
+ borderColor: "#5b21b6"
16135
+ },
16136
+ findingCardIcon: {
16137
+ fontSize: 14
16138
+ },
16139
+ findingCardTitle: {
16140
+ fontSize: 12,
16141
+ fontWeight: "500",
16142
+ color: "#fafafa"
16143
+ },
16144
+ findingCardSeverity: {
16145
+ fontSize: 10,
16146
+ fontWeight: "500",
16147
+ marginTop: 2,
16148
+ textTransform: "capitalize"
16149
+ },
16150
+ endSessionButton: {
16151
+ backgroundColor: "#3f3f46",
16152
+ borderRadius: 8,
16153
+ paddingVertical: 10,
16154
+ alignItems: "center"
16155
+ },
16156
+ endSessionButtonText: {
16157
+ color: "#d4d4d8",
16158
+ fontSize: 14,
16159
+ fontWeight: "500"
16160
+ }
16161
+ });
16162
+ var feedbackStyles = StyleSheet.create({
16163
+ container: {
16164
+ padding: 4
16165
+ },
16166
+ statusText: {
16167
+ fontSize: 16,
16168
+ fontWeight: "600",
16169
+ marginTop: 4
16170
+ },
16171
+ infoBox: {
16172
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
16173
+ borderRadius: 8,
16174
+ padding: 12,
16175
+ marginBottom: 16,
16176
+ borderWidth: 1,
16177
+ borderColor: "#1e3a5f"
16178
+ },
16179
+ infoTitle: {
16180
+ fontSize: 14,
16181
+ fontWeight: "500",
16182
+ color: "#93c5fd",
16183
+ marginBottom: 4
16184
+ },
16185
+ infoSubtitle: {
16186
+ fontSize: 12,
16187
+ color: "#60a5fa"
16188
+ },
16189
+ ratingSection: {
16190
+ alignItems: "center",
16191
+ marginBottom: 16
16192
+ },
16193
+ ratingLabel: {
16194
+ fontSize: 12,
16195
+ fontWeight: "500",
16196
+ color: "#a1a1aa",
16197
+ marginBottom: 8
16198
+ },
16199
+ starsRow: {
16200
+ flexDirection: "row",
16201
+ gap: 4
16202
+ },
16203
+ star: {
16204
+ fontSize: 28
16205
+ },
16206
+ starActive: {
16207
+ color: "#facc15"
16208
+ },
16209
+ starInactive: {
16210
+ color: "#3f3f46"
16211
+ },
16212
+ ratingDesc: {
16213
+ fontSize: 12,
16214
+ color: "#71717a",
16215
+ marginTop: 4
16216
+ },
16217
+ flagsSection: {
16218
+ marginBottom: 12
16219
+ },
16220
+ flagsGrid: {
16221
+ flexDirection: "row",
16222
+ flexWrap: "wrap",
16223
+ gap: 8
16224
+ },
16225
+ flagButton: {
16226
+ paddingHorizontal: 10,
16227
+ paddingVertical: 6,
16228
+ borderRadius: 6,
16229
+ backgroundColor: "#27272a",
16230
+ borderWidth: 1,
16231
+ borderColor: "#3f3f46"
16232
+ },
16233
+ flagButtonActive: {
16234
+ backgroundColor: "#1e3a5f",
16235
+ borderColor: "#3B82F6"
16236
+ },
16237
+ flagButtonText: {
16238
+ fontSize: 12,
16239
+ fontWeight: "500",
16240
+ color: "#a1a1aa"
16241
+ },
16242
+ flagButtonTextActive: {
16243
+ color: "#93c5fd"
16244
+ },
16245
+ noteInput: {
16246
+ backgroundColor: "#27272a",
16247
+ borderRadius: 8,
16248
+ paddingHorizontal: 12,
16249
+ paddingVertical: 10,
16250
+ fontSize: 14,
16251
+ color: "#fafafa",
16252
+ borderWidth: 1,
16253
+ borderColor: "#3f3f46",
16254
+ minHeight: 60
16255
+ },
16256
+ buttonRow: {
16257
+ flexDirection: "row",
16258
+ gap: 8
16259
+ },
16260
+ skipButton: {
16261
+ flex: 1,
16262
+ paddingVertical: 10,
16263
+ backgroundColor: "#3f3f46",
16264
+ borderRadius: 8,
16265
+ alignItems: "center"
16266
+ },
16267
+ skipButtonText: {
16268
+ color: "#a1a1aa",
16269
+ fontSize: 14,
16270
+ fontWeight: "500"
16271
+ },
16272
+ submitButton: {
16273
+ flex: 1,
16274
+ paddingVertical: 10,
16275
+ backgroundColor: "#3B82F6",
16276
+ borderRadius: 8,
16277
+ alignItems: "center"
16278
+ },
16279
+ submitButtonText: {
16280
+ color: "#fff",
16281
+ fontSize: 14,
16282
+ fontWeight: "500"
16283
+ }
16284
+ });
16285
+ var timerStyles = StyleSheet.create({
16286
+ container: {
16287
+ flexDirection: "row",
16288
+ alignItems: "center",
16289
+ gap: 6,
16290
+ backgroundColor: "rgba(22, 163, 74, 0.15)",
16291
+ paddingHorizontal: 8,
16292
+ paddingVertical: 4,
16293
+ borderRadius: 6,
16294
+ marginBottom: 8,
16295
+ alignSelf: "flex-start"
16296
+ },
16297
+ dot: {
16298
+ width: 6,
16299
+ height: 6,
16300
+ borderRadius: 3,
16301
+ backgroundColor: "#22c55e"
16302
+ },
16303
+ label: {
16304
+ fontSize: 12,
16305
+ fontWeight: "500",
16306
+ color: "#4ade80"
16307
+ },
16308
+ time: {
16309
+ fontSize: 12,
16310
+ fontWeight: "600",
16311
+ color: "#4ade80",
16312
+ fontVariant: ["tabular-nums"]
14331
16313
  }
14332
16314
  });
14333
16315
  export {