New feature: edit bookmark

master
TZGyn 2 years ago
parent fd3ba9e08d
commit b8701332c3
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

@ -1,4 +1,4 @@
import { newBookmarkSchema } from '@/types' import { bookmarkSchema, newBookmarkSchema } from '@/types'
import { NextRequest, NextResponse } from 'next/server' import { NextRequest, NextResponse } from 'next/server'
import { db, bookmark } from '@/lib/schema' import { db, bookmark } from '@/lib/schema'
import { eq } from 'drizzle-orm' import { eq } from 'drizzle-orm'
@ -23,6 +23,23 @@ export const POST = async (request: NextRequest) => {
return NextResponse.json(newBookmark.error) return NextResponse.json(newBookmark.error)
} }
export const PATCH = async (request: NextRequest) => {
const body = await request.json()
const updateBookmark = bookmarkSchema.safeParse(body)
if (updateBookmark.success) {
await db
.update(bookmark)
.set({ ...updateBookmark.data })
.where(eq(bookmark.id, updateBookmark.data.id))
return NextResponse.json({ message: 'Bookmark Updated' })
}
return NextResponse.json({ message: 'Invalid Bookmark' })
}
export const DELETE = async (request: NextRequest) => { export const DELETE = async (request: NextRequest) => {
const body = await request.json() const body = await request.json()

@ -1,6 +1,7 @@
import { BookmarkCard } from '@/components/bookmarkCard' import { BookmarkCard } from '@/components/bookmarkCard'
import { bookmarkSchema } from '@/types' import { bookmarkSchema } from '@/types'
import { db, bookmark } from '@/lib/schema' import { db, bookmark } from '@/lib/schema'
import EditBookmarkForm from '@/components/editBookmarkForm'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
export const fetchCache = 'force-no-store' export const fetchCache = 'force-no-store'
@ -17,6 +18,7 @@ export default async function DashboardPage() {
data={data} data={data}
/> />
))} ))}
<EditBookmarkForm />
</div> </div>
) )
} }

@ -1,19 +1,69 @@
"use client"; 'use client'
import * as React from "react"; import * as React from 'react'
import { NextUIProvider } from "@nextui-org/system"; import { NextUIProvider } from '@nextui-org/system'
import { ThemeProvider as NextThemesProvider } from "next-themes"; import { ThemeProvider as NextThemesProvider } from 'next-themes'
import { ThemeProviderProps } from "next-themes/dist/types"; import { ThemeProviderProps } from 'next-themes/dist/types'
import { Bookmark } from '@/types'
export interface ProvidersProps { export interface ProvidersProps {
children: React.ReactNode; children: React.ReactNode
themeProps?: ThemeProviderProps; themeProps?: ThemeProviderProps
} }
export type EditBookmarkContextContent = {
isEditBookmark: boolean
setIsEditBookmark: (c: boolean) => void
}
export const EditBookmarkContext =
React.createContext<EditBookmarkContextContent>({
isEditBookmark: false,
setIsEditBookmark: () => {},
})
export type BookmarkContextContent = {
bookmark: Bookmark
setBookmark: (c: Bookmark) => void
}
export const BookmarkContext = React.createContext<BookmarkContextContent>({
bookmark: {
id: 0,
name: '',
link: '',
description: '',
url: '',
},
setBookmark: () => {},
})
export function Providers({ children, themeProps }: ProvidersProps) { export function Providers({ children, themeProps }: ProvidersProps) {
const [isEditBookmark, setIsEditBookmark] = React.useState<boolean>(false)
const [bookmark, setBookmark] = React.useState<Bookmark>({
id: 0,
name: '',
link: '',
description: '',
url: '',
})
return ( return (
<NextUIProvider> <BookmarkContext.Provider
<NextThemesProvider {...themeProps}>{children}</NextThemesProvider> value={{
</NextUIProvider> bookmark,
); setBookmark,
}}>
<EditBookmarkContext.Provider
value={{
isEditBookmark,
setIsEditBookmark,
}}>
<NextUIProvider>
<NextThemesProvider {...themeProps}>
{children}
</NextThemesProvider>
</NextUIProvider>
</EditBookmarkContext.Provider>
</BookmarkContext.Provider>
)
} }

@ -14,9 +14,15 @@ import {
} from '@nextui-org/dropdown' } from '@nextui-org/dropdown'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import EditBookmarkForm from './editBookmarkForm'
import { type Bookmark } from '@/types' import { type Bookmark } from '@/types'
import { useContext } from 'react'
import { BookmarkContext, EditBookmarkContext } from '@/app/providers'
export const BookmarkCard = ({ data }: { data: Bookmark }) => { export const BookmarkCard = ({ data }: { data: Bookmark }) => {
const { setIsEditBookmark } = useContext(EditBookmarkContext)
const { bookmark, setBookmark } = useContext(BookmarkContext)
const router = useRouter() const router = useRouter()
const deleteBookmark = async (event: React.MouseEvent, id: Number) => { const deleteBookmark = async (event: React.MouseEvent, id: Number) => {
event.stopPropagation() event.stopPropagation()
@ -26,6 +32,10 @@ export const BookmarkCard = ({ data }: { data: Bookmark }) => {
}) })
router.refresh() router.refresh()
} }
const editBookmark = (selectedBookmark: Bookmark) => {
setBookmark({ ...bookmark, ...selectedBookmark })
setIsEditBookmark(true)
}
return ( return (
<> <>
<Card className='w-96 select-none'> <Card className='w-96 select-none'>
@ -55,6 +65,11 @@ export const BookmarkCard = ({ data }: { data: Bookmark }) => {
</Button> </Button>
</DropdownTrigger> </DropdownTrigger>
<DropdownMenu aria-label='Static Actions'> <DropdownMenu aria-label='Static Actions'>
<DropdownItem
key='edit'
onClick={() => editBookmark(data)}>
Edit Bookmark
</DropdownItem>
<DropdownItem <DropdownItem
key='delete' key='delete'
className='text-danger' className='text-danger'

@ -0,0 +1,122 @@
'use client'
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
} from '@nextui-org/modal'
import { Button } from '@nextui-org/button'
import { Input } from '@nextui-org/input'
import { Icon } from '@iconify/react'
import { useRouter } from 'next/navigation'
import { useContext, useState } from 'react'
import { Bookmark } from '@/types'
import { BookmarkContext, EditBookmarkContext } from '@/app/providers'
export default function EditBookmarkForm() {
const { isEditBookmark, setIsEditBookmark } =
useContext(EditBookmarkContext)
const { bookmark, setBookmark } = useContext(BookmarkContext)
const router = useRouter()
const onSubmit = async () => {
const body = bookmark
await fetch('/api/bookmark', {
method: 'PATCH',
body: JSON.stringify(body),
})
setIsEditBookmark(false)
router.refresh()
}
return (
<>
<Modal
isOpen={isEditBookmark}
onOpenChange={() => setIsEditBookmark(false)}
placement='top-center'
hideCloseButton>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className='flex gap-2'>
Edit Bookmark
<Icon
icon='mdi:bookmark-box'
fontSize={30}
/>
</ModalHeader>
<ModalBody className='gap-4'>
<Input
autoFocus
label='Name'
placeholder='Enter Name'
variant='bordered'
value={bookmark.name}
onChange={(event) => {
setBookmark({
...bookmark,
name: event.target.value,
})
}}
/>
<Input
label='Link'
placeholder='Enter Link'
variant='bordered'
value={bookmark.link}
onChange={(event) => {
setBookmark({
...bookmark,
link: event.target.value,
})
}}
/>
<Input
label='Description'
placeholder='Enter Desription'
variant='bordered'
value={bookmark.description}
onChange={(event) => {
setBookmark({
...bookmark,
description: event.target.value,
})
}}
/>
<Input
label='Url'
placeholder='Enter Url'
variant='bordered'
value={bookmark.url}
onChange={(event) => {
setBookmark({
...bookmark,
url: event.target.value,
})
}}
/>
</ModalBody>
<ModalFooter>
<Button
color='danger'
variant='flat'
onClick={onClose}>
Close
</Button>
<Button
color='primary'
onPress={onSubmit}>
Add
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</>
)
}
Loading…
Cancel
Save