-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ccbe373
commit 3f1fb2c
Showing
78 changed files
with
12,559 additions
and
2,190 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,3 +33,9 @@ yarn-error.log* | |
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts | ||
|
||
# trunk | ||
.trunk | ||
|
||
# vscode | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
"use client"; | ||
|
||
import { useMutation, useQuery } from "convex/react"; | ||
import dynamic from "next/dynamic"; | ||
import { useMemo } from "react"; | ||
|
||
import { api } from "@/convex/_generated/api"; | ||
import { Id } from "@/convex/_generated/dataModel"; | ||
import { Toolbar } from "@/components/toolbar"; | ||
import { Cover } from "@/components/cover"; | ||
import { Skeleton } from "@/components/ui/skeleton"; | ||
import { useParams } from "next/navigation"; | ||
|
||
// interface DocumentIdPageProps { | ||
// params: { | ||
// documentId: Id<"documents">; | ||
// }; | ||
// }; | ||
|
||
const DocumentIdPage = () => { | ||
const Editor = useMemo(() => dynamic(() => import("@/components/editor"), { ssr: false }) ,[]); | ||
const params = useParams(); | ||
|
||
const document = useQuery(api.documents.getById, { | ||
documentId: params.documentId as Id<"documents"> | ||
}); | ||
|
||
const update = useMutation(api.documents.update); | ||
|
||
const onChange = (content: string) => { | ||
update({ | ||
id: params.documentId as Id<"documents">, | ||
content | ||
}); | ||
}; | ||
|
||
if (document === undefined) { | ||
return ( | ||
<div> | ||
<Cover.Skeleton /> | ||
<div className="md:max-w-3xl lg:max-w-4xl mx-auto mt-10"> | ||
<div className="space-y-4 pl-8 pt-4"> | ||
<Skeleton className="h-14 w-[50%]" /> | ||
<Skeleton className="h-4 w-[80%]" /> | ||
<Skeleton className="h-4 w-[40%]" /> | ||
<Skeleton className="h-4 w-[60%]" /> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
if (document === null) { | ||
return <div>Not found</div> | ||
} | ||
|
||
return ( | ||
<div className="pb-40"> | ||
<Cover url={document.coverImage} /> | ||
<div className="md:max-w-3xl lg:max-w-4xl mx-auto"> | ||
<Toolbar initialData={document} /> | ||
<Editor | ||
onChange={onChange} | ||
initialContent={document.content} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default DocumentIdPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"use client"; | ||
|
||
import Image from "next/image"; | ||
import { useUser } from "@clerk/clerk-react"; | ||
import { PlusCircle } from "lucide-react"; | ||
import { useMutation } from "convex/react"; | ||
import { toast } from "sonner"; | ||
import { useRouter } from "next/navigation"; | ||
|
||
import { api } from "@/convex/_generated/api"; | ||
import { Button } from "@/components/ui/button"; | ||
|
||
const DocumentsPage = () => { | ||
const router = useRouter(); | ||
const { user } = useUser(); | ||
const create = useMutation(api.documents.create); | ||
|
||
const onCreate = () => { | ||
const promise = create({ title: "Untitled" }) | ||
.then((result) => { | ||
if (!result) { | ||
throw new Error("Failed to create document"); | ||
} | ||
router.push(`/documents/${result}`); | ||
}) | ||
toast.promise(promise, { | ||
loading: "Creating a new note...", | ||
success: "New note created!", | ||
error: "Failed to create a new note." | ||
}); | ||
}; | ||
|
||
return ( | ||
<div className="h-full flex flex-col items-center justify-center space-y-4"> | ||
<Image | ||
src="/empty.png" | ||
height="300" | ||
width="300" | ||
alt="Empty" | ||
className="dark:hidden" | ||
/> | ||
<Image | ||
src="/empty-dark.png" | ||
height="300" | ||
width="300" | ||
alt="Empty" | ||
className="hidden dark:block" | ||
/> | ||
<h2 className="text-lg font-medium"> | ||
Welcome to {user?.firstName}'s Jotion | ||
</h2> | ||
<Button onClick={onCreate}> | ||
<PlusCircle className="h-4 w-4 mr-2" /> | ||
Create a note | ||
</Button> | ||
</div> | ||
); | ||
} | ||
|
||
export default DocumentsPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
"use client"; | ||
|
||
import { useRouter } from "next/navigation"; | ||
import { useMutation } from "convex/react"; | ||
import { toast } from "sonner"; | ||
|
||
import { Id } from "@/convex/_generated/dataModel"; | ||
import { api } from "@/convex/_generated/api"; | ||
import { Button } from "@/components/ui/button"; | ||
import { ConfirmModal } from "@/components/modals/confirm-modal"; | ||
|
||
interface BannerProps { | ||
documentId: Id<"documents">; | ||
}; | ||
|
||
export const Banner = ({ | ||
documentId | ||
}: BannerProps) => { | ||
const router = useRouter(); | ||
|
||
const remove = useMutation(api.documents.remove); | ||
const restore = useMutation(api.documents.restore); | ||
|
||
const onRemove = () => { | ||
const promise = remove({ id: documentId }); | ||
|
||
toast.promise(promise, { | ||
loading: "Deleting note...", | ||
success: "Note deleted!", | ||
error: "Failed to delete note." | ||
}); | ||
|
||
router.push("/documents"); | ||
}; | ||
|
||
const onRestore = () => { | ||
const promise = restore({ id: documentId }); | ||
|
||
toast.promise(promise, { | ||
loading: "Restoring note...", | ||
success: "Note restored!", | ||
error: "Failed to restore note." | ||
}); | ||
}; | ||
|
||
return ( | ||
<div className="w-full bg-rose-500 text-center text-sm p-2 text-white flex items-center gap-x-2 justify-center"> | ||
<p> | ||
This page is in the Trash. | ||
</p> | ||
<Button | ||
size="sm" | ||
onClick={onRestore} | ||
variant="outline" | ||
className="border-white bg-transparent hover:bg-primary/5 text-white hover:text-white p-1 px-2 h-auto font-normal" | ||
> | ||
Restore page | ||
</Button> | ||
<ConfirmModal onConfirm={onRemove}> | ||
<Button | ||
size="sm" | ||
variant="outline" | ||
className="border-white bg-transparent hover:bg-primary/5 text-white hover:text-white p-1 px-2 h-auto font-normal" | ||
> | ||
Delete forever | ||
</Button> | ||
</ConfirmModal> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
"use client"; | ||
|
||
import { api } from "@/convex/_generated/api"; | ||
import { Doc, Id } from "@/convex/_generated/dataModel"; | ||
import { useQuery } from "convex/react"; | ||
import { useParams, useRouter } from "next/navigation"; | ||
import { useState } from "react"; | ||
import { Item } from "./item"; | ||
import { cn } from "@/lib/utils"; | ||
import { FileIcon } from "lucide-react"; | ||
|
||
interface DocumentListProps { | ||
parentDocumentId?: Id<"documents">; | ||
level?: number; | ||
data?: Doc<"documents">[]; | ||
} | ||
|
||
export const DocumentList = ( | ||
{ parentDocumentId, level = 0 }: DocumentListProps | ||
) => { | ||
const params = useParams(); | ||
const router = useRouter(); | ||
const [expanded, setExpanded] = useState<Record<string, boolean>>({}); | ||
|
||
const onExpand = (documentId: string) => { | ||
setExpanded(prev => ({ | ||
...prev, | ||
[documentId]: !prev[documentId] | ||
})) | ||
} | ||
|
||
const documents = useQuery(api.documents.getSidebar, { | ||
parentDocument: parentDocumentId | ||
}); | ||
|
||
const onRedirect = (documentId: string) => { | ||
router.push(`/documents/${documentId}`); | ||
}; | ||
|
||
if (documents === undefined) { | ||
return ( | ||
<> | ||
<Item.Skeleton level={level} /> | ||
{level === 0 && ( | ||
<> | ||
<Item.Skeleton level={level} /> | ||
<Item.Skeleton level={level} /> | ||
</> | ||
)} | ||
</> | ||
) | ||
} | ||
|
||
return ( | ||
<> | ||
<p | ||
style={{ | ||
paddingLeft: level ? `${(level * 12) + 25}px` : "12px" | ||
}} | ||
className={cn( | ||
"hidden text-sm text-muted-foreground/80 font-medium", | ||
expanded && "last:block", | ||
level === 0 && "hidden" | ||
)} | ||
> | ||
No pages inside | ||
</p> | ||
{documents.map((document) => ( | ||
<div key={document._id}> | ||
<Item | ||
id={document._id} | ||
onClick={() => onRedirect(document._id)} | ||
label={document.title} | ||
icon={FileIcon} | ||
documentIcon={document.icon} | ||
active={params.documentId === document._id} | ||
level={level} | ||
onExpand={() => onExpand(document._id)} | ||
expanded={expanded[document._id]} | ||
/> | ||
{expanded[document._id] && ( | ||
<DocumentList | ||
parentDocumentId={document._id} | ||
level={level + 1} | ||
/> | ||
)} | ||
</div> | ||
))} | ||
</> | ||
) | ||
} |
Oops, something went wrong.