Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions apps/web/app/(ee)/api/commissions/timeseries/route.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -21,20 +22,22 @@ 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);

const { startDate, endDate, granularity } = getStartEndDates({
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 } =
Expand All @@ -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
Expand Down
44 changes: 24 additions & 20 deletions apps/web/app/(ee)/api/programs/[programId]/revenue/route.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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);
});
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => {
Expand Down
8 changes: 2 additions & 6 deletions apps/web/app/(ee)/app.dub.co/embed/referrals/page-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,8 @@ export function ReferralsEmbedPageClient({

return (
<div
style={
themeOptions.backgroundColor
? { backgroundColor: themeOptions.backgroundColor }
: undefined
}
className="bg-bg-default flex min-h-screen flex-col"
style={{ backgroundColor: themeOptions.backgroundColor || "transparent" }}
className="flex min-h-screen flex-col"
>
<div className="relative z-0 p-5">
<div className="border-border-default relative flex flex-col overflow-hidden rounded-lg border p-4 md:p-6">
Expand Down
8 changes: 2 additions & 6 deletions apps/web/app/(ee)/app.dub.co/embed/referrals/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,8 @@ async function ReferralsEmbedRSC({
function EmbedInlineLoading({ themeOptions }: { themeOptions: ThemeOptions }) {
return (
<div
style={
themeOptions.backgroundColor
? { backgroundColor: themeOptions.backgroundColor }
: undefined
}
className="bg-bg-default flex min-h-screen flex-col"
style={{ backgroundColor: themeOptions.backgroundColor || "transparent" }}
className="flex min-h-screen flex-col"
>
<div className="p-5">
<div className="border-border-default relative flex flex-col overflow-hidden rounded-lg border p-4 md:p-6">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ function CreateCommissionSheetContent({
await executeAsync({
...data,
workspaceId,
programId: program.id,
saleAmount: data.saleAmount ? data.saleAmount * 100 : null,
saleEventDate,
leadEventDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ function InvitePartnerSheetContent({ setIsOpen }: InvitePartnerSheetProps) {
await executeAsync({
...data,
workspaceId,
programId: program.id,
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,6 @@ function RowMenuButton({

await resendInvite({
workspaceId,
programId: row.original.programId!,
partnerId: row.original.id,
});
}}
Expand All @@ -434,7 +433,6 @@ function RowMenuButton({

await deleteInvite({
workspaceId,
programId: row.original.programId!,
partnerId: row.original.id,
});
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ function LinksSettingsForm({ program }: { program: ProgramProps }) {
await executeAsync({
...data,
workspaceId: workspaceId!,
programId: program.id,
});

// Reset isDirty state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -82,7 +82,7 @@ function WorkspaceLinks() {
);

const [dotLinkOfferDismissed, _, { loading: loadingDotLinkOfferDismissed }] =
useWorkspaceStore<string>(STORE_KEYS.dotLinkOfferDismissed);
useWorkspaceStore<string>("dotLinkOfferDismissed");

const [showedDotLinkModal, setShowedDotLinkModal] = useState(false);
const { setShowDotLinkOfferModal, DotLinkOfferModal } =
Expand Down
5 changes: 4 additions & 1 deletion apps/web/lib/actions/partners/approve-partner.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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({
Expand Down
13 changes: 6 additions & 7 deletions apps/web/lib/actions/partners/ban-partner.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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.");
}
Expand Down Expand Up @@ -91,6 +88,8 @@ export const banPartnerAction = authActionClient
return;
}

const { program } = programEnrollment;

const supportEmail = program.supportEmail || "support@dub.co";

await sendEmail({
Expand Down
6 changes: 4 additions & 2 deletions apps/web/lib/actions/partners/confirm-payouts.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -13,7 +14,6 @@ import { authActionClient } from "../safe-action";

const confirmPayoutsSchema = z.object({
workspaceId: z.string(),
programId: z.string(),
paymentMethodId: z.string(),
});

Expand All @@ -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,
Expand Down
11 changes: 5 additions & 6 deletions apps/web/lib/actions/partners/create-commission.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -21,7 +22,6 @@ export const createCommissionAction = authActionClient
const { workspace } = ctx;

const {
programId,
partnerId,
linkId,
invoiceId,
Expand All @@ -32,23 +32,22 @@ 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,
},
}),
]);

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.`);
Expand Down
14 changes: 5 additions & 9 deletions apps/web/lib/actions/partners/create-discount.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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,
Expand Down
Loading