mirror of
https://github.com/mfts/papermark.git
synced 2025-12-20 01:03:24 +08:00
chore: run prettier format
This commit is contained in:
@@ -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 }) {
|
||||
|
||||
@@ -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'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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
105
app/page.tsx
105
app/page.tsx
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.`}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Image, { ImageProps } from "next/image";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function BlurImage(props: ImageProps) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 }) => {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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[],
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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} />
|
||||
))}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)}
|
||||
/>
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 */}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { FilePlusIcon, PlusIcon } from "lucide-react";
|
||||
|
||||
import { Button } from "../ui/button";
|
||||
import { AddDocumentModal } from "./add-document-modal";
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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} />
|
||||
))}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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>
|
||||
) : (
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" }}
|
||||
>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user