diff --git a/apps/docs/cli.json b/apps/docs/cli.json index 89d51513d..e299c4676 100644 --- a/apps/docs/cli.json +++ b/apps/docs/cli.json @@ -10,4 +10,4 @@ "baseDir": "src", "uiLibrary": "radix-ui", "commands": {} -} \ No newline at end of file +} diff --git a/apps/docs/content/docs/concepts/meta.json b/apps/docs/content/docs/concepts/meta.json index 925998a98..decdd116e 100644 --- a/apps/docs/content/docs/concepts/meta.json +++ b/apps/docs/content/docs/concepts/meta.json @@ -1,10 +1,4 @@ { "title": "Concepts", - "pages": [ - "document-lifecycle", - "recipient-roles", - "field-types", - "signing-workflow", - "signing-certificates" - ] + "pages": ["document-lifecycle", "recipient-roles", "field-types", "signing-workflow", "signing-certificates"] } diff --git a/apps/docs/content/docs/developers/api/meta.json b/apps/docs/content/docs/developers/api/meta.json index ffabac120..98c9bf00f 100644 --- a/apps/docs/content/docs/developers/api/meta.json +++ b/apps/docs/content/docs/developers/api/meta.json @@ -1,13 +1,4 @@ { "title": "API Reference", - "pages": [ - "documents", - "recipients", - "fields", - "templates", - "teams", - "rate-limits", - "versioning", - "developer-mode" - ] + "pages": ["documents", "recipients", "fields", "templates", "teams", "rate-limits", "versioning", "developer-mode"] } diff --git a/apps/docs/content/docs/users/organisations/meta.json b/apps/docs/content/docs/users/organisations/meta.json index f19f48f4d..79142356a 100644 --- a/apps/docs/content/docs/users/organisations/meta.json +++ b/apps/docs/content/docs/users/organisations/meta.json @@ -1,13 +1,4 @@ { "title": "Organisations", - "pages": [ - "overview", - "create-team", - "members", - "groups", - "email-domains", - "preferences", - "single-sign-on", - "billing" - ] + "pages": ["overview", "create-team", "members", "groups", "email-domains", "preferences", "single-sign-on", "billing"] } diff --git a/apps/docs/src/app/(home)/layout.tsx b/apps/docs/src/app/(home)/layout.tsx index b1bf08edc..77379fac3 100644 --- a/apps/docs/src/app/(home)/layout.tsx +++ b/apps/docs/src/app/(home)/layout.tsx @@ -1,5 +1,5 @@ -import { baseOptions } from '@/lib/layout.shared'; import { HomeLayout } from 'fumadocs-ui/layouts/home'; +import { baseOptions } from '@/lib/layout.shared'; export default function Layout({ children }: LayoutProps<'/'>) { return {children}; diff --git a/apps/docs/src/app/(home)/page.tsx b/apps/docs/src/app/(home)/page.tsx index 0bd99fdd5..5b358b9be 100644 --- a/apps/docs/src/app/(home)/page.tsx +++ b/apps/docs/src/app/(home)/page.tsx @@ -1,16 +1,7 @@ +import { BookOpenIcon, CodeIcon, FileTextIcon, GithubIcon, ServerIcon, ShieldCheckIcon, UserIcon } from 'lucide-react'; import type { Metadata } from 'next'; import Link from 'next/link'; -import { - BookOpenIcon, - CodeIcon, - FileTextIcon, - GithubIcon, - ServerIcon, - ShieldCheckIcon, - UserIcon, -} from 'lucide-react'; - export const metadata: Metadata = { title: 'Documenso Docs', description: @@ -22,21 +13,21 @@ export default function HomePage() {
{/* Hero */}
-

Documenso Documentation

-

- The open-source document signing platform. Send documents for signatures, integrate with - your apps, or self-host with full control. +

Documenso Documentation

+

+ The open-source document signing platform. Send documents for signatures, integrate with your apps, or + self-host with full control.

Get Started View on GitHub @@ -48,64 +39,60 @@ export default function HomePage() {
-

User Guide

-

+

User Guide

+

Send documents, create templates, and manage your team using the web application.

- Get started → + Get started →
-

Developer Guide

-

- Integrate document signing into your applications with the REST API, webhooks, and - embedding. +

Developer Guide

+

+ Integrate document signing into your applications with the REST API, webhooks, and embedding.

- View API docs → + View API docs →
-

Self-Hosting Guide

-

+

Self-Hosting Guide

+

Deploy your own Documenso instance with Docker, Kubernetes, or Railway.

- Deploy now → + Deploy now →
{/* Quick Start & Core Concepts */}
-
+

- + Quick Start

-

Send your first document

-
    +

    Send your first document

    +
    1. - + Create an account
    2. @@ -120,8 +107,8 @@ export default function HomePage() {
-

Integrate with the API

-
    +

    Integrate with the API

    +
-

Deploy self-hosted

-
    +

    Deploy self-hosted

    +
-
+

- + Core Concepts

Document Lifecycle
Draft to completed
Recipient Roles
Signers and approvers
Field Types
Signatures and inputs
Signing Certificates
Digital verification
@@ -206,7 +193,7 @@ export default function HomePage() {
@@ -221,7 +208,7 @@ export default function HomePage() {
@@ -236,22 +223,22 @@ export default function HomePage() {
{/* Community CTA */} -
-

Join the Community

-

+

+

Join the Community

+

Documenso is open source. Contribute, ask questions, or share feedback.

GitHub @@ -260,7 +247,7 @@ export default function HomePage() { Try Documenso diff --git a/apps/docs/src/app/api/search/route.ts b/apps/docs/src/app/api/search/route.ts index 7ba7e8231..5069e9066 100644 --- a/apps/docs/src/app/api/search/route.ts +++ b/apps/docs/src/app/api/search/route.ts @@ -1,5 +1,5 @@ -import { source } from '@/lib/source'; import { createFromSource } from 'fumadocs-core/search/server'; +import { source } from '@/lib/source'; export const { GET } = createFromSource(source, { // https://docs.orama.com/docs/orama-js/supported-languages diff --git a/apps/docs/src/app/docs/[[...slug]]/page.tsx b/apps/docs/src/app/docs/[[...slug]]/page.tsx index f2234442f..590b588a2 100644 --- a/apps/docs/src/app/docs/[[...slug]]/page.tsx +++ b/apps/docs/src/app/docs/[[...slug]]/page.tsx @@ -1,10 +1,9 @@ +import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page'; import type { Metadata } from 'next'; import { notFound } from 'next/navigation'; - import { LLMCopyButton, ViewOptions } from '@/components/ai/page-actions'; import { getPageImage, source } from '@/lib/source'; import { getMDXComponents } from '@/mdx-components'; -import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page'; const gitConfig = { user: 'documenso', diff --git a/apps/docs/src/app/docs/layout.tsx b/apps/docs/src/app/docs/layout.tsx index 8371fe953..39ee4ba60 100644 --- a/apps/docs/src/app/docs/layout.tsx +++ b/apps/docs/src/app/docs/layout.tsx @@ -1,16 +1,14 @@ 'use client'; -import { useMemo } from 'react'; - -import Link from 'next/link'; -import { usePathname } from 'next/navigation'; - -import { cn } from '@/lib/cn'; -import { baseOptions } from '@/lib/layout.shared'; -import { getFilteredPageTree, source } from '@/lib/source'; import type * as PageTree from 'fumadocs-core/page-tree'; import { DocsLayout } from 'fumadocs-ui/layouts/docs'; import { CodeIcon, ServerIcon, UserIcon } from 'lucide-react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import { useMemo } from 'react'; +import { cn } from '@/lib/cn'; +import { baseOptions } from '@/lib/layout.shared'; +import { getFilteredPageTree, source } from '@/lib/source'; const ROOT_SECTIONS = [ { @@ -44,7 +42,9 @@ function getFirstPageUrl(children: PageTree.Node[]): string | undefined { } if (child.type === 'folder' && child.children.length > 0) { const url = getFirstPageUrl(child.children); - if (url) return url; + if (url) { + return url; + } } } return undefined; @@ -69,13 +69,8 @@ function SectionSwitcher({ activeSection }: { activeSection: string | null }) { >
- {section.label} - + {section.label} + {section.subtitle}
diff --git a/apps/docs/src/app/global.css b/apps/docs/src/app/global.css index c7e4f0540..7d9c89316 100644 --- a/apps/docs/src/app/global.css +++ b/apps/docs/src/app/global.css @@ -1,6 +1,6 @@ -@import 'tailwindcss'; -@import 'fumadocs-ui/css/shadcn.css'; -@import 'fumadocs-ui/css/preset.css'; +@import "tailwindcss"; +@import "fumadocs-ui/css/shadcn.css"; +@import "fumadocs-ui/css/preset.css"; @theme { /* Brand utility colors */ @@ -43,13 +43,11 @@ --sidebar-border: hsl(223.8136 0.0001% 89.8161%); --sidebar-ring: hsl(223.8136 0% 63.0163%); --font-sans: - ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; - --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; - --font-mono: - ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', - monospace; + ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji"; + --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --radius: 0.5rem; --shadow-x: 0; --shadow-y: 1px; @@ -103,13 +101,11 @@ --sidebar-border: hsl(223.8136 0% 15.5096%); --sidebar-ring: hsl(223.8136 0% 32.1993%); --font-sans: - ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; - --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; - --font-mono: - ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', - monospace; + ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji"; + --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --radius: 0.5rem; --shadow-x: 0; --shadow-y: 1px; diff --git a/apps/docs/src/app/layout.tsx b/apps/docs/src/app/layout.tsx index 5c52be8ba..391918370 100644 --- a/apps/docs/src/app/layout.tsx +++ b/apps/docs/src/app/layout.tsx @@ -1,7 +1,6 @@ +import { RootProvider } from 'fumadocs-ui/provider/next'; import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; - -import { RootProvider } from 'fumadocs-ui/provider/next'; import PlausibleProvider from 'next-plausible'; import './global.css'; @@ -16,8 +15,7 @@ export const metadata: Metadata = { template: '%s | Documenso Docs', default: 'Documenso Docs', }, - description: - 'The official documentation for Documenso, the open-source document signing platform.', + description: 'The official documentation for Documenso, the open-source document signing platform.', openGraph: { siteName: 'Documenso Docs', type: 'website', diff --git a/apps/docs/src/app/not-found.tsx b/apps/docs/src/app/not-found.tsx index ed252e4a3..cbc25f2ce 100644 --- a/apps/docs/src/app/not-found.tsx +++ b/apps/docs/src/app/not-found.tsx @@ -3,20 +3,20 @@ import Link from 'next/link'; export default function NotFound() { return (
-

Page not found

-

+

Page not found

+

The page you are looking for may have moved. Our documentation was recently restructured.

Browse documentation Go to homepage diff --git a/apps/docs/src/app/og/docs/[...slug]/route.tsx b/apps/docs/src/app/og/docs/[...slug]/route.tsx index 1a7153f47..76815dd3b 100644 --- a/apps/docs/src/app/og/docs/[...slug]/route.tsx +++ b/apps/docs/src/app/og/docs/[...slug]/route.tsx @@ -1,21 +1,16 @@ -import { notFound } from 'next/navigation'; -import { ImageResponse } from 'next/og'; - -import { getPageImage, source } from '@/lib/source'; import { readFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; +import { notFound } from 'next/navigation'; +import { ImageResponse } from 'next/og'; +import { getPageImage, source } from '@/lib/source'; export const revalidate = false; const loadAssets = async () => { const [logoBuffer, interRegularData, interSemiBoldData, interBoldData] = await Promise.all([ readFile(fileURLToPath(new URL('../../../../../public/logo.png', import.meta.url))), - readFile( - fileURLToPath(new URL('../../../../../public/fonts/inter-regular.ttf', import.meta.url)), - ), - readFile( - fileURLToPath(new URL('../../../../../public/fonts/inter-semibold.ttf', import.meta.url)), - ), + readFile(fileURLToPath(new URL('../../../../../public/fonts/inter-regular.ttf', import.meta.url))), + readFile(fileURLToPath(new URL('../../../../../public/fonts/inter-semibold.ttf', import.meta.url))), readFile(fileURLToPath(new URL('../../../../../public/fonts/inter-bold.ttf', import.meta.url))), ]); @@ -40,104 +35,100 @@ export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[... const { logoSrc, fonts } = await loadAssets(); return new ImageResponse( - ( +
+ {/* Green accent bar */} +
+ + {/* Top: Logo */} +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + Documenso + + | + + Docs +
+ + {/* Middle: Title + description */}
- {/* Green accent bar */} -
- - {/* Top: Logo */} -
40 ? '48px' : '56px', + fontWeight: 700, + lineHeight: 1.15, + letterSpacing: '-0.025em', + margin: 0, }} > - {/* eslint-disable-next-line @next/next/no-img-element */} - Documenso - + {page.data.description && ( +

- | - - Docs -

- - {/* Middle: Title + description */} -
-

40 ? '48px' : '56px', - fontWeight: 700, - lineHeight: 1.15, - letterSpacing: '-0.025em', + lineHeight: 1.4, margin: 0, + maxWidth: '900px', + overflow: 'hidden', + textOverflow: 'ellipsis', + display: '-webkit-box', + WebkitLineClamp: 2, + WebkitBoxOrient: 'vertical', }} > - {page.data.title} -

- {page.data.description && ( -

- {page.data.description} -

- )} -
- - {/* Bottom: URL */} -
- - docs.documenso.com{page.url} - -
+ {page.data.description} +

+ )}
- ), + + {/* Bottom: URL */} +
+ docs.documenso.com{page.url} +
+
, { width: 1200, height: 630, diff --git a/apps/docs/src/components/ai/page-actions.tsx b/apps/docs/src/components/ai/page-actions.tsx index 705eaef89..662cbab3d 100644 --- a/apps/docs/src/components/ai/page-actions.tsx +++ b/apps/docs/src/components/ai/page-actions.tsx @@ -1,12 +1,11 @@ 'use client'; -import { useMemo, useState } from 'react'; - -import { cn } from '@/lib/cn'; import { buttonVariants } from 'fumadocs-ui/components/ui/button'; import { Popover, PopoverContent, PopoverTrigger } from 'fumadocs-ui/components/ui/popover'; import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button'; import { Check, ChevronDown, Copy, ExternalLinkIcon, MessageCircleIcon } from 'lucide-react'; +import { useMemo, useState } from 'react'; +import { cn } from '@/lib/cn'; const cache = new Map(); @@ -21,7 +20,9 @@ export function LLMCopyButton({ const [isLoading, setLoading] = useState(false); const [checked, onClick] = useCopyButton(async () => { const cached = cache.get(markdownUrl); - if (cached) return navigator.clipboard.writeText(cached); + if (cached) { + return navigator.clipboard.writeText(cached); + } setLoading(true); @@ -48,7 +49,7 @@ export function LLMCopyButton({ buttonVariants({ color: 'secondary', size: 'sm', - className: '[&_svg]:text-fd-muted-foreground gap-2 [&_svg]:size-3.5', + className: 'gap-2 [&_svg]:size-3.5 [&_svg]:text-fd-muted-foreground', }), )} onClick={onClick} @@ -74,8 +75,7 @@ export function ViewOptions({ githubUrl: string; }) { const items = useMemo(() => { - const fullMarkdownUrl = - typeof window !== 'undefined' ? new URL(markdownUrl, window.location.origin) : 'loading'; + const fullMarkdownUrl = typeof window !== 'undefined' ? new URL(markdownUrl, window.location.origin) : 'loading'; const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`; return [ @@ -96,12 +96,7 @@ export function ViewOptions({ q, })}`, icon: ( - + OpenAI @@ -113,12 +108,7 @@ export function ViewOptions({ q, })}`, icon: ( - + Anthropic @@ -146,7 +136,7 @@ export function ViewOptions({ )} > Open - + {items.map((item) => ( @@ -155,11 +145,11 @@ export function ViewOptions({ href={item.href} rel="noreferrer noopener" target="_blank" - className="hover:text-fd-accent-foreground hover:bg-fd-accent inline-flex items-center gap-2 rounded-lg p-2 text-sm [&_svg]:size-4" + className="inline-flex items-center gap-2 rounded-lg p-2 text-sm hover:bg-fd-accent hover:text-fd-accent-foreground [&_svg]:size-4" > {item.icon} {item.title} - + ))} diff --git a/apps/docs/src/components/mdx/mermaid.tsx b/apps/docs/src/components/mdx/mermaid.tsx index 58b5c16a6..1cc1467d9 100644 --- a/apps/docs/src/components/mdx/mermaid.tsx +++ b/apps/docs/src/components/mdx/mermaid.tsx @@ -1,8 +1,7 @@ 'use client'; -import { useEffect, useId, useRef, useState } from 'react'; - import { useTheme } from 'next-themes'; +import { useEffect, useId, useRef, useState } from 'react'; export const Mermaid = ({ chart }: { chart: string }) => { const [mounted, setMounted] = useState(false); diff --git a/apps/docs/src/lib/source.ts b/apps/docs/src/lib/source.ts index 0f995f2e8..b885e85b8 100644 --- a/apps/docs/src/lib/source.ts +++ b/apps/docs/src/lib/source.ts @@ -1,7 +1,7 @@ +import { docs } from 'fumadocs-mdx:collections/server'; import type * as PageTree from 'fumadocs-core/page-tree'; import { type InferPageType, loader } from 'fumadocs-core/source'; import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons'; -import { docs } from 'fumadocs-mdx:collections/server'; // See https://fumadocs.dev/docs/headless/source-api for more info export const source = loader({ @@ -30,9 +30,7 @@ export function getFilteredPageTree(rootName: string): PageTree.Root { // Find the main section folder const rootFolder = fullTree.children.find( (child): child is PageTree.Folder => - child.type === 'folder' && - typeof child.name === 'string' && - child.name.toLowerCase() === rootName.toLowerCase(), + child.type === 'folder' && typeof child.name === 'string' && child.name.toLowerCase() === rootName.toLowerCase(), ); if (!rootFolder) { @@ -42,9 +40,7 @@ export function getFilteredPageTree(rootName: string): PageTree.Root { // Find shared section folders const sharedFolders = fullTree.children.filter( (child): child is PageTree.Folder => - child.type === 'folder' && - typeof child.name === 'string' && - SHARED_SECTIONS.includes(child.name.toLowerCase()), + child.type === 'folder' && typeof child.name === 'string' && SHARED_SECTIONS.includes(child.name.toLowerCase()), ); // Create separator for main section diff --git a/apps/docs/src/mdx-components.tsx b/apps/docs/src/mdx-components.tsx index 008027298..298b70960 100644 --- a/apps/docs/src/mdx-components.tsx +++ b/apps/docs/src/mdx-components.tsx @@ -1,7 +1,7 @@ -import { Mermaid } from '@/components/mdx/mermaid'; import * as TabsComponents from 'fumadocs-ui/components/tabs'; import defaultMdxComponents from 'fumadocs-ui/mdx'; import type { MDXComponents } from 'mdx/types'; +import { Mermaid } from '@/components/mdx/mermaid'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export function getMDXComponents(components?: MDXComponents): any { diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json index 77775fb39..0555e582c 100644 --- a/apps/docs/tsconfig.json +++ b/apps/docs/tsconfig.json @@ -2,11 +2,7 @@ "compilerOptions": { "baseUrl": ".", "target": "ESNext", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -20,12 +16,8 @@ "jsx": "react-jsx", "incremental": true, "paths": { - "@/*": [ - "./src/*" - ], - "fumadocs-mdx:collections/*": [ - ".source/*" - ] + "@/*": ["./src/*"], + "fumadocs-mdx:collections/*": [".source/*"] }, "plugins": [ { @@ -33,14 +25,6 @@ } ] }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts", - ".next/dev/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/apps/openpage-api/lib/add-zero-month.ts b/apps/openpage-api/lib/add-zero-month.ts index 91e0d89c7..b20bc7cc5 100644 --- a/apps/openpage-api/lib/add-zero-month.ts +++ b/apps/openpage-api/lib/add-zero-month.ts @@ -10,10 +10,7 @@ export type TransformedData = { const FORMAT = 'MMM yyyy'; -export const addZeroMonth = ( - transformedData: TransformedData, - isCumulative = false, -): TransformedData => { +export const addZeroMonth = (transformedData: TransformedData, isCumulative = false): TransformedData => { const result: TransformedData = { labels: [...transformedData.labels], datasets: transformedData.datasets.map((dataset) => ({ diff --git a/apps/openpage-api/lib/cors.ts b/apps/openpage-api/lib/cors.ts index 2d667ab23..78dcebde5 100644 --- a/apps/openpage-api/lib/cors.ts +++ b/apps/openpage-api/lib/cors.ts @@ -60,7 +60,9 @@ async function originHeadersFromReq(req: Request, origin: StaticOrigin | OriginF const reqOrigin = req.headers.get('Origin') || undefined; const value = typeof origin === 'function' ? await origin(reqOrigin, req) : origin; - if (!value) return; + if (!value) { + return; + } return getOriginHeaders(reqOrigin, value); } @@ -85,12 +87,17 @@ export default async function cors(req: Request, res: Response, options?: CorsOp const { headers } = res; const originHeaders = await originHeadersFromReq(req, opts.origin ?? false); const mergeHeaders = (v: string, k: string) => { - if (k === 'Vary') headers.append(k, v); - else headers.set(k, v); + if (k === 'Vary') { + headers.append(k, v); + } else { + headers.set(k, v); + } }; // If there's no origin we won't touch the response - if (!originHeaders) return res; + if (!originHeaders) { + return res; + } originHeaders.forEach(mergeHeaders); @@ -98,9 +105,7 @@ export default async function cors(req: Request, res: Response, options?: CorsOp headers.set('Access-Control-Allow-Credentials', 'true'); } - const exposed = Array.isArray(opts.exposedHeaders) - ? opts.exposedHeaders.join(',') - : opts.exposedHeaders; + const exposed = Array.isArray(opts.exposedHeaders) ? opts.exposedHeaders.join(',') : opts.exposedHeaders; if (exposed) { headers.set('Access-Control-Expose-Headers', exposed); @@ -120,7 +125,9 @@ export default async function cors(req: Request, res: Response, options?: CorsOp headers.set('Access-Control-Max-Age', String(opts.maxAge)); } - if (opts.preflightContinue) return res; + if (opts.preflightContinue) { + return res; + } headers.set('Content-Length', '0'); return new Response(null, { status: opts.optionsSuccessStatus, headers }); diff --git a/apps/openpage-api/lib/growth/get-monthly-completed-document.ts b/apps/openpage-api/lib/growth/get-monthly-completed-document.ts index b704c04eb..2e1eec095 100644 --- a/apps/openpage-api/lib/growth/get-monthly-completed-document.ts +++ b/apps/openpage-api/lib/growth/get-monthly-completed-document.ts @@ -1,8 +1,7 @@ +import { kyselyPrisma, sql } from '@documenso/prisma'; import { DocumentStatus, EnvelopeType } from '@prisma/client'; import { DateTime } from 'luxon'; -import { kyselyPrisma, sql } from '@documenso/prisma'; - import { addZeroMonth } from '../add-zero-month'; export const getCompletedDocumentsMonthly = async (type: 'count' | 'cumulative' = 'count') => { @@ -30,9 +29,7 @@ export const getCompletedDocumentsMonthly = async (type: 'count' | 'cumulative' datasets: [ { label: type === 'count' ? 'Completed Documents per Month' : 'Total Completed Documents', - data: result - .map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))) - .reverse(), + data: result.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))).reverse(), }, ], }; @@ -40,6 +37,4 @@ export const getCompletedDocumentsMonthly = async (type: 'count' | 'cumulative' return addZeroMonth(transformedData, type === 'cumulative'); }; -export type GetCompletedDocumentsMonthlyResult = Awaited< - ReturnType ->; +export type GetCompletedDocumentsMonthlyResult = Awaited>; diff --git a/apps/openpage-api/lib/growth/get-signer-conversion.ts b/apps/openpage-api/lib/growth/get-signer-conversion.ts index 8d25e3a14..464ae263e 100644 --- a/apps/openpage-api/lib/growth/get-signer-conversion.ts +++ b/apps/openpage-api/lib/growth/get-signer-conversion.ts @@ -1,6 +1,5 @@ -import { DateTime } from 'luxon'; - import { kyselyPrisma, sql } from '@documenso/prisma'; +import { DateTime } from 'luxon'; import { addZeroMonth } from '../add-zero-month'; @@ -29,9 +28,7 @@ export const getSignerConversionMonthly = async (type: 'count' | 'cumulative' = datasets: [ { label: type === 'count' ? 'Signers That Signed Up' : 'Total Signers That Signed Up', - data: result - .map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))) - .reverse(), + data: result.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))).reverse(), }, ], }; @@ -39,6 +36,4 @@ export const getSignerConversionMonthly = async (type: 'count' | 'cumulative' = return addZeroMonth(transformedData, type === 'cumulative'); }; -export type GetSignerConversionMonthlyResult = Awaited< - ReturnType ->; +export type GetSignerConversionMonthlyResult = Awaited>; diff --git a/apps/openpage-api/lib/growth/get-user-monthly-growth.ts b/apps/openpage-api/lib/growth/get-user-monthly-growth.ts index ae428813c..696266d69 100644 --- a/apps/openpage-api/lib/growth/get-user-monthly-growth.ts +++ b/apps/openpage-api/lib/growth/get-user-monthly-growth.ts @@ -1,6 +1,5 @@ -import { DateTime } from 'luxon'; - import { kyselyPrisma, sql } from '@documenso/prisma'; +import { DateTime } from 'luxon'; import { addZeroMonth } from '../add-zero-month'; @@ -26,9 +25,7 @@ export const getUserMonthlyGrowth = async (type: 'count' | 'cumulative' = 'count datasets: [ { label: type === 'count' ? 'New Users' : 'Total Users', - data: result - .map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))) - .reverse(), + data: result.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))).reverse(), }, ], }; diff --git a/apps/openpage-api/lib/transform-data.ts b/apps/openpage-api/lib/transform-data.ts index 801dd4281..cadeaac31 100644 --- a/apps/openpage-api/lib/transform-data.ts +++ b/apps/openpage-api/lib/transform-data.ts @@ -1,6 +1,6 @@ import { DateTime } from 'luxon'; -import { type TransformedData, addZeroMonth } from './add-zero-month'; +import { addZeroMonth, type TransformedData } from './add-zero-month'; type MetricKeys = { stars: number; @@ -24,13 +24,7 @@ const FRIENDLY_METRIC_NAMES: { [key in MetricKey]: string } = { earlyAdopters: 'Customers', }; -export function transformData({ - data, - metric, -}: { - data: DataEntry; - metric: MetricKey; -}): TransformedData { +export function transformData({ data, metric }: { data: DataEntry; metric: MetricKey }): TransformedData { try { if (!data || Object.keys(data).length === 0) { return { diff --git a/apps/remix/app/app.css b/apps/remix/app/app.css index 9255cdb6a..359a10904 100644 --- a/apps/remix/app/app.css +++ b/apps/remix/app/app.css @@ -1,9 +1,9 @@ -@import '@documenso/ui/styles/theme.css'; +@import "@documenso/ui/styles/theme.css"; /* Inter Variable Fonts */ @font-face { - font-family: 'Inter'; - src: url('/fonts/inter-variablefont_opsz,wght.ttf') format('truetype-variations'); + font-family: "Inter"; + src: url("/fonts/inter-variablefont_opsz,wght.ttf") format("truetype-variations"); font-weight: 100 900; font-style: normal; font-display: swap; @@ -11,8 +11,8 @@ /* Inter Italic Variable Fonts */ @font-face { - font-family: 'Inter'; - src: url('/fonts/inter-italic-variablefont_opsz,wght.ttf') format('truetype-variations'); + font-family: "Inter"; + src: url("/fonts/inter-italic-variablefont_opsz,wght.ttf") format("truetype-variations"); font-weight: 100 900; font-style: italic; font-display: swap; @@ -20,16 +20,16 @@ /* Caveat Variable Font */ @font-face { - font-family: 'Caveat'; - src: url('/fonts/caveat-variablefont_wght.ttf') format('truetype-variations'); + font-family: "Caveat"; + src: url("/fonts/caveat-variablefont_wght.ttf") format("truetype-variations"); font-weight: 400 600; font-style: normal; font-display: swap; } @font-face { - font-family: 'Noto Sans'; - src: url('/fonts/noto-sans.ttf') format('truetype-variations'); + font-family: "Noto Sans"; + src: url("/fonts/noto-sans.ttf") format("truetype-variations"); font-weight: 100 900; font-style: normal; font-display: swap; @@ -37,8 +37,8 @@ /* Korean noto sans */ @font-face { - font-family: 'Noto Sans Korean'; - src: url('/fonts/noto-sans-korean.ttf') format('truetype-variations'); + font-family: "Noto Sans Korean"; + src: url("/fonts/noto-sans-korean.ttf") format("truetype-variations"); font-weight: 100 900; font-style: normal; font-display: swap; @@ -46,8 +46,8 @@ /* Japanese noto sans */ @font-face { - font-family: 'Noto Sans Japanese'; - src: url('/fonts/noto-sans-japanese.ttf') format('truetype-variations'); + font-family: "Noto Sans Japanese"; + src: url("/fonts/noto-sans-japanese.ttf") format("truetype-variations"); font-weight: 100 900; font-style: normal; font-display: swap; @@ -55,8 +55,8 @@ /* Chinese noto sans */ @font-face { - font-family: 'Noto Sans Chinese'; - src: url('/fonts/noto-sans-chinese.ttf') format('truetype-variations'); + font-family: "Noto Sans Chinese"; + src: url("/fonts/noto-sans-chinese.ttf") format("truetype-variations"); font-weight: 100 900; font-style: normal; font-display: swap; @@ -64,8 +64,8 @@ @layer base { :root { - --font-sans: 'Inter'; - --font-signature: 'Caveat'; - --font-noto: 'Noto Sans', 'Noto Sans Korean', 'Noto Sans Japanese', 'Noto Sans Chinese'; + --font-sans: "Inter"; + --font-signature: "Caveat"; + --font-noto: "Noto Sans", "Noto Sans Korean", "Noto Sans Japanese", "Noto Sans Chinese"; } } diff --git a/apps/remix/app/components/dialogs/account-delete-dialog.tsx b/apps/remix/app/components/dialogs/account-delete-dialog.tsx index 5c528dfc4..d23a0a74b 100644 --- a/apps/remix/app/components/dialogs/account-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/account-delete-dialog.tsx @@ -1,9 +1,3 @@ -import { useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; - import { authClient } from '@documenso/auth/client'; import { useSession } from '@documenso/lib/client-only/providers/session'; import { trpc } from '@documenso/trpc/react'; @@ -21,6 +15,10 @@ import { import { Input } from '@documenso/ui/primitives/input'; import { Label } from '@documenso/ui/primitives/label'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useState } from 'react'; export type AccountDeleteDialogProps = { className?: string; @@ -36,8 +34,7 @@ export const AccountDeleteDialog = ({ className }: AccountDeleteDialogProps) => const [enteredEmail, setEnteredEmail] = useState(''); - const { mutateAsync: deleteAccount, isPending: isDeletingAccount } = - trpc.profile.deleteAccount.useMutation(); + const { mutateAsync: deleteAccount, isPending: isDeletingAccount } = trpc.profile.deleteAccount.useMutation(); const onDeleteAccount = async () => { try { @@ -63,18 +60,15 @@ export const AccountDeleteDialog = ({ className }: AccountDeleteDialogProps) => return (
- +
Delete Account - Delete your account and all its contents, including completed documents. This action - is irreversible and will cancel your subscription, so proceed with caution. + Delete your account and all its contents, including completed documents. This action is irreversible and + will cancel your subscription, so proceed with caution.
@@ -109,10 +103,8 @@ export const AccountDeleteDialog = ({ className }: AccountDeleteDialogProps) => - Documenso will delete{' '} - all of your documents, along with all of - your completed documents, signatures, and all other resources belonging to your - Account. + Documenso will delete all of your documents, along with all + of your completed documents, signatures, and all other resources belonging to your Account. @@ -121,9 +113,7 @@ export const AccountDeleteDialog = ({ className }: AccountDeleteDialogProps) =>
diff --git a/apps/remix/app/components/dialogs/admin-document-delete-dialog.tsx b/apps/remix/app/components/dialogs/admin-document-delete-dialog.tsx index 076fb0546..9fbf41a19 100644 --- a/apps/remix/app/components/dialogs/admin-document-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/admin-document-delete-dialog.tsx @@ -1,10 +1,3 @@ -import { useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { useNavigate } from 'react-router'; - import { trpc } from '@documenso/trpc/react'; import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert'; import { Button } from '@documenso/ui/primitives/button'; @@ -19,6 +12,11 @@ import { } from '@documenso/ui/primitives/dialog'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useState } from 'react'; +import { useNavigate } from 'react-router'; export type AdminDocumentDeleteDialogProps = { envelopeId: string; @@ -32,8 +30,7 @@ export const AdminDocumentDeleteDialog = ({ envelopeId }: AdminDocumentDeleteDia const [reason, setReason] = useState(''); - const { mutateAsync: deleteDocument, isPending: isDeletingDocument } = - trpc.admin.document.delete.useMutation(); + const { mutateAsync: deleteDocument, isPending: isDeletingDocument } = trpc.admin.document.delete.useMutation(); const handleDeleteDocument = async () => { try { @@ -64,18 +61,13 @@ export const AdminDocumentDeleteDialog = ({ envelopeId }: AdminDocumentDeleteDia return (
- +
Delete Document - - Delete the document. This action is irreversible so proceed with caution. - + Delete the document. This action is irreversible so proceed with caution.
@@ -105,12 +97,7 @@ export const AdminDocumentDeleteDialog = ({ envelopeId }: AdminDocumentDeleteDia To confirm, please enter the reason - setReason(e.target.value)} - /> + setReason(e.target.value)} />
diff --git a/apps/remix/app/components/dialogs/admin-organisation-create-dialog.tsx b/apps/remix/app/components/dialogs/admin-organisation-create-dialog.tsx index 840a4bb5d..d8eb9d35a 100644 --- a/apps/remix/app/components/dialogs/admin-organisation-create-dialog.tsx +++ b/apps/remix/app/components/dialogs/admin-organisation-create-dialog.tsx @@ -1,13 +1,3 @@ -import { useEffect, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { useForm } from 'react-hook-form'; -import { useNavigate } from 'react-router'; -import type { z } from 'zod'; - import { AppError } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import { ZCreateAdminOrganisationRequestSchema } from '@documenso/trpc/server/admin-router/create-admin-organisation.types'; @@ -22,16 +12,16 @@ import { DialogTitle, DialogTrigger, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Trans, useLingui } from '@lingui/react/macro'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { useNavigate } from 'react-router'; +import type { z } from 'zod'; export type OrganisationCreateDialogProps = { trigger?: React.ReactNode; @@ -44,11 +34,7 @@ const ZCreateAdminOrganisationFormSchema = ZCreateAdminOrganisationRequestSchema type TCreateOrganisationFormSchema = z.infer; -export const AdminOrganisationCreateDialog = ({ - trigger, - ownerUserId, - ...props -}: OrganisationCreateDialogProps) => { +export const AdminOrganisationCreateDialog = ({ trigger, ownerUserId, ...props }: OrganisationCreateDialogProps) => { const { t } = useLingui(); const { toast } = useToast(); @@ -101,11 +87,7 @@ export const AdminOrganisationCreateDialog = ({ }, [open, form]); return ( - !form.formState.isSubmitting && setOpen(value)} - > + !form.formState.isSubmitting && setOpen(value)}> e.stopPropagation()} asChild={true}> {trigger ?? ( - diff --git a/apps/remix/app/components/dialogs/admin-user-delete-dialog.tsx b/apps/remix/app/components/dialogs/admin-user-delete-dialog.tsx index 157cc5284..e98f63320 100644 --- a/apps/remix/app/components/dialogs/admin-user-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/admin-user-delete-dialog.tsx @@ -1,11 +1,3 @@ -import { useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { useNavigate } from 'react-router'; -import { match } from 'ts-pattern'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import type { TGetUserResponse } from '@documenso/trpc/server/admin-router/get-user.types'; @@ -22,6 +14,12 @@ import { } from '@documenso/ui/primitives/dialog'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useState } from 'react'; +import { useNavigate } from 'react-router'; +import { match } from 'ts-pattern'; export type AdminUserDeleteDialogProps = { className?: string; @@ -34,8 +32,7 @@ export const AdminUserDeleteDialog = ({ className, user }: AdminUserDeleteDialog const navigate = useNavigate(); const [email, setEmail] = useState(''); - const { mutateAsync: deleteUser, isPending: isDeletingUser } = - trpc.admin.user.delete.useMutation(); + const { mutateAsync: deleteUser, isPending: isDeletingUser } = trpc.admin.user.delete.useMutation(); const onDeleteAccount = async () => { try { @@ -69,16 +66,13 @@ export const AdminUserDeleteDialog = ({ className, user }: AdminUserDeleteDialog return (
- +
Delete Account - Delete the users account and all its contents. This action is irreversible and will - cancel their subscription, so proceed with caution. + Delete the users account and all its contents. This action is irreversible and will cancel their + subscription, so proceed with caution.
@@ -111,12 +105,7 @@ export const AdminUserDeleteDialog = ({ className, user }: AdminUserDeleteDialog - setEmail(e.target.value)} - /> + setEmail(e.target.value)} />
diff --git a/apps/remix/app/components/dialogs/admin-user-disable-dialog.tsx b/apps/remix/app/components/dialogs/admin-user-disable-dialog.tsx index 347532a19..08b5cd2e2 100644 --- a/apps/remix/app/components/dialogs/admin-user-disable-dialog.tsx +++ b/apps/remix/app/components/dialogs/admin-user-disable-dialog.tsx @@ -1,10 +1,3 @@ -import { useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { match } from 'ts-pattern'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import type { TGetUserResponse } from '@documenso/trpc/server/admin-router/get-user.types'; @@ -21,23 +14,24 @@ import { } from '@documenso/ui/primitives/dialog'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useState } from 'react'; +import { match } from 'ts-pattern'; export type AdminUserDisableDialogProps = { className?: string; userToDisable: TGetUserResponse; }; -export const AdminUserDisableDialog = ({ - className, - userToDisable, -}: AdminUserDisableDialogProps) => { +export const AdminUserDisableDialog = ({ className, userToDisable }: AdminUserDisableDialogProps) => { const { _ } = useLingui(); const { toast } = useToast(); const [email, setEmail] = useState(''); - const { mutateAsync: disableUser, isPending: isDisablingUser } = - trpc.admin.user.disable.useMutation(); + const { mutateAsync: disableUser, isPending: isDisablingUser } = trpc.admin.user.disable.useMutation(); const onDisableAccount = async () => { try { @@ -69,16 +63,13 @@ export const AdminUserDisableDialog = ({ return (
- +
Disable Account - Disabling the user results in the user not being able to use the account. It also - disables all the related contents such as subscription, webhooks, teams, and API keys. + Disabling the user results in the user not being able to use the account. It also disables all the related + contents such as subscription, webhooks, teams, and API keys.
@@ -100,9 +91,8 @@ export const AdminUserDisableDialog = ({ - This action is reversible, but please be careful as the account may be - affected permanently (e.g. their settings and contents not being restored - properly). + This action is reversible, but please be careful as the account may be affected permanently (e.g. + their settings and contents not being restored properly). @@ -116,12 +106,7 @@ export const AdminUserDisableDialog = ({ - setEmail(e.target.value)} - /> + setEmail(e.target.value)} />
diff --git a/apps/remix/app/components/dialogs/admin-user-enable-dialog.tsx b/apps/remix/app/components/dialogs/admin-user-enable-dialog.tsx index 64f9aa72d..21a3b7e50 100644 --- a/apps/remix/app/components/dialogs/admin-user-enable-dialog.tsx +++ b/apps/remix/app/components/dialogs/admin-user-enable-dialog.tsx @@ -1,10 +1,3 @@ -import { useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { match } from 'ts-pattern'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import type { TGetUserResponse } from '@documenso/trpc/server/admin-router/get-user.types'; @@ -21,6 +14,11 @@ import { } from '@documenso/ui/primitives/dialog'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useState } from 'react'; +import { match } from 'ts-pattern'; export type AdminUserEnableDialogProps = { className?: string; @@ -33,8 +31,7 @@ export const AdminUserEnableDialog = ({ className, userToEnable }: AdminUserEnab const [email, setEmail] = useState(''); - const { mutateAsync: enableUser, isPending: isEnablingUser } = - trpc.admin.user.enable.useMutation(); + const { mutateAsync: enableUser, isPending: isEnablingUser } = trpc.admin.user.enable.useMutation(); const onEnableAccount = async () => { try { @@ -66,16 +63,13 @@ export const AdminUserEnableDialog = ({ className, userToEnable }: AdminUserEnab return (
- +
Enable Account - Enabling the account results in the user being able to use the account again, and all - the related features such as webhooks, teams, and API keys for example. + Enabling the account results in the user being able to use the account again, and all the related features + such as webhooks, teams, and API keys for example.
@@ -103,20 +97,11 @@ export const AdminUserEnableDialog = ({ className, userToEnable }: AdminUserEnab - setEmail(e.target.value)} - /> + setEmail(e.target.value)} />
- diff --git a/apps/remix/app/components/dialogs/admin-user-reset-two-factor-dialog.tsx b/apps/remix/app/components/dialogs/admin-user-reset-two-factor-dialog.tsx index 59372ecc9..3a63ede2a 100644 --- a/apps/remix/app/components/dialogs/admin-user-reset-two-factor-dialog.tsx +++ b/apps/remix/app/components/dialogs/admin-user-reset-two-factor-dialog.tsx @@ -1,11 +1,3 @@ -import { useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { useRevalidator } from 'react-router'; -import { match } from 'ts-pattern'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import type { TGetUserResponse } from '@documenso/trpc/server/admin-router/get-user.types'; @@ -22,24 +14,26 @@ import { } from '@documenso/ui/primitives/dialog'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useState } from 'react'; +import { useRevalidator } from 'react-router'; +import { match } from 'ts-pattern'; export type AdminUserResetTwoFactorDialogProps = { className?: string; user: TGetUserResponse; }; -export const AdminUserResetTwoFactorDialog = ({ - className, - user, -}: AdminUserResetTwoFactorDialogProps) => { +export const AdminUserResetTwoFactorDialog = ({ className, user }: AdminUserResetTwoFactorDialogProps) => { const { _ } = useLingui(); const { toast } = useToast(); const { revalidate } = useRevalidator(); const [email, setEmail] = useState(''); const [open, setOpen] = useState(false); - const { mutateAsync: resetTwoFactor, isPending: isResettingTwoFactor } = - trpc.admin.user.resetTwoFactor.useMutation(); + const { mutateAsync: resetTwoFactor, isPending: isResettingTwoFactor } = trpc.admin.user.resetTwoFactor.useMutation(); const onResetTwoFactor = async () => { try { @@ -64,9 +58,7 @@ export const AdminUserResetTwoFactorDialog = ({ AppErrorCode.UNAUTHORIZED, () => msg`You are not authorized to reset two factor authentcation for this user.`, ) - .otherwise( - () => msg`An error occurred while resetting two factor authentication for the user.`, - ); + .otherwise(() => msg`An error occurred while resetting two factor authentication for the user.`); toast({ title: _(msg`Error`), @@ -87,16 +79,13 @@ export const AdminUserResetTwoFactorDialog = ({ return (
- +
Reset Two Factor Authentication - Reset the users two factor authentication. This action is irreversible and will - disable two factor authentication for the user. + Reset the users two factor authentication. This action is irreversible and will disable two factor + authentication for the user.
@@ -119,8 +108,7 @@ export const AdminUserResetTwoFactorDialog = ({ - This action is irreversible. Please ensure you have informed the user before - proceeding. + This action is irreversible. Please ensure you have informed the user before proceeding. @@ -132,12 +120,7 @@ export const AdminUserResetTwoFactorDialog = ({ - setEmail(e.target.value)} - /> + setEmail(e.target.value)} />
diff --git a/apps/remix/app/components/dialogs/ai-features-enable-dialog.tsx b/apps/remix/app/components/dialogs/ai-features-enable-dialog.tsx index 20c2c1e8e..8508c49a9 100644 --- a/apps/remix/app/components/dialogs/ai-features-enable-dialog.tsx +++ b/apps/remix/app/components/dialogs/ai-features-enable-dialog.tsx @@ -1,20 +1,11 @@ -import { useState } from 'react'; - -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import { OrganisationMemberRole, TeamMemberRole } from '@prisma/client'; - import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { trpc } from '@documenso/trpc/react'; import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; import { Button } from '@documenso/ui/primitives/button'; -import { - Dialog, - DialogContent, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@documenso/ui/primitives/dialog'; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@documenso/ui/primitives/dialog'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { OrganisationMemberRole, TeamMemberRole } from '@prisma/client'; +import { useState } from 'react'; import { useCurrentTeam } from '~/providers/team'; @@ -24,11 +15,7 @@ type AiFeaturesEnableDialogProps = { onEnabled: () => void; }; -export const AiFeaturesEnableDialog = ({ - open, - onOpenChange, - onEnabled, -}: AiFeaturesEnableDialogProps) => { +export const AiFeaturesEnableDialog = ({ open, onOpenChange, onEnabled }: AiFeaturesEnableDialogProps) => { const { t } = useLingui(); const team = useCurrentTeam(); @@ -71,11 +58,7 @@ export const AiFeaturesEnableDialog = ({ onOpenChange(false); } catch (err) { console.error('Failed to enable AI features', err); - setError( - err instanceof Error - ? err.message - : t`We couldn't enable AI features right now. Please try again.`, - ); + setError(err instanceof Error ? err.message : t`We couldn't enable AI features right now. Please try again.`); } }; @@ -89,39 +72,38 @@ export const AiFeaturesEnableDialog = ({
-

+

- Turn on AI detection to automatically find recipients and fields in your documents. AI - providers do not retain your data for training. + Turn on AI detection to automatically find recipients and fields in your documents. AI providers do not + retain your data for training.

- Your document content will be sent securely to our AI provider solely for detection - and will not be stored or used for training. + Your document content will be sent securely to our AI provider solely for detection and will not be + stored or used for training. {canEnableAiFeatures ? ( -

+

- You're an admin. You can enable AI features for this team right away. Everyone on - the team will see AI detection once enabled. + You're an admin. You can enable AI features for this team right away. Everyone on the team will see AI + detection once enabled.

) : ( -

+

- AI features are disabled for your team. Please ask your team owner or organisation - owner to enable them. + AI features are disabled for your team. Please ask your team owner or organisation owner to enable them.

)} - {error ?

{error}

: null} + {error ?

{error}

: null}
diff --git a/apps/remix/app/components/dialogs/ai-field-detection-dialog.tsx b/apps/remix/app/components/dialogs/ai-field-detection-dialog.tsx index 748966960..62f59d9dc 100644 --- a/apps/remix/app/components/dialogs/ai-field-detection-dialog.tsx +++ b/apps/remix/app/components/dialogs/ai-field-detection-dialog.tsx @@ -1,29 +1,17 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; - +import type { NormalizedFieldWithContext } from '@documenso/lib/server-only/ai/envelope/detect-fields/types'; +import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; +import { Button } from '@documenso/ui/primitives/button'; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@documenso/ui/primitives/dialog'; +import { Label } from '@documenso/ui/primitives/label'; +import { Textarea } from '@documenso/ui/primitives/textarea'; import type { MessageDescriptor } from '@lingui/core'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Plural, Trans } from '@lingui/react/macro'; import { CheckIcon, FormInputIcon, ShieldCheckIcon } from 'lucide-react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; -import type { NormalizedFieldWithContext } from '@documenso/lib/server-only/ai/envelope/detect-fields/types'; -import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; -import { Button } from '@documenso/ui/primitives/button'; -import { - Dialog, - DialogContent, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@documenso/ui/primitives/dialog'; -import { Label } from '@documenso/ui/primitives/label'; -import { Textarea } from '@documenso/ui/primitives/textarea'; - -import { - AiApiError, - type DetectFieldsProgressEvent, - detectFields, -} from '../../../server/api/ai/detect-fields.client'; +import { AiApiError, type DetectFieldsProgressEvent, detectFields } from '../../../server/api/ai/detect-fields.client'; import { AnimatedDocumentScanner } from '../general/animated-document-scanner'; type DialogState = 'PROMPT' | 'PROCESSING' | 'REVIEW' | 'ERROR' | 'RATE_LIMITED'; @@ -171,20 +159,17 @@ export const AiFieldDetectionDialog = ({
-

+

- We'll scan your document to find form fields like signature lines, text inputs, - checkboxes, and more. Detected fields will be suggested for you to review. + We'll scan your document to find form fields like signature lines, text inputs, checkboxes, and more. + Detected fields will be suggested for you to review.

- - Your document is processed securely using AI services that don't retain your - data. - + Your document is processed securely using AI services that don't retain your data. @@ -200,7 +185,7 @@ export const AiFieldDetectionDialog = ({ rows={2} className="resize-none" /> -

+

Help the AI assign fields to the right recipients.

@@ -231,7 +216,7 @@ export const AiFieldDetectionDialog = ({

{_(PROCESSING_MESSAGES[messageIndex])}

{progress && ( -

+

)} -

+

This can take a minute or two depending on the size of your document.

@@ -278,16 +263,16 @@ export const AiFieldDetectionDialog = ({ {detectedFields.length === 0 ? (
-

+

No fields were detected in your document.

-

+

You can add fields manually in the editor.

) : ( <> -

+

(

  • {_(FIELD_TYPE_LABELS[type]) || type} - {count} + {count}
  • ))} @@ -314,7 +299,7 @@ export const AiFieldDetectionDialog = ({ {detectedFields.length > 0 && ( )} @@ -331,11 +316,11 @@ export const AiFieldDetectionDialog = ({
    -

    +

    Something went wrong while detecting fields.

    - {error &&

    {error}

    } + {error &&

    {error}

    }
    @@ -358,10 +343,8 @@ export const AiFieldDetectionDialog = ({
    -

    - - You've made too many detection requests. Please wait a minute before trying again. - +

    + You've made too many detection requests. Please wait a minute before trying again.

    diff --git a/apps/remix/app/components/dialogs/ai-recipient-detection-dialog.tsx b/apps/remix/app/components/dialogs/ai-recipient-detection-dialog.tsx index cef7903c9..b0759e638 100644 --- a/apps/remix/app/components/dialogs/ai-recipient-detection-dialog.tsx +++ b/apps/remix/app/components/dialogs/ai-recipient-detection-dialog.tsx @@ -1,22 +1,14 @@ -import { useCallback, useEffect, useState } from 'react'; - -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Plural, Trans } from '@lingui/react/macro'; -import { CheckIcon, ShieldCheckIcon, UserIcon, XIcon } from 'lucide-react'; - import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles'; import type { TDetectedRecipientSchema } from '@documenso/lib/server-only/ai/envelope/detect-recipients/schema'; import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; import { AvatarWithText } from '@documenso/ui/primitives/avatar'; import { Button } from '@documenso/ui/primitives/button'; -import { - Dialog, - DialogContent, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@documenso/ui/primitives/dialog'; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@documenso/ui/primitives/dialog'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Plural, Trans } from '@lingui/react/macro'; +import { CheckIcon, ShieldCheckIcon, UserIcon, XIcon } from 'lucide-react'; +import { useCallback, useEffect, useState } from 'react'; import { AiApiError, @@ -146,20 +138,17 @@ export const AiRecipientDetectionDialog = ({
    -

    +

    - We'll scan your document to find signature fields and identify who needs to sign. - Detected recipients will be suggested for you to review. + We'll scan your document to find signature fields and identify who needs to sign. Detected recipients + will be suggested for you to review.

    - - Your document is processed securely using AI services that don't retain your - data. - + Your document is processed securely using AI services that don't retain your data.
    @@ -189,7 +178,7 @@ export const AiRecipientDetectionDialog = ({

    {_(PROCESSING_MESSAGES[messageIndex])}

    {progress && ( -

    +

    )} -

    +

    This can take a minute or two depending on the size of your document.

    @@ -236,16 +225,16 @@ export const AiRecipientDetectionDialog = ({ {detectedRecipients.length === 0 ? (
    -

    +

    No recipients were detected in your document.

    -

    +

    You can add recipients manually in the editor.

    ) : ( <> -

    +

    +

    {recipient.name || _(msg`Unknown name`)}

    } secondaryText={ -
    -

    +

    +

    {recipient.email || _(msg`No email detected`)}

    {_(RECIPIENT_ROLES_DESCRIPTION[recipient.role].roleName)}

    @@ -304,7 +293,7 @@ export const AiRecipientDetectionDialog = ({ {detectedRecipients.length > 0 && ( )} @@ -321,11 +310,11 @@ export const AiRecipientDetectionDialog = ({
    -

    +

    Something went wrong while detecting recipients.

    - {error &&

    {error}

    } + {error &&

    {error}

    }
    @@ -349,10 +338,8 @@ export const AiRecipientDetectionDialog = ({
    -

    - - You've made too many detection requests. Please wait a minute before trying again. - +

    + You've made too many detection requests. Please wait a minute before trying again.

    diff --git a/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx b/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx index b6c38e4d0..02297dae9 100644 --- a/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx +++ b/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx @@ -1,10 +1,3 @@ -import { useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { Trans, useLingui } from '@lingui/react/macro'; -import { useForm } from 'react-hook-form'; -import { z } from 'zod'; - import { zEmail } from '@documenso/lib/utils/zod'; import { Button } from '@documenso/ui/primitives/button'; import { @@ -15,15 +8,13 @@ import { DialogHeader, DialogTitle, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; import { DocumentSigningDisclosure } from '../general/document-signing/document-signing-disclosure'; @@ -104,9 +95,8 @@ export function AssistantConfirmationDialog({ - Are you sure you want to complete the document? This action cannot be undone. - Please ensure that you have completed prefilling all relevant fields before - proceeding. + Are you sure you want to complete the document? This action cannot be undone. Please ensure that you + have completed prefilling all relevant fields before proceeding. @@ -116,7 +106,7 @@ export function AssistantConfirmationDialog({
    {!isEditingNextSigner && (
    -

    +

    The next recipient to sign this document will be{' '} {form.watch('name')} ( @@ -147,11 +137,7 @@ export function AssistantConfirmationDialog({ Name - + diff --git a/apps/remix/app/components/dialogs/claim-create-dialog.tsx b/apps/remix/app/components/dialogs/claim-create-dialog.tsx index b308fa485..88c936e5f 100644 --- a/apps/remix/app/components/dialogs/claim-create-dialog.tsx +++ b/apps/remix/app/components/dialogs/claim-create-dialog.tsx @@ -1,8 +1,3 @@ -import { useState } from 'react'; - -import { Trans, useLingui } from '@lingui/react/macro'; -import type { z } from 'zod'; - import type { TLicenseClaim } from '@documenso/lib/types/license'; import { generateDefaultSubscriptionClaim } from '@documenso/lib/utils/organisations-claims'; import { trpc } from '@documenso/trpc/react'; @@ -18,6 +13,9 @@ import { DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { useState } from 'react'; +import type { z } from 'zod'; import { SubscriptionClaimForm } from '../forms/subscription-claim-form'; @@ -75,12 +73,7 @@ export const ClaimCreateDialog = ({ licenseFlags }: ClaimCreateDialogProps) => { licenseFlags={licenseFlags} formSubmitTrigger={ - diff --git a/apps/remix/app/components/dialogs/claim-delete-dialog.tsx b/apps/remix/app/components/dialogs/claim-delete-dialog.tsx index 61124fa9d..d63a3cf1f 100644 --- a/apps/remix/app/components/dialogs/claim-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/claim-delete-dialog.tsx @@ -1,7 +1,3 @@ -import { useState } from 'react'; - -import { Trans, useLingui } from '@lingui/react/macro'; - import { trpc } from '@documenso/trpc/react'; import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; import { Button } from '@documenso/ui/primitives/button'; @@ -15,6 +11,8 @@ import { DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { useState } from 'react'; export type ClaimDeleteDialogProps = { claimId: string; @@ -23,12 +21,7 @@ export type ClaimDeleteDialogProps = { trigger: React.ReactNode; }; -export const ClaimDeleteDialog = ({ - claimId, - claimName, - claimLocked, - trigger, -}: ClaimDeleteDialogProps) => { +export const ClaimDeleteDialog = ({ claimId, claimName, claimLocked, trigger }: ClaimDeleteDialogProps) => { const { t } = useLingui(); const { toast } = useToast(); diff --git a/apps/remix/app/components/dialogs/claim-update-dialog.tsx b/apps/remix/app/components/dialogs/claim-update-dialog.tsx index 01057910b..bcbd91a56 100644 --- a/apps/remix/app/components/dialogs/claim-update-dialog.tsx +++ b/apps/remix/app/components/dialogs/claim-update-dialog.tsx @@ -1,7 +1,3 @@ -import { useState } from 'react'; - -import { Trans, useLingui } from '@lingui/react/macro'; - import type { TLicenseClaim } from '@documenso/lib/types/license'; import { trpc } from '@documenso/trpc/react'; import type { TFindSubscriptionClaimsResponse } from '@documenso/trpc/server/admin-router/find-subscription-claims.types'; @@ -16,6 +12,8 @@ import { DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { useState } from 'react'; import { SubscriptionClaimForm } from '../forms/subscription-claim-form'; @@ -74,12 +72,7 @@ export const ClaimUpdateDialog = ({ claim, trigger, licenseFlags }: ClaimUpdateD licenseFlags={licenseFlags} formSubmitTrigger={ - diff --git a/apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx b/apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx index 45ec1465a..694f2d56a 100644 --- a/apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx +++ b/apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx @@ -1,15 +1,3 @@ -import { useEffect, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { FolderIcon, HomeIcon, Loader2, Search } from 'lucide-react'; -import { useForm } from 'react-hook-form'; -import { useNavigate } from 'react-router'; -import { z } from 'zod'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { FolderType } from '@documenso/lib/types/folder-type'; import { formatDocumentsPath } from '@documenso/lib/utils/teams'; @@ -23,16 +11,19 @@ import { DialogHeader, DialogTitle, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { FolderIcon, HomeIcon, Loader2, Search } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { useNavigate } from 'react-router'; +import { z } from 'zod'; import { useCurrentTeam } from '~/providers/team'; @@ -165,7 +156,7 @@ export const DocumentMoveToFolderDialog = ({

    - + +
    No folders found
    )} @@ -239,9 +230,7 @@ export const DocumentMoveToFolderDialog = ({ diff --git a/apps/remix/app/components/dialogs/document-resend-dialog.tsx b/apps/remix/app/components/dialogs/document-resend-dialog.tsx index d8c0a73ee..dc2a81289 100644 --- a/apps/remix/app/components/dialogs/document-resend-dialog.tsx +++ b/apps/remix/app/components/dialogs/document-resend-dialog.tsx @@ -1,14 +1,3 @@ -import { useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { type Recipient, SigningStatus, type Team, type User } from '@prisma/client'; -import { History } from 'lucide-react'; -import { useForm, useWatch } from 'react-hook-form'; -import * as z from 'zod'; - import { useSession } from '@documenso/lib/client-only/providers/session'; import { getRecipientType } from '@documenso/lib/client-only/recipient-type'; import { recipientAbbreviation } from '@documenso/lib/utils/recipient-formatter'; @@ -27,14 +16,17 @@ import { DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { DropdownMenuItem } from '@documenso/ui/primitives/dropdown-menu'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel } from '@documenso/ui/primitives/form/form'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { type Recipient, SigningStatus, type Team, type User } from '@prisma/client'; +import { History } from 'lucide-react'; +import { useState } from 'react'; +import { useForm, useWatch } from 'react-hook-form'; +import * as z from 'zod'; import { useCurrentTeam } from '~/providers/team'; @@ -141,10 +133,7 @@ export const DocumentResendDialog = ({ document, recipients }: DocumentResendDia render={({ field: { value, onChange } }) => ( <> {recipients.map((recipient) => ( - + diff --git a/apps/remix/app/components/dialogs/envelopes-bulk-move-dialog.tsx b/apps/remix/app/components/dialogs/envelopes-bulk-move-dialog.tsx index be50e85a2..f0c81da77 100644 --- a/apps/remix/app/components/dialogs/envelopes-bulk-move-dialog.tsx +++ b/apps/remix/app/components/dialogs/envelopes-bulk-move-dialog.tsx @@ -1,15 +1,3 @@ -import { useEffect, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { Plural, useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import { EnvelopeType } from '@prisma/client'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { FolderIcon, HomeIcon, Loader2, Search } from 'lucide-react'; -import { useForm } from 'react-hook-form'; -import { match } from 'ts-pattern'; -import { z } from 'zod'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; @@ -21,16 +9,18 @@ import { DialogHeader, DialogTitle, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Plural, Trans, useLingui } from '@lingui/react/macro'; +import { EnvelopeType } from '@prisma/client'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { FolderIcon, HomeIcon, Loader2, Search } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { match } from 'ts-pattern'; +import { z } from 'zod'; export type EnvelopesBulkMoveDialogProps = { envelopeIds: string[]; @@ -119,10 +109,7 @@ export const EnvelopesBulkMoveDialog = ({ const error = AppError.parseError(err); const errorMessage = match(error.code) - .with( - AppErrorCode.NOT_FOUND, - () => t`The folder you are trying to move the items to does not exist.`, - ) + .with(AppErrorCode.NOT_FOUND, () => t`The folder you are trying to move the items to does not exist.`) .with(AppErrorCode.UNAUTHORIZED, () => t`You are not allowed to move these items.`) .with(AppErrorCode.INVALID_BODY, () => t`All items must be of the same type.`) .otherwise(() => t`An error occurred while moving the items.`); @@ -143,11 +130,7 @@ export const EnvelopesBulkMoveDialog = ({ - {isDocument ? ( - Move Documents to Folder - ) : ( - Move Templates to Folder - )} + {isDocument ? Move Documents to Folder : Move Templates to Folder} @@ -168,7 +151,7 @@ export const EnvelopesBulkMoveDialog = ({
    - + +
    No folders found
    )} diff --git a/apps/remix/app/components/dialogs/folder-create-dialog.tsx b/apps/remix/app/components/dialogs/folder-create-dialog.tsx index f7623885f..c2cf21eaa 100644 --- a/apps/remix/app/components/dialogs/folder-create-dialog.tsx +++ b/apps/remix/app/components/dialogs/folder-create-dialog.tsx @@ -1,14 +1,3 @@ -import { useEffect, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { Trans, useLingui } from '@lingui/react/macro'; -import type { FolderType } from '@prisma/client'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { FolderPlusIcon } from 'lucide-react'; -import { useForm } from 'react-hook-form'; -import { useParams } from 'react-router'; -import { z } from 'zod'; - import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import { @@ -20,16 +9,18 @@ import { DialogTitle, DialogTrigger, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Trans, useLingui } from '@lingui/react/macro'; +import type { FolderType } from '@prisma/client'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { FolderPlusIcon } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { useParams } from 'react-router'; +import { z } from 'zod'; const ZCreateFolderFormSchema = z.object({ name: z.string().min(1, { message: 'Folder name is required' }), @@ -43,12 +34,7 @@ export type FolderCreateDialogProps = { parentFolderId?: string | null; } & Omit; -export const FolderCreateDialog = ({ - type, - trigger, - parentFolderId, - ...props -}: FolderCreateDialogProps) => { +export const FolderCreateDialog = ({ type, trigger, parentFolderId, ...props }: FolderCreateDialogProps) => { const { t } = useLingui(); const { toast } = useToast(); const { folderId } = useParams(); @@ -98,11 +84,7 @@ export const FolderCreateDialog = ({ {trigger ?? ( - @@ -139,11 +121,7 @@ export const FolderCreateDialog = ({ /> - diff --git a/apps/remix/app/components/dialogs/folder-delete-dialog.tsx b/apps/remix/app/components/dialogs/folder-delete-dialog.tsx index cec8b1da0..e05f943b3 100644 --- a/apps/remix/app/components/dialogs/folder-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/folder-delete-dialog.tsx @@ -1,12 +1,3 @@ -import { useEffect } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { useForm } from 'react-hook-form'; -import { z } from 'zod'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import type { TFolderWithSubfolders } from '@documenso/trpc/server/folder-router/schema'; @@ -20,16 +11,15 @@ import { DialogHeader, DialogTitle, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Trans, useLingui } from '@lingui/react/macro'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { useEffect } from 'react'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; export type FolderDeleteDialogProps = { folder: TFolderWithSubfolders; @@ -110,14 +100,12 @@ export const FolderDeleteDialog = ({ folder, isOpen, onOpenChange }: FolderDelet - {(folder._count.documents > 0 || - folder._count.templates > 0 || - folder._count.subfolders > 0) && ( + {(folder._count.documents > 0 || folder._count.templates > 0 || folder._count.subfolders > 0) && ( - This folder contains multiple items. Deleting it will remove all subfolders and move - all nested documents and templates to the root folder. + This folder contains multiple items. Deleting it will remove all subfolders and move all nested + documents and templates to the root folder. @@ -134,9 +122,7 @@ export const FolderDeleteDialog = ({ folder, isOpen, onOpenChange }: FolderDelet Confirm by typing:{' '} - - {deleteMessage} - + {deleteMessage} diff --git a/apps/remix/app/components/dialogs/folder-move-dialog.tsx b/apps/remix/app/components/dialogs/folder-move-dialog.tsx index b12922a6a..c4cc84c9a 100644 --- a/apps/remix/app/components/dialogs/folder-move-dialog.tsx +++ b/apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -1,13 +1,3 @@ -import { useEffect, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { FolderIcon, HomeIcon, Search } from 'lucide-react'; -import { useForm } from 'react-hook-form'; -import { z } from 'zod'; - import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; import type { TFolderWithSubfolders } from '@documenso/trpc/server/folder-router/schema'; @@ -20,15 +10,16 @@ import { DialogHeader, DialogTitle, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Trans, useLingui } from '@lingui/react/macro'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { FolderIcon, HomeIcon, Search } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; export type FolderMoveDialogProps = { foldersData: TFolderWithSubfolders[] | undefined; @@ -43,12 +34,7 @@ const ZMoveFolderFormSchema = z.object({ type TMoveFolderFormSchema = z.infer; -export const FolderMoveDialog = ({ - foldersData, - folder, - isOpen, - onOpenChange, -}: FolderMoveDialogProps) => { +export const FolderMoveDialog = ({ foldersData, folder, isOpen, onOpenChange }: FolderMoveDialogProps) => { const { t } = useLingui(); const { toast } = useToast(); const [searchTerm, setSearchTerm] = useState(''); @@ -129,7 +115,7 @@ export const FolderMoveDialog = ({
    - + ( - IS_BILLING_ENABLED() ? 'billing' : 'create', - ); + const [step, setStep] = useState<'billing' | 'create'>(IS_BILLING_ENABLED() ? 'billing' : 'create'); const [selectedPriceId, setSelectedPriceId] = useState(''); @@ -145,11 +133,7 @@ export const OrganisationCreateDialog = ({ trigger, ...props }: OrganisationCrea }; return ( - !form.formState.isSubmitting && setOpen(value)} - > + !form.formState.isSubmitting && setOpen(value)}> e.stopPropagation()} asChild={true}> {trigger ?? ( ) : ( @@ -290,30 +267,23 @@ type BillingPlanFormProps = { canCreateFreeOrganisation: boolean; }; -const BillingPlanForm = ({ - value, - onChange, - plans, - canCreateFreeOrganisation, -}: BillingPlanFormProps) => { +const BillingPlanForm = ({ value, onChange, plans, canCreateFreeOrganisation }: BillingPlanFormProps) => { const { t } = useLingui(); const [billingPeriod, setBillingPeriod] = useState<'monthlyPrice' | 'yearlyPrice'>('yearlyPrice'); const dynamicPlans = useMemo(() => { - return [INTERNAL_CLAIM_ID.INDIVIDUAL, INTERNAL_CLAIM_ID.TEAM, INTERNAL_CLAIM_ID.PLATFORM].map( - (planId) => { - const plan = plans[planId]; + return [INTERNAL_CLAIM_ID.INDIVIDUAL, INTERNAL_CLAIM_ID.TEAM, INTERNAL_CLAIM_ID.PLATFORM].map((planId) => { + const plan = plans[planId]; - return { - id: planId, - name: plan.name, - description: parseMessageDescriptorMacro(t, internalClaimsDescription[planId]), - monthlyPrice: plan.monthlyPrice, - yearlyPrice: plan.yearlyPrice, - }; - }, - ); + return { + id: planId, + name: plan.name, + description: parseMessageDescriptorMacro(t, internalClaimsDescription[planId]), + monthlyPrice: plan.monthlyPrice, + yearlyPrice: plan.yearlyPrice, + }; + }); }, [plans]); useEffect(() => { @@ -357,9 +327,9 @@ const BillingPlanForm = ({
    -
    +

    {plan[billingPeriod]?.friendlyPrice}

    - {billingPeriod === 'monthlyPrice' ? ( - per month - ) : ( - per year - )} + {billingPeriod === 'monthlyPrice' ? per month : per year}
    @@ -417,13 +382,13 @@ const BillingPlanForm = ({
    -

    +

    Enterprise

    -

    +

    Contact sales here

    @@ -434,7 +399,7 @@ const BillingPlanForm = ({
    Compare all plans and features in detail diff --git a/apps/remix/app/components/dialogs/organisation-delete-dialog.tsx b/apps/remix/app/components/dialogs/organisation-delete-dialog.tsx index 10b53833b..fff29a8bd 100644 --- a/apps/remix/app/components/dialogs/organisation-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/organisation-delete-dialog.tsx @@ -1,13 +1,3 @@ -import { useEffect, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { useForm } from 'react-hook-form'; -import { useNavigate } from 'react-router'; -import { z } from 'zod'; - import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { useSession } from '@documenso/lib/client-only/providers/session'; import { AppError } from '@documenso/lib/errors/app-error'; @@ -22,16 +12,17 @@ import { DialogTitle, DialogTrigger, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Trans } from '@lingui/react/macro'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { useNavigate } from 'react-router'; +import { z } from 'zod'; export type OrganisationDeleteDialogProps = { trigger?: React.ReactNode; @@ -117,19 +108,16 @@ export const OrganisationDeleteDialog = ({ trigger }: OrganisationDeleteDialogPr - You are about to delete {organisation.name}. - All data related to this organisation such as teams, documents, and all other - resources will be deleted. This action is irreversible. + You are about to delete {organisation.name}. All data related to + this organisation such as teams, documents, and all other resources will be deleted. This action is + irreversible. -
    +
    { @@ -176,14 +173,14 @@ export const OrganisationEmailCreateDialog = ({ }} placeholder={t`support`} /> -
    +
    @{emailDomain.domain}
    {!form.formState.errors.email && ( - + {field.value ? ( field.value ) : ( @@ -225,11 +222,7 @@ export const OrganisationEmailCreateDialog = ({ Cancel - diff --git a/apps/remix/app/components/dialogs/organisation-email-delete-dialog.tsx b/apps/remix/app/components/dialogs/organisation-email-delete-dialog.tsx index 5f48ce9f1..8438d8772 100644 --- a/apps/remix/app/components/dialogs/organisation-email-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/organisation-email-delete-dialog.tsx @@ -1,8 +1,3 @@ -import { useState } from 'react'; - -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; - import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { trpc } from '@documenso/trpc/react'; import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; @@ -17,6 +12,8 @@ import { DialogTrigger, } from '@documenso/ui/primitives/dialog'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { useState } from 'react'; export type OrganisationEmailDeleteDialogProps = { emailId: string; @@ -24,11 +21,7 @@ export type OrganisationEmailDeleteDialogProps = { trigger?: React.ReactNode; }; -export const OrganisationEmailDeleteDialog = ({ - trigger, - emailId, - email, -}: OrganisationEmailDeleteDialogProps) => { +export const OrganisationEmailDeleteDialog = ({ trigger, emailId, email }: OrganisationEmailDeleteDialogProps) => { const [open, setOpen] = useState(false); const { t } = useLingui(); @@ -36,26 +29,25 @@ export const OrganisationEmailDeleteDialog = ({ const organisation = useCurrentOrganisation(); - const { mutateAsync: deleteEmail, isPending: isDeleting } = - trpc.enterprise.organisation.email.delete.useMutation({ - onSuccess: () => { - toast({ - title: t`Success`, - description: t`You have successfully removed this email from the organisation.`, - duration: 5000, - }); + const { mutateAsync: deleteEmail, isPending: isDeleting } = trpc.enterprise.organisation.email.delete.useMutation({ + onSuccess: () => { + toast({ + title: t`Success`, + description: t`You have successfully removed this email from the organisation.`, + duration: 5000, + }); - setOpen(false); - }, - onError: () => { - toast({ - title: t`An unknown error occurred`, - description: t`We encountered an unknown error while attempting to remove this email. Please try again later.`, - variant: 'destructive', - duration: 10000, - }); - }, - }); + setOpen(false); + }, + onError: () => { + toast({ + title: t`An unknown error occurred`, + description: t`We encountered an unknown error while attempting to remove this email. Please try again later.`, + variant: 'destructive', + duration: 10000, + }); + }, + }); return ( !isDeleting && setOpen(value)}> diff --git a/apps/remix/app/components/dialogs/organisation-email-domain-create-dialog.tsx b/apps/remix/app/components/dialogs/organisation-email-domain-create-dialog.tsx index d51967b1d..ca57ebac5 100644 --- a/apps/remix/app/components/dialogs/organisation-email-domain-create-dialog.tsx +++ b/apps/remix/app/components/dialogs/organisation-email-domain-create-dialog.tsx @@ -1,12 +1,3 @@ -import { useEffect, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { useLingui } from '@lingui/react/macro'; -import { Trans } from '@lingui/react/macro'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { useForm } from 'react-hook-form'; -import type { z } from 'zod'; - import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { trpc } from '@documenso/trpc/react'; @@ -32,6 +23,12 @@ import { } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Trans, useLingui } from '@lingui/react/macro'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import type { z } from 'zod'; import { OrganisationEmailDomainRecordContent } from './organisation-email-domain-records-dialog'; @@ -43,9 +40,7 @@ const ZCreateOrganisationEmailDomainFormSchema = ZCreateOrganisationEmailDomainR domain: true, }); -type TCreateOrganisationEmailDomainFormSchema = z.infer< - typeof ZCreateOrganisationEmailDomainFormSchema ->; +type TCreateOrganisationEmailDomainFormSchema = z.infer; type DomainRecord = { name: string; @@ -53,10 +48,7 @@ type DomainRecord = { type: string; }; -export const OrganisationEmailDomainCreateDialog = ({ - trigger, - ...props -}: OrganisationEmailCreateDialogProps) => { +export const OrganisationEmailDomainCreateDialog = ({ trigger, ...props }: OrganisationEmailCreateDialogProps) => { const { t } = useLingui(); const { toast } = useToast(); const organisation = useCurrentOrganisation(); @@ -72,8 +64,7 @@ export const OrganisationEmailDomainCreateDialog = ({ }, }); - const { mutateAsync: createOrganisationEmail } = - trpc.enterprise.organisation.emailDomain.create.useMutation(); + const { mutateAsync: createOrganisationEmail } = trpc.enterprise.organisation.emailDomain.create.useMutation(); // Reset state when dialog closes useEffect(() => { @@ -119,11 +110,7 @@ export const OrganisationEmailDomainCreateDialog = ({ }; return ( - !form.formState.isSubmitting && setOpen(value)} - > + !form.formState.isSubmitting && setOpen(value)}> e.stopPropagation()} asChild={true}> {trigger ?? ( )} @@ -154,19 +141,13 @@ export const PasskeyCreateDialog = ({ trigger, onSuccess, ...props }: PasskeyCre - - Passkeys allow you to sign in and authenticate using biometrics, password managers, - etc. - + Passkeys allow you to sign in and authenticate using biometrics, password managers, etc. -
    +
    - When you click continue, you will be prompted to add the first available - authenticator on your system. + When you click continue, you will be prompted to add the first available authenticator on your + system. - If you do not want to use the authenticator prompted, you can close it, which - will then display the next available authenticator. + If you do not want to use the authenticator prompted, you can close it, which will then display the + next available authenticator. @@ -219,9 +200,7 @@ export const PasskeyCreateDialog = ({ trigger, onSuccess, ...props }: PasskeyCre .with('InvalidStateError', () => ( <> - - Passkey creation cancelled due to one of the following reasons: - + Passkey creation cancelled due to one of the following reasons:
      diff --git a/apps/remix/app/components/dialogs/public-profile-template-manage-dialog.tsx b/apps/remix/app/components/dialogs/public-profile-template-manage-dialog.tsx index 4ef2de031..53c61af2d 100644 --- a/apps/remix/app/components/dialogs/public-profile-template-manage-dialog.tsx +++ b/apps/remix/app/components/dialogs/public-profile-template-manage-dialog.tsx @@ -1,17 +1,4 @@ -import { useEffect, useMemo, useState } from 'react'; - -import { zodResolver } from '@hookform/resolvers/zod'; -import { msg } from '@lingui/core/macro'; -import { useLingui } from '@lingui/react'; -import { Plural, Trans } from '@lingui/react/macro'; -import { type TemplateDirectLink, TemplateType } from '@prisma/client'; -import type * as DialogPrimitive from '@radix-ui/react-dialog'; -import { CheckCircle2Icon, CircleIcon } from 'lucide-react'; -import { useForm } from 'react-hook-form'; -import { P, match } from 'ts-pattern'; -import { z } from 'zod'; - -import { type Template } from '@documenso/prisma/types/template-legacy-schema'; +import type { Template } from '@documenso/prisma/types/template-legacy-schema'; import { trpc } from '@documenso/trpc/react'; import { MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH, @@ -29,25 +16,22 @@ import { DialogTitle, DialogTrigger, } from '@documenso/ui/primitives/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@documenso/ui/primitives/form/form'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from '@documenso/ui/primitives/table'; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@documenso/ui/primitives/table'; import { Textarea } from '@documenso/ui/primitives/textarea'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { msg } from '@lingui/core/macro'; +import { useLingui } from '@lingui/react'; +import { Plural, Trans } from '@lingui/react/macro'; +import { type TemplateDirectLink, TemplateType } from '@prisma/client'; +import type * as DialogPrimitive from '@radix-ui/react-dialog'; +import { CheckCircle2Icon, CircleIcon } from 'lucide-react'; +import { useEffect, useMemo, useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { match, P } from 'ts-pattern'; +import { z } from 'zod'; import { useCurrentTeam } from '~/providers/team'; @@ -145,10 +129,7 @@ export const ManagePublicTemplateDialog = ({ } }; - const onFormSubmit = async ({ - publicTitle, - publicDescription, - }: TUpdatePublicTemplateFormSchema) => { + const onFormSubmit = async ({ publicTitle, publicDescription }: TUpdatePublicTemplateFormSchema) => { if (!selectedTemplateId) { return; } @@ -251,9 +232,7 @@ export const ManagePublicTemplateDialog = ({ {team ? ( - - Select a template you'd like to display on your team's public profile - + Select a template you'd like to display on your team's public profile ) : ( Select a template you'd like to display on your public profile )} @@ -290,13 +269,9 @@ export const ManagePublicTemplateDialog = ({ key={row.id} onClick={() => setSelectedTemplateId(row.id)} > - - {row.title} - + {row.title} - - {i18n.date(row.createdAt)} - + {i18n.date(row.createdAt)} {selectedTemplateId === row.id ? ( @@ -317,11 +292,7 @@ export const ManagePublicTemplateDialog = ({ - @@ -340,10 +311,7 @@ export const ManagePublicTemplateDialog = ({ - + Title - + @@ -365,17 +330,14 @@ export const ManagePublicTemplateDialog = ({ control={form.control} name="publicDescription" render={({ field }) => { - const remaningLength = - MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH - (field.value || '').length; + const remaningLength = MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH - (field.value || '').length; return ( Description