@bbearai/react-native 0.1.7 → 0.1.9

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.
Files changed (3) hide show
  1. package/dist/index.js +964 -256
  2. package/dist/index.mjs +964 -256
  3. package/package.json +4 -4
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,7 @@ var BugBearClient = class {
11462
11471
  const { data, error } = await this.supabase.from("test_assignments").select(`
11463
11472
  id,
11464
11473
  status,
11474
+ started_at,
11465
11475
  test_case:test_cases(
11466
11476
  id,
11467
11477
  title,
@@ -11489,6 +11499,7 @@ var BugBearClient = class {
11489
11499
  return (data || []).map((item) => ({
11490
11500
  id: item.id,
11491
11501
  status: item.status,
11502
+ startedAt: item.started_at,
11492
11503
  testCase: {
11493
11504
  id: item.test_case.id,
11494
11505
  title: item.test_case.title,
@@ -11514,47 +11525,430 @@ var BugBearClient = class {
11514
11525
  return [];
11515
11526
  }
11516
11527
  }
11528
+ /**
11529
+ * Get assignment by ID with time tracking fields
11530
+ */
11531
+ async getAssignment(assignmentId) {
11532
+ try {
11533
+ const { data, error } = await this.supabase.from("test_assignments").select(`
11534
+ id,
11535
+ status,
11536
+ started_at,
11537
+ completed_at,
11538
+ duration_seconds,
11539
+ test_case:test_cases(
11540
+ id,
11541
+ title,
11542
+ test_key,
11543
+ description,
11544
+ steps,
11545
+ expected_result,
11546
+ priority,
11547
+ target_route,
11548
+ track:qa_tracks(
11549
+ id,
11550
+ name,
11551
+ icon,
11552
+ color,
11553
+ test_template,
11554
+ rubric_mode,
11555
+ description
11556
+ )
11557
+ )
11558
+ `).eq("id", assignmentId).single();
11559
+ if (error || !data) return null;
11560
+ const testCase = data.test_case;
11561
+ if (!testCase) {
11562
+ console.error("BugBear: Assignment returned without test_case");
11563
+ return null;
11564
+ }
11565
+ const track = testCase.track;
11566
+ return {
11567
+ id: data.id,
11568
+ status: data.status,
11569
+ startedAt: data.started_at,
11570
+ durationSeconds: data.duration_seconds,
11571
+ testCase: {
11572
+ id: testCase.id,
11573
+ title: testCase.title,
11574
+ testKey: testCase.test_key,
11575
+ description: testCase.description,
11576
+ steps: testCase.steps,
11577
+ expectedResult: testCase.expected_result,
11578
+ priority: testCase.priority,
11579
+ targetRoute: testCase.target_route,
11580
+ track: track ? {
11581
+ id: track.id,
11582
+ name: track.name,
11583
+ icon: track.icon,
11584
+ color: track.color,
11585
+ testTemplate: track.test_template,
11586
+ rubricMode: track.rubric_mode || "pass_fail",
11587
+ description: track.description
11588
+ } : void 0
11589
+ }
11590
+ };
11591
+ } catch (err) {
11592
+ console.error("BugBear: Error fetching assignment", err);
11593
+ return null;
11594
+ }
11595
+ }
11596
+ /**
11597
+ * Update assignment status with automatic time tracking
11598
+ * - Sets started_at when status changes to 'in_progress'
11599
+ * - Calculates duration_seconds when status changes to 'passed'/'failed'/'blocked'
11600
+ * - Optionally include feedback when completing a test
11601
+ */
11602
+ async updateAssignmentStatus(assignmentId, status, options) {
11603
+ try {
11604
+ const { data: currentAssignment, error: fetchError } = await this.supabase.from("test_assignments").select("status, started_at").eq("id", assignmentId).single();
11605
+ if (fetchError || !currentAssignment) {
11606
+ return { success: false, error: "Assignment not found" };
11607
+ }
11608
+ const updateData = { status };
11609
+ let durationSeconds;
11610
+ if (status === "in_progress" && currentAssignment.status !== "in_progress") {
11611
+ updateData.started_at = (/* @__PURE__ */ new Date()).toISOString();
11612
+ }
11613
+ if (["passed", "failed", "blocked"].includes(status)) {
11614
+ updateData.completed_at = (/* @__PURE__ */ new Date()).toISOString();
11615
+ if (currentAssignment.started_at) {
11616
+ const startedAt = new Date(currentAssignment.started_at);
11617
+ const completedAt = /* @__PURE__ */ new Date();
11618
+ durationSeconds = Math.round((completedAt.getTime() - startedAt.getTime()) / 1e3);
11619
+ updateData.duration_seconds = durationSeconds;
11620
+ }
11621
+ }
11622
+ if (options?.notes) {
11623
+ updateData.notes = options.notes;
11624
+ }
11625
+ if (options?.testResult) {
11626
+ updateData.test_result = options.testResult;
11627
+ }
11628
+ const { error } = await this.supabase.from("test_assignments").update(updateData).eq("id", assignmentId);
11629
+ if (error) {
11630
+ console.error("BugBear: Failed to update assignment status", error);
11631
+ return { success: false, error: error.message };
11632
+ }
11633
+ if (options?.feedback && ["passed", "failed", "blocked"].includes(status)) {
11634
+ const { data: assignmentData, error: fetchError2 } = await this.supabase.from("test_assignments").select("test_case_id").eq("id", assignmentId).single();
11635
+ if (fetchError2) {
11636
+ console.error("BugBear: Failed to fetch assignment for feedback", fetchError2);
11637
+ } else if (assignmentData?.test_case_id) {
11638
+ const feedbackResult = await this.submitTestFeedback({
11639
+ testCaseId: assignmentData.test_case_id,
11640
+ assignmentId,
11641
+ feedback: options.feedback,
11642
+ timeToCompleteSeconds: durationSeconds
11643
+ });
11644
+ if (!feedbackResult.success) {
11645
+ console.error("BugBear: Failed to submit feedback", feedbackResult.error);
11646
+ }
11647
+ }
11648
+ }
11649
+ return { success: true, durationSeconds };
11650
+ } catch (err) {
11651
+ const message = err instanceof Error ? err.message : "Unknown error";
11652
+ console.error("BugBear: Error updating assignment status", err);
11653
+ return { success: false, error: message };
11654
+ }
11655
+ }
11656
+ /**
11657
+ * Submit feedback on a test case to help improve test quality
11658
+ * This empowers testers to shape better tests over time
11659
+ */
11660
+ async submitTestFeedback(options) {
11661
+ try {
11662
+ const testerInfo = await this.getTesterInfo();
11663
+ if (!testerInfo) {
11664
+ return { success: false, error: "Not authenticated as tester" };
11665
+ }
11666
+ const { testCaseId, assignmentId, feedback, timeToCompleteSeconds } = options;
11667
+ if (feedback.rating < 1 || feedback.rating > 5) {
11668
+ return { success: false, error: "Rating must be between 1 and 5" };
11669
+ }
11670
+ const { error: feedbackError } = await this.supabase.from("test_feedback").insert({
11671
+ project_id: this.config.projectId,
11672
+ test_case_id: testCaseId,
11673
+ assignment_id: assignmentId || null,
11674
+ tester_id: testerInfo.id,
11675
+ rating: feedback.rating,
11676
+ clarity_rating: feedback.clarityRating || null,
11677
+ steps_rating: feedback.stepsRating || null,
11678
+ relevance_rating: feedback.relevanceRating || null,
11679
+ feedback_note: feedback.feedbackNote?.trim() || null,
11680
+ suggested_improvement: feedback.suggestedImprovement?.trim() || null,
11681
+ is_outdated: feedback.isOutdated || false,
11682
+ needs_more_detail: feedback.needsMoreDetail || false,
11683
+ steps_unclear: feedback.stepsUnclear || false,
11684
+ expected_result_unclear: feedback.expectedResultUnclear || false,
11685
+ platform: this.getDeviceInfo().platform,
11686
+ time_to_complete_seconds: timeToCompleteSeconds || null
11687
+ });
11688
+ if (feedbackError) {
11689
+ console.error("BugBear: Failed to submit feedback", feedbackError);
11690
+ return { success: false, error: feedbackError.message };
11691
+ }
11692
+ if (assignmentId) {
11693
+ const { error: assignmentError } = await this.supabase.from("test_assignments").update({
11694
+ feedback_rating: feedback.rating,
11695
+ feedback_note: feedback.feedbackNote?.trim() || null,
11696
+ feedback_submitted_at: (/* @__PURE__ */ new Date()).toISOString()
11697
+ }).eq("id", assignmentId);
11698
+ if (assignmentError) {
11699
+ console.error("BugBear: Failed to update assignment feedback fields", assignmentError);
11700
+ }
11701
+ }
11702
+ return { success: true };
11703
+ } catch (err) {
11704
+ const message = err instanceof Error ? err.message : "Unknown error";
11705
+ console.error("BugBear: Error submitting feedback", err);
11706
+ return { success: false, error: message };
11707
+ }
11708
+ }
11709
+ /**
11710
+ * Get the currently active (in_progress) assignment for the tester
11711
+ */
11712
+ async getActiveAssignment() {
11713
+ try {
11714
+ const testerInfo = await this.getTesterInfo();
11715
+ if (!testerInfo) return null;
11716
+ const { data, error } = await this.supabase.from("test_assignments").select(`
11717
+ id,
11718
+ status,
11719
+ started_at,
11720
+ test_case:test_cases(
11721
+ id,
11722
+ title,
11723
+ test_key,
11724
+ description,
11725
+ steps,
11726
+ expected_result,
11727
+ priority,
11728
+ target_route,
11729
+ track:qa_tracks(
11730
+ id,
11731
+ name,
11732
+ icon,
11733
+ color,
11734
+ test_template,
11735
+ rubric_mode,
11736
+ description
11737
+ )
11738
+ )
11739
+ `).eq("project_id", this.config.projectId).eq("tester_id", testerInfo.id).eq("status", "in_progress").order("started_at", { ascending: false }).limit(1).maybeSingle();
11740
+ if (error || !data) return null;
11741
+ const testCase = data.test_case;
11742
+ if (!testCase) {
11743
+ console.error("BugBear: Active assignment returned without test_case");
11744
+ return null;
11745
+ }
11746
+ const track = testCase.track;
11747
+ return {
11748
+ id: data.id,
11749
+ status: data.status,
11750
+ startedAt: data.started_at,
11751
+ testCase: {
11752
+ id: testCase.id,
11753
+ title: testCase.title,
11754
+ testKey: testCase.test_key,
11755
+ description: testCase.description,
11756
+ steps: testCase.steps,
11757
+ expectedResult: testCase.expected_result,
11758
+ priority: testCase.priority,
11759
+ targetRoute: testCase.target_route,
11760
+ track: track ? {
11761
+ id: track.id,
11762
+ name: track.name,
11763
+ icon: track.icon,
11764
+ color: track.color,
11765
+ testTemplate: track.test_template,
11766
+ rubricMode: track.rubric_mode || "pass_fail",
11767
+ description: track.description
11768
+ } : void 0
11769
+ }
11770
+ };
11771
+ } catch (err) {
11772
+ console.error("BugBear: Error fetching active assignment", err);
11773
+ return null;
11774
+ }
11775
+ }
11517
11776
  /**
11518
11777
  * Get current tester info
11519
11778
  * Looks up tester by email from the host app's authenticated user
11779
+ * Checks both primary email AND additional_emails array
11780
+ * Uses parameterized RPC function to prevent SQL injection
11520
11781
  */
11521
11782
  async getTesterInfo() {
11522
11783
  try {
11523
11784
  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();
11785
+ if (!userInfo?.email) return null;
11786
+ if (!this.isValidEmail(userInfo.email)) {
11787
+ console.warn("BugBear: Invalid email format");
11788
+ return null;
11789
+ }
11790
+ const { data, error } = await this.supabase.rpc("lookup_tester_by_email", {
11791
+ p_project_id: this.config.projectId,
11792
+ p_email: userInfo.email
11793
+ }).maybeSingle();
11526
11794
  if (error || !data) return null;
11795
+ const tester = data;
11527
11796
  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
11797
+ id: tester.id,
11798
+ name: tester.name,
11799
+ email: tester.email,
11800
+ additionalEmails: tester.additional_emails || [],
11801
+ avatarUrl: tester.avatar_url || void 0,
11802
+ platforms: tester.platforms || [],
11803
+ assignedTests: tester.assigned_count || 0,
11804
+ completedTests: tester.completed_count || 0
11536
11805
  };
11537
11806
  } catch (err) {
11538
11807
  console.error("BugBear: getTesterInfo error", err);
11539
11808
  return null;
11540
11809
  }
11541
11810
  }
11811
+ /**
11812
+ * Basic email format validation (defense in depth)
11813
+ */
11814
+ isValidEmail(email) {
11815
+ if (!email || email.length > 254) return false;
11816
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
11817
+ return emailRegex.test(email);
11818
+ }
11819
+ /**
11820
+ * Validate report input before submission
11821
+ * Returns error message if invalid, null if valid
11822
+ */
11823
+ validateReport(report) {
11824
+ const validTypes = ["bug", "feedback", "suggestion", "test_pass", "test_fail"];
11825
+ if (report.type && !validTypes.includes(report.type)) {
11826
+ return `Invalid report type: ${report.type}. Must be one of: ${validTypes.join(", ")}`;
11827
+ }
11828
+ const validSeverities = ["critical", "high", "medium", "low"];
11829
+ if (report.severity && !validSeverities.includes(report.severity)) {
11830
+ return `Invalid severity: ${report.severity}. Must be one of: ${validSeverities.join(", ")}`;
11831
+ }
11832
+ if (report.title && report.title.length > 500) {
11833
+ return "Title must be 500 characters or less";
11834
+ }
11835
+ if (report.description && report.description.length > 1e4) {
11836
+ return "Description must be 10,000 characters or less";
11837
+ }
11838
+ if (report.screenshots && Array.isArray(report.screenshots)) {
11839
+ if (report.screenshots.length > 10) {
11840
+ return "Maximum 10 screenshots allowed";
11841
+ }
11842
+ for (const url of report.screenshots) {
11843
+ if (typeof url !== "string" || url.length > 2e3) {
11844
+ return "Invalid screenshot URL";
11845
+ }
11846
+ }
11847
+ }
11848
+ return null;
11849
+ }
11850
+ /**
11851
+ * Validate profile update input
11852
+ * Returns error message if invalid, null if valid
11853
+ */
11854
+ validateProfileUpdate(updates) {
11855
+ if (updates.name !== void 0) {
11856
+ if (typeof updates.name !== "string" || updates.name.length > 100) {
11857
+ return "Name must be 100 characters or less";
11858
+ }
11859
+ }
11860
+ if (updates.additionalEmails !== void 0) {
11861
+ if (!Array.isArray(updates.additionalEmails)) {
11862
+ return "Additional emails must be an array";
11863
+ }
11864
+ if (updates.additionalEmails.length > 5) {
11865
+ return "Maximum 5 additional emails allowed";
11866
+ }
11867
+ for (const email of updates.additionalEmails) {
11868
+ if (!this.isValidEmail(email)) {
11869
+ return `Invalid email format: ${email}`;
11870
+ }
11871
+ }
11872
+ }
11873
+ if (updates.avatarUrl !== void 0 && updates.avatarUrl !== null) {
11874
+ if (typeof updates.avatarUrl !== "string" || updates.avatarUrl.length > 2e3) {
11875
+ return "Invalid avatar URL";
11876
+ }
11877
+ }
11878
+ if (updates.platforms !== void 0) {
11879
+ if (!Array.isArray(updates.platforms)) {
11880
+ return "Platforms must be an array";
11881
+ }
11882
+ const validPlatforms = ["ios", "android", "web", "desktop", "other"];
11883
+ for (const platform of updates.platforms) {
11884
+ if (!validPlatforms.includes(platform)) {
11885
+ return `Invalid platform: ${platform}. Must be one of: ${validPlatforms.join(", ")}`;
11886
+ }
11887
+ }
11888
+ }
11889
+ return null;
11890
+ }
11891
+ /**
11892
+ * Check rate limit for an action
11893
+ * Returns { allowed: boolean, error?: string, remaining?: number }
11894
+ */
11895
+ async checkRateLimit(identifier, action) {
11896
+ try {
11897
+ const { data, error } = await this.supabase.rpc("check_rate_limit", {
11898
+ p_identifier: identifier,
11899
+ p_action: action,
11900
+ p_project_id: this.config.projectId
11901
+ });
11902
+ if (error) {
11903
+ console.warn("BugBear: Rate limit check failed, allowing request", error.message);
11904
+ return { allowed: true };
11905
+ }
11906
+ if (!data.allowed) {
11907
+ return {
11908
+ allowed: false,
11909
+ error: `Rate limit exceeded. Try again in ${Math.ceil((new Date(data.reset_at).getTime() - Date.now()) / 1e3)} seconds.`,
11910
+ remaining: 0,
11911
+ resetAt: data.reset_at
11912
+ };
11913
+ }
11914
+ return {
11915
+ allowed: true,
11916
+ remaining: data.remaining,
11917
+ resetAt: data.reset_at
11918
+ };
11919
+ } catch (err) {
11920
+ console.warn("BugBear: Rate limit check error", err);
11921
+ return { allowed: true };
11922
+ }
11923
+ }
11542
11924
  /**
11543
11925
  * Update tester profile
11544
11926
  * Allows testers to update their name, additional emails, avatar, and platforms
11545
11927
  */
11546
11928
  async updateTesterProfile(updates) {
11547
11929
  try {
11930
+ const validationError = this.validateProfileUpdate(updates);
11931
+ if (validationError) {
11932
+ return { success: false, error: validationError };
11933
+ }
11548
11934
  const userInfo = await this.getCurrentUserInfo();
11549
11935
  if (!userInfo) {
11550
11936
  return { success: false, error: "Not authenticated" };
11551
11937
  }
11938
+ const rateLimit = await this.checkRateLimit(userInfo.email, "profile_update");
11939
+ if (!rateLimit.allowed) {
11940
+ return { success: false, error: rateLimit.error };
11941
+ }
11942
+ const testerInfo = await this.getTesterInfo();
11943
+ if (!testerInfo) {
11944
+ return { success: false, error: "Not a registered tester" };
11945
+ }
11552
11946
  const updateData = {};
11553
11947
  if (updates.name !== void 0) updateData.name = updates.name;
11554
11948
  if (updates.additionalEmails !== void 0) updateData.additional_emails = updates.additionalEmails;
11555
11949
  if (updates.avatarUrl !== void 0) updateData.avatar_url = updates.avatarUrl;
11556
11950
  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);
11951
+ const { error } = await this.supabase.from("testers").update(updateData).eq("id", testerInfo.id);
11558
11952
  if (error) {
11559
11953
  console.error("BugBear: updateTesterProfile error", error);
11560
11954
  return { success: false, error: error.message };
@@ -11830,6 +12224,11 @@ var BugBearClient = class {
11830
12224
  console.error("BugBear: No tester info, cannot send message");
11831
12225
  return false;
11832
12226
  }
12227
+ const rateLimit = await this.checkRateLimit(testerInfo.email, "message_send");
12228
+ if (!rateLimit.allowed) {
12229
+ console.error("BugBear: Rate limit exceeded for messages");
12230
+ return false;
12231
+ }
11833
12232
  const { error } = await this.supabase.from("discussion_messages").insert({
11834
12233
  thread_id: threadId,
11835
12234
  sender_type: "tester",
@@ -11924,6 +12323,248 @@ var BugBearClient = class {
11924
12323
  return { success: false, error: message };
11925
12324
  }
11926
12325
  }
12326
+ // ============================================
12327
+ // QA Sessions (Sprint 1)
12328
+ // ============================================
12329
+ /**
12330
+ * Start a new QA session for exploratory testing
12331
+ */
12332
+ async startSession(options = {}) {
12333
+ try {
12334
+ const testerInfo = await this.getTesterInfo();
12335
+ if (!testerInfo) {
12336
+ return { success: false, error: "Not authenticated as a tester" };
12337
+ }
12338
+ const activeSession = await this.getActiveSession();
12339
+ if (activeSession) {
12340
+ return { success: false, error: "You already have an active session. End it before starting a new one." };
12341
+ }
12342
+ const { data, error } = await this.supabase.rpc("start_qa_session", {
12343
+ p_project_id: this.config.projectId,
12344
+ p_tester_id: testerInfo.id,
12345
+ p_focus_area: options.focusArea || null,
12346
+ p_track: options.track || null,
12347
+ p_platform: options.platform || null
12348
+ });
12349
+ if (error) {
12350
+ console.error("BugBear: Failed to start session", error);
12351
+ return { success: false, error: error.message };
12352
+ }
12353
+ const session = await this.getSession(data);
12354
+ if (!session) {
12355
+ return { success: false, error: "Session created but could not be fetched" };
12356
+ }
12357
+ return { success: true, session };
12358
+ } catch (err) {
12359
+ const message = err instanceof Error ? err.message : "Unknown error";
12360
+ console.error("BugBear: Error starting session", err);
12361
+ return { success: false, error: message };
12362
+ }
12363
+ }
12364
+ /**
12365
+ * End the current QA session
12366
+ */
12367
+ async endSession(sessionId, options = {}) {
12368
+ try {
12369
+ const { data, error } = await this.supabase.rpc("end_qa_session", {
12370
+ p_session_id: sessionId,
12371
+ p_notes: options.notes || null,
12372
+ p_routes_covered: options.routesCovered || null
12373
+ });
12374
+ if (error) {
12375
+ console.error("BugBear: Failed to end session", error);
12376
+ return { success: false, error: error.message };
12377
+ }
12378
+ const session = this.transformSession(data);
12379
+ return { success: true, session };
12380
+ } catch (err) {
12381
+ const message = err instanceof Error ? err.message : "Unknown error";
12382
+ console.error("BugBear: Error ending session", err);
12383
+ return { success: false, error: message };
12384
+ }
12385
+ }
12386
+ /**
12387
+ * Get the current active session for the tester
12388
+ */
12389
+ async getActiveSession() {
12390
+ try {
12391
+ const testerInfo = await this.getTesterInfo();
12392
+ if (!testerInfo) return null;
12393
+ 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();
12394
+ if (error || !data) return null;
12395
+ return this.transformSession(data);
12396
+ } catch (err) {
12397
+ console.error("BugBear: Error fetching active session", err);
12398
+ return null;
12399
+ }
12400
+ }
12401
+ /**
12402
+ * Get a session by ID
12403
+ */
12404
+ async getSession(sessionId) {
12405
+ try {
12406
+ const { data, error } = await this.supabase.from("qa_sessions").select("*").eq("id", sessionId).single();
12407
+ if (error || !data) return null;
12408
+ return this.transformSession(data);
12409
+ } catch (err) {
12410
+ console.error("BugBear: Error fetching session", err);
12411
+ return null;
12412
+ }
12413
+ }
12414
+ /**
12415
+ * Get session history for the tester
12416
+ */
12417
+ async getSessionHistory(limit = 10) {
12418
+ try {
12419
+ const testerInfo = await this.getTesterInfo();
12420
+ if (!testerInfo) return [];
12421
+ 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);
12422
+ if (error) {
12423
+ console.error("BugBear: Failed to fetch session history", error);
12424
+ return [];
12425
+ }
12426
+ return (data || []).map((s) => this.transformSession(s));
12427
+ } catch (err) {
12428
+ console.error("BugBear: Error fetching session history", err);
12429
+ return [];
12430
+ }
12431
+ }
12432
+ /**
12433
+ * Add a finding during a session
12434
+ */
12435
+ async addFinding(sessionId, options) {
12436
+ try {
12437
+ const { data, error } = await this.supabase.rpc("add_session_finding", {
12438
+ p_session_id: sessionId,
12439
+ p_type: options.type,
12440
+ p_title: options.title,
12441
+ p_description: options.description || null,
12442
+ p_severity: options.severity || "observation",
12443
+ p_route: options.route || null,
12444
+ p_screenshot_url: options.screenshotUrl || null,
12445
+ p_console_logs: options.consoleLogs || null,
12446
+ p_network_snapshot: options.networkSnapshot || null,
12447
+ p_device_info: options.deviceInfo || null,
12448
+ p_app_context: options.appContext || null
12449
+ });
12450
+ if (error) {
12451
+ console.error("BugBear: Failed to add finding", error);
12452
+ return { success: false, error: error.message };
12453
+ }
12454
+ const finding = this.transformFinding(data);
12455
+ return { success: true, finding };
12456
+ } catch (err) {
12457
+ const message = err instanceof Error ? err.message : "Unknown error";
12458
+ console.error("BugBear: Error adding finding", err);
12459
+ return { success: false, error: message };
12460
+ }
12461
+ }
12462
+ /**
12463
+ * Get findings for a session
12464
+ */
12465
+ async getSessionFindings(sessionId) {
12466
+ try {
12467
+ const { data, error } = await this.supabase.from("qa_findings").select("*").eq("session_id", sessionId).order("created_at", { ascending: true });
12468
+ if (error) {
12469
+ console.error("BugBear: Failed to fetch findings", error);
12470
+ return [];
12471
+ }
12472
+ return (data || []).map((f) => this.transformFinding(f));
12473
+ } catch (err) {
12474
+ console.error("BugBear: Error fetching findings", err);
12475
+ return [];
12476
+ }
12477
+ }
12478
+ /**
12479
+ * Convert a finding to a bug report
12480
+ */
12481
+ async convertFindingToBug(findingId) {
12482
+ try {
12483
+ const { data, error } = await this.supabase.rpc("convert_finding_to_bug", {
12484
+ p_finding_id: findingId
12485
+ });
12486
+ if (error) {
12487
+ console.error("BugBear: Failed to convert finding", error);
12488
+ return { success: false, error: error.message };
12489
+ }
12490
+ return { success: true, bugId: data };
12491
+ } catch (err) {
12492
+ const message = err instanceof Error ? err.message : "Unknown error";
12493
+ console.error("BugBear: Error converting finding", err);
12494
+ return { success: false, error: message };
12495
+ }
12496
+ }
12497
+ /**
12498
+ * Dismiss a finding
12499
+ */
12500
+ async dismissFinding(findingId, reason) {
12501
+ try {
12502
+ const { error } = await this.supabase.from("qa_findings").update({
12503
+ dismissed: true,
12504
+ dismissed_reason: reason || null,
12505
+ dismissed_at: (/* @__PURE__ */ new Date()).toISOString()
12506
+ }).eq("id", findingId);
12507
+ if (error) {
12508
+ console.error("BugBear: Failed to dismiss finding", error);
12509
+ return { success: false, error: error.message };
12510
+ }
12511
+ return { success: true };
12512
+ } catch (err) {
12513
+ const message = err instanceof Error ? err.message : "Unknown error";
12514
+ console.error("BugBear: Error dismissing finding", err);
12515
+ return { success: false, error: message };
12516
+ }
12517
+ }
12518
+ /**
12519
+ * Transform database session to QASession type
12520
+ */
12521
+ transformSession(data) {
12522
+ return {
12523
+ id: data.id,
12524
+ projectId: data.project_id,
12525
+ testerId: data.tester_id,
12526
+ focusArea: data.focus_area,
12527
+ track: data.track,
12528
+ platform: data.platform,
12529
+ startedAt: data.started_at,
12530
+ endedAt: data.ended_at,
12531
+ notes: data.notes,
12532
+ routesCovered: data.routes_covered || [],
12533
+ status: data.status,
12534
+ durationMinutes: data.duration_minutes,
12535
+ findingsCount: data.findings_count || 0,
12536
+ bugsFiled: data.bugs_filed || 0,
12537
+ createdAt: data.created_at,
12538
+ updatedAt: data.updated_at
12539
+ };
12540
+ }
12541
+ /**
12542
+ * Transform database finding to QAFinding type
12543
+ */
12544
+ transformFinding(data) {
12545
+ return {
12546
+ id: data.id,
12547
+ sessionId: data.session_id,
12548
+ projectId: data.project_id,
12549
+ type: data.type,
12550
+ severity: data.severity,
12551
+ title: data.title,
12552
+ description: data.description,
12553
+ route: data.route,
12554
+ screenshotUrl: data.screenshot_url,
12555
+ consoleLogs: data.console_logs,
12556
+ networkSnapshot: data.network_snapshot,
12557
+ deviceInfo: data.device_info,
12558
+ appContext: data.app_context,
12559
+ convertedToBugId: data.converted_to_bug_id,
12560
+ convertedToTestId: data.converted_to_test_id,
12561
+ dismissed: data.dismissed || false,
12562
+ dismissedReason: data.dismissed_reason,
12563
+ dismissedAt: data.dismissed_at,
12564
+ createdAt: data.created_at,
12565
+ updatedAt: data.updated_at
12566
+ };
12567
+ }
11927
12568
  };
11928
12569
  function createBugBear(config) {
11929
12570
  return new BugBearClient(config);
@@ -12320,6 +12961,7 @@ function BugBearButton({
12320
12961
  const [modalVisible, setModalVisible] = useState2(false);
12321
12962
  const [activeTab, setActiveTab] = useState2("tests");
12322
12963
  const [showSteps, setShowSteps] = useState2(false);
12964
+ const [showProfileOverlay, setShowProfileOverlay] = useState2(false);
12323
12965
  const [messageView, setMessageView] = useState2("list");
12324
12966
  const [selectedThread, setSelectedThread] = useState2(null);
12325
12967
  const [threadMessages, setThreadMessages] = useState2([]);
@@ -12520,6 +13162,15 @@ function BugBearButton({
12520
13162
  }
12521
13163
  setSendingNewMessage(false);
12522
13164
  };
13165
+ const handleOpenProfile = () => {
13166
+ if (testerInfo) {
13167
+ setProfileName(testerInfo.name);
13168
+ setProfileAdditionalEmails(testerInfo.additionalEmails || []);
13169
+ setProfilePlatforms(testerInfo.platforms || []);
13170
+ }
13171
+ setProfileEditing(false);
13172
+ setShowProfileOverlay(true);
13173
+ };
12523
13174
  const handleStartEditProfile = () => {
12524
13175
  if (testerInfo) {
12525
13176
  setProfileName(testerInfo.name);
@@ -12532,6 +13183,11 @@ function BugBearButton({
12532
13183
  setProfileEditing(false);
12533
13184
  setNewEmailInput("");
12534
13185
  };
13186
+ const handleCloseProfile = () => {
13187
+ setShowProfileOverlay(false);
13188
+ setProfileEditing(false);
13189
+ setNewEmailInput("");
13190
+ };
12535
13191
  const handleAddEmail = () => {
12536
13192
  const email = newEmailInput.trim().toLowerCase();
12537
13193
  if (email && email.includes("@") && !profileAdditionalEmails.includes(email)) {
@@ -12560,7 +13216,10 @@ function BugBearButton({
12560
13216
  if (result.success) {
12561
13217
  setProfileEditing(false);
12562
13218
  setProfileSaved(true);
12563
- setTimeout(() => setProfileSaved(false), 2e3);
13219
+ setTimeout(() => {
13220
+ setProfileSaved(false);
13221
+ setShowProfileOverlay(false);
13222
+ }, 1500);
12564
13223
  }
12565
13224
  setSavingProfile(false);
12566
13225
  };
@@ -12617,7 +13276,7 @@ function BugBearButton({
12617
13276
  const steps = displayedAssignment.testCase.steps;
12618
13277
  const info = templateInfo[template];
12619
13278
  const rubricMode = displayedAssignment.testCase.track?.rubricMode || "pass_fail";
12620
- 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(
13279
+ 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(
12621
13280
  TouchableOpacity,
12622
13281
  {
12623
13282
  key: idx,
@@ -12726,7 +13385,7 @@ function BugBearButton({
12726
13385
  behavior: Platform2.OS === "ios" ? "padding" : "height",
12727
13386
  style: styles.modalContainer
12728
13387
  },
12729
- /* @__PURE__ */ React2.createElement(View, { style: styles.modalContent }, /* @__PURE__ */ React2.createElement(View, { style: styles.header }, /* @__PURE__ */ React2.createElement(View, { style: styles.headerLeft }, /* @__PURE__ */ React2.createElement(Text, { style: styles.headerEmoji }, "\u{1F43B}"), /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.headerTitle }, "BugBear"), /* @__PURE__ */ React2.createElement(Text, { style: styles.headerSubtitle }, testerInfo?.name))), /* @__PURE__ */ React2.createElement(
13388
+ /* @__PURE__ */ React2.createElement(View, { style: styles.modalContent }, /* @__PURE__ */ React2.createElement(View, { style: styles.header }, /* @__PURE__ */ React2.createElement(View, { style: styles.headerLeft }, /* @__PURE__ */ React2.createElement(Text, { style: styles.headerEmoji }, "\u{1F43B}"), /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.headerTitle }, "BugBear"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: handleOpenProfile, style: styles.headerNameButton }, /* @__PURE__ */ React2.createElement(Text, { style: styles.headerSubtitle }, testerInfo?.name), /* @__PURE__ */ React2.createElement(Text, { style: styles.headerPencil }, "\u270E")))), /* @__PURE__ */ React2.createElement(
12730
13389
  TouchableOpacity,
12731
13390
  {
12732
13391
  onPress: () => setModalVisible(false),
@@ -12747,13 +13406,6 @@ function BugBearButton({
12747
13406
  onPress: () => setActiveTab("messages")
12748
13407
  },
12749
13408
  /* @__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)))
12750
- ), /* @__PURE__ */ React2.createElement(
12751
- TouchableOpacity,
12752
- {
12753
- style: [styles.tab, activeTab === "profile" && styles.activeTab],
12754
- onPress: () => setActiveTab("profile")
12755
- },
12756
- /* @__PURE__ */ React2.createElement(Text, { style: [styles.tabText, activeTab === "profile" && styles.activeTabText] }, "Profile")
12757
13409
  ), /* @__PURE__ */ React2.createElement(
12758
13410
  TouchableOpacity,
12759
13411
  {
@@ -12830,7 +13482,7 @@ function BugBearButton({
12830
13482
  value: composeSubject,
12831
13483
  onChangeText: setComposeSubject,
12832
13484
  placeholder: "What's this about?",
12833
- placeholderTextColor: "#9CA3AF",
13485
+ placeholderTextColor: "#71717a",
12834
13486
  maxLength: 100
12835
13487
  }
12836
13488
  ), /* @__PURE__ */ React2.createElement(Text, { style: [styles.label, { marginTop: 16 }] }, "Message"), /* @__PURE__ */ React2.createElement(
@@ -12840,7 +13492,7 @@ function BugBearButton({
12840
13492
  value: composeMessage,
12841
13493
  onChangeText: setComposeMessage,
12842
13494
  placeholder: "Write your message...",
12843
- placeholderTextColor: "#9CA3AF",
13495
+ placeholderTextColor: "#71717a",
12844
13496
  multiline: true,
12845
13497
  numberOfLines: 6,
12846
13498
  textAlignVertical: "top",
@@ -12905,7 +13557,70 @@ function BugBearButton({
12905
13557
  message.senderType === "tester" && styles.messageTimeTester
12906
13558
  ] }, formatMessageTime(message.createdAt))
12907
13559
  ))))
12908
- )), activeTab === "profile" && /* @__PURE__ */ React2.createElement(View, null, profileSaved ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u2705"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Profile saved!")) : profileEditing ? (
13560
+ )), activeTab === "report" && /* @__PURE__ */ React2.createElement(View, null, submitted ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u{1F389}"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Report submitted!")) : /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(View, { style: styles.reportTypes }, [
13561
+ { type: "bug", label: "\u{1F41B} Bug" },
13562
+ { type: "feedback", label: "\u{1F4A1} Feedback" },
13563
+ { type: "suggestion", label: "\u2728 Idea" }
13564
+ ].map(({ type, label }) => /* @__PURE__ */ React2.createElement(
13565
+ TouchableOpacity,
13566
+ {
13567
+ key: type,
13568
+ style: [
13569
+ styles.reportTypeButton,
13570
+ reportType === type && styles.reportTypeActive
13571
+ ],
13572
+ onPress: () => setReportType(type)
13573
+ },
13574
+ /* @__PURE__ */ React2.createElement(Text, { style: [
13575
+ styles.reportTypeText,
13576
+ reportType === type && styles.reportTypeTextActive
13577
+ ] }, label)
13578
+ ))), (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) => {
13579
+ const activeStyles = {
13580
+ critical: styles.severityCriticalActive,
13581
+ high: styles.severityHighActive,
13582
+ medium: styles.severityMediumActive,
13583
+ low: styles.severityLowActive
13584
+ };
13585
+ return /* @__PURE__ */ React2.createElement(
13586
+ TouchableOpacity,
13587
+ {
13588
+ key: sev,
13589
+ style: [
13590
+ styles.severityButton,
13591
+ severity === sev && activeStyles[sev]
13592
+ ],
13593
+ onPress: () => setSeverity(sev)
13594
+ },
13595
+ /* @__PURE__ */ React2.createElement(Text, { style: [
13596
+ styles.severityText,
13597
+ severity === sev && styles.severityTextActive
13598
+ ] }, sev)
13599
+ );
13600
+ }))), /* @__PURE__ */ React2.createElement(View, { style: styles.descriptionSection }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "What happened?"), /* @__PURE__ */ React2.createElement(
13601
+ TextInput,
13602
+ {
13603
+ style: styles.textInput,
13604
+ value: description,
13605
+ onChangeText: setDescription,
13606
+ placeholder: "Describe the issue...",
13607
+ placeholderTextColor: "#71717a",
13608
+ multiline: true,
13609
+ numberOfLines: 4,
13610
+ textAlignVertical: "top"
13611
+ }
13612
+ )), /* @__PURE__ */ React2.createElement(
13613
+ TouchableOpacity,
13614
+ {
13615
+ style: [
13616
+ styles.submitButton,
13617
+ (!description.trim() || submitting) && styles.submitButtonDisabled
13618
+ ],
13619
+ onPress: handleSubmitReport,
13620
+ disabled: !description.trim() || submitting
13621
+ },
13622
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.submitButtonText }, submitting ? "Submitting..." : "Submit Report")
13623
+ )))), showProfileOverlay && /* @__PURE__ */ React2.createElement(View, { style: styles.profileOverlay }, /* @__PURE__ */ React2.createElement(ScrollView, { style: styles.profileOverlayContent }, profileSaved ? /* @__PURE__ */ React2.createElement(View, { style: styles.emptyState }, /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyEmoji }, "\u2705"), /* @__PURE__ */ React2.createElement(Text, { style: styles.emptyTitle }, "Profile saved!")) : profileEditing ? (
12909
13624
  /* Edit Profile Form */
12910
13625
  /* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(View, { style: styles.profileEditHeader }, /* @__PURE__ */ React2.createElement(Text, { style: styles.profileEditTitle }, "Edit Profile"), /* @__PURE__ */ React2.createElement(TouchableOpacity, { onPress: handleCancelEditProfile }, /* @__PURE__ */ React2.createElement(Text, { style: styles.cancelText }, "Cancel"))), /* @__PURE__ */ React2.createElement(View, { style: styles.profileSection }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "Name"), /* @__PURE__ */ React2.createElement(
12911
13626
  TextInput,
@@ -12914,7 +13629,7 @@ function BugBearButton({
12914
13629
  value: profileName,
12915
13630
  onChangeText: setProfileName,
12916
13631
  placeholder: "Your name",
12917
- placeholderTextColor: "#9CA3AF"
13632
+ placeholderTextColor: "#71717a"
12918
13633
  }
12919
13634
  )), /* @__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(
12920
13635
  TextInput,
@@ -12923,7 +13638,7 @@ function BugBearButton({
12923
13638
  value: newEmailInput,
12924
13639
  onChangeText: setNewEmailInput,
12925
13640
  placeholder: "email@example.com",
12926
- placeholderTextColor: "#9CA3AF",
13641
+ placeholderTextColor: "#71717a",
12927
13642
  keyboardType: "email-address",
12928
13643
  autoCapitalize: "none"
12929
13644
  }
@@ -12972,70 +13687,14 @@ function BugBearButton({
12972
13687
  },
12973
13688
  /* @__PURE__ */ React2.createElement(Text, { style: styles.editProfileButtonText }, "Edit Profile")
12974
13689
  ))
12975
- )), 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 }, [
12976
- { type: "bug", label: "\u{1F41B} Bug" },
12977
- { type: "feedback", label: "\u{1F4A1} Feedback" },
12978
- { type: "suggestion", label: "\u2728 Idea" }
12979
- ].map(({ type, label }) => /* @__PURE__ */ React2.createElement(
13690
+ )), /* @__PURE__ */ React2.createElement(View, { style: styles.profileOverlayFooter }, /* @__PURE__ */ React2.createElement(
12980
13691
  TouchableOpacity,
12981
13692
  {
12982
- key: type,
12983
- style: [
12984
- styles.reportTypeButton,
12985
- reportType === type && styles.reportTypeActive
12986
- ],
12987
- onPress: () => setReportType(type)
13693
+ style: styles.closeProfileButton,
13694
+ onPress: handleCloseProfile
12988
13695
  },
12989
- /* @__PURE__ */ React2.createElement(Text, { style: [
12990
- styles.reportTypeText,
12991
- reportType === type && styles.reportTypeTextActive
12992
- ] }, label)
12993
- ))), (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) => {
12994
- const activeStyles = {
12995
- critical: styles.severityCriticalActive,
12996
- high: styles.severityHighActive,
12997
- medium: styles.severityMediumActive,
12998
- low: styles.severityLowActive
12999
- };
13000
- return /* @__PURE__ */ React2.createElement(
13001
- TouchableOpacity,
13002
- {
13003
- key: sev,
13004
- style: [
13005
- styles.severityButton,
13006
- severity === sev && activeStyles[sev]
13007
- ],
13008
- onPress: () => setSeverity(sev)
13009
- },
13010
- /* @__PURE__ */ React2.createElement(Text, { style: [
13011
- styles.severityText,
13012
- severity === sev && styles.severityTextActive
13013
- ] }, sev)
13014
- );
13015
- }))), /* @__PURE__ */ React2.createElement(View, { style: styles.descriptionSection }, /* @__PURE__ */ React2.createElement(Text, { style: styles.label }, "What happened?"), /* @__PURE__ */ React2.createElement(
13016
- TextInput,
13017
- {
13018
- style: styles.textInput,
13019
- value: description,
13020
- onChangeText: setDescription,
13021
- placeholder: "Describe the issue...",
13022
- placeholderTextColor: "#9CA3AF",
13023
- multiline: true,
13024
- numberOfLines: 4,
13025
- textAlignVertical: "top"
13026
- }
13027
- )), /* @__PURE__ */ React2.createElement(
13028
- TouchableOpacity,
13029
- {
13030
- style: [
13031
- styles.submitButton,
13032
- (!description.trim() || submitting) && styles.submitButtonDisabled
13033
- ],
13034
- onPress: handleSubmitReport,
13035
- disabled: !description.trim() || submitting
13036
- },
13037
- /* @__PURE__ */ React2.createElement(Text, { style: styles.submitButtonText }, submitting ? "Submitting..." : "Submit Report")
13038
- )))), activeTab === "messages" && messageView === "thread" && selectedThread ? (
13696
+ /* @__PURE__ */ React2.createElement(Text, { style: styles.closeProfileButtonText }, "\u2190 Back")
13697
+ ))), activeTab === "messages" && messageView === "thread" && selectedThread ? (
13039
13698
  /* Reply Composer */
13040
13699
  /* @__PURE__ */ React2.createElement(View, { style: styles.replyComposer }, /* @__PURE__ */ React2.createElement(
13041
13700
  TextInput,
@@ -13044,7 +13703,7 @@ function BugBearButton({
13044
13703
  value: replyText,
13045
13704
  onChangeText: setReplyText,
13046
13705
  placeholder: "Type a reply...",
13047
- placeholderTextColor: "#9CA3AF",
13706
+ placeholderTextColor: "#71717a",
13048
13707
  multiline: true,
13049
13708
  maxLength: 1e3
13050
13709
  }
@@ -13073,13 +13732,13 @@ var styles = StyleSheet.create({
13073
13732
  width: 56,
13074
13733
  height: 56,
13075
13734
  borderRadius: 28,
13076
- backgroundColor: "#7C3AED",
13735
+ backgroundColor: "#3B82F6",
13077
13736
  justifyContent: "center",
13078
13737
  alignItems: "center",
13079
- shadowColor: "#000",
13738
+ shadowColor: "#3B82F6",
13080
13739
  shadowOffset: { width: 0, height: 4 },
13081
- shadowOpacity: 0.3,
13082
- shadowRadius: 8,
13740
+ shadowOpacity: 0.4,
13741
+ shadowRadius: 12,
13083
13742
  elevation: 8,
13084
13743
  zIndex: 999999
13085
13744
  },
@@ -13112,10 +13771,10 @@ var styles = StyleSheet.create({
13112
13771
  modalContainer: {
13113
13772
  flex: 1,
13114
13773
  justifyContent: "flex-end",
13115
- backgroundColor: "rgba(0, 0, 0, 0.5)"
13774
+ backgroundColor: "rgba(0, 0, 0, 0.6)"
13116
13775
  },
13117
13776
  modalContent: {
13118
- backgroundColor: "#fff",
13777
+ backgroundColor: "#18181b",
13119
13778
  borderTopLeftRadius: 20,
13120
13779
  borderTopRightRadius: 20,
13121
13780
  maxHeight: "85%"
@@ -13124,11 +13783,13 @@ var styles = StyleSheet.create({
13124
13783
  flexDirection: "row",
13125
13784
  alignItems: "center",
13126
13785
  justifyContent: "space-between",
13127
- backgroundColor: "#7C3AED",
13786
+ backgroundColor: "#09090b",
13128
13787
  paddingHorizontal: 16,
13129
13788
  paddingVertical: 12,
13130
13789
  borderTopLeftRadius: 20,
13131
- borderTopRightRadius: 20
13790
+ borderTopRightRadius: 20,
13791
+ borderBottomWidth: 1,
13792
+ borderBottomColor: "#27272a"
13132
13793
  },
13133
13794
  headerLeft: {
13134
13795
  flexDirection: "row",
@@ -13139,25 +13800,35 @@ var styles = StyleSheet.create({
13139
13800
  marginRight: 10
13140
13801
  },
13141
13802
  headerTitle: {
13142
- color: "#fff",
13803
+ color: "#fafafa",
13143
13804
  fontSize: 16,
13144
13805
  fontWeight: "600"
13145
13806
  },
13146
13807
  headerSubtitle: {
13147
- color: "#DDD6FE",
13808
+ color: "#71717a",
13148
13809
  fontSize: 12
13149
13810
  },
13811
+ headerNameButton: {
13812
+ flexDirection: "row",
13813
+ alignItems: "center",
13814
+ gap: 4
13815
+ },
13816
+ headerPencil: {
13817
+ color: "#71717a",
13818
+ fontSize: 11
13819
+ },
13150
13820
  closeButton: {
13151
13821
  padding: 8
13152
13822
  },
13153
13823
  closeButtonText: {
13154
- color: "#fff",
13824
+ color: "#a1a1aa",
13155
13825
  fontSize: 18
13156
13826
  },
13157
13827
  tabs: {
13158
13828
  flexDirection: "row",
13159
13829
  borderBottomWidth: 1,
13160
- borderBottomColor: "#E5E7EB"
13830
+ borderBottomColor: "#27272a",
13831
+ backgroundColor: "#18181b"
13161
13832
  },
13162
13833
  tab: {
13163
13834
  flex: 1,
@@ -13166,15 +13837,15 @@ var styles = StyleSheet.create({
13166
13837
  },
13167
13838
  activeTab: {
13168
13839
  borderBottomWidth: 2,
13169
- borderBottomColor: "#7C3AED"
13840
+ borderBottomColor: "#3B82F6"
13170
13841
  },
13171
13842
  tabText: {
13172
13843
  fontSize: 14,
13173
13844
  fontWeight: "500",
13174
- color: "#6B7280"
13845
+ color: "#71717a"
13175
13846
  },
13176
13847
  activeTabText: {
13177
- color: "#7C3AED"
13848
+ color: "#3B82F6"
13178
13849
  },
13179
13850
  content: {
13180
13851
  padding: 16,
@@ -13187,16 +13858,16 @@ var styles = StyleSheet.create({
13187
13858
  paddingHorizontal: 16,
13188
13859
  paddingVertical: 12,
13189
13860
  borderTopWidth: 1,
13190
- borderTopColor: "#E5E7EB",
13191
- backgroundColor: "#F9FAFB"
13861
+ borderTopColor: "#27272a",
13862
+ backgroundColor: "#09090b"
13192
13863
  },
13193
13864
  footerText: {
13194
13865
  fontSize: 12,
13195
- color: "#9CA3AF"
13866
+ color: "#52525b"
13196
13867
  },
13197
13868
  refreshText: {
13198
13869
  fontSize: 12,
13199
- color: "#6B7280"
13870
+ color: "#71717a"
13200
13871
  },
13201
13872
  emptyState: {
13202
13873
  alignItems: "center",
@@ -13208,7 +13879,7 @@ var styles = StyleSheet.create({
13208
13879
  emptyTitle: {
13209
13880
  fontSize: 18,
13210
13881
  fontWeight: "600",
13211
- color: "#374151",
13882
+ color: "#e4e4e7",
13212
13883
  marginTop: 12
13213
13884
  },
13214
13885
  passedEmoji: {
@@ -13223,26 +13894,26 @@ var styles = StyleSheet.create({
13223
13894
  },
13224
13895
  emptySubtitle: {
13225
13896
  fontSize: 14,
13226
- color: "#9CA3AF",
13897
+ color: "#71717a",
13227
13898
  marginTop: 4
13228
13899
  },
13229
13900
  // List view styles
13230
13901
  listHeader: {
13231
13902
  fontSize: 12,
13232
- color: "#6B7280",
13903
+ color: "#71717a",
13233
13904
  marginBottom: 12
13234
13905
  },
13235
13906
  listItem: {
13236
- backgroundColor: "#F9FAFB",
13907
+ backgroundColor: "#27272a",
13237
13908
  borderRadius: 12,
13238
13909
  padding: 12,
13239
13910
  marginBottom: 8,
13240
13911
  borderWidth: 1,
13241
- borderColor: "#E5E7EB"
13912
+ borderColor: "#3f3f46"
13242
13913
  },
13243
13914
  listItemCurrent: {
13244
- backgroundColor: "#EDE9FE",
13245
- borderColor: "#C4B5FD"
13915
+ backgroundColor: "#1e3a5f",
13916
+ borderColor: "#3B82F6"
13246
13917
  },
13247
13918
  listItemHeader: {
13248
13919
  flexDirection: "row",
@@ -13253,7 +13924,7 @@ var styles = StyleSheet.create({
13253
13924
  listItemKey: {
13254
13925
  fontSize: 12,
13255
13926
  fontFamily: Platform2.OS === "ios" ? "Menlo" : "monospace",
13256
- color: "#6B7280"
13927
+ color: "#71717a"
13257
13928
  },
13258
13929
  listItemBadges: {
13259
13930
  flexDirection: "row",
@@ -13262,7 +13933,7 @@ var styles = StyleSheet.create({
13262
13933
  listItemTitle: {
13263
13934
  fontSize: 14,
13264
13935
  fontWeight: "600",
13265
- color: "#111827",
13936
+ color: "#fafafa",
13266
13937
  marginBottom: 4
13267
13938
  },
13268
13939
  listItemMeta: {
@@ -13271,11 +13942,11 @@ var styles = StyleSheet.create({
13271
13942
  },
13272
13943
  listItemMetaText: {
13273
13944
  fontSize: 12,
13274
- color: "#9CA3AF"
13945
+ color: "#71717a"
13275
13946
  },
13276
13947
  currentBadge: {
13277
13948
  fontSize: 12,
13278
- color: "#7C3AED",
13949
+ color: "#3B82F6",
13279
13950
  fontWeight: "600",
13280
13951
  marginLeft: 8
13281
13952
  },
@@ -13285,15 +13956,17 @@ var styles = StyleSheet.create({
13285
13956
  },
13286
13957
  backButtonText: {
13287
13958
  fontSize: 14,
13288
- color: "#7C3AED",
13959
+ color: "#3B82F6",
13289
13960
  fontWeight: "500"
13290
13961
  },
13291
13962
  // Test card styles
13292
13963
  testCard: {
13293
- backgroundColor: "#F9FAFB",
13964
+ backgroundColor: "#27272a",
13294
13965
  borderRadius: 12,
13295
13966
  padding: 16,
13296
- marginBottom: 16
13967
+ marginBottom: 16,
13968
+ borderWidth: 1,
13969
+ borderColor: "#3f3f46"
13297
13970
  },
13298
13971
  testHeader: {
13299
13972
  flexDirection: "row",
@@ -13308,7 +13981,7 @@ var styles = StyleSheet.create({
13308
13981
  testKey: {
13309
13982
  fontSize: 12,
13310
13983
  fontFamily: Platform2.OS === "ios" ? "Menlo" : "monospace",
13311
- color: "#6B7280"
13984
+ color: "#71717a"
13312
13985
  },
13313
13986
  trackBadge: {
13314
13987
  paddingHorizontal: 6,
@@ -13320,38 +13993,38 @@ var styles = StyleSheet.create({
13320
13993
  color: "#fff"
13321
13994
  },
13322
13995
  priorityBadge: {
13323
- backgroundColor: "#E5E7EB",
13996
+ backgroundColor: "#3f3f46",
13324
13997
  paddingHorizontal: 8,
13325
13998
  paddingVertical: 2,
13326
13999
  borderRadius: 4
13327
14000
  },
13328
14001
  priorityP0: {
13329
- backgroundColor: "#FEE2E2"
14002
+ backgroundColor: "#7f1d1d"
13330
14003
  },
13331
14004
  priorityP1: {
13332
- backgroundColor: "#FED7AA"
14005
+ backgroundColor: "#78350f"
13333
14006
  },
13334
14007
  priorityText: {
13335
14008
  fontSize: 12,
13336
14009
  fontWeight: "600",
13337
- color: "#374151"
14010
+ color: "#e4e4e7"
13338
14011
  },
13339
14012
  testTitle: {
13340
14013
  fontSize: 16,
13341
14014
  fontWeight: "600",
13342
- color: "#111827",
14015
+ color: "#fafafa",
13343
14016
  marginBottom: 4
13344
14017
  },
13345
14018
  testDescription: {
13346
14019
  fontSize: 14,
13347
- color: "#6B7280",
14020
+ color: "#a1a1aa",
13348
14021
  marginBottom: 8
13349
14022
  },
13350
14023
  // Navigate button
13351
14024
  navigateButton: {
13352
- backgroundColor: "#EFF6FF",
14025
+ backgroundColor: "#1e3a5f",
13353
14026
  borderWidth: 1,
13354
- borderColor: "#BFDBFE",
14027
+ borderColor: "#3B82F6",
13355
14028
  borderRadius: 8,
13356
14029
  paddingVertical: 10,
13357
14030
  paddingHorizontal: 16,
@@ -13361,7 +14034,7 @@ var styles = StyleSheet.create({
13361
14034
  navigateButtonText: {
13362
14035
  fontSize: 14,
13363
14036
  fontWeight: "500",
13364
- color: "#1D4ED8"
14037
+ color: "#60a5fa"
13365
14038
  },
13366
14039
  // Template badge
13367
14040
  templateBadge: {
@@ -13379,12 +14052,12 @@ var styles = StyleSheet.create({
13379
14052
  templateName: {
13380
14053
  fontSize: 12,
13381
14054
  fontWeight: "600",
13382
- color: "#374151",
14055
+ color: "#e4e4e7",
13383
14056
  marginRight: 4
13384
14057
  },
13385
14058
  templateAction: {
13386
14059
  fontSize: 12,
13387
- color: "#6B7280"
14060
+ color: "#71717a"
13388
14061
  },
13389
14062
  // Steps toggle
13390
14063
  stepsToggle: {
@@ -13392,7 +14065,7 @@ var styles = StyleSheet.create({
13392
14065
  },
13393
14066
  stepsToggleText: {
13394
14067
  fontSize: 14,
13395
- color: "#7C3AED",
14068
+ color: "#3B82F6",
13396
14069
  fontWeight: "500"
13397
14070
  },
13398
14071
  stepsList: {
@@ -13406,7 +14079,7 @@ var styles = StyleSheet.create({
13406
14079
  width: 24,
13407
14080
  height: 24,
13408
14081
  borderRadius: 12,
13409
- backgroundColor: "#EDE9FE",
14082
+ backgroundColor: "#1e3a5f",
13410
14083
  justifyContent: "center",
13411
14084
  alignItems: "center",
13412
14085
  marginRight: 12
@@ -13414,41 +14087,41 @@ var styles = StyleSheet.create({
13414
14087
  stepNumberText: {
13415
14088
  fontSize: 12,
13416
14089
  fontWeight: "600",
13417
- color: "#7C3AED"
14090
+ color: "#3B82F6"
13418
14091
  },
13419
14092
  stepContent: {
13420
14093
  flex: 1
13421
14094
  },
13422
14095
  stepAction: {
13423
14096
  fontSize: 14,
13424
- color: "#374151"
14097
+ color: "#e4e4e7"
13425
14098
  },
13426
14099
  stepExpected: {
13427
14100
  fontSize: 12,
13428
- color: "#9CA3AF",
14101
+ color: "#71717a",
13429
14102
  marginTop: 2
13430
14103
  },
13431
14104
  // Checklist styles
13432
14105
  checklistItem: {
13433
14106
  flexDirection: "row",
13434
14107
  alignItems: "center",
13435
- backgroundColor: "#fff",
14108
+ backgroundColor: "#27272a",
13436
14109
  borderWidth: 1,
13437
- borderColor: "#E5E7EB",
14110
+ borderColor: "#3f3f46",
13438
14111
  borderRadius: 8,
13439
14112
  padding: 12,
13440
14113
  marginBottom: 8
13441
14114
  },
13442
14115
  checklistItemChecked: {
13443
- backgroundColor: "#ECFDF5",
13444
- borderColor: "#86EFAC"
14116
+ backgroundColor: "#14532d",
14117
+ borderColor: "#22C55E"
13445
14118
  },
13446
14119
  checkbox: {
13447
14120
  width: 24,
13448
14121
  height: 24,
13449
14122
  borderRadius: 4,
13450
14123
  borderWidth: 2,
13451
- borderColor: "#22D3EE",
14124
+ borderColor: "#3B82F6",
13452
14125
  marginRight: 12,
13453
14126
  justifyContent: "center",
13454
14127
  alignItems: "center"
@@ -13465,16 +14138,16 @@ var styles = StyleSheet.create({
13465
14138
  checklistText: {
13466
14139
  flex: 1,
13467
14140
  fontSize: 14,
13468
- color: "#374151"
14141
+ color: "#e4e4e7"
13469
14142
  },
13470
14143
  checklistTextChecked: {
13471
- color: "#15803D"
14144
+ color: "#4ade80"
13472
14145
  },
13473
14146
  // Rubric styles
13474
14147
  rubricItem: {
13475
- backgroundColor: "#fff",
14148
+ backgroundColor: "#27272a",
13476
14149
  borderWidth: 1,
13477
- borderColor: "#E5E7EB",
14150
+ borderColor: "#3f3f46",
13478
14151
  borderRadius: 8,
13479
14152
  padding: 12,
13480
14153
  marginBottom: 8
@@ -13488,7 +14161,7 @@ var styles = StyleSheet.create({
13488
14161
  width: 24,
13489
14162
  height: 24,
13490
14163
  borderRadius: 4,
13491
- backgroundColor: "#EDE9FE",
14164
+ backgroundColor: "#1e3a5f",
13492
14165
  justifyContent: "center",
13493
14166
  alignItems: "center",
13494
14167
  marginRight: 8
@@ -13496,17 +14169,17 @@ var styles = StyleSheet.create({
13496
14169
  rubricNumberText: {
13497
14170
  fontSize: 12,
13498
14171
  fontWeight: "600",
13499
- color: "#7C3AED"
14172
+ color: "#3B82F6"
13500
14173
  },
13501
14174
  rubricTitle: {
13502
14175
  flex: 1,
13503
14176
  fontSize: 14,
13504
14177
  fontWeight: "500",
13505
- color: "#111827"
14178
+ color: "#fafafa"
13506
14179
  },
13507
14180
  rubricExpected: {
13508
14181
  fontSize: 12,
13509
- color: "#6B7280",
14182
+ color: "#71717a",
13510
14183
  marginLeft: 32,
13511
14184
  marginBottom: 8
13512
14185
  },
@@ -13520,7 +14193,7 @@ var styles = StyleSheet.create({
13520
14193
  paddingVertical: 8,
13521
14194
  paddingHorizontal: 12,
13522
14195
  borderRadius: 6,
13523
- backgroundColor: "#F3F4F6",
14196
+ backgroundColor: "#3f3f46",
13524
14197
  alignItems: "center"
13525
14198
  },
13526
14199
  passButtonActive: {
@@ -13532,7 +14205,7 @@ var styles = StyleSheet.create({
13532
14205
  passFailButtonText: {
13533
14206
  fontSize: 12,
13534
14207
  fontWeight: "600",
13535
- color: "#6B7280"
14208
+ color: "#a1a1aa"
13536
14209
  },
13537
14210
  passButtonTextActive: {
13538
14211
  color: "#fff"
@@ -13549,17 +14222,17 @@ var styles = StyleSheet.create({
13549
14222
  width: 36,
13550
14223
  height: 36,
13551
14224
  borderRadius: 6,
13552
- backgroundColor: "#F3F4F6",
14225
+ backgroundColor: "#3f3f46",
13553
14226
  justifyContent: "center",
13554
14227
  alignItems: "center"
13555
14228
  },
13556
14229
  ratingButtonActive: {
13557
- backgroundColor: "#7C3AED"
14230
+ backgroundColor: "#3B82F6"
13558
14231
  },
13559
14232
  ratingButtonText: {
13560
14233
  fontSize: 14,
13561
14234
  fontWeight: "600",
13562
- color: "#6B7280"
14235
+ color: "#a1a1aa"
13563
14236
  },
13564
14237
  ratingButtonTextActive: {
13565
14238
  color: "#fff"
@@ -13573,17 +14246,17 @@ var styles = StyleSheet.create({
13573
14246
  },
13574
14247
  helperText: {
13575
14248
  fontSize: 12,
13576
- color: "#9CA3AF"
14249
+ color: "#71717a"
13577
14250
  },
13578
14251
  resetText: {
13579
14252
  fontSize: 12,
13580
- color: "#9CA3AF"
14253
+ color: "#71717a"
13581
14254
  },
13582
14255
  // Freeform styles
13583
14256
  freeformBox: {
13584
- backgroundColor: "#FFFBEB",
14257
+ backgroundColor: "#422006",
13585
14258
  borderWidth: 1,
13586
- borderColor: "#FDE68A",
14259
+ borderColor: "#a16207",
13587
14260
  borderRadius: 8,
13588
14261
  padding: 12,
13589
14262
  marginTop: 8
@@ -13591,22 +14264,22 @@ var styles = StyleSheet.create({
13591
14264
  freeformTitle: {
13592
14265
  fontSize: 14,
13593
14266
  fontWeight: "600",
13594
- color: "#92400E",
14267
+ color: "#fbbf24",
13595
14268
  marginBottom: 4
13596
14269
  },
13597
14270
  freeformText: {
13598
14271
  fontSize: 12,
13599
- color: "#A16207",
14272
+ color: "#fcd34d",
13600
14273
  marginBottom: 4
13601
14274
  },
13602
14275
  freeformBullet: {
13603
14276
  fontSize: 12,
13604
- color: "#A16207",
14277
+ color: "#fcd34d",
13605
14278
  marginLeft: 8
13606
14279
  },
13607
14280
  // Expected result
13608
14281
  expectedResult: {
13609
- backgroundColor: "#ECFDF5",
14282
+ backgroundColor: "#14532d",
13610
14283
  padding: 12,
13611
14284
  borderRadius: 8,
13612
14285
  marginTop: 12
@@ -13614,12 +14287,12 @@ var styles = StyleSheet.create({
13614
14287
  expectedLabel: {
13615
14288
  fontSize: 12,
13616
14289
  fontWeight: "600",
13617
- color: "#065F46",
14290
+ color: "#4ade80",
13618
14291
  marginBottom: 4
13619
14292
  },
13620
14293
  expectedText: {
13621
14294
  fontSize: 14,
13622
- color: "#047857"
14295
+ color: "#86efac"
13623
14296
  },
13624
14297
  // Action buttons
13625
14298
  actionButtons: {
@@ -13628,7 +14301,7 @@ var styles = StyleSheet.create({
13628
14301
  },
13629
14302
  failButton: {
13630
14303
  flex: 1,
13631
- backgroundColor: "#FEE2E2",
14304
+ backgroundColor: "#7f1d1d",
13632
14305
  paddingVertical: 14,
13633
14306
  borderRadius: 12,
13634
14307
  alignItems: "center"
@@ -13636,7 +14309,7 @@ var styles = StyleSheet.create({
13636
14309
  failButtonText: {
13637
14310
  fontSize: 16,
13638
14311
  fontWeight: "600",
13639
- color: "#DC2626"
14312
+ color: "#fca5a5"
13640
14313
  },
13641
14314
  passButton: {
13642
14315
  flex: 1,
@@ -13658,22 +14331,22 @@ var styles = StyleSheet.create({
13658
14331
  },
13659
14332
  reportTypeButton: {
13660
14333
  flex: 1,
13661
- backgroundColor: "#F3F4F6",
14334
+ backgroundColor: "#3f3f46",
13662
14335
  paddingVertical: 10,
13663
14336
  borderRadius: 8,
13664
14337
  alignItems: "center"
13665
14338
  },
13666
14339
  reportTypeActive: {
13667
- backgroundColor: "#EDE9FE",
14340
+ backgroundColor: "#1e3a5f",
13668
14341
  borderWidth: 2,
13669
- borderColor: "#7C3AED"
14342
+ borderColor: "#3B82F6"
13670
14343
  },
13671
14344
  reportTypeText: {
13672
14345
  fontSize: 14,
13673
- color: "#6B7280"
14346
+ color: "#a1a1aa"
13674
14347
  },
13675
14348
  reportTypeTextActive: {
13676
- color: "#7C3AED",
14349
+ color: "#3B82F6",
13677
14350
  fontWeight: "600"
13678
14351
  },
13679
14352
  severitySection: {
@@ -13682,7 +14355,7 @@ var styles = StyleSheet.create({
13682
14355
  label: {
13683
14356
  fontSize: 14,
13684
14357
  fontWeight: "500",
13685
- color: "#374151",
14358
+ color: "#e4e4e7",
13686
14359
  marginBottom: 8
13687
14360
  },
13688
14361
  severityButtons: {
@@ -13691,7 +14364,7 @@ var styles = StyleSheet.create({
13691
14364
  },
13692
14365
  severityButton: {
13693
14366
  flex: 1,
13694
- backgroundColor: "#F3F4F6",
14367
+ backgroundColor: "#3f3f46",
13695
14368
  paddingVertical: 8,
13696
14369
  borderRadius: 6,
13697
14370
  alignItems: "center"
@@ -13710,7 +14383,7 @@ var styles = StyleSheet.create({
13710
14383
  },
13711
14384
  severityText: {
13712
14385
  fontSize: 12,
13713
- color: "#6B7280",
14386
+ color: "#a1a1aa",
13714
14387
  textTransform: "capitalize"
13715
14388
  },
13716
14389
  severityTextActive: {
@@ -13721,17 +14394,17 @@ var styles = StyleSheet.create({
13721
14394
  marginBottom: 16
13722
14395
  },
13723
14396
  textInput: {
13724
- backgroundColor: "#F9FAFB",
14397
+ backgroundColor: "#27272a",
13725
14398
  borderWidth: 1,
13726
- borderColor: "#E5E7EB",
14399
+ borderColor: "#3f3f46",
13727
14400
  borderRadius: 12,
13728
14401
  padding: 12,
13729
14402
  fontSize: 14,
13730
14403
  minHeight: 100,
13731
- color: "#111827"
14404
+ color: "#fafafa"
13732
14405
  },
13733
14406
  submitButton: {
13734
- backgroundColor: "#7C3AED",
14407
+ backgroundColor: "#3B82F6",
13735
14408
  paddingVertical: 14,
13736
14409
  borderRadius: 12,
13737
14410
  alignItems: "center"
@@ -13770,16 +14443,16 @@ var styles = StyleSheet.create({
13770
14443
  },
13771
14444
  // Thread list styles
13772
14445
  threadItem: {
13773
- backgroundColor: "#F9FAFB",
14446
+ backgroundColor: "#27272a",
13774
14447
  borderRadius: 12,
13775
14448
  padding: 12,
13776
14449
  marginBottom: 8,
13777
14450
  borderWidth: 1,
13778
- borderColor: "#E5E7EB"
14451
+ borderColor: "#3f3f46"
13779
14452
  },
13780
14453
  threadItemUnread: {
13781
- backgroundColor: "#EFF6FF",
13782
- borderColor: "#BFDBFE"
14454
+ backgroundColor: "#1e3a5f",
14455
+ borderColor: "#3B82F6"
13783
14456
  },
13784
14457
  threadHeader: {
13785
14458
  flexDirection: "row",
@@ -13803,12 +14476,12 @@ var styles = StyleSheet.create({
13803
14476
  threadSubject: {
13804
14477
  fontSize: 14,
13805
14478
  fontWeight: "500",
13806
- color: "#374151",
14479
+ color: "#e4e4e7",
13807
14480
  flex: 1
13808
14481
  },
13809
14482
  threadSubjectUnread: {
13810
14483
  fontWeight: "600",
13811
- color: "#111827"
14484
+ color: "#fafafa"
13812
14485
  },
13813
14486
  priorityDot: {
13814
14487
  width: 8,
@@ -13818,7 +14491,7 @@ var styles = StyleSheet.create({
13818
14491
  },
13819
14492
  threadPreview: {
13820
14493
  fontSize: 13,
13821
- color: "#6B7280",
14494
+ color: "#a1a1aa",
13822
14495
  marginBottom: 4
13823
14496
  },
13824
14497
  threadMeta: {
@@ -13828,7 +14501,7 @@ var styles = StyleSheet.create({
13828
14501
  },
13829
14502
  threadMetaText: {
13830
14503
  fontSize: 12,
13831
- color: "#9CA3AF"
14504
+ color: "#71717a"
13832
14505
  },
13833
14506
  unreadBadge: {
13834
14507
  backgroundColor: "#3B82F6",
@@ -13843,7 +14516,7 @@ var styles = StyleSheet.create({
13843
14516
  },
13844
14517
  threadTime: {
13845
14518
  fontSize: 12,
13846
- color: "#9CA3AF"
14519
+ color: "#71717a"
13847
14520
  },
13848
14521
  // Thread detail styles
13849
14522
  threadDetailContainer: {
@@ -13852,7 +14525,7 @@ var styles = StyleSheet.create({
13852
14525
  threadDetailHeader: {
13853
14526
  flexDirection: "row",
13854
14527
  alignItems: "center",
13855
- backgroundColor: "#F3F4F6",
14528
+ backgroundColor: "#27272a",
13856
14529
  padding: 12,
13857
14530
  borderRadius: 8,
13858
14531
  marginBottom: 12
@@ -13865,7 +14538,7 @@ var styles = StyleSheet.create({
13865
14538
  flex: 1,
13866
14539
  fontSize: 15,
13867
14540
  fontWeight: "600",
13868
- color: "#111827"
14541
+ color: "#fafafa"
13869
14542
  },
13870
14543
  loadingMessages: {
13871
14544
  padding: 20,
@@ -13873,7 +14546,7 @@ var styles = StyleSheet.create({
13873
14546
  },
13874
14547
  loadingText: {
13875
14548
  fontSize: 14,
13876
- color: "#6B7280"
14549
+ color: "#71717a"
13877
14550
  },
13878
14551
  messagesContainer: {
13879
14552
  paddingBottom: 8
@@ -13886,26 +14559,26 @@ var styles = StyleSheet.create({
13886
14559
  },
13887
14560
  messageBubbleAdmin: {
13888
14561
  alignSelf: "flex-start",
13889
- backgroundColor: "#F3F4F6",
14562
+ backgroundColor: "#27272a",
13890
14563
  borderBottomLeftRadius: 4
13891
14564
  },
13892
14565
  messageBubbleTester: {
13893
14566
  alignSelf: "flex-end",
13894
- backgroundColor: "#7C3AED",
14567
+ backgroundColor: "#3B82F6",
13895
14568
  borderBottomRightRadius: 4
13896
14569
  },
13897
14570
  messageSender: {
13898
14571
  fontSize: 12,
13899
14572
  fontWeight: "600",
13900
- color: "#6B7280",
14573
+ color: "#71717a",
13901
14574
  marginBottom: 2
13902
14575
  },
13903
14576
  messageSenderTester: {
13904
- color: "#DDD6FE"
14577
+ color: "#93c5fd"
13905
14578
  },
13906
14579
  messageContent: {
13907
14580
  fontSize: 14,
13908
- color: "#111827",
14581
+ color: "#fafafa",
13909
14582
  lineHeight: 20
13910
14583
  },
13911
14584
  messageContentTester: {
@@ -13913,12 +14586,12 @@ var styles = StyleSheet.create({
13913
14586
  },
13914
14587
  messageTime: {
13915
14588
  fontSize: 11,
13916
- color: "#9CA3AF",
14589
+ color: "#71717a",
13917
14590
  marginTop: 4,
13918
14591
  textAlign: "right"
13919
14592
  },
13920
14593
  messageTimeTester: {
13921
- color: "#C4B5FD"
14594
+ color: "#93c5fd"
13922
14595
  },
13923
14596
  // Reply composer styles
13924
14597
  replyComposer: {
@@ -13926,24 +14599,24 @@ var styles = StyleSheet.create({
13926
14599
  alignItems: "flex-end",
13927
14600
  padding: 12,
13928
14601
  borderTopWidth: 1,
13929
- borderTopColor: "#E5E7EB",
13930
- backgroundColor: "#fff"
14602
+ borderTopColor: "#27272a",
14603
+ backgroundColor: "#18181b"
13931
14604
  },
13932
14605
  replyInput: {
13933
14606
  flex: 1,
13934
- backgroundColor: "#F9FAFB",
14607
+ backgroundColor: "#27272a",
13935
14608
  borderWidth: 1,
13936
- borderColor: "#E5E7EB",
14609
+ borderColor: "#3f3f46",
13937
14610
  borderRadius: 20,
13938
14611
  paddingHorizontal: 16,
13939
14612
  paddingVertical: 10,
13940
14613
  fontSize: 14,
13941
- color: "#111827",
14614
+ color: "#fafafa",
13942
14615
  maxHeight: 100,
13943
14616
  marginRight: 8
13944
14617
  },
13945
14618
  sendButton: {
13946
- backgroundColor: "#7C3AED",
14619
+ backgroundColor: "#3B82F6",
13947
14620
  paddingHorizontal: 16,
13948
14621
  paddingVertical: 10,
13949
14622
  borderRadius: 20,
@@ -13951,7 +14624,7 @@ var styles = StyleSheet.create({
13951
14624
  alignItems: "center"
13952
14625
  },
13953
14626
  sendButtonDisabled: {
13954
- backgroundColor: "#C4B5FD"
14627
+ backgroundColor: "#1e40af"
13955
14628
  },
13956
14629
  sendButtonText: {
13957
14630
  fontSize: 14,
@@ -13963,7 +14636,7 @@ var styles = StyleSheet.create({
13963
14636
  flexDirection: "row",
13964
14637
  alignItems: "center",
13965
14638
  justifyContent: "center",
13966
- backgroundColor: "#7C3AED",
14639
+ backgroundColor: "#3B82F6",
13967
14640
  paddingVertical: 12,
13968
14641
  paddingHorizontal: 20,
13969
14642
  borderRadius: 12,
@@ -13985,48 +14658,50 @@ var styles = StyleSheet.create({
13985
14658
  composeTitle: {
13986
14659
  fontSize: 20,
13987
14660
  fontWeight: "600",
13988
- color: "#111827",
14661
+ color: "#fafafa",
13989
14662
  marginBottom: 4
13990
14663
  },
13991
14664
  composeSubtitle: {
13992
14665
  fontSize: 14,
13993
- color: "#6B7280"
14666
+ color: "#71717a"
13994
14667
  },
13995
14668
  composeForm: {
13996
- backgroundColor: "#F9FAFB",
14669
+ backgroundColor: "#27272a",
13997
14670
  borderRadius: 12,
13998
- padding: 16
14671
+ padding: 16,
14672
+ borderWidth: 1,
14673
+ borderColor: "#3f3f46"
13999
14674
  },
14000
14675
  composeSubjectInput: {
14001
- backgroundColor: "#fff",
14676
+ backgroundColor: "#18181b",
14002
14677
  borderWidth: 1,
14003
- borderColor: "#E5E7EB",
14678
+ borderColor: "#3f3f46",
14004
14679
  borderRadius: 8,
14005
14680
  paddingHorizontal: 12,
14006
14681
  paddingVertical: 10,
14007
14682
  fontSize: 15,
14008
- color: "#111827"
14683
+ color: "#fafafa"
14009
14684
  },
14010
14685
  composeMessageInput: {
14011
- backgroundColor: "#fff",
14686
+ backgroundColor: "#18181b",
14012
14687
  borderWidth: 1,
14013
- borderColor: "#E5E7EB",
14688
+ borderColor: "#3f3f46",
14014
14689
  borderRadius: 8,
14015
14690
  paddingHorizontal: 12,
14016
14691
  paddingVertical: 10,
14017
14692
  fontSize: 15,
14018
- color: "#111827",
14693
+ color: "#fafafa",
14019
14694
  minHeight: 120
14020
14695
  },
14021
14696
  composeSendButton: {
14022
- backgroundColor: "#7C3AED",
14697
+ backgroundColor: "#3B82F6",
14023
14698
  paddingVertical: 14,
14024
14699
  borderRadius: 12,
14025
14700
  alignItems: "center",
14026
14701
  marginTop: 20
14027
14702
  },
14028
14703
  composeSendButtonDisabled: {
14029
- backgroundColor: "#C4B5FD"
14704
+ backgroundColor: "#1e40af"
14030
14705
  },
14031
14706
  composeSendButtonText: {
14032
14707
  fontSize: 16,
@@ -14035,17 +14710,19 @@ var styles = StyleSheet.create({
14035
14710
  },
14036
14711
  // Profile styles
14037
14712
  profileCard: {
14038
- backgroundColor: "#F9FAFB",
14713
+ backgroundColor: "#27272a",
14039
14714
  borderRadius: 16,
14040
14715
  padding: 24,
14041
14716
  alignItems: "center",
14042
- marginBottom: 16
14717
+ marginBottom: 16,
14718
+ borderWidth: 1,
14719
+ borderColor: "#3f3f46"
14043
14720
  },
14044
14721
  avatarCircle: {
14045
14722
  width: 72,
14046
14723
  height: 72,
14047
14724
  borderRadius: 36,
14048
- backgroundColor: "#7C3AED",
14725
+ backgroundColor: "#3B82F6",
14049
14726
  justifyContent: "center",
14050
14727
  alignItems: "center",
14051
14728
  marginBottom: 12
@@ -14058,12 +14735,12 @@ var styles = StyleSheet.create({
14058
14735
  profileName: {
14059
14736
  fontSize: 20,
14060
14737
  fontWeight: "600",
14061
- color: "#111827",
14738
+ color: "#fafafa",
14062
14739
  marginBottom: 4
14063
14740
  },
14064
14741
  profileEmail: {
14065
14742
  fontSize: 14,
14066
- color: "#6B7280",
14743
+ color: "#71717a",
14067
14744
  marginBottom: 16
14068
14745
  },
14069
14746
  profileStats: {
@@ -14077,35 +14754,37 @@ var styles = StyleSheet.create({
14077
14754
  profileStatValue: {
14078
14755
  fontSize: 24,
14079
14756
  fontWeight: "700",
14080
- color: "#7C3AED"
14757
+ color: "#3B82F6"
14081
14758
  },
14082
14759
  profileStatLabel: {
14083
14760
  fontSize: 12,
14084
- color: "#6B7280",
14761
+ color: "#71717a",
14085
14762
  marginTop: 2
14086
14763
  },
14087
14764
  profileStatDivider: {
14088
14765
  width: 1,
14089
14766
  height: 32,
14090
- backgroundColor: "#E5E7EB"
14767
+ backgroundColor: "#3f3f46"
14091
14768
  },
14092
14769
  profileInfoSection: {
14093
- backgroundColor: "#F9FAFB",
14770
+ backgroundColor: "#27272a",
14094
14771
  borderRadius: 12,
14095
14772
  padding: 16,
14096
- marginBottom: 12
14773
+ marginBottom: 12,
14774
+ borderWidth: 1,
14775
+ borderColor: "#3f3f46"
14097
14776
  },
14098
14777
  profileInfoLabel: {
14099
14778
  fontSize: 12,
14100
14779
  fontWeight: "600",
14101
- color: "#6B7280",
14780
+ color: "#71717a",
14102
14781
  marginBottom: 8,
14103
14782
  textTransform: "uppercase",
14104
14783
  letterSpacing: 0.5
14105
14784
  },
14106
14785
  profileInfoValue: {
14107
14786
  fontSize: 14,
14108
- color: "#374151",
14787
+ color: "#e4e4e7",
14109
14788
  marginBottom: 4
14110
14789
  },
14111
14790
  platformTags: {
@@ -14114,18 +14793,18 @@ var styles = StyleSheet.create({
14114
14793
  gap: 8
14115
14794
  },
14116
14795
  platformTag: {
14117
- backgroundColor: "#EDE9FE",
14796
+ backgroundColor: "#1e3a5f",
14118
14797
  paddingHorizontal: 12,
14119
14798
  paddingVertical: 6,
14120
14799
  borderRadius: 16
14121
14800
  },
14122
14801
  platformTagText: {
14123
14802
  fontSize: 13,
14124
- color: "#7C3AED",
14803
+ color: "#60a5fa",
14125
14804
  fontWeight: "500"
14126
14805
  },
14127
14806
  editProfileButton: {
14128
- backgroundColor: "#7C3AED",
14807
+ backgroundColor: "#3B82F6",
14129
14808
  paddingVertical: 14,
14130
14809
  borderRadius: 12,
14131
14810
  alignItems: "center",
@@ -14146,48 +14825,48 @@ var styles = StyleSheet.create({
14146
14825
  profileEditTitle: {
14147
14826
  fontSize: 20,
14148
14827
  fontWeight: "600",
14149
- color: "#111827"
14828
+ color: "#fafafa"
14150
14829
  },
14151
14830
  cancelText: {
14152
14831
  fontSize: 14,
14153
- color: "#6B7280"
14832
+ color: "#71717a"
14154
14833
  },
14155
14834
  profileSection: {
14156
14835
  marginBottom: 20
14157
14836
  },
14158
14837
  profileInput: {
14159
- backgroundColor: "#F9FAFB",
14838
+ backgroundColor: "#27272a",
14160
14839
  borderWidth: 1,
14161
- borderColor: "#E5E7EB",
14840
+ borderColor: "#3f3f46",
14162
14841
  borderRadius: 10,
14163
14842
  paddingHorizontal: 14,
14164
14843
  paddingVertical: 12,
14165
14844
  fontSize: 15,
14166
- color: "#111827"
14845
+ color: "#fafafa"
14167
14846
  },
14168
14847
  profileReadOnly: {
14169
- backgroundColor: "#F3F4F6",
14848
+ backgroundColor: "#27272a",
14170
14849
  borderRadius: 10,
14171
14850
  padding: 14
14172
14851
  },
14173
14852
  profileReadOnlyText: {
14174
14853
  fontSize: 15,
14175
- color: "#374151"
14854
+ color: "#a1a1aa"
14176
14855
  },
14177
14856
  profileReadOnlyHint: {
14178
14857
  fontSize: 12,
14179
- color: "#9CA3AF",
14858
+ color: "#52525b",
14180
14859
  marginTop: 4
14181
14860
  },
14182
14861
  profileHint: {
14183
14862
  fontSize: 13,
14184
- color: "#6B7280",
14863
+ color: "#71717a",
14185
14864
  marginBottom: 12
14186
14865
  },
14187
14866
  emailChip: {
14188
14867
  flexDirection: "row",
14189
14868
  alignItems: "center",
14190
- backgroundColor: "#EDE9FE",
14869
+ backgroundColor: "#1e3a5f",
14191
14870
  paddingHorizontal: 12,
14192
14871
  paddingVertical: 8,
14193
14872
  borderRadius: 20,
@@ -14196,11 +14875,11 @@ var styles = StyleSheet.create({
14196
14875
  emailChipText: {
14197
14876
  flex: 1,
14198
14877
  fontSize: 14,
14199
- color: "#5B21B6"
14878
+ color: "#60a5fa"
14200
14879
  },
14201
14880
  emailChipRemove: {
14202
14881
  fontSize: 14,
14203
- color: "#8B5CF6",
14882
+ color: "#93c5fd",
14204
14883
  fontWeight: "600",
14205
14884
  marginLeft: 8
14206
14885
  },
@@ -14210,23 +14889,23 @@ var styles = StyleSheet.create({
14210
14889
  },
14211
14890
  addEmailInput: {
14212
14891
  flex: 1,
14213
- backgroundColor: "#F9FAFB",
14892
+ backgroundColor: "#27272a",
14214
14893
  borderWidth: 1,
14215
- borderColor: "#E5E7EB",
14894
+ borderColor: "#3f3f46",
14216
14895
  borderRadius: 10,
14217
14896
  paddingHorizontal: 14,
14218
14897
  paddingVertical: 10,
14219
14898
  fontSize: 14,
14220
- color: "#111827"
14899
+ color: "#fafafa"
14221
14900
  },
14222
14901
  addEmailButton: {
14223
- backgroundColor: "#7C3AED",
14902
+ backgroundColor: "#3B82F6",
14224
14903
  paddingHorizontal: 16,
14225
14904
  borderRadius: 10,
14226
14905
  justifyContent: "center"
14227
14906
  },
14228
14907
  addEmailButtonDisabled: {
14229
- backgroundColor: "#C4B5FD"
14908
+ backgroundColor: "#1e40af"
14230
14909
  },
14231
14910
  addEmailButtonText: {
14232
14911
  fontSize: 14,
@@ -14239,7 +14918,7 @@ var styles = StyleSheet.create({
14239
14918
  },
14240
14919
  platformButton: {
14241
14920
  flex: 1,
14242
- backgroundColor: "#F3F4F6",
14921
+ backgroundColor: "#3f3f46",
14243
14922
  paddingVertical: 12,
14244
14923
  borderRadius: 10,
14245
14924
  alignItems: "center",
@@ -14247,16 +14926,16 @@ var styles = StyleSheet.create({
14247
14926
  borderColor: "transparent"
14248
14927
  },
14249
14928
  platformButtonActive: {
14250
- backgroundColor: "#EDE9FE",
14251
- borderColor: "#7C3AED"
14929
+ backgroundColor: "#1e3a5f",
14930
+ borderColor: "#3B82F6"
14252
14931
  },
14253
14932
  platformButtonText: {
14254
14933
  fontSize: 13,
14255
- color: "#6B7280",
14934
+ color: "#a1a1aa",
14256
14935
  fontWeight: "500"
14257
14936
  },
14258
14937
  platformButtonTextActive: {
14259
- color: "#7C3AED"
14938
+ color: "#3B82F6"
14260
14939
  },
14261
14940
  saveProfileButton: {
14262
14941
  backgroundColor: "#16A34A",
@@ -14272,6 +14951,35 @@ var styles = StyleSheet.create({
14272
14951
  fontSize: 16,
14273
14952
  fontWeight: "600",
14274
14953
  color: "#fff"
14954
+ },
14955
+ // Profile overlay styles
14956
+ profileOverlay: {
14957
+ position: "absolute",
14958
+ top: 0,
14959
+ left: 0,
14960
+ right: 0,
14961
+ bottom: 0,
14962
+ backgroundColor: "#18181b",
14963
+ zIndex: 100
14964
+ },
14965
+ profileOverlayContent: {
14966
+ flex: 1,
14967
+ padding: 16
14968
+ },
14969
+ profileOverlayFooter: {
14970
+ borderTopWidth: 1,
14971
+ borderTopColor: "#27272a",
14972
+ padding: 12,
14973
+ backgroundColor: "#09090b"
14974
+ },
14975
+ closeProfileButton: {
14976
+ paddingVertical: 8,
14977
+ alignItems: "center"
14978
+ },
14979
+ closeProfileButtonText: {
14980
+ fontSize: 14,
14981
+ fontWeight: "500",
14982
+ color: "#3B82F6"
14275
14983
  }
14276
14984
  });
14277
14985
  export {