Skip to content

Commit d8c1872

Browse files
committed
Handle sending feedback to Slack using Plain
1 parent ac81a9c commit d8c1872

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { ActionFunctionArgs, json } from "@remix-run/server-runtime";
2+
import { PlainClient, uiComponent } from "@team-plain/typescript-sdk";
3+
import { inspect } from "util";
4+
import { env } from "~/env.server";
5+
import { redirectWithSuccessMessage } from "~/models/message.server";
6+
import { requireUser } from "~/services/session.server";
7+
8+
let client: PlainClient | undefined;
9+
10+
export async function action({ request }: ActionFunctionArgs) {
11+
const user = await requireUser(request);
12+
13+
const formData = await request.formData();
14+
const path = formData.get("path") as string;
15+
const reasons = formData.getAll("reason") as string[];
16+
const message = formData.get("message") as string;
17+
18+
try {
19+
if (!env.PLAIN_API_KEY) {
20+
console.error("PLAIN_API_KEY is not set");
21+
return json({ error: "PLAIN_API_KEY is not set" }, { status: 500 });
22+
}
23+
24+
client = new PlainClient({
25+
apiKey: env.PLAIN_API_KEY,
26+
});
27+
28+
const upsertCustomerRes = await client.upsertCustomer({
29+
identifier: {
30+
emailAddress: user.email,
31+
},
32+
onCreate: {
33+
externalId: user.id,
34+
fullName: user.name ?? "",
35+
email: {
36+
email: user.email,
37+
isVerified: true,
38+
},
39+
},
40+
onUpdate: {
41+
externalId: { value: user.id },
42+
fullName: { value: user.name ?? "" },
43+
email: {
44+
email: user.email,
45+
isVerified: true,
46+
},
47+
},
48+
});
49+
50+
if (upsertCustomerRes.error) {
51+
console.error(
52+
inspect(upsertCustomerRes.error, {
53+
showHidden: false,
54+
depth: null,
55+
colors: true,
56+
})
57+
);
58+
return json({ error: upsertCustomerRes.error.message }, { status: 400 });
59+
}
60+
61+
// Only create a thread if there are reasons or a message
62+
if (reasons.length > 0 || message) {
63+
const createThreadRes = await client.createThread({
64+
customerIdentifier: {
65+
customerId: upsertCustomerRes.data.customer.id,
66+
},
67+
title: "Plan cancelation feedback",
68+
components: [
69+
uiComponent.text({
70+
text: `${user.name} (${user.email}) just canceled their plan.`,
71+
}),
72+
uiComponent.divider({ spacingSize: "M" }),
73+
...(reasons.length > 0
74+
? [
75+
uiComponent.spacer({ size: "L" }),
76+
uiComponent.text({
77+
size: "S",
78+
color: "ERROR",
79+
text: "Reasons:",
80+
}),
81+
uiComponent.text({
82+
text: reasons.join(", "),
83+
}),
84+
]
85+
: []),
86+
...(message
87+
? [
88+
uiComponent.spacer({ size: "L" }),
89+
uiComponent.text({
90+
size: "S",
91+
color: "ERROR",
92+
text: "Comment:",
93+
}),
94+
uiComponent.text({
95+
text: message,
96+
}),
97+
]
98+
: []),
99+
],
100+
});
101+
102+
if (createThreadRes.error) {
103+
console.error(
104+
inspect(createThreadRes.error, {
105+
showHidden: false,
106+
depth: null,
107+
colors: true,
108+
})
109+
);
110+
return json({ error: createThreadRes.error.message }, { status: 400 });
111+
}
112+
}
113+
114+
return redirectWithSuccessMessage(path, request, "Your plan has been successfully canceled.");
115+
} catch (e) {
116+
return json({ error: "An unexpected error occurred" }, { status: 500 });
117+
}
118+
}

0 commit comments

Comments
 (0)