From f4ebc5b9005d41410a4ec280bc0d458c7116dc7b Mon Sep 17 00:00:00 2001 From: Kiran K Date: Mon, 15 Jun 2026 08:28:35 +0530 Subject: [PATCH 1/2] Require support email during program onboarding --- .../program/new/overview/page-client.tsx | 22 ++++++++++++++++--- .../web/lib/zod/schemas/program-onboarding.ts | 21 ++++++++++-------- apps/web/lib/zod/schemas/programs.ts | 2 +- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/program/new/overview/page-client.tsx b/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/program/new/overview/page-client.tsx index 454e4a67276..e51f714f0b5 100644 --- a/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/program/new/overview/page-client.tsx +++ b/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/program/new/overview/page-client.tsx @@ -40,13 +40,29 @@ export function PageClient() { }; const isValid = useMemo(() => { - const { name, url, domain, logo, type, amountInCents, amountInPercentage } = - data; + const { + name, + url, + domain, + logo, + type, + amountInCents, + amountInPercentage, + supportEmail, + } = data; const hasAmount = type === "flat" ? amountInCents != null : amountInPercentage != null; - if (!name || !url || !domain || !logo || !type || !hasAmount) { + if ( + !name || + !url || + !domain || + !logo || + !type || + !hasAmount || + !supportEmail + ) { return false; } diff --git a/apps/web/lib/zod/schemas/program-onboarding.ts b/apps/web/lib/zod/schemas/program-onboarding.ts index bcc9ce4e6c3..c065efc760c 100644 --- a/apps/web/lib/zod/schemas/program-onboarding.ts +++ b/apps/web/lib/zod/schemas/program-onboarding.ts @@ -10,7 +10,7 @@ import { import { parseUrlSchema } from "./utils"; // Getting started -export const programInfoSchema = z.object({ +const programInfoSchema = z.object({ name: z.string().max(100), logo: z.string(), domain: z.string(), @@ -20,7 +20,7 @@ export const programInfoSchema = z.object({ }); // Configure rewards -export const programRewardSchema = z.object({ +const programRewardSchema = z.object({ defaultRewardType: z.enum(["lead", "sale"]).default("lead"), type: z.enum(RewardStructure).nullish(), amountInCents: FLAT_REWARD_AMOUNT_SCHEMA.nullish(), @@ -29,7 +29,7 @@ export const programRewardSchema = z.object({ }); // Invite partners -export const programInvitePartnersSchema = z.object({ +const programInvitePartnersSchema = z.object({ partners: z .array( z.object({ @@ -47,13 +47,16 @@ export const programInvitePartnersSchema = z.object({ }); // Help and support -export const programSupportSchema = updateProgramSchema.pick({ - supportEmail: true, - helpUrl: true, - termsUrl: true, -}); +const programSupportSchema = updateProgramSchema + .pick({ + helpUrl: true, + termsUrl: true, + }) + .extend({ + supportEmail: z.email().max(255), + }); -export const onboardingStepSchema = z.enum([ +const onboardingStepSchema = z.enum([ "get-started", "configure-reward", "invite-partners", diff --git a/apps/web/lib/zod/schemas/programs.ts b/apps/web/lib/zod/schemas/programs.ts index 440b6cdce4b..d3fa6406a8d 100644 --- a/apps/web/lib/zod/schemas/programs.ts +++ b/apps/web/lib/zod/schemas/programs.ts @@ -103,7 +103,7 @@ export const updateProgramSchema = z.object({ .refine((val) => ALLOWED_MIN_PAYOUT_AMOUNTS.includes(val), { message: `Minimum payout amount must be one of ${ALLOWED_MIN_PAYOUT_AMOUNTS.join(", ")}`, }), - supportEmail: z.email().max(255).nullish(), + supportEmail: z.email().max(255).optional(), // Support email is required for a program helpUrl: z.httpUrl().max(500).nullish(), termsUrl: z.httpUrl().max(500).nullish(), messagingEnabledAt: z.coerce.date().nullish(), From 153107966a52b93d3d28a06c78bfcbc335df3939 Mon Sep 17 00:00:00 2001 From: Kiran K Date: Mon, 15 Jun 2026 22:42:21 +0530 Subject: [PATCH 2/2] fix build --- .../(ee)/program/resources/program-help-and-support.tsx | 6 ++++-- apps/web/ui/partners/program-onboarding-form-wrapper.tsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx index c99731dce6b..7630d8d9810 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx @@ -6,16 +6,18 @@ import { getPlanCapabilities } from "@/lib/plan-capabilities"; import useProgram from "@/lib/swr/use-program"; import useWorkspace from "@/lib/swr/use-workspace"; import { ProgramProps } from "@/lib/types"; +import { updateProgramSchema } from "@/lib/zod/schemas/programs"; import { usePartnersUpgradeModal } from "@/ui/partners/partners-upgrade-modal"; import { Button, CrownSmall, Switch, TooltipContent } from "@dub/ui"; import { useAction } from "next-safe-action/hooks"; import { Controller, useForm } from "react-hook-form"; import { toast } from "sonner"; import { mutate } from "swr"; +import * as z from "zod/v4"; import { SettingsRow } from "../program-settings-row"; type FormData = Pick< - ProgramProps, + z.infer, "supportEmail" | "helpUrl" | "termsUrl" | "messagingEnabledAt" >; @@ -57,7 +59,7 @@ export function ProgramHelpAndSupportContent({ } = useForm({ mode: "onBlur", defaultValues: { - supportEmail: program?.supportEmail, + supportEmail: program?.supportEmail || undefined, helpUrl: program?.helpUrl, termsUrl: program?.termsUrl, messagingEnabledAt: program?.messagingEnabledAt, diff --git a/apps/web/ui/partners/program-onboarding-form-wrapper.tsx b/apps/web/ui/partners/program-onboarding-form-wrapper.tsx index f2d0e3d89dd..7a0f72d48bf 100644 --- a/apps/web/ui/partners/program-onboarding-form-wrapper.tsx +++ b/apps/web/ui/partners/program-onboarding-form-wrapper.tsx @@ -44,7 +44,7 @@ export function ProgramOnboardingFormWrapper({ partners: programOnboarding.partners?.length ? programOnboarding.partners : [{ email: "" }], - supportEmail: programOnboarding.supportEmail || null, + supportEmail: programOnboarding.supportEmail, helpUrl: programOnboarding.helpUrl || null, termsUrl: programOnboarding.termsUrl || null, ...values,