@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.d.mts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +2279 -297
- package/dist/index.mjs +2280 -298
- 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,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
|
-
|
|
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:
|
|
11529
|
-
name:
|
|
11530
|
-
email:
|
|
11531
|
-
additionalEmails:
|
|
11532
|
-
avatarUrl:
|
|
11533
|
-
platforms:
|
|
11534
|
-
assignedTests:
|
|
11535
|
-
completedTests:
|
|
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("
|
|
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
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
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
|
-
*
|
|
12409
|
+
* End the current QA session
|
|
11942
12410
|
*/
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
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
|
-
*
|
|
12431
|
+
* Get the current active session for the tester
|
|
11951
12432
|
*/
|
|
11952
|
-
|
|
11953
|
-
|
|
11954
|
-
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
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
|
|
12446
|
+
* Get a session by ID
|
|
11965
12447
|
*/
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
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
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
}
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
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
|
-
}
|
|
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` : "#
|
|
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
|
|
12777
|
-
/* @__PURE__ */ React2.createElement(View, null, /* @__PURE__ */ React2.createElement(Text, { style: styles.listHeader }, assignments.length, " test", assignments.length !== 1 ? "s" : "", " assigned"),
|
|
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:
|
|
12781
|
-
onPress: () =>
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
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
|
-
|
|
12788
|
-
|
|
13834
|
+
feedbackStyles.flagButton,
|
|
13835
|
+
feedbackFlags[key] && feedbackStyles.flagButtonActive
|
|
12789
13836
|
]
|
|
12790
13837
|
},
|
|
12791
|
-
/* @__PURE__ */ React2.createElement(
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
|
|
12797
|
-
|
|
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))),
|
|
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: "#
|
|
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: "#
|
|
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 === "
|
|
12920
|
-
|
|
12921
|
-
{
|
|
12922
|
-
|
|
12923
|
-
|
|
12924
|
-
|
|
12925
|
-
|
|
12926
|
-
|
|
12927
|
-
|
|
12928
|
-
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
14399
|
+
backgroundColor: "#3B82F6",
|
|
13095
14400
|
justifyContent: "center",
|
|
13096
14401
|
alignItems: "center",
|
|
13097
|
-
shadowColor: "#
|
|
14402
|
+
shadowColor: "#3B82F6",
|
|
13098
14403
|
shadowOffset: { width: 0, height: 4 },
|
|
13099
|
-
shadowOpacity: 0.
|
|
13100
|
-
shadowRadius:
|
|
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.
|
|
14438
|
+
backgroundColor: "rgba(0, 0, 0, 0.6)"
|
|
13134
14439
|
},
|
|
13135
14440
|
modalContent: {
|
|
13136
|
-
backgroundColor: "#
|
|
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: "#
|
|
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: "#
|
|
14467
|
+
color: "#fafafa",
|
|
13161
14468
|
fontSize: 16,
|
|
13162
14469
|
fontWeight: "600"
|
|
13163
14470
|
},
|
|
13164
14471
|
headerSubtitle: {
|
|
13165
|
-
color: "#
|
|
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: "#
|
|
14481
|
+
color: "#71717a",
|
|
13175
14482
|
fontSize: 11
|
|
13176
14483
|
},
|
|
13177
14484
|
closeButton: {
|
|
13178
14485
|
padding: 8
|
|
13179
14486
|
},
|
|
13180
14487
|
closeButtonText: {
|
|
13181
|
-
color: "#
|
|
14488
|
+
color: "#a1a1aa",
|
|
13182
14489
|
fontSize: 18
|
|
13183
14490
|
},
|
|
13184
14491
|
tabs: {
|
|
13185
14492
|
flexDirection: "row",
|
|
13186
14493
|
borderBottomWidth: 1,
|
|
13187
|
-
borderBottomColor: "#
|
|
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: "#
|
|
14504
|
+
borderBottomColor: "#3B82F6"
|
|
13197
14505
|
},
|
|
13198
14506
|
tabText: {
|
|
13199
14507
|
fontSize: 14,
|
|
13200
14508
|
fontWeight: "500",
|
|
13201
|
-
color: "#
|
|
14509
|
+
color: "#71717a"
|
|
13202
14510
|
},
|
|
13203
14511
|
activeTabText: {
|
|
13204
|
-
color: "#
|
|
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: "#
|
|
13218
|
-
backgroundColor: "#
|
|
14525
|
+
borderTopColor: "#27272a",
|
|
14526
|
+
backgroundColor: "#09090b"
|
|
13219
14527
|
},
|
|
13220
14528
|
footerText: {
|
|
13221
14529
|
fontSize: 12,
|
|
13222
|
-
color: "#
|
|
14530
|
+
color: "#52525b"
|
|
13223
14531
|
},
|
|
13224
14532
|
refreshText: {
|
|
13225
14533
|
fontSize: 12,
|
|
13226
|
-
color: "#
|
|
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: "#
|
|
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: "#
|
|
14561
|
+
color: "#71717a",
|
|
13254
14562
|
marginTop: 4
|
|
13255
14563
|
},
|
|
13256
14564
|
// List view styles
|
|
13257
14565
|
listHeader: {
|
|
13258
14566
|
fontSize: 12,
|
|
13259
|
-
color: "#
|
|
14567
|
+
color: "#71717a",
|
|
13260
14568
|
marginBottom: 12
|
|
13261
14569
|
},
|
|
13262
14570
|
listItem: {
|
|
13263
|
-
backgroundColor: "#
|
|
14571
|
+
backgroundColor: "#27272a",
|
|
13264
14572
|
borderRadius: 12,
|
|
13265
14573
|
padding: 12,
|
|
13266
14574
|
marginBottom: 8,
|
|
13267
14575
|
borderWidth: 1,
|
|
13268
|
-
borderColor: "#
|
|
14576
|
+
borderColor: "#3f3f46"
|
|
13269
14577
|
},
|
|
13270
14578
|
listItemCurrent: {
|
|
13271
|
-
backgroundColor: "#
|
|
13272
|
-
borderColor: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
14609
|
+
color: "#71717a"
|
|
13302
14610
|
},
|
|
13303
14611
|
currentBadge: {
|
|
13304
14612
|
fontSize: 12,
|
|
13305
|
-
color: "#
|
|
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: "#
|
|
14623
|
+
color: "#3B82F6",
|
|
13316
14624
|
fontWeight: "500"
|
|
13317
14625
|
},
|
|
13318
14626
|
// Test card styles
|
|
13319
14627
|
testCard: {
|
|
13320
|
-
backgroundColor: "#
|
|
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: "#
|
|
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: "#
|
|
14660
|
+
backgroundColor: "#3f3f46",
|
|
13351
14661
|
paddingHorizontal: 8,
|
|
13352
14662
|
paddingVertical: 2,
|
|
13353
14663
|
borderRadius: 4
|
|
13354
14664
|
},
|
|
13355
14665
|
priorityP0: {
|
|
13356
|
-
backgroundColor: "#
|
|
14666
|
+
backgroundColor: "#7f1d1d"
|
|
13357
14667
|
},
|
|
13358
14668
|
priorityP1: {
|
|
13359
|
-
backgroundColor: "#
|
|
14669
|
+
backgroundColor: "#78350f"
|
|
13360
14670
|
},
|
|
13361
14671
|
priorityText: {
|
|
13362
14672
|
fontSize: 12,
|
|
13363
14673
|
fontWeight: "600",
|
|
13364
|
-
color: "#
|
|
14674
|
+
color: "#e4e4e7"
|
|
13365
14675
|
},
|
|
13366
14676
|
testTitle: {
|
|
13367
14677
|
fontSize: 16,
|
|
13368
14678
|
fontWeight: "600",
|
|
13369
|
-
color: "#
|
|
14679
|
+
color: "#fafafa",
|
|
13370
14680
|
marginBottom: 4
|
|
13371
14681
|
},
|
|
13372
14682
|
testDescription: {
|
|
13373
14683
|
fontSize: 14,
|
|
13374
|
-
color: "#
|
|
14684
|
+
color: "#a1a1aa",
|
|
13375
14685
|
marginBottom: 8
|
|
13376
14686
|
},
|
|
13377
14687
|
// Navigate button
|
|
13378
14688
|
navigateButton: {
|
|
13379
|
-
backgroundColor: "#
|
|
14689
|
+
backgroundColor: "#1e3a5f",
|
|
13380
14690
|
borderWidth: 1,
|
|
13381
|
-
borderColor: "#
|
|
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: "#
|
|
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: "#
|
|
14719
|
+
color: "#e4e4e7",
|
|
13410
14720
|
marginRight: 4
|
|
13411
14721
|
},
|
|
13412
14722
|
templateAction: {
|
|
13413
14723
|
fontSize: 12,
|
|
13414
|
-
color: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
14754
|
+
color: "#3B82F6"
|
|
13445
14755
|
},
|
|
13446
14756
|
stepContent: {
|
|
13447
14757
|
flex: 1
|
|
13448
14758
|
},
|
|
13449
14759
|
stepAction: {
|
|
13450
14760
|
fontSize: 14,
|
|
13451
|
-
color: "#
|
|
14761
|
+
color: "#e4e4e7"
|
|
13452
14762
|
},
|
|
13453
14763
|
stepExpected: {
|
|
13454
14764
|
fontSize: 12,
|
|
13455
|
-
color: "#
|
|
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: "#
|
|
14772
|
+
backgroundColor: "#27272a",
|
|
13463
14773
|
borderWidth: 1,
|
|
13464
|
-
borderColor: "#
|
|
14774
|
+
borderColor: "#3f3f46",
|
|
13465
14775
|
borderRadius: 8,
|
|
13466
14776
|
padding: 12,
|
|
13467
14777
|
marginBottom: 8
|
|
13468
14778
|
},
|
|
13469
14779
|
checklistItemChecked: {
|
|
13470
|
-
backgroundColor: "#
|
|
13471
|
-
borderColor: "#
|
|
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: "#
|
|
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: "#
|
|
14805
|
+
color: "#e4e4e7"
|
|
13496
14806
|
},
|
|
13497
14807
|
checklistTextChecked: {
|
|
13498
|
-
color: "#
|
|
14808
|
+
color: "#4ade80"
|
|
13499
14809
|
},
|
|
13500
14810
|
// Rubric styles
|
|
13501
14811
|
rubricItem: {
|
|
13502
|
-
backgroundColor: "#
|
|
14812
|
+
backgroundColor: "#27272a",
|
|
13503
14813
|
borderWidth: 1,
|
|
13504
|
-
borderColor: "#
|
|
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: "#
|
|
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: "#
|
|
14836
|
+
color: "#3B82F6"
|
|
13527
14837
|
},
|
|
13528
14838
|
rubricTitle: {
|
|
13529
14839
|
flex: 1,
|
|
13530
14840
|
fontSize: 14,
|
|
13531
14841
|
fontWeight: "500",
|
|
13532
|
-
color: "#
|
|
14842
|
+
color: "#fafafa"
|
|
13533
14843
|
},
|
|
13534
14844
|
rubricExpected: {
|
|
13535
14845
|
fontSize: 12,
|
|
13536
|
-
color: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
14889
|
+
backgroundColor: "#3f3f46",
|
|
13580
14890
|
justifyContent: "center",
|
|
13581
14891
|
alignItems: "center"
|
|
13582
14892
|
},
|
|
13583
14893
|
ratingButtonActive: {
|
|
13584
|
-
backgroundColor: "#
|
|
14894
|
+
backgroundColor: "#3B82F6"
|
|
13585
14895
|
},
|
|
13586
14896
|
ratingButtonText: {
|
|
13587
14897
|
fontSize: 14,
|
|
13588
14898
|
fontWeight: "600",
|
|
13589
|
-
color: "#
|
|
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: "#
|
|
14913
|
+
color: "#71717a"
|
|
13604
14914
|
},
|
|
13605
14915
|
resetText: {
|
|
13606
14916
|
fontSize: 12,
|
|
13607
|
-
color: "#
|
|
14917
|
+
color: "#71717a"
|
|
13608
14918
|
},
|
|
13609
14919
|
// Freeform styles
|
|
13610
14920
|
freeformBox: {
|
|
13611
|
-
backgroundColor: "#
|
|
14921
|
+
backgroundColor: "#422006",
|
|
13612
14922
|
borderWidth: 1,
|
|
13613
|
-
borderColor: "#
|
|
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: "#
|
|
14931
|
+
color: "#fbbf24",
|
|
13622
14932
|
marginBottom: 4
|
|
13623
14933
|
},
|
|
13624
14934
|
freeformText: {
|
|
13625
14935
|
fontSize: 12,
|
|
13626
|
-
color: "#
|
|
14936
|
+
color: "#fcd34d",
|
|
13627
14937
|
marginBottom: 4
|
|
13628
14938
|
},
|
|
13629
14939
|
freeformBullet: {
|
|
13630
14940
|
fontSize: 12,
|
|
13631
|
-
color: "#
|
|
14941
|
+
color: "#fcd34d",
|
|
13632
14942
|
marginLeft: 8
|
|
13633
14943
|
},
|
|
13634
14944
|
// Expected result
|
|
13635
14945
|
expectedResult: {
|
|
13636
|
-
backgroundColor: "#
|
|
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: "#
|
|
14954
|
+
color: "#4ade80",
|
|
13645
14955
|
marginBottom: 4
|
|
13646
14956
|
},
|
|
13647
14957
|
expectedText: {
|
|
13648
14958
|
fontSize: 14,
|
|
13649
|
-
color: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
14998
|
+
backgroundColor: "#3f3f46",
|
|
13689
14999
|
paddingVertical: 10,
|
|
13690
15000
|
borderRadius: 8,
|
|
13691
15001
|
alignItems: "center"
|
|
13692
15002
|
},
|
|
13693
15003
|
reportTypeActive: {
|
|
13694
|
-
backgroundColor: "#
|
|
15004
|
+
backgroundColor: "#1e3a5f",
|
|
13695
15005
|
borderWidth: 2,
|
|
13696
|
-
borderColor: "#
|
|
15006
|
+
borderColor: "#3B82F6"
|
|
13697
15007
|
},
|
|
13698
15008
|
reportTypeText: {
|
|
13699
15009
|
fontSize: 14,
|
|
13700
|
-
color: "#
|
|
15010
|
+
color: "#a1a1aa"
|
|
13701
15011
|
},
|
|
13702
15012
|
reportTypeTextActive: {
|
|
13703
|
-
color: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
15061
|
+
backgroundColor: "#27272a",
|
|
13752
15062
|
borderWidth: 1,
|
|
13753
|
-
borderColor: "#
|
|
15063
|
+
borderColor: "#3f3f46",
|
|
13754
15064
|
borderRadius: 12,
|
|
13755
15065
|
padding: 12,
|
|
13756
15066
|
fontSize: 14,
|
|
13757
15067
|
minHeight: 100,
|
|
13758
|
-
color: "#
|
|
15068
|
+
color: "#fafafa"
|
|
13759
15069
|
},
|
|
13760
15070
|
submitButton: {
|
|
13761
|
-
backgroundColor: "#
|
|
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: "#
|
|
15117
|
+
backgroundColor: "#27272a",
|
|
13801
15118
|
borderRadius: 12,
|
|
13802
15119
|
padding: 12,
|
|
13803
15120
|
marginBottom: 8,
|
|
13804
15121
|
borderWidth: 1,
|
|
13805
|
-
borderColor: "#
|
|
15122
|
+
borderColor: "#3f3f46"
|
|
13806
15123
|
},
|
|
13807
15124
|
threadItemUnread: {
|
|
13808
|
-
backgroundColor: "#
|
|
13809
|
-
borderColor: "#
|
|
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: "#
|
|
15150
|
+
color: "#e4e4e7",
|
|
13834
15151
|
flex: 1
|
|
13835
15152
|
},
|
|
13836
15153
|
threadSubjectUnread: {
|
|
13837
15154
|
fontWeight: "600",
|
|
13838
|
-
color: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
15233
|
+
backgroundColor: "#27272a",
|
|
13917
15234
|
borderBottomLeftRadius: 4
|
|
13918
15235
|
},
|
|
13919
15236
|
messageBubbleTester: {
|
|
13920
15237
|
alignSelf: "flex-end",
|
|
13921
|
-
backgroundColor: "#
|
|
15238
|
+
backgroundColor: "#3B82F6",
|
|
13922
15239
|
borderBottomRightRadius: 4
|
|
13923
15240
|
},
|
|
13924
15241
|
messageSender: {
|
|
13925
15242
|
fontSize: 12,
|
|
13926
15243
|
fontWeight: "600",
|
|
13927
|
-
color: "#
|
|
15244
|
+
color: "#71717a",
|
|
13928
15245
|
marginBottom: 2
|
|
13929
15246
|
},
|
|
13930
15247
|
messageSenderTester: {
|
|
13931
|
-
color: "#
|
|
15248
|
+
color: "#93c5fd"
|
|
13932
15249
|
},
|
|
13933
15250
|
messageContent: {
|
|
13934
15251
|
fontSize: 14,
|
|
13935
|
-
color: "#
|
|
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: "#
|
|
15260
|
+
color: "#71717a",
|
|
13944
15261
|
marginTop: 4,
|
|
13945
15262
|
textAlign: "right"
|
|
13946
15263
|
},
|
|
13947
15264
|
messageTimeTester: {
|
|
13948
|
-
color: "#
|
|
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: "#
|
|
13957
|
-
backgroundColor: "#
|
|
15273
|
+
borderTopColor: "#27272a",
|
|
15274
|
+
backgroundColor: "#18181b"
|
|
13958
15275
|
},
|
|
13959
15276
|
replyInput: {
|
|
13960
15277
|
flex: 1,
|
|
13961
|
-
backgroundColor: "#
|
|
15278
|
+
backgroundColor: "#27272a",
|
|
13962
15279
|
borderWidth: 1,
|
|
13963
|
-
borderColor: "#
|
|
15280
|
+
borderColor: "#3f3f46",
|
|
13964
15281
|
borderRadius: 20,
|
|
13965
15282
|
paddingHorizontal: 16,
|
|
13966
15283
|
paddingVertical: 10,
|
|
13967
15284
|
fontSize: 14,
|
|
13968
|
-
color: "#
|
|
15285
|
+
color: "#fafafa",
|
|
13969
15286
|
maxHeight: 100,
|
|
13970
15287
|
marginRight: 8
|
|
13971
15288
|
},
|
|
13972
15289
|
sendButton: {
|
|
13973
|
-
backgroundColor: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
15332
|
+
color: "#fafafa",
|
|
14016
15333
|
marginBottom: 4
|
|
14017
15334
|
},
|
|
14018
15335
|
composeSubtitle: {
|
|
14019
15336
|
fontSize: 14,
|
|
14020
|
-
color: "#
|
|
15337
|
+
color: "#71717a"
|
|
14021
15338
|
},
|
|
14022
15339
|
composeForm: {
|
|
14023
|
-
backgroundColor: "#
|
|
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: "#
|
|
15347
|
+
backgroundColor: "#18181b",
|
|
14029
15348
|
borderWidth: 1,
|
|
14030
|
-
borderColor: "#
|
|
15349
|
+
borderColor: "#3f3f46",
|
|
14031
15350
|
borderRadius: 8,
|
|
14032
15351
|
paddingHorizontal: 12,
|
|
14033
15352
|
paddingVertical: 10,
|
|
14034
15353
|
fontSize: 15,
|
|
14035
|
-
color: "#
|
|
15354
|
+
color: "#fafafa"
|
|
14036
15355
|
},
|
|
14037
15356
|
composeMessageInput: {
|
|
14038
|
-
backgroundColor: "#
|
|
15357
|
+
backgroundColor: "#18181b",
|
|
14039
15358
|
borderWidth: 1,
|
|
14040
|
-
borderColor: "#
|
|
15359
|
+
borderColor: "#3f3f46",
|
|
14041
15360
|
borderRadius: 8,
|
|
14042
15361
|
paddingHorizontal: 12,
|
|
14043
15362
|
paddingVertical: 10,
|
|
14044
15363
|
fontSize: 15,
|
|
14045
|
-
color: "#
|
|
15364
|
+
color: "#fafafa",
|
|
14046
15365
|
minHeight: 120
|
|
14047
15366
|
},
|
|
14048
15367
|
composeSendButton: {
|
|
14049
|
-
backgroundColor: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
15409
|
+
color: "#fafafa",
|
|
14089
15410
|
marginBottom: 4
|
|
14090
15411
|
},
|
|
14091
15412
|
profileEmail: {
|
|
14092
15413
|
fontSize: 14,
|
|
14093
|
-
color: "#
|
|
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: "#
|
|
15428
|
+
color: "#3B82F6"
|
|
14108
15429
|
},
|
|
14109
15430
|
profileStatLabel: {
|
|
14110
15431
|
fontSize: 12,
|
|
14111
|
-
color: "#
|
|
15432
|
+
color: "#71717a",
|
|
14112
15433
|
marginTop: 2
|
|
14113
15434
|
},
|
|
14114
15435
|
profileStatDivider: {
|
|
14115
15436
|
width: 1,
|
|
14116
15437
|
height: 32,
|
|
14117
|
-
backgroundColor: "#
|
|
15438
|
+
backgroundColor: "#3f3f46"
|
|
14118
15439
|
},
|
|
14119
15440
|
profileInfoSection: {
|
|
14120
|
-
backgroundColor: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
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: "#
|
|
15474
|
+
color: "#60a5fa",
|
|
14152
15475
|
fontWeight: "500"
|
|
14153
15476
|
},
|
|
14154
15477
|
editProfileButton: {
|
|
14155
|
-
backgroundColor: "#
|
|
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: "#
|
|
15499
|
+
color: "#fafafa"
|
|
14177
15500
|
},
|
|
14178
15501
|
cancelText: {
|
|
14179
15502
|
fontSize: 14,
|
|
14180
|
-
color: "#
|
|
15503
|
+
color: "#71717a"
|
|
14181
15504
|
},
|
|
14182
15505
|
profileSection: {
|
|
14183
15506
|
marginBottom: 20
|
|
14184
15507
|
},
|
|
14185
15508
|
profileInput: {
|
|
14186
|
-
backgroundColor: "#
|
|
15509
|
+
backgroundColor: "#27272a",
|
|
14187
15510
|
borderWidth: 1,
|
|
14188
|
-
borderColor: "#
|
|
15511
|
+
borderColor: "#3f3f46",
|
|
14189
15512
|
borderRadius: 10,
|
|
14190
15513
|
paddingHorizontal: 14,
|
|
14191
15514
|
paddingVertical: 12,
|
|
14192
15515
|
fontSize: 15,
|
|
14193
|
-
color: "#
|
|
15516
|
+
color: "#fafafa"
|
|
14194
15517
|
},
|
|
14195
15518
|
profileReadOnly: {
|
|
14196
|
-
backgroundColor: "#
|
|
15519
|
+
backgroundColor: "#27272a",
|
|
14197
15520
|
borderRadius: 10,
|
|
14198
15521
|
padding: 14
|
|
14199
15522
|
},
|
|
14200
15523
|
profileReadOnlyText: {
|
|
14201
15524
|
fontSize: 15,
|
|
14202
|
-
color: "#
|
|
15525
|
+
color: "#a1a1aa"
|
|
14203
15526
|
},
|
|
14204
15527
|
profileReadOnlyHint: {
|
|
14205
15528
|
fontSize: 12,
|
|
14206
|
-
color: "#
|
|
15529
|
+
color: "#52525b",
|
|
14207
15530
|
marginTop: 4
|
|
14208
15531
|
},
|
|
14209
15532
|
profileHint: {
|
|
14210
15533
|
fontSize: 13,
|
|
14211
|
-
color: "#
|
|
15534
|
+
color: "#71717a",
|
|
14212
15535
|
marginBottom: 12
|
|
14213
15536
|
},
|
|
14214
15537
|
emailChip: {
|
|
14215
15538
|
flexDirection: "row",
|
|
14216
15539
|
alignItems: "center",
|
|
14217
|
-
backgroundColor: "#
|
|
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: "#
|
|
15549
|
+
color: "#60a5fa"
|
|
14227
15550
|
},
|
|
14228
15551
|
emailChipRemove: {
|
|
14229
15552
|
fontSize: 14,
|
|
14230
|
-
color: "#
|
|
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: "#
|
|
15563
|
+
backgroundColor: "#27272a",
|
|
14241
15564
|
borderWidth: 1,
|
|
14242
|
-
borderColor: "#
|
|
15565
|
+
borderColor: "#3f3f46",
|
|
14243
15566
|
borderRadius: 10,
|
|
14244
15567
|
paddingHorizontal: 14,
|
|
14245
15568
|
paddingVertical: 10,
|
|
14246
15569
|
fontSize: 14,
|
|
14247
|
-
color: "#
|
|
15570
|
+
color: "#fafafa"
|
|
14248
15571
|
},
|
|
14249
15572
|
addEmailButton: {
|
|
14250
|
-
backgroundColor: "#
|
|
15573
|
+
backgroundColor: "#3B82F6",
|
|
14251
15574
|
paddingHorizontal: 16,
|
|
14252
15575
|
borderRadius: 10,
|
|
14253
15576
|
justifyContent: "center"
|
|
14254
15577
|
},
|
|
14255
15578
|
addEmailButtonDisabled: {
|
|
14256
|
-
backgroundColor: "#
|
|
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: "#
|
|
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: "#
|
|
14278
|
-
borderColor: "#
|
|
15600
|
+
backgroundColor: "#1e3a5f",
|
|
15601
|
+
borderColor: "#3B82F6"
|
|
14279
15602
|
},
|
|
14280
15603
|
platformButtonText: {
|
|
14281
15604
|
fontSize: 13,
|
|
14282
|
-
color: "#
|
|
15605
|
+
color: "#a1a1aa",
|
|
14283
15606
|
fontWeight: "500"
|
|
14284
15607
|
},
|
|
14285
15608
|
platformButtonTextActive: {
|
|
14286
|
-
color: "#
|
|
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: "#
|
|
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: "#
|
|
15642
|
+
borderTopColor: "#27272a",
|
|
14320
15643
|
padding: 12,
|
|
14321
|
-
backgroundColor: "#
|
|
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: "#
|
|
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 {
|