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

Program lander #1703

Merged
merged 111 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
4b392f7
Program Lander page
steven-tey Nov 7, 2024
9639b92
fix mutate in deposit funds modal
steven-tey Nov 7, 2024
3434e71
swap
steven-tey Nov 7, 2024
a5f3b9a
Merge branch 'payouts' into program-lander
steven-tey Nov 7, 2024
a82c0f8
Merge branch 'payouts' into program-lander
steven-tey Nov 12, 2024
63ee921
Merge branch 'payouts' into program-lander
TWilson023 Nov 12, 2024
942d3b3
Add program lander page
TWilson023 Nov 12, 2024
c4fbc0e
Update page.tsx
TWilson023 Nov 12, 2024
c4ed096
Add footer
TWilson023 Nov 12, 2024
6114915
Update page.tsx
TWilson023 Nov 12, 2024
f7b8e14
Merge branch 'main' into program-lander
steven-tey Nov 12, 2024
3de5e3a
Merge branch 'main' into program-lander
steven-tey Nov 13, 2024
68bd309
Merge branch 'fix-track-sale' into program-lander
steven-tey Nov 13, 2024
2be154c
Merge branch 'main' into program-lander
devkiran Nov 13, 2024
0029678
Just use regular prisma to avoid downgrading adapter-planetscale
TWilson023 Nov 13, 2024
ba91f2e
Pull out common layout + make header sticky
TWilson023 Nov 13, 2024
58314ec
Separate details grid into component
TWilson023 Nov 13, 2024
d6e99e5
Add application form
TWilson023 Nov 13, 2024
f364f05
Add success page
TWilson023 Nov 13, 2024
1a8df76
Add login button to header
TWilson023 Nov 13, 2024
7ab51e1
Little fixes
TWilson023 Nov 13, 2024
87f9b05
Update cta-button.tsx
TWilson023 Nov 13, 2024
86ac17f
Merge branch 'main' into program-lander
steven-tey Nov 13, 2024
d6ce42d
Merge branch 'partner-invite' into program-lander
steven-tey Nov 13, 2024
447ab9a
landerData
steven-tey Nov 13, 2024
a6a2b1a
update partner status
steven-tey Nov 14, 2024
e4fdba0
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
60c6c31
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
c0b4e42
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
f2ac473
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
4079b86
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
d5bb995
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
0966cc7
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
dbc6244
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
15a14b4
Merge branch 'partner-invite' into program-lander
TWilson023 Nov 14, 2024
b5c5870
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
446db53
Automatically associate applications with programs
TWilson023 Nov 14, 2024
cebefd5
Fix layout shift
TWilson023 Nov 14, 2024
b15311f
Autofill form with partner/user details
TWilson023 Nov 14, 2024
2838f01
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
d8e3c2f
Add entrance animations
TWilson023 Nov 14, 2024
cfaec6b
Update FilesBlock.tsx
TWilson023 Nov 14, 2024
a7f54bf
Add image size
TWilson023 Nov 14, 2024
436f332
Add setError
TWilson023 Nov 14, 2024
2c7bc51
Update create-program-application.ts
TWilson023 Nov 14, 2024
1c40edc
Merge branch 'partner-invite' into program-lander
steven-tey Nov 14, 2024
2dca224
Merge branch 'partner-invite' into program-lander
steven-tey Nov 15, 2024
06e9e87
Merge branch 'partner-invite' into program-lander
steven-tey Nov 15, 2024
f25e5dd
Merge branch 'partner-invite' into program-lander
steven-tey Nov 15, 2024
ed0cfb8
Save applications and create enrollments when logged in
TWilson023 Nov 15, 2024
53d6c3b
Update complete-program-applications.ts
TWilson023 Nov 15, 2024
46110a3
Merge branch 'partner-invite' into program-lander
TWilson023 Nov 15, 2024
8c0abb5
Merge branch 'partner-invite' into program-lander
steven-tey Nov 15, 2024
1ee3137
Merge branch 'partner-invite' into program-lander
steven-tey Nov 15, 2024
411f4d9
Merge branch 'partner-invite' into program-lander
steven-tey Nov 16, 2024
b05a9f9
Merge branch 'partner-invite' into program-lander
steven-tey Nov 16, 2024
d31faa1
Merge branch 'main' into program-lander
steven-tey Nov 16, 2024
9ad426e
move programEnrollment to waitUntil
steven-tey Nov 16, 2024
30ccacf
fix schema
steven-tey Nov 16, 2024
3d9de22
Merge branch 'main' into program-lander
devkiran Nov 18, 2024
0b0e2ca
fix build
devkiran Nov 18, 2024
f79c779
update createProgramApplicationSchema
devkiran Nov 19, 2024
b57710c
update createProgramApplicationSchema
devkiran Nov 19, 2024
a0f46a0
Merge branch 'main' into program-lander
devkiran Nov 19, 2024
6b43f04
remove unused query
devkiran Nov 19, 2024
385d5b4
update createProgramApplicationAction
devkiran Nov 19, 2024
4c83fe7
fix Check if ProgramEnrollment already exists
devkiran Nov 19, 2024
8b622db
format
devkiran Nov 19, 2024
eeb2f93
run prettier
devkiran Nov 19, 2024
14f9bd9
fix middleware
devkiran Nov 19, 2024
6eb1c32
Merge branch 'main' into program-lander
devkiran Nov 19, 2024
82c7a46
Merge branch 'main' into program-lander
steven-tey Nov 19, 2024
6092810
Merge branch 'main' into program-lander
steven-tey Nov 19, 2024
b3ca0ce
Merge branch 'main' into program-lander
devkiran Nov 20, 2024
29e7adc
Merge branch 'main' into program-lander
devkiran Nov 20, 2024
da9320f
Merge branch 'program-lander' of https://github.com/dubinc/dub into p…
devkiran Nov 20, 2024
0541e91
Update programs.ts
devkiran Nov 20, 2024
4583499
Merge branch 'main' into program-lander
steven-tey Nov 20, 2024
2bd118f
bump next-safe-action
devkiran Nov 20, 2024
812fdbc
update approvePartnerAction
devkiran Nov 20, 2024
093bfcb
update serverError usage
devkiran Nov 20, 2024
f209b9e
update createDotsFlowAction
devkiran Nov 20, 2024
b485b0c
update updatePartnerProfileAction
devkiran Nov 20, 2024
92daae9
update rejectPartnerAction
devkiran Nov 20, 2024
637d74e
Merge branch 'main' into improve-server-actions
steven-tey Nov 20, 2024
8574030
Merge branch 'main' into improve-server-actions
steven-tey Nov 20, 2024
0ad917a
Merge branch 'main' into program-lander
steven-tey Nov 20, 2024
dc34f79
Merge branch 'program-lander' into improve-server-actions
steven-tey Nov 20, 2024
37f74a8
Merge pull request #1737 from dubinc/improve-server-actions
steven-tey Nov 20, 2024
2f47d27
rearrange
steven-tey Nov 20, 2024
503eebd
Merge branch 'main' into program-lander
steven-tey Nov 20, 2024
5439203
Update backfill-sales.ts
steven-tey Nov 20, 2024
6f41c5b
Merge branch 'main' into program-lander
steven-tey Nov 20, 2024
ee5451e
Merge branch 'main' into program-lander
steven-tey Nov 21, 2024
0d032ed
move to index
steven-tey Nov 21, 2024
b1951ac
plan → proposal
steven-tey Nov 21, 2024
d5df567
fix meta tags, duration display
steven-tey Nov 21, 2024
e966bdc
accordion variant
steven-tey Nov 21, 2024
8447868
use brand colors for form inputs
steven-tey Nov 21, 2024
af92548
make button disabled classes important
steven-tey Nov 21, 2024
d5ee18f
remove application status
steven-tey Nov 21, 2024
10a7e12
improve program description
steven-tey Nov 21, 2024
482694a
Update create-program-application.ts
steven-tey Nov 21, 2024
fe83c12
getProgram cache, useSession instead of getSession
steven-tey Nov 21, 2024
248dd7a
Merge branch 'main' into program-lander
steven-tey Nov 21, 2024
5d4ade4
Use `enabled:` instead of `!`
TWilson023 Nov 21, 2024
64e6942
Merge branch 'main' into program-lander
steven-tey Nov 21, 2024
011c64f
Merge branch 'main' into program-lander
steven-tey Nov 21, 2024
f3f8d9f
Merge pull request #1742 from dubinc/important-alternative
steven-tey Nov 21, 2024
7ba7e7b
Update header.tsx
devkiran Nov 21, 2024
40f89d7
improve server action
devkiran Nov 21, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function InvitePartnerSheetContent({ setIsOpen }: InvitePartnerSheetProps) {
setIsOpen(false);
},
onError({ error }) {
toast.error(error.serverError?.serverError);
toast.error(error.serverError);
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default function IntegrationPageClient({
window.location.href = data.url;
},
onError: ({ error }) => {
toast.error(error.serverError?.serverError);
toast.error(error.serverError);
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function OAuthAppManagePageClient({ appId }: { appId: string }) {
toast.success("New client secret generated.");
},
onError: ({ error }) => {
toast.error(error.serverError?.serverError);
toast.error(error.serverError);
},
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const ComplianceButton = () => {
});
},
onError({ error }) {
toast.error(error.serverError?.serverError);
toast.error(error.serverError);
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function GenerateButton() {
toast.success("Referral link generated.");
},
onError: ({ error }) => {
toast.error(error.serverError?.serverError);
toast.error(error.serverError);
},
},
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
"use client";

import { createProgramApplicationAction } from "@/lib/actions/partners/create-program-application";
import { Button, useMediaQuery } from "@dub/ui";
import { cn } from "@dub/utils";
import { Program } from "@prisma/client";
import { useSession } from "next-auth/react";
import { useAction } from "next-safe-action/hooks";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import ReactTextareaAutosize from "react-textarea-autosize";
import { toast } from "sonner";

type FormData = {
name: string;
email: string;
website?: string;
proposal: string;
comments?: string;
};

export function ProgramApplicationForm({
program,
}: {
program: Pick<Program, "id" | "slug" | "name">;
}) {
const { isMobile } = useMediaQuery();
const router = useRouter();
const { data: session } = useSession();

const {
register,
handleSubmit,
setError,
setValue,
formState: { errors, isSubmitting, isSubmitSuccessful },
} = useForm<FormData>();

useEffect(() => {
if (session?.user) {
setValue("name", session.user.name ?? "");
setValue("email", session.user.email ?? "");
}
}, [session?.user, setValue]);

const { executeAsync, isExecuting } = useAction(
createProgramApplicationAction,
{
async onSuccess({ data }) {
if (!data) {
toast.error("Failed to submit application. Please try again.");
return;
}

toast.success("Your application submitted successfully.");

const { programApplicationId, programEnrollmentId } = data;

const searchParams = new URLSearchParams({
applicationId: programApplicationId,
...(programEnrollmentId && {
enrollmentId: programEnrollmentId,
}),
});

router.push(
`/apply/${program.slug}/application/success?${searchParams.toString()}`,
);
},
onError({ error }) {
toast.error(error.serverError);

setError("root.serverError", {
message: error.serverError,
});
},
},
);

const isLoading = isSubmitting || isSubmitSuccessful || isExecuting;

return (
<form
onSubmit={handleSubmit(async (data) => {
await executeAsync({
...data,
programId: program.id,
});
})}
className="flex flex-col gap-6"
>
<label>
<span className="text-sm font-medium text-gray-800">Name</span>
<input
type="text"
className={cn(
"mt-2 block w-full rounded-md focus:outline-none sm:text-sm",
errors.name
? "border-red-400 pr-10 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500"
: "border-gray-300 text-gray-900 placeholder-gray-400 focus:border-[var(--brand)] focus:ring-[var(--brand)]",
)}
placeholder="Acme, Inc."
autoFocus={!isMobile}
{...register("name", {
required: true,
})}
/>
</label>

<label>
<span className="text-sm font-medium text-gray-800">Email</span>
<input
type="email"
className={cn(
"mt-2 block w-full rounded-md focus:outline-none sm:text-sm",
errors.email
? "border-red-400 pr-10 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500"
: "border-gray-300 text-gray-900 placeholder-gray-400 focus:border-[var(--brand)] focus:ring-[var(--brand)]",
)}
placeholder="panic@thedis.co"
{...register("email", {
required: true,
})}
/>
</label>

<label>
<span className="text-sm font-medium text-gray-800">
Website / Social media channel
<span className="font-normal text-neutral-500"> (optional)</span>
</span>
<input
type="text"
className={cn(
"mt-2 block w-full rounded-md focus:outline-none sm:text-sm",
errors.website
? "border-red-400 pr-10 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500"
: "border-gray-300 text-gray-900 placeholder-gray-400 focus:border-[var(--brand)] focus:ring-[var(--brand)]",
)}
placeholder="https://example.com"
{...register("website")}
/>
</label>

<label>
<span className="text-sm font-medium text-gray-800">
How do you plan to promote {program.name}?
</span>
<ReactTextareaAutosize
className={cn(
"mt-2 block max-h-48 min-h-12 w-full rounded-md focus:outline-none sm:text-sm",
errors.proposal
? "border-red-400 pr-10 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500"
: "border-gray-300 text-gray-900 placeholder-gray-400 focus:border-[var(--brand)] focus:ring-[var(--brand)]",
)}
placeholder=""
minRows={3}
{...register("proposal", { required: true })}
/>
</label>

<label>
<span className="text-sm font-medium text-gray-800">
Any additional questions or comments?
<span className="font-normal text-neutral-500"> (optional)</span>
</span>
<ReactTextareaAutosize
className={cn(
"mt-2 block max-h-48 min-h-12 w-full rounded-md focus:outline-none sm:text-sm",
errors.comments
? "border-red-400 pr-10 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500"
: "border-gray-300 text-gray-900 placeholder-gray-400 focus:border-[var(--brand)] focus:ring-[var(--brand)]",
)}
placeholder=""
minRows={3}
{...register("comments")}
/>
</label>

<Button
text="Submit application"
className="mt-4 enabled:border-[var(--brand)] enabled:bg-[var(--brand)] enabled:hover:bg-[var(--brand)] enabled:hover:ring-[var(--brand-ring)]"
loading={isLoading}
/>
</form>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { getProgram } from "@/lib/fetchers/get-program";
import { notFound } from "next/navigation";
import { CSSProperties } from "react";
import { DetailsGrid } from "../details-grid";
import { Header } from "../header";
import { ProgramApplicationForm } from "./form";

export default async function ApplicationPage({
params: { programSlug },
}: {
params: { programSlug: string };
}) {
const program = await getProgram({ slug: programSlug });

if (!program) {
notFound();
}

return (
<div
className="relative"
style={
{
"--brand": program.brandColor || "#3b82f6",
"--brand-ring": "rgb(from var(--brand) r g b / 0.2)",
} as CSSProperties
}
>
<Header
program={{
logo: program.logo,
wordmark: program.wordmark,
}}
slug={programSlug}
showApply={false}
/>
<div className="p-6">
{/* Hero section */}
<div className="grid grid-cols-1 gap-5 sm:pt-20">
<p className="font-mono text-xs font-medium uppercase text-[var(--brand)]">
Affiliate Program
</p>
<h1 className="text-4xl font-semibold">{program.name} application</h1>
<p className="text-base text-neutral-700">
Submit your application to join the affiliate program.
</p>
</div>

{/* Program details grid */}
<DetailsGrid program={program} className="mt-10" />

{/* Application form */}
<div className="mt-10">
<ProgramApplicationForm
program={{ id: program.id, name: program.name, slug: program.slug }}
/>
</div>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"use client";

import { Button } from "@dub/ui";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";

export function CTAButtons() {
const router = useRouter();
const { data: session, status } = useSession();

return (
<>
<Button
type="button"
text={
status === "authenticated"
? "Continue to Dub Partners"
: "Create your Dub Partners account"
}
className="border-[var(--brand)] bg-[var(--brand)] hover:bg-[var(--brand)] hover:ring-[var(--brand-ring)]"
onClick={() =>
router.push(status === "authenticated" ? "/" : "/register")
}
/>
{status === "unauthenticated" && (
<Button
type="button"
variant="secondary"
text="Log in to Dub Partners"
onClick={() => router.push("/login")}
/>
)}
</>
);
}
Loading
Loading