Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 10 additions & 3 deletions apps/web/app/(ee)/api/cron/cleanup/e2e-tests/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { deleteDiscountCodes } from "@/lib/api/discounts/delete-discount-code";
import { markDomainAsDeleted } from "@/lib/api/domains/mark-domain-deleted";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { bulkDeleteLinks } from "@/lib/api/links/bulk-delete-links";
Expand Down Expand Up @@ -100,12 +99,20 @@ export async function POST(req: Request) {

// Delete the links
if (links.length > 0) {
await deleteDiscountCodes(links.flatMap((link) => link.discountCode));
const linkIds = links.map((link) => link.id);

await prisma.discountCode.deleteMany({
where: {
linkId: {
in: linkIds,
},
},
});

await prisma.link.deleteMany({
where: {
id: {
in: links.map((link) => link.id),
in: linkIds,
},
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { DubApiError } from "@/lib/api/errors";
import { getProgramEnrollmentOrThrow } from "@/lib/api/programs/get-program-enrollment-or-throw";
import { withPartnerProfile } from "@/lib/auth/partner";
import {
activityLogSchema,
getActivityLogsQuerySchema,
} from "@/lib/zod/schemas/activity-log";
import { prisma } from "@dub/prisma";
import { NextResponse } from "next/server";
import * as z from "zod/v4";

export const GET = withPartnerProfile(
async ({ partner, params, searchParams }) => {
const { resourceType, resourceId, action } =
getActivityLogsQuerySchema.parse(searchParams);

// Limit to referral for now
if (resourceType !== "referral") {
throw new DubApiError({
code: "bad_request",
message: "Resource type must be referral.",
});
}

const programEnrollment = await getProgramEnrollmentOrThrow({
partnerId: partner.id,
programId: params.programId,
include: {},
});

// Check if the resource is a referral and belongs to the program and partner
if (resourceType === "referral") {
const referral = await prisma.partnerReferral.findUnique({
where: {
id: resourceId,
programId: programEnrollment.programId,
partnerId: partner.id,
},
select: {
id: true,
},
});

if (!referral) {
throw new DubApiError({
code: "not_found",
message: "Referral not found.",
});
}
}

const activityLogs = await prisma.activityLog.findMany({
where: {
programId: programEnrollment.programId,
resourceType,
resourceId,
action,
},
orderBy: {
createdAt: "desc",
},
take: 100,
});

return NextResponse.json(z.array(activityLogSchema).parse(activityLogs));
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -315,61 +315,59 @@ export function Form() {

{defaultRewardType === "sale" && (
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
{PAYOUT_MODELS.map(
({ key, label, description, mostCommon }) => {
const isSelected = key === type;
{PAYOUT_MODELS.map(({ key, label, description, mostCommon }) => {
const isSelected = key === type;

return (
<div
key={key}
return (
<div
key={key}
className={cn(
"flex flex-col items-center",
mostCommon &&
"rounded-md border border-neutral-200 bg-neutral-100",
)}
>
<label
className={cn(
"flex flex-col items-center",
mostCommon &&
"rounded-md border border-neutral-200 bg-neutral-100",
"relative flex w-full cursor-pointer items-start gap-0.5 rounded-md border border-neutral-200 bg-white p-3 text-neutral-600 hover:bg-neutral-50",
"transition-all duration-150",
mostCommon && "border-transparent shadow-sm",
isSelected &&
"border-black bg-neutral-50 text-neutral-900 ring-1 ring-black",
)}
>
<label
<input
type="radio"
value={key}
className="hidden"
checked={isSelected}
onChange={() =>
setValue("type", key, { shouldDirty: true })
}
/>
<div className="flex grow flex-col text-sm">
<span className="text-sm font-semibold text-neutral-900">
{label}
</span>
<span className="text-sm font-normal text-neutral-600">
{description}
</span>
</div>
<CircleCheckFill
className={cn(
"relative flex w-full cursor-pointer items-start gap-0.5 rounded-md border border-neutral-200 bg-white p-3 text-neutral-600 hover:bg-neutral-50",
"transition-all duration-150",
mostCommon && "border-transparent shadow-sm",
isSelected &&
"border-black bg-neutral-50 text-neutral-900 ring-1 ring-black",
"-mr-px -mt-px flex size-4 scale-75 items-center justify-center rounded-full opacity-0 transition-[transform,opacity] duration-150",
isSelected && "scale-100 opacity-100",
)}
>
<input
type="radio"
value={key}
className="hidden"
checked={isSelected}
onChange={() =>
setValue("type", key, { shouldDirty: true })
}
/>
<div className="flex grow flex-col text-sm">
<span className="text-sm font-semibold text-neutral-900">
{label}
</span>
<span className="text-sm font-normal text-neutral-600">
{description}
</span>
</div>
<CircleCheckFill
className={cn(
"-mr-px -mt-px flex size-4 scale-75 items-center justify-center rounded-full opacity-0 transition-[transform,opacity] duration-150",
isSelected && "scale-100 opacity-100",
)}
/>
</label>
{mostCommon && (
<span className="py-0.5 text-xs font-medium text-neutral-500">
Most common
</span>
)}
</div>
);
},
)}
/>
</label>
{mostCommon && (
<span className="py-0.5 text-xs font-medium text-neutral-500">
Most common
</span>
)}
</div>
);
})}
</div>
)}

Expand Down
Loading