From 303765c21bbfeeb15fb53fc5af540a8e0341e026 Mon Sep 17 00:00:00 2001 From: AmoabaKelvin Date: Thu, 18 Jul 2024 09:50:08 +0000 Subject: [PATCH 1/2] feat: allow users to change the default new submission email recipient --- .../app/(main)/form/[id]/form-settings.tsx | 121 +++- apps/web/src/app/(main)/form/[id]/page.tsx | 26 +- apps/web/src/app/api/s/[id]/route.ts | 17 +- packages/api/routers/form.ts | 16 +- packages/auth/lucia.ts | 15 +- packages/db/drizzle/0001_military_rictor.sql | 1 + packages/db/drizzle/meta/0001_snapshot.json | 548 ++++++++++++++++++ packages/db/drizzle/meta/_journal.json | 7 + packages/db/schema/forms.ts | 7 +- 9 files changed, 701 insertions(+), 57 deletions(-) create mode 100644 packages/db/drizzle/0001_military_rictor.sql create mode 100644 packages/db/drizzle/meta/0001_snapshot.json diff --git a/apps/web/src/app/(main)/form/[id]/form-settings.tsx b/apps/web/src/app/(main)/form/[id]/form-settings.tsx index e4cd929..3945142 100644 --- a/apps/web/src/app/(main)/form/[id]/form-settings.tsx +++ b/apps/web/src/app/(main)/form/[id]/form-settings.tsx @@ -1,15 +1,8 @@ 'use client'; -import { useRouter } from 'next/navigation'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { BellRing, ExternalLink, FolderPen, FolderX } from 'lucide-react'; -import { useForm } from 'react-hook-form'; -import { toast } from 'sonner'; -import { z } from 'zod'; - -import { type RouterOutputs } from '@formbase/api'; -import { Button } from '@formbase/ui/primitives/button'; +import { RouterOutputs } from "@formbase/api"; +import { UserInstance } from "@formbase/auth"; +import { Button } from "@formbase/ui/primitives/button"; import { Form, FormControl, @@ -17,15 +10,21 @@ import { FormField, FormItem, FormLabel, -} from '@formbase/ui/primitives/form'; -import { Input } from '@formbase/ui/primitives/input'; -import { Label } from '@formbase/ui/primitives/label'; -import { Switch } from '@formbase/ui/primitives/switch'; - -import { api } from '~/lib/trpc/react'; - -import { revalidateDashboard } from '../../_actions/revalidateDashboard'; -import { DeleteFormDialog } from './delete-form-dialog'; +} from "@formbase/ui/primitives/form"; +import { Input } from "@formbase/ui/primitives/input"; +import { Label } from "@formbase/ui/primitives/label"; +import { Switch } from "@formbase/ui/primitives/switch"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { BellRing, ExternalLink, FolderPen, FolderX } from "lucide-react"; +import { useRouter } from "next/navigation"; +import { useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; + +import { api } from "~/lib/trpc/react"; + +import { revalidateDashboard } from "../../_actions/revalidateDashboard"; +import { DeleteFormDialog } from "./delete-form-dialog"; const formNameSchema = z.object({ name: z.string().min(1).optional(), @@ -47,17 +46,24 @@ const enableNotificationsSchema = z.object({ enableNotifications: z.boolean().default(true).optional(), }); +const defaultSubmissionEmailSchema = z.object({ + defaultSubmissionEmail: z.string().email().optional(), +}); + type FormNameSchema = z.infer; type EnableFormSubmissionsSchema = z.infer; type _EnableSubmissionsRetentionSchema = z.infer; type EnableFormNotificationsSchema = z.infer; type FormReturnUrlSchema = z.infer; +type DefaultSubmissionEmailSchema = z.infer; + type FormSettingsProps = { form: RouterOutputs['form']['get']; + user: UserInstance | null; }; -export function FormSettings({ form }: FormSettingsProps) { +export function FormSettings({ form, user }: FormSettingsProps) { const router = useRouter(); if (!form) { @@ -85,6 +91,14 @@ export function FormSettings({ form }: FormSettingsProps) { enableNotifications={form.enableEmailNotifications} /> + {/* only show the if the user has enabled email notifications */} + {form.enableEmailNotifications && ( + + )} +
@@ -247,6 +261,73 @@ const ReturnUrlForm = ({ ); }; +const FormDefaultSubmissionEmailRecipient = ({ formId, email }: { formId: string; email: string }) => { + const router = useRouter(); + + const formDefaultSubmissionEmail = useForm({ + resolver: zodResolver(defaultSubmissionEmailSchema), + defaultValues: { + defaultSubmissionEmail: email, + }, + }); + + const { mutateAsync: updateFormDefaultSubmissionEmail, isPending: isUpdatingFormDefaultSubmissionEmail } = + api.form.update.useMutation(); + + async function handleFormDefaultSubmissionEmailSubmit(data: DefaultSubmissionEmailSchema) { + try { + await updateFormDefaultSubmissionEmail({ + id: formId, + defaultSubmissionEmail: data.defaultSubmissionEmail, + }); + + toast('Your form default submission email has been updated', { + icon: , + }); + + router.refresh(); + } catch { + toast('Failed to update form', { + description: 'Please try again later', + icon: , + }); + } + } + + return ( +
+ + ( + +
+ + Default Submission Email + + This is the email address that submission emails will be sent to +
+ +
+ + +
+
+
+ )} + /> + + + ); +}; + const EnableFormSubmissions = ({ formId, enableSubmissions, diff --git a/apps/web/src/app/(main)/form/[id]/page.tsx b/apps/web/src/app/(main)/form/[id]/page.tsx index 9f15195..b7e870c 100644 --- a/apps/web/src/app/(main)/form/[id]/page.tsx +++ b/apps/web/src/app/(main)/form/[id]/page.tsx @@ -1,18 +1,14 @@ -import { type FormData } from '@formbase/db/schema'; -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from '@formbase/ui/primitives/tabs'; +import { validateRequest } from "@formbase/auth"; +import { FormData } from "@formbase/db/schema"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@formbase/ui/primitives/tabs"; -import { CopyButton } from '~/components/copy-button'; -import { api } from '~/lib/trpc/server'; +import { CopyButton } from "~/components/copy-button"; +import { api } from "~/lib/trpc/server"; -import { EmptyFormState } from '../../dashboard/_components/empty-state'; -import { ExportSubmissionsDropDownButton } from './export-submissions-button'; -import { FormSettings } from './form-settings'; -import { SubmissionsTable } from './submissions-table'; +import { EmptyFormState } from "../../dashboard/_components/empty-state"; +import { ExportSubmissionsDropDownButton } from "./export-submissions-button"; +import { FormSettings } from "./form-settings"; +import { SubmissionsTable } from "./submissions-table"; export default async function FormPage({ params }: { params: { id: string } }) { const formId = params.id; @@ -21,6 +17,8 @@ export default async function FormPage({ params }: { params: { id: string } }) { api.formData.all({ formId }), ]); + const { user } = await validateRequest(); + return (
@@ -66,7 +64,7 @@ export default async function FormPage({ params }: { params: { id: string } }) { {/* Change your password here. */} {/* Look at your analytics here */} - +
diff --git a/apps/web/src/app/api/s/[id]/route.ts b/apps/web/src/app/api/s/[id]/route.ts index 8a6bc2e..d805acb 100644 --- a/apps/web/src/app/api/s/[id]/route.ts +++ b/apps/web/src/app/api/s/[id]/route.ts @@ -1,12 +1,11 @@ -import { userAgent } from 'next/server'; +import { Form } from "@formbase/db/schema"; +import { env } from "@formbase/env"; +import { userAgent } from "next/server"; -import { type Form } from '@formbase/db/schema'; -import { env } from '@formbase/env'; - -import { sendMail } from '~/lib/email/mailer'; -import { renderNewSubmissionEmail } from '~/lib/email/templates/new-submission'; -import { api } from '~/lib/trpc/server'; -import { assignFileOrImage, uploadFileFromBlob } from '~/lib/upload-file'; +import { sendMail } from "~/lib/email/mailer"; +import { renderNewSubmissionEmail } from "~/lib/email/templates/new-submission"; +import { api } from "~/lib/trpc/server"; +import { assignFileOrImage, uploadFileFromBlob } from "~/lib/upload-file"; type Json = string | number | boolean | null | { [key: string]: Json } | Json[]; @@ -68,7 +67,7 @@ async function handleEmailNotifications( if (!user) throw new Error('User not found'); await sendMail({ - to: user.email, + to: form.defaultSubmissionEmail ?? user.email, subject: `New Submission for "${form.title}"`, body: renderNewSubmissionEmail({ formTitle: form.title, diff --git a/packages/api/routers/form.ts b/packages/api/routers/form.ts index 1793145..3b417d4 100644 --- a/packages/api/routers/form.ts +++ b/packages/api/routers/form.ts @@ -1,10 +1,9 @@ -import { z } from 'zod'; +import { drizzlePrimitives } from "@formbase/db"; +import { formDatas, forms, onboardingForms } from "@formbase/db/schema"; +import { generateId } from "@formbase/utils/generate-id"; +import { z } from "zod"; -import { drizzlePrimitives } from '@formbase/db'; -import { formDatas, forms, onboardingForms } from '@formbase/db/schema'; -import { generateId } from '@formbase/utils/generate-id'; - -import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc'; +import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; const { and, count, eq } = drizzlePrimitives; @@ -57,6 +56,7 @@ export const formRouter = createTRPCRouter({ ) .mutation(async ({ ctx, input }) => { const id = generateId(15); + const userEmail = ctx.user.email; await ctx.db.insert(forms).values({ id, @@ -68,6 +68,7 @@ export const formRouter = createTRPCRouter({ keys: [''], enableEmailNotifications: true, enableSubmissions: true, + defaultSubmissionEmail: userEmail, }); return { id }; @@ -114,6 +115,7 @@ export const formRouter = createTRPCRouter({ enableSubmissions: z.boolean().optional(), enableEmailNotifications: z.boolean().optional(), returnUrl: z.string().optional(), + defaultSubmissionEmail: z.string().optional(), }), ) .mutation(async ({ ctx, input }) => { @@ -135,6 +137,8 @@ export const formRouter = createTRPCRouter({ enableEmailNotifications: input.enableEmailNotifications ?? form.enableEmailNotifications, returnUrl: input.returnUrl ?? form.returnUrl, + defaultSubmissionEmail: + input.defaultSubmissionEmail ?? form.defaultSubmissionEmail, }) .where(eq(forms.id, input.id)); }), diff --git a/packages/auth/lucia.ts b/packages/auth/lucia.ts index 478be92..13b9ced 100644 --- a/packages/auth/lucia.ts +++ b/packages/auth/lucia.ts @@ -1,11 +1,12 @@ import type { User } from '@formbase/db/schema'; -import { DrizzlePostgreSQLAdapter } from '@lucia-auth/adapter-drizzle'; -import { Lucia } from 'lucia'; +import { db } from "@formbase/db"; +import { sessions, users } from "@formbase/db/schema"; +import { env } from "@formbase/env"; +import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle"; +import { Lucia } from "lucia"; -import { db } from '@formbase/db'; -import { sessions, users } from '@formbase/db/schema'; -import { env } from '@formbase/env'; +import type { User as LuciaUser } from 'lucia'; const adapter = new DrizzlePostgreSQLAdapter(db, sessions, users); @@ -36,3 +37,7 @@ declare module 'lucia' { DatabaseUserAttributes: DatabaseUserAttributes; } } + + +// export lucia user type +export type UserInstance = LuciaUser; \ No newline at end of file diff --git a/packages/db/drizzle/0001_military_rictor.sql b/packages/db/drizzle/0001_military_rictor.sql new file mode 100644 index 0000000..5099bc3 --- /dev/null +++ b/packages/db/drizzle/0001_military_rictor.sql @@ -0,0 +1 @@ +ALTER TABLE "forms" ADD COLUMN "default_submission_email" varchar(255); \ No newline at end of file diff --git a/packages/db/drizzle/meta/0001_snapshot.json b/packages/db/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..8233a5c --- /dev/null +++ b/packages/db/drizzle/meta/0001_snapshot.json @@ -0,0 +1,548 @@ +{ + "id": "6efd6048-6668-4398-b3d5-8245ab011497", + "prevId": "14203c94-ceaa-4515-b165-f9d5b62f84ed", + "version": "6", + "dialect": "postgresql", + "tables": { + "public.email_verification_codes": { + "name": "email_verification_codes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "email_verif_user_idx": { + "name": "email_verif_user_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "email_verif_idx": { + "name": "email_verif_idx", + "columns": [ + "email" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_verification_codes_user_id_unique": { + "name": "email_verification_codes_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + } + }, + "public.form_datas": { + "name": "form_datas", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "form_id": { + "name": "form_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "form_idx": { + "name": "form_idx", + "columns": [ + "form_id" + ], + "isUnique": false + }, + "form_data_created_at_idx": { + "name": "form_data_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "form_datas_form_id_forms_id_fk": { + "name": "form_datas_form_id_forms_id_fk", + "tableFrom": "form_datas", + "tableTo": "forms", + "columnsFrom": [ + "form_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.forms": { + "name": "forms", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "return_url": { + "name": "return_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "send_email_for_new_submissions": { + "name": "send_email_for_new_submissions", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "keys": { + "name": "keys", + "type": "text[]", + "primaryKey": false, + "notNull": true + }, + "enable_submissions": { + "name": "enable_submissions", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "enable_retention": { + "name": "enable_retention", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "default_submission_email": { + "name": "default_submission_email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "form_user_idx": { + "name": "form_user_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "form_created_at_idx": { + "name": "form_created_at_idx", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "forms_user_id_users_id_fk": { + "name": "forms_user_id_users_id_fk", + "tableFrom": "forms", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.oauth_account": { + "name": "oauth_account", + "schema": "", + "columns": { + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_user_id": { + "name": "provider_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "oauth_account_user_id_users_id_fk": { + "name": "oauth_account_user_id_users_id_fk", + "tableFrom": "oauth_account", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "oauth_account_provider_id_provider_user_id_pk": { + "name": "oauth_account_provider_id_provider_user_id_pk", + "columns": [ + "provider_id", + "provider_user_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.password_reset_tokens": { + "name": "password_reset_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "password_reset_user_idx": { + "name": "password_reset_user_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "sessions_user_idx": { + "name": "sessions_user_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "github_id": { + "name": "github_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "hashed_password": { + "name": "hashed_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_subscription_id": { + "name": "stripe_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_price_id": { + "name": "stripe_price_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "stripe_current_period_end": { + "name": "stripe_current_period_end", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "email_idx": { + "name": "email_idx", + "columns": [ + "email" + ], + "isUnique": false + }, + "github_idx": { + "name": "github_idx", + "columns": [ + "github_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_github_id_unique": { + "name": "users_github_id_unique", + "nullsNotDistinct": false, + "columns": [ + "github_id" + ] + }, + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.onboarding_forms": { + "name": "onboarding_forms", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "form_id": { + "name": "form_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "onboarding_forms_form_id_forms_id_fk": { + "name": "onboarding_forms_form_id_forms_id_fk", + "tableFrom": "onboarding_forms", + "tableTo": "forms", + "columnsFrom": [ + "form_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index ae71854..27a265a 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1718590793739, "tag": "0000_known_luckman", "breakpoints": true + }, + { + "idx": 1, + "version": "6", + "when": 1721293778281, + "tag": "0001_military_rictor", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/db/schema/forms.ts b/packages/db/schema/forms.ts index 681246e..ca98ccd 100644 --- a/packages/db/schema/forms.ts +++ b/packages/db/schema/forms.ts @@ -1,9 +1,9 @@ import type { InferSelectModel } from 'drizzle-orm'; -import { boolean, index, pgTable, text, timestamp } from 'drizzle-orm/pg-core'; -import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; +import { boolean, index, pgTable, text, timestamp, varchar } from "drizzle-orm/pg-core"; +import { createInsertSchema, createSelectSchema } from "drizzle-zod"; -import { users } from './users'; +import { users } from "./users"; export const forms = pgTable( 'forms', @@ -23,6 +23,7 @@ export const forms = pgTable( keys: text('keys').array().notNull(), enableSubmissions: boolean('enable_submissions').default(true).notNull(), enableRetention: boolean('enable_retention').default(true).notNull(), + defaultSubmissionEmail: varchar('default_submission_email', { length: 255 }), }, (t) => ({ userIdx: index('form_user_idx').on(t.userId), From df2e35bceb6979ffd83e1bce0a039ff801778d48 Mon Sep 17 00:00:00 2001 From: AmoabaKelvin Date: Sat, 20 Jul 2024 08:48:15 +0000 Subject: [PATCH 2/2] resolve typescript issues --- .../app/(main)/form/[id]/form-settings.tsx | 75 ++++++++++++------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/apps/web/src/app/(main)/form/[id]/form-settings.tsx b/apps/web/src/app/(main)/form/[id]/form-settings.tsx index 3945142..821850a 100644 --- a/apps/web/src/app/(main)/form/[id]/form-settings.tsx +++ b/apps/web/src/app/(main)/form/[id]/form-settings.tsx @@ -1,8 +1,16 @@ 'use client'; -import { RouterOutputs } from "@formbase/api"; -import { UserInstance } from "@formbase/auth"; -import { Button } from "@formbase/ui/primitives/button"; +import { useRouter } from 'next/navigation'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { BellRing, ExternalLink, FolderPen, FolderX } from 'lucide-react'; +import { useForm } from 'react-hook-form'; +import { toast } from 'sonner'; +import { z } from 'zod'; + +import { type RouterOutputs } from '@formbase/api'; +import { type UserInstance } from '@formbase/auth'; +import { Button } from '@formbase/ui/primitives/button'; import { Form, FormControl, @@ -10,21 +18,15 @@ import { FormField, FormItem, FormLabel, -} from "@formbase/ui/primitives/form"; -import { Input } from "@formbase/ui/primitives/input"; -import { Label } from "@formbase/ui/primitives/label"; -import { Switch } from "@formbase/ui/primitives/switch"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { BellRing, ExternalLink, FolderPen, FolderX } from "lucide-react"; -import { useRouter } from "next/navigation"; -import { useForm } from "react-hook-form"; -import { toast } from "sonner"; -import { z } from "zod"; - -import { api } from "~/lib/trpc/react"; - -import { revalidateDashboard } from "../../_actions/revalidateDashboard"; -import { DeleteFormDialog } from "./delete-form-dialog"; +} from '@formbase/ui/primitives/form'; +import { Input } from '@formbase/ui/primitives/input'; +import { Label } from '@formbase/ui/primitives/label'; +import { Switch } from '@formbase/ui/primitives/switch'; + +import { api } from '~/lib/trpc/react'; + +import { revalidateDashboard } from '../../_actions/revalidateDashboard'; +import { DeleteFormDialog } from './delete-form-dialog'; const formNameSchema = z.object({ name: z.string().min(1).optional(), @@ -56,7 +58,9 @@ type _EnableSubmissionsRetentionSchema = z.infer; type EnableFormNotificationsSchema = z.infer; type FormReturnUrlSchema = z.infer; -type DefaultSubmissionEmailSchema = z.infer; +type DefaultSubmissionEmailSchema = z.infer< + typeof defaultSubmissionEmailSchema +>; type FormSettingsProps = { form: RouterOutputs['form']['get']; @@ -261,7 +265,13 @@ const ReturnUrlForm = ({ ); }; -const FormDefaultSubmissionEmailRecipient = ({ formId, email }: { formId: string; email: string }) => { +const FormDefaultSubmissionEmailRecipient = ({ + formId, + email, +}: { + formId: string; + email: string; +}) => { const router = useRouter(); const formDefaultSubmissionEmail = useForm({ @@ -271,10 +281,14 @@ const FormDefaultSubmissionEmailRecipient = ({ formId, email }: { formId: string }, }); - const { mutateAsync: updateFormDefaultSubmissionEmail, isPending: isUpdatingFormDefaultSubmissionEmail } = - api.form.update.useMutation(); + const { + mutateAsync: updateFormDefaultSubmissionEmail, + isPending: isUpdatingFormDefaultSubmissionEmail, + } = api.form.update.useMutation(); - async function handleFormDefaultSubmissionEmailSubmit(data: DefaultSubmissionEmailSchema) { + async function handleFormDefaultSubmissionEmailSubmit( + data: DefaultSubmissionEmailSchema, + ) { try { await updateFormDefaultSubmissionEmail({ id: formId, @@ -296,7 +310,11 @@ const FormDefaultSubmissionEmailRecipient = ({ formId, email }: { formId: string return (
- + Default Submission Email - This is the email address that submission emails will be sent to + + This is the email address that submission emails will be sent + to +
@@ -392,7 +413,7 @@ const EnableFormSubmissions = ({
{ field.onChange(isChecked); await handleEnableSubmissionsRetentionSubmit({ @@ -472,7 +493,7 @@ const EnableFormNotifications = ({
{ field.onChange(isChecked); await handleEnableSubmissionsNotifications({