-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from Lostovayne/auth
Auth
- Loading branch information
Showing
8 changed files
with
275 additions
and
31 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
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
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
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
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,118 @@ | ||
"use client"; | ||
|
||
import { Button } from "@/components/ui/button"; | ||
import { Input } from "@/components/ui/input"; | ||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; | ||
import { api } from "@/convex/_generated/api"; | ||
import type { Doc } from "@/convex/_generated/dataModel"; | ||
|
||
import { useOrigin } from "@/hooks/use-origin"; | ||
import { useMutation } from "convex/react"; | ||
import { Check, CheckIcon, CopyIcon, GlobeIcon } from "lucide-react"; | ||
import { FC, ReactElement, useState } from "react"; | ||
import { toast } from "sonner"; | ||
|
||
interface PublishProps { | ||
initialData: Doc<"documents">; | ||
} | ||
|
||
const Publish: FC<PublishProps> = ({ initialData }): ReactElement => { | ||
const origin = useOrigin(); | ||
const update = useMutation(api.documents.update); | ||
|
||
const [copied, setCopied] = useState<boolean>(false); | ||
const [isSubmitting, setIsSubmitting] = useState<boolean>(false); | ||
|
||
const url = `${origin}/preview/${initialData._id}`; | ||
|
||
const onPublish = async () => { | ||
setIsSubmitting(true); | ||
const promise = update({ | ||
id: initialData._id, | ||
isPublished: true | ||
}).finally(() => setIsSubmitting(false)); | ||
|
||
toast.promise(promise, { | ||
loading: "Publishing...", | ||
success: "Note published", | ||
error: "Could not publish note" | ||
}); | ||
}; | ||
|
||
const onUnPublish = async () => { | ||
setIsSubmitting(true); | ||
const promise = update({ | ||
id: initialData._id, | ||
isPublished: false | ||
}).finally(() => setIsSubmitting(false)); | ||
|
||
toast.promise(promise, { | ||
loading: "Unpublishing...", | ||
success: "Note unpublished", | ||
error: "Could not unpublish note" | ||
}); | ||
}; | ||
|
||
const onCopy = () => { | ||
navigator.clipboard.writeText(url); | ||
setCopied(true); | ||
setTimeout(() => setCopied(false), 1000); | ||
}; | ||
|
||
return ( | ||
<Popover> | ||
<PopoverTrigger asChild> | ||
<Button size={"sm"} variant={"ghost"}> | ||
Publish | ||
{initialData.isPublished && <GlobeIcon className=" text-sky-500 ml-2 h-4 w-4" />} | ||
</Button> | ||
</PopoverTrigger> | ||
<PopoverContent className={"w-72"} align={"end"} alignOffset={8} forceMount> | ||
{initialData.isPublished ? | ||
<div className={"space-y-2"}> | ||
<div className={"flex items-center gap-x-2"}> | ||
<GlobeIcon className={"text-sky-500 h-4 w-4"} /> | ||
<p>This note is live on the internet</p> | ||
</div> | ||
<div className={"flex items-center"}> | ||
<Input | ||
value={url} | ||
readOnly | ||
className={ | ||
"flex-1 px-2 text-xs border rounded-l-md h-8 bg-muted-foreground truncate" | ||
} | ||
disabled | ||
/> | ||
<Button onClick={onCopy} disabled={copied} className={"h-8 rounded-l-none"}> | ||
{copied ? | ||
<CheckIcon className={" h-4 w-4"} /> | ||
: <CopyIcon className={" h-4 w-4"} />} | ||
</Button> | ||
</div> | ||
<Button | ||
onClick={onUnPublish} | ||
size={"sm"} | ||
className={"w-full text-xs"} | ||
disabled={isSubmitting}> | ||
Unpublish | ||
</Button> | ||
</div> | ||
: <div className={"flex flex-col items-center justify-center"}> | ||
<GlobeIcon className={"size-8 text-muted-foreground mb-2"} /> | ||
<p className={"text-sm font-medium mb-2"}>Publish this note</p> | ||
<span>Share your work with the world</span> | ||
<Button | ||
disabled={isSubmitting} | ||
onClick={onPublish} | ||
className={"w-full text-xs"} | ||
size={"sm"}> | ||
Publish | ||
</Button> | ||
</div> | ||
} | ||
</PopoverContent> | ||
</Popover> | ||
); | ||
}; | ||
|
||
export default Publish; |
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,54 @@ | ||
"use client"; | ||
import Cover from "@/components/cover"; | ||
import { Editor } from "@/components/dynamic-editor"; | ||
import Toolbar from "@/components/toolbar"; | ||
import { Skeleton } from "@/components/ui/skeleton"; | ||
import { api } from "@/convex/_generated/api"; | ||
import type { Id } from "@/convex/_generated/dataModel"; | ||
import { useMutation, useQuery } from "convex/react"; | ||
import { ReactElement } from "react"; | ||
|
||
interface DocumentIdPageProps { | ||
params: { documentId: Id<"documents"> }; | ||
} | ||
|
||
const DocumentIdPage = ({ params }: DocumentIdPageProps): ReactElement => { | ||
const documentId = params.documentId; | ||
const document = useQuery(api.documents.getById, { | ||
documentId: documentId | ||
}); | ||
|
||
const update = useMutation(api.documents.update); | ||
|
||
const onChange = (content: string) => { | ||
update({ id: documentId, 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>Document not found</div>; | ||
|
||
return ( | ||
<div className={"pb-40"}> | ||
<Cover preview url={document.coverImage} /> | ||
<div className={"md:max-w-4xl lg:max-w-5xl xl:max-w-6xl 2xl:max-w-7xl mx-auto"}> | ||
<Toolbar preview initialData={document} /> | ||
<Editor onChange={onChange} initialContent={document.content} editable={false} /> | ||
</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,41 @@ | ||
"use client"; | ||
|
||
import Image from "next/image"; | ||
import Link from "next/link"; | ||
import { Button } from "@/components/ui/button"; | ||
|
||
const Error = () => { | ||
return ( | ||
<div className={"h-full flex flex-col items-center justify-center space-y-4"}> | ||
<Image | ||
src={"/error.png"} | ||
height={230} | ||
width={300} | ||
alt="error" | ||
className={"dark:hidden object-cover"} | ||
priority | ||
layout="fixed" | ||
/> | ||
<Image | ||
src={"/error-dark.png"} | ||
height={230} | ||
width={300} | ||
layout="fixed" | ||
alt="error" | ||
className={"hidden dark:block object-cover"} | ||
priority | ||
loading="eager" | ||
/> | ||
<h2 className={"text-lg font-medium"}>Oops! Something went wrong</h2> | ||
<p className={"text-sm text-muted-foreground"}> | ||
We're sorry, but something went wrong. Please try again later. | ||
</p> | ||
|
||
<Button asChild> | ||
<Link href={"/documents"}>Go back home</Link> | ||
</Button> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Error; |
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,22 @@ | ||
import { useEffect, useState } from "react"; | ||
|
||
export const useOrigin = () => { | ||
const [mounted, setMounted] = useState<boolean>(false); | ||
/** | ||
* Determina el origen de la ventana actual. | ||
* Si la ventana no está definida, devuelve una cadena vacía. | ||
* evita el error de windows no definido en el entorno del server | ||
* | ||
* @returns {string} El origen de la ventana actual o una cadena vacía si no está disponible. | ||
*/ | ||
const origin = | ||
typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; | ||
|
||
useEffect(() => { | ||
setMounted(true); | ||
}, []); | ||
|
||
if (!mounted) return ""; | ||
|
||
return origin; | ||
}; |