Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/prnote.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: PRNote

on:
pull_request:
types: [opened]

permissions:
contents: read
pull-requests: write

jobs:
generate-pr-note:
runs-on: ubuntu-latest
steps:
- name: Generate PR title and description
uses: prnote/prnote-action@v0.1.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
10 changes: 10 additions & 0 deletions src/components/admin/FeedbackFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useSearchParams } from "react-router-dom";
import { STRIPE_CONNECT_EARLY_ACCESS_REPORT_ID } from "@/lib/feedbackFilters";

export function FeedbackFilters() {
const [searchParams, setSearchParams] = useSearchParams();
Expand All @@ -17,6 +18,15 @@ export function FeedbackFilters() {

return (
<div className="card flex flex-wrap gap-3">
<select
className="input w-auto py-2"
value={searchParams.get("report_id") ?? "all"}
onChange={(event) => updateFilter("report_id", event.target.value)}
>
<option value="all">All sources</option>
<option value={STRIPE_CONNECT_EARLY_ACCESS_REPORT_ID}>Stripe Connect early access</option>
</select>

<select
className="input w-auto py-2"
value={searchParams.get("believability") ?? "all"}
Expand Down
9 changes: 8 additions & 1 deletion src/components/admin/FeedbackTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Link } from "react-router-dom";
import { formatFeedbackReportId } from "@/lib/feedbackFilters";
import type { FeedbackSubmission } from "@/types/feedback";
import { resolvedBelievability, resolvedRecommendationIntent, resolvedStripeIntent } from "@/types/feedback";

Expand Down Expand Up @@ -30,10 +31,12 @@ export function FeedbackTable({ feedback }: { feedback: FeedbackSubmission[] })

return (
<div className="overflow-x-auto rounded-lg border border-[var(--border)] bg-white">
<table className="w-full min-w-[1200px] text-left text-sm">
<table className="w-full min-w-[1400px] text-left text-sm">
<thead className="border-b border-[var(--border)] bg-[var(--surface-muted)] text-xs uppercase text-[var(--ink-muted)]">
<tr>
<th className="px-4 py-3">Created</th>
<th className="px-4 py-3">Email</th>
<th className="px-4 py-3">Report ID</th>
<th className="px-4 py-3">Visitor</th>
<th className="px-4 py-3">Report type</th>
<th className="px-4 py-3">Data path</th>
Expand All @@ -51,6 +54,10 @@ export function FeedbackTable({ feedback }: { feedback: FeedbackSubmission[] })
{feedback.map((item) => (
<tr key={item.id} className="border-b border-[var(--border)] last:border-b-0">
<td className="px-4 py-3 text-[var(--ink-muted)]">{formatDate(item.created_at)}</td>
<td className="px-4 py-3">{formatValue(item.founder_email)}</td>
<td className="max-w-xs truncate px-4 py-3" title={item.report_id}>
{formatFeedbackReportId(item)}
</td>
<td className="px-4 py-3 font-mono text-xs">{shortenId(item.visitor_id)}</td>
<td className="px-4 py-3">{formatValue(item.report_type)}</td>
<td className="px-4 py-3">{formatValue(item.stripe_data_path)}</td>
Expand Down
19 changes: 19 additions & 0 deletions src/lib/feedbackFilters.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
import type { FeedbackSubmission } from "@/types/feedback";
import { resolvedBelievability, resolvedRecommendationIntent, resolvedStripeIntent } from "@/types/feedback";

export const STRIPE_CONNECT_EARLY_ACCESS_REPORT_ID = "stripe_connect_early_access";

export type FeedbackFilterParams = {
believability?: string;
recommendation_intent?: string;
stripe_connection_intent?: string;
report_id?: string;
};

export function isStripeConnectEarlyAccess(item: FeedbackSubmission): boolean {
return item.report_id === STRIPE_CONNECT_EARLY_ACCESS_REPORT_ID;
}

export function formatFeedbackReportId(item: FeedbackSubmission): string {
if (isStripeConnectEarlyAccess(item)) {
return "Stripe Connect early access";
}

return item.report_id;
}

export function applyFilters(
feedback: FeedbackSubmission[],
searchParams: FeedbackFilterParams,
): FeedbackSubmission[] {
return feedback.filter((item) => {
if (searchParams.report_id && item.report_id !== searchParams.report_id) {
return false;
}

if (searchParams.believability && resolvedBelievability(item) !== searchParams.believability) {
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion src/pages/FeedbackInboxPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function FeedbackInboxPage() {

const filters = useMemo(
() => ({
report_id: searchParams.get("report_id") ?? undefined,
believability: searchParams.get("believability") ?? undefined,
recommendation_intent: searchParams.get("recommendation_intent") ?? undefined,
stripe_connection_intent: searchParams.get("stripe_connection_intent") ?? undefined,
Expand Down Expand Up @@ -76,7 +77,7 @@ export function FeedbackInboxPage() {
<p className="text-sm text-[var(--ink-muted)]">Validation</p>
<h2 className="text-2xl font-semibold text-[var(--ink)]">Feedback Inbox</h2>
<p className="mt-2 text-sm text-[var(--ink-muted)]">
Review founder feedback from sample and generated reports.
Review founder feedback from sample and generated reports, plus Stripe Connect early access signups.
</p>
</div>

Expand Down
Loading