Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show application details in partner details sheet #2070

Merged
merged 1 commit into from
Feb 22, 2025
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
1 change: 1 addition & 0 deletions apps/web/app/api/partners/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const GET = withWorkspace(
pe.programId,
pe.partnerId,
pe.tenantId,
pe.applicationId,
pe.createdAt as enrollmentCreatedAt,
COALESCE(SUM(l.clicks), 0) as totalClicks,
COALESCE(SUM(l.leads), 0) as totalLeads,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw";
import { withWorkspace } from "@/lib/auth";
import { prisma } from "@dub/prisma";
import { NextResponse } from "next/server";

export const GET = withWorkspace(async ({ workspace, params }) => {
await getProgramOrThrow({
workspaceId: workspace.id,
programId: params.programId,
});

const application = await prisma.programApplication.findUnique({
where: { id: params.applicationId },
});

if (!application || application.programId !== params.programId) {
return NextResponse.json(
{ error: "Application not found" },
{ status: 404 },
);
}

return NextResponse.json(application);
});
3 changes: 3 additions & 0 deletions apps/web/lib/zod/schemas/partners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ export const EnrolledPartnerSchema = PartnerSchema.pick({
sales: z.number().default(0),
saleAmount: z.number().default(0),
earnings: z.number().default(0),
})
.extend({
applicationId: z.string().nullish(),
});

export const LeaderboardPartnerSchema = z.object({
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"js-cookie": "^3.0.5",
"json-2-csv": "^5.5.0",
"jszip": "^3.10.1",
"linkify-react": "^4.1.3",
"lucide-react": "^0.462.0",
"luxon": "^3.5.0",
"nanoid": "^5.0.1",
Expand Down
67 changes: 62 additions & 5 deletions apps/web/ui/partners/partner-details-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@ import {
COUNTRIES,
currencyFormatter,
DICEBEAR_AVATAR_URL,
fetcher,
getPrettyUrl,
nFormatter,
} from "@dub/utils";
import { formatPeriod } from "@dub/utils/src/functions/datetime";
import { ProgramApplication } from "@prisma/client";
import Linkify from "linkify-react";
import { ChevronLeft } from "lucide-react";
import { useAction } from "next-safe-action/hooks";
import Link from "next/link";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { toast } from "sonner";
import useSWRImmutable from "swr/immutable";
import { AnimatedEmptyState } from "../shared/animated-empty-state";
import { useCreatePayoutSheet } from "./create-payout-sheet";
import { PartnerLinkSelector } from "./partner-link-selector";
Expand Down Expand Up @@ -207,11 +211,7 @@ function PartnerDetailsSheetContent({
{tab === "links" && <PartnerLinks partner={partner} />}
</>
) : (
<div className="flex flex-col gap-6 text-sm text-neutral-500">
<h3 className="text-base font-semibold text-neutral-900">
About this partner
</h3>

<div className="grid gap-6 text-sm text-neutral-500">
<div>
<h4 className="font-semibold text-neutral-900">Description</h4>
<p className="mt-1.5">
Expand All @@ -222,6 +222,9 @@ function PartnerDetailsSheetContent({
)}
</p>
</div>
{partner.applicationId && (
<PartnerApplication applicationId={partner.applicationId} />
)}
</div>
)}
</div>
Expand Down Expand Up @@ -253,6 +256,60 @@ function PartnerDetailsSheetContent({
);
}

function PartnerApplication({ applicationId }: { applicationId: string }) {
const { id: workspaceId } = useWorkspace();
const { program } = useProgram();

const { data: application } = useSWRImmutable<ProgramApplication>(
program &&
workspaceId &&
`/api/programs/${program.id}/applications/${applicationId}?workspaceId=${workspaceId}`,
fetcher,
);

const fields = [
{
title: "Website / Social Media channels",
value: application?.website,
},
{
title: `How do you plan to promote ${program?.name}?`,
value: application?.proposal,
},
{
title: "Any additional questions or comments?",
value: application?.comments,
},
];

return (
<div className="grid gap-6">
{fields.map((field) => (
<div key={field.title}>
<h4 className="font-semibold text-neutral-900">{field.title}</h4>
<div className="mt-1.5">
{field.value || field.value === "" ? (
<Linkify
as="p"
options={{
target: "_blank",
rel: "noopener noreferrer nofollow",
className:
"underline underline-offset-4 text-neutral-400 hover:text-neutral-700",
}}
>
{field.value || "No response provided"}
</Linkify>
) : (
<div className="h-5 w-28 min-w-0 animate-pulse rounded-md bg-neutral-200" />
)}
</div>
</div>
))}
</div>
);
}

function PartnerApproval({
partner,
setIsOpen,
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading