Skip to content

Commit b2b6d7e

Browse files
committed
feat: collection management ui
1 parent 0981432 commit b2b6d7e

File tree

15 files changed

+221
-141
lines changed

15 files changed

+221
-141
lines changed

app/(protected)/admin/books/[id]/edit/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default async function EditBookPage({
1717
}) {
1818
const { id } = await params
1919

20-
await Verify({ from: `/libraries/${id}/edit` })
20+
await Verify({ from: `/admin/books/${id}/edit` })
2121

2222
const [bookRes] = await Promise.all([getBook({ id })])
2323

app/(protected)/admin/books/[id]/page.tsx

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
BreadcrumbSeparator,
88
} from '@/components/ui/breadcrumb'
99
import { getBook } from '@/lib/api/book'
10-
import { BookDown, Calendar, Hash, Library } from 'lucide-react'
10+
import { BookDown, Calendar, Hash, Library, Pen } from 'lucide-react'
1111
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
1212
import { ThreeDBook } from '@/components/books/three-d-book'
1313
import { Button } from '@/components/ui/button'
@@ -51,18 +51,11 @@ export default async function BookDetailsPage({
5151
{/* Book Cover */}
5252
<div className="lg:col-span-1 grid place-items-center gap-4">
5353
<ThreeDBook book={bookRes.data} />
54-
<Button
55-
className="w-full"
56-
disabled={!bookRes.data.stats?.is_available}
57-
>
58-
{true ? (
59-
<>
60-
<BookDown className="mr-2 h-4 w-4" />
61-
Borrow Book
62-
</>
63-
) : (
64-
'Currently Borrowed'
65-
)}
54+
<Button className="w-full" asChild>
55+
<Link href={`/admin/books/${bookRes.data.id}/edit`}>
56+
<Pen />
57+
Edit
58+
</Link>
6659
</Button>
6760
</div>
6861

app/(protected)/admin/collections/[id]/edit/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default async function EditCollectionPage({
2020
const [collectionRes] = await Promise.all([getCollection(id)])
2121

2222
if ('error' in collectionRes) {
23-
console.log({ libRes: collectionRes })
23+
console.log(collectionRes)
2424
return <div>{JSON.stringify(collectionRes.message)}</div>
2525
}
2626

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ListBook } from '@/components/books/ListBook'
2-
import { BtnDeleteCollection } from '@/components/collections/BtnDeleteCollection'
1+
import { FormManageCollectionBooks } from '@/components/collections/FormManageCollectionBooks'
32
import {
43
Breadcrumb,
54
BreadcrumbItem,
@@ -8,21 +7,9 @@ import {
87
BreadcrumbPage,
98
BreadcrumbSeparator,
109
} from '@/components/ui/breadcrumb'
11-
import { Button } from '@/components/ui/button'
12-
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
13-
import { deleteCollectionAction } from '@/lib/actions/collection'
10+
import { Card } from '@/components/ui/card'
1411
import { getCollection, getListCollectionBooks } from '@/lib/api/collection'
15-
import {
16-
BookOpen,
17-
Calendar,
18-
Edit,
19-
Library,
20-
Plus,
21-
Settings,
22-
Users,
23-
} from 'lucide-react'
24-
import Image from 'next/image'
25-
import Link from 'next/link'
12+
import { Book } from 'lucide-react'
2613

2714
export default async function CollectionManageBooksPage({
2815
params,
@@ -34,7 +21,7 @@ export default async function CollectionManageBooksPage({
3421
const { id } = await params
3522

3623
const [collectionRes, bookRes] = await Promise.all([
37-
getCollection(id),
24+
getCollection(id, { include_book_ids: 'true' }),
3825
getListCollectionBooks(id, {
3926
include_book: 'true',
4027
}),
@@ -73,32 +60,24 @@ export default async function CollectionManageBooksPage({
7360

7461
{/* Books in Collection */}
7562
<div className="lg:col-span-3">
76-
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
77-
{bookRes.data.map((collectionBook) => (
78-
<ListBook book={collectionBook.book!} key={collectionBook.id} />
79-
))}
80-
</div>
81-
82-
{collectionRes.data.book_count === 0 && (
83-
<Card className="p-12 text-center">
84-
<BookOpen className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
85-
<h3 className="text-lg font-medium mb-2">
86-
No books in this collection
87-
</h3>
88-
<p className="text-muted-foreground mb-4">
89-
Start building your collection by adding some books.
90-
</p>
91-
<Button asChild>
92-
<Link
93-
href={`/admin/collections/${collectionRes.data.id}/manage-books`}
94-
>
95-
<Plus className="mr-2 h-4 w-4" />
96-
Add Books
97-
</Link>
98-
</Button>
99-
</Card>
100-
)}
63+
<FormManageCollectionBooks
64+
initialBooks={bookRes.data.map((b) => b.book!)}
65+
libraryID={collectionRes.data.library_id}
66+
initialBookIDs={collectionRes.data.book_ids}
67+
/>
10168
</div>
69+
70+
{collectionRes.data.book_count === 0 && (
71+
<Card className="p-12 text-center">
72+
<Book className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
73+
<h3 className="text-lg font-medium mb-2">
74+
No books in this collection yet
75+
</h3>
76+
<p className="text-muted-foreground mb-4">
77+
Start building your collection by adding some books.
78+
</p>
79+
</Card>
80+
)}
10281
</div>
10382
)
10483
}

app/(protected)/admin/collections/[id]/page.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
1313
import { deleteCollectionAction } from '@/lib/actions/collection'
1414
import { getCollection, getListCollectionBooks } from '@/lib/api/collection'
1515
import {
16-
BookOpen,
16+
Book,
1717
Calendar,
1818
Edit,
1919
Library,
@@ -27,21 +27,20 @@ import Link from 'next/link'
2727
export default async function CollectionDetailsPage({
2828
params,
2929
}: {
30-
params: Promise<{ id: string }>
30+
params: Promise<{ id: string; title?: string }>
3131
}) {
32-
// const claims = await IsLoggedIn()
33-
34-
const { id } = await params
32+
const { id, title } = await params
3533

3634
const [collectionRes, bookRes] = await Promise.all([
3735
getCollection(id),
3836
getListCollectionBooks(id, {
3937
include_book: 'true',
38+
book_title: title,
4039
}),
4140
])
4241

4342
if ('error' in collectionRes) {
44-
console.log({ libRes: collectionRes })
43+
console.log(collectionRes)
4544
return <div>{JSON.stringify(collectionRes.message)}</div>
4645
}
4746

@@ -71,9 +70,9 @@ export default async function CollectionDetailsPage({
7170
</BreadcrumbList>
7271
</Breadcrumb>
7372

74-
<div className="relative aspect-[2] rounded-lg overflow-hidden mb-6">
73+
<div className="relative aspect-[2] rounded-lg mb-6">
7574
<Image
76-
src={collectionRes.data.cover?.path || '/book-placeholder.svg'}
75+
src={collectionRes.data.cover?.path ?? '/book-placeholder.svg'}
7776
alt={collectionRes.data.title}
7877
fill
7978
className="w-full h-full object-cover rounded-t"
@@ -93,7 +92,7 @@ export default async function CollectionDetailsPage({
9392
<span>{collectionRes.data.follower_count} followers</span>
9493
</div>
9594
<div className="flex items-center gap-1">
96-
<BookOpen className="h-4 w-4" />
95+
<Book className="h-4 w-4" />
9796
<span>{collectionRes.data.book_count} books</span>
9897
</div>
9998
</div>
@@ -150,7 +149,7 @@ export default async function CollectionDetailsPage({
150149
<span>{collectionRes.data.follower_count} followers</span>
151150
</div>
152151
<div className="flex items-center gap-2 text-sm">
153-
<BookOpen className="h-4 w-4 text-muted-foreground" />
152+
<Book className="h-4 w-4 text-muted-foreground" />
154153
<span>{bookRes.data.length} books</span>
155154
</div>
156155
<div className="flex items-center gap-2 text-sm">
@@ -183,13 +182,18 @@ export default async function CollectionDetailsPage({
183182

184183
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
185184
{bookRes.data.map((collectionBook) => (
186-
<ListBook book={collectionBook.book!} key={collectionBook.id} />
185+
<Link
186+
href={`/admin/books/${collectionBook.book?.id}`}
187+
key={collectionBook.id}
188+
>
189+
<ListBook book={collectionBook.book!} />
190+
</Link>
187191
))}
188192
</div>
189193

190194
{collectionRes.data.book_count === 0 && (
191195
<Card className="p-12 text-center">
192-
<BookOpen className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
196+
<Book className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
193197
<h3 className="text-lg font-medium mb-2">
194198
No books in this collection
195199
</h3>

app/(protected)/books/[id]/page.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,6 @@ export default async function BookDetailsPage({
5252
</Breadcrumb>
5353

5454
<DetailBook book={bookRes.data}>
55-
<Button className="w-full" disabled={!bookRes.data.stats?.is_available}>
56-
<>
57-
<BookDown className="mr-2 h-4 w-4" />
58-
Borrow Book
59-
</>
60-
</Button>
6155
<BtnWatchlist
6256
bookId={bookRes.data.id}
6357
isWatched={!!bookRes.data.watchlists?.[0]}

app/(protected)/collections/[id]/page.tsx

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,29 @@ import {
77
BreadcrumbPage,
88
BreadcrumbSeparator,
99
} from '@/components/ui/breadcrumb'
10-
import { Button } from '@/components/ui/button'
1110
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
1211
import { getCollection, getListCollectionBooks } from '@/lib/api/collection'
13-
import {
14-
BookOpen,
15-
Calendar,
16-
Edit,
17-
Heart,
18-
Library,
19-
Plus,
20-
Settings,
21-
Trash2,
22-
Users,
23-
} from 'lucide-react'
12+
import { Book, Calendar, Library, Users } from 'lucide-react'
2413
import Image from 'next/image'
2514
import Link from 'next/link'
2615

2716
export default async function CollectionDetailsPage({
2817
params,
18+
searchParams,
2919
}: {
3020
params: Promise<{ id: string }>
21+
searchParams: { title?: string }
3122
}) {
3223
// const claims = await IsLoggedIn()
3324

3425
const { id } = await params
26+
const { title } = searchParams
3527

3628
const [collectionRes, bookRes] = await Promise.all([
3729
getCollection(id),
3830
getListCollectionBooks(id, {
3931
include_book: 'true',
32+
book_title: title,
4033
}),
4134
])
4235

@@ -91,40 +84,13 @@ export default async function CollectionDetailsPage({
9184
<span>{collectionRes.data.follower_count} followers</span>
9285
</div>
9386
<div className="flex items-center gap-1">
94-
<BookOpen className="h-4 w-4" />
87+
<Book className="h-4 w-4" />
9588
<span>{collectionRes.data.book_count} books</span>
9689
</div>
9790
</div>
9891
</div>
9992
</div>
10093

101-
{/* Action Buttons */}
102-
{/* <div className="flex gap-2 mb-8 flex-wrap">
103-
<Button variant={true ? 'secondary' : 'default'}>
104-
<Heart className={`mr-2 h-4 w-4 ${true ? 'fill-current' : ''}`} />
105-
{true ? 'Following' : 'Follow'}
106-
</Button>
107-
<Button variant="outline" asChild>
108-
<Link href={`/collections/${collectionRes.data.id}/manage-books`}>
109-
<Settings className="mr-2 h-4 w-4" />
110-
Manage Books
111-
</Link>
112-
</Button>
113-
<Button variant="outline" asChild>
114-
<Link href={`/collections/${collectionRes.data.id}/edit`}>
115-
<Edit className="mr-2 h-4 w-4" />
116-
Edit
117-
</Link>
118-
</Button>
119-
<Button
120-
variant="outline"
121-
className="text-red-600 hover:text-red-700 bg-transparent"
122-
>
123-
<Trash2 className="mr-2 h-4 w-4" />
124-
Delete
125-
</Button>
126-
</div> */}
127-
12894
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
12995
{/* Collection Info */}
13096
<div className="lg:col-span-1">
@@ -149,7 +115,7 @@ export default async function CollectionDetailsPage({
149115
<span>{collectionRes.data.follower_count} followers</span>
150116
</div>
151117
<div className="flex items-center gap-2 text-sm">
152-
<BookOpen className="h-4 w-4 text-muted-foreground" />
118+
<Book className="h-4 w-4 text-muted-foreground" />
153119
<span>{bookRes.data.length} books</span>
154120
</div>
155121
<div className="flex items-center gap-2 text-sm">
@@ -170,37 +136,28 @@ export default async function CollectionDetailsPage({
170136
<div className="lg:col-span-3">
171137
<div className="flex justify-between items-center mb-6">
172138
<h2 className="text-2xl font-semibold">Books in Collection</h2>
173-
{/* <Button asChild>
174-
<Link href={`/collections/${collectionRes.data.id}/manage-books`}>
175-
<Plus className="mr-2 h-4 w-4" />
176-
Manage Books
177-
</Link>
178-
</Button> */}
179139
</div>
180140

181141
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
182142
{bookRes.data.map((collectionBook) => (
183-
<ListBook book={collectionBook.book!} key={collectionBook.id} />
143+
<Link
144+
href={`/books/${collectionBook.book?.id}`}
145+
key={collectionBook.id}
146+
>
147+
<ListBook book={collectionBook.book!} />
148+
</Link>
184149
))}
185150
</div>
186151

187152
{collectionRes.data.book_count === 0 && (
188153
<Card className="p-12 text-center">
189-
<BookOpen className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
154+
<Book className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
190155
<h3 className="text-lg font-medium mb-2">
191156
No books in this collection
192157
</h3>
193158
<p className="text-muted-foreground mb-4">
194-
Start building your collection by adding some books.
159+
Follow this collection to get updates when new books are added.
195160
</p>
196-
{/* <Button asChild>
197-
<Link
198-
href={`/collections/${collectionRes.data.id}/manage-books`}
199-
>
200-
<Plus className="mr-2 h-4 w-4" />
201-
Add Books
202-
</Link>
203-
</Button> */}
204161
</Card>
205162
)}
206163
</div>

app/(protected)/collections/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export default async function UserCollections({
110110
/>
111111
</div>
112112

113-
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
113+
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
114114
{res.data.map((col) => (
115115
<Link key={col.id} href={`/collections/${col.id}`} passHref>
116116
<ListCollection collection={col}>
@@ -121,6 +121,7 @@ export default async function UserCollections({
121121
backgroundColor: 'var(--accent-bg)',
122122
color: 'var(--accent-text)',
123123
}}
124+
disabled
124125
>
125126
<Heart className="mr-2 size-4" />
126127
Follow

0 commit comments

Comments
 (0)