Improved the feedback form

This commit is contained in:
Matt Aitken
2023-06-21 10:32:58 +01:00
parent 2cf253a914
commit 90ae06df2a
3 changed files with 77 additions and 18 deletions
+9 -6
View File
@@ -8,7 +8,7 @@ import {
useNavigation,
} from "@remix-run/react";
import { useState } from "react";
import { schema } from "~/routes/resources.feedback";
import { feedbackTypeLabel, schema } from "~/routes/resources.feedback";
import { Button } from "./primitives/Buttons";
import { Fieldset } from "./primitives/Fieldset";
import { FormButtons } from "./primitives/FormButtons";
@@ -67,7 +67,7 @@ export function Feedback() {
Send us feedback
</Button>
</SheetTrigger>
<SheetContent>
<SheetContent size="sm">
<SheetHeader className="justify-between">Give us feedback</SheetHeader>
<SheetBody>
<Paragraph variant="small" className="mb-4">
@@ -82,14 +82,16 @@ export function Feedback() {
<InputGroup>
<Label>What kind of feedback do you have?</Label>
<SelectGroup>
<Select {...conform.input(feedbackType)} defaultValue="bug">
<Select {...conform.input(feedbackType)} defaultValue={"bug"}>
<SelectTrigger size="medium" width="full">
<SelectValue placeholder="Type" />
</SelectTrigger>
<SelectContent>
<SelectItem value="bug">Bug report</SelectItem>
<SelectItem value="feature">Feature request</SelectItem>
<SelectItem value="help">Help me out</SelectItem>
{Object.entries(feedbackTypeLabel).map(([key, value]) => (
<SelectItem key={key} value={key}>
{value}
</SelectItem>
))}
</SelectContent>
</Select>
</SelectGroup>
@@ -104,6 +106,7 @@ export function Feedback() {
</InputGroup>
<FormError>{form.error}</FormError>
<FormButtons
className="max-w-md"
confirmButton={
<Button type="submit" variant="primary/medium">
Send
@@ -1,12 +1,16 @@
import { cn } from "~/utils/cn";
export function FormButtons({
cancelButton,
confirmButton,
className,
}: {
cancelButton?: React.ReactNode;
confirmButton: React.ReactNode;
className?: string;
}) {
return (
<div className="flex w-full items-center justify-between">
<div className={cn("flex w-full items-center justify-between", className)}>
{cancelButton ? cancelButton : <div />} {confirmButton}
</div>
);
+63 -11
View File
@@ -1,8 +1,13 @@
import { parse } from "@conform-to/zod";
import { ActionArgs, json } from "@remix-run/server-runtime";
import { PlainClient } from "@team-plain/typescript-sdk";
import {
ComponentDividerSpacingSize,
ComponentSpacerSize,
ComponentTextColor,
ComponentTextSize,
PlainClient,
} from "@team-plain/typescript-sdk";
import { inspect } from "util";
import { s } from "vitest/dist/index-6e18a03a";
import { z } from "zod";
import { env } from "~/env.server";
import { redirectWithSuccessMessage } from "~/models/message.server";
@@ -10,20 +15,31 @@ import { requireUser } from "~/services/session.server";
let client: PlainClient | undefined;
export const feedbackTypeLabel = {
bug: "Bug report",
feature: "Feature request",
help: "Help me out",
integration: "Request an integration",
};
type FeedbackType = keyof typeof feedbackTypeLabel;
const feedbackTypeLiterals = Object.keys(feedbackTypeLabel).map((key) =>
z.literal(key)
);
const feedbackType = z.union(
[z.literal("bug"), z.literal("feature"), z.literal("help")],
[
feedbackTypeLiterals[0],
feedbackTypeLiterals[1],
...feedbackTypeLiterals.slice(2),
],
{
required_error: "Must be either 'bug' or 'feature'",
invalid_type_error: "Must be either 'bug' or 'feature'",
}
);
const feedbackTypeLabel = {
bug: "Bug",
feature: "Feature request",
help: "Help",
};
export const schema = z.object({
path: z.string(),
feedbackType,
@@ -77,10 +93,46 @@ export async function action({ request }: ActionArgs) {
return json(submission);
}
const title =
feedbackTypeLabel[submission.value.feedbackType as FeedbackType];
const upsertTimelineEntryRes = await client.upsertCustomTimelineEntry({
customerId: upsertCustomerRes.data.customer.id,
title: feedbackTypeLabel[submission.value.feedbackType],
title,
components: [
{
componentText: {
text: `New ${title} reported by ${user.name} (${user.email})`,
},
},
{
componentDivider: {
dividerSpacingSize: ComponentDividerSpacingSize.M,
},
},
{
componentText: {
textSize: ComponentTextSize.S,
textColor: ComponentTextColor.Muted,
text: "Page",
},
},
{
componentText: {
text: submission.value.path,
},
},
{
componentSpacer: {
spacerSize: ComponentSpacerSize.M,
},
},
{
componentText: {
textSize: ComponentTextSize.S,
textColor: ComponentTextColor.Muted,
text: "Message",
},
},
{
componentText: {
text: submission.value.message,
@@ -105,7 +157,7 @@ export async function action({ request }: ActionArgs) {
return redirectWithSuccessMessage(
submission.value.path,
request,
"Feedback submitted"
"Thanks for your feedback! We'll get back to you soon."
);
} catch (e) {
return json(e, { status: 400 });