Files
markone/packages/web/src/app/bookmarks/-dialogs/edit-bookmark-dialog.tsx

105 lines
2.9 KiB
TypeScript

import type { Bookmark, Tag } from "@markone/core"
import { useId, useRef } from "react"
import { useBookmarkTags, useUpdateBookmark } from "~/bookmark/api"
import { Button } from "~/components/button"
import { Dialog, DialogActionRow, DialogBody, DialogTitle } from "~/components/dialog"
import { FormField } from "~/components/form-field"
import { LoadingSpinner } from "~/components/loading-spinner"
import { Message, MessageVariant } from "~/components/message.tsx"
import { TagsInput, type TagsInputRef } from "~/components/tags-input"
import { useBookmarkPageStore } from "../-store"
function EditBookmarkDialog({ bookmark }: { bookmark: Bookmark }) {
const closeDialog = useBookmarkPageStore((state) => state.closeDialog)
const { data: tags, status } = useBookmarkTags(bookmark)
const editFormId = useId()
function content() {
switch (status) {
case "pending":
return (
<p>
Loading <LoadingSpinner />
</p>
)
case "success":
return <EditForm formId={editFormId} bookmark={bookmark} tags={tags} />
case "error":
return null
}
}
return (
<Dialog>
<DialogTitle>EDIT BOOKMARK</DialogTitle>
<DialogBody>{content()}</DialogBody>
<DialogActionRow>
<Button type="submit" form={editFormId} disabled={status !== "success"}>
<span className="underline">S</span>AVE
</Button>
<Button disabled={status !== "success"} onClick={closeDialog}>
<span className="underline">C</span>ANCEL
</Button>
</DialogActionRow>
</Dialog>
)
}
function EditForm({ formId, bookmark, tags }: { formId: string; bookmark: Bookmark; tags: Tag[] }) {
const tagsInputRef = useRef<TagsInputRef>(null)
const updateBookmarkMutation = useUpdateBookmark(bookmark)
const closeDialog = useBookmarkPageStore((state) => state.closeDialog)
async function onSubmit(event: React.FormEvent<HTMLFormElement>) {
if (tagsInputRef.current) {
event.preventDefault()
const form = new FormData(event.currentTarget)
const title = form.get("title")
const tags = tagsInputRef.current.tags
if (title && typeof title === "string") {
try {
await updateBookmarkMutation.mutateAsync({
title,
tags,
})
closeDialog()
} catch {}
}
}
}
function message() {
switch (updateBookmarkMutation.status) {
case "pending":
return (
<p>
Saving changes <LoadingSpinner />
</p>
)
case "error":
return <Message variant={MessageVariant.Error}>Error updating the bookmark!</Message>
default:
return null
}
}
return (
<>
{message()}
<form id={formId} onSubmit={onSubmit}>
<FormField
type="text"
name="title"
label="TITLE"
className="w-full"
defaultValue={bookmark.title}
labelClassName="bg-stone-300 dark:bg-stone-800"
/>
<TagsInput ref={tagsInputRef} initialValue={tags.map((tag) => tag.name).join(" ")} />
</form>
</>
)
}
export { EditBookmarkDialog }