diff --git a/.env.example b/.env.example index 7da56a2e3..a1faef3f0 100644 --- a/.env.example +++ b/.env.example @@ -16,6 +16,11 @@ NEXT_PUBLIC_WEBAPP_URL='http://localhost:3000' NEXTAUTH_SECRET='lorem ipsum sit dolor random string for encryption this could literally be anything' NEXTAUTH_URL='http://localhost:3000' +# SIGNING +CERT_FILE_PATH= +CERT_PASSPHRASE= +CERT_FILE_ENCODING= + # MAIL (NODEMAILER) # SENDGRID # Get a Sendgrid Api key here: https://signup.sendgrid.com @@ -37,6 +42,13 @@ SMTP_MAIL_PASSWORD='' # Sender for signing requests and completion mails. MAIL_FROM='documenso@localhost.com' +# STRIPE +STRIPE_API_KEY= +STRIPE_WEBHOOK_SECRET= +NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID= +NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID= + #FEATURE FLAGS # Allow users to register via the /signup page. Otherwise they will be redirect to the home page. -ALLOW_SIGNUP=true +NEXT_PUBLIC_ALLOW_SIGNUP=true +NEXT_PUBLIC_ALLOW_SUBSCRIPTIONS=true \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 17ceca23e..36b7f475c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,7 +13,13 @@ "editor.codeActionsOnSave": { "source.removeUnusedImports": false }, - "typescript.tsdk": "node_modules\\typescript\\lib", - "spellright.language": ["de"], - "spellright.documentTypes": ["markdown", "latex", "plaintext"] + "typescript.tsdk": "node_modules/typescript/lib", + "spellright.language": [ + "de" + ], + "spellright.documentTypes": [ + "markdown", + "latex", + "plaintext" + ] } diff --git a/README.md b/README.md index c70655905..26316054f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ -

+

+

+ We are LIVE on Product Hunt. Come say hi.. +

+Documenso - The Open Source DocuSign Alternative. | Product Hunt +
+
+

- Documenso Logo + Documenso Logo

Open Source Signing Infrastructure

diff --git a/apps/web/components/billing-plans.tsx b/apps/web/components/billing-plans.tsx new file mode 100644 index 000000000..419478cfd --- /dev/null +++ b/apps/web/components/billing-plans.tsx @@ -0,0 +1,70 @@ +import { useState } from "react"; +import { classNames } from "@documenso/lib"; +import { STRIPE_PLANS, fetchCheckoutSession, useSubscription } from "@documenso/lib/stripe"; +import { Button } from "@documenso/ui"; +import { Switch } from "@headlessui/react"; + +export const BillingPlans = () => { + const { subscription, isLoading } = useSubscription(); + const [isAnnual, setIsAnnual] = useState(false); + + return ( +
+ {!subscription && + STRIPE_PLANS.map((plan) => ( +
+

{plan.name}

+ +
+ + + + + Annual billing{" "} + (Save $60) + + +
+ +

+ ${(isAnnual ? plan.prices.yearly.price : plan.prices.monthly.price).toFixed(2)}{" "} + {isAnnual ? "/yr" : "/mo"} +

+ +

+ All you need for easy signing.

Includes everthing we build this year. +

+
+ +
+
+ ))} +
+ ); +}; diff --git a/apps/web/components/billing-warning.tsx b/apps/web/components/billing-warning.tsx new file mode 100644 index 000000000..bf68c44f2 --- /dev/null +++ b/apps/web/components/billing-warning.tsx @@ -0,0 +1,51 @@ +import { useSubscription } from "@documenso/lib/stripe" +import { PaperAirplaneIcon } from "@heroicons/react/24/outline"; +import { SubscriptionStatus } from '@prisma/client' +import Link from "next/link"; + +export const BillingWarning = () => { + const { subscription } = useSubscription(); + + return ( + <> + {subscription?.status === SubscriptionStatus.PAST_DUE && ( +
+
+
+
+ +
+

+ Your subscription is past due.{" "} + + Please update your payment information to avoid any service interruptions. + +

+
+
+
+ )} + + {subscription?.status === SubscriptionStatus.INACTIVE && ( +
+
+
+
+ +
+

+ Your subscription is inactive. You can continue to view and edit your documents, + but you will not be able to send them or create new ones.{" "} + + You can update your payment information here + +

+
+
+
+ )} + + ) +} \ No newline at end of file diff --git a/apps/web/components/editor/pdf-signer.tsx b/apps/web/components/editor/pdf-signer.tsx index a4a4cd2c6..a3bb08389 100644 --- a/apps/web/components/editor/pdf-signer.tsx +++ b/apps/web/components/editor/pdf-signer.tsx @@ -70,10 +70,12 @@ export default function PDFSigner(props: any) {
-
- +
+ +

Documenso

-
+ +

{props.document.User.name ? `${props.document.User.name} (${props.document.User.email})` diff --git a/apps/web/components/layout.tsx b/apps/web/components/layout.tsx index 408472633..aa0fad8dc 100644 --- a/apps/web/components/layout.tsx +++ b/apps/web/components/layout.tsx @@ -1,7 +1,12 @@ import { useEffect } from "react"; +import Link from "next/link"; import { useRouter } from "next/router"; import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib/constants"; +import { useSubscription } from "@documenso/lib/stripe"; +import { BillingWarning } from "./billing-warning"; import Navigation from "./navigation"; +import { PaperAirplaneIcon } from "@heroicons/react/24/outline"; +import { SubscriptionStatus } from "@prisma/client"; import { useSession } from "next-auth/react"; function useRedirectToLoginIfUnauthenticated() { @@ -30,11 +35,16 @@ function useRedirectToLoginIfUnauthenticated() { export default function Layout({ children }: any) { useRedirectToLoginIfUnauthenticated(); + const { subscription } = useSubscription(); + return ( <>

- + +
+ +
{children}
diff --git a/apps/web/components/login.tsx b/apps/web/components/login.tsx index 2d9262c2a..4f086a8e1 100644 --- a/apps/web/components/login.tsx +++ b/apps/web/components/login.tsx @@ -69,7 +69,7 @@ export default function Login(props: any) {
- +

Sign in to your account

@@ -111,7 +111,7 @@ export default function Login(props: any) {
@@ -123,7 +123,7 @@ export default function Login(props: any) { className="group relative flex w-full"> @@ -141,7 +141,9 @@ export default function Login(props: any) { {props.allowSignup ? (

Are you new here?{" "} - + Create a new Account

@@ -151,7 +153,7 @@ export default function Login(props: any) { - Hosted Documenso will be available soon™ + Hosted Documenso is here!

)} diff --git a/apps/web/components/logo.tsx b/apps/web/components/logo.tsx index c1504e081..64d61bc76 100644 --- a/apps/web/components/logo.tsx +++ b/apps/web/components/logo.tsx @@ -4,16 +4,77 @@ import { classNames } from "@documenso/lib"; export default function Logo(props: any) { return ( <> - - - - - - - - + + + + + + + + + + + + + + + + + + + + ); } diff --git a/apps/web/components/navigation.tsx b/apps/web/components/navigation.tsx index d0143a41c..c09d5b912 100644 --- a/apps/web/components/navigation.tsx +++ b/apps/web/components/navigation.tsx @@ -112,9 +112,13 @@ export default function TopNavigation() {
-
- -
+ + +

Documenso

+ +
{navigation.map((item) => ( { getUser().then((res: any) => { res.json().then((j: any) => { @@ -48,6 +60,7 @@ export default function Setttings() { }); const [savingTimeout, setSavingTimeout] = useState(); + const [password, setPassword] = useState(""); function handleNameChange(e: ChangeEvent): void { let u = { ...user }; u.name = e.target.value; @@ -158,22 +171,110 @@ export default function Setttings() {
+ + +
+