Compare commits

..

No commits in common. '19f4a2ebde3c8bd8f98bbddba70a5faca7cb07b6' and '4def1b5fc5ed091d769936382b101635e587fdbc' have entirely different histories.

@ -9,7 +9,6 @@ import clsx from 'clsx'
import { userSchema } from '@/types'
import { cookies } from 'next/headers'
import { getUser } from '@/lib/auth'
import { getBookmarkCategories } from '@/lib/utils'
export const metadata: Metadata = {
title: {
@ -41,10 +40,6 @@ export default async function RootLayout({
user = userSchema.parse(userData)
}
const bookmarkCategories = await getBookmarkCategories(
userData ? userData.id : null
)
return (
<html
lang='en'
@ -58,10 +53,7 @@ export default async function RootLayout({
<Providers
themeProps={{ attribute: 'class', defaultTheme: 'dark' }}>
<div className='relative flex h-screen flex-col'>
<Navbar
user={user}
categories={bookmarkCategories}
/>
<Navbar user={user} />
<main className='container mx-auto max-w-7xl flex-grow px-6 pt-16'>
{children}
</main>

@ -30,15 +30,9 @@ import { GithubIcon } from '@/components/icons'
import { Icon } from '@iconify/react'
import NewBookmarkForm from '@/components/newBookmarkForm'
import { usePathname, useRouter } from 'next/navigation'
import { BookmarkCategory, User } from '@/types'
import { User } from '@/types'
export const Navbar = ({
user,
categories,
}: {
user: User | null
categories: BookmarkCategory[]
}) => {
export const Navbar = ({ user }: { user: User | null }) => {
const pathname = usePathname()
const router = useRouter()
@ -101,7 +95,7 @@ export const Navbar = ({
<NavbarItem className='hidden gap-2 sm:flex'>
{pathname.startsWith('/dashboard') && (
<div className='mr-4'>
<NewBookmarkForm categories={categories} />
<NewBookmarkForm />
</div>
)}
<Link

@ -8,37 +8,30 @@ import {
ModalFooter,
useDisclosure,
} from '@nextui-org/modal'
import { Select, SelectSection, SelectItem } from '@nextui-org/select'
import { Selection } from '@nextui-org/react'
import {
Dropdown,
DropdownTrigger,
DropdownMenu,
DropdownItem,
} from '@nextui-org/dropdown'
import { Button } from '@nextui-org/button'
import { Input } from '@nextui-org/input'
import { Icon } from '@iconify/react'
import { ChevronDownIcon } from './ChevronDownIcon'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
import { Tab, Tabs } from '@nextui-org/tabs'
import { BookmarkCategory } from '@/types'
export default function NewBookmarkForm({
categories,
}: {
categories: BookmarkCategory[]
}) {
export default function NewBookmarkForm() {
const { isOpen, onOpen, onOpenChange } = useDisclosure()
const router = useRouter()
const onSubmit = () => {
if (selected === 'bookmark') submitBookmark()
else if (selected === 'bookmark_category') submitCategory()
else return
}
const submitBookmark = async () => {
const onSubmit = async () => {
const body = {
name,
link,
description,
url,
category_id: parseInt(value.currentKey),
category_id: selectedKey === 'Other' ? 2 : 1,
}
await fetch('/api/bookmark', {
method: 'POST',
@ -48,28 +41,12 @@ export default function NewBookmarkForm({
router.refresh()
}
const submitCategory = async () => {
const body = {
name: categoryName,
}
await fetch('/api/bookmark_category', {
method: 'POST',
body: JSON.stringify(body),
})
onOpenChange()
router.refresh()
}
const [selected, setSelected] = useState('bookmark')
const [name, setName] = useState('')
const [link, setLink] = useState('')
const [description, setDescription] = useState('')
const [url, setUrl] = useState('')
const [categoryName, setCategoryName] = useState('')
const [value, setValue] = useState<Selection>(new Set([]))
const [selectedKey, setSelectedKey] = useState('Other')
return (
<>
@ -90,95 +67,84 @@ export default function NewBookmarkForm({
onOpenChange={onOpenChange}
placement='center'
hideCloseButton>
<ModalContent>
<ModalContent
onKeyUp={(e) => {
if (e.key === 'Enter') onSubmit()
}}>
{(onClose) => (
<>
<ModalHeader className='flex gap-2'>
New Bookmark/Category
New Bookmark
<Icon
icon='mdi:bookmark-box'
fontSize={30}
/>
</ModalHeader>
<ModalBody className='gap-4'>
<Tabs
selectedKey={selected}
onSelectionChange={(key) =>
setSelected(key.toString())
}
fullWidth
color='primary'>
<Tab
key='bookmark'
title={'Bookmark'}>
<form className='flex flex-col gap-4'>
<Select
label='Select category'
placeholder='Select a category'
selectedKeys={value}
onSelectionChange={setValue}>
{categories.length > 0 ? (
categories.map(
(category) => (
<SelectItem
key={
category.id
}
value={
category.id
}>
{category.name}
</SelectItem>
)
)
) : (
<SelectItem
key={'test'}
value={'test'}>
{'test'}
</SelectItem>
)}
</Select>
<Input
autoFocus
label='Name'
placeholder='Enter Name'
variant='bordered'
value={name}
onChange={(event) => {
setName(event.target.value)
}}
/>
<Input
label='Url'
placeholder='Enter Url'
variant='bordered'
value={url}
onChange={(event) => {
setUrl(event.target.value)
}}
/>
</form>
</Tab>
<Tab
key='bookmark_category'
title={'Bookmark Category'}>
<form className='flex flex-col gap-4'>
<Input
autoFocus
label='Category Name'
placeholder='Enter Category Name'
variant='bordered'
value={categoryName}
onChange={(event) => {
setCategoryName(
event.target.value
)
}}
/>
</form>
</Tab>
</Tabs>
<Dropdown>
<DropdownTrigger className='flex justify-start'>
<Button
startContent={
<span className='text-default-400'>
Category:
</span>
}
endContent={
<ChevronDownIcon className='text-small' />
}
variant='flat'>
<div className='w-full text-start'>
{selectedKey}
</div>
</Button>
</DropdownTrigger>
<DropdownMenu
disallowEmptySelection
selectionMode='single'
selectedKeys={selectedKey}
disabledKeys={['disabled']}>
<DropdownItem
key='disabled'
className='capitalize'>
Select Category
</DropdownItem>
<DropdownItem
key='Coding'
onClick={() => {
setSelectedKey('Coding')
}}
className='capitalize'>
Coding
</DropdownItem>
<DropdownItem
key='Other'
onClick={() => {
setSelectedKey('Other')
}}
className='capitalize'>
Other
</DropdownItem>
</DropdownMenu>
</Dropdown>
<Input
autoFocus
label='Name'
placeholder='Enter Name'
variant='bordered'
value={name}
onChange={(event) => {
setName(event.target.value)
}}
/>
<Input
label='Url'
placeholder='Enter Url'
variant='bordered'
value={url}
onChange={(event) => {
setUrl(event.target.value)
}}
/>
</ModalBody>
<ModalFooter>
<Button

@ -1,6 +0,0 @@
ALTER TABLE "bookmark_categories" ALTER COLUMN "user_id" SET DEFAULT 0;--> statement-breakpoint
ALTER TABLE "bookmark_categories" ALTER COLUMN "user_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "bookmark_categories" ALTER COLUMN "name" SET DEFAULT 'Other';--> statement-breakpoint
ALTER TABLE "bookmark_categories" ALTER COLUMN "name" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "users" ALTER COLUMN "password" SET DEFAULT '';--> statement-breakpoint
ALTER TABLE "users" ALTER COLUMN "password" SET NOT NULL;

@ -1,214 +0,0 @@
{
"version": "5",
"dialect": "pg",
"id": "8ee9d2e6-45d6-45ac-8552-b3e40c39b90e",
"prevId": "bd1fa6fc-b40d-4d9a-b024-69acb0a34270",
"tables": {
"bookmarks": {
"name": "bookmarks",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"category_id": {
"name": "category_id",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"link": {
"name": "link",
"type": "text",
"primaryKey": false,
"notNull": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"url": {
"name": "url",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"bookmarks_user_id_users_id_fk": {
"name": "bookmarks_user_id_users_id_fk",
"tableFrom": "bookmarks",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"bookmark_categories": {
"name": "bookmark_categories",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'Other'"
}
},
"indexes": {},
"foreignKeys": {
"bookmark_categories_user_id_users_id_fk": {
"name": "bookmark_categories_user_id_users_id_fk",
"tableFrom": "bookmark_categories",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"session": {
"name": "session",
"schema": "",
"columns": {
"sessionToken": {
"name": "sessionToken",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_user_id_users_id_fk": {
"name": "session_user_id_users_id_fk",
"tableFrom": "session",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
}
}

@ -22,13 +22,6 @@
"when": 1692438117496,
"tag": "0002_unusual_nico_minoru",
"breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1693043001584,
"tag": "0003_same_texas_twister",
"breakpoints": true
}
]
}

@ -5,7 +5,7 @@ export const user = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name'),
email: text('email'),
hashedPassword: text('password').notNull().default(''),
hashedPassword: text('password').notNull(),
createdAt: timestamp('created_at'),
updatedAt: timestamp('updated_at'),
})
@ -38,11 +38,8 @@ export const bookmarkRelations = relations(bookmark, ({ one }) => ({
export const bookmarkCategory = pgTable('bookmark_categories', {
id: serial('id').primaryKey(),
userId: integer('user_id')
.references(() => user.id)
.notNull()
.default(0),
name: text('name').notNull().default('Other'),
userId: integer('user_id').references(() => user.id),
name: text('name'),
})
export const bookmarkCategoryRelations = relations(

@ -1,10 +0,0 @@
import { db } from './db'
export const getBookmarkCategories = async (user: number | null) => {
const bookmarkCategories = await db.query.bookmarkCategory.findMany({
where: (bookmarkCategory, { eq }) =>
eq(bookmarkCategory.userId, user ?? 0),
})
return bookmarkCategories
}

@ -22,8 +22,6 @@
"@nextui-org/link": "2.0.0",
"@nextui-org/modal": "^2.0.13",
"@nextui-org/navbar": "2.0.0",
"@nextui-org/react": "^2.1.5",
"@nextui-org/select": "^2.1.4",
"@nextui-org/snippet": "2.0.0",
"@nextui-org/switch": "2.0.0",
"@nextui-org/system": "2.0.0",

File diff suppressed because it is too large Load Diff

@ -34,12 +34,9 @@ export const newBookmarkCategorySchema = z.object({
export const bookmarkCategorySchema = z.object({
id: z.number(),
userId: z.number(),
...bookmarkCategory,
})
export type BookmarkCategory = z.infer<typeof bookmarkCategorySchema>
export const bookmarkCategoryWithBookmarksSchema = z.object({
id: z.number(),
...bookmarkCategory,

Loading…
Cancel
Save