diff --git a/apps/web/app/(ee)/api/commissions/timeseries/route.ts b/apps/web/app/(ee)/api/commissions/timeseries/route.ts index d0e458e7673..ae1feee6e20 100644 --- a/apps/web/app/(ee)/api/commissions/timeseries/route.ts +++ b/apps/web/app/(ee)/api/commissions/timeseries/route.ts @@ -1,4 +1,5 @@ import { getStartEndDates } from "@/lib/analytics/utils/get-start-end-dates"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { withWorkspace } from "@/lib/auth"; import { sqlGranularityMap } from "@/lib/planetscale/granularity"; @@ -21,12 +22,7 @@ interface Commission { // GET /api/commissions/timeseries - get commissions timeseries for a program export const GET = withWorkspace(async ({ workspace, searchParams }) => { - const { programId } = searchParams; - - const program = await getProgramOrThrow({ - workspaceId: workspace.id, - programId, - }); + const programId = getDefaultProgramIdOrThrow(workspace); const { start, end, interval, timezone } = querySchema.parse(searchParams); @@ -34,7 +30,14 @@ export const GET = withWorkspace(async ({ workspace, searchParams }) => { interval, start, end, - dataAvailableFrom: program.createdAt, + dataAvailableFrom: + // ideally we should get the first commission event date for dataAvailableFrom + interval === "all" + ? await getProgramOrThrow({ + workspaceId: workspace.id, + programId, + }).then((program) => program.createdAt) + : undefined, }); const { dateFormat, dateIncrement, startFunction, formatString } = @@ -47,7 +50,7 @@ export const GET = withWorkspace(async ({ workspace, searchParams }) => { FROM Commission WHERE earnings > 0 - AND programId = ${program.id} + AND programId = ${programId} AND createdAt >= ${startDate} AND createdAt < ${endDate} GROUP BY start diff --git a/apps/web/app/(ee)/api/programs/[programId]/revenue/route.ts b/apps/web/app/(ee)/api/programs/[programId]/revenue/route.ts index c80660c211a..0086cc135ec 100644 --- a/apps/web/app/(ee)/api/programs/[programId]/revenue/route.ts +++ b/apps/web/app/(ee)/api/programs/[programId]/revenue/route.ts @@ -1,4 +1,5 @@ import { getAnalytics } from "@/lib/analytics/get-analytics"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { withWorkspace } from "@/lib/auth"; import { analyticsQuerySchema } from "@/lib/zod/schemas/analytics"; @@ -14,27 +15,30 @@ const querySchema = analyticsQuerySchema.pick({ }); // GET /api/programs/[programId]/revenue - get revenue timeseries for a program -export const GET = withWorkspace( - async ({ workspace, params, searchParams }) => { - const program = await getProgramOrThrow({ - workspaceId: workspace.id, - programId: params.programId, - }); +export const GET = withWorkspace(async ({ workspace, searchParams }) => { + const programId = getDefaultProgramIdOrThrow(workspace); - const parsedParams = querySchema.parse(searchParams); + const parsedParams = querySchema.parse(searchParams); + const { interval } = parsedParams; - const response = await getAnalytics({ - ...parsedParams, - workspaceId: workspace.id, - programId: program.id, - dataAvailableFrom: program.createdAt, - }); + const response = await getAnalytics({ + ...parsedParams, + workspaceId: workspace.id, + programId, + dataAvailableFrom: + // ideally we should get the first commission event date for dataAvailableFrom + interval === "all" + ? await getProgramOrThrow({ + workspaceId: workspace.id, + programId, + }).then((program) => program.createdAt) + : undefined, + }); - const timeseries = response.map((item) => ({ - start: item.start, - saleAmount: item.saleAmount, - })); + const timeseries = response.map((item) => ({ + start: item.start, + saleAmount: item.saleAmount, + })); - return NextResponse.json(timeseries); - }, -); + return NextResponse.json(timeseries); +}); diff --git a/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/partners/form.tsx b/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/partners/form.tsx index e6d219c4bcf..0908a1747ca 100644 --- a/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/partners/form.tsx +++ b/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/partners/form.tsx @@ -114,7 +114,7 @@ export function Form() { const { executeAsync, isPending } = useAction(onboardProgramAction, { onSuccess: () => { - router.push(`/${workspaceSlug}/programs/new/connect`); + router.push(`/${workspaceSlug}/programs/new/support`); mutate(); }, onError: ({ error }) => { diff --git a/apps/web/app/(ee)/app.dub.co/embed/referrals/page-client.tsx b/apps/web/app/(ee)/app.dub.co/embed/referrals/page-client.tsx index 9f23277431c..83a68351da8 100644 --- a/apps/web/app/(ee)/app.dub.co/embed/referrals/page-client.tsx +++ b/apps/web/app/(ee)/app.dub.co/embed/referrals/page-client.tsx @@ -108,12 +108,8 @@ export function ReferralsEmbedPageClient({ return (
diff --git a/apps/web/app/(ee)/app.dub.co/embed/referrals/page.tsx b/apps/web/app/(ee)/app.dub.co/embed/referrals/page.tsx index f70562a2a8d..a8f3c90eecd 100644 --- a/apps/web/app/(ee)/app.dub.co/embed/referrals/page.tsx +++ b/apps/web/app/(ee)/app.dub.co/embed/referrals/page.tsx @@ -38,12 +38,8 @@ async function ReferralsEmbedRSC({ function EmbedInlineLoading({ themeOptions }: { themeOptions: ThemeOptions }) { return (
diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/commissions/create-commission-sheet.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/commissions/create-commission-sheet.tsx index 54037fa8950..a45c58789be 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/commissions/create-commission-sheet.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/commissions/create-commission-sheet.tsx @@ -87,7 +87,6 @@ function CreateCommissionSheetContent({ await executeAsync({ ...data, workspaceId, - programId: program.id, saleAmount: data.saleAmount ? data.saleAmount * 100 : null, saleEventDate, leadEventDate, diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/invite-partner-sheet.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/invite-partner-sheet.tsx index 8d91ae92c05..cd3951c8bc5 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/invite-partner-sheet.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/invite-partner-sheet.tsx @@ -113,7 +113,6 @@ function InvitePartnerSheetContent({ setIsOpen }: InvitePartnerSheetProps) { await executeAsync({ ...data, workspaceId, - programId: program.id, }); }; diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/partner-table.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/partner-table.tsx index b3e621bafea..e2cbae9580d 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/partner-table.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/partners/partner-table.tsx @@ -410,7 +410,6 @@ function RowMenuButton({ await resendInvite({ workspaceId, - programId: row.original.programId!, partnerId: row.original.id, }); }} @@ -434,7 +433,6 @@ function RowMenuButton({ await deleteInvite({ workspaceId, - programId: row.original.programId!, partnerId: row.original.id, }); }} diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/branding/branding-settings.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/branding/branding-settings.tsx index f262819d17d..8f60ddb30a5 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/branding/branding-settings.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/branding/branding-settings.tsx @@ -60,8 +60,7 @@ function BrandingSettingsForm({ program }: { program: ProgramProps }) { className="rounded-lg border border-neutral-200 bg-white" onSubmit={handleSubmit(async (data) => { await executeAsync({ - workspaceId: workspaceId || "", - programId: program.id, + workspaceId: workspaceId!, ...data, }); diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/communication/page-client.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/communication/page-client.tsx index 49a82c148ca..2e3cdfa2d7c 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/communication/page-client.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/communication/page-client.tsx @@ -44,14 +44,13 @@ export function ProgramCommunication() { }); const onSubmit = async (data: FormData) => { - if (!workspaceId || !program?.id) { + if (!workspaceId) { return; } await executeAsync({ ...data, workspaceId, - programId: program.id, helpUrl: data.helpUrl || null, termsUrl: data.termsUrl || null, }); diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/links/links-settings.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/links/links-settings.tsx index bb160110f76..b42c4bc8af4 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/links/links-settings.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/links/links-settings.tsx @@ -78,7 +78,6 @@ function LinksSettingsForm({ program }: { program: ProgramProps }) { await executeAsync({ ...data, workspaceId: workspaceId!, - programId: program.id, }); // Reset isDirty state diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/rewards/settings.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/rewards/settings.tsx index ac40613cfb7..981574b4e24 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/rewards/settings.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/programs/[programId]/settings/rewards/settings.tsx @@ -46,13 +46,12 @@ export function RewardSettings() { }); const onSubmit = async (data: FormData) => { - if (!workspaceId || !program?.id) { + if (!workspaceId) { return; } await executeAsync({ workspaceId, - programId: program.id, ...data, }); }; diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/links/page-client.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/links/page-client.tsx index 8b684e0284a..75eaa3029ef 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/links/page-client.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/links/page-client.tsx @@ -7,7 +7,7 @@ import { import { useIsMegaFolder } from "@/lib/swr/use-is-mega-folder"; import useLinks from "@/lib/swr/use-links"; import useWorkspace from "@/lib/swr/use-workspace"; -import { STORE_KEYS, useWorkspaceStore } from "@/lib/swr/use-workspace-store"; +import { useWorkspaceStore } from "@/lib/swr/use-workspace-store"; import { RequestFolderEditAccessButton } from "@/ui/folders/request-edit-button"; import LinkDisplay from "@/ui/links/link-display"; import LinksContainer from "@/ui/links/links-container"; @@ -82,7 +82,7 @@ function WorkspaceLinks() { ); const [dotLinkOfferDismissed, _, { loading: loadingDotLinkOfferDismissed }] = - useWorkspaceStore(STORE_KEYS.dotLinkOfferDismissed); + useWorkspaceStore("dotLinkOfferDismissed"); const [showedDotLinkModal, setShowedDotLinkModal] = useState(false); const { setShowDotLinkOfferModal, DotLinkOfferModal } = diff --git a/apps/web/lib/actions/partners/approve-partner.ts b/apps/web/lib/actions/partners/approve-partner.ts index 0ad67303195..931e2c76fd3 100644 --- a/apps/web/lib/actions/partners/approve-partner.ts +++ b/apps/web/lib/actions/partners/approve-partner.ts @@ -1,6 +1,7 @@ "use server"; import { createPartnerLink } from "@/lib/api/partners/create-partner-link"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { determinePartnerReward } from "@/lib/partners/determine-partner-reward"; import { ProgramPartnerLinkProps } from "@/lib/types"; import { sendWorkspaceWebhook } from "@/lib/webhook/publish"; @@ -23,7 +24,9 @@ export const approvePartnerAction = authActionClient .schema(approvePartnerSchema) .action(async ({ parsedInput, ctx }) => { const { workspace, user } = ctx; - const { programId, partnerId, linkId } = parsedInput; + const { partnerId, linkId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const [program, link] = await Promise.all([ getProgramOrThrow({ diff --git a/apps/web/lib/actions/partners/ban-partner.ts b/apps/web/lib/actions/partners/ban-partner.ts index 719c1e88f25..42bdc2dba59 100644 --- a/apps/web/lib/actions/partners/ban-partner.ts +++ b/apps/web/lib/actions/partners/ban-partner.ts @@ -1,6 +1,7 @@ "use server"; import { linkCache } from "@/lib/api/links/cache"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramEnrollmentOrThrow } from "@/lib/api/programs/get-program-enrollment-or-throw"; import { BAN_PARTNER_REASONS, @@ -17,19 +18,15 @@ export const banPartnerAction = authActionClient .schema(banPartnerSchema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { programId, partnerId } = parsedInput; + const { partnerId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const programEnrollment = await getProgramEnrollmentOrThrow({ partnerId, programId, }); - const { program } = programEnrollment; - - if (program.workspaceId !== workspace.id) { - throw new Error("You are not authorized to ban this partner."); - } - if (programEnrollment.status === "banned") { throw new Error("This partner is already banned."); } @@ -91,6 +88,8 @@ export const banPartnerAction = authActionClient return; } + const { program } = programEnrollment; + const supportEmail = program.supportEmail || "support@dub.co"; await sendEmail({ diff --git a/apps/web/lib/actions/partners/confirm-payouts.ts b/apps/web/lib/actions/partners/confirm-payouts.ts index 23521986657..c03f62f2d92 100644 --- a/apps/web/lib/actions/partners/confirm-payouts.ts +++ b/apps/web/lib/actions/partners/confirm-payouts.ts @@ -1,6 +1,7 @@ "use server"; import { createId } from "@/lib/api/create-id"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { PAYOUT_FEES } from "@/lib/partners/constants"; import { stripe } from "@/lib/stripe"; @@ -13,7 +14,6 @@ import { authActionClient } from "../safe-action"; const confirmPayoutsSchema = z.object({ workspaceId: z.string(), - programId: z.string(), paymentMethodId: z.string(), }); @@ -24,7 +24,9 @@ export const confirmPayoutsAction = authActionClient .schema(confirmPayoutsSchema) .action(async ({ parsedInput, ctx }) => { const { workspace, user } = ctx; - const { programId, paymentMethodId } = parsedInput; + const { paymentMethodId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const { minPayoutAmount } = await getProgramOrThrow({ workspaceId: workspace.id, diff --git a/apps/web/lib/actions/partners/create-commission.ts b/apps/web/lib/actions/partners/create-commission.ts index ceab2da9fcd..40030e2c9db 100644 --- a/apps/web/lib/actions/partners/create-commission.ts +++ b/apps/web/lib/actions/partners/create-commission.ts @@ -1,5 +1,6 @@ "use server"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramEnrollmentOrThrow } from "@/lib/api/programs/get-program-enrollment-or-throw"; import { createPartnerCommission } from "@/lib/partners/create-partner-commission"; import { getLeadEvent } from "@/lib/tinybird"; @@ -21,7 +22,6 @@ export const createCommissionAction = authActionClient const { workspace } = ctx; const { - programId, partnerId, linkId, invoiceId, @@ -32,11 +32,14 @@ export const createCommissionAction = authActionClient leadEventName, } = parsedInput; + const programId = getDefaultProgramIdOrThrow(workspace); + const [programEnrollment, customer] = await Promise.all([ getProgramEnrollmentOrThrow({ programId, partnerId, }), + prisma.customer.findUniqueOrThrow({ where: { id: customerId, @@ -44,11 +47,7 @@ export const createCommissionAction = authActionClient }), ]); - const { program, partner, links } = programEnrollment; - - if (program.workspaceId !== workspace.id) { - throw new Error(`Program ${programId} not found.`); - } + const { partner, links } = programEnrollment; if (customer.projectId !== workspace.id) { throw new Error(`Customer ${customerId} not found.`); diff --git a/apps/web/lib/actions/partners/create-discount.ts b/apps/web/lib/actions/partners/create-discount.ts index ec491812a53..578de9b305b 100644 --- a/apps/web/lib/actions/partners/create-discount.ts +++ b/apps/web/lib/actions/partners/create-discount.ts @@ -1,6 +1,7 @@ "use server"; import { createId } from "@/lib/api/create-id"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { qstash } from "@/lib/cron"; import { createDiscountSchema } from "@/lib/zod/schemas/discount"; @@ -13,15 +14,10 @@ export const createDiscountAction = authActionClient .schema(createDiscountSchema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { - programId, - partnerIds, - amount, - type, - maxDuration, - couponId, - couponTestId, - } = parsedInput; + const { partnerIds, amount, type, maxDuration, couponId, couponTestId } = + parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const program = await getProgramOrThrow({ workspaceId: workspace.id, diff --git a/apps/web/lib/actions/partners/create-manual-payout.ts b/apps/web/lib/actions/partners/create-manual-payout.ts index 247f0f1737e..389ef31e56f 100644 --- a/apps/web/lib/actions/partners/create-manual-payout.ts +++ b/apps/web/lib/actions/partners/create-manual-payout.ts @@ -1,7 +1,7 @@ "use server"; import { createId } from "@/lib/api/create-id"; -import { DubApiError } from "@/lib/api/errors"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { createManualPayoutSchema } from "@/lib/zod/schemas/payouts"; import { prisma } from "@dub/prisma"; import { authActionClient } from "../safe-action"; @@ -10,31 +10,19 @@ export const createManualPayoutAction = authActionClient .schema(createManualPayoutSchema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { programId, partnerId, amount, description } = parsedInput; + const { partnerId, amount, description } = parsedInput; - const programEnrollment = await prisma.programEnrollment.findUniqueOrThrow({ + const programId = getDefaultProgramIdOrThrow(workspace); + + await prisma.programEnrollment.findUniqueOrThrow({ where: { partnerId_programId: { partnerId, programId, }, }, - select: { - program: { - select: { - workspaceId: true, - }, - }, - }, }); - if (programEnrollment.program.workspaceId !== workspace.id) { - throw new DubApiError({ - code: "not_found", - message: "Program not found", - }); - } - const amountInCents = amount || 0; const payout = await prisma.payout.create({ diff --git a/apps/web/lib/actions/partners/create-reward.ts b/apps/web/lib/actions/partners/create-reward.ts index f1535cf3911..6ff3c8c7190 100644 --- a/apps/web/lib/actions/partners/create-reward.ts +++ b/apps/web/lib/actions/partners/create-reward.ts @@ -1,6 +1,7 @@ "use server"; import { createId } from "@/lib/api/create-id"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { createRewardSchema } from "@/lib/zod/schemas/rewards"; import { prisma } from "@dub/prisma"; @@ -10,15 +11,10 @@ export const createRewardAction = authActionClient .schema(createRewardSchema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { - programId, - partnerIds, - event, - amount, - type, - maxDuration, - maxAmount, - } = parsedInput; + const { partnerIds, event, amount, type, maxDuration, maxAmount } = + parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const program = await getProgramOrThrow({ workspaceId: workspace.id, diff --git a/apps/web/lib/actions/partners/delete-discount.ts b/apps/web/lib/actions/partners/delete-discount.ts index 3896cf346ae..83b60d2a68d 100644 --- a/apps/web/lib/actions/partners/delete-discount.ts +++ b/apps/web/lib/actions/partners/delete-discount.ts @@ -1,6 +1,7 @@ "use server"; import { getDiscountOrThrow } from "@/lib/api/partners/get-discount-or-throw"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { qstash } from "@/lib/cron"; import { redis } from "@/lib/upstash"; @@ -12,7 +13,6 @@ import { authActionClient } from "../safe-action"; const deleteDiscountSchema = z.object({ workspaceId: z.string(), - programId: z.string(), discountId: z.string(), }); @@ -20,7 +20,9 @@ export const deleteDiscountAction = authActionClient .schema(deleteDiscountSchema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { programId, discountId } = parsedInput; + const { discountId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const program = await getProgramOrThrow({ workspaceId: workspace.id, diff --git a/apps/web/lib/actions/partners/delete-program-invite.ts b/apps/web/lib/actions/partners/delete-program-invite.ts index dd272f67c63..0502c8f98f4 100644 --- a/apps/web/lib/actions/partners/delete-program-invite.ts +++ b/apps/web/lib/actions/partners/delete-program-invite.ts @@ -1,22 +1,24 @@ "use server"; import { bulkDeleteLinks } from "@/lib/api/links/bulk-delete-links"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { prisma } from "@dub/prisma"; import z from "../../zod"; import { authActionClient } from "../safe-action"; const deleteProgramInviteSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerId: z.string(), }); export const deleteProgramInviteAction = authActionClient .schema(deleteProgramInviteSchema) .action(async ({ parsedInput, ctx }) => { - const { programId, partnerId } = parsedInput; + const { partnerId } = parsedInput; const { workspace } = ctx; + const programId = getDefaultProgramIdOrThrow(workspace); + const { program, partner, ...programEnrollment } = await prisma.programEnrollment.findUniqueOrThrow({ where: { @@ -32,10 +34,6 @@ export const deleteProgramInviteAction = authActionClient }, }); - if (program.workspaceId !== workspace.id) { - throw new Error("Program not found."); - } - if (programEnrollment.status !== "invited") { throw new Error("Invite not found."); } diff --git a/apps/web/lib/actions/partners/delete-reward.ts b/apps/web/lib/actions/partners/delete-reward.ts index 56e9d9fb02b..e72395b1169 100644 --- a/apps/web/lib/actions/partners/delete-reward.ts +++ b/apps/web/lib/actions/partners/delete-reward.ts @@ -2,6 +2,7 @@ import { DubApiError } from "@/lib/api/errors"; import { getRewardOrThrow } from "@/lib/api/partners/get-reward-or-throw"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { prisma } from "@dub/prisma"; import { z } from "zod"; @@ -9,7 +10,6 @@ import { authActionClient } from "../safe-action"; const schema = z.object({ workspaceId: z.string(), - programId: z.string(), rewardId: z.string(), }); @@ -17,7 +17,9 @@ export const deleteRewardAction = authActionClient .schema(schema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { programId, rewardId } = parsedInput; + const { rewardId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const program = await getProgramOrThrow({ workspaceId: workspace.id, diff --git a/apps/web/lib/actions/partners/invite-partner.ts b/apps/web/lib/actions/partners/invite-partner.ts index e745aceb0d8..f800b4d9e25 100644 --- a/apps/web/lib/actions/partners/invite-partner.ts +++ b/apps/web/lib/actions/partners/invite-partner.ts @@ -4,6 +4,7 @@ import { createAndEnrollPartner } from "@/lib/api/partners/create-and-enroll-par import { createPartnerLink } from "@/lib/api/partners/create-partner-link"; import { getDiscountOrThrow } from "@/lib/api/partners/get-discount-or-throw"; import { getRewardOrThrow } from "@/lib/api/partners/get-reward-or-throw"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { invitePartnerSchema } from "@/lib/zod/schemas/partners"; import { sendEmail } from "@dub/email"; import { PartnerInvite } from "@dub/email/templates/partner-invite"; @@ -17,8 +18,9 @@ export const invitePartnerAction = authActionClient .schema(invitePartnerSchema) .action(async ({ parsedInput, ctx }) => { const { workspace, user } = ctx; - const { programId, name, email, linkId, rewardId, discountId } = - parsedInput; + const { name, email, linkId, rewardId, discountId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); let [program, link, , ,] = await Promise.all([ getProgramOrThrow({ diff --git a/apps/web/lib/actions/partners/mark-commission-duplicate.ts b/apps/web/lib/actions/partners/mark-commission-duplicate.ts index 675d5c771b8..3984561e7f6 100644 --- a/apps/web/lib/actions/partners/mark-commission-duplicate.ts +++ b/apps/web/lib/actions/partners/mark-commission-duplicate.ts @@ -8,7 +8,6 @@ import { authActionClient } from "../safe-action"; const markCommissionDuplicateSchema = z.object({ workspaceId: z.string(), - programId: z.string(), commissionId: z.string(), }); diff --git a/apps/web/lib/actions/partners/mark-commission-fraud-or-canceled.ts b/apps/web/lib/actions/partners/mark-commission-fraud-or-canceled.ts index 5317828ca71..eac8a826c25 100644 --- a/apps/web/lib/actions/partners/mark-commission-fraud-or-canceled.ts +++ b/apps/web/lib/actions/partners/mark-commission-fraud-or-canceled.ts @@ -7,7 +7,6 @@ import { authActionClient } from "../safe-action"; const markCommissionFraudOrCanceledSchema = z.object({ workspaceId: z.string(), - programId: z.string(), commissionId: z.string(), status: z.enum(["fraud", "canceled"]), }); diff --git a/apps/web/lib/actions/partners/mark-payout-paid.ts b/apps/web/lib/actions/partners/mark-payout-paid.ts index ad93c817be5..27d4be3e06e 100644 --- a/apps/web/lib/actions/partners/mark-payout-paid.ts +++ b/apps/web/lib/actions/partners/mark-payout-paid.ts @@ -8,7 +8,6 @@ import { authActionClient } from "../safe-action"; const markPayoutPaidSchema = z.object({ workspaceId: z.string(), - programId: z.string(), payoutId: z.string(), }); diff --git a/apps/web/lib/actions/partners/reject-partner.ts b/apps/web/lib/actions/partners/reject-partner.ts index 2df49a01ac1..9f7f0dd1d6a 100644 --- a/apps/web/lib/actions/partners/reject-partner.ts +++ b/apps/web/lib/actions/partners/reject-partner.ts @@ -7,7 +7,6 @@ import { authActionClient } from "../safe-action"; const rejectPartnerSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerId: z.string(), }); @@ -43,6 +42,4 @@ export const rejectPartnerAction = authActionClient }); // TODO: [partners] Notify partner of rejection? - - return { ok: true }; }); diff --git a/apps/web/lib/actions/partners/resend-program-invite.ts b/apps/web/lib/actions/partners/resend-program-invite.ts index 34875e6853e..72d60b3b046 100644 --- a/apps/web/lib/actions/partners/resend-program-invite.ts +++ b/apps/web/lib/actions/partners/resend-program-invite.ts @@ -1,5 +1,6 @@ "use server"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { sendEmail } from "@dub/email"; import { PartnerInvite } from "@dub/email/templates/partner-invite"; import { prisma } from "@dub/prisma"; @@ -8,16 +9,17 @@ import { authActionClient } from "../safe-action"; const resendProgramInviteSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerId: z.string(), }); export const resendProgramInviteAction = authActionClient .schema(resendProgramInviteSchema) .action(async ({ parsedInput, ctx }) => { - const { programId, partnerId } = parsedInput; + const { partnerId } = parsedInput; const { workspace } = ctx; + const programId = getDefaultProgramIdOrThrow(workspace); + const { program, partner, ...programEnrollment } = await prisma.programEnrollment.findUniqueOrThrow({ where: { @@ -32,10 +34,6 @@ export const resendProgramInviteAction = authActionClient }, }); - if (program.workspaceId !== workspace.id) { - throw new Error("Program not found."); - } - if (programEnrollment.status !== "invited") { throw new Error("Invite not found."); } diff --git a/apps/web/lib/actions/partners/start-rewardful-import.ts b/apps/web/lib/actions/partners/start-rewardful-import.ts index 57972fe4785..37d81659ca2 100644 --- a/apps/web/lib/actions/partners/start-rewardful-import.ts +++ b/apps/web/lib/actions/partners/start-rewardful-import.ts @@ -1,5 +1,6 @@ "use server"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { rewardfulImporter } from "@/lib/rewardful/importer"; import { z } from "zod"; import { getProgramOrThrow } from "../../api/programs/get-program-or-throw"; @@ -7,7 +8,6 @@ import { authActionClient } from "../safe-action"; const schema = z.object({ workspaceId: z.string(), - programId: z.string(), campaignId: z.string().describe("Rewardful campaign ID to import."), }); @@ -15,7 +15,9 @@ export const startRewardfulImportAction = authActionClient .schema(schema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { campaignId, programId } = parsedInput; + const { campaignId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const program = await getProgramOrThrow({ workspaceId: workspace.id, diff --git a/apps/web/lib/actions/partners/unban-partner.ts b/apps/web/lib/actions/partners/unban-partner.ts index 7547bfd2fa3..8cd7124ea38 100644 --- a/apps/web/lib/actions/partners/unban-partner.ts +++ b/apps/web/lib/actions/partners/unban-partner.ts @@ -1,6 +1,7 @@ "use server"; import { linkCache } from "@/lib/api/links/cache"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramEnrollmentOrThrow } from "@/lib/api/programs/get-program-enrollment-or-throw"; import { banPartnerSchema } from "@/lib/zod/schemas/partners"; import { prisma } from "@dub/prisma"; @@ -16,19 +17,15 @@ export const unbanPartnerAction = authActionClient .schema(unbanPartnerSchema) .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; - const { programId, partnerId } = parsedInput; + const { partnerId } = parsedInput; + + const programId = getDefaultProgramIdOrThrow(workspace); const programEnrollment = await getProgramEnrollmentOrThrow({ partnerId, programId, }); - const { program } = programEnrollment; - - if (program.workspaceId !== workspace.id) { - throw new Error("You are not authorized to ban this partner."); - } - if (programEnrollment.status !== "banned") { throw new Error("This partner is not banned."); } diff --git a/apps/web/lib/actions/partners/update-discount.ts b/apps/web/lib/actions/partners/update-discount.ts index efacb3e4dcd..fadb8c4b08a 100644 --- a/apps/web/lib/actions/partners/update-discount.ts +++ b/apps/web/lib/actions/partners/update-discount.ts @@ -1,6 +1,7 @@ "use server"; import { getDiscountOrThrow } from "@/lib/api/partners/get-discount-or-throw"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { qstash } from "@/lib/cron"; import { updateDiscountSchema } from "@/lib/zod/schemas/discount"; @@ -14,7 +15,6 @@ export const updateDiscountAction = authActionClient .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; const { - programId, discountId, partnerIds, amount, @@ -24,6 +24,8 @@ export const updateDiscountAction = authActionClient couponTestId, } = parsedInput; + const programId = getDefaultProgramIdOrThrow(workspace); + const program = await getProgramOrThrow({ workspaceId: workspace.id, programId, diff --git a/apps/web/lib/actions/partners/update-program.ts b/apps/web/lib/actions/partners/update-program.ts index 6f946ac1317..8eced649b9a 100644 --- a/apps/web/lib/actions/partners/update-program.ts +++ b/apps/web/lib/actions/partners/update-program.ts @@ -1,5 +1,6 @@ "use server"; +import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getFolderOrThrow } from "@/lib/folder/get-folder-or-throw"; import { isStored, storage } from "@/lib/storage"; import { prisma } from "@dub/prisma"; @@ -12,7 +13,6 @@ import { authActionClient } from "../safe-action"; const schema = updateProgramSchema.partial().extend({ workspaceId: z.string(), - programId: z.string(), logo: z.string().nullish(), wordmark: z.string().nullish(), brandColor: z.string().nullish(), @@ -23,7 +23,6 @@ export const updateProgramAction = authActionClient .action(async ({ parsedInput, ctx }) => { const { workspace } = ctx; const { - programId, defaultFolderId, name, holdingPeriodDays, @@ -40,67 +39,64 @@ export const updateProgramAction = authActionClient termsUrl, } = parsedInput; - try { - const program = await getProgramOrThrow({ + const programId = getDefaultProgramIdOrThrow(workspace); + const program = await getProgramOrThrow({ + workspaceId: workspace.id, + programId, + }); + + if (defaultFolderId) { + await getFolderOrThrow({ workspaceId: workspace.id, - programId, + userId: ctx.user.id, + folderId: defaultFolderId, }); + } - if (defaultFolderId) { - await getFolderOrThrow({ - workspaceId: workspace.id, - userId: ctx.user.id, - folderId: defaultFolderId, - }); - } - - const [logoUrl, wordmarkUrl] = await Promise.all([ - logo && !isStored(logo) - ? storage - .upload(`programs/${programId}/logo_${nanoid(7)}`, logo) - .then(({ url }) => url) - : null, - wordmark && !isStored(wordmark) - ? storage - .upload(`programs/${programId}/wordmark_${nanoid(7)}`, wordmark) - .then(({ url }) => url) - : null, - ]); + const [logoUrl, wordmarkUrl] = await Promise.all([ + logo && !isStored(logo) + ? storage + .upload(`programs/${programId}/logo_${nanoid(7)}`, logo) + .then(({ url }) => url) + : null, + wordmark && !isStored(wordmark) + ? storage + .upload(`programs/${programId}/wordmark_${nanoid(7)}`, wordmark) + .then(({ url }) => url) + : null, + ]); - await prisma.program.update({ - where: { - id: programId, - }, - data: { - name, - cookieLength, - holdingPeriodDays, - minPayoutAmount, - domain, - url, - brandColor, - logo: logoUrl ?? undefined, - wordmark: wordmarkUrl ?? undefined, - defaultFolderId, - linkStructure, - supportEmail, - helpUrl, - termsUrl, - }, - }); + await prisma.program.update({ + where: { + id: programId, + }, + data: { + name, + cookieLength, + holdingPeriodDays, + minPayoutAmount, + domain, + url, + brandColor, + logo: logoUrl ?? undefined, + wordmark: wordmarkUrl ?? undefined, + defaultFolderId, + linkStructure, + supportEmail, + helpUrl, + termsUrl, + }, + }); - // Delete old logo/wordmark if they were updated - waitUntil( - Promise.all([ - ...(logoUrl && program.logo - ? [storage.delete(program.logo.replace(`${R2_URL}/`, ""))] - : []), - ...(wordmarkUrl && program.wordmark - ? [storage.delete(program.wordmark.replace(`${R2_URL}/`, ""))] - : []), - ]), - ); - } catch (e) { - throw new Error("Failed to update program."); - } + // Delete old logo/wordmark if they were updated + waitUntil( + Promise.all([ + ...(logoUrl && program.logo + ? [storage.delete(program.logo.replace(`${R2_URL}/`, ""))] + : []), + ...(wordmarkUrl && program.wordmark + ? [storage.delete(program.wordmark.replace(`${R2_URL}/`, ""))] + : []), + ]), + ); }); diff --git a/apps/web/lib/actions/update-workspace-store.ts b/apps/web/lib/actions/update-workspace-store.ts index 3f7b2294013..49b0e0fa9b1 100644 --- a/apps/web/lib/actions/update-workspace-store.ts +++ b/apps/web/lib/actions/update-workspace-store.ts @@ -2,26 +2,27 @@ import { prisma } from "@dub/prisma"; import z from "../zod"; +import { workspaceStoreKeys } from "../zod/schemas/workspaces"; import { authActionClient } from "./safe-action"; -const schema = z.object({ +const updateWorkspaceStoreSchema = z.object({ workspaceId: z.string(), - key: z.string(), - value: z.any(), + key: workspaceStoreKeys, + value: z.any().refine((val) => { + const valueStr = JSON.stringify(val); + const sizeInBytes = new TextEncoder().encode(valueStr).length; + return sizeInBytes <= 1_097_152; // 1 MB in bytes + }, "Value size must not exceed 1 MB"), }); -// TODO: -// Add validation for key and value, otherwise it is open to abuse - // Update a workspace store item export const updateWorkspaceStore = authActionClient - .schema(schema) + .schema(updateWorkspaceStoreSchema) .action(async ({ ctx, parsedInput }) => { const { workspace } = ctx; const { key, value } = parsedInput; - const store = - (workspace.store as Record | undefined | null) ?? {}; + const store = workspace.store; await prisma.project.update({ where: { @@ -29,11 +30,9 @@ export const updateWorkspaceStore = authActionClient }, data: { store: { - ...store, + ...(store as Record), [key]: value, }, }, }); - - return { ok: true }; }); diff --git a/apps/web/lib/api/programs/get-default-program-id-or-throw.ts b/apps/web/lib/api/programs/get-default-program-id-or-throw.ts index 93d009a6389..44954318d5e 100644 --- a/apps/web/lib/api/programs/get-default-program-id-or-throw.ts +++ b/apps/web/lib/api/programs/get-default-program-id-or-throw.ts @@ -5,6 +5,7 @@ export const getDefaultProgramIdOrThrow = ( workspace: Pick, ) => { const programId = workspace.defaultProgramId; + if (!programId) { throw new DubApiError({ code: "not_found", diff --git a/apps/web/lib/middleware/workspaces.ts b/apps/web/lib/middleware/workspaces.ts index 2140ffda8b6..f474511261b 100644 --- a/apps/web/lib/middleware/workspaces.ts +++ b/apps/web/lib/middleware/workspaces.ts @@ -11,7 +11,8 @@ export default async function WorkspacesMiddleware( const { path, searchParamsObj, searchParamsString } = parse(req); // special case for handling ?next= query param - if (searchParamsObj.next) { + // only redirect if next is a valid relative path (not an absolute URL) + if (searchParamsObj.next && searchParamsObj.next.startsWith("/")) { return NextResponse.redirect(new URL(searchParamsObj.next, req.url)); } diff --git a/apps/web/lib/swr/use-workspace-store.ts b/apps/web/lib/swr/use-workspace-store.ts index d1e9bb5b473..6ec5ba912d2 100644 --- a/apps/web/lib/swr/use-workspace-store.ts +++ b/apps/web/lib/swr/use-workspace-store.ts @@ -3,16 +3,13 @@ import { useAction } from "next-safe-action/hooks"; import { useEffect, useState } from "react"; import { mutate } from "swr"; +import { z } from "zod"; import { updateWorkspaceStore } from "../actions/update-workspace-store"; +import { workspaceStoreKeys } from "../zod/schemas/workspaces"; import useWorkspace from "./use-workspace"; -export const STORE_KEYS = { - conversionsOnboarding: "conversionsOnboarding", - dotLinkOfferDismissed: "dotLinkOfferDismissed", -}; - export function useWorkspaceStore( - key: string, + key: z.infer, ): [ T | undefined, (value: T) => Promise, @@ -38,7 +35,12 @@ export function useWorkspaceStore( const setItem = async (value: T) => { setItemState(value); - await executeAsync({ key, value, workspaceId: workspaceId! }); + + await executeAsync({ + key, + value, + workspaceId: workspaceId!, + }); }; const mutateWorkspace = () => { diff --git a/apps/web/lib/zod/schemas/commissions.ts b/apps/web/lib/zod/schemas/commissions.ts index a3455b6f127..605f3655be1 100644 --- a/apps/web/lib/zod/schemas/commissions.ts +++ b/apps/web/lib/zod/schemas/commissions.ts @@ -87,7 +87,6 @@ export const getCommissionsCountQuerySchema = getCommissionsQuerySchema.omit({ export const createCommissionSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerId: z.string(), linkId: z.string(), customerId: z.string(), diff --git a/apps/web/lib/zod/schemas/discount.ts b/apps/web/lib/zod/schemas/discount.ts index f5da8fd1cc8..5a454409814 100644 --- a/apps/web/lib/zod/schemas/discount.ts +++ b/apps/web/lib/zod/schemas/discount.ts @@ -23,7 +23,6 @@ export const DiscountSchemaWithDeprecatedFields = DiscountSchema.extend({ export const createDiscountSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerIds: z.array(z.string()).nullish(), amount: z.number().min(0), type: z.nativeEnum(CommissionType).default("flat"), diff --git a/apps/web/lib/zod/schemas/partners.ts b/apps/web/lib/zod/schemas/partners.ts index d33757e27e3..8e7ef6b2d38 100644 --- a/apps/web/lib/zod/schemas/partners.ts +++ b/apps/web/lib/zod/schemas/partners.ts @@ -510,7 +510,6 @@ export const updatePartnerSaleSchema = z.object({ export const invitePartnerSchema = z.object({ workspaceId: z.string(), - programId: z.string(), name: z.string().trim().min(1).max(100), email: z.string().trim().email().min(1).max(100), linkId: z.string().optional(), @@ -520,7 +519,6 @@ export const invitePartnerSchema = z.object({ export const banPartnerSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerId: z.string(), reason: z.enum( Object.keys(BAN_PARTNER_REASONS) as [ @@ -532,7 +530,6 @@ export const banPartnerSchema = z.object({ export const approvePartnerSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerId: z.string(), linkId: z.string().nullable(), }); diff --git a/apps/web/lib/zod/schemas/payouts.ts b/apps/web/lib/zod/schemas/payouts.ts index 9a54f5374cd..a289b82f0ef 100644 --- a/apps/web/lib/zod/schemas/payouts.ts +++ b/apps/web/lib/zod/schemas/payouts.ts @@ -6,7 +6,6 @@ import { ProgramSchema } from "./programs"; export const createManualPayoutSchema = z.object({ workspaceId: z.string(), - programId: z.string(), partnerId: z.string({ required_error: "Please select a partner" }), amount: z .preprocess((val) => { diff --git a/apps/web/lib/zod/schemas/rewards.ts b/apps/web/lib/zod/schemas/rewards.ts index 7ca1eb15def..ce1d3cefb02 100644 --- a/apps/web/lib/zod/schemas/rewards.ts +++ b/apps/web/lib/zod/schemas/rewards.ts @@ -29,7 +29,6 @@ export const RewardSchema = z.object({ export const createOrUpdateRewardSchema = z.object({ workspaceId: z.string(), - programId: z.string(), event: z.nativeEnum(EventType), type: z.nativeEnum(CommissionType).default("flat"), amount: z.number().min(0), diff --git a/apps/web/lib/zod/schemas/workspaces.ts b/apps/web/lib/zod/schemas/workspaces.ts index a6194fbd94f..76070edb1cf 100644 --- a/apps/web/lib/zod/schemas/workspaces.ts +++ b/apps/web/lib/zod/schemas/workspaces.ts @@ -162,3 +162,9 @@ export const WorkspaceSchemaExtended = WorkspaceSchema.extend({ }), ), }); + +export const workspaceStoreKeys = z.enum([ + "programOnboarding", // json + "conversionsOnboarding", // boolean + "dotLinkOfferDismissed", // string +]); diff --git a/apps/web/ui/layout/sidebar/conversions/conversions-onboarding.tsx b/apps/web/ui/layout/sidebar/conversions/conversions-onboarding.tsx index bbc53e8edeb..4f1d33aed01 100644 --- a/apps/web/ui/layout/sidebar/conversions/conversions-onboarding.tsx +++ b/apps/web/ui/layout/sidebar/conversions/conversions-onboarding.tsx @@ -1,7 +1,7 @@ "use client"; import useWorkspace from "@/lib/swr/use-workspace"; -import { STORE_KEYS, useWorkspaceStore } from "@/lib/swr/use-workspace-store"; +import { useWorkspaceStore } from "@/lib/swr/use-workspace-store"; import { X } from "@/ui/shared/icons"; import { Book2Small, useMediaQuery } from "@dub/ui"; import { useConversionOnboardingModal } from "./conversions-onboarding-modal"; @@ -23,7 +23,7 @@ export function ConversionsOnboarding({ setConversionsOnboarding, { loading: loadingConversionsOnboarding }, ] = useWorkspaceStore( - STORE_KEYS.conversionsOnboarding, + "conversionsOnboarding", ); const { setShowConversionOnboardingModal, conversionOnboardingModal } = diff --git a/apps/web/ui/modals/dot-link-offer-modal.tsx b/apps/web/ui/modals/dot-link-offer-modal.tsx index ee62add7ec5..1ee9e4996c3 100644 --- a/apps/web/ui/modals/dot-link-offer-modal.tsx +++ b/apps/web/ui/modals/dot-link-offer-modal.tsx @@ -1,5 +1,5 @@ import useWorkspace from "@/lib/swr/use-workspace"; -import { STORE_KEYS, useWorkspaceStore } from "@/lib/swr/use-workspace-store"; +import { useWorkspaceStore } from "@/lib/swr/use-workspace-store"; import { ArrowTurnRight2, Button, @@ -31,7 +31,7 @@ function DotLinkOfferModal({ setShowDotLinkOfferModal: Dispatch>; }) { const [_, setDotLinkOfferDismissed, { mutateWorkspace }] = - useWorkspaceStore(STORE_KEYS.dotLinkOfferDismissed); + useWorkspaceStore("dotLinkOfferDismissed"); const scrollRef = useRef(null); const { scrollProgress, updateScrollProgress } = useScrollProgress(scrollRef); diff --git a/apps/web/ui/modals/import-rewardful-modal.tsx b/apps/web/ui/modals/import-rewardful-modal.tsx index 5a80ffc3f30..4469071450b 100644 --- a/apps/web/ui/modals/import-rewardful-modal.tsx +++ b/apps/web/ui/modals/import-rewardful-modal.tsx @@ -126,7 +126,6 @@ function ImportRewardfulModal({ await startRewardfulImport({ workspaceId, - programId: program.id, campaignId: selectedCampaign?.id, }); }; diff --git a/apps/web/ui/modals/upgraded-modal.tsx b/apps/web/ui/modals/upgraded-modal.tsx index 717efca2349..cf341d89bfa 100644 --- a/apps/web/ui/modals/upgraded-modal.tsx +++ b/apps/web/ui/modals/upgraded-modal.tsx @@ -1,5 +1,5 @@ import useWorkspace from "@/lib/swr/use-workspace"; -import { STORE_KEYS, useWorkspaceStore } from "@/lib/swr/use-workspace-store"; +import { useWorkspaceStore } from "@/lib/swr/use-workspace-store"; import { Button, Modal, useRouterStuff, useScrollProgress } from "@dub/ui"; import { getPlanDetails, PLANS, PRO_PLAN } from "@dub/utils"; import { usePlausible } from "next-plausible"; @@ -29,7 +29,7 @@ function UpgradedModal({ const { dotLinkClaimed } = useWorkspace(); const [_, setDotLinkOfferDismissed, { mutateWorkspace }] = - useWorkspaceStore(STORE_KEYS.dotLinkOfferDismissed); + useWorkspaceStore("dotLinkOfferDismissed"); const scrollRef = useRef(null); const { scrollProgress, updateScrollProgress } = useScrollProgress(scrollRef); diff --git a/apps/web/ui/partners/add-edit-discount-sheet.tsx b/apps/web/ui/partners/add-edit-discount-sheet.tsx index 4fcb12708ab..197f0e4ad55 100644 --- a/apps/web/ui/partners/add-edit-discount-sheet.tsx +++ b/apps/web/ui/partners/add-edit-discount-sheet.tsx @@ -153,14 +153,12 @@ function DiscountSheetContent({ const payload = { ...data, workspaceId, - programId: program.id, amount: data.type === "flat" ? data.amount * 100 : data.amount || 0, maxDuration: Number(data.maxDuration) === Infinity ? null : data.maxDuration, }; if (!discount) { - console.log("payload", payload); await createDiscount(payload); } else { await updateDiscount({ @@ -181,7 +179,6 @@ function DiscountSheetContent({ await deleteDiscount({ workspaceId, - programId: program.id, discountId: discount.id, }); }; diff --git a/apps/web/ui/partners/add-edit-reward-sheet.tsx b/apps/web/ui/partners/add-edit-reward-sheet.tsx index bba2f4f0c5d..683399554f0 100644 --- a/apps/web/ui/partners/add-edit-reward-sheet.tsx +++ b/apps/web/ui/partners/add-edit-reward-sheet.tsx @@ -233,7 +233,6 @@ function RewardSheetContent({ const payload = { ...data, workspaceId, - programId: program.id, partnerIds, amount: type === "flat" ? data.amount * 100 : data.amount, maxDuration: @@ -262,7 +261,6 @@ function RewardSheetContent({ await deleteReward({ workspaceId, - programId: program.id, rewardId: reward.id, }); }; diff --git a/apps/web/ui/partners/ban-partner-modal.tsx b/apps/web/ui/partners/ban-partner-modal.tsx index d8f76fbc13c..42266d2316b 100644 --- a/apps/web/ui/partners/ban-partner-modal.tsx +++ b/apps/web/ui/partners/ban-partner-modal.tsx @@ -71,7 +71,6 @@ function BanPartnerModal({ await executeAsync({ ...data, workspaceId, - programId, partnerId: partner.id, }); }, diff --git a/apps/web/ui/partners/create-payout-sheet.tsx b/apps/web/ui/partners/create-payout-sheet.tsx index 8a0dd12886d..6265383be8f 100644 --- a/apps/web/ui/partners/create-payout-sheet.tsx +++ b/apps/web/ui/partners/create-payout-sheet.tsx @@ -101,7 +101,6 @@ function CreatePayoutSheetContent(props: CreatePayoutSheetProps) { await executeAsync({ ...data, workspaceId, - programId: program.id, amount: amount * 100, partnerId, }); diff --git a/apps/web/ui/partners/mark-commission-duplicate-modal.tsx b/apps/web/ui/partners/mark-commission-duplicate-modal.tsx index 799f8b0956b..953e6b9d754 100644 --- a/apps/web/ui/partners/mark-commission-duplicate-modal.tsx +++ b/apps/web/ui/partners/mark-commission-duplicate-modal.tsx @@ -153,7 +153,6 @@ function ModalInner({ await executeAsync({ workspaceId, - programId, commissionId: commission.id, }); }} diff --git a/apps/web/ui/partners/mark-commission-fraud-or-canceled-modal.tsx b/apps/web/ui/partners/mark-commission-fraud-or-canceled-modal.tsx index 58fb776027c..788eb9d8239 100644 --- a/apps/web/ui/partners/mark-commission-fraud-or-canceled-modal.tsx +++ b/apps/web/ui/partners/mark-commission-fraud-or-canceled-modal.tsx @@ -161,7 +161,6 @@ function ModalInner({ await executeAsync({ workspaceId, - programId, commissionId: commission.id, status, }); diff --git a/apps/web/ui/partners/mark-payout-paid-modal.tsx b/apps/web/ui/partners/mark-payout-paid-modal.tsx index df53b77ffbc..77ac7cd02b1 100644 --- a/apps/web/ui/partners/mark-payout-paid-modal.tsx +++ b/apps/web/ui/partners/mark-payout-paid-modal.tsx @@ -79,7 +79,6 @@ function MarkPayoutPaidModalInner({ onClick={() => execute({ workspaceId: workspaceId!, - programId: programId as string, payoutId: payout.id, }) } diff --git a/apps/web/ui/partners/partner-application-sheet.tsx b/apps/web/ui/partners/partner-application-sheet.tsx index 640f8219a9d..9fd44d2ad05 100644 --- a/apps/web/ui/partners/partner-application-sheet.tsx +++ b/apps/web/ui/partners/partner-application-sheet.tsx @@ -298,7 +298,6 @@ function PartnerApproval({ await executeAsync({ workspaceId: workspaceId!, partnerId: partner.id, - programId: program.id, linkId: selectedLinkId, }); }} @@ -317,12 +316,10 @@ function PartnerRejectButton({ setIsOpen: Dispatch>; }) { const { id: workspaceId } = useWorkspace(); - const { program } = useProgram(); const { executeAsync, isPending } = useAction(rejectPartnerAction, { onSuccess: async () => { await mutatePrefix("/api/partners"); - toast.success("Partner rejected successfully."); setIsOpen(false); }, @@ -341,7 +338,6 @@ function PartnerRejectButton({ await executeAsync({ workspaceId: workspaceId!, partnerId: partner.id, - programId: program!.id, }); }} /> diff --git a/apps/web/ui/partners/payout-invoice-sheet.tsx b/apps/web/ui/partners/payout-invoice-sheet.tsx index ebc55339374..591f717187a 100644 --- a/apps/web/ui/partners/payout-invoice-sheet.tsx +++ b/apps/web/ui/partners/payout-invoice-sheet.tsx @@ -360,7 +360,6 @@ function PayoutInvoiceSheetContent({ setIsOpen }: PayoutInvoiceSheetProps) { await executeAsync({ workspaceId, - programId, paymentMethodId: selectedPaymentMethod.id, }); }} diff --git a/apps/web/ui/partners/unban-partner-modal.tsx b/apps/web/ui/partners/unban-partner-modal.tsx index 206999cb50c..ea8454ad755 100644 --- a/apps/web/ui/partners/unban-partner-modal.tsx +++ b/apps/web/ui/partners/unban-partner-modal.tsx @@ -63,7 +63,6 @@ function UnbanPartnerModal({ await executeAsync({ workspaceId, - programId, partnerId: partner.id, }); }, [executeAsync, partner.id, programId, workspaceId]);