From 6e9eba4b4700f1dd02eee29cc91664e3226a5d63 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 02:45:24 +0000 Subject: [PATCH 1/3] Initial plan From 10aee7303c64053358bd825e090617f750775fa8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 02:49:37 +0000 Subject: [PATCH 2/3] Pass name from report to signup via success page URL params Co-authored-by: timothyfroehlich <5819722+timothyfroehlich@users.noreply.github.com> --- e2e/smoke/public-reporting.spec.ts | 32 ++++++++++++++++++++++++++++++ src/app/(auth)/signup/page.tsx | 21 +++++++++++++++++--- src/app/report/actions.ts | 7 +++++++ src/app/report/success/page.tsx | 21 ++++++++++++++++++-- 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/e2e/smoke/public-reporting.spec.ts b/e2e/smoke/public-reporting.spec.ts index c2066583..474dc69e 100644 --- a/e2e/smoke/public-reporting.spec.ts +++ b/e2e/smoke/public-reporting.spec.ts @@ -79,6 +79,38 @@ test.describe("Public Issue Reporting", () => { ).toBeVisible(); }); + test("should pre-fill name on signup when provided without email", async ({ + page, + }) => { + await page.goto("/report"); + await page.getByTestId("machine-select").selectOption({ index: 1 }); + // Wait for URL refresh (router.push) to prevent race conditions on Mobile Safari + await expect(page).toHaveURL(/machine=/); + + await page + .getByLabel("Issue Title *") + .fill(`${PUBLIC_PREFIX} with Name Only`); + await selectOption(page, "severity-select", "minor"); + + // Provide name but no email + await page.getByLabel("First Name").fill("Jane"); + await page.getByLabel("Last Name").fill("Reporter"); + + await page.getByRole("button", { name: "Submit Issue Report" }).click(); + + // Should redirect to success page with new_pending flag + await expect(page).toHaveURL(/\/report\/success/); + await expect(page.getByText("Want to track your reports?")).toBeVisible(); + + // Click the signup link + await page.getByRole("link", { name: "Join PinPoint" }).click(); + + // Should redirect to signup page with name pre-filled + await expect(page).toHaveURL(/\/signup\?/); + await expect(page.getByLabel(/First Name/i)).toHaveValue("Jane"); + await expect(page.getByLabel(/Last Name/i)).toHaveValue("Reporter"); + }); + test("should allow reporting another issue from success page", async ({ page, }) => { diff --git a/src/app/(auth)/signup/page.tsx b/src/app/(auth)/signup/page.tsx index 6326790a..4223923c 100644 --- a/src/app/(auth)/signup/page.tsx +++ b/src/app/(auth)/signup/page.tsx @@ -19,7 +19,11 @@ import { eq } from "drizzle-orm"; export default async function SignupPage({ searchParams, }: { - searchParams: Promise<{ email?: string }>; + searchParams: Promise<{ + email?: string; + firstName?: string; + lastName?: string; + }>; }): Promise { // Check if already logged in const supabase = await createClient(); @@ -31,7 +35,7 @@ export default async function SignupPage({ redirect("/dashboard"); } - const { email } = await searchParams; + const { email, firstName, lastName } = await searchParams; let initialData = undefined; if (email) { @@ -47,8 +51,19 @@ export default async function SignupPage({ }; } else { // If email is provided but no invited user found, we still pre-fill the email - initialData = { email }; + // Also include firstName and lastName from query params if provided + initialData = { + email, + ...(firstName && { firstName }), + ...(lastName && { lastName }), + }; } + } else if (firstName || lastName) { + // No email but name provided (e.g., from report success page) + initialData = { + ...(firstName && { firstName }), + ...(lastName && { lastName }), + }; } return ( diff --git a/src/app/report/actions.ts b/src/app/report/actions.ts index 151a9f5e..8210ec1d 100644 --- a/src/app/report/actions.ts +++ b/src/app/report/actions.ts @@ -195,6 +195,13 @@ export async function submitPublicIssueAction( // We can use reporterEmail or reporterName to decide if they provided info if ((reporterEmail || reporterName) && !reportedBy) { successParams.set("new_pending", "true"); + // Pass name information to success page for signup pre-fill + if (firstName) { + successParams.set("firstName", firstName); + } + if (lastName) { + successParams.set("lastName", lastName); + } } const successUrl = successParams.toString() diff --git a/src/app/report/success/page.tsx b/src/app/report/success/page.tsx index 3b660f42..b827998f 100644 --- a/src/app/report/success/page.tsx +++ b/src/app/report/success/page.tsx @@ -7,11 +7,28 @@ import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; export default async function ReportSuccessPage({ searchParams, }: { - searchParams: Promise<{ new_pending?: string }>; + searchParams: Promise<{ + new_pending?: string; + firstName?: string; + lastName?: string; + }>; }): Promise { const params = await searchParams; const isNewPending = params.new_pending === "true"; + // Build signup URL with pre-filled name data + const signupParams = new URLSearchParams(); + if (params.firstName) { + signupParams.set("firstName", params.firstName); + } + if (params.lastName) { + signupParams.set("lastName", params.lastName); + } + const signupUrl = + signupParams.toString() !== "" + ? `/signup?${signupParams.toString()}` + : "/signup"; + return (
@@ -50,7 +67,7 @@ export default async function ReportSuccessPage({ size="sm" className="w-full bg-primary text-on-primary" > - Join PinPoint + Join PinPoint
)} From 9f5903dd3a383e80073c0836b33dbee613cbb163 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 02:58:42 +0000 Subject: [PATCH 3/3] Add email forwarding from report to signup via success page Co-authored-by: timothyfroehlich <5819722+timothyfroehlich@users.noreply.github.com> --- e2e/smoke/public-reporting.spec.ts | 37 ++++++++++++++++++++++++++++++ src/app/report/actions.ts | 5 +++- src/app/report/success/page.tsx | 6 ++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/e2e/smoke/public-reporting.spec.ts b/e2e/smoke/public-reporting.spec.ts index 474dc69e..974ebbe6 100644 --- a/e2e/smoke/public-reporting.spec.ts +++ b/e2e/smoke/public-reporting.spec.ts @@ -111,6 +111,43 @@ test.describe("Public Issue Reporting", () => { await expect(page.getByLabel(/Last Name/i)).toHaveValue("Reporter"); }); + test("should pre-fill name and email on signup when both provided", async ({ + page, + }) => { + const timestamp = Date.now(); + const email = `reporter-${timestamp}@example.com`; + + await page.goto("/report"); + await page.getByTestId("machine-select").selectOption({ index: 1 }); + // Wait for URL refresh (router.push) to prevent race conditions on Mobile Safari + await expect(page).toHaveURL(/machine=/); + + await page + .getByLabel("Issue Title *") + .fill(`${PUBLIC_PREFIX} with Name and Email`); + await selectOption(page, "severity-select", "minor"); + + // Provide name and email + await page.getByLabel("First Name").fill("John"); + await page.getByLabel("Last Name").fill("Smith"); + await page.getByLabel("Email Address").fill(email); + + await page.getByRole("button", { name: "Submit Issue Report" }).click(); + + // Should redirect to success page with new_pending flag + await expect(page).toHaveURL(/\/report\/success/); + await expect(page.getByText("Want to track your reports?")).toBeVisible(); + + // Click the signup link + await page.getByRole("link", { name: "Join PinPoint" }).click(); + + // Should redirect to signup page with name and email pre-filled + await expect(page).toHaveURL(/\/signup\?/); + await expect(page.getByLabel(/First Name/i)).toHaveValue("John"); + await expect(page.getByLabel(/Last Name/i)).toHaveValue("Smith"); + await expect(page.getByLabel(/Email/i)).toHaveValue(email); + }); + test("should allow reporting another issue from success page", async ({ page, }) => { diff --git a/src/app/report/actions.ts b/src/app/report/actions.ts index 8210ec1d..eeeefe39 100644 --- a/src/app/report/actions.ts +++ b/src/app/report/actions.ts @@ -195,13 +195,16 @@ export async function submitPublicIssueAction( // We can use reporterEmail or reporterName to decide if they provided info if ((reporterEmail || reporterName) && !reportedBy) { successParams.set("new_pending", "true"); - // Pass name information to success page for signup pre-fill + // Pass name and email information to success page for signup pre-fill if (firstName) { successParams.set("firstName", firstName); } if (lastName) { successParams.set("lastName", lastName); } + if (reporterEmail) { + successParams.set("email", reporterEmail); + } } const successUrl = successParams.toString() diff --git a/src/app/report/success/page.tsx b/src/app/report/success/page.tsx index b827998f..8b9fd32e 100644 --- a/src/app/report/success/page.tsx +++ b/src/app/report/success/page.tsx @@ -11,12 +11,13 @@ export default async function ReportSuccessPage({ new_pending?: string; firstName?: string; lastName?: string; + email?: string; }>; }): Promise { const params = await searchParams; const isNewPending = params.new_pending === "true"; - // Build signup URL with pre-filled name data + // Build signup URL with pre-filled name and email data const signupParams = new URLSearchParams(); if (params.firstName) { signupParams.set("firstName", params.firstName); @@ -24,6 +25,9 @@ export default async function ReportSuccessPage({ if (params.lastName) { signupParams.set("lastName", params.lastName); } + if (params.email) { + signupParams.set("email", params.email); + } const signupUrl = signupParams.toString() !== "" ? `/signup?${signupParams.toString()}`