diff --git a/src/app/(access)/login/page.tsx b/src/app/login/page.tsx
similarity index 82%
rename from src/app/(access)/login/page.tsx
rename to src/app/login/page.tsx
index e83dd4e..e247bd8 100644
--- a/src/app/(access)/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -1,4 +1,4 @@
-import { LoginForm } from "@/app/(access)/login/_components/LoginForm";
+import { LoginForm } from "@/app/login/_components/LoginForm";
import { loginAction } from "@/server/login";
import { Metadata } from "next";
import { fetchAuthenticatedUser } from "@/lib/session";
@@ -13,7 +13,7 @@ export const metadata: Metadata = {
export default async function LoginPage() {
const user = await fetchAuthenticatedUser();
const dbUser = await getUserById(user?.id || "");
- if (dbUser && dbUser.verifiedAt) {
+ if (dbUser && dbUser.verifiedAt && dbUser.checkoutAt) {
return redirect(authenticatedUrl);
}
return ;
diff --git a/src/app/(access)/signup/_components/SignUpForm.tsx b/src/app/signup/_components/SignUpForm.tsx
similarity index 93%
rename from src/app/(access)/signup/_components/SignUpForm.tsx
rename to src/app/signup/_components/SignUpForm.tsx
index 573058c..745e5ce 100644
--- a/src/app/(access)/signup/_components/SignUpForm.tsx
+++ b/src/app/signup/_components/SignUpForm.tsx
@@ -16,13 +16,14 @@ import { Loader } from "lucide-react";
import Image from "next/image";
import Link from "@/components/performance-link";
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { toast } from "sonner";
import { PasswordField } from "@/components/ui/password-input";
import { useRouter } from "@/hooks/use-performance-router";
import { useServerAction } from "zsa-react";
+import { useSearchParams } from "next/navigation";
export const SignUpForm = ({
signUp,
@@ -33,6 +34,16 @@ export const SignUpForm = ({
const [isSubmitting, setIsSubmitting] = useState(false);
const router = useRouter();
+ const searchParams = useSearchParams();
+
+ useEffect(() => {
+ if (searchParams.get("redirecterror") === "nouser") {
+ toast.error(
+ "You need to create an account or login before accessing the checkout page.",
+ );
+ }
+ }, [searchParams]);
+
const form = useForm>({
resolver: zodResolver(signUpSchema),
defaultValues: {
diff --git a/src/app/signup/checkout/_components/DemoCheckoutButton.tsx b/src/app/signup/checkout/_components/DemoCheckoutButton.tsx
new file mode 100644
index 0000000..9c00bad
--- /dev/null
+++ b/src/app/signup/checkout/_components/DemoCheckoutButton.tsx
@@ -0,0 +1,27 @@
+"use client";
+import { Button } from "@/components/ui/button";
+import { setUserCheckoutAction } from "@/server/billing";
+import React from "react";
+import { toast } from "sonner";
+import { useServerAction } from "zsa-react";
+
+export function DemoCheckoutButton() {
+ const { execute } = useServerAction(setUserCheckoutAction);
+ async function handleClick() {
+ try {
+ const [data, err] = await execute();
+ if (err) {
+ toast.error(err.message);
+ } else {
+ toast.success("Checkout Completed");
+ }
+ } catch (error) {
+ toast.error("Something Went Wrong. Failed to complete checkout.");
+ }
+ }
+ return (
+
+ );
+}
diff --git a/src/app/signup/checkout/page.tsx b/src/app/signup/checkout/page.tsx
new file mode 100644
index 0000000..8dbbe74
--- /dev/null
+++ b/src/app/signup/checkout/page.tsx
@@ -0,0 +1,35 @@
+import { Metadata } from "next";
+import { fetchAuthenticatedUser } from "@/lib/session";
+import { redirect } from "next/navigation";
+import { getUserById } from "@/data-access/users";
+import { authenticatedUrl } from "@/constants";
+import { Link } from "next-view-transitions";
+import { DemoCheckoutButton } from "./_components/DemoCheckoutButton";
+
+export const metadata: Metadata = {
+ title: "Sign Up",
+};
+
+export default async function CheckoutPage() {
+ const user = await fetchAuthenticatedUser();
+ const PADDLE_DOMAIN_APPROVED = false;
+ if (!user) return redirect("/signup?redirecterror=nouser");
+ const dbUser = await getUserById(user.id || "");
+ if (PADDLE_DOMAIN_APPROVED) {
+ if (
+ dbUser &&
+ dbUser.verifiedAt &&
+ dbUser.onboardedAt &&
+ dbUser.checkoutAt
+ ) {
+ return redirect(authenticatedUrl);
+ }
+ }
+
+ return (
+
+ Checkout Page here.... (Embedded checkout from paddle)
+
+
+ );
+}
diff --git a/src/app/(access)/onboarding/_components/OnboardingForm.tsx b/src/app/signup/onboarding/_components/OnboardingForm.tsx
similarity index 100%
rename from src/app/(access)/onboarding/_components/OnboardingForm.tsx
rename to src/app/signup/onboarding/_components/OnboardingForm.tsx
diff --git a/src/app/(access)/onboarding/page.tsx b/src/app/signup/onboarding/page.tsx
similarity index 74%
rename from src/app/(access)/onboarding/page.tsx
rename to src/app/signup/onboarding/page.tsx
index 245a2a2..456919e 100644
--- a/src/app/(access)/onboarding/page.tsx
+++ b/src/app/signup/onboarding/page.tsx
@@ -4,7 +4,7 @@ import { getUserById } from "@/data-access/users";
import { fetchAuthenticatedUser } from "@/lib/session";
import { redirect } from "next/navigation";
import { authenticatedUrl, unauthenticatedUrl } from "@/constants";
-import { OnboardingForm } from "@/app/(access)/onboarding/_components/OnboardingForm";
+import { OnboardingForm } from "@/app/signup/onboarding/_components/OnboardingForm";
export const metadata: Metadata = {
title: "Onboarding",
@@ -16,7 +16,10 @@ const OnboardingPage = async () => {
return redirect(unauthenticatedUrl);
}
const dbUser = await getUserById(user.id);
- if (dbUser?.verifiedAt && dbUser?.onboardedAt) {
+ if (
+ (dbUser?.verifiedAt && dbUser?.onboardedAt) ||
+ (dbUser?.checkoutAt && dbUser?.verifiedAt && dbUser?.onboardedAt)
+ ) {
return redirect(authenticatedUrl);
}
return ;
diff --git a/src/app/(access)/signup/page.tsx b/src/app/signup/page.tsx
similarity index 79%
rename from src/app/(access)/signup/page.tsx
rename to src/app/signup/page.tsx
index a95da08..dbb91bd 100644
--- a/src/app/(access)/signup/page.tsx
+++ b/src/app/signup/page.tsx
@@ -1,4 +1,4 @@
-import { SignUpForm } from "@/app/(access)/signup/_components/SignUpForm";
+import { SignUpForm } from "@/app/signup/_components/SignUpForm";
import { signUpAction } from "@/server/signup";
import { Metadata } from "next";
import { fetchAuthenticatedUser } from "@/lib/session";
@@ -13,7 +13,7 @@ export const metadata: Metadata = {
export default async function LoginPage() {
const user = await fetchAuthenticatedUser();
const dbUser = await getUserById(user?.id || "");
- if (dbUser && dbUser.verifiedAt && dbUser.onboardedAt) {
+ if (dbUser && dbUser.verifiedAt && dbUser.onboardedAt && dbUser.checkoutAt) {
return redirect(authenticatedUrl);
}
return ;
diff --git a/src/app/(access)/verify-email/_components/ResendVerifyEmailButton.tsx b/src/app/signup/verify-email/_components/ResendVerifyEmailButton.tsx
similarity index 100%
rename from src/app/(access)/verify-email/_components/ResendVerifyEmailButton.tsx
rename to src/app/signup/verify-email/_components/ResendVerifyEmailButton.tsx
diff --git a/src/app/(access)/verify-email/_components/VerifyEmailForm.tsx b/src/app/signup/verify-email/_components/VerifyEmailForm.tsx
similarity index 100%
rename from src/app/(access)/verify-email/_components/VerifyEmailForm.tsx
rename to src/app/signup/verify-email/_components/VerifyEmailForm.tsx
diff --git a/src/app/(access)/verify-email/page.tsx b/src/app/signup/verify-email/page.tsx
similarity index 100%
rename from src/app/(access)/verify-email/page.tsx
rename to src/app/signup/verify-email/page.tsx
diff --git a/src/constants.ts b/src/constants.ts
index ba6bc4a..f42f44b 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,5 +1,6 @@
-export const afterSignUpUrl = "/verify-email";
-export const afterVerifyUrl = "/onboarding";
+export const afterSignUpUrl = "/signup/verify-email";
+export const afterVerifyUrl = "/signup/checkout";
+export const afterCheckoutUrl = "/signup/onboarding";
export const authenticatedUrl = "/app/home";
export const unauthenticatedUrl = "/login";
diff --git a/src/server/billing.ts b/src/server/billing.ts
new file mode 100644
index 0000000..9ba1a61
--- /dev/null
+++ b/src/server/billing.ts
@@ -0,0 +1,19 @@
+"use server";
+import { createServerAction } from "zsa";
+import { getUserById, updateUser } from "@/data-access/users";
+import { redirect } from "next/navigation";
+import { authenticatedUrl } from "@/constants";
+import { fetchAuthenticatedUser } from "@/lib/session";
+import { authenticatedAction } from "@/lib/zsa";
+
+export const setUserCheckoutAction = authenticatedAction
+ .createServerAction()
+ .handler(async ({ input, ctx }) => {
+ const { user } = ctx;
+ const updatedUser = await updateUser(user.id, {
+ checkoutAt: new Date(),
+ updatedAt: new Date(),
+ });
+ if (!updatedUser) throw new Error("Couldn't set user as checked out");
+ return redirect(authenticatedUrl);
+ });