chore: run prettier format

This commit is contained in:
Marc Seitz
2024-05-13 14:52:25 +02:00
parent d29f1bdfab
commit 385ef2a593
404 changed files with 3365 additions and 2598 deletions

View File

@@ -1,9 +1,12 @@
import "@/styles/globals.css";
import { Inter } from "next/font/google";
import { Toaster } from "sonner";
import Head from "next/head";
import { Toaster } from "sonner";
import { ThemeProvider } from "@/components/theme-provider";
import "@/styles/globals.css";
const inter = Inter({ subsets: ["latin"] });
export default function Layout({ children }: { children: React.ReactNode }) {

View File

@@ -1,17 +1,20 @@
"use client";
import { Button } from "@/components/ui/button";
import { signIn } from "next-auth/react";
import { signInWithPasskey } from "@teamhanko/passkeys-next-auth-provider/client";
import Link from "next/link";
import { Input } from "@/components/ui/input";
import { useParams } from "next/navigation";
import Passkey from "@/components/shared/icons/passkey";
import { useState } from "react";
import { toast } from "sonner";
import LinkedIn from "@/components/shared/icons/linkedin";
import { signInWithPasskey } from "@teamhanko/passkeys-next-auth-provider/client";
import { Loader } from "lucide-react";
import { signIn } from "next-auth/react";
import { toast } from "sonner";
import Google from "@/components/shared/icons/google";
import LinkedIn from "@/components/shared/icons/linkedin";
import Passkey from "@/components/shared/icons/passkey";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export default function Login() {
@@ -34,19 +37,19 @@ export default function Login() {
className="absolute inset-x-0 top-10 -z-10 flex transform-gpu justify-center overflow-hidden blur-3xl"
aria-hidden="true"
></div>
<div className="z-10 mt-[calc(20vh)] h-fit w-full mx-5 sm:mx-0 max-w-md overflow-hidden rounded-lg">
<div className="z-10 mx-5 mt-[calc(20vh)] h-fit w-full max-w-md overflow-hidden rounded-lg sm:mx-0">
<div className="flex flex-col items-center justify-center space-y-3 px-4 py-6 pt-8 text-center sm:px-16">
<Link href="/">
<span className=" text-2xl font-semibold text-gray-800 text-balance ">
<span className=" text-balance text-2xl font-semibold text-gray-800 ">
Welcome to Papermark
</span>
</Link>
<h3 className="text-sm text-gray-800 text-balance ">
<h3 className="text-balance text-sm text-gray-800 ">
Share documents. Not attachments.
</h3>
</div>
<form
className="flex flex-col px-4 pt-8 sm:px-16 gap-4"
className="flex flex-col gap-4 px-4 pt-8 sm:px-16"
onSubmit={(e) => {
e.preventDefault();
setIsLoginWithEmail(true);
@@ -86,7 +89,7 @@ export default function Login() {
disabled={isLoginWithEmail}
value={email}
onChange={(e) => setEmail(e.target.value)}
className="flex h-10 w-full rounded-md border-0 ring-1 ring-gray-200 bg-background px-3 py-2 text-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 bg-white text-gray-900"
className="flex h-10 w-full rounded-md border-0 bg-background bg-white px-3 py-2 text-sm text-gray-900 ring-1 ring-gray-200 transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
/>
{/* <Button type="submit" disabled={isLoginWithEmail}>
{isLoginWithEmail && (
@@ -99,13 +102,13 @@ export default function Login() {
loading={isLoginWithEmail}
className={`${
isLoginWithEmail ? "bg-black" : "bg-gray-800 hover:bg-gray-900 "
} text-white py-2 px-4 rounded focus:outline-none focus:shadow-outline transform transition-colors duration-300 ease-in-out`}
} focus:shadow-outline transform rounded px-4 py-2 text-white transition-colors duration-300 ease-in-out focus:outline-none`}
>
{emailButtonText}
</Button>
</form>
<p className="text-center py-4">or</p>
<div className="flex flex-col px-4 sm:px-16 space-y-2">
<p className="py-4 text-center">or</p>
<div className="flex flex-col space-y-2 px-4 sm:px-16">
<Button
onClick={() => {
setIsLoginWithGoogle(true);
@@ -118,12 +121,12 @@ export default function Login() {
});
}}
disabled={isLoginWithGoogle}
className="flex justify-center items-center space-x-2 font-normal bg-gray-100 text-gray-900 border border-gray-200 hover:bg-gray-200 "
className="flex items-center justify-center space-x-2 border border-gray-200 bg-gray-100 font-normal text-gray-900 hover:bg-gray-200 "
>
{isLoginWithGoogle ? (
<Loader className="w-5 h-5 mr-2 animate-spin" />
<Loader className="mr-2 h-5 w-5 animate-spin" />
) : (
<Google className="w-5 h-5" />
<Google className="h-5 w-5" />
)}
<span>Continue with Google</span>
</Button>
@@ -139,10 +142,10 @@ export default function Login() {
});
}}
disabled={isLoginWithLinkedIn}
className="flex justify-center items-center space-x-2 font-normal bg-gray-100 text-gray-900 border border-gray-200 hover:bg-gray-200"
className="flex items-center justify-center space-x-2 border border-gray-200 bg-gray-100 font-normal text-gray-900 hover:bg-gray-200"
>
{isLoginWithLinkedIn ? (
<Loader className="w-5 h-5 mr-2 animate-spin " />
<Loader className="mr-2 h-5 w-5 animate-spin " />
) : (
<LinkedIn />
)}
@@ -155,13 +158,13 @@ export default function Login() {
})
}
variant="outline"
className="flex justify-center items-center space-x-2 border border-gray-200 hover:bg-gray-200 font-normal bg-gray-100 text-gray-900 hover:text-gray-900"
className="flex items-center justify-center space-x-2 border border-gray-200 bg-gray-100 font-normal text-gray-900 hover:bg-gray-200 hover:text-gray-900"
>
<Passkey className="w-4 h-4 " />
<Passkey className="h-4 w-4 " />
<span>Continue with a passkey</span>
</Button>
</div>
<p className=" mt-10 text-xs text-muted-foreground w-full max-w-md px-4 sm:px-16">
<p className=" mt-10 w-full max-w-md px-4 text-xs text-muted-foreground sm:px-16">
By clicking continue, you acknowledge that you have read and agree
to Papermark&apos;s{" "}
<Link href="/terms" className="underline">
@@ -176,23 +179,23 @@ export default function Login() {
</div>
</div>
<div className="hidden w-full justify-center bg-gray-800 md:flex md:w-1/2 lg:w-3/5">
<div className="flex w-full max-w-5xl px-4 md:px-8 py-20">
<div className="flex w-full max-w-5xl px-4 py-20 md:px-8">
<div
className="flex w-full mx-auto max-w-5xl px-4 md:px-8 py-20 bg-gray-800 rounded-3xl justify-center"
className="mx-auto flex w-full max-w-5xl justify-center rounded-3xl bg-gray-800 px-4 py-20 md:px-8"
id="features"
>
<div className="flex flex-col items-center">
{/* Image container */}
<div className="w-64 h-64 mb-4">
<div className="mb-4 h-64 w-64">
<img
className="object-cover w-full h-full rounded-2xl shadow-2xl"
className="h-full w-full rounded-2xl object-cover shadow-2xl"
src="https://www.papermark.io/_static/testimonials/jaski.jpeg"
alt="Jaski"
/>
</div>
{/* Text content */}
<div className="max-w-xl text-center">
<blockquote className="text-l leading-8 text-gray-100 sm:text-xl sm:leading-9 text-balance">
<blockquote className="text-l text-balance leading-8 text-gray-100 sm:text-xl sm:leading-9">
<p>
True builders listen to their users and build what they
need. Thanks Papermark team for solving a big pain point.
@@ -200,10 +203,10 @@ export default function Login() {
</p>
</blockquote>
<figcaption className="mt-4">
<div className="font-semibold text-white text-balance ">
<div className="text-balance font-semibold text-white ">
Jaski
</div>
<div className="text-gray-400 text-balance ">
<div className="text-balance text-gray-400 ">
Founder, Townhall Network
</div>
</figcaption>

View File

@@ -1,15 +1,18 @@
"use client";
import { Button } from "@/components/ui/button";
import { signIn } from "next-auth/react";
import Image from "next/image";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Input } from "@/components/ui/input";
import { useState } from "react";
import { toast } from "sonner";
import LinkedIn from "@/components/shared/icons/linkedin";
import PapermarkLogo from "@/public/_static/papermark-logo.svg";
import Image from "next/image";
import { signIn } from "next-auth/react";
import { toast } from "sonner";
import LinkedIn from "@/components/shared/icons/linkedin";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
export default function Register() {
const { next } = useParams as { next?: string };
@@ -30,7 +33,7 @@ export default function Register() {
}}
/>
</div>
<div className="z-10 mt-[calc(20vh)] h-fit w-full mx-5 sm:mx-0 max-w-md overflow-hidden border border-border bg-gray-50 dark:bg-gray-900 rounded-lg sm:shadow-xl">
<div className="z-10 mx-5 mt-[calc(20vh)] h-fit w-full max-w-md overflow-hidden rounded-lg border border-border bg-gray-50 dark:bg-gray-900 sm:mx-0 sm:shadow-xl">
<div className="flex flex-col items-center justify-center space-y-3 px-4 py-6 pt-8 text-center sm:px-16">
<Link href="/">
<Image
@@ -40,12 +43,12 @@ export default function Register() {
alt="Papermark Logo"
/>
</Link>
<h3 className="text-2xl text-foreground font-medium">
<h3 className="text-2xl font-medium text-foreground">
Start sharing documents
</h3>
</div>
<form
className="flex flex-col p-4 pt-8 sm:px-16 gap-4"
className="flex flex-col gap-4 p-4 pt-8 sm:px-16"
onSubmit={(e) => {
e.preventDefault();
signIn("email", {
@@ -71,14 +74,14 @@ export default function Register() {
<Button type="submit">Continue with Email</Button>
</form>
<p className="text-center">or</p>
<div className="flex flex-col px-4 py-8 sm:px-16 space-y-2">
<div className="flex flex-col space-y-2 px-4 py-8 sm:px-16">
<Button
onClick={() => {
signIn("google", {
...(next && next.length > 0 ? { callbackUrl: next } : {}),
});
}}
className="flex justify-center items-center space-x-2"
className="flex items-center justify-center space-x-2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@@ -96,7 +99,7 @@ export default function Register() {
...(next && next.length > 0 ? { callbackUrl: next } : {}),
});
}}
className="flex justify-center items-center space-x-2"
className="flex items-center justify-center space-x-2"
>
<LinkedIn />
<span>Continue with LinkedIn</span>

View File

@@ -1,6 +1,6 @@
export default function PrivacyPage() {
return (
<div className="relative pt-48 pb-14 mx-auto px-4 lg:px-8 bg-white text-black">
<div className="relative mx-auto bg-white px-4 pb-14 pt-48 text-black lg:px-8">
<article className="prose prose-slate mx-auto">
<h1>Privacy Policy</h1>
<p>Effective date: 09/04/2023</p>

View File

@@ -1,6 +1,6 @@
export default function TermsPage() {
return (
<div className="relative pt-48 pb-14 mx-auto px-4 lg:px-8 bg-white text-black">
<div className="relative mx-auto bg-white px-4 pb-14 pt-48 text-black lg:px-8">
<article className="prose prose-slate mx-auto">
<h1>Terms of Service</h1>
<p>Effective date: 26/04/2024</p>

View File

@@ -1,15 +1,15 @@
import { type Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import Testimonials from "@/components/web/testimonials";
import Features from "@/components/web/alternatives/features";
import FAQ from "@/components/web/faq";
import { Button } from "@/components/ui/button";
import { CheckIcon, XIcon } from "lucide-react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import Features from "@/components/web/alternatives/features";
import FAQ from "@/components/web/faq";
import Testimonials from "@/components/web/testimonials";
import { getAlternative, getAlternatives } from "@/lib/content/alternative";
import { notFound } from "next/navigation";
import { constructMetadata } from "@/lib/utils";
export async function generateStaticParams() {
@@ -44,8 +44,8 @@ export default async function AlternativePage({
if (!alternative) return notFound();
return (
<div className="flex flex-1 flex-col bg-white text-black justify-center">
<div className="max-w-5xl w-full mx-auto px-4 md:px-8 text-center">
<div className="flex flex-1 flex-col justify-center bg-white text-black">
<div className="mx-auto w-full max-w-5xl px-4 text-center md:px-8">
<div className="pt-32">
<div className=" pb-4">
<img
@@ -59,19 +59,19 @@ export default async function AlternativePage({
{/* <div className="relative rounded-full px-3 py-1 text-sm leading-6 text-black ring-black/10 hover:ring-white/20">
Free {alternative.name} alternative
</div> */}
<h1 className="text-6xl text-balance">{alternative.title}</h1>
<p className="text-xl mt-8 text-balance max-w-3xl mx-auto md:text-2xl">
<h1 className="text-balance text-6xl">{alternative.title}</h1>
<p className="mx-auto mt-8 max-w-3xl text-balance text-xl md:text-2xl">
{alternative.description}
</p>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link href="/login">
<Button className="text-white bg-gray-900 rounded-3xl hover:bg-gray-500 justify-center">
<Button className="justify-center rounded-3xl bg-gray-900 text-white hover:bg-gray-500">
Send Document
</Button>
</Link>
</div>
</div>
<div className="mt-24 mx-auto w-full">
<div className="mx-auto mt-24 w-full">
<video
width="100%"
id="video1"
@@ -91,33 +91,33 @@ export default async function AlternativePage({
</div>
</div>
{/* Comparison section */}
<div className="max-w-5xl w-full mx-auto px-4 md:px-8">
<div className="pt-32 pb-2">
<h2 className="text-5xl text-balance">
<div className="mx-auto w-full max-w-5xl px-4 md:px-8">
<div className="pb-2 pt-32">
<h2 className="text-balance text-5xl">
{alternative.subtitlecompare}
</h2>
<p className="text-xl mt-8 text-balance max-w-3xl">
<p className="mt-8 max-w-3xl text-balance text-xl">
{alternative.descriptioncompare}
</p>
</div>
<div className="bg-white py-16">
<div className="mx-auto max-w-5xl ">
<div className="isolate grid grid-cols-1 md:grid-cols-2 border border-black rounded-xl overflow-hidden">
<div className="isolate grid grid-cols-1 overflow-hidden rounded-xl border border-black md:grid-cols-2">
{/* Column 1 - Papermark */}
<div className="border-black border-r-0 md:odd:border-r xl:even:border-r xl:last:!border-r-0 flex flex-col justify-between">
<div className="flex flex-col justify-between border-r-0 border-black md:odd:border-r xl:last:!border-r-0 xl:even:border-r">
<div>
<div className="border-b border-black p-6 bg-gray-100">
<h3 className="text-balance text-gray-800 text-xl leading-8">
<div className="border-b border-black bg-gray-100 p-6">
<h3 className="text-balance text-xl leading-8 text-gray-800">
Papermark
</h3>
</div>
<div className="p-6">
<p className="mt-4 text-sm leading-6 text-gray-500 text-balance">
<p className="mt-4 text-balance text-sm leading-6 text-gray-500">
Papermark plans start from freemium
</p>
<div className="flex flex-col justify-between"></div>
<p className="mt-4 text-2xl text-balance font-semibold leading-6 text-gray-900">
<p className="mt-4 text-balance text-2xl font-semibold leading-6 text-gray-900">
$0
</p>
<ul className="mt-8 space-y-3 text-sm leading-6 text-gray-500">
@@ -176,7 +176,7 @@ export default async function AlternativePage({
>
<Button
variant="outline"
className="text-balance rounded-3xl bg-transparent bg-[#fb7a00] hover:bg-gray-500"
className="text-balance rounded-3xl bg-[#fb7a00] bg-transparent hover:bg-gray-500"
>
Start for free
</Button>
@@ -186,7 +186,7 @@ export default async function AlternativePage({
{/* Column 2 - Docsend */}
<div className="flex flex-col justify-between">
<div>
<div className="border-b border-black p-6 bg-gray-100">
<div className="border-b border-black bg-gray-100 p-6">
<h3 className="text-xl leading-8 text-gray-800">
{alternative.name}
</h3>
@@ -195,7 +195,7 @@ export default async function AlternativePage({
<p className="mt-4 text-sm leading-6 text-gray-500">
{`${alternative.name} feature description`}
</p>
<p className="mt-4 text-2xl text-balance font-semibold leading-6 text-gray-900">
<p className="mt-4 text-balance text-2xl font-semibold leading-6 text-gray-900">
{alternative.price}
</p>
<ul className="mt-8 space-y-3 text-sm leading-6 text-gray-500">
@@ -254,7 +254,7 @@ export default async function AlternativePage({
>
<Button
variant="outline"
className="text-balance rounded-3xl bg-transparent border-black"
className="text-balance rounded-3xl border-black bg-transparent"
>
{`Start with ${alternative.name} alternative`}
</Button>
@@ -267,10 +267,10 @@ export default async function AlternativePage({
{/* Features*/}
<div
className="w-full mx-auto max-w-5xl px-4 md:px-8 py-20"
className="mx-auto w-full max-w-5xl px-4 py-20 md:px-8"
id="features"
>
<h2 className="text-4xl text-balance pt-12 pb-20 max-w-3xl">
<h2 className="max-w-3xl text-balance pb-20 pt-12 text-4xl">
{alternative.subtitlefeatures}{" "}
<span className="text-gray-500">
{alternative.descriptionfeatures}
@@ -283,10 +283,10 @@ export default async function AlternativePage({
{/* FAQ section */}
<div
className="w-full mx-auto max-w-5xl px-4 md:px-8 py-32"
className="mx-auto w-full max-w-5xl px-4 py-32 md:px-8"
id="features"
>
<h2 className="text-4xl text-balance pt-6 max-w-3xl">
<h2 className="max-w-3xl text-balance pt-6 text-4xl">
FAQ{" "}
<span className="text-gray-500">{alternative.descriptionfaq}</span>
</h2>
@@ -295,10 +295,10 @@ export default async function AlternativePage({
{/* CTA */}
<div className="bg-[#fb7a00]">
<div className="w-full mx-auto max-w-5xl py-32 px-4 md:px-8">
<h2 className="text-4xl text-balance">{alternative.subtitlecta}</h2>
<div className="mx-auto w-full max-w-5xl px-4 py-32 md:px-8">
<h2 className="text-balance text-4xl">{alternative.subtitlecta}</h2>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link href="/login">
<Button className="text-balance rounded-3xl">
Start sending documents for free

View File

@@ -1,12 +1,14 @@
import { getPostsRemote as getPosts, getPost } from "@/lib/content/blog";
import { ContentBody } from "@/components/mdx/post-body";
import { notFound } from "next/navigation";
import Link from "next/link";
import BlurImage from "@/components/blur-image";
import { constructMetadata, formatDate } from "@/lib/utils";
import { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import BlurImage from "@/components/blur-image";
import { ContentBody } from "@/components/mdx/post-body";
import TableOfContents from "@/components/mdx/table-of-contents";
import { getPost, getPostsRemote as getPosts } from "@/lib/content/blog";
import { constructMetadata, formatDate } from "@/lib/utils";
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({ slug: post?.data.slug }));
@@ -41,19 +43,19 @@ export default async function BlogPage({
return (
<>
<div className="max-w-7xl w-full mx-auto px-4 md:px-8 mb-10">
<div className="mx-auto mb-10 w-full max-w-7xl px-4 md:px-8">
<div className="flex max-w-screen-sm flex-col space-y-4 pt-16">
<div className="flex items-center space-x-4">
<time dateTime={post.data.publishedAt} className="text-sm">
{formatDate(post.data.publishedAt)}
</time>
</div>
<h1 className="text-4xl md:text-6xl text-balance">
<h1 className="text-balance text-4xl md:text-6xl">
{post.data.title}
</h1>
<p className="text-xl text-gray-600">{post.data.summary}</p>
<div className="items-center space-x-4 flex flex-col self-start">
<div className="flex flex-col items-center space-x-4 self-start">
<Link
href={`https://twitter.com/mfts0`}
className="group flex items-center space-x-3"
@@ -77,11 +79,11 @@ export default async function BlogPage({
</div>
<div className="relative">
<div className="grid grid-cols-4 gap-10 py-10 max-w-7xl w-full mx-auto px-4 md:px-8">
<div className="relative col-span-4 mb-10 flex flex-col space-y-8 bg-white md:col-span-3 sm:border-r sm:border-orange-500">
<div className="mx-auto grid w-full max-w-7xl grid-cols-4 gap-10 px-4 py-10 md:px-8">
<div className="relative col-span-4 mb-10 flex flex-col space-y-8 bg-white sm:border-r sm:border-orange-500 md:col-span-3">
<div
data-mdx-container
className="prose prose-h2:mb-2 first:prose-h2:mt-0 prose-h2:mt-10 prose-headings:font-medium sm:max-w-screen-md sm:pr-2 md:pr-0"
className="prose prose-headings:font-medium prose-h2:mb-2 prose-h2:mt-10 first:prose-h2:mt-0 sm:max-w-screen-md sm:pr-2 md:pr-0"
>
<ContentBody>{post.body}</ContentBody>
</div>

View File

@@ -1,4 +1,5 @@
import Link from "next/link";
import { getPostsRemote as getPosts } from "@/lib/content/blog";
export default async function BlogIndex() {
@@ -7,10 +8,10 @@ export default async function BlogIndex() {
<div className="bg-white py-24 sm:py-32">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl lg:mx-0">
<h2 className="text-6xl text-balance text-gray-900 sm:text-6xl">
<h2 className="text-balance text-6xl text-gray-900 sm:text-6xl">
Papermark Blog
</h2>
<p className="mt-2 text-lg leading-8 text-gray-500 text-balance">
<p className="mt-2 text-balance text-lg leading-8 text-gray-500">
All insights on secure document sharing in 2024
</p>
</div>
@@ -21,11 +22,11 @@ export default async function BlogIndex() {
className="flex max-w-xl flex-col items-start justify-between"
>
<div className="flex items-center gap-x-4 text-xs">
<h1 className="text-2xl md:text-2xl text-balance">
<h1 className="text-balance text-2xl md:text-2xl">
{post?.data.title}
</h1>
</div>
<p className="mt-1 text-xs md:text-xs text-balance text-gray-500">
<p className="mt-1 text-balance text-xs text-gray-500 md:text-xs">
{post?.data.summary}
</p>
@@ -33,7 +34,7 @@ export default async function BlogIndex() {
<h3 className="mt-4 text-lg font-semibold leading-6 text-gray-900 group-hover:text-gray-600">
<Link
href={`/blog/${post?.data.slug}`}
className="text-gray-500 text-balance font-light text-xs rounded-3xl bg-transparent border border-gray-500 px-4 py-2"
className="text-balance rounded-3xl border border-gray-500 bg-transparent px-4 py-2 text-xs font-light text-gray-500"
target="_blank"
rel="noopener noreferrer"
>

View File

@@ -1,10 +1,10 @@
import { getHelpArticles, getHelpArticle } from "@/lib/content/help";
import { ContentBody } from "@/components/mdx/post-body";
import { notFound } from "next/navigation";
import Link from "next/link";
import BlurImage from "@/components/blur-image";
import { constructMetadata, formatDate } from "@/lib/utils";
import { Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import BlurImage from "@/components/blur-image";
import { ContentBody } from "@/components/mdx/post-body";
import TableOfContents from "@/components/mdx/table-of-contents";
import {
Breadcrumb,
BreadcrumbItem,
@@ -13,7 +13,9 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import TableOfContents from "@/components/mdx/table-of-contents";
import { getHelpArticle, getHelpArticles } from "@/lib/content/help";
import { constructMetadata, formatDate } from "@/lib/utils";
export async function generateStaticParams() {
const articles = await getHelpArticles();
@@ -51,7 +53,7 @@ export default async function BlogPage({
return (
<>
<div className="max-w-7xl w-full mx-auto px-4 md:px-8 mb-10">
<div className="mx-auto mb-10 w-full max-w-7xl px-4 md:px-8">
<div className="flex max-w-screen-sm flex-col space-y-4 pt-16">
<div className="flex items-center space-x-4">
<Breadcrumb>
@@ -72,12 +74,12 @@ export default async function BlogPage({
</BreadcrumbList>
</Breadcrumb>
</div>
<h1 className="text-4xl md:text-5xl text-balance">
<h1 className="text-balance text-4xl md:text-5xl">
{article.data.title}
</h1>
<p className="text-lg text-gray-600">{article.data.summary}</p>
<div className="items-center space-x-4 flex flex-col self-start">
<div className="flex flex-col items-center space-x-4 self-start">
<Link
href={`https://twitter.com/mfts0`}
className="group flex items-center space-x-3"
@@ -106,11 +108,11 @@ export default async function BlogPage({
</div>
<div className="relative">
<div className="grid grid-cols-4 gap-10 py-10 max-w-7xl w-full mx-auto px-4 md:px-8">
<div className="relative col-span-4 mb-10 flex flex-col space-y-8 bg-white md:col-span-3 sm:border-r sm:border-orange-500">
<div className="mx-auto grid w-full max-w-7xl grid-cols-4 gap-10 px-4 py-10 md:px-8">
<div className="relative col-span-4 mb-10 flex flex-col space-y-8 bg-white sm:border-r sm:border-orange-500 md:col-span-3">
<div
data-mdx-container
className="prose prose-h2:mb-2 first:prose-h2:mt-0 prose-h2:mt-10 prose-headings:font-medium sm:max-w-screen-md sm:pr-2 md:pr-0"
className="prose prose-headings:font-medium prose-h2:mb-2 prose-h2:mt-10 first:prose-h2:mt-0 sm:max-w-screen-md sm:pr-2 md:pr-0"
>
<ContentBody>{article.body}</ContentBody>
</div>

View File

@@ -1,15 +1,17 @@
"use client";
import Fuse from "fuse.js";
import { useSearchParams } from "next/navigation";
import { useMemo, useState } from "react";
import { GlobeIcon, SearchIcon } from "lucide-react";
import classNames from "clsx";
import Link from "next/link";
import Image from "next/image";
import PlaceholderImg from "@/public/_static/placeholder.png";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useMemo, useState } from "react";
import PapermarkPImg from "@/public/_static/papermark-p.svg";
import PlaceholderImg from "@/public/_static/placeholder.png";
import classNames from "clsx";
import Fuse from "fuse.js";
import { GlobeIcon, SearchIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
const searchOptions = {
@@ -112,8 +114,8 @@ export default function Dashboard({ data }: any) {
return (
<>
<div className="sm:flex flex-col md:flex-row justify-between mt-4">
<span className="isolate mt-5 inline-flex rounded-md shadow-sm w-fit px-2 md:px-0">
<div className="mt-4 flex-col justify-between sm:flex md:flex-row">
<span className="isolate mt-5 inline-flex w-fit rounded-md px-2 shadow-sm md:px-0">
{stages.map((stage) => (
<Link
href={
@@ -126,7 +128,7 @@ export default function Dashboard({ data }: any) {
category === stage.id || (!category && stage.id === "7")
? "bg-gray-200"
: "bg-white hover:bg-gray-50",
"relative inline-flex items-center first-of-type:rounded-l-md last-of-type:rounded-r-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 focus:z-10 focus:outline-none focus:ring-gray-500 -ml-px first-of-type:-ml-0",
"relative -ml-px inline-flex items-center border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 first-of-type:-ml-0 first-of-type:rounded-l-md last-of-type:rounded-r-md focus:z-10 focus:outline-none focus:ring-gray-500",
)}
>
{stage.label}
@@ -135,7 +137,7 @@ export default function Dashboard({ data }: any) {
</span>
<div className="relative mt-5 px-2 md:px-0">
<SearchIcon
className="h-5 w-5 absolute z-20 left-3 bottom-2 ml-1 md:ml-0"
className="absolute bottom-2 left-3 z-20 ml-1 h-5 w-5 md:ml-0"
aria-hidden="true"
/>
<input
@@ -144,21 +146,21 @@ export default function Dashboard({ data }: any) {
name="search"
value={search}
onChange={(e) => setSearch(e.target.value)}
className="w-full rounded-xl shadow-sm inline-flex relative items-center border border-gray-300 px-4 py-2 text-sm text-gray-700 placeholder:text-gray-400 focus:z-10 focus:outline-none focus:ring-gray-500 md:w-72 pl-10 xs:pl-12"
className="xs:pl-12 relative inline-flex w-full items-center rounded-xl border border-gray-300 px-4 py-2 pl-10 text-sm text-gray-700 shadow-sm placeholder:text-gray-400 focus:z-10 focus:outline-none focus:ring-gray-500 md:w-72"
placeholder="Search by name or country"
/>
</div>
</div>
<div className="mt-8 flex flex-col">
<div className="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full py-2 align-middle px-6 lg:px-8">
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full px-6 py-2 align-middle lg:px-8">
<div className="py-2">
<span className="font-bold">{currentInvestors.length}</span>{" "}
investors
</div>
<div className="overflow-hidden md:shadow md:ring-1 md:ring-black md:ring-opacity-5 rounded-lg">
<table className="min-w-full md:divide-y bg-gray-100 md:bg-transparent divide-gray-300 rounded-lg overflow-hidden md:rounded-none">
<thead className="bg-gray-50 hidden md:table-header-group">
<div className="overflow-hidden rounded-lg md:shadow md:ring-1 md:ring-black md:ring-opacity-5">
<table className="min-w-full divide-gray-300 overflow-hidden rounded-lg bg-gray-100 md:divide-y md:rounded-none md:bg-transparent">
<thead className="hidden bg-gray-50 md:table-header-group">
<tr>
<th
scope="col"
@@ -193,20 +195,20 @@ export default function Dashboard({ data }: any) {
</tr>
</thead>
<tbody className="md:divide-y divide-gray-200 md:bg-white grid grid-cols-1 gap-3 sm:grid-cols-2 md:table-row-group">
<tbody className="grid grid-cols-1 gap-3 divide-gray-200 sm:grid-cols-2 md:table-row-group md:divide-y md:bg-white">
{paginatedInvestors.map((investor: any) => (
// Assuming you have a slug or some unique identifier for each investor
<tr
key={investor.id}
className="hover:bg-gray-100 group grid grid-cols-3 gap-1 md:table-row bg-white rounded-lg md:rounded-none md:bg-transparent shadow md:shadow-none border border-gray-200 md:border-x-0 py-3 px-2 md:p-0"
className="group grid grid-cols-3 gap-1 rounded-lg border border-gray-200 bg-white px-2 py-3 shadow hover:bg-gray-100 md:table-row md:rounded-none md:border-x-0 md:bg-transparent md:p-0 md:shadow-none"
>
<td className="col-span-3 whitespace-nowrap pl-3 md:py-2 md:pl-6 text-sm sm:pl-6 md:h-24">
<td className="col-span-3 whitespace-nowrap pl-3 text-sm sm:pl-6 md:h-24 md:py-2 md:pl-6">
<div className="flex items-center space-x-2">
<div className="h-10 w-10 flex-shrink-0">
{investor.imageUrl ? (
<img
className="rounded-full h-10 w-10 object-contain"
className="h-10 w-10 rounded-full object-contain"
width={40}
height={40}
src={
@@ -218,7 +220,7 @@ export default function Dashboard({ data }: any) {
/>
) : (
<Image
className="rounded-full h-10 w-10 object-contain"
className="h-10 w-10 rounded-full object-contain"
width={40}
height={40}
src={PlaceholderImg}
@@ -230,7 +232,7 @@ export default function Dashboard({ data }: any) {
<div className="font-medium text-gray-900">
{investor.name}
</div>
<div className="flex space-x-2 items-center">
<div className="flex items-center space-x-2">
{investor.website && (
<a
className="text-black"
@@ -239,7 +241,7 @@ export default function Dashboard({ data }: any) {
rel="noopener"
>
<span className="sr-only">Website</span>
<GlobeIcon className="w-4 h-4" />
<GlobeIcon className="h-4 w-4" />
</a>
)}
<Link
@@ -250,27 +252,27 @@ export default function Dashboard({ data }: any) {
width={18}
height={18}
alt="Papermark"
className="block ring-1 ring-gray-300 rounded-full"
className="block rounded-full ring-1 ring-gray-300"
/>
</Link>
</div>
</div>
</div>
</td>
<td className="col-span-1 row-start-2 whitespace-nowrap px-3 md:px-2 md:py-3 text-sm text-gray-500 font-bold md:font-normal">
<td className="col-span-1 row-start-2 whitespace-nowrap px-3 text-sm font-bold text-gray-500 md:px-2 md:py-3 md:font-normal">
{investor.round ? investor.round : "Unknown"}
</td>
<td className="col-span-3 whitespace-nowrap px-3 md:px-2 md:py-3 text-sm text-gray-500 md:mt-0">
<td className="col-span-3 whitespace-nowrap px-3 text-sm text-gray-500 md:mt-0 md:px-2 md:py-3">
{investor.location ? investor.location : "Unknown"}
</td>
<td className="col-span-3 md:max-w-xs px-3 md:px-2 md:py-3 text-sm text-gray-500 truncate w-40">
<td className="col-span-3 w-40 truncate px-3 text-sm text-gray-500 md:max-w-xs md:px-2 md:py-3">
{investor.sector ? investor.sector : "Unknown"}
</td>
<td className="col-span-3 md:max-w-xs px-3 md:px-2 md:py-3 text-sm text-gray-500 truncate w-40">
<td className="col-span-3 w-40 truncate px-3 text-sm text-gray-500 md:max-w-xs md:px-2 md:py-3">
<a
href={`/investors/${encodeURIComponent(investor.slug)}`}
>
<Button className="rounded-3xl bg-gray-200 text-xs text-gray-800 hover:bg-[#fb7a00]]">
<Button className="hover:bg-[#fb7a00]] rounded-3xl bg-gray-200 text-xs text-gray-800">
Learn more
</Button>
</a>
@@ -279,27 +281,27 @@ export default function Dashboard({ data }: any) {
))}
</tbody>
</table>
<div className="flex justify-between items-center w-full my-4 px-4">
<div className="my-4 flex w-full items-center justify-between px-4">
<button
onClick={() => goToPage(currentPage - 1)}
disabled={currentPage === 1}
className="px-2 py-2 rounded border text-xs"
className="rounded border px-2 py-2 text-xs"
>
Previous
</button>
<div className="px-2 py-2 rounded text-xs">
<div className="rounded px-2 py-2 text-xs">
Page {currentPage} of {totalPages}
</div>
<button
onClick={() => goToPage(currentPage + 1)}
disabled={currentPage === totalPages}
className="px-2 py-2 rounded border text-xs"
className="rounded border px-2 py-2 text-xs"
>
Next
</button>
</div>
{currentInvestors.length === 0 && (
<div className="text-center my-10">No results found</div>
<div className="my-10 text-center">No results found</div>
)}
</div>
</div>

View File

@@ -1,10 +1,12 @@
import Link from "next/link";
import { cn } from "@/lib/utils";
import Image from "next/image";
import PlaceholderImg from "@/public/_static/placeholder.png";
import Link from "next/link";
import PapermarkPImg from "@/public/_static/papermark-p.svg";
import PlaceholderImg from "@/public/_static/placeholder.png";
import { GlobeIcon } from "lucide-react";
import { cn } from "@/lib/utils";
const stages = [
{ id: "7", label: "All" },
{ id: "5", label: "Pre-Seed" },
@@ -14,8 +16,11 @@ const stages = [
{ id: "4", label: "Series C" },
];
export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) => {
export const FallbackInvestors = async ({
allInvestors,
}: {
allInvestors: any[];
}) => {
const category = "7";
const pageSize = 10; // Showing 10 investors per page
@@ -32,8 +37,8 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
return (
<>
<div className="sm:flex flex-col md:flex-row justify-between mt-4">
<span className="isolate mt-5 inline-flex rounded-md shadow-sm w-fit px-2 lg:px-2 ">
<div className="mt-4 flex-col justify-between sm:flex md:flex-row">
<span className="isolate mt-5 inline-flex w-fit rounded-md px-2 shadow-sm lg:px-2 ">
{stages.map((stage) => (
<Link
href={
@@ -46,7 +51,7 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
category === stage.id || (!category && stage.id === "7")
? "bg-gray-200"
: "bg-white hover:bg-gray-50",
"relative inline-flex items-center first-of-type:rounded-l-md last-of-type:rounded-r-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 focus:z-10 focus:outline-none focus:ring-gray-500 -ml-px first-of-type:-ml-0",
"relative -ml-px inline-flex items-center border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 first-of-type:-ml-0 first-of-type:rounded-l-md last-of-type:rounded-r-md focus:z-10 focus:outline-none focus:ring-gray-500",
)}
>
{stage.label}
@@ -55,15 +60,14 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
</span>
</div>
<div className="mt-8 flex flex-col">
<div className="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full py-2 align-middle px-6 lg:px-8">
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full px-6 py-2 align-middle lg:px-8">
<div className="py-2">
<span className="font-bold">{allInvestors.length}</span>{" "}
investors
<span className="font-bold">{allInvestors.length}</span> investors
</div>
<div className="overflow-hidden md:shadow md:ring-1 md:ring-black md:ring-opacity-5 rounded-lg">
<table className="min-w-full md:divide-y bg-gray-100 md:bg-transparent divide-gray-300 rounded-lg overflow-hidden md:rounded-none">
<thead className="bg-gray-50 hidden md:table-header-group">
<div className="overflow-hidden rounded-lg md:shadow md:ring-1 md:ring-black md:ring-opacity-5">
<table className="min-w-full divide-gray-300 overflow-hidden rounded-lg bg-gray-100 md:divide-y md:rounded-none md:bg-transparent">
<thead className="hidden bg-gray-50 md:table-header-group">
<tr>
<th
scope="col"
@@ -91,18 +95,18 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
</th>
</tr>
</thead>
<tbody className="md:divide-y divide-gray-200 md:bg-white grid grid-cols-1 gap-3 sm:grid-cols-2 md:table-row-group">
<tbody className="grid grid-cols-1 gap-3 divide-gray-200 sm:grid-cols-2 md:table-row-group md:divide-y md:bg-white">
{paginatedInvestors.map((investor: any) => (
<tr
key={investor.id}
className="group grid grid-cols-3 gap-1 md:table-row bg-white rounded-lg md:rounded-none md:bg-transparent shadow md:shadow-none border border-gray-200 md:border-x-0 py-3 px-2 md:p-0"
className="group grid grid-cols-3 gap-1 rounded-lg border border-gray-200 bg-white px-2 py-3 shadow md:table-row md:rounded-none md:border-x-0 md:bg-transparent md:p-0 md:shadow-none"
>
<td className="col-span-3 whitespace-nowrap pl-3 md:py-2 md:pl-6 text-sm sm:pl-6 md:h-24">
<td className="col-span-3 whitespace-nowrap pl-3 text-sm sm:pl-6 md:h-24 md:py-2 md:pl-6">
<div className="flex items-center space-x-2">
<div className="h-10 w-10 flex-shrink-0">
{investor.imageUrl ? (
<img
className="rounded-full h-10 w-10 object-contain"
className="h-10 w-10 rounded-full object-contain"
width={40}
height={40}
src={
@@ -114,7 +118,7 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
/>
) : (
<Image
className="rounded-full h-10 w-10 object-contain"
className="h-10 w-10 rounded-full object-contain"
width={40}
height={40}
src={PlaceholderImg}
@@ -126,7 +130,7 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
<div className="font-medium text-gray-900">
{investor.name}
</div>
<div className="flex space-x-2 items-center">
<div className="flex items-center space-x-2">
{investor.website && (
<a
className="text-black"
@@ -135,7 +139,7 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
rel="noopener"
>
<span className="sr-only">Website</span>
<GlobeIcon className="w-4 h-4" />
<GlobeIcon className="h-4 w-4" />
</a>
)}
<Link
@@ -146,45 +150,45 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
width={18}
height={18}
alt="Papermark"
className="block ring-1 ring-gray-300 rounded-full"
className="block rounded-full ring-1 ring-gray-300"
/>
</Link>
</div>
</div>
</div>
</td>
<td className="col-span-1 row-start-2 whitespace-nowrap px-3 md:px-2 md:py-3 text-sm text-gray-500 font-bold md:font-normal">
<td className="col-span-1 row-start-2 whitespace-nowrap px-3 text-sm font-bold text-gray-500 md:px-2 md:py-3 md:font-normal">
{investor.round ? investor.round : "Unknown"}
</td>
<td className="col-span-3 whitespace-nowrap px-3 md:px-2 md:py-3 text-sm text-gray-500 md:mt-0">
<td className="col-span-3 whitespace-nowrap px-3 text-sm text-gray-500 md:mt-0 md:px-2 md:py-3">
{investor.location ? investor.location : "Unknown"}
</td>
<td className="col-span-3 md:max-w-xs px-3 md:px-2 md:py-3 text-sm text-gray-500 truncate w-40">
<td className="col-span-3 w-40 truncate px-3 text-sm text-gray-500 md:max-w-xs md:px-2 md:py-3">
{investor.sector ? investor.sector : "Unknown"}
</td>
</tr>
))}
</tbody>
</table>
<div className="flex justify-between items-center w-full my-4 px-4">
<div className="my-4 flex w-full items-center justify-between px-4">
<button
disabled={currentPage === 1}
className="px-2 py-2 rounded border text-xs"
className="rounded border px-2 py-2 text-xs"
>
Previous
</button>
<div className="px-2 py-2 rounded text-xs">
<div className="rounded px-2 py-2 text-xs">
Page {currentPage} of {totalPages}
</div>
<button
disabled={currentPage === totalPages}
className="px-2 py-2 rounded border text-xs"
className="rounded border px-2 py-2 text-xs"
>
Next
</button>
</div>
{allInvestors.length === 0 && (
<div className="text-center my-10">No results found</div>
<div className="my-10 text-center">No results found</div>
)}
</div>
</div>
@@ -192,4 +196,4 @@ export const FallbackInvestors = async ({allInvestors}: {allInvestors: any[]}) =
</div>
</>
);
}
};

View File

@@ -1,27 +1,30 @@
import { getInvestor } from "@/lib/content/investor";
import { notFound } from "next/navigation";
import Head from "next/head";
import Footer from "@/components/web/footer";
import Link from "next/link";
import { notFound } from "next/navigation";
import { Disclosure } from "@headlessui/react";
import { CheckIcon } from "lucide-react";
import { XIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import {
Plus as PlusSmallIcon,
Minus as MinusSmallIcon,
RefreshCw as ArrowPathIcon,
GitPullRequestArrow as CloudArrowUpIcon,
Settings as Cog6ToothIcon,
Fingerprint as FingerPrintIcon,
Lock as LockClosedIcon,
Minus as MinusSmallIcon,
Plus as PlusSmallIcon,
HardDrive as ServerIcon,
} from "lucide-react";
import Link from "next/link";
import { classNames } from "@/lib/utils";
import { LogoCloud } from "@/components/web/landing-page/logo-cloud";
import { Button } from "@/components/ui/button";
import Footer from "@/components/web/footer";
import { LogoCloud } from "@/components/web/landing-page/logo-cloud";
import Navbar from "@/components/web/navbar";
import { getInvestor } from "@/lib/content/investor";
import { cn } from "@/lib/utils";
import { classNames } from "@/lib/utils";
export default async function InvestorPage({
params,
}: {
@@ -56,8 +59,8 @@ export default async function InvestorPage({
</Head>
{/* Hero section */}
<div className="flex flex-1 flex-col bg-white text-black justify-center">
<div className="max-w-5xl w-full mx-auto px-4 md:px-8 text-center">
<div className="flex flex-1 flex-col justify-center bg-white text-black">
<div className="mx-auto w-full max-w-5xl px-4 text-center md:px-8">
<div className="pt-32">
{/* <div className=" pb-4">
<img
@@ -68,19 +71,19 @@ export default async function InvestorPage({
height={50}
/>
</div> */}
<div className="relative rounded-full inline-block my-4 ">
<span className="px-3 py-1 text-sm leading-6 bg-green-100 text-green-600 border border-green-200 rounded-full text-balance">
<div className="relative my-4 inline-block rounded-full ">
<span className="text-balance rounded-full border border-green-200 bg-green-100 px-3 py-1 text-sm leading-6 text-green-600">
Active
</span>
</div>
<h1 className="text-6xl text-balance">{investor.name}</h1>
<p className="text-xl mt-8 text-balance max-w-3xl mx-auto md:text-2xl">
<h1 className="text-balance text-6xl">{investor.name}</h1>
<p className="mx-auto mt-8 max-w-3xl text-balance text-xl md:text-2xl">
Venture capital and investor firm
</p>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link href={investor.website || "/investors"}>
<Button className="text-white bg-gray-800 rounded-3xl hover:bg-gray-500 justify-center">
<Button className="justify-center rounded-3xl bg-gray-800 text-white hover:bg-gray-500">
{investor.name} website link
</Button>
</Link>
@@ -89,20 +92,20 @@ export default async function InvestorPage({
</div>
{/* Comparison section */}
<div className="max-w-5xl w-full mx-auto px-4 md:px-8"></div>
<div className="mx-auto w-full max-w-5xl px-4 md:px-8"></div>
<div className="bg-white py-16">
<div className="mx-auto max-w-5xl px-4 md:px-8">
<div className="isolate grid grid-cols-1 md:grid-cols-2 border border-black rounded-xl overflow-hidden">
<div className="isolate grid grid-cols-1 overflow-hidden rounded-xl border border-black md:grid-cols-2">
{/* First hardcoded tier */}
<div className="border-black border-r-0 md:odd:border-r xl:even:border-r xl:last:!border-r-0 flex flex-col justify-between">
<div className="flex flex-col justify-between border-r-0 border-black md:odd:border-r xl:last:!border-r-0 xl:even:border-r">
<div>
<div className="border-b border-black p-6 bg-gray-100">
<h3 className="text-balance text-gray-800 text-xl leading-8">
<div className="border-b border-black bg-gray-100 p-6">
<h3 className="text-balance text-xl leading-8 text-gray-800">
Rounds {investor.name} invests
</h3>
</div>
<div className="p-6">
<p className="mt-4 text-sm leading-6 text-gray-500 text-balance">
<p className="mt-4 text-balance text-sm leading-6 text-gray-500">
Investor stage information
</p>
<p className="mt-6 flex items-baseline gap-x-1">
@@ -128,15 +131,15 @@ export default async function InvestorPage({
</div>
{/* Second hardcoded tier */}
<div className="border-black flex flex-col justify-between">
<div className="flex flex-col justify-between border-black">
<div>
<div className="border-b border-black p-6 bg-gray-100">
<h3 className="text-balance text-gray-800 text-xl leading-8">
<div className="border-b border-black bg-gray-100 p-6">
<h3 className="text-balance text-xl leading-8 text-gray-800">
Location {investor.name} invests
</h3>
</div>
<div className="p-6">
<p className="mt-4 text-sm leading-6 text-gray-500 text-balance">
<p className="mt-4 text-balance text-sm leading-6 text-gray-500">
Investor primarily location but not limited
</p>
<p className="mt-6 flex items-baseline gap-x-1">
@@ -162,16 +165,16 @@ export default async function InvestorPage({
</div>
</div>
<div className="my-8 isolate border border-black rounded-xl overflow-hidden">
<div className="isolate my-8 overflow-hidden rounded-xl border border-black">
<div className="flex flex-col justify-between">
<div>
<div className="border-b border-black p-6 bg-gray-100">
<h3 className="text-balance text-gray-800 text-xl leading-8">
<div className="border-b border-black bg-gray-100 p-6">
<h3 className="text-balance text-xl leading-8 text-gray-800">
Sector {investor.name} invests
</h3>
</div>
<div className="p-6">
<p className="mt-4 text-sm leading-6 text-gray-500 text-balance">
<p className="mt-4 text-balance text-sm leading-6 text-gray-500">
Sectors primarily invested in
</p>
<p className="mt-6 flex items-baseline gap-x-1">
@@ -199,23 +202,23 @@ export default async function InvestorPage({
</div>
</div>
<div className="w-full max-w-5xl px-4 md:px-8 mx-auto ">
<div className="py-12 bg-[#fb7a00] rounded-3xl mx-auto px-6">
<div className="flex lg:flex-row flex-col item-center justify-between space-y-10 lg:space-y-0">
<h2 className="text-3xl text-nowrap">
<div className="mx-auto w-full max-w-5xl px-4 md:px-8 ">
<div className="mx-auto rounded-3xl bg-[#fb7a00] px-6 py-12">
<div className="item-center flex flex-col justify-between space-y-10 lg:flex-row lg:space-y-0">
<h2 className="text-nowrap text-3xl">
Looking for more investors? <br />
<p className="text-gray-800 text-xl my-2">
<p className="my-2 text-xl text-gray-800">
Access our investor database with 10k+ venture capital firms
</p>
</h2>
<div className="space-x-2 flex items-center">
<div className="flex items-center space-x-2">
<Link
href="/investors"
target="_blank"
rel="noopener noreferrer"
>
<Button className="text-base rounded-3xl text-gray-200 bg-black hover:bg-gray-900">
<Button className="rounded-3xl bg-black text-base text-gray-200 hover:bg-gray-900">
Full investor database
</Button>
</Link>
@@ -226,10 +229,10 @@ export default async function InvestorPage({
{/* /* Feature Section*/}
<div
className="w-full mx-auto max-w-5xl px-4 md:px-8 py-20"
className="mx-auto w-full max-w-5xl px-4 py-20 md:px-8"
id="features"
>
<h2 className="text-4xl text-balance pt-12 pb-20 max-w-3xl">
<h2 className="max-w-3xl text-balance pb-20 pt-12 text-4xl">
Powered by Papermark{" "}
<span className="text-gray-500">
Open Source DocSend alternative to share your pitchdeck and
@@ -239,15 +242,15 @@ export default async function InvestorPage({
{/* Testimonial section */}
<div
className="w-full mx-auto max-w-5xl px-4 md:px-8 py-20 bg-gray-100 rounded-3xl"
className="mx-auto w-full max-w-5xl rounded-3xl bg-gray-100 px-4 py-20 md:px-8"
id="features"
>
<div className="mx-auto flex flex-col items-center gap-x-8 gap-y-10 px-6 sm:gap-y-8 lg:px-8 xl:flex-row xl:items-stretch">
<div className="-mt-8 w-full max-w-2xl xl:-mb-8 xl:w-96 xl:flex-none flex items-center justify-center my-6">
<div className="relative w-64 h-64">
<div className="my-6 -mt-8 flex w-full max-w-2xl items-center justify-center xl:-mb-8 xl:w-96 xl:flex-none">
<div className="relative h-64 w-64">
{" "}
<img
className="absolute inset-0 object-cover rounded-2xl bg-gray-800 shadow-2xl"
className="absolute inset-0 rounded-2xl bg-gray-800 object-cover shadow-2xl"
src="https://www.papermark.io/_static/testimonials/jaski.jpeg"
alt=""
/>
@@ -271,7 +274,7 @@ export default async function InvestorPage({
x={86}
/>
</svg>
<blockquote className="text-xl font-medium leading-8 text-balance text-gray-800 text-black sm:text-2xl sm:leading-9">
<blockquote className="text-balance text-xl font-medium leading-8 text-black text-gray-800 sm:text-2xl sm:leading-9">
<p>
Papermark solved a big pain point for me. DocSend
monopoly will end soon!
@@ -279,13 +282,13 @@ export default async function InvestorPage({
</blockquote>
<figcaption className="mt-8 text-balance ">
<div className="font-semibold text-black ">Jaski</div>
<div className="mt-1 text-gray-500 my-6 ">
<div className="my-6 mt-1 text-gray-500 ">
Founder in web3 space
</div>
</figcaption>
</figure>
<Link href="/login" target="_blank" rel="noopener noreferrer">
<Button className="text-base rounded-3xl text-gray-800 bg-[#fb7a00] hover:bg-gray-200">
<Button className="rounded-3xl bg-[#fb7a00] text-base text-gray-800 hover:bg-gray-200">
Join Jaski now
</Button>
</Link>

View File

@@ -1,17 +1,19 @@
import { Suspense } from "react";
import { getInvestors } from "@/lib/content/investor";
import Dashboard from "./ClientPage";
import { FallbackInvestors } from "./Fallback";
import { getInvestors } from "@/lib/content/investor";
export default async function HomePage() {
const allInvestors = await getInvestors();
return (
<>
<div className="mx-auto max-w-6xl pt-4 mb-10">
<div className="max-w-6xl mx-auto px-4 md:px-8 sm:pt-16 pt-8 text-gray-600">
<div className="space-y-5 max-w-4xl mx-auto text-center mb-10">
<h1 className="text-3xl text-gray-800 font-extrabold mx-auto sm:text-6xl max-w-3xl tracking-tighter">
<div className="mx-auto mb-10 max-w-6xl pt-4">
<div className="mx-auto max-w-6xl px-4 pt-8 text-gray-600 sm:pt-16 md:px-8">
<div className="mx-auto mb-10 max-w-4xl space-y-5 text-center">
<h1 className="mx-auto max-w-3xl text-3xl font-extrabold tracking-tighter text-gray-800 sm:text-6xl">
Investors Database
</h1>
<p>

View File

@@ -1,6 +1,7 @@
import { Metadata } from "next";
import Footer from "@/components/web/footer";
import Navbar from "@/components/web/navbar";
import { Metadata } from "next";
const data = {
description:

View File

@@ -1,12 +1,16 @@
"use client";
import Fuse from "fuse.js";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useMemo, useState } from "react";
import InvestorTable from "@/components/investors/table";
import Fuse from "fuse.js";
import SearchBar from "@/components/investors/search";
import Stats from "@/components/investors/stats";
import Link from "next/link";
import InvestorTable from "@/components/investors/table";
import { cn } from "@/lib/utils";
const searchOptions = {
@@ -88,8 +92,8 @@ export default function Dashboard({ data }: any) {
return (
<>
<Stats angelsLength={angels.length} />
<div className="sm:flex flex-col md:flex-row justify-between mt-4">
<span className="isolate mt-5 inline-flex rounded-md shadow-sm w-fit">
<div className="mt-4 flex-col justify-between sm:flex md:flex-row">
<span className="isolate mt-5 inline-flex w-fit rounded-md shadow-sm">
{checkSizes.map((checkSize) => (
<Link
href={
@@ -99,11 +103,10 @@ export default function Dashboard({ data }: any) {
}
key={checkSize.id}
className={cn(
category === checkSize.id ||
(!category && checkSize.id === "7")
category === checkSize.id || (!category && checkSize.id === "7")
? "bg-gray-200"
: "bg-white hover:bg-gray-50",
"relative inline-flex items-center first-of-type:rounded-l-md last-of-type:rounded-r-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 focus:z-10 focus:outline-none focus:ring-gray-500 -ml-px first-of-type:-ml-0",
"relative -ml-px inline-flex items-center border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 first-of-type:-ml-0 first-of-type:rounded-l-md last-of-type:rounded-r-md focus:z-10 focus:outline-none focus:ring-gray-500",
)}
>
{checkSize.label}
@@ -113,9 +116,9 @@ export default function Dashboard({ data }: any) {
<SearchBar search={search} setSearch={setSearch} />
</div>
<div className="mt-8 flex flex-col">
<div className="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full py-2 align-middle px-6 lg:px-8">
<div className="overflow-hidden md:shadow md:ring-1 md:ring-black md:ring-opacity-5 rounded-lg">
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full px-6 py-2 align-middle lg:px-8">
<div className="overflow-hidden rounded-lg md:shadow md:ring-1 md:ring-black md:ring-opacity-5">
<InvestorTable investors={angels} />
</div>
</div>

View File

@@ -1,10 +1,14 @@
import { Metadata } from "next";
import Dashboard from "./ClientPage";
import Link from "next/link";
import { Suspense } from "react";
import Stats from "@/components/investors/stats";
import InvestorTable from "@/components/investors/table";
import Link from "next/link";
import { cn } from "@/lib/utils";
import { Suspense } from "react";
import Dashboard from "./ClientPage";
export const revalidate = 3600; // revalidate the data at most every 24 hours
@@ -90,8 +94,8 @@ const InvestorFallback = ({ allInvestors }: { allInvestors: Investor[] }) => {
return (
<>
<Stats angelsLength={allInvestors.length} />
<div className="sm:flex flex-col md:flex-row justify-between mt-4">
<span className="isolate mt-5 inline-flex rounded-md shadow-sm w-fit">
<div className="mt-4 flex-col justify-between sm:flex md:flex-row">
<span className="isolate mt-5 inline-flex w-fit rounded-md shadow-sm">
{checkSizes.map((checkSize) => (
<Link
href={
@@ -104,7 +108,7 @@ const InvestorFallback = ({ allInvestors }: { allInvestors: Investor[] }) => {
category === checkSize.id || (!category && checkSize.id === "7")
? "bg-gray-200"
: "bg-white hover:bg-gray-50",
"relative inline-flex items-center first-of-type:rounded-l-md last-of-type:rounded-r-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 focus:z-10 focus:outline-none focus:ring-gray-500 -ml-px first-of-type:-ml-0",
"relative -ml-px inline-flex items-center border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 first-of-type:-ml-0 first-of-type:rounded-l-md last-of-type:rounded-r-md focus:z-10 focus:outline-none focus:ring-gray-500",
)}
>
{checkSize.label}
@@ -113,9 +117,9 @@ const InvestorFallback = ({ allInvestors }: { allInvestors: Investor[] }) => {
</span>
</div>
<div className="mt-8 flex flex-col">
<div className="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full py-2 align-middle px-6 lg:px-8">
<div className="overflow-hidden md:shadow md:ring-1 md:ring-black md:ring-opacity-5 rounded-lg">
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full px-6 py-2 align-middle lg:px-8">
<div className="overflow-hidden rounded-lg md:shadow md:ring-1 md:ring-black md:ring-opacity-5">
<InvestorTable investors={allInvestors} />
</div>
</div>
@@ -131,10 +135,10 @@ export default async function HomePage() {
return (
<>
<div className="mx-auto max-w-6xl pt-4 mb-10">
<div className="max-w-6xl mx-auto px-4 md:px-8 sm:pt-16 pt-8 text-gray-600">
<div className="space-y-5 max-w-4xl mx-auto text-center">
<h1 className="text-3xl text-gray-800 font-extrabold mx-auto sm:text-6xl max-w-3xl tracking-tighter">
<div className="mx-auto mb-10 max-w-6xl pt-4">
<div className="mx-auto max-w-6xl px-4 pt-8 text-gray-600 sm:pt-16 md:px-8">
<div className="mx-auto max-w-4xl space-y-5 text-center">
<h1 className="mx-auto max-w-3xl text-3xl font-extrabold tracking-tighter text-gray-800 sm:text-6xl">
Find the next angel investor for your open-source project
</h1>
</div>

View File

@@ -1,7 +1,8 @@
import { Button } from "@/components/ui/button";
import { Metadata } from "next";
import Image from "next/image";
import { Button } from "@/components/ui/button";
const data = {
description:
"Meet our fellow open source projects. Papermark is an open-source document infrastructure for sharing and collaboration.",
@@ -190,7 +191,7 @@ export default function Friends() {
{friends.map((friend) => (
<li
key={friend.id}
className="overflow-hidden rounded-xl border border-gray-200 flex flex-col justify-between"
className="flex flex-col justify-between overflow-hidden rounded-xl border border-gray-200"
>
<div>
<div className="flex items-center gap-x-4 p-6">
@@ -202,14 +203,14 @@ export default function Friends() {
className="h-12 w-12 flex-none rounded-lg bg-white object-cover"
/>
</div>
<div className="text-xl font-medium leading-6 text-gray-900 pb-1 px-6">
<div className="px-6 pb-1 text-xl font-medium leading-6 text-gray-900">
{friend.name}
</div>
<p className="px-6 mt-2 text-gray-600 text-sm ">
<p className="mt-2 px-6 text-sm text-gray-600 ">
{friend.description}
</p>
</div>
<div className="text-left px-6">
<div className="px-6 text-left">
<a
href={friend.buttonLink}
target="_blank"
@@ -218,7 +219,7 @@ export default function Friends() {
>
<Button
type="button"
className="mt-4 mb-6 rounded-md bg-black text-sm font-semibold text-white shadow-sm"
className="mb-6 mt-4 rounded-md bg-black text-sm font-semibold text-white shadow-sm"
>
{friend.buttonText}
</Button>

View File

@@ -1,11 +1,11 @@
import { type Metadata } from "next";
import Link from "next/link";
import { notFound } from "next/navigation";
import { Button } from "@/components/ui/button";
import Testimonials from "@/components/web/testimonials";
import { getPage, getPages } from "@/lib/content/page";
import { notFound } from "next/navigation";
import { getPage, getPages } from "@/lib/content/page";
import { constructMetadata } from "@/lib/utils";
export async function generateStaticParams() {
@@ -38,8 +38,8 @@ export default async function PagePage({
if (!page) return notFound();
return (
<div className="flex flex-1 flex-col bg-white text-black justify-center">
<div className="max-w-5xl w-full mx-auto px-4 md:px-8 text-center">
<div className="flex flex-1 flex-col justify-center bg-white text-black">
<div className="mx-auto w-full max-w-5xl px-4 text-center md:px-8">
<div className="pt-32">
{/* <div className=" pb-4">
<img
@@ -53,19 +53,19 @@ export default async function PagePage({
{/* <div className="relative rounded-full px-3 py-1 text-sm leading-6 text-black ring-black/10 hover:ring-white/20 text-balance">
Join 1000s happy users
</div> */}
<h1 className="text-6xl text-balance">{page.title}</h1>
<p className="text-xl mt-8 text-balance max-w-3xl mx-auto md:text-2xl">
<h1 className="text-balance text-6xl">{page.title}</h1>
<p className="mx-auto mt-8 max-w-3xl text-balance text-xl md:text-2xl">
{page.description}
</p>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link href="/login">
<Button className="text-white text-balance bg-gray-900 rounded-3xl hover:bg-gray-800 justify-center">
<Button className="justify-center text-balance rounded-3xl bg-gray-900 text-white hover:bg-gray-800">
{page.button}
</Button>
</Link>
</div>
</div>
<div className="mt-24 mx-auto w-full">
<div className="mx-auto mt-24 w-full">
<video
width="100%"
id="video1"
@@ -90,16 +90,16 @@ export default async function PagePage({
<div className="grid grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:grid-cols-2 lg:items-start">
<div className="px-6 lg:px-0 lg:pr-4 lg:pt-4">
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-lg">
<h2 className="mt-2 text-3xl text-gray-900 sm:text-4xl text-balance">
<h2 className="mt-2 text-balance text-3xl text-gray-900 sm:text-4xl">
{page.subtitle1}
</h2>
<p className="mt-6 text-lg leading-8 text-gray-600 text-balance">
<p className="mt-6 text-balance text-lg leading-8 text-gray-600">
{page.description1}
</p>
</div>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link href="/login">
<Button className="text-white text-balance bg-gray-900 rounded-3xl hover:bg-gray-800 justify-center">
<Button className="justify-center text-balance rounded-3xl bg-gray-900 text-white hover:bg-gray-800">
{page.button}
</Button>
</Link>
@@ -162,16 +162,16 @@ export default async function PagePage({
</div>
<div className="px-6 lg:px-0 lg:pr-4 lg:pt-4">
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-lg">
<h2 className="mt-2 text-3xl text-gray-900 sm:text-4xl text-balance">
<h2 className="mt-2 text-balance text-3xl text-gray-900 sm:text-4xl">
{page.subtitle2}
</h2>
<p className="mt-6 text-lg leading-8 text-gray-600 text-balance">
<p className="mt-6 text-balance text-lg leading-8 text-gray-600">
{page.description2}
</p>
</div>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link href="/login">
<Button className="text-white text-balance bg-gray-900 rounded-3xl hover:bg-gray-800 justify-center">
<Button className="justify-center text-balance rounded-3xl bg-gray-900 text-white hover:bg-gray-800">
{page.button}
</Button>
</Link>
@@ -186,10 +186,10 @@ export default async function PagePage({
{/* CTA */}
<div className="bg-[#fb7a00]">
<div className="w-full mx-auto max-w-5xl py-32 px-4 md:px-8">
<h2 className="text-4xl text-balance ">{page.cta}</h2>
<div className="mx-auto w-full max-w-5xl px-4 py-32 md:px-8">
<h2 className="text-balance text-4xl ">{page.cta}</h2>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link href="/login">
<Button className="text-balance rounded-3xl">
Start for free

View File

@@ -1,6 +1,6 @@
import { NextResponse } from "next/server";
import { receiver } from "@/lib/cron";
import { handleDomainUpdates } from "./utils";
import {
getConfigResponse,
getDomainResponse,
@@ -9,6 +9,8 @@ import {
import prisma from "@/lib/prisma";
import { log } from "@/lib/utils";
import { handleDomainUpdates } from "./utils";
/**
* Cron to check if domains are verified.
* If a domain is invalid for more than 14 days, we send a reminder email to the owner.
@@ -116,7 +118,7 @@ export async function POST(req: Request) {
await log({
message: `Domains cron failed. \n\nError: ${(error as Error).message}`,
type: "cron",
mention: true
mention: true,
});
return NextResponse.json({ error: (error as Error).message });
}

View File

@@ -1,9 +1,9 @@
import { log } from "@/lib/utils";
import { deleteDomain } from "@/lib/api/domains";
import prisma from "@/lib/prisma";
import { limiter } from "@/lib/cron";
import { sendDeletedDomainEmail } from "@/lib/emails/send-deleted-domain";
import { sendInvalidDomainEmail } from "@/lib/emails/send-invalid-domain";
import prisma from "@/lib/prisma";
import { log } from "@/lib/utils";
export const handleDomainUpdates = async ({
domain,
@@ -19,7 +19,10 @@ export const handleDomainUpdates = async ({
linksCount: number;
}) => {
if (changed) {
await log({message: `Domain *${domain}* changed status to *${verified}*`, type: "cron"});
await log({
message: `Domain *${domain}* changed status to *${verified}*`,
type: "cron",
});
}
if (verified) return;
@@ -111,7 +114,7 @@ export const handleDomainUpdates = async ({
await log({
message: `Domain *${domain}* has been invalid for > 30 days and has links with clicks, skipping.`,
type: "cron",
mention: true
mention: true,
});
return;
}

View File

@@ -1,9 +1,10 @@
import { NextResponse } from "next/server";
import { limiter, receiver } from "@/lib/cron";
import { sendTrialEndFinalReminderEmail } from "@/lib/emails/send-trial-end-final-reminder";
import { sendTrialEndReminderEmail } from "@/lib/emails/send-trial-end-reminder";
import prisma from "@/lib/prisma";
import { calculateDaysLeft, log } from "@/lib/utils";
import { sendTrialEndReminderEmail } from "@/lib/emails/send-trial-end-reminder";
import { sendTrialEndFinalReminderEmail } from "@/lib/emails/send-trial-end-final-reminder";
/**
* Cron to check if trial has expired.

View File

@@ -1,7 +1,6 @@
import { createAppRoute } from "@trigger.dev/nextjs";
import { client } from "@/trigger";
import "@/jobs";
import { client } from "@/trigger";
import { createAppRoute } from "@trigger.dev/nextjs";
// This is the maximum duration of a job in seconds
export const maxDuration = 120;

View File

@@ -1,8 +1,10 @@
import "@/styles/globals.css";
import { Metadata } from "next";
import PlausibleProvider from "next-plausible";
import { Inter } from "next/font/google";
import PlausibleProvider from "next-plausible";
import "@/styles/globals.css";
const inter = Inter({ subsets: ["latin"] });
const data = {

View File

@@ -1,22 +1,23 @@
import Link from "next/link";
import TwitterIcon from "@/components/shared/icons/twitter";
import ProductHuntIcon from "@/components/shared/icons/producthunt";
import { Button } from "@/components/ui/button";
import Image from "next/image";
import Navbar from "@/components/web/navbar";
import Footer from "@/components/web/footer";
import { LogoCloud } from "@/components/web/landing-page/logo-cloud";
import Testimonials from "@/components/web/testimonials";
import Link from "next/link";
import {
RefreshCw as ArrowPathIcon,
Settings as Cog6ToothIcon,
ServerIcon,
PaletteIcon,
SlidersIcon,
BarChart3Icon,
Settings as Cog6ToothIcon,
PaletteIcon,
ServerIcon,
SlidersIcon,
} from "lucide-react";
import ProductHuntIcon from "@/components/shared/icons/producthunt";
import TwitterIcon from "@/components/shared/icons/twitter";
import { Button } from "@/components/ui/button";
import Footer from "@/components/web/footer";
import { LogoCloud } from "@/components/web/landing-page/logo-cloud";
import Navbar from "@/components/web/navbar";
import Testimonials from "@/components/web/testimonials";
const features = [
{
name: "Fine-tune access control",
@@ -60,16 +61,16 @@ export default function Home() {
<div className="flex flex-1 flex-col bg-white text-black">
<Navbar />
<div className="max-w-7xl w-full mx-auto px-4 md:px-8">
<div className="mx-auto w-full max-w-7xl px-4 md:px-8">
<div className="pt-24">
<h1 className="text-6xl md:text-8xl text-balance">
<h1 className="text-balance text-6xl md:text-8xl">
The Open-Source DocSend Alternative
</h1>
<p className="text-2xl mt-8 text-balance max-w-3xl">
<p className="mt-8 max-w-3xl text-balance text-2xl">
Papermark is a modern document sharing infrastructure with
built-in page analytics and full white-labeling
</p>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link
href="https://cal.com/marcseitz/papermark"
target="_blank"
@@ -77,16 +78,16 @@ export default function Home() {
>
<Button
variant="outline"
className="text-base rounded-3xl bg-transparent border-black"
className="rounded-3xl border-black bg-transparent text-base"
>
Book a demo
</Button>
</Link>
<Link href="/login">
<Button className="text-base rounded-3xl">Send document</Button>
<Button className="rounded-3xl text-base">Send document</Button>
</Link>
</div>
<div className="mt-24 mx-auto w-full">
<div className="mx-auto mt-24 w-full">
<video
width="100%"
id="video1"
@@ -106,16 +107,16 @@ export default function Home() {
</div>
</div>
<div className="grid gap-16 md:gap-24 lg:gap-32 mt-20">
<div className="mt-20 grid gap-16 md:gap-24 lg:gap-32">
<div className="mx-auto mt-4 w-full px-0 lg:px-8 xl:p-0">
<LogoCloud />
</div>
</div>
</div>
<div className="mt-24 bg-gray-50 w-full overflow-x-hidden">
<div className="w-full mx-auto max-w-7xl px-4 md:px-8">
<h2 className="text-4xl text-balance pt-20 pb-20">
<div className="mt-24 w-full overflow-x-hidden bg-gray-50">
<div className="mx-auto w-full max-w-7xl px-4 md:px-8">
<h2 className="text-balance pb-20 pt-20 text-4xl">
Share your documents, securely.{" "}
<span className="text-gray-500">
{/* Fine-tune access control. Receive real-time page analytics.
@@ -124,54 +125,54 @@ export default function Home() {
</span>
</h2>
</div>
<div className="mx-4 sm:mx-0 sm:flex sm:flex-nowrap gap-6 lg:gap-10 mb-6 lg:mb-10 sm:translate-x-[-30px] text-balance">
<div className="bg-gray-200 flex-none rounded-xl p-6 mb-6 sm:max-w-[300px] sm:p-6 sm:mb-0 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="text-black/90 font-380 text-base lg:text-base xl:text-base 2xl:text-lg 2xl:-ml-0.5 tracking-tight leading-none">
<div className="mx-4 mb-6 gap-6 text-balance sm:mx-0 sm:flex sm:translate-x-[-30px] sm:flex-nowrap lg:mb-10 lg:gap-10">
<div className="mb-6 flex-none rounded-xl bg-gray-200 p-6 sm:mb-0 sm:max-w-[300px] sm:p-6 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="font-380 text-base leading-none tracking-tight text-black/90 lg:text-base xl:text-base 2xl:-ml-0.5 2xl:text-lg">
Real Estate
</p>
<p className="text-black/90 font-380 text-xl -ml-0.5 md:text-2xl md:-ml-0.5 md:leading-none lg:text-4xl lg:-ml-0.5 xl:text-4xl xl:-ml-0.5 tracking-tighter leading-tight ">
<p className="font-380 -ml-0.5 text-xl leading-tight tracking-tighter text-black/90 md:-ml-0.5 md:text-2xl md:leading-none lg:-ml-0.5 lg:text-4xl xl:-ml-0.5 xl:text-4xl ">
Securely share property documents with clients
</p>
</div>
<div className="bg-black/80 flex-none rounded-xl p-6 mb-6 sm:max-w-[300px] sm:p-6 sm:mb-0 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="text-gray-50 font-380 text-base lg:text-base xl:text-base 2xl:text-lg 2xl:-ml-0.5 tracking-tight leading-none">
<div className="mb-6 flex-none rounded-xl bg-black/80 p-6 sm:mb-0 sm:max-w-[300px] sm:p-6 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="font-380 text-base leading-none tracking-tight text-gray-50 lg:text-base xl:text-base 2xl:-ml-0.5 2xl:text-lg">
Startups
</p>
<p className="text-gray-50 font-380 text-xl -ml-0.5 md:text-2xl md:-ml-0.5 md:leading-none lg:text-4xl lg:-ml-0.5 xl:text-4xl xl:-ml-0.5 tracking-tighter leading-tight ">
<p className="font-380 -ml-0.5 text-xl leading-tight tracking-tighter text-gray-50 md:-ml-0.5 md:text-2xl md:leading-none lg:-ml-0.5 lg:text-4xl xl:-ml-0.5 xl:text-4xl ">
Take ownership of your fundraising process
</p>
</div>
<div className="bg-gray-200 flex-none rounded-xl p-6 mb-6 sm:max-w-[300px] sm:p-6 sm:mb-0 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="text-black/90 font-380 text-base lg:text-base xl:text-base 2xl:text-lg 2xl:-ml-0.5 tracking-tight leading-none">
<div className="mb-6 flex-none rounded-xl bg-gray-200 p-6 sm:mb-0 sm:max-w-[300px] sm:p-6 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="font-380 text-base leading-none tracking-tight text-black/90 lg:text-base xl:text-base 2xl:-ml-0.5 2xl:text-lg">
Growth
</p>
<p className="text-black/90 font-380 text-xl -ml-0.5 md:text-2xl md:-ml-0.5 md:leading-none lg:text-4xl lg:-ml-0.5 xl:text-4xl xl:-ml-0.5 tracking-tighter leading-tight ">
<p className="font-380 -ml-0.5 text-xl leading-tight tracking-tighter text-black/90 md:-ml-0.5 md:text-2xl md:leading-none lg:-ml-0.5 lg:text-4xl xl:-ml-0.5 xl:text-4xl ">
Capture marketing-qualified leads on social media
</p>
</div>
</div>
<div className="mx-4 sm:mx-0 sm:flex sm:flex-nowrap gap-6 lg:gap-10 mb-6 lg:mb-10 sm:translate-x-[50px] text-balance">
<div className="bg-black/80 flex-none rounded-xl p-6 mb-6 sm:max-w-[300px] sm:p-6 sm:mb-0 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="text-gray-50 font-380 text-base lg:text-base xl:text-base 2xl:text-lg 2xl:-ml-0.5 tracking-tight leading-none">
<div className="mx-4 mb-6 gap-6 text-balance sm:mx-0 sm:flex sm:translate-x-[50px] sm:flex-nowrap lg:mb-10 lg:gap-10">
<div className="mb-6 flex-none rounded-xl bg-black/80 p-6 sm:mb-0 sm:max-w-[300px] sm:p-6 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="font-380 text-base leading-none tracking-tight text-gray-50 lg:text-base xl:text-base 2xl:-ml-0.5 2xl:text-lg">
Sales
</p>
<p className="text-gray-50 font-380 text-xl -ml-0.5 md:text-2xl md:-ml-0.5 md:leading-none lg:text-4xl lg:-ml-0.5 xl:text-4xl xl:-ml-0.5 tracking-tighter leading-tight ">
<p className="font-380 -ml-0.5 text-xl leading-tight tracking-tighter text-gray-50 md:-ml-0.5 md:text-2xl md:leading-none lg:-ml-0.5 lg:text-4xl xl:-ml-0.5 xl:text-4xl ">
Spend time on only engaged prospects
</p>
</div>
<div className="bg-gray-200 flex-none rounded-xl p-6 mb-6 sm:max-w-[300px] sm:p-6 sm:mb-0 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="text-black/90 font-380 text-base lg:text-base xl:text-base 2xl:text-lg 2xl:-ml-0.5 tracking-tight leading-none">
<div className="mb-6 flex-none rounded-xl bg-gray-200 p-6 sm:mb-0 sm:max-w-[300px] sm:p-6 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="font-380 text-base leading-none tracking-tight text-black/90 lg:text-base xl:text-base 2xl:-ml-0.5 2xl:text-lg">
Investors
</p>
<p className="text-black/90 font-380 text-xl -ml-0.5 md:text-2xl md:-ml-0.5 md:leading-none lg:text-4xl lg:-ml-0.5 xl:text-4xl xl:-ml-0.5 tracking-tighter leading-tight">
<p className="font-380 -ml-0.5 text-xl leading-tight tracking-tighter text-black/90 md:-ml-0.5 md:text-2xl md:leading-none lg:-ml-0.5 lg:text-4xl xl:-ml-0.5 xl:text-4xl">
Take the guess-work out of LP updates
</p>
</div>
<div className="bg-black/80 flex-none rounded-xl p-6 mb-6 sm:max-w-[300px] sm:p-6 sm:mb-0 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="text-gray-50 font-380 text-base lg:text-base xl:text-base 2xl:text-lg 2xl:-ml-0.5 tracking-tight leading-none">
<div className="mb-6 flex-none rounded-xl bg-black/80 p-6 sm:mb-0 sm:max-w-[300px] sm:p-6 md:max-w-[360px] lg:max-w-[500px] lg:p-8 xl:max-w-[560px] xl:p-10 2xl:max-w-[640px]">
<p className="font-380 text-base leading-none tracking-tight text-gray-50 lg:text-base xl:text-base 2xl:-ml-0.5 2xl:text-lg">
Non-Profits
</p>
<p className="text-gray-50 font-380 text-xl -ml-0.5 md:text-2xl md:-ml-0.5 md:leading-none lg:text-4xl lg:-ml-0.5 xl:text-4xl xl:-ml-0.5 tracking-tighter leading-tight ">
<p className="font-380 -ml-0.5 text-xl leading-tight tracking-tighter text-gray-50 md:-ml-0.5 md:text-2xl md:leading-none lg:-ml-0.5 lg:text-4xl xl:-ml-0.5 xl:text-4xl ">
Securely share and track grant applications
</p>
</div>
@@ -179,10 +180,10 @@ export default function Home() {
</div>
<div
className="w-full mx-auto max-w-7xl px-4 md:px-8 py-20"
className="mx-auto w-full max-w-7xl px-4 py-20 md:px-8"
id="features"
>
<h2 className="text-4xl text-balance pt-12 pb-20 max-w-3xl">
<h2 className="max-w-3xl text-balance pb-20 pt-12 text-4xl">
Built for modern teams.{" "}
<span className="text-gray-500">
Share your documents with an impression that lasts.
@@ -199,10 +200,10 @@ export default function Home() {
className="h-10 w-10 text-gray-800"
aria-hidden="true"
/>
<dt className="inline text-gray-800 text-2xl">
<dt className="inline text-2xl text-gray-800">
{feature.name}
</dt>{" "}
<dd className="inline text-base text-balance">
<dd className="inline text-balance text-base">
{feature.description}
</dd>
</div>
@@ -216,11 +217,11 @@ export default function Home() {
</div>
<div className="bg-[#fb7a00]">
<div className="w-full mx-auto max-w-7xl py-32 px-4 md:px-8">
<h2 className="text-4xl text-balance ">
<div className="mx-auto w-full max-w-7xl px-4 py-32 md:px-8">
<h2 className="text-balance text-4xl ">
Sharing with Papermark is secure, fast, and free.
</h2>
<div className="pt-8 space-x-2">
<div className="space-x-2 pt-8">
<Link
href="https://cal.com/marcseitz/papermark"
target="_blank"
@@ -228,13 +229,13 @@ export default function Home() {
>
<Button
variant="outline"
className="text-base rounded-3xl bg-transparent border-black"
className="rounded-3xl border-black bg-transparent text-base"
>
Book a demo
</Button>
</Link>
<Link href="/login">
<Button className="text-base rounded-3xl">
<Button className="rounded-3xl text-base">
Start for free
</Button>
</Link>

View File

@@ -1,11 +1,12 @@
import {
getPosts,
getAlternatives,
getPages,
getHelpArticles,
} from "@/lib/content";
import { MetadataRoute } from "next";
import {
getAlternatives,
getHelpArticles,
getPages,
getPosts,
} from "@/lib/content";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getPosts();
const solutions = await getPages();

View File

@@ -1,7 +1,7 @@
export default function EmailForm({ onSubmitHandler, setEmail }: any) {
return (
<>
<div className="flex h-screen flex-1 flex-col px-6 py-12 lg:px-8 bg-black">
<div className="flex h-screen flex-1 flex-col bg-black px-6 py-12 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-10 text-2xl font-bold leading-9 tracking-tight text-white">
Enter your email to view the document

View File

@@ -1,10 +1,12 @@
import { useEffect, useRef, useState } from "react";
import { Brand, DataroomBrand } from "@prisma/client";
import { ExtendedRecordMap } from "notion-types";
import { NotionRenderer } from "react-notion-x";
// core styles shared by all of react-notion-x (required)
import "react-notion-x/src/styles.css";
import Nav from "./view/nav";
import { Brand, DataroomBrand } from "@prisma/client";
export const NotionPage = ({
recordMap,

View File

@@ -1,38 +1,43 @@
import { useEffect, useState } from "react";
import { useSession } from "next-auth/react";
import SettingsIcon from "@/components/shared/icons/settings";
import MenuIcon from "@/components/shared/icons/menu";
import { cn } from "@/lib/utils";
import { useRouter } from "next/router";
import Banner from "./banner";
import ProBanner from "./billing/pro-banner";
import Cookies from "js-cookie";
import { usePlan } from "@/lib/swr/use-billing";
import SelectTeam from "./teams/select-team";
import { useEffect, useState } from "react";
import { TeamContextType, initialState, useTeam } from "@/context/team-context";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import ProfileMenu from "./profile-menu";
import Cookies from "js-cookie";
import {
PaletteIcon,
FolderIcon as FolderLucideIcon,
FolderOpenIcon,
PaletteIcon,
ServerIcon,
} from "lucide-react";
import SiderbarFolders from "./sidebar-folders";
import { ScrollArea } from "./ui/scroll-area";
import { useSession } from "next-auth/react";
import MenuIcon from "@/components/shared/icons/menu";
import SettingsIcon from "@/components/shared/icons/settings";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { usePlan } from "@/lib/swr/use-billing";
import { cn } from "@/lib/utils";
import Banner from "./banner";
import ProBanner from "./billing/pro-banner";
import { UpgradePlanModal } from "./billing/upgrade-plan-modal";
import ProfileMenu from "./profile-menu";
import SiderbarFolders from "./sidebar-folders";
import SelectTeam from "./teams/select-team";
import { ScrollArea } from "./ui/scroll-area";
export default function Sidebar() {
return (
<>
<nav>
{/* sidebar for desktop */}
<SidebarComponent className="hidden lg:fixed lg:inset-y-0 lg:flex lg:z-50" />
<SidebarComponent className="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex" />
{/* move main screen to the right by width of the sidebar on desktop */}
<div className="lg:pl-72"></div>
{/* sidebar for mobile */}
<div className="sticky lg:hidden top-0 z-40 mb-1 flex items-center h-14 shrink-0 border-gray-50/90 bg-gray-50 dark:border-black/10 dark:bg-black/95 px-6 sm:px-12 border-b dark:border-none">
<div className="sticky top-0 z-40 mb-1 flex h-14 shrink-0 items-center border-b border-gray-50/90 bg-gray-50 px-6 dark:border-none dark:border-black/10 dark:bg-black/95 sm:px-12 lg:hidden">
<Sheet>
<SheetTrigger asChild>
<button className="mt-1 p-0.5 text-muted-foreground lg:hidden">
@@ -41,12 +46,12 @@ export default function Sidebar() {
</SheetTrigger>
<SheetContent
side="left"
className="w-[280px] sm:w-[300px] lg:hidden p-0 m-0"
className="m-0 w-[280px] p-0 sm:w-[300px] lg:hidden"
>
<SidebarComponent className="flex" />
</SheetContent>
</Sheet>
<div className="flex flex-1 gap-x-4 self-stretch items-center lg:gap-x-6 justify-end">
<div className="flex flex-1 items-center justify-end gap-x-4 self-stretch lg:gap-x-6">
<ProfileMenu size="small" className="mr-3 mt-1.5" />
</div>
</div>
@@ -138,17 +143,17 @@ export const SidebarComponent = ({ className }: { className?: string }) => {
<div>
<aside
className={cn(
"w-full h-screen lg:w-72 flex-shrink-0 flex-col justify-between gap-y-6 bg-gray-50 dark:bg-black px-4 lg:px-6 pt-4 lg:pt-6",
"h-screen w-full flex-shrink-0 flex-col justify-between gap-y-6 bg-gray-50 px-4 pt-4 dark:bg-black lg:w-72 lg:px-6 lg:pt-6",
className,
)}
>
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex h-16 shrink-0 items-center space-x-3">
<p className="text-2xl font-bold text-black dark:text-white tracking-tighter flex items-center">
<p className="flex items-center text-2xl font-bold tracking-tighter text-black dark:text-white">
Papermark{" "}
{userPlan && userPlan != "free" ? (
<span className="bg-background text-foreground ring-1 ring-gray-800 tracking-normal rounded-full px-2.5 py-1 text-xs ml-4">
<span className="ml-4 rounded-full bg-background px-2.5 py-1 text-xs tracking-normal text-foreground ring-1 ring-gray-800">
{userPlan.charAt(0).toUpperCase() + userPlan.slice(1)}
</span>
) : null}
@@ -195,9 +200,9 @@ export const SidebarComponent = ({ className }: { className?: string }) => {
disabled={item.disabled}
className={cn(
item.current
? "bg-gray-200 dark:bg-secondary text-foreground font-semibold"
: " hover:bg-gray-200 hover:dark:bg-muted duration-200",
"group flex gap-x-2 items-center rounded-md px-3 py-2 text-sm leading-6 w-full disabled:hover:bg-transparent disabled:text-muted-foreground disabled:cursor-default",
? "bg-gray-200 font-semibold text-foreground dark:bg-secondary"
: " duration-200 hover:bg-gray-200 hover:dark:bg-muted",
"group flex w-full items-center gap-x-2 rounded-md px-3 py-2 text-sm leading-6 disabled:cursor-default disabled:text-muted-foreground disabled:hover:bg-transparent",
)}
>
<item.icon
@@ -222,7 +227,7 @@ export const SidebarComponent = ({ className }: { className?: string }) => {
clickedPlan={"Business"}
trigger={"datarooms"}
>
<div className="group flex gap-x-2 items-center rounded-md px-3 py-2 text-sm leading-6 w-full hover:bg-transparent text-muted-foreground">
<div className="group flex w-full items-center gap-x-2 rounded-md px-3 py-2 text-sm leading-6 text-muted-foreground hover:bg-transparent">
<item.icon
className="h-5 w-5 shrink-0"
aria-hidden="true"
@@ -239,9 +244,9 @@ export const SidebarComponent = ({ className }: { className?: string }) => {
disabled={item.disabled}
className={cn(
item.current
? "bg-gray-200 dark:bg-secondary text-foreground font-semibold"
: " hover:bg-gray-200 hover:dark:bg-muted duration-200",
"group flex gap-x-2 items-center rounded-md px-3 py-2 text-sm leading-6 w-full disabled:hover:bg-transparent disabled:text-muted-foreground disabled:cursor-default",
? "bg-gray-200 font-semibold text-foreground dark:bg-secondary"
: " duration-200 hover:bg-gray-200 hover:dark:bg-muted",
"group flex w-full items-center gap-x-2 rounded-md px-3 py-2 text-sm leading-6 disabled:cursor-default disabled:text-muted-foreground disabled:hover:bg-transparent",
)}
>
<item.icon
@@ -271,7 +276,7 @@ export const SidebarComponent = ({ className }: { className?: string }) => {
<ProBanner setShowProBanner={setShowProBanner} />
) : null}
<div className="w-full hidden lg:block">
<div className="hidden w-full lg:block">
<ProfileMenu size="large" />
</div>
</div>

View File

@@ -1,9 +1,12 @@
import Link from "next/link";
import { Button } from "./ui/button";
import { calculateDaysLeft } from "@/lib/utils";
import { CustomUser } from "@/lib/types";
import { Session } from "next-auth";
import { useDomains } from "@/lib/swr/use-domains";
import { CustomUser } from "@/lib/types";
import { calculateDaysLeft } from "@/lib/utils";
import { Button } from "./ui/button";
const cutoffDate = new Date("2023-10-12T00:00:00.000Z");
@@ -21,9 +24,9 @@ export default function Banner({ session }: { session: Session | null }) {
domains && !noDomains && domains.every((domain) => domain.verified);
return (
<aside className="flex flex-col justify-center w-full bg-background text-foreground p-4 mb-2 rounded-lg border border-gray-700">
<aside className="mb-2 flex w-full flex-col justify-center rounded-lg border border-gray-700 bg-background p-4 text-foreground">
<div className="flex space-x-2">
<span className="font-bold text-sm"> Pro Trial </span>
<span className="text-sm font-bold"> Pro Trial </span>
</div>
<p className="my-4 text-sm">
{`You are on the Pro trial for the next ${userDaysLeft} days.`}

View File

@@ -1,11 +1,15 @@
import Cookies from "js-cookie";
import { Dispatch, SetStateAction } from "react";
import { UpgradePlanModal } from "./upgrade-plan-modal";
import { Button } from "@/components/ui/button";
import Cookies from "js-cookie";
import { usePlausible } from "next-plausible";
import X from "@/components/shared/icons/x";
import { Button } from "@/components/ui/button";
import { useAnalytics } from "@/lib/analytics";
import { UpgradePlanModal } from "./upgrade-plan-modal";
export default function ProBanner({
setShowProBanner,
}: {
@@ -23,17 +27,17 @@ export default function ProBanner({
};
return (
<aside className="flex flex-col justify-center w-full bg-background text-foreground p-4 mb-2 rounded-lg border border-gray-700 relative">
<aside className="relative mb-2 flex w-full flex-col justify-center rounded-lg border border-gray-700 bg-background p-4 text-foreground">
<button
type="button"
onClick={handleHideBanner}
className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
>
<X className="w-4 h-4" />
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</button>
<div className="flex space-x-2">
<span className="font-bold text-sm"> Papermark Pro </span>
<span className="text-sm font-bold"> Papermark Pro </span>
</div>
<p className="my-4 text-sm">
Join the Papermark Pro plan to unlock custom domains, team members, and

View File

@@ -1,18 +1,22 @@
import { useEffect, useMemo, useState } from "react";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { motion } from "framer-motion";
import { STAGGER_CHILD_VARIANTS } from "@/lib/constants";
import { capitalize } from "@/lib/utils";
import { PLANS } from "@/lib/stripe/utils";
import { getStripe } from "@/lib/stripe/client";
import { Badge } from "../ui/badge";
import { useTeam } from "@/context/team-context";
import { useAnalytics } from "@/lib/analytics";
import React from "react";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useTeam } from "@/context/team-context";
import { motion } from "framer-motion";
import { CheckIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useAnalytics } from "@/lib/analytics";
import { STAGGER_CHILD_VARIANTS } from "@/lib/constants";
import { getStripe } from "@/lib/stripe/client";
import { PLANS } from "@/lib/stripe/utils";
import { capitalize } from "@/lib/utils";
import { DataroomTrialModal } from "../datarooms/dataroom-trial-modal";
import { Badge } from "../ui/badge";
export function UpgradePlanModal({
clickedPlan,
@@ -111,7 +115,7 @@ export function UpgradePlanModal({
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>{buttonChild}</DialogTrigger>
<DialogContent className="text-foreground bg-background">
<DialogContent className="bg-background text-foreground">
<motion.div
variants={{
show: {
@@ -180,7 +184,7 @@ export function UpgradePlanModal({
PLANS.find((p) => p.name === plan)!.price[period].amount
}/month`}{" "}
{period === "yearly" ? (
<span className="text-xs ml-1">(billed yearly)</span>
<span className="ml-1 text-xs">(billed yearly)</span>
) : null}
</Badge>
</div>
@@ -258,7 +262,7 @@ export function UpgradePlanModal({
{plan === "Business" ? (
<DataroomTrialModal>
<button
className="text-center text-xs text-muted-foreground underline-offset-4 transition-all hover:text-gray-800 hover:dark:text-muted-foreground/80 hover:underline"
className="text-center text-xs text-muted-foreground underline-offset-4 transition-all hover:text-gray-800 hover:underline hover:dark:text-muted-foreground/80"
onClick={() => analytics.capture("Dataroom Trial Clicked")}
>
Looking for a dataroom trial?
@@ -268,7 +272,7 @@ export function UpgradePlanModal({
<a
href="https://cal.com/marcseitz/papermark"
target="_blank"
className="text-center text-xs text-muted-foreground underline-offset-4 transition-all hover:text-gray-800 hover:dark:text-muted-foreground/80 hover:underline"
className="text-center text-xs text-muted-foreground underline-offset-4 transition-all hover:text-gray-800 hover:underline hover:dark:text-muted-foreground/80"
>
Looking for Papermark Enterprise?
</a>

View File

@@ -1,6 +1,7 @@
"use client";
import Image, { ImageProps } from "next/image";
import { useEffect, useState } from "react";
export default function BlurImage(props: ImageProps) {

View File

@@ -1,7 +1,9 @@
import { getColorForVersion, timeFormatter } from "./utils";
import { useDocumentThumbnail } from "@/lib/swr/use-document";
import { useRouter } from "next/router";
import { useDocumentThumbnail } from "@/lib/swr/use-document";
import { getColorForVersion, timeFormatter } from "./utils";
const CustomTooltip = ({
payload,
active,
@@ -23,9 +25,9 @@ const CustomTooltip = ({
return (
<>
<div className="bg-tremor-background dark:bg-dark-tremor-background border border-tremor-border dark:border-dark-tremor-border rounded-md w-52 text-sm leading-6">
<div className="py-2 px-2.5 bg-tremor-background dark:bg-dark-tremor-background border-b border-tremor-border dark:border-dark-tremor-border rounded-t-md">
<p className="text-tremor-content dark:text-dark-tremor-content font-medium">
<div className="w-52 rounded-md border border-tremor-border bg-tremor-background text-sm leading-6 dark:border-dark-tremor-border dark:bg-dark-tremor-background">
<div className="rounded-t-md border-b border-tremor-border bg-tremor-background px-2.5 py-2 dark:border-dark-tremor-border dark:bg-dark-tremor-background">
<p className="font-medium text-tremor-content dark:text-dark-tremor-content">
Page {payload[0].payload.pageNumber}
</p>
{imageUrl ? (
@@ -37,19 +39,19 @@ const CustomTooltip = ({
</div>
{payload.map((item: any, idx: number) => (
<div
className="py-2 px-2.5 justify-between items-center w-full flex space-x-4"
className="flex w-full items-center justify-between space-x-4 px-2.5 py-2"
key={idx}
>
<div className="whitespace-nowrap overflow-hidden text-overflow-ellipsis items-center flex space-x-2">
<div className="text-overflow-ellipsis flex items-center space-x-2 overflow-hidden whitespace-nowrap">
<span
className={`bg-${getColorForVersion(item.dataKey)}-500 rounded-full flex-shrink-0 w-2.5 h-2.5`}
className={`bg-${getColorForVersion(item.dataKey)}-500 h-2.5 w-2.5 flex-shrink-0 rounded-full`}
aria-hidden="true"
></span>
<p className="text-tremor-content dark:text-dark-tremor-content whitespace-nowrap overflow-hidden text-overflow-ellipsis">
<p className="text-overflow-ellipsis overflow-hidden whitespace-nowrap text-tremor-content dark:text-dark-tremor-content">
{item.dataKey}
</p>
</div>
<p className="text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis font-medium">
<p className="font-medium text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis">
{timeFormatter(item.value)}
</p>
</div>

View File

@@ -1,5 +1,8 @@
import { BarChart } from "@tremor/react";
import { useState } from "react";
import { BarChart } from "@tremor/react";
import CustomTooltip from "./bar-chart-tooltip";
import {
type Data,
type SumData,
@@ -7,7 +10,6 @@ import {
getColors,
timeFormatter,
} from "./utils";
import CustomTooltip from "./bar-chart-tooltip";
const renameDummyDurationKey = (data: Data[]): TransformedData[] => {
return data.reduce((acc, { pageNumber, data }) => {

View File

@@ -1,10 +1,13 @@
import { useEffect, useRef } from "react";
import { AssistantStatus, type Message } from "ai/react";
import Textarea from "react-textarea-autosize";
import { Button } from "@/components/ui/button";
import Textarea from "react-textarea-autosize";
import { useEffect, useRef } from "react";
import { cn } from "@/lib/utils";
import { useEnterSubmit } from "@/lib/utils/use-enter-submit";
import ArrowUp from "../shared/icons/arrow-up";
export function ChatInput({
@@ -37,14 +40,14 @@ export function ChatInput({
<div className="mx-auto sm:max-w-3xl sm:px-4">
<div className="space-y-4 bg-background px-4 py-4 md:py-4">
<form onSubmit={submitMessage} ref={formRef}>
<div className="relative flex max-h-60 w-full flex-col overflow-hidden bg-background pr-8 rounded-xl ring-1 ring-muted-foreground/50 sm:pr-12 focus-within:ring-1 focus-within:ring-foreground">
<div className="relative flex max-h-60 w-full flex-col overflow-hidden rounded-xl bg-background pr-8 ring-1 ring-muted-foreground/50 focus-within:ring-1 focus-within:ring-foreground sm:pr-12">
<Textarea
ref={inputRef}
tabIndex={0}
rows={1}
onKeyDown={onKeyDown}
disabled={status !== "awaiting_message"}
className="min-h-[60px] w-full resize-none bg-transparent px-4 py-[1.3rem] focus:ring-0 sm:text-sm border-none"
className="min-h-[60px] w-full resize-none border-none bg-transparent px-4 py-[1.3rem] focus:ring-0 sm:text-sm"
value={input}
placeholder="Message Papermark Assistant..."
onChange={handleInputChange}
@@ -55,7 +58,7 @@ export function ChatInput({
type="submit"
disabled={status === "in_progress" || input === ""}
title="Send message"
className="rounded-md p-1 md:p-2 h-10 w-10"
className="h-10 w-10 rounded-md p-1 md:p-2"
>
<ArrowUp className="h-full w-full" />
<span className="sr-only">Send message</span>

View File

@@ -1,9 +1,10 @@
import { type Message } from "ai";
import { Separator } from "@/components/ui/separator";
import { ChatMessage } from "./chat-message";
import Skeleton from "../Skeleton";
import PapermarkSparkle from "../shared/icons/papermark-sparkle";
import { ChatMessage } from "./chat-message";
export interface ChatList {
messages: Message[];
@@ -30,13 +31,13 @@ export function ChatList({ messages, status }: ChatList) {
<Separator className="my-4 bg-background" />
<div
key={"loading-message"}
className="group relative mb-4 flex items-start ml-5 whitespace-pre-wrap"
className="group relative mb-4 ml-5 flex items-start whitespace-pre-wrap"
>
<div className="flex h-8 w-8 shrink-0 select-none items-center justify-center rounded-md border shadow bg-primary text-primary-foreground">
<div className="flex h-8 w-8 shrink-0 select-none items-center justify-center rounded-md border bg-primary text-primary-foreground shadow">
<PapermarkSparkle />
</div>
<div className="flex-1 px-1 ml-4 space-y-2 overflow-hidden">
<div className="font-semibold select-none">
<div className="ml-4 flex-1 space-y-2 overflow-hidden px-1">
<div className="select-none font-semibold">
Papermark Assistant
</div>
<Skeleton className="h-4 w-64" />

View File

@@ -3,8 +3,10 @@
import { type Message } from "ai";
import { Button } from "@/components/ui/button";
import { useCopyToClipboard } from "@/lib/utils/use-copy-to-clipboard";
import { cn } from "@/lib/utils";
import { useCopyToClipboard } from "@/lib/utils/use-copy-to-clipboard";
import Check from "../shared/icons/check";
import Copy from "../shared/icons/copy";
@@ -27,7 +29,7 @@ export function ChatMessageActions({
return (
<div
className={cn(
"flex items-center justify-end md:hidden md:absolute md:right-0 md:-top-2",
"flex items-center justify-end md:absolute md:-top-2 md:right-0 md:hidden",
className,
)}
{...props}

View File

@@ -1,10 +1,11 @@
import { type Message } from "ai";
import { cn } from "@/lib/utils";
import { ChatMessageActions } from "./chat-message-actions";
import UserRound from "../shared/icons/user-round";
import PapermarkSparkle from "../shared/icons/papermark-sparkle";
import AlertCircle from "../shared/icons/alert-circle";
import PapermarkSparkle from "../shared/icons/papermark-sparkle";
import UserRound from "../shared/icons/user-round";
import { ChatMessageActions } from "./chat-message-actions";
// map role to icon and name
const mapMessageRole = {
@@ -25,7 +26,7 @@ export function ChatMessage({ message, ...props }: ChatMessageProps) {
<div
key={message.id}
className={cn(
"group relative mb-4 flex items-start md:ml-5 whitespace-pre-wrap",
"group relative mb-4 flex items-start whitespace-pre-wrap md:ml-5",
)}
{...props}
>
@@ -41,12 +42,12 @@ export function ChatMessage({ message, ...props }: ChatMessageProps) {
>
{mapMessageRole[message.role].icon}
</div>
<div className="flex-1 px-1 ml-4 space-y-2 overflow-hidden">
<div className="relative flex w-[calc(100%-50px)] flex-col group">
<div className="font-semibold select-none">
<div className="ml-4 flex-1 space-y-2 overflow-hidden px-1">
<div className="group relative flex w-[calc(100%-50px)] flex-col">
<div className="select-none font-semibold">
{mapMessageRole[message.role].name}
</div>
<div className="prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 font-light">
<div className="prose break-words font-light dark:prose-invert prose-p:leading-relaxed prose-pre:p-0">
<p className="mb-2 last:mb-0">{message.content}</p>
</div>
</div>

View File

@@ -1,6 +1,7 @@
"use client";
import * as React from "react";
import { useInView } from "react-intersection-observer";
import { useAtBottom } from "@/lib/utils/use-at-bottom";

View File

@@ -1,18 +1,20 @@
"use client";
import {
experimental_useAssistant as useAssistant,
type Message,
} from "ai/react";
import { useEffect, useState } from "react";
import {
type Message,
experimental_useAssistant as useAssistant,
} from "ai/react";
import { nanoid } from "nanoid";
import { BasePlan } from "@/lib/swr/use-billing";
import { cn } from "@/lib/utils";
import { ChatList } from "./chat-list";
import { ChatInput } from "./chat-input";
import { ChatList } from "./chat-list";
import { ChatScrollAnchor } from "./chat-scroll-anchor";
import { EmptyScreen } from "./empty-screen";
import { useEffect, useState } from "react";
import { nanoid } from "nanoid";
import { BasePlan } from "@/lib/swr/use-billing";
export interface ChatProps extends React.ComponentProps<"div"> {
initialMessages: Message[];
@@ -93,7 +95,7 @@ export function Chat({
<>
<div
className={cn(
"pb-[20px] pt-24 h-[calc(100vh-96px)] relative overflow-y-auto",
"relative h-[calc(100vh-96px)] overflow-y-auto pb-[20px] pt-24",
className,
)}
>

View File

@@ -1,5 +1,7 @@
import { Button } from "@/components/ui/button";
import Image from "next/image";
import { Button } from "@/components/ui/button";
import Sparkle from "../shared/icons/sparkle";
const exampleMessages = [
@@ -43,7 +45,7 @@ export function EmptyScreen({
{firstPage ? (
firstPage.includes("cloudfront.net") ? (
<img
className="object-contain rounded-md ring-1 ring-gray-700"
className="rounded-md object-contain ring-1 ring-gray-700"
src={firstPage}
alt={`Page 1`}
fetchPriority="high"
@@ -53,13 +55,13 @@ export function EmptyScreen({
src={firstPage}
width={768}
height={100}
className="object-contain rounded-md ring-1 ring-gray-700"
className="rounded-md object-contain ring-1 ring-gray-700"
alt="First page of the document"
/>
)
) : (
<div className="flex items-center justify-center rounded-md w-full">
<p className="text-2xl text-center">
<div className="flex w-full items-center justify-center rounded-md">
<p className="text-center text-2xl">
Chat with{" "}
<span className="text-2xl font-bold tracking-tighter ">
Papermark
@@ -70,13 +72,13 @@ export function EmptyScreen({
)}
</div>
<div className="flex justify-center text-lg mt-4">
<div className="mt-4 flex justify-center text-lg">
What would you like to know?
</div>
</div>
<div className="mx-auto max-w-2xl px-4 absolute bottom-0 inset-x-0">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
<div className="absolute inset-x-0 bottom-0 mx-auto max-w-2xl px-4">
<div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
{exampleMessages.map((message, index) => (
<Button
key={index}

View File

@@ -1,3 +1,12 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { toast } from "sonner";
import { mutate } from "swr";
import { SidebarFolderTreeSelection } from "@/components/sidebar-folders";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -7,12 +16,6 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { mutate } from "swr";
import { SidebarFolderTreeSelection } from "@/components/sidebar-folders";
import { useRouter } from "next/router";
export function AddDataroomDocumentModal({
open,
@@ -105,7 +108,7 @@ export function AddDataroomDocumentModal({
<DialogFooter>
<Button
onClick={handleSubmit}
className="w-full h-9"
className="h-9 w-full"
loading={loading}
>
Add to dataroom

View File

@@ -1,3 +1,9 @@
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { toast } from "sonner";
import { mutate } from "swr";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -10,13 +16,11 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
import { usePlan } from "@/lib/swr/use-billing";
import { useAnalytics } from "@/lib/analytics";
import { mutate } from "swr";
import { usePlan } from "@/lib/swr/use-billing";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
export function AddDataroomModal({ children }: { children?: React.ReactNode }) {
const [dataroomName, setDataroomName] = useState<string>("");
@@ -101,11 +105,11 @@ export function AddDataroomModal({ children }: { children?: React.ReactNode }) {
<Input
id="dataroom-name"
placeholder="ACME Aquisition"
className="w-full mt-1 mb-4"
className="mb-4 mt-1 w-full"
onChange={(e) => setDataroomName(e.target.value)}
/>
<DialogFooter>
<Button type="submit" className="w-full h-9" loading={loading}>
<Button type="submit" className="h-9 w-full" loading={loading}>
Add new dataroom
</Button>
</DialogFooter>

View File

@@ -1,3 +1,11 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { toast } from "sonner";
import { mutate } from "swr";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -10,12 +18,8 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTeam } from "@/context/team-context";
import { useAnalytics } from "@/lib/analytics";
import { useRouter } from "next/router";
import { useState } from "react";
import { toast } from "sonner";
import { mutate } from "swr";
export function AddViewerModal({
dataroomId,
@@ -170,7 +174,7 @@ export function AddViewerModal({
{emails.map((email, index) => (
<div
key={index}
className="flex items-center gap-2 bg-gray-100 px-2 py-1 rounded"
className="flex items-center gap-2 rounded bg-gray-100 px-2 py-1"
>
{email}
<button type="button" onClick={() => removeEmail(index)}>
@@ -195,7 +199,7 @@ export function AddViewerModal({
</div>
<DialogFooter>
<Button type="submit" className="w-full h-9 mt-8" loading={loading}>
<Button type="submit" className="mt-8 h-9 w-full" loading={loading}>
{loading ? "Sending emails..." : "Add members"}
</Button>
</DialogFooter>

View File

@@ -1,5 +1,8 @@
import React, { useMemo } from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import React, { useMemo } from "react";
import {
Breadcrumb,
BreadcrumbItem,
@@ -8,7 +11,7 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { useRouter } from "next/router";
import { useDataroomFolderWithParents } from "@/lib/swr/use-dataroom";
function BreadcrumbComponentBase({

View File

@@ -1,11 +1,19 @@
import { nFormatter, timeAgo } from "@/lib/utils";
import Link from "next/link";
import { type DocumentWithLinksAndLinkCountAndViewCount } from "@/lib/types";
import { TeamContextType } from "@/context/team-context";
import BarChart from "@/components/shared/icons/bar-chart";
import Image from "next/image";
import NotionIcon from "@/components/shared/icons/notion";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { TeamContextType } from "@/context/team-context";
import { FolderInputIcon, MoreVertical, TrashIcon } from "lucide-react";
import { useTheme } from "next-themes";
import { toast } from "sonner";
import { mutate } from "swr";
import { MoveToFolderModal } from "@/components/documents/move-folder-modal";
import BarChart from "@/components/shared/icons/bar-chart";
import Check from "@/components/shared/icons/check";
import Copy from "@/components/shared/icons/copy";
import NotionIcon from "@/components/shared/icons/notion";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
@@ -15,15 +23,12 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { TrashIcon, MoreVertical, FolderInputIcon } from "lucide-react";
import { mutate } from "swr";
import { useCopyToClipboard } from "@/lib/utils/use-copy-to-clipboard";
import Check from "@/components/shared/icons/check";
import Copy from "@/components/shared/icons/copy";
import { useEffect, useRef, useState } from "react";
import { useTheme } from "next-themes";
import { MoveToFolderModal } from "@/components/documents/move-folder-modal";
import { type DataroomFolderDocument } from "@/lib/swr/use-dataroom";
import { type DocumentWithLinksAndLinkCountAndViewCount } from "@/lib/types";
import { nFormatter, timeAgo } from "@/lib/utils";
import { useCopyToClipboard } from "@/lib/utils/use-copy-to-clipboard";
import { MoveToDataroomFolderModal } from "./move-dataroom-folder-modal";
type DocumentsCardProps = {
@@ -46,11 +51,11 @@ export default function DataroomDocumentCard({
return (
<>
<li className="group/row relative rounded-lg p-3 border-0 dark:bg-secondary ring-1 ring-gray-200 dark:ring-gray-700 transition-all hover:ring-gray-300 hover:dark:ring-gray-500 hover:bg-secondary sm:p-4 flex justify-between items-center">
<div className="min-w-0 flex shrink items-center space-x-2 sm:space-x-4">
<div className="w-8 mx-0.5 sm:mx-1 text-center flex justify-center items-center">
<li className="group/row relative flex items-center justify-between rounded-lg border-0 p-3 ring-1 ring-gray-200 transition-all hover:bg-secondary hover:ring-gray-300 dark:bg-secondary dark:ring-gray-700 hover:dark:ring-gray-500 sm:p-4">
<div className="flex min-w-0 shrink items-center space-x-2 sm:space-x-4">
<div className="mx-0.5 flex w-8 items-center justify-center text-center sm:mx-1">
{document.document.type === "notion" ? (
<NotionIcon className="w-8 h-8" />
<NotionIcon className="h-8 w-8" />
) : (
<Image
src={`/_icons/${document.document.type}${isLight ? "-light" : ""}.svg`}
@@ -63,10 +68,10 @@ export default function DataroomDocumentCard({
<div className="flex-col">
<div className="flex items-center">
<h2 className="min-w-0 text-sm font-semibold leading-6 text-foreground truncate max-w-[150px] sm:max-w-md">
<h2 className="min-w-0 max-w-[150px] truncate text-sm font-semibold leading-6 text-foreground sm:max-w-md">
<Link
href={`/documents/${document.document.id}`}
className="truncate w-full"
className="w-full truncate"
>
<span>{document.document.name}</span>
<span className="absolute inset-0" />
@@ -91,10 +96,10 @@ export default function DataroomDocumentCard({
e.stopPropagation();
}}
href={`/documents/${document.document.id}`}
className="flex items-center z-10 space-x-1 rounded-md bg-gray-200 dark:bg-gray-700 px-1.5 sm:px-2 py-0.5 transition-all duration-75 hover:scale-105 active:scale-100"
className="z-10 flex items-center space-x-1 rounded-md bg-gray-200 px-1.5 py-0.5 transition-all duration-75 hover:scale-105 active:scale-100 dark:bg-gray-700 sm:px-2"
>
<BarChart className="h-3 sm:h-4 w-3 sm:w-4 text-muted-foreground" />
<p className="whitespace-nowrap text-xs sm:text-sm text-muted-foreground">
<BarChart className="h-3 w-3 text-muted-foreground sm:h-4 sm:w-4" />
<p className="whitespace-nowrap text-xs text-muted-foreground sm:text-sm">
{nFormatter(document.document._count.views)}
<span className="ml-1 hidden sm:inline-block">views</span>
</p>
@@ -105,16 +110,16 @@ export default function DataroomDocumentCard({
<Button
// size="icon"
variant="outline"
className="h-8 lg:h-9 w-8 lg:w-9 p-0 z-10 bg-transparent border-gray-200 dark:border-gray-700 hover:bg-gray-200 hover:dark:bg-gray-700"
className="z-10 h-8 w-8 border-gray-200 bg-transparent p-0 hover:bg-gray-200 dark:border-gray-700 hover:dark:bg-gray-700 lg:h-9 lg:w-9"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="w-4 h-4" />
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" ref={dropdownRef}>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem onClick={() => setMoveFolderOpen(true)}>
<FolderInputIcon className="w-4 h-4 mr-2" />
<FolderInputIcon className="mr-2 h-4 w-4" />
Move to folder
</DropdownMenuItem>
<DropdownMenuSeparator />

View File

@@ -15,9 +15,9 @@ export const DataroomHeader = ({
}
return (
<section className="flex items-center justify-between mb-4 md:mb-8 lg:mb-12">
<section className="mb-4 flex items-center justify-between md:mb-8 lg:mb-12">
<div className="space-y-1">
<h1 className="text-xl sm:text-2xl text-foreground font-semibold tracking-tight">
<h1 className="text-xl font-semibold tracking-tight text-foreground sm:text-2xl">
{title}
</h1>
{/* <p className="text-xs sm:text-sm text-muted-foreground font-mono">
@@ -28,7 +28,7 @@ export const DataroomHeader = ({
{actionRows.map((row, i) => (
<ul
key={i.toString()}
className="flex flex-wrap items-center justify-end gap-2 md:gap-4 md:flex-nowrap"
className="flex flex-wrap items-center justify-end gap-2 md:flex-nowrap md:gap-4"
>
{row.map((action, i) => (
<li key={i}>{action}</li>

View File

@@ -1,3 +1,12 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { E164Number } from "libphonenumber-js/types.cjs";
import { toast } from "sonner";
import { mutate } from "swr";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -10,12 +19,11 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
import { useAnalytics } from "@/lib/analytics";
import { mutate } from "swr";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
import { PhoneInput } from "../ui/phone-input";
import {
Select,
SelectContent,
@@ -23,9 +31,6 @@ import {
SelectTrigger,
SelectValue,
} from "../ui/select";
import { PhoneInput } from "../ui/phone-input";
import { E164Number } from "libphonenumber-js/types.cjs";
import { useRouter } from "next/router";
export function DataroomTrialModal({
children,
@@ -120,7 +125,7 @@ export function DataroomTrialModal({
autoComplete="off"
data-1p-ignore
placeholder="John Doe"
className="w-full mt-1 mb-4"
className="mb-4 mt-1 w-full"
onChange={(e) => setName(e.target.value)}
/>
</div>
@@ -134,7 +139,7 @@ export function DataroomTrialModal({
autoComplete="off"
data-1p-ignore
placeholder="ACME Inc."
className="w-full mt-1 mb-4"
className="mb-4 mt-1 w-full"
onChange={(e) => setCompanyName(e.target.value)}
/>
</div>
@@ -202,7 +207,7 @@ export function DataroomTrialModal({
<div className="flex flex-col space-y-4">
<Button
type="submit"
className="w-full h-9"
className="h-9 w-full"
disabled={
!phoneNumber ||
!companySize ||

View File

@@ -1,5 +1,5 @@
import { SidebarFolderTree } from "./sidebar-tree";
import { SidebarFolderTreeSelection } from "./selection-tree";
import { SidebarFolderTree } from "./sidebar-tree";
import { ViewFolderTree } from "./view-tree";
export { SidebarFolderTree, SidebarFolderTreeSelection, ViewFolderTree };

View File

@@ -1,11 +1,14 @@
import { FileTree } from "@/components/ui/nextra-filetree";
import { memo, useMemo } from "react";
import { buildNestedFolderStructure } from "./utils";
import { FileTree } from "@/components/ui/nextra-filetree";
import {
DataroomFolderWithDocuments,
useDataroomFoldersTree,
} from "@/lib/swr/use-dataroom";
import { buildNestedFolderStructure } from "./utils";
const FolderComponentSelection = memo(
({
folder,

View File

@@ -1,12 +1,16 @@
import { useRouter } from "next/router";
import { FileTree } from "@/components/ui/nextra-filetree";
import { memo, useMemo } from "react";
import { buildNestedFolderStructure } from "./utils";
import { FileTree } from "@/components/ui/nextra-filetree";
import {
DataroomFolderWithDocuments,
useDataroomFoldersTree,
} from "@/lib/swr/use-dataroom";
import { buildNestedFolderStructure } from "./utils";
const FolderComponent = memo(
({
dataroomId,

View File

@@ -1,6 +1,7 @@
import { DataroomFolderWithDocuments } from "@/lib/swr/use-dataroom";
import { DataroomDocument, DataroomFolder } from "@prisma/client";
import { DataroomFolderWithDocuments } from "@/lib/swr/use-dataroom";
// Helper function to build nested folder structure
export const buildNestedFolderStructure = (
folders: DataroomFolderWithDocuments[],

View File

@@ -1,9 +1,13 @@
import { useRouter } from "next/router";
import { FileTree } from "@/components/ui/nextra-filetree";
import { memo, useMemo } from "react";
import { buildNestedFolderStructureWithDocs } from "./utils";
import { DataroomDocument, DataroomFolder } from "@prisma/client";
import { FileTree } from "@/components/ui/nextra-filetree";
import { buildNestedFolderStructureWithDocs } from "./utils";
type DataroomDocumentWithVersion = {
dataroomDocumentId: string;
folderId: string | null;

View File

@@ -1,3 +1,12 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { toast } from "sonner";
import { mutate } from "swr";
import { SidebarFolderTreeSelection } from "@/components/datarooms/folders";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -7,12 +16,6 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { mutate } from "swr";
import { SidebarFolderTreeSelection } from "@/components/datarooms/folders";
import { useRouter } from "next/router";
export function MoveToDataroomFolderModal({
open,
@@ -112,7 +115,7 @@ export function MoveToDataroomFolderModal({
</div>
<DialogFooter>
<Button onClick={handleSubmit} className="w-full h-9">
<Button onClick={handleSubmit} className="h-9 w-full">
Move to folder
</Button>
</DialogFooter>

View File

@@ -1,6 +1,8 @@
import ErrorPage from "next/error";
import StatsElement from "@/components/documents/stats-element";
import { Skeleton } from "@/components/ui/skeleton";
import { useDataroomStats } from "@/lib/swr/use-dataroom-stats";
export default function StatsCard() {
@@ -12,10 +14,10 @@ export default function StatsCard() {
if (loading) {
return (
<div className="grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3 border-foreground/5 space-y-2 sm:space-y-0 sm:space-x-2 lg:space-x-3">
<div className="grid grid-cols-1 space-y-2 border-foreground/5 sm:grid-cols-3 sm:space-x-2 sm:space-y-0 lg:grid-cols-3 lg:space-x-3">
{Array.from({ length: 3 }).map((_, i) => (
<div
className="border border-foreground/5 py-6 px-4 sm:px-6 lg:px-8 rounded-lg"
className="rounded-lg border border-foreground/5 px-4 py-6 sm:px-6 lg:px-8"
key={i}
>
<Skeleton className="h-6 w-[80%] rounded-sm" />
@@ -55,7 +57,7 @@ export default function StatsCard() {
];
return stats && stats.dataroomViews.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3 border-foreground/5 space-y-2 sm:space-y-0 sm:space-x-2 lg:space-x-3">
<div className="grid grid-cols-1 space-y-2 border-foreground/5 sm:grid-cols-3 sm:space-x-2 sm:space-y-0 lg:grid-cols-3 lg:space-x-3">
{statistics.map((stat, statIdx) => (
<StatsElement key={statIdx} stat={stat} statIdx={statIdx} />
))}

View File

@@ -1,35 +1,36 @@
import { useMemo, useState } from "react";
import { useDropzone } from "react-dropzone";
import { bytesToSize } from "@/lib/utils";
import { toast } from "sonner";
import { useTeam } from "@/context/team-context";
import {
Upload as ArrowUpTrayIcon,
File as DocumentIcon,
FileText as DocumentTextIcon,
Presentation as PresentationChartBarIcon,
Image as PhotoIcon,
Presentation as PresentationChartBarIcon,
} from "lucide-react";
import { useTeam } from "@/context/team-context";
import { useDropzone } from "react-dropzone";
import { toast } from "sonner";
import { usePlan } from "@/lib/swr/use-billing";
import { bytesToSize } from "@/lib/utils";
import { getPagesCount } from "@/lib/utils/get-page-number-count";
function fileIcon(fileType: string) {
switch (fileType) {
case "application/pdf":
return <DocumentTextIcon className="h-6 w-6 mx-auto" />;
return <DocumentTextIcon className="mx-auto h-6 w-6" />;
case "image/png":
case "image/jpeg":
case "image/gif":
case "image/jpg":
return <PhotoIcon className="h-6 w-6 mx-auto" />;
return <PhotoIcon className="mx-auto h-6 w-6" />;
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
case "application/vnd.ms-powerpoint":
case "application/msword":
return <PresentationChartBarIcon className="h-6 w-6 mx-auto" />;
return <PresentationChartBarIcon className="mx-auto h-6 w-6" />;
default:
return <DocumentIcon className="h-6 w-6 mx-auto" />;
return <DocumentIcon className="mx-auto h-6 w-6" />;
}
}
@@ -89,13 +90,13 @@ export default function DocumentUpload({
<div className="col-span-full">
<div
{...getRootProps()}
className="relative cursor-pointer font-semibold text-foreground hover:text-gray-900 hover:bg-gray-100 hover:dark:text-gray-500 hover:dark:bg-gray-900 block group"
className="group relative block cursor-pointer font-semibold text-foreground hover:bg-gray-100 hover:text-gray-900 hover:dark:bg-gray-900 hover:dark:text-gray-500"
>
<input {...getInputProps()} name="file" className="sr-only" />
<div className="flex justify-center rounded-lg border border-dashed border-black/25 dark:border-white/25 px-6 py-10 min-h-[200px] md:min-w-full items-center">
<div className="flex min-h-[200px] items-center justify-center rounded-lg border border-dashed border-black/25 px-6 py-10 dark:border-white/25 md:min-w-full">
{currentFile ? (
<div
className="absolute inset-0 opacity-10 pointer-events-none group-hover:opacity-5 transition-opacity"
className="pointer-events-none absolute inset-0 opacity-10 transition-opacity group-hover:opacity-5"
style={{
backgroundImage: `url(${imageBlobUrl})`,
backgroundPosition: "center",
@@ -105,7 +106,7 @@ export default function DocumentUpload({
) : null}
<div className="text-center">
{currentFile ? (
<div className="flex flex-col sm:flex-row items-center space-y-1 sm:space-x-2 text-foreground">
<div className="flex flex-col items-center space-y-1 text-foreground sm:flex-row sm:space-x-2">
<div>{fileIcon(currentFile.type)}</div>
<p>{currentFile.name}</p>
<p className="text-gray-500">{bytesToSize(currentFile.size)}</p>

View File

@@ -1,4 +1,15 @@
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { useRouter } from "next/router";
import { FormEvent, useState } from "react";
import { useTeam } from "@/context/team-context";
import { usePlausible } from "next-plausible";
import { parsePageId } from "notion-utils";
import { toast } from "sonner";
import { mutate } from "swr";
import DocumentUpload from "@/components/document-upload";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
@@ -6,25 +17,18 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { FormEvent, useState } from "react";
import { useRouter } from "next/router";
import DocumentUpload from "@/components/document-upload";
import { copyToClipboard } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { usePlausible } from "next-plausible";
import { toast } from "sonner";
import { useTeam } from "@/context/team-context";
import { parsePageId } from "notion-utils";
import { putFile } from "@/lib/files/put-file";
import { useAnalytics } from "@/lib/analytics";
import {
DocumentData,
createDocument,
createNewDocumentVersion,
} from "@/lib/documents/create-document";
import { useAnalytics } from "@/lib/analytics";
import { mutate } from "swr";
import { putFile } from "@/lib/files/put-file";
import { copyToClipboard } from "@/lib/utils";
export function AddDocumentModal({
newVersion,
@@ -344,7 +348,7 @@ export function AddDocumentModal({
<Dialog open={isOpen} onOpenChange={clearModelStates}>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent
className="text-foreground bg-transparent border-none shadow-none"
className="border-none bg-transparent text-foreground shadow-none"
isDocumentDialog
>
<Tabs defaultValue="document">
@@ -427,7 +431,7 @@ export function AddDocumentModal({
name="notion-link"
id="notion-link"
placeholder="notion.site/..."
className="flex w-full rounded-md border-0 py-1.5 text-foreground bg-background shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 sm:text-sm sm:leading-6"
className="flex w-full rounded-md border-0 bg-background py-1.5 text-foreground shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 sm:text-sm sm:leading-6"
value={notionLink || ""}
onChange={(e) => setNotionLink(e.target.value)}
/>

View File

@@ -1,5 +1,10 @@
import React, { useMemo } from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import React, { useMemo } from "react";
import { useFolderWithParents } from "@/lib/swr/use-folders";
import {
Breadcrumb,
BreadcrumbItem,
@@ -8,8 +13,6 @@ import {
BreadcrumbPage,
BreadcrumbSeparator,
} from "../ui/breadcrumb";
import { useRouter } from "next/router";
import { useFolderWithParents } from "@/lib/swr/use-folders";
function BreadcrumbComponentBase({ name }: { name: string[] }) {
const { folders: folderNames } = useFolderWithParents({ name });

View File

@@ -1,11 +1,18 @@
import { nFormatter, timeAgo } from "@/lib/utils";
import Link from "next/link";
import { DocumentWithLinksAndLinkCountAndViewCount } from "@/lib/types";
import { TeamContextType } from "@/context/team-context";
import BarChart from "@/components/shared/icons/bar-chart";
import Image from "next/image";
import NotionIcon from "@/components/shared/icons/notion";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { TeamContextType } from "@/context/team-context";
import { FolderInputIcon, MoreVertical, TrashIcon } from "lucide-react";
import { useTheme } from "next-themes";
import { toast } from "sonner";
import { mutate } from "swr";
import BarChart from "@/components/shared/icons/bar-chart";
import Check from "@/components/shared/icons/check";
import Copy from "@/components/shared/icons/copy";
import NotionIcon from "@/components/shared/icons/notion";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
@@ -15,13 +22,11 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { TrashIcon, MoreVertical, FolderInputIcon } from "lucide-react";
import { mutate } from "swr";
import { DocumentWithLinksAndLinkCountAndViewCount } from "@/lib/types";
import { nFormatter, timeAgo } from "@/lib/utils";
import { useCopyToClipboard } from "@/lib/utils/use-copy-to-clipboard";
import Check from "@/components/shared/icons/check";
import Copy from "@/components/shared/icons/copy";
import { useEffect, useRef, useState } from "react";
import { useTheme } from "next-themes";
import { MoveToFolderModal } from "./move-folder-modal";
type DocumentsCardProps = {
@@ -122,11 +127,11 @@ export default function DocumentsCard({
return (
<>
<li className="group/row relative rounded-lg p-3 border-0 dark:bg-secondary ring-1 ring-gray-200 dark:ring-gray-700 transition-all hover:ring-gray-300 hover:dark:ring-gray-500 hover:bg-secondary sm:p-4 flex justify-between items-center">
<div className="min-w-0 flex shrink items-center space-x-2 sm:space-x-4">
<div className="w-8 mx-0.5 sm:mx-1 text-center flex justify-center items-center">
<li className="group/row relative flex items-center justify-between rounded-lg border-0 p-3 ring-1 ring-gray-200 transition-all hover:bg-secondary hover:ring-gray-300 dark:bg-secondary dark:ring-gray-700 hover:dark:ring-gray-500 sm:p-4">
<div className="flex min-w-0 shrink items-center space-x-2 sm:space-x-4">
<div className="mx-0.5 flex w-8 items-center justify-center text-center sm:mx-1">
{prismaDocument.type === "notion" ? (
<NotionIcon className="w-8 h-8" />
<NotionIcon className="h-8 w-8" />
) : (
<Image
src={`/_icons/${prismaDocument.type}${isLight ? "-light" : ""}.svg`}
@@ -139,18 +144,18 @@ export default function DocumentsCard({
<div className="flex-col">
<div className="flex items-center">
<h2 className="min-w-0 text-sm font-semibold leading-6 text-foreground truncate max-w-[150px] sm:max-w-md">
<h2 className="min-w-0 max-w-[150px] truncate text-sm font-semibold leading-6 text-foreground sm:max-w-md">
<Link
href={`/documents/${prismaDocument.id}`}
className="truncate w-full"
className="w-full truncate"
>
<span>{prismaDocument.name}</span>
<span className="absolute inset-0" />
</Link>
</h2>
<div className="flex ml-2">
<div className="ml-2 flex">
<button
className="group rounded-md bg-gray-200 dark:bg-gray-700 z-10 p-1 transition-all duration-75 hover:scale-105 hover:bg-emerald-100 hover:dark:bg-emerald-200 active:scale-95"
className="group z-10 rounded-md bg-gray-200 p-1 transition-all duration-75 hover:scale-105 hover:bg-emerald-100 active:scale-95 dark:bg-gray-700 hover:dark:bg-emerald-200"
onClick={() =>
handleCopyToClipboard(prismaDocument.links[0].id)
}
@@ -187,10 +192,10 @@ export default function DocumentsCard({
e.stopPropagation();
}}
href={`/documents/${prismaDocument.id}`}
className="flex items-center z-10 space-x-1 rounded-md bg-gray-200 dark:bg-gray-700 px-1.5 sm:px-2 py-0.5 transition-all duration-75 hover:scale-105 active:scale-100"
className="z-10 flex items-center space-x-1 rounded-md bg-gray-200 px-1.5 py-0.5 transition-all duration-75 hover:scale-105 active:scale-100 dark:bg-gray-700 sm:px-2"
>
<BarChart className="h-3 sm:h-4 w-3 sm:w-4 text-muted-foreground" />
<p className="whitespace-nowrap text-xs sm:text-sm text-muted-foreground">
<BarChart className="h-3 w-3 text-muted-foreground sm:h-4 sm:w-4" />
<p className="whitespace-nowrap text-xs text-muted-foreground sm:text-sm">
{nFormatter(prismaDocument._count.views)}
<span className="ml-1 hidden sm:inline-block">views</span>
</p>
@@ -201,28 +206,28 @@ export default function DocumentsCard({
<Button
// size="icon"
variant="outline"
className="h-8 lg:h-9 w-8 lg:w-9 p-0 z-10 bg-transparent border-gray-200 dark:border-gray-700 hover:bg-gray-200 hover:dark:bg-gray-700"
className="z-10 h-8 w-8 border-gray-200 bg-transparent p-0 hover:bg-gray-200 dark:border-gray-700 hover:dark:bg-gray-700 lg:h-9 lg:w-9"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="w-4 h-4" />
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" ref={dropdownRef}>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem onClick={() => setMoveFolderOpen(true)}>
<FolderInputIcon className="w-4 h-4 mr-2" />
<FolderInputIcon className="mr-2 h-4 w-4" />
Move to folder
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={(event) => handleButtonClick(event, prismaDocument.id)}
className="text-destructive focus:bg-destructive focus:text-destructive-foreground duration-200"
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
>
{isFirstClick ? (
"Really delete?"
) : (
<>
<TrashIcon className="w-4 h-4 mr-2" /> Delete document
<TrashIcon className="mr-2 h-4 w-4" /> Delete document
</>
)}
</DropdownMenuItem>

View File

@@ -1,17 +1,21 @@
import { getExtension } from "@/lib/utils";
import { Document, DocumentVersion } from "@prisma/client";
import Image from "next/image";
import NotionIcon from "@/components/shared/icons/notion";
import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { useTheme } from "next-themes";
import { AddDocumentModal } from "./add-document-modal";
import FileUp from "@/components/shared/icons/file-up";
import { Button } from "@/components/ui/button";
import PapermarkSparkle from "@/components/shared/icons/papermark-sparkle";
import { mutate } from "swr";
import { useRouter } from "next/router";
import { useEffect, useRef, useState } from "react";
import { useTeam } from "@/context/team-context";
import { Document, DocumentVersion } from "@prisma/client";
import { Sparkles, TrashIcon } from "lucide-react";
import { usePlausible } from "next-plausible";
import { useTheme } from "next-themes";
import { toast } from "sonner";
import { mutate } from "swr";
import FileUp from "@/components/shared/icons/file-up";
import MoreVertical from "@/components/shared/icons/more-vertical";
import NotionIcon from "@/components/shared/icons/notion";
import PapermarkSparkle from "@/components/shared/icons/papermark-sparkle";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
@@ -21,10 +25,11 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import MoreVertical from "@/components/shared/icons/more-vertical";
import { Sparkles, TrashIcon } from "lucide-react";
import { DocumentWithLinksAndLinkCountAndViewCount } from "@/lib/types";
import { useTeam } from "@/context/team-context";
import { getExtension } from "@/lib/utils";
import { AddDocumentModal } from "./add-document-modal";
export default function DocumentHeader({
prismaDocument,
@@ -238,12 +243,12 @@ export default function DocumentHeader({
};
return (
<header className="flex items-center justify-between gap-x-8 !mb-16">
<div className="flex space-x-2 items-center">
<header className="!mb-16 flex items-center justify-between gap-x-8">
<div className="flex items-center space-x-2">
{primaryVersion.type === "notion" ? (
<NotionIcon className="w-7 lg:w-8 h-7 lg:h-8" />
<NotionIcon className="h-7 w-7 lg:h-8 lg:w-8" />
) : (
<div className="w-[25px] lg:w-[32px] h-[25px] lg:h-[32px]">
<div className="h-[25px] w-[25px] lg:h-[32px] lg:w-[32px]">
<Image
src={`/_icons/${getExtension(primaryVersion.file)}${isLight ? "-light" : ""}.svg`}
alt="File icon"
@@ -253,9 +258,9 @@ export default function DocumentHeader({
</div>
)}
<div className="flex flex-col mt-1 lg:mt-0">
<div className="mt-1 flex flex-col lg:mt-0">
<h2
className="text-lg lg:text-xl xl:text-2xl text-foreground font-semibold tracking-tight py-0.5 lg:py-1 px-1 lg:px-3 rounded-md border border-transparent hover:cursor-text hover:border hover:border-border focus-visible:text-lg lg:focus-visible:text-xl duration-200"
className="rounded-md border border-transparent px-1 py-0.5 text-lg font-semibold tracking-tight text-foreground duration-200 hover:cursor-text hover:border hover:border-border focus-visible:text-lg lg:px-3 lg:py-1 lg:text-xl lg:focus-visible:text-xl xl:text-2xl"
ref={nameRef}
contentEditable={true}
onFocus={() => setIsEditingName(true)}
@@ -265,7 +270,7 @@ export default function DocumentHeader({
dangerouslySetInnerHTML={{ __html: prismaDocument.name }}
/>
{isEditingName && (
<span className="text-xs text-muted-foreground mt-1">
<span className="mt-1 text-xs text-muted-foreground">
{`Press <Enter> to save the name.`}
</span>
)}
@@ -276,7 +281,7 @@ export default function DocumentHeader({
{primaryVersion.type !== "notion" && (
<AddDocumentModal newVersion>
<button title="Upload a new version" className="hidden md:flex">
<FileUp className="w-6 h-6" />
<FileUp className="h-6 w-6" />
</button>
</AddDocumentModal>
)}
@@ -284,7 +289,7 @@ export default function DocumentHeader({
{prismaDocument.type !== "notion" &&
prismaDocument.assistantEnabled && (
<Button
className="group hidden md:flex h-8 lg:h-9 space-x-1 text-xs lg:text-sm whitespace-nowrap bg-gradient-to-r from-[#16222A] via-emerald-500 to-[#16222A] duration-200 ease-linear hover:bg-right"
className="group hidden h-8 space-x-1 whitespace-nowrap bg-gradient-to-r from-[#16222A] via-emerald-500 to-[#16222A] text-xs duration-200 ease-linear hover:bg-right md:flex lg:h-9 lg:text-sm"
variant={"special"}
size={"icon"}
style={{ backgroundSize: "200% auto" }}
@@ -299,7 +304,7 @@ export default function DocumentHeader({
{actionRows.map((row, i) => (
<ul
key={i.toString()}
className="flex flex-wrap items-center justify-end gap-2 md:gap-4 md:flex-nowrap"
className="flex flex-wrap items-center justify-end gap-2 md:flex-nowrap md:gap-4"
>
{row.map((action, i) => (
<li key={i}>{action}</li>
@@ -312,7 +317,7 @@ export default function DocumentHeader({
<DropdownMenuTrigger asChild>
<Button
variant="outline"
className="h-8 lg:h-9 w-8 lg:w-9 p-0 bg-transparent"
className="h-8 w-8 bg-transparent p-0 lg:h-9 lg:w-9"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4" />
@@ -331,7 +336,7 @@ export default function DocumentHeader({
title="Add a new version"
className="flex items-center"
>
<FileUp className="w-4 h-4 mr-2" /> Add new version
<FileUp className="mr-2 h-4 w-4" /> Add new version
</button>
</AddDocumentModal>
</DropdownMenuItem>
@@ -340,7 +345,7 @@ export default function DocumentHeader({
<DropdownMenuItem
onClick={() => activateOrRedirectAssistant(prismaDocument)}
>
<PapermarkSparkle className="h-4 w-4 mr-2" />
<PapermarkSparkle className="mr-2 h-4 w-4" />
Open AI Assistant
</DropdownMenuItem>
)}
@@ -355,7 +360,7 @@ export default function DocumentHeader({
activateOrDeactivateAssistant(true, prismaDocument.id)
}
>
<Sparkles className="w-4 h-4 mr-2" /> Activate Assistant
<Sparkles className="mr-2 h-4 w-4" /> Activate Assistant
</DropdownMenuItem>
) : (
<DropdownMenuItem
@@ -363,7 +368,7 @@ export default function DocumentHeader({
activateOrDeactivateAssistant(false, prismaDocument.id)
}
>
<Sparkles className="w-4 h-4 mr-2" /> Disable Assistant
<Sparkles className="mr-2 h-4 w-4" /> Disable Assistant
</DropdownMenuItem>
))}
@@ -373,7 +378,7 @@ export default function DocumentHeader({
className="text-destructive focus:bg-destructive focus:text-destructive-foreground"
onClick={(event) => handleButtonClick(event, prismaDocument.id)}
>
<TrashIcon className="w-4 h-4 mr-2" />
<TrashIcon className="mr-2 h-4 w-4" />
{isFirstClick ? "Really delete?" : "Delete document"}
</DropdownMenuItem>
{/* create a dropdownmenuitem that onclick calls a post request to /api/assistants with the documentId */}

View File

@@ -1,4 +1,5 @@
import { FilePlusIcon, PlusIcon } from "lucide-react";
import { Button } from "../ui/button";
import { AddDocumentModal } from "./add-document-modal";

View File

@@ -1,6 +1,12 @@
import { timeAgo } from "@/lib/utils";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { TeamContextType } from "@/context/team-context";
import { FolderIcon, MoreVertical, TrashIcon } from "lucide-react";
import { toast } from "sonner";
import { mutate } from "swr";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
@@ -10,13 +16,12 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { MoreVertical, FolderIcon, TrashIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { FolderWithCount } from "@/lib/swr/use-documents";
import { DataroomFolderWithCount } from "@/lib/swr/use-dataroom";
import { FolderWithCount } from "@/lib/swr/use-documents";
import { timeAgo } from "@/lib/utils";
import { EditFolderModal } from "../folders/edit-folder-modal";
import { toast } from "sonner";
import { mutate } from "swr";
type FolderCardProps = {
folder: FolderWithCount | DataroomFolderWithCount;
@@ -124,16 +129,16 @@ export default function FolderCard({
return (
<>
<li className="group/row relative rounded-lg p-3 border-0 dark:bg-secondary ring-1 ring-gray-400 dark:ring-gray-500 transition-all hover:ring-gray-500 hover:dark:ring-gray-400 hover:bg-secondary sm:p-4 flex justify-between items-center">
<div className="min-w-0 flex shrink items-center space-x-2 sm:space-x-4">
<div className="w-8 mx-0.5 sm:mx-1 text-center flex justify-center items-center">
<FolderIcon className="w-8 h-8 " strokeWidth={1} />
<li className="group/row relative flex items-center justify-between rounded-lg border-0 p-3 ring-1 ring-gray-400 transition-all hover:bg-secondary hover:ring-gray-500 dark:bg-secondary dark:ring-gray-500 hover:dark:ring-gray-400 sm:p-4">
<div className="flex min-w-0 shrink items-center space-x-2 sm:space-x-4">
<div className="mx-0.5 flex w-8 items-center justify-center text-center sm:mx-1">
<FolderIcon className="h-8 w-8 " strokeWidth={1} />
</div>
<div className="flex-col">
<div className="flex items-center">
<h2 className="min-w-0 text-sm font-semibold leading-6 text-foreground truncate max-w-[150px] sm:max-w-md">
<Link href={`${folderPath}`} className="truncate w-full">
<h2 className="min-w-0 max-w-[150px] truncate text-sm font-semibold leading-6 text-foreground sm:max-w-md">
<Link href={`${folderPath}`} className="w-full truncate">
<span>{folder.name}</span>
<span className="absolute inset-0" />
</Link>
@@ -175,10 +180,10 @@ export default function FolderCard({
<Button
// size="icon"
variant="outline"
className="h-8 lg:h-9 w-8 lg:w-9 p-0 z-10 bg-transparent border-gray-200 dark:border-gray-700 hover:bg-gray-200 hover:dark:bg-gray-700"
className="z-10 h-8 w-8 border-gray-200 bg-transparent p-0 hover:bg-gray-200 dark:border-gray-700 hover:dark:bg-gray-700 lg:h-9 lg:w-9"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="w-4 h-4" />
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" ref={dropdownRef}>
@@ -190,13 +195,13 @@ export default function FolderCard({
<DropdownMenuItem
onClick={(event) => handleButtonClick(event, folder.id)}
className="text-destructive focus:bg-destructive focus:text-destructive-foreground duration-200"
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
>
{isFirstClick ? (
"Really delete?"
) : (
<>
<TrashIcon className="w-4 h-4 mr-2" /> Delete Folder
<TrashIcon className="mr-2 h-4 w-4" /> Delete Folder
</>
)}
</DropdownMenuItem>

View File

@@ -1,3 +1,12 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { toast } from "sonner";
import { mutate } from "swr";
import { SidebarFolderTreeSelection } from "@/components/sidebar-folders";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -7,12 +16,6 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { mutate } from "swr";
import { SidebarFolderTreeSelection } from "@/components/sidebar-folders";
import { useRouter } from "next/router";
export function MoveToFolderModal({
open,
@@ -105,7 +108,7 @@ export function MoveToFolderModal({
</div>
<DialogFooter>
<Button onClick={handleSubmit} className="w-full h-9">
<Button onClick={handleSubmit} className="h-9 w-full">
Move to folder
</Button>
</DialogFooter>

View File

@@ -1,7 +1,9 @@
import { Progress } from "@/components/ui/progress";
import { cn } from "@/lib/utils";
import { useEventRunStatuses } from "@trigger.dev/react";
import { Progress } from "@/components/ui/progress";
import { cn } from "@/lib/utils";
export default function ProcessStatusBar({
documentVersionId,
className,
@@ -18,7 +20,7 @@ export default function ProcessStatusBar({
value={0}
text="Processing document..."
className={cn(
"w-full text-[8px] font-semibold rounded-none",
"w-full rounded-none text-[8px] font-semibold",
className,
)}
/>
@@ -31,7 +33,7 @@ export default function ProcessStatusBar({
value={0}
text={error.message}
className={cn(
"w-full text-[8px] font-semibold rounded-none",
"w-full rounded-none text-[8px] font-semibold",
className,
)}
/>
@@ -52,7 +54,7 @@ export default function ProcessStatusBar({
text={`Error processing document page ${Number(statuses[0]?.data?.currentPage)}`}
error={true}
className={cn(
"w-full text-[8px] font-semibold rounded-none",
"w-full rounded-none text-[8px] font-semibold",
className,
)}
/>
@@ -63,7 +65,7 @@ export default function ProcessStatusBar({
<Progress
value={progress}
text={text}
className={cn("w-full text-[8px] font-semibold rounded-none", className)}
className={cn("w-full rounded-none text-[8px] font-semibold", className)}
/>
);
}

View File

@@ -1,8 +1,11 @@
import { TStatsData } from "@/lib/swr/use-stats";
import ErrorPage from "next/error";
import StatsElement from "./stats-element";
import { Skeleton } from "@/components/ui/skeleton";
import { TStatsData } from "@/lib/swr/use-stats";
import StatsElement from "./stats-element";
export default function StatsCard({
statsData,
}: {
@@ -16,10 +19,10 @@ export default function StatsCard({
if (loading) {
return (
<div className="grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3 border-foreground/5 space-y-2 sm:space-y-0 sm:space-x-2 lg:space-x-3">
<div className="grid grid-cols-1 space-y-2 border-foreground/5 sm:grid-cols-3 sm:space-x-2 sm:space-y-0 lg:grid-cols-3 lg:space-x-3">
{Array.from({ length: 3 }).map((_, i) => (
<div
className="border border-foreground/5 py-6 px-4 sm:px-6 lg:px-8 rounded-lg"
className="rounded-lg border border-foreground/5 px-4 py-6 sm:px-6 lg:px-8"
key={i}
>
<Skeleton className="h-6 w-[80%] rounded-sm" />
@@ -66,7 +69,7 @@ export default function StatsCard({
];
return stats && stats.views.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3 border-foreground/5 space-y-2 sm:space-y-0 sm:space-x-2 lg:space-x-3">
<div className="grid grid-cols-1 space-y-2 border-foreground/5 sm:grid-cols-3 sm:space-x-2 sm:space-y-0 lg:grid-cols-3 lg:space-x-3">
{statistics.map((stat, statIdx) => (
<StatsElement key={statIdx} stat={stat} statIdx={statIdx} />
))}

View File

@@ -16,7 +16,7 @@ export default function StatsChartDummy({
}));
return (
<div className="pl-0.5 md:pl-1 pb-0.5 md:pb-1 border-l border-b rounded-bl-lg">
<div className="rounded-bl-lg border-b border-l pb-0.5 pl-0.5 md:pb-1 md:pl-1">
<BarChartComponent data={durationData} isDummy />
</div>
);

View File

@@ -1,22 +1,23 @@
import { Skeleton } from "../ui/skeleton";
import { cn } from "@/lib/utils";
import { Skeleton } from "../ui/skeleton";
const StatsChartSkeleton = ({ className }: { className?: string }) => {
return (
<section className={cn("px-4 border-l border-b rounded-bl-lg", className)}>
<section className={cn("rounded-bl-lg border-b border-l px-4", className)}>
<div className="flex items-center justify-end">
<Skeleton className="h-4 w-28" />
</div>
<div className="flex justify-start items-end space-x-8">
<div className="flex items-end justify-start space-x-8">
<div className="flex flex-col">
{Array.from({ length: 5 }).map((_, i) => (
<Skeleton className="w-10 h-4 rounded-sm my-[18px]" key={i} />
<Skeleton className="my-[18px] h-4 w-10 rounded-sm" key={i} />
))}
</div>
<div className="w-full flex items-end space-x-4 sm:space-x-5 md:space-x-8">
<div className="flex w-full items-end space-x-4 sm:space-x-5 md:space-x-8">
{[250, 200, 150, 100, 50, 20].map((item, i) => (
<Skeleton
className="w-16 sm:w-20 md:w-28 !rounded-t-lg rounded-b-none"
className="w-16 !rounded-t-lg rounded-b-none sm:w-20 md:w-28"
style={{ height: `${item}px` }}
key={i}
/>

View File

@@ -1,8 +1,10 @@
import { TStatsData } from "@/lib/swr/use-stats";
import ErrorPage from "next/error";
import { TStatsData } from "@/lib/swr/use-stats";
import BarChartComponent from "../charts/bar-chart";
import StatsChartSkeleton from "./stats-chart-skeleton";
import StatsChartDummy from "./stats-chart-dummy";
import StatsChartSkeleton from "./stats-chart-skeleton";
export default function StatsChart({
documentId,
@@ -80,7 +82,7 @@ export default function StatsChart({
}
return stats && stats.views.length > 0 ? (
<div className="pl-0.5 md:pl-1 pb-0.5 md:pb-1 border-l border-b rounded-bl-lg">
<div className="rounded-bl-lg border-b border-l pb-0.5 pl-0.5 md:pb-1 md:pl-1">
<BarChartComponent data={durationData} />
</div>
) : (

View File

@@ -15,17 +15,17 @@ export default function StatsElement({ stat, statIdx }: StatsElementProps) {
return (
<div
key={statIdx}
className="border border-foreground/5 py-6 px-6 xl:px-8 rounded-lg overflow-hidden"
className="overflow-hidden rounded-lg border border-foreground/5 px-6 py-6 xl:px-8"
>
<div
className={cn(
"flex sm:flex-col lg:flex-row items-center sm:items-start lg:items-center space-x-2 sm:space-x-0 sm:space-y-2 lg:space-y-0 lg:space-x-2",
"flex items-center space-x-2 sm:flex-col sm:items-start sm:space-x-0 sm:space-y-2 lg:flex-row lg:items-center lg:space-x-2 lg:space-y-0",
!stat.active
? "text-gray-300 dark:text-gray-700"
: "text-muted-foreground",
)}
>
<p className="text-sm font-medium leading-6 whitespace-nowrap capitalize">
<p className="whitespace-nowrap text-sm font-medium capitalize leading-6">
{stat.name}
</p>
</div>

View File

@@ -1,9 +1,12 @@
import { useState } from "react";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { useStats } from "@/lib/swr/use-stats";
import StatsCard from "./stats-card";
import StatsChart from "./stats-chart";
import { useState } from "react";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
export const StatsComponent = ({
documentId,

View File

@@ -1,3 +1,8 @@
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -10,14 +15,13 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
import { usePlan } from "@/lib/swr/use-billing";
import { useAnalytics } from "@/lib/analytics";
import { usePlan } from "@/lib/swr/use-billing";
import useLimits from "@/lib/swr/use-limits";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
export function AddDomainModal({
open,
setOpen,
@@ -132,11 +136,11 @@ export function AddDomainModal({
<Input
id="domain"
placeholder="docs.yourdomain.com"
className="w-full mt-1 mb-8"
className="mb-8 mt-1 w-full"
onChange={(e) => setDomain(e.target.value)}
/>
<DialogFooter>
<Button type="submit" className="w-full h-9">
<Button type="submit" className="h-9 w-full">
Add domain
</Button>
</DialogFooter>

View File

@@ -1,17 +1,19 @@
import { mutate } from "swr";
import { useDomainStatus } from "./use-domain-status";
import DomainConfiguration from "./domain-configuration";
import CheckCircle2 from "../shared/icons/check-cirlce-2";
import AlertCircle from "../shared/icons/alert-circle";
import XCircle from "../shared/icons/x-circle";
import LoadingSpinner from "../ui/loading-spinner";
import ExternalLink from "../shared/icons/external-link";
import { Button } from "../ui/button";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { mutate } from "swr";
import { useAnalytics } from "@/lib/analytics";
import AlertCircle from "../shared/icons/alert-circle";
import CheckCircle2 from "../shared/icons/check-cirlce-2";
import ExternalLink from "../shared/icons/external-link";
import XCircle from "../shared/icons/x-circle";
import { Button } from "../ui/button";
import LoadingSpinner from "../ui/loading-spinner";
import DomainConfiguration from "./domain-configuration";
import { useDomainStatus } from "./use-domain-status";
export default function DomainCard({
domain,
onDelete,
@@ -49,7 +51,7 @@ export default function DomainCard({
return (
<>
<div className="flex flex-col space-y-3 rounded-lg ring-1 ring-gray-200 dark:ring-gray-700 bg-white dark:bg-secondary hover:ring-gray-400 hover:dark:ring-gray-500 px-5 py-8 sm:px-10">
<div className="flex flex-col space-y-3 rounded-lg bg-white px-5 py-8 ring-1 ring-gray-200 hover:ring-gray-400 dark:bg-secondary dark:ring-gray-700 hover:dark:ring-gray-500 sm:px-10">
<div className="flex flex-col justify-between space-y-4 sm:flex-row sm:space-x-4">
<div className="flex items-center space-x-2">
<a

View File

@@ -1,10 +1,12 @@
"use client";
import { useState } from "react";
import { useDomainStatus } from "./use-domain-status";
import { getSubdomain } from "@/lib/domains";
import { cn } from "@/lib/utils";
import { useDomainStatus } from "./use-domain-status";
export const InlineSnippet = ({
className,
children,

View File

@@ -1,7 +1,8 @@
import useSWR from "swr";
import { fetcher } from "@/lib/utils";
import { DomainResponse, DomainVerificationStatusProps } from "@/lib/types";
import { useTeam } from "@/context/team-context";
import useSWR from "swr";
import { DomainResponse, DomainVerificationStatusProps } from "@/lib/types";
import { fetcher } from "@/lib/utils";
export function useDomainStatus({ domain }: { domain: string }) {
const teamInfo = useTeam();

View File

@@ -1,17 +1,19 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Preview,
Text,
Tailwind,
Section,
Button,
Hr,
Tailwind,
Text,
} from "@react-email/components";
export default function DataroomNotification({
dataroomName,
documentName,
@@ -28,12 +30,12 @@ export default function DataroomNotification({
<Head />
<Preview>View dataroom on Papermark</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="text-xl font-seminbold text-center p-0 mt-4 mb-8 mx-0">
<Heading className="font-seminbold mx-0 mb-8 mt-4 p-0 text-center text-xl">
{`New document available for ${dataroomName}`}
</Heading>
<Text className="text-sm leading-6 text-black">Hey!</Text>
@@ -43,9 +45,9 @@ export default function DataroomNotification({
added to <span className="font-semibold">{dataroomName}</span>{" "}
dataroom on Papermark.
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Section className="mb-[32px] mt-[32px] text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`${url}`}
style={{ padding: "12px 20px" }}
>
@@ -63,7 +65,7 @@ export default function DataroomNotification({
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,17 +1,19 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Preview,
Text,
Tailwind,
Section,
Button,
Hr,
Tailwind,
Text,
} from "@react-email/components";
export default function DataroomViewerInvitation({
dataroomName,
senderEmail,
@@ -26,12 +28,12 @@ export default function DataroomViewerInvitation({
<Head />
<Preview>View dataroom on Papermark</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="text-xl font-seminbold text-center p-0 mt-4 mb-8 mx-0">
<Heading className="font-seminbold mx-0 mb-8 mt-4 p-0 text-center text-xl">
{`View ${dataroomName}`}
</Heading>
<Text className="text-sm leading-6 text-black">Hey!</Text>
@@ -43,9 +45,9 @@ export default function DataroomViewerInvitation({
The invitation was sent by{" "}
<span className="font-semibold">{senderEmail}</span>.
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Section className="mb-[32px] mt-[32px] text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`${url}`}
style={{ padding: "12px 20px" }}
>
@@ -63,7 +65,7 @@ export default function DataroomViewerInvitation({
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,16 +1,17 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Preview,
Section,
Text,
Tailwind,
Hr,
Text,
} from "@react-email/components";
export default function DomainDeleted({
@@ -23,12 +24,12 @@ export default function DomainDeleted({
<Head />
<Preview>Domain Deleted</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="text-xl font-seminbold text-center p-0 mt-4 mb-8 mx-0">
<Heading className="font-seminbold mx-0 mb-8 mt-4 p-0 text-center text-xl">
Domain Deleted
</Heading>
<Text className="text-sm leading-6 text-black">
@@ -42,7 +43,7 @@ export default function DomainDeleted({
</Text>
<Section className="my-8 text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`https://www.papermark.io/settings/domains`}
style={{ padding: "12px 20px" }}
>
@@ -59,7 +60,7 @@ export default function DomainDeleted({
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,16 +1,17 @@
import React from "react";
import {
Body,
Container,
Button,
Container,
Head,
Heading,
Hr,
Html,
Preview,
Section,
Text,
Tailwind,
Hr,
Text,
} from "@react-email/components";
export default function EmailVerification({
@@ -25,9 +26,9 @@ export default function EmailVerification({
<Head />
<Preview>Verify your email to view the document</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="mx-0 my-7 p-0 text-center text-xl font-semibold text-black">
@@ -38,7 +39,7 @@ export default function EmailVerification({
</Text>
<Section className="my-8 text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={verificationURL}
style={{ padding: "12px 20px" }}
>
@@ -57,7 +58,7 @@ export default function EmailVerification({
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,17 +1,18 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Link,
Preview,
Section,
Text,
Tailwind,
Link,
Hr,
Text,
} from "@react-email/components";
export default function InvalidDomain({
@@ -26,9 +27,9 @@ export default function InvalidDomain({
<Head />
<Preview>Invalid Domain Configuration</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="mx-0 my-7 p-0 text-center text-xl font-semibold text-black">
@@ -50,7 +51,7 @@ export default function InvalidDomain({
</Text>
<Section className="my-8 text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`https://www.papermark.io/settings/domains`}
style={{ padding: "12px 20px" }}
>
@@ -83,7 +84,7 @@ export default function InvalidDomain({
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,17 +1,19 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Preview,
Text,
Tailwind,
Section,
Button,
Hr,
Tailwind,
Text,
} from "@react-email/components";
export default function TeamInvitation({
senderName,
senderEmail,
@@ -28,12 +30,12 @@ export default function TeamInvitation({
<Head />
<Preview>Join the team on Papermark</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="text-xl font-seminbold text-center p-0 mt-4 mb-8 mx-0">
<Heading className="font-seminbold mx-0 mb-8 mt-4 p-0 text-center text-xl">
{`Join ${teamName} on Papermark`}
</Heading>
<Text className="text-sm leading-6 text-black">Hey!</Text>
@@ -43,9 +45,9 @@ export default function TeamInvitation({
<span className="font-semibold">{teamName}</span> team on{" "}
<span className="font-semibold">Papermark</span>.
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Section className="mb-[32px] mt-[32px] text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`${url}`}
style={{ padding: "12px 20px" }}
>
@@ -63,7 +65,7 @@ export default function TeamInvitation({
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,17 +1,18 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Link,
Preview,
Section,
Text,
Tailwind,
Link,
Hr,
Text,
} from "@react-email/components";
interface TrialEndFinalReminderEmail {
@@ -26,12 +27,12 @@ const TrialEndFinalReminderEmail = ({ name }: TrialEndFinalReminderEmail) => {
<Head />
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="text-xl font-seminbold text-center p-0 mt-4 mb-8 mx-0">
<Heading className="font-seminbold mx-0 mb-8 mt-4 p-0 text-center text-xl">
Your pro trial expires in 24 hours
</Heading>
<Text className="text-sm leading-6 text-black">
@@ -57,9 +58,9 @@ const TrialEndFinalReminderEmail = ({ name }: TrialEndFinalReminderEmail) => {
<Text className="ml-1 text-sm leading-4 text-black">
Upload <span className="font-bold">large</span> files
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Section className="mb-[32px] mt-[32px] text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`https://www.papermark.io/settings/billing`}
style={{ padding: "12px 20px" }}
>
@@ -77,7 +78,7 @@ const TrialEndFinalReminderEmail = ({ name }: TrialEndFinalReminderEmail) => {
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,17 +1,18 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Link,
Preview,
Section,
Text,
Tailwind,
Link,
Hr,
Text,
} from "@react-email/components";
interface TrialEndReminderEmail {
@@ -26,12 +27,12 @@ const TrialEndReminderEmail = ({ name }: TrialEndReminderEmail) => {
<Head />
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="text-xl font-seminbold text-center p-0 mt-4 mb-8 mx-0">
<Heading className="font-seminbold mx-0 mb-8 mt-4 p-0 text-center text-xl">
Your pro trial is almost over
</Heading>
<Text className="text-sm leading-6 text-black">
@@ -56,9 +57,9 @@ const TrialEndReminderEmail = ({ name }: TrialEndReminderEmail) => {
<Text className="ml-1 text-sm leading-4 text-black">
Large file uploads
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Section className="mb-[32px] mt-[32px] text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`https://www.papermark.io/settings/billing`}
style={{ padding: "12px 20px" }}
>
@@ -67,7 +68,7 @@ const TrialEndReminderEmail = ({ name }: TrialEndReminderEmail) => {
</Section>
<Text className="text-sm font-semibold">
<span className="text-red-500"></span> Links with custom domains
will be <span className="underline text-red-500">disabled</span>{" "}
will be <span className="text-red-500 underline">disabled</span>{" "}
after your trial.
</Text>
<Text className="text-sm text-gray-400">Marc from Papermark</Text>
@@ -77,7 +78,7 @@ const TrialEndReminderEmail = ({ name }: TrialEndReminderEmail) => {
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,17 +1,18 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Link,
Preview,
Section,
Text,
Tailwind,
Link,
Hr,
Text,
} from "@react-email/components";
interface UpgradePlanEmailProps {
@@ -26,12 +27,12 @@ const UpgradePlanEmail = ({ name }: UpgradePlanEmailProps) => {
<Head />
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="text-xl font-seminbold text-center p-0 mt-4 mb-8 mx-0">
<Heading className="font-seminbold mx-0 mb-8 mt-4 p-0 text-center text-xl">
Thanks for for upgrading to Papermark Pro!
</Heading>
<Text className="text-sm leading-6 text-black">
@@ -69,9 +70,9 @@ const UpgradePlanEmail = ({ name }: UpgradePlanEmailProps) => {
<Text className="ml-1 text-sm leading-4 text-black">
Invite your team members
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Section className="mb-[32px] mt-[32px] text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`${process.env.NEXT_PUBLIC_BASE_URL}/settings/domains`}
style={{ padding: "12px 20px" }}
>
@@ -91,7 +92,7 @@ const UpgradePlanEmail = ({ name }: UpgradePlanEmailProps) => {
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,4 +1,5 @@
import React from "react";
import {
Body,
Button,
@@ -8,8 +9,8 @@ import {
Html,
Preview,
Section,
Text,
Tailwind,
Text,
} from "@react-email/components";
const VerificationLinkEmail = ({
@@ -24,7 +25,7 @@ const VerificationLinkEmail = ({
<Tailwind>
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 max-w-[500px] rounded border border-solid border-gray-200 px-10 py-5">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="mx-0 my-7 p-0 text-center text-xl font-semibold text-black">
@@ -39,7 +40,7 @@ const VerificationLinkEmail = ({
</Text>
<Section className="my-8 text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={url}
style={{ padding: "12px 20px" }}
>

View File

@@ -1,16 +1,17 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Preview,
Section,
Text,
Tailwind,
Hr,
Text,
} from "@react-email/components";
export default function ViewedDocument({
@@ -27,9 +28,9 @@ export default function ViewedDocument({
<Head />
<Preview>See who visited your document</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
<Heading className="mx-0 my-7 p-0 text-center text-xl font-semibold text-black">
@@ -50,7 +51,7 @@ export default function ViewedDocument({
</Text>
<Section className="my-8 text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`https://www.papermark.io/documents/${documentId}`}
style={{ padding: "12px 20px" }}
>
@@ -66,7 +67,7 @@ export default function ViewedDocument({
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,17 +1,18 @@
import React from "react";
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Link,
Preview,
Section,
Text,
Tailwind,
Link,
Hr,
Text,
} from "@react-email/components";
interface WelcomeEmailProps {
@@ -26,9 +27,9 @@ const WelcomeEmail = ({ name }: WelcomeEmailProps) => {
<Head />
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="my-10 mx-auto p-5 w-[465px]">
<Heading className="text-2xl font-normal text-center p-0 mt-4 mb-8 mx-0">
<Body className="mx-auto my-auto bg-white font-sans">
<Container className="mx-auto my-10 w-[465px] p-5">
<Heading className="mx-0 mb-8 mt-4 p-0 text-center text-2xl font-normal">
Welcome to{" "}
<span className="font-bold tracking-tighter">Papermark</span>
</Heading>
@@ -44,7 +45,7 @@ const WelcomeEmail = ({ name }: WelcomeEmailProps) => {
Here are a few things you can do to get started:
</Text>
<Text className="text-sm">
<ul className="list-disc list-inside text-sm">
<ul className="list-inside list-disc text-sm">
<li>Upload a document</li>
<li>
Share a link{" "}
@@ -53,9 +54,9 @@ const WelcomeEmail = ({ name }: WelcomeEmailProps) => {
<li>Watch the views come in real-time</li>
</ul>
</Text>
<Section className="text-center mt-[32px] mb-[32px]">
<Section className="mb-[32px] mt-[32px] text-center">
<Button
className="bg-black rounded text-white text-xs font-semibold no-underline text-center"
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
href={`${process.env.NEXT_PUBLIC_BASE_URL}/welcome`}
style={{ padding: "12px 20px" }}
>
@@ -67,7 +68,7 @@ const WelcomeEmail = ({ name }: WelcomeEmailProps) => {
If you would like to keep up to date, you can do:
</Text>
<Text className="text-sm">
<ul className="list-disc list-inside text-sm">
<ul className="list-inside list-disc text-sm">
<li>
Star the repo on{" "}
<Link
@@ -99,7 +100,7 @@ const WelcomeEmail = ({ name }: WelcomeEmailProps) => {
© {new Date().getFullYear()}{" "}
<a
href="https://www.papermark.io"
className="no-underline text-gray-400 hover:text-gray-400 visited:text-gray-400"
className="text-gray-400 no-underline visited:text-gray-400 hover:text-gray-400"
target="_blank"
>
papermark.io

View File

@@ -1,3 +1,12 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { Folder } from "@prisma/client";
import { toast } from "sonner";
import { mutate } from "swr";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -10,15 +19,11 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
import { usePlan } from "@/lib/swr/use-billing";
import { useAnalytics } from "@/lib/analytics";
import { mutate } from "swr";
import { Folder } from "@prisma/client";
import { useRouter } from "next/router";
import { usePlan } from "@/lib/swr/use-billing";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
export function AddFolderModal({
// open,
@@ -127,11 +132,11 @@ export function AddFolderModal({
<Input
id="folder-name"
placeholder="folder-123"
className="w-full mt-1 mb-4"
className="mb-4 mt-1 w-full"
onChange={(e) => setFolderName(e.target.value)}
/>
<DialogFooter>
<Button type="submit" className="w-full h-9">
<Button type="submit" className="h-9 w-full">
Add new folder
</Button>
</DialogFooter>

View File

@@ -1,3 +1,12 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { useTeam } from "@/context/team-context";
import { Folder } from "@prisma/client";
import { toast } from "sonner";
import { mutate } from "swr";
import { Button } from "@/components/ui/button";
import {
Dialog,
@@ -10,15 +19,11 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useTeam } from "@/context/team-context";
import { useState } from "react";
import { toast } from "sonner";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
import { usePlan } from "@/lib/swr/use-billing";
import { useAnalytics } from "@/lib/analytics";
import { mutate } from "swr";
import { Folder } from "@prisma/client";
import { useRouter } from "next/router";
import { usePlan } from "@/lib/swr/use-billing";
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
export function EditFolderModal({
open,
@@ -113,11 +118,11 @@ export function EditFolderModal({
id="folder-name-update"
value={folderName}
placeholder="folder-123"
className="w-full mt-1 mb-4"
className="mb-4 mt-1 w-full"
onChange={(e) => setFolderName(e.target.value)}
/>
<DialogFooter>
<Button type="submit" className="w-full h-9" loading={loading}>
<Button type="submit" className="h-9 w-full" loading={loading}>
Update folder
</Button>
</DialogFooter>

View File

@@ -1,4 +1,5 @@
import { Dispatch, SetStateAction } from "react";
import SearchIcon from "@/components/shared/icons/search";
export default function SearchBar({
@@ -11,7 +12,7 @@ export default function SearchBar({
return (
<div className="relative mt-5">
<SearchIcon
className="h-5 w-5 absolute z-20 left-3 bottom-2"
className="absolute bottom-2 left-3 z-20 h-5 w-5"
aria-hidden="true"
/>
<input
@@ -20,7 +21,7 @@ export default function SearchBar({
name="search"
value={search}
onChange={(e) => setSearch(e.target.value)}
className="w-full rounded-xl shadow-sm inline-flex relative items-center border border-gray-300 px-4 py-2 text-sm text-gray-700 placeholder:text-gray-400 focus:z-10 focus:outline-none focus:ring-gray-500 md:w-72 pl-10 xs:pl-12"
className="xs:pl-12 relative inline-flex w-full items-center rounded-xl border border-gray-300 px-4 py-2 pl-10 text-sm text-gray-700 shadow-sm placeholder:text-gray-400 focus:z-10 focus:outline-none focus:ring-gray-500 md:w-72"
placeholder="Search by name"
/>
</div>

View File

@@ -12,7 +12,7 @@ export default function Stats({ angelsLength }: { angelsLength: any }) {
{angelsLength}
</dd>
</div>
<div className="flex flex-col border-t border-b border-gray-100 p-6 text-center sm:border-0 sm:border-l sm:border-r">
<div className="flex flex-col border-b border-t border-gray-100 p-6 text-center sm:border-0 sm:border-l sm:border-r">
<dt className="order-2 mt-2 text-lg font-medium leading-6 text-gray-500">
Average Check Size
</dt>
@@ -20,7 +20,7 @@ export default function Stats({ angelsLength }: { angelsLength: any }) {
$45k
</dd>
</div>
<div className="flex flex-col border-t border-b border-gray-100 p-6 text-center sm:border-0 sm:border-l sm:border-r">
<div className="flex flex-col border-b border-t border-gray-100 p-6 text-center sm:border-0 sm:border-l sm:border-r">
<dt className="order-2 mt-2 text-lg font-medium leading-6 text-gray-500">
Confirmed Investments
</dt>

View File

@@ -1,15 +1,17 @@
import Image from "next/image";
import TwitterIcon from "@/components/shared/icons/twitter";
import WebsiteIcon from "@/components/shared/icons/globe";
import { cn } from "@/lib/utils";
import { type Investor } from "@/app/(static)/open-source-investors/page";
import WebsiteIcon from "@/components/shared/icons/globe";
import TwitterIcon from "@/components/shared/icons/twitter";
import { cn } from "@/lib/utils";
export default function Table({ investors }: { investors: Investor[] }) {
return (
<div>
<table className="min-w-full md:divide-y bg-gray-100 md:bg-transparent divide-gray-300 rounded-lg overflow-hidden md:rounded-none">
<thead className="bg-gray-50 hidden md:table-header-group">
<table className="min-w-full divide-gray-300 overflow-hidden rounded-lg bg-gray-100 md:divide-y md:rounded-none md:bg-transparent">
<thead className="hidden bg-gray-50 md:table-header-group">
<tr>
<th
scope="col"
@@ -43,13 +45,13 @@ export default function Table({ investors }: { investors: Investor[] }) {
</th>
</tr>
</thead>
<tbody className="md:divide-y divide-gray-200 md:bg-white grid grid-cols-1 gap-3 sm:grid-cols-2 md:table-row-group">
<tbody className="grid grid-cols-1 gap-3 divide-gray-200 sm:grid-cols-2 md:table-row-group md:divide-y md:bg-white">
{investors.map((person: Investor) => (
<tr
key={person.id}
className="grid grid-cols-3 gap-1 md:table-row bg-white rounded-lg md:rounded-none md:bg-transparent shadow md:shadow-none border border-gray-200 md:border-x-0 py-3 px-2 md:p-0"
className="grid grid-cols-3 gap-1 rounded-lg border border-gray-200 bg-white px-2 py-3 shadow md:table-row md:rounded-none md:border-x-0 md:bg-transparent md:p-0 md:shadow-none"
>
<td className="col-span-3 whitespace-nowrap pl-3 md:py-2 md:pl-6 text-sm sm:pl-6 h-24">
<td className="col-span-3 h-24 whitespace-nowrap pl-3 text-sm sm:pl-6 md:py-2 md:pl-6">
<div className="flex items-center">
<div className="h-10 w-10 flex-shrink-0">
<Image
@@ -64,7 +66,7 @@ export default function Table({ investors }: { investors: Investor[] }) {
<div className="font-medium text-gray-900">
{person.fields.name}
</div>
<div className="flex space-x-2 items-center mt-1">
<div className="mt-1 flex items-center space-x-2">
{person.fields.twitterUrl && (
<a
className="text-black"
@@ -73,7 +75,7 @@ export default function Table({ investors }: { investors: Investor[] }) {
rel="noopener noreferrer"
>
<span className="sr-only">Twitter</span>
<TwitterIcon className="w-4 h-4" />
<TwitterIcon className="h-4 w-4" />
</a>
)}
{person.fields.websiteUrl && (
@@ -84,20 +86,20 @@ export default function Table({ investors }: { investors: Investor[] }) {
rel="noopener noreferrer"
>
<span className="sr-only">Website</span>
<WebsiteIcon className="w-4 h-4" />
<WebsiteIcon className="h-4 w-4" />
</a>
)}
</div>
</div>
</div>
</td>
<td className="col-span-1 row-start-2 whitespace-nowrap px-3 md:px-2 md:py-3 text-sm text-gray-500 font-bold md:font-normal">
<td className="col-span-1 row-start-2 whitespace-nowrap px-3 text-sm font-bold text-gray-500 md:px-2 md:py-3 md:font-normal">
{person.fields.company ?? "Unknown"}
</td>
<td className="col-span-3 whitespace-nowrap px-3 md:px-2 md:py-3 text-sm text-gray-500 -mt-2 md:mt-0">
<td className="col-span-3 -mt-2 whitespace-nowrap px-3 text-sm text-gray-500 md:mt-0 md:px-2 md:py-3">
{person.fields.title ?? "Software Engineer"}
</td>
<td className="col-span-3 row-start-2 whitespace-nowrap px-0 md:px-2 md:py-3 text-sm text-gray-500 justify-self-end">
<td className="col-span-3 row-start-2 justify-self-end whitespace-nowrap px-0 text-sm text-gray-500 md:px-2 md:py-3">
<span
className={cn(
person.fields.checkSize === "Unknown"
@@ -117,7 +119,7 @@ export default function Table({ investors }: { investors: Investor[] }) {
{person.fields.checkSize}
</span>
</td>
<td className="col-span-3 md:max-w-xs px-3 md:px-2 md:py-3 text-sm text-gray-500">
<td className="col-span-3 px-3 text-sm text-gray-500 md:max-w-xs md:px-2 md:py-3">
{person.fields.openSourceInvestments ?? "Unknown"}
</td>
</tr>
@@ -125,7 +127,7 @@ export default function Table({ investors }: { investors: Investor[] }) {
</tbody>
</table>
{investors.length === 0 && (
<div className="text-center my-10">No results found</div>
<div className="my-10 text-center">No results found</div>
)}
</div>
);

View File

@@ -3,9 +3,9 @@ import Sidebar from "../Sidebar";
export default function AppLayout({ children }: { children: React.ReactNode }) {
return (
<div>
<div className="flex flex-col lg:flex-row bg-gray-50 dark:bg-black min-h-screen">
<div className="flex min-h-screen flex-col bg-gray-50 dark:bg-black lg:flex-row">
<Sidebar />
<main className="grow w-full overflow-y-auto bg-white dark:bg-gray-900 ring-gray-200 dark:ring-gray-800 dark:border-none lg:m-2 rounded-xl ring-1">
<main className="w-full grow overflow-y-auto rounded-xl bg-white ring-1 ring-gray-200 dark:border-none dark:bg-gray-900 dark:ring-gray-800 lg:m-2">
{children}
</main>
</div>

View File

@@ -1,6 +1,9 @@
import { Dispatch, SetStateAction, useState, useEffect } from "react";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function AllowDownloadSection({

View File

@@ -1,14 +1,18 @@
import {
ChangeEvent,
Dispatch,
SetStateAction,
useState,
useEffect,
ChangeEvent,
useState,
} from "react";
import { Switch } from "@/components/ui/switch";
import { motion } from "framer-motion";
import { Switch } from "@/components/ui/switch";
import { FADE_IN_ANIMATION_SETTINGS } from "@/lib/constants";
import { cn, sanitizeAllowDenyList } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function AllowListSection({
@@ -87,7 +91,7 @@ export default function AllowListSection({
>
Allow specified viewers
{hasFreePlan && (
<span className="bg-background text-foreground ring-1 ring-gray-800 dark:ring-gray-500 rounded-full px-2 py-0.5 text-xs ml-2">
<span className="ml-2 rounded-full bg-background px-2 py-0.5 text-xs text-foreground ring-1 ring-gray-800 dark:ring-gray-500">
Pro
</span>
)}
@@ -113,7 +117,7 @@ export default function AllowListSection({
{...FADE_IN_ANIMATION_SETTINGS}
>
<textarea
className="form-textarea w-full rounded-md border-0 py-1.5 text-foreground bg-background shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 text-sm leading-6"
className="form-textarea w-full rounded-md border-0 bg-background py-1.5 text-sm leading-6 text-foreground shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400"
rows={5}
placeholder="Enter allowed emails/domains, one per line, e.g. marc@papermark.io @example.org"
value={allowListInput}

View File

@@ -1,6 +1,9 @@
import { Dispatch, SetStateAction, useState, useEffect } from "react";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function AllowNotificationSection({

View File

@@ -1,14 +1,18 @@
import {
ChangeEvent,
Dispatch,
SetStateAction,
useState,
useEffect,
ChangeEvent,
useState,
} from "react";
import { Switch } from "@/components/ui/switch";
import { motion } from "framer-motion";
import { Switch } from "@/components/ui/switch";
import { FADE_IN_ANIMATION_SETTINGS } from "@/lib/constants";
import { cn, sanitizeAllowDenyList } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function DenyListSection({
@@ -86,7 +90,7 @@ export default function DenyListSection({
>
Block specified viewers
{hasFreePlan && (
<span className="bg-background text-foreground ring-1 ring-gray-800 dark:ring-gray-500 rounded-full px-2 py-0.5 text-xs ml-2">
<span className="ml-2 rounded-full bg-background px-2 py-0.5 text-xs text-foreground ring-1 ring-gray-800 dark:ring-gray-500">
Pro
</span>
)}
@@ -112,7 +116,7 @@ export default function DenyListSection({
{...FADE_IN_ANIMATION_SETTINGS}
>
<textarea
className="form-textarea w-full rounded-md border-0 py-1.5 text-foreground bg-background shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 text-sm leading-6"
className="form-textarea w-full rounded-md border-0 bg-background py-1.5 text-sm leading-6 text-foreground shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400"
rows={5}
placeholder="Enter blocked emails/domains, one per line, e.g. marc@papermark.io @example.org"
value={denyListInput}

View File

@@ -1,17 +1,20 @@
import { Dispatch, SetStateAction, useState } from "react";
import { cn } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
import { Label } from "@/components/ui/label";
import { Domain } from "@prisma/client";
import { AddDomainModal } from "@/components/domains/add-domain-modal";
import { mutate } from "swr";
import Link from "next/link";
import { Dispatch, SetStateAction, useState } from "react";
import { useTeam } from "@/context/team-context";
import { Domain } from "@prisma/client";
import { mutate } from "swr";
import { AddDomainModal } from "@/components/domains/add-domain-modal";
import { Label } from "@/components/ui/label";
import { BLOCKED_PATHNAMES } from "@/lib/constants";
import { BasePlan } from "@/lib/swr/use-billing";
import useLimits from "@/lib/swr/use-limits";
import { cn } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function DomainSection({
data,
@@ -62,7 +65,7 @@ export default function DomainSection({
"w-full rounded-l-md border border-r-0 border-border bg-secondary px-5 text-sm text-secondary-foreground focus:border-border focus:outline-none focus:ring-0",
data.domain && data.domain !== "papermark.io"
? ""
: "rounded-r-md border-r-1",
: "border-r-1 rounded-r-md",
)}
>
<option key="papermark.io" value="papermark.io">
@@ -123,7 +126,7 @@ export default function DomainSection({
}}
autoComplete="off"
className={cn(
"hidden w-full rounded-r-md border-0 py-1.5 text-foreground bg-background shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 sm:text-sm sm:leading-6",
"hidden w-full rounded-r-md border-0 bg-background py-1.5 text-foreground shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 sm:text-sm sm:leading-6",
data.domain && data.domain !== "papermark.io" ? "flex" : "",
)}
placeholder="deck"
@@ -146,7 +149,7 @@ export default function DomainSection({
</div>
{data.domain && data.domain !== "papermark.io" && !isDomainVerified ? (
<div className="text-sm text-red-500 mt-4">
<div className="mt-4 text-sm text-red-500">
Your domain is not verified yet!{" "}
<Link
className="underline hover:text-red-500/80"

View File

@@ -1,6 +1,9 @@
import { Dispatch, SetStateAction, useState, useEffect } from "react";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function EmailAuthenticationSection({
@@ -55,7 +58,7 @@ export default function EmailAuthenticationSection({
>
Require email verification
{hasFreePlan && (
<span className="bg-background text-foreground ring-1 ring-gray-800 dark:ring-gray-500 rounded-full px-2 py-0.5 text-xs ml-2">
<span className="ml-2 rounded-full bg-background px-2 py-0.5 text-xs text-foreground ring-1 ring-gray-800 dark:ring-gray-500">
Pro
</span>
)}

View File

@@ -1,6 +1,9 @@
import { Dispatch, SetStateAction, useState, useEffect } from "react";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function EmailProtectionSection({

View File

@@ -1,8 +1,12 @@
import { Dispatch, SetStateAction, useState, useEffect } from "react";
import { Switch } from "@/components/ui/switch";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { motion } from "framer-motion";
import { Switch } from "@/components/ui/switch";
import { FADE_IN_ANIMATION_SETTINGS } from "@/lib/constants";
import { cn, getDateTimeLocal } from "@/lib/utils";
import { DEFAULT_LINK_TYPE } from ".";
export default function ExpirationSection({
@@ -54,7 +58,7 @@ export default function ExpirationSection({
onChange={(e) => {
setData({ ...data, expiresAt: new Date(e.target.value) });
}}
className="flex w-full rounded-md border-0 py-1.5 text-foreground bg-background shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 sm:text-sm sm:leading-6"
className="flex w-full rounded-md border-0 bg-background py-1.5 text-foreground shadow-sm ring-1 ring-inset ring-input placeholder:text-muted-foreground focus:ring-2 focus:ring-inset focus:ring-gray-400 sm:text-sm sm:leading-6"
/>
</motion.div>
)}

Some files were not shown because too many files have changed in this diff Show More