Skip to content

Commit d637fed

Browse files
committed
feat(webapp): add hipaa contact form type sharing marketing plain labels
1 parent 7b4443a commit d637fed

3 files changed

Lines changed: 86 additions & 23 deletions

File tree

apps/webapp/app/components/Feedback.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { conform, useForm } from "@conform-to/react";
22
import { parse } from "@conform-to/zod";
33
import { InformationCircleIcon, ArrowUpCircleIcon } from "@heroicons/react/20/solid";
4-
import { EnvelopeIcon } from "@heroicons/react/24/solid";
4+
import { EnvelopeIcon, ShieldCheckIcon } from "@heroicons/react/24/solid";
55
import { Form, useActionData, useLocation, useNavigation, useSearchParams } from "@remix-run/react";
66
import { type ReactNode, useEffect, useState } from "react";
7-
import { type FeedbackType, feedbackTypeLabel, schema } from "~/routes/resources.feedback";
7+
import { type FeedbackType, feedbackTypes, schema } from "~/routes/resources.feedback";
88
import { Button } from "./primitives/Buttons";
99
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from "./primitives/Dialog";
1010
import { Fieldset } from "./primitives/Fieldset";
@@ -84,9 +84,12 @@ export function Feedback({ button, defaultValue = "bug", onOpenChange }: Feedbac
8484
How can we help? We read every message and will respond as quickly as we can.
8585
</Paragraph>
8686
</div>
87-
{!(type === "feature" || type === "help" || type === "concurrency") && (
88-
<hr className="border-grid-dimmed" />
89-
)}
87+
{!(
88+
type === "feature" ||
89+
type === "help" ||
90+
type === "concurrency" ||
91+
type === "hipaa"
92+
) && <hr className="border-grid-dimmed" />}
9093
<Form method="post" action="/resources/feedback" {...form.props} className="w-full">
9194
<Fieldset className="max-w-full gap-y-3">
9295
<input value={location.pathname} {...conform.input(path, { type: "hidden" })} />
@@ -132,19 +135,33 @@ export function Feedback({ button, defaultValue = "bug", onOpenChange }: Feedbac
132135
</Paragraph>
133136
</InfoPanel>
134137
)}
138+
{type === "hipaa" && (
139+
<InfoPanel
140+
icon={ShieldCheckIcon}
141+
iconClassName="text-green-500"
142+
panelClassName="w-full mb-2"
143+
>
144+
<Paragraph variant="small">
145+
We offer a signed Business Associate Agreement (BAA) as a paid add-on on Pro
146+
and Enterprise plans. To help us get back to you quickly, please include your
147+
company name, expected go-live date, and a brief description of the PHI
148+
workload you plan to run.
149+
</Paragraph>
150+
</InfoPanel>
151+
)}
135152
<Select
136153
{...conform.select(feedbackType)}
137154
variant="tertiary/medium"
138155
value={type}
139156
defaultValue={type}
140157
setValue={(v) => setType(v as FeedbackType)}
141158
placeholder="Select type"
142-
text={(value) => feedbackTypeLabel[value as FeedbackType]}
159+
text={(value) => feedbackTypes[value as FeedbackType].label}
143160
dropdownIcon
144161
>
145-
{Object.entries(feedbackTypeLabel).map(([name, title]) => (
162+
{Object.entries(feedbackTypes).map(([name, { label }]) => (
146163
<SelectItem key={name} value={name}>
147-
{title}
164+
{label}
148165
</SelectItem>
149166
))}
150167
</Select>

apps/webapp/app/routes/resources.feedback.ts

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,55 @@ import { sendToPlain } from "~/utils/plain.server";
88

99
let client: PlainClient | undefined;
1010

11-
export const feedbackTypeLabel = {
12-
bug: "Bug report",
13-
feature: "Feature request",
14-
help: "Help me out",
15-
enterprise: "Enterprise enquiry",
16-
feedback: "General feedback",
17-
concurrency: "Increase my concurrency",
18-
region: "Suggest a new region",
19-
};
11+
export const feedbackTypes = {
12+
bug: {
13+
label: "Bug report",
14+
labelTypeId: "lt_01HB920BTPFS36KH1JT9C36YVY",
15+
threadTitle: "Contact form: Bug report",
16+
},
17+
feature: {
18+
label: "Feature request",
19+
labelTypeId: "lt_01HB920BV8CJGYXVE15WWN6P07",
20+
threadTitle: "Contact form: Feature request",
21+
},
22+
help: {
23+
label: "Help me out",
24+
labelTypeId: undefined,
25+
threadTitle: "Contact form: Help me out",
26+
},
27+
enterprise: {
28+
label: "Enterprise enquiry",
29+
labelTypeId: "lt_01K7PF5EV2877EH4SZYB667FW4",
30+
threadTitle: "Contact form: Enterprise enquiry",
31+
},
32+
feedback: {
33+
label: "General feedback",
34+
labelTypeId: "lt_01HB920BT61HB7T776BCK4GC7X",
35+
threadTitle: "Contact form: General feedback",
36+
},
37+
concurrency: {
38+
label: "Increase my concurrency",
39+
labelTypeId: undefined,
40+
threadTitle: "Contact form: Increase my concurrency",
41+
},
42+
region: {
43+
label: "Suggest a new region",
44+
labelTypeId: undefined,
45+
threadTitle: "Contact form: Suggest a new region",
46+
},
47+
hipaa: {
48+
label: "HIPAA BAA request",
49+
labelTypeId: "lt_01KS54WBRYKE6DY369KPK2SS4W",
50+
threadTitle: "Contact form: HIPAA BAA request",
51+
},
52+
} as const satisfies Record<
53+
string,
54+
{ label: string; labelTypeId?: string; threadTitle: string }
55+
>;
2056

21-
export type FeedbackType = keyof typeof feedbackTypeLabel;
57+
export type FeedbackType = keyof typeof feedbackTypes;
2258

23-
const feedbackTypeLiterals = Object.keys(feedbackTypeLabel).map((key) => z.literal(key));
59+
const feedbackTypeLiterals = Object.keys(feedbackTypes).map((key) => z.literal(key));
2460

2561
const feedbackType = z.union(
2662
[feedbackTypeLiterals[0], feedbackTypeLiterals[1], ...feedbackTypeLiterals.slice(2)],
@@ -46,16 +82,17 @@ export async function action({ request }: ActionFunctionArgs) {
4682
return json(submission);
4783
}
4884

49-
const title = feedbackTypeLabel[submission.value.feedbackType as FeedbackType];
85+
const inquiry = feedbackTypes[submission.value.feedbackType as FeedbackType];
5086
try {
5187
await sendToPlain({
5288
userId: user.id,
5389
email: user.email,
5490
name: user.name ?? user.displayName ?? user.email,
55-
title,
91+
title: inquiry.threadTitle,
92+
labelTypeIds: inquiry.labelTypeId ? [inquiry.labelTypeId] : undefined,
5693
components: [
5794
uiComponent.text({
58-
text: `New ${title} reported by ${user.name} (${user.email})`,
95+
text: `New ${inquiry.label} reported by ${user.name} (${user.email})`,
5996
}),
6097
uiComponent.divider({ spacingSize: "M" }),
6198
uiComponent.text({

apps/webapp/app/utils/plain.server.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,17 @@ type Input = {
77
name: string;
88
title: string;
99
components: ReturnType<typeof uiComponent.text>[];
10+
labelTypeIds?: string[];
1011
};
1112

12-
export async function sendToPlain({ userId, email, name, title, components }: Input) {
13+
export async function sendToPlain({
14+
userId,
15+
email,
16+
name,
17+
title,
18+
components,
19+
labelTypeIds,
20+
}: Input) {
1321
if (!env.PLAIN_API_KEY) {
1422
return;
1523
}
@@ -51,6 +59,7 @@ export async function sendToPlain({ userId, email, name, title, components }: In
5159
},
5260
title: title,
5361
components: components,
62+
labelTypeIds,
5463
});
5564

5665
if (createThreadRes.error) {

0 commit comments

Comments
 (0)