Skip to content

Commit 23ceefc

Browse files
committed
Submit feedback to Plain when an org signs up
1 parent 7ce56fa commit 23ceefc

File tree

1 file changed

+64
-2
lines changed
  • apps/webapp/app/routes/_app.orgs.new

1 file changed

+64
-2
lines changed

apps/webapp/app/routes/_app.orgs.new/route.tsx

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@ import { TextArea } from "~/components/primitives/TextArea";
2121
import { useFeatures } from "~/hooks/useFeatures";
2222
import { createOrganization } from "~/models/organization.server";
2323
import { NewOrganizationPresenter } from "~/presenters/NewOrganizationPresenter.server";
24-
import { requireUserId } from "~/services/session.server";
24+
import { requireUser, requireUserId } from "~/services/session.server";
2525
import { organizationPath, rootPath } from "~/utils/pathBuilder";
26+
import { PlainClient, uiComponent } from "@team-plain/typescript-sdk";
27+
import { env } from "~/env.server";
2628

2729
const schema = z.object({
2830
orgName: z.string().min(3).max(50),
2931
companySize: z.string().optional(),
32+
whyUseUs: z.string().optional(),
3033
});
3134

3235
export const loader = async ({ request }: LoaderFunctionArgs) => {
@@ -41,7 +44,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
4144

4245
export const action: ActionFunction = async ({ request }) => {
4346
const userId = await requireUserId(request);
44-
47+
const user = await requireUser(request);
4548
const formData = await request.formData();
4649
const submission = parse(formData, { schema });
4750

@@ -56,6 +59,65 @@ export const action: ActionFunction = async ({ request }) => {
5659
companySize: submission.value.companySize ?? null,
5760
});
5861

62+
if (env.PLAIN_API_KEY) {
63+
const client = new PlainClient({
64+
apiKey: env.PLAIN_API_KEY,
65+
});
66+
67+
const whyUseUs = formData.get("whyUseUs");
68+
69+
const upsertCustomerRes = await client.upsertCustomer({
70+
identifier: {
71+
emailAddress: user.email,
72+
},
73+
onCreate: {
74+
externalId: userId,
75+
fullName: submission.value.orgName,
76+
email: {
77+
email: user.email,
78+
isVerified: true,
79+
},
80+
},
81+
onUpdate: {
82+
externalId: { value: userId },
83+
fullName: { value: submission.value.orgName },
84+
email: {
85+
email: user.email,
86+
isVerified: true,
87+
},
88+
},
89+
});
90+
91+
if (upsertCustomerRes.error) {
92+
console.error("Failed to upsert customer in Plain", upsertCustomerRes.error);
93+
} else if (whyUseUs) {
94+
const createThreadRes = await client.createThread({
95+
customerIdentifier: {
96+
customerId: upsertCustomerRes.data.customer.id,
97+
},
98+
title: "New org feedback",
99+
components: [
100+
uiComponent.text({
101+
text: `${submission.value.orgName} just created a new organization.`,
102+
}),
103+
uiComponent.divider({ spacingSize: "M" }),
104+
uiComponent.text({
105+
size: "L",
106+
color: "NORMAL",
107+
text: "What problem are they trying to solve?",
108+
}),
109+
uiComponent.text({
110+
text: whyUseUs.toString(),
111+
}),
112+
],
113+
});
114+
115+
if (createThreadRes.error) {
116+
console.error("Failed to create thread in Plain", createThreadRes.error);
117+
}
118+
}
119+
}
120+
59121
return redirect(organizationPath(organization));
60122
} catch (error: any) {
61123
return json({ errors: { body: error.message } }, { status: 400 });

0 commit comments

Comments
 (0)