diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 60b385403..3471f4f88 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,7 +10,13 @@ "ghcr.io/devcontainers/features/node:1": {} }, "onCreateCommand": "./.devcontainer/on-create.sh", - "forwardPorts": [3000, 54320, 9000, 2500, 1100], + "forwardPorts": [ + 3000, + 54320, + 9000, + 2500, + 1100 + ], "customizations": { "vscode": { "extensions": [ @@ -25,8 +31,8 @@ "GitHub.copilot", "GitHub.vscode-pull-request-github", "Prisma.prisma", - "VisualStudioExptTeam.vscodeintellicode", + "VisualStudioExptTeam.vscodeintellicode" ] } } -} +} \ No newline at end of file diff --git a/README.md b/README.md index 6d2fab334..cdb687264 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ ->We are nominated for a Product Hunt Gold Kitty ๐Ÿ˜บโœจ and appreciate any support: https://documen.so/kitty +> ๐Ÿšจ It is Launch Week #2 - Day 1: We launches teams ๐ŸŽ‰ https://documen.so/day1 Documenso Logo @@ -107,7 +107,7 @@ Contact us if you are interested in our Enterprise plan for large organizations To run Documenso locally, you will need -- Node.js +- Node.js (v18 or above) - Postgres SQL Database - Docker (optional) diff --git a/apps/marketing/content/blog/early-adopters.mdx b/apps/marketing/content/blog/early-adopters.mdx index 2ff7ae1f6..ddd779fbc 100644 --- a/apps/marketing/content/blog/early-adopters.mdx +++ b/apps/marketing/content/blog/early-adopters.mdx @@ -24,6 +24,8 @@ tags: +> ๐Ÿ”” UPDATE: We launched teams and the early adopters plan will be replaced by the new teams pricing as soon as all availible early adopters seats are filled. + ## Community-Driven Development As we ramp up hiring and development speed for Documenso, I want to discuss how we plan to build its core version. diff --git a/apps/marketing/content/blog/launch-week-2-day-1.mdx b/apps/marketing/content/blog/launch-week-2-day-1.mdx new file mode 100644 index 000000000..2799baafe --- /dev/null +++ b/apps/marketing/content/blog/launch-week-2-day-1.mdx @@ -0,0 +1,64 @@ +--- +title: Launch Week II - Day 1 - Teams +description: Teams for Documenso are here. And they come free for early adopters! +authorName: 'Timur Ercan' +authorImage: '/blog/blog-author-timur.jpeg' +authorRole: 'Co-Founder' +date: 2024-02-26 +tags: + - Launch Week + - Teams + - Early Adopter Perks +--- + + + +> TLDR; Docucmenso now supports teams that share documents, templates and a team mail address. Early Adopter get UNLIMITED1 Users. + +## Kicking off Launch Week II - "Connected" + +The day has come! Roughly 5 months after kicked off our first launch week with open sourcing our design and Malfunction Mania, Launch Week #2 is here ๐ŸŽ‰ This Launch Week's theme is "connected", since this is all about connecting humans, machines and documents. + +Working with documents and getting that signature is a team sport. This is why we are kicking it off today with a very long-awaited feature: Documenso now supports teams! + +## Introducing Teams for Documenso + +You can now create teams next to your personal account: Simply invite your colleagues, and you can include everyone you like in working with your documents. With teams, you can: + +- Send unlimited signature requests with unlimited recipients +- Create, view, edit and sign documents owned by the team +- Define a dedicated team email, to receive signing requests into a team inbox for the owner to sign +- Manage team roles: Member (Create+Edit), Managers (+Manage Team Members), Owner (+Transfer Team +Delete Team + Sign Documents sent to team email) + +## Pricing + +Together with Teams, we are announcing the new teams pricing: + +- $10 per seat per month +- 5 seats minimum +- You can add seats dynamically as needed + +This pricing will take effect, as soon as the early adopter seats run out. Want to check out teams: [https://documen.so/teams](https://documen.so/teams). + +## Early Adopter Perks + +There is one more point on pricing I have been looking forward to for a long time: + +All early adopter plans now include **UNLIMITED teams and users**1 . We appreciate your support so far very much, and I'm happy to announce this first of more early adopter perks to come. We have roughly 48 early adopter plans left, so if you plan to onboard your team, now is a great time to [grab your early adopter seat.](https://documen.so/claim-early-adopters-plan) + +We are eager to hear from all teams users how you like this addition and what we can add to make it even better. Connect with us on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments! We're always here, and we would love to hear from you :) + +> ๐Ÿšจ We need you help to help us to make this the biggest launch week yet: Support us on Twitter or anywhere to spread awareness for open signing! The best posts will receive merch codes ๐Ÿ‘€ + +Best from Hamburg\ +Timur + +\ +[1] Within reason. If you are unsure what that means, feel free to contact hi@documenso.com and ask for clarification if it's more than 100. diff --git a/apps/marketing/content/blog/launch-week-2-day-2.mdx b/apps/marketing/content/blog/launch-week-2-day-2.mdx new file mode 100644 index 000000000..3a67977ec --- /dev/null +++ b/apps/marketing/content/blog/launch-week-2-day-2.mdx @@ -0,0 +1,76 @@ +--- +title: Launch Week II - Day 2 - Templates +description: Templates help you prepare regular documents faster. And you can share them with your team! +authorName: 'Timur Ercan' +authorImage: '/blog/blog-author-timur.jpeg' +authorRole: 'Co-Founder' +date: 2024-02-27 +tags: + - Launch Week + - Templates +--- + + + +> TLDR; You can now reuse documents via templates. More field types coming soon as well. + +## Introducing Templates + +It's day 2 of Launch Week, everybody ๐Ÿ™Œ After introducing [Teams](https://documenso.com/blog/launch-week-2-day-1) yesterday, today we are looking at making Documenso faster for daily use: +We are launching templates for Documenso! Templates are an easy way to reuse documents you send out often with just a few clicks. With templates, you can: + +
+ + +
+ Quickly fill out recipients, when creating from a template +
+
+ +- Save often-uploaded documents for reuse +- Pre-define fields, so you just have to send the document +- Quickly fill out recipients and roles for new documents +- Share templates with your team to make working together even easier + +
+ + +
+ POV: You are a diligent german and create custom receipts with Documenso +
+
+ +## Pricing + +Templates are **included in all Documenso Plans!** That includes our free tier: The limit of 5 documents per month still applies, but you are free to reach it with less friction using templates. Sharing templates with other users is only possible with the teams plan. If you want to share templates with people not in your team, we might have something coming up later this week ๐Ÿ‘€ + +## What's Next for Templates + +We have a lot of great stuff coming up for templates as well: + +- More Field Types are in the pipeline +- Sharing Templates Externally ๐Ÿ‘€ + +Check out templates [here](https://documen.so/templates) and let us know what you think and what we can improve. Which field types are you missing? Connect with us on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments! We're always here and would love to hear from you :) + +> ๐Ÿšจ We need you help to help us to make this the biggest launch week yet: Support us on Twitter or anywhere to spread awareness for open signing! The best posts will receive merch codes ๐Ÿ‘€ + +Best from Hamburg\ +Timur diff --git a/apps/marketing/content/blog/launch-week-2-day-3.mdx b/apps/marketing/content/blog/launch-week-2-day-3.mdx new file mode 100644 index 000000000..6ea0db9b9 --- /dev/null +++ b/apps/marketing/content/blog/launch-week-2-day-3.mdx @@ -0,0 +1,53 @@ +--- +title: Launch Week II - Day 3 - API +description: Documenso's mission is to create a plattform developers all around the world can build upon. Today we are releasing the first version of our public API, included in all plans! +authorName: 'Timur Ercan' +authorImage: '/blog/blog-author-timur.jpeg' +authorRole: 'Co-Founder' +date: 2024-02-28 +tags: + - Launch Week + - API +--- + + + +> TLDR; The public API is now availible for all plans. + +## Introducing the public Documenso API + +Launch. Week. Day. 3 ๐ŸŽ‰ Documenso's mission is to create a platform that developers all around the world can build upon. Today we are releasing the first version of our public API, and we are pumped. Since this is the first version, we focused on the basics. With the new API you can: + +- Get Documents (Individual or all Accessible) +- Upload Documents +- Delete Documents +- Create Documents from Templates +- Trigger Sending Documents for Singing + +You can check out the detailed API documentation here: + +> API DOCUMENTATION: [https://app.documenso.com/api/v1/openapi](https://app.documenso.com/api/v1/openapi) + +## Pricing + +We are building Documenso to be an open and extendable platform; therefore the API is included in all current plans. The API is authenticated via auth tokens, which every user can create at no extra cost, as can teams. Existing limits still apply (i.e., the number of included documents for the free plan). While we don't have all the details yet, we don't intend to price the API usage in itself (rather the accounts using it) since we want you to build on Documenso without being smothered by API costs. + +> Try the API here for free: [https://documen.so/api](https://documen.so/api) + +## What's next for the API + +You tell us. This is by far the most requested feature, so we would like to hear from you. What should we add? How can we integrate even better? + +Connect with us on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord) if you have any questions or comments! We're always here and would love to hear from you :) + +> ๐Ÿšจ We need you help to help us to make this the biggest launch week yet: Support us on Twitter or anywhere to spread awareness for open signing! The best posts will receive merch codes ๐Ÿ‘€ + +Best from Hamburg\ +Timur diff --git a/apps/marketing/content/blog/launch-week-2-day-4.mdx b/apps/marketing/content/blog/launch-week-2-day-4.mdx new file mode 100644 index 000000000..b6f5691fd --- /dev/null +++ b/apps/marketing/content/blog/launch-week-2-day-4.mdx @@ -0,0 +1,63 @@ +--- +title: Launch Week II - Day 4 - Webhooks and Zapier +description: If you want to integrate Documenso without fiddling with the API, we got you as well. You can now integrate Documenso via Zapier, included in all plans! +authorName: 'Timur Ercan' +authorImage: '/blog/blog-author-timur.jpeg' +authorRole: 'Co-Founder' +date: 2024-02-29 +tags: + - Launch Week + - Zapier + - Webhooks +--- + + + +> TLDR; Zapier Integration is now available for all plans. + +## Introducing Zapier for Documenso + +Day 4 ๐Ÿฅณ Yesterday we introduced our [public API](https://documen.so/day3) for developers to build on Documenso. If you are not a developer or simple want a quicker integration this is for you: Documenso now support Zapier Integrations! Just connect your Documenso account via a simple login flow with Zapier and you will have access to Zapier's universe of integrations ๐Ÿ’ซ The integration currently supports: + +- Document Created ([https://documen.so/zapier-created](https://documen.so/zapier-created)) +- Document Sent ([Chttps://documen.so/zapier-sent](https://documen.so/zapier-sent)) +- Document Opened ([https://documen.so/zapier-opened](https://documen.so/zapier-opened)) +- Document Signed ([https://documen.so/zapier-signed](https://documen.so/zapier-signed)) +- Document Completed ([https://documen.so/zapier-completed](https://documen.so/zapier-completed)) + +> โšก๏ธ You can create your own Zaps here: https://zapier.com/apps/documenso/integrations + +Each event comes with extensive meta-data for you to use in Zapier. Missing something? Reach out on [Twitter / X](https://twitter.com/eltimuro) (DM open) or [Discord](https://documen.so/discord). We're always here and would love to hear from you :) + +## Also Introducing for Documenso: Webhooks + +To build the Zapier Integration, we needed a good webhooks concept, so we added that as well. Together with your Zaps, you can also now create customer webhooks in Documenso. You can try webhooks here for free: [https://documen.so/webhooks](https://documen.so/webhooks) + +
+ + +
+ Create unlimited custom webhooks with each plan. +
+
+ +## Pricing + +Just like the API, we consider the Zapier integration and webhooks part of the open Documenso platform. Zapier is **available for all Documenso plans**, including free! [Login now](https://documen.so/login) to check it out. + +> ๐Ÿšจ We need you help to help us to make this the biggest launch week yet: Support us on Twitter or anywhere to spread awareness for open signing! The best posts will receive merch codes ๐Ÿ‘€ + +Best from Hamburg\ +Timur diff --git a/apps/marketing/content/blog/launch-week-2-day-5.mdx b/apps/marketing/content/blog/launch-week-2-day-5.mdx new file mode 100644 index 000000000..04d639206 --- /dev/null +++ b/apps/marketing/content/blog/launch-week-2-day-5.mdx @@ -0,0 +1,61 @@ +--- +title: Launch Week II - Day 5 - Documenso Profiles +description: Documenso profiles allow you to send signing links to people so they can sign anytime and see who you are. Documenso Profile Usernames can be claimed starting today. Long ones free, short ones paid. Profiles will launch as soon as they are shiny. +authorName: 'Timur Ercan' +authorImage: '/blog/blog-author-timur.jpeg' +authorRole: 'Co-Founder' +date: 2024-03-01 +tags: + - Launch Week + - Profiles +--- + + + +> TLDR; Documenso profiles allow you to send signing links to people so they can sign anytime and see who you are. Documenso Profile Usernames can be claimed starting today. Long ones free, short ones paid. Profiles launch as soon as they are shiny. + +## Introducing Documenso Profile Links + +Day 5 - The Finale ๐Ÿ”ฅ + +Signing documents has always been between humans, and signing something together should be as frictionless as possible. It should also be async, so you don't force your counterpart to jog to their device to send something when you are ready. Today we are announcing the new Documenso Profiles: + +
+ + +
+ Async > Sync: Add public templates to your Documenso Link and let people sign whenever they are ready. +
+
+ +Documenso profiles work with your existing templates. You can just add them to your public profile to let everyone with your link sign them. With profiles, we want to bring back the human aspect of signing. + +By making profiles public, you can always access what your counterparty offers and make them more visible in the process. Long-term, we plan to add more to profiles to help you ensure the person you are dealing with is who they claim to be. Documenso wants to be the trust layer of the internet, and we want to start at the very fundamental level: The individual transaction. + +Profiles are our first step towards bringing more trust into everything, simply by making the use of signing more frictionless. As there is more and more content of questionable origin out there, we want to support you in making it clear what you send out and what not. + +## Pricing and Claiming + +Documenso profile username can be claimed starting today. Documenso profiles will launch as soon as we are happy with the details โœจ + +- Long usernames (6 characters or more) come free with every account, e.g. **documenso.com/u/timurercan** +- Short usernames (5 characters or fewer) or less require any paid account ([Early Adopter](https://documen.so/claim-early-adopters-plan), [Teams](https://documen.so/teams) or Enterprise): **e.g., documenso.com/u/timur** + +You can claim your username here: [https://documen.so/claim](https://documen.so/claim) + +> ๐Ÿšจ We need you help to help us to make this the biggest launch week yet: Support us on Twitter or anywhere to spread awareness for open signing! The best posts will receive merch codes ๐Ÿ‘€ + +Best from Hamburg\ +Timur diff --git a/apps/marketing/public/blog/hooks.png b/apps/marketing/public/blog/hooks.png new file mode 100644 index 000000000..9c324db0b Binary files /dev/null and b/apps/marketing/public/blog/hooks.png differ diff --git a/apps/marketing/public/blog/profile.png b/apps/marketing/public/blog/profile.png new file mode 100644 index 000000000..b216e9758 Binary files /dev/null and b/apps/marketing/public/blog/profile.png differ diff --git a/apps/marketing/public/blog/quickfill.png b/apps/marketing/public/blog/quickfill.png new file mode 100644 index 000000000..17765b643 Binary files /dev/null and b/apps/marketing/public/blog/quickfill.png differ diff --git a/apps/marketing/public/blog/template.png b/apps/marketing/public/blog/template.png new file mode 100644 index 000000000..74dd48de9 Binary files /dev/null and b/apps/marketing/public/blog/template.png differ diff --git a/apps/marketing/src/app/(marketing)/layout.tsx b/apps/marketing/src/app/(marketing)/layout.tsx index dd1a46418..c5f761853 100644 --- a/apps/marketing/src/app/(marketing)/layout.tsx +++ b/apps/marketing/src/app/(marketing)/layout.tsx @@ -2,8 +2,12 @@ import React, { useEffect, useState } from 'react'; +import Image from 'next/image'; import { usePathname } from 'next/navigation'; +import launchWeekTwoImage from '@documenso/assets/images/background-lw-2.png'; +import { useFeatureFlags } from '@documenso/lib/client-only/providers/feature-flag'; +import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { cn } from '@documenso/ui/lib/utils'; import { Footer } from '~/components/(marketing)/footer'; @@ -17,6 +21,10 @@ export default function MarketingLayout({ children }: MarketingLayoutProps) { const [scrollY, setScrollY] = useState(0); const pathname = usePathname(); + const { getFlag } = useFeatureFlags(); + + const showProfilesAnnouncementBar = getFlag('marketing_profiles_announcement_bar'); + useEffect(() => { const onScroll = () => { setScrollY(window.scrollY); @@ -38,6 +46,31 @@ export default function MarketingLayout({ children }: MarketingLayoutProps) { 'bg-background/50 backdrop-blur-md': scrollY > 5, })} > + {showProfilesAnnouncementBar && ( +
+
+ Launch Week 2 +
+ +
+ Claim your documenso public profile username now!{' '} + documenso.com/u/yourname +
+ + Claim Now + +
+
+
+ )} +
diff --git a/apps/marketing/src/app/(marketing)/singleplayer/[token]/success/page.tsx b/apps/marketing/src/app/(marketing)/singleplayer/[token]/success/page.tsx index fbf020c38..51fbaff36 100644 --- a/apps/marketing/src/app/(marketing)/singleplayer/[token]/success/page.tsx +++ b/apps/marketing/src/app/(marketing)/singleplayer/[token]/success/page.tsx @@ -27,7 +27,7 @@ export default async function SinglePlayerModeSuccessPage({ return notFound(); } - const signatures = await getRecipientSignatures({ recipientId: document.Recipient.id }); + const signatures = await getRecipientSignatures({ recipientId: document.Recipient[0].id }); return ; } diff --git a/apps/marketing/src/app/(marketing)/singleplayer/client.tsx b/apps/marketing/src/app/(marketing)/singleplayer/client.tsx index 1d6604a87..74158249a 100644 --- a/apps/marketing/src/app/(marketing)/singleplayer/client.tsx +++ b/apps/marketing/src/app/(marketing)/singleplayer/client.tsx @@ -191,7 +191,7 @@ export const SinglePlayerClient = () => {

Create a{' '} @@ -257,6 +257,7 @@ export const SinglePlayerClient = () => { fields={fields} onSubmit={onSignSubmit} requireName={Boolean(fields.find((field) => field.type === 'NAME'))} + requireCustomText={Boolean(fields.find((field) => field.type === 'TEXT'))} requireSignature={Boolean(fields.find((field) => field.type === 'SIGNATURE'))} /> diff --git a/apps/marketing/src/app/layout.tsx b/apps/marketing/src/app/layout.tsx index 57da42c3f..99a1a6483 100644 --- a/apps/marketing/src/app/layout.tsx +++ b/apps/marketing/src/app/layout.tsx @@ -2,6 +2,8 @@ import { Suspense } from 'react'; import { Caveat, Inter } from 'next/font/google'; +import { PublicEnvScript } from 'next-runtime-env'; + import { FeatureFlagProvider } from '@documenso/lib/client-only/providers/feature-flag'; import { NEXT_PUBLIC_MARKETING_URL } from '@documenso/lib/constants/app'; import { getAllAnonymousFlags } from '@documenso/lib/universal/get-feature-flag'; @@ -62,6 +64,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo + diff --git a/apps/marketing/src/components/(marketing)/callout.tsx b/apps/marketing/src/components/(marketing)/callout.tsx index 72ae3907b..990aa163b 100644 --- a/apps/marketing/src/components/(marketing)/callout.tsx +++ b/apps/marketing/src/components/(marketing)/callout.tsx @@ -40,9 +40,9 @@ export const Callout = ({ starCount }: CalloutProps) => { className="rounded-full bg-transparent backdrop-blur-sm" onClick={onSignUpClick} > - Get the Early Adopters Plan - - $30/mo. forever! + Claim Community Plan + + $30/mo diff --git a/apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx b/apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx index ee123d7ad..b80b2fe8c 100644 --- a/apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx +++ b/apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx @@ -1,4 +1,4 @@ -import { HTMLAttributes } from 'react'; +import type { HTMLAttributes } from 'react'; import Image from 'next/image'; diff --git a/apps/marketing/src/components/(marketing)/header.tsx b/apps/marketing/src/components/(marketing)/header.tsx index e1813f7f6..915c13852 100644 --- a/apps/marketing/src/components/(marketing)/header.tsx +++ b/apps/marketing/src/components/(marketing)/header.tsx @@ -9,6 +9,7 @@ import Link from 'next/link'; import LogoImage from '@documenso/assets/logo.png'; import { useFeatureFlags } from '@documenso/lib/client-only/providers/feature-flag'; import { cn } from '@documenso/ui/lib/utils'; +import { Button } from '@documenso/ui/primitives/button'; import { HamburgerMenu } from './mobile-hamburger'; import { MobileNavigation } from './mobile-navigation'; @@ -68,12 +69,18 @@ export const Header = ({ className, ...props }: HeaderProps) => { Sign in + + { className="rounded-full bg-transparent backdrop-blur-sm" onClick={onSignUpClick} > - Get the Early Adopters Plan - - $30/mo. forever! + Claim Community Plan + + $30/mo @@ -224,8 +225,7 @@ export const Hero = ({ className, ...props }: HeroProps) => { (in a non-legally binding, but heartfelt way) {' '} - and lock in the early supporter plan for forever, including everything we build this - year. + and lock in the community plan for forever, including everything we build this year.

diff --git a/apps/marketing/src/components/(marketing)/mobile-navigation.tsx b/apps/marketing/src/components/(marketing)/mobile-navigation.tsx index 982e2967a..434b30053 100644 --- a/apps/marketing/src/components/(marketing)/mobile-navigation.tsx +++ b/apps/marketing/src/components/(marketing)/mobile-navigation.tsx @@ -47,9 +47,13 @@ export const MENU_NAVIGATION_LINKS = [ text: 'Privacy', }, { - href: 'https://app.documenso.com/signin', + href: 'https://app.documenso.com/signin?utm_source=marketing-header', text: 'Sign in', }, + { + href: 'https://app.documenso.com/signup?utm_source=marketing-header', + text: 'Sign up', + }, ]; export const MobileNavigation = ({ isMenuOpen, onMenuOpenChange }: MobileNavigationProps) => { diff --git a/apps/marketing/src/components/(marketing)/pricing-table.tsx b/apps/marketing/src/components/(marketing)/pricing-table.tsx index ce4695199..ab35bcc90 100644 --- a/apps/marketing/src/components/(marketing)/pricing-table.tsx +++ b/apps/marketing/src/components/(marketing)/pricing-table.tsx @@ -8,6 +8,7 @@ import Link from 'next/link'; import { AnimatePresence, motion } from 'framer-motion'; import { usePlausible } from 'next-plausible'; +import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; @@ -82,7 +83,11 @@ export const PricingTable = ({ className, ...props }: PricingTableProps) => {

@@ -113,33 +118,31 @@ export const PricingTable = ({ className, ...props }: PricingTableProps) => {

-

- {' '} - - The Early Adopter Deal: +

+ + Limited Time Offer: Read More

-

Join the movement

-

Simple signing solution

+

Unlimited Teams

+

Unlimited Users

+

Unlimited Documents per month

+

Includes all upcoming features

Email, Discord and Slack assistance

-

- - {' '} - - Includes all upcoming features - - -

-

Fixed, straightforward pricing

+
@@ -65,7 +65,7 @@ export const SinglePlayerModeSuccess = ({
@@ -86,7 +86,7 @@ export const SinglePlayerModeSuccess = ({

Create a{' '} diff --git a/apps/marketing/src/components/(marketing)/widget.tsx b/apps/marketing/src/components/(marketing)/widget.tsx index fe7502d27..15e3fbdeb 100644 --- a/apps/marketing/src/components/(marketing)/widget.tsx +++ b/apps/marketing/src/components/(marketing)/widget.tsx @@ -199,7 +199,7 @@ export const Widget = ({ className, children, ...props }: WidgetProps) => { className="bg-foreground/5 col-span-12 flex flex-col rounded-2xl p-6 lg:col-span-5" onSubmit={handleSubmit(onFormSubmit)} > -

Sign up for the early adopters plan

+

Sign up to Community Plan

with Timur Ercan & Lucas Smith from Documenso

@@ -208,7 +208,7 @@ export const Widget = ({ className, children, ...props }: WidgetProps) => { -
); }; diff --git a/apps/web/src/app/(dashboard)/admin/site-settings/banner-form.tsx b/apps/web/src/app/(dashboard)/admin/site-settings/banner-form.tsx new file mode 100644 index 000000000..351e146ff --- /dev/null +++ b/apps/web/src/app/(dashboard)/admin/site-settings/banner-form.tsx @@ -0,0 +1,200 @@ +'use client'; + +import { useRouter } from 'next/navigation'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import type { z } from 'zod'; + +import type { TSiteSettingsBannerSchema } from '@documenso/lib/server-only/site-settings/schemas/banner'; +import { + SITE_SETTINGS_BANNER_ID, + ZSiteSettingsBannerSchema, +} from '@documenso/lib/server-only/site-settings/schemas/banner'; +import { TRPCClientError } from '@documenso/trpc/client'; +import { trpc as trpcReact } from '@documenso/trpc/react'; +import { Button } from '@documenso/ui/primitives/button'; +import { ColorPicker } from '@documenso/ui/primitives/color-picker'; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@documenso/ui/primitives/form/form'; +import { Switch } from '@documenso/ui/primitives/switch'; +import { Textarea } from '@documenso/ui/primitives/textarea'; +import { useToast } from '@documenso/ui/primitives/use-toast'; + +const ZBannerFormSchema = ZSiteSettingsBannerSchema; + +type TBannerFormSchema = z.infer; + +export type BannerFormProps = { + banner?: TSiteSettingsBannerSchema; +}; + +export function BannerForm({ banner }: BannerFormProps) { + const router = useRouter(); + const { toast } = useToast(); + + const form = useForm({ + resolver: zodResolver(ZBannerFormSchema), + defaultValues: { + id: SITE_SETTINGS_BANNER_ID, + enabled: banner?.enabled ?? false, + data: { + content: banner?.data?.content ?? '', + bgColor: banner?.data?.bgColor ?? '#000000', + textColor: banner?.data?.textColor ?? '#FFFFFF', + }, + }, + }); + + const enabled = form.watch('enabled'); + + const { mutateAsync: updateSiteSetting, isLoading: isUpdateSiteSettingLoading } = + trpcReact.admin.updateSiteSetting.useMutation(); + + const onBannerUpdate = async ({ id, enabled, data }: TBannerFormSchema) => { + try { + await updateSiteSetting({ + id, + enabled, + data, + }); + + toast({ + title: 'Banner Updated', + description: 'Your banner has been updated successfully.', + duration: 5000, + }); + + router.refresh(); + } catch (err) { + if (err instanceof TRPCClientError && err.data?.code === 'BAD_REQUEST') { + toast({ + title: 'An error occurred', + description: err.message, + variant: 'destructive', + }); + } else { + toast({ + title: 'An unknown error occurred', + variant: 'destructive', + description: + 'We encountered an unknown error while attempting to update the banner. Please try again later.', + }); + } + } + }; + + return ( +
+

Site Banner

+

+ The site banner is a message that is shown at the top of the site. It can be used to display + important information to your users. +

+ +
+ +
+ ( + + Enabled + + +
+ +
+
+
+ )} + /> + +
+ ( + + Background Color + + +
+ +
+
+ + +
+ )} + /> + + ( + + Text Color + + +
+ +
+
+ + +
+ )} + /> +
+
+ +
+ ( + + Content + + +