chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import { parseWithZod } from "@conform-to/zod";
|
||||
import { type ActionFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { type PlainClient, uiComponent } from "@team-plain/typescript-sdk";
|
||||
import { z } from "zod";
|
||||
import { redirectWithSuccessMessage } from "~/models/message.server";
|
||||
import { requireUser } from "~/services/session.server";
|
||||
import { sendToPlain } from "~/utils/plain.server";
|
||||
|
||||
let _client: PlainClient | undefined;
|
||||
|
||||
export const feedbackTypes = {
|
||||
bug: {
|
||||
label: "Bug report",
|
||||
labelTypeId: "lt_01HB920BTPFS36KH1JT9C36YVY",
|
||||
threadTitle: "Web app: Bug report",
|
||||
},
|
||||
feature: {
|
||||
label: "Feature request",
|
||||
labelTypeId: "lt_01HB920BV8CJGYXVE15WWN6P07",
|
||||
threadTitle: "Web app: Feature request",
|
||||
},
|
||||
help: {
|
||||
label: "Help me out",
|
||||
labelTypeId: "lt_01KTVCAPZY5ZJ0SS4ACMXWYYT3",
|
||||
threadTitle: "Web app: Help me out",
|
||||
},
|
||||
enterprise: {
|
||||
label: "Enterprise enquiry",
|
||||
labelTypeId: "lt_01K7PF5EV2877EH4SZYB667FW4",
|
||||
threadTitle: "Web app: Enterprise enquiry",
|
||||
},
|
||||
feedback: {
|
||||
label: "General feedback",
|
||||
labelTypeId: "lt_01HB920BSRZ3RA1ETHBVEB5ST2",
|
||||
threadTitle: "Web app: General feedback",
|
||||
},
|
||||
concurrency: {
|
||||
label: "Increase my concurrency",
|
||||
labelTypeId: "lt_01KTVCCY2PDE5V6WV2PQ8N85K2",
|
||||
threadTitle: "Web app: Increase my concurrency",
|
||||
},
|
||||
region: {
|
||||
label: "Suggest a new region",
|
||||
labelTypeId: "lt_01KTVCDPYYBW6KS9H5V8MTQ0GG",
|
||||
threadTitle: "Web app: Suggest a new region",
|
||||
},
|
||||
hipaa: {
|
||||
label: "HIPAA BAA request",
|
||||
labelTypeId: "lt_01KS54WBRYKE6DY369KPK2SS4W",
|
||||
threadTitle: "Web app: HIPAA BAA request",
|
||||
},
|
||||
} as const satisfies Record<string, { label: string; labelTypeId?: string; threadTitle: string }>;
|
||||
|
||||
export type FeedbackType = keyof typeof feedbackTypes;
|
||||
|
||||
const feedbackTypeLiterals = Object.keys(feedbackTypes).map((key) => z.literal(key));
|
||||
|
||||
const feedbackType = z.union(
|
||||
[feedbackTypeLiterals[0], feedbackTypeLiterals[1], ...feedbackTypeLiterals.slice(2)],
|
||||
{
|
||||
required_error: "Must be either 'bug' or 'feature'",
|
||||
invalid_type_error: "Must be either 'bug' or 'feature'",
|
||||
}
|
||||
);
|
||||
|
||||
export const schema = z.object({
|
||||
path: z.string(),
|
||||
feedbackType,
|
||||
message: z.string().min(10, "Must be at least 10 characters"),
|
||||
});
|
||||
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
const user = await requireUser(request);
|
||||
|
||||
const formData = await request.formData();
|
||||
const submission = parseWithZod(formData, { schema });
|
||||
|
||||
if (submission.status !== "success") {
|
||||
return json(submission.reply());
|
||||
}
|
||||
|
||||
const inquiry = feedbackTypes[submission.value.feedbackType as FeedbackType];
|
||||
try {
|
||||
await sendToPlain({
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
name: user.name ?? user.displayName ?? user.email,
|
||||
title: inquiry.threadTitle,
|
||||
labelTypeIds: inquiry.labelTypeId ? [inquiry.labelTypeId] : undefined,
|
||||
components: [
|
||||
uiComponent.text({
|
||||
text: `New ${inquiry.label} reported by ${user.name} (${user.email})`,
|
||||
}),
|
||||
uiComponent.divider({ spacingSize: "M" }),
|
||||
uiComponent.text({
|
||||
size: "S",
|
||||
color: "MUTED",
|
||||
text: "Page",
|
||||
}),
|
||||
uiComponent.text({
|
||||
text: submission.value.path,
|
||||
}),
|
||||
uiComponent.spacer({ size: "M" }),
|
||||
uiComponent.text({
|
||||
size: "S",
|
||||
color: "MUTED",
|
||||
text: "Message",
|
||||
}),
|
||||
uiComponent.text({
|
||||
text: submission.value.message,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
return redirectWithSuccessMessage(
|
||||
submission.value.path,
|
||||
request,
|
||||
"Thanks for your feedback! We'll get back to you soon."
|
||||
);
|
||||
} catch (e) {
|
||||
return json(
|
||||
submission.reply({
|
||||
fieldErrors: { message: [e instanceof Error ? e.message : "Unknown error"] },
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user