Skip to content

Commit 14c8595

Browse files
committed
feat: collection enhancement
1 parent 6ac0043 commit 14c8595

File tree

17 files changed

+402
-160
lines changed

17 files changed

+402
-160
lines changed

.vscode/launch.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
"name": "Launch Chrome against localhost",
1111
"url": "http://localhost:3000",
1212
"webRoot": "${workspaceFolder}"
13+
},
14+
{
15+
"type": "node-terminal",
16+
"request": "launch",
17+
"name": "Run Script: devs",
18+
"command": "yarn devs",
19+
"cwd": "${workspaceFolder}"
1320
}
1421
]
1522
}

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,23 @@ import {
99
} from '@/components/ui/breadcrumb'
1010
import { updateCollectionAction } from '@/lib/actions/collection'
1111
import { getCollection } from '@/lib/api/collection'
12+
import { Verify } from '@/lib/firebase/firebase'
1213

1314
export default async function EditCollectionPage({
1415
params,
1516
}: {
1617
params: Promise<{ id: string }>
1718
}) {
1819
const { id } = await params
20+
const headers = await Verify({ from: `/admin/collections/${id}/edit` })
1921

20-
const [collectionRes] = await Promise.all([getCollection(id)])
22+
const [collectionRes] = await Promise.all([
23+
getCollection(
24+
id,
25+
{ include_books: 'true', include_stats: 'true' },
26+
{ headers }
27+
),
28+
])
2129

2230
if ('error' in collectionRes) {
2331
console.log(collectionRes)
@@ -26,7 +34,7 @@ export default async function EditCollectionPage({
2634

2735
return (
2836
<div className="space-y-4">
29-
<h1 className="text-2xl font-semibold">New Collection</h1>
37+
<h1 className="text-2xl font-semibold">Edit Collection</h1>
3038
<Breadcrumb>
3139
<BreadcrumbList>
3240
<BreadcrumbItem>
@@ -47,12 +55,16 @@ export default async function EditCollectionPage({
4755

4856
<FormCollection
4957
initialData={{
58+
id: collectionRes.data.id,
5059
library_id: collectionRes.data.library_id,
5160
title: collectionRes.data.title,
52-
cover: collectionRes.data.cover?.path,
61+
cover: collectionRes.data.cover,
5362
description: collectionRes.data.description,
5463
}}
55-
onSubmit={updateCollectionAction.bind(null, collectionRes.data.id)}
64+
onSubmitAction={updateCollectionAction.bind(
65+
null,
66+
collectionRes.data.id
67+
)}
5668
/>
5769
</div>
5870
)

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
PaginationPrevious,
2121
} from '@/components/ui/pagination'
2222
import { Route } from 'next'
23+
import { Verify } from '@/lib/firebase/firebase'
2324

2425
export default async function CollectionManageBooksPage({
2526
params,
@@ -33,8 +34,16 @@ export default async function CollectionManageBooksPage({
3334
const skip = Number(sp?.skip ?? 0)
3435
const limit = Number(sp?.limit ?? 20)
3536

37+
const headers = await Verify({
38+
from: `/admin/collections/${id}/manage-books`,
39+
})
40+
3641
const [collectionRes, colBookRes] = await Promise.all([
37-
getCollection(id, { include_book_ids: 'true' }),
42+
getCollection(
43+
id,
44+
{ include_book_ids: 'true', include_stats: 'true' },
45+
{ headers }
46+
),
3847
getListCollectionBooks(id, {
3948
include_book: 'true',
4049
}),

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

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Button } from '@/components/ui/button'
1212
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
1313
import { deleteCollectionAction } from '@/lib/actions/collection'
1414
import { getCollection, getListCollectionBooks } from '@/lib/api/collection'
15+
import { Verify } from '@/lib/firebase/firebase'
1516
import {
1617
Book,
1718
Calendar,
@@ -30,9 +31,10 @@ export default async function CollectionDetailsPage({
3031
params: Promise<{ id: string; title?: string }>
3132
}) {
3233
const { id, title } = await params
34+
const headers = await Verify({ from: `/admin/collections/${id}` })
3335

3436
const [collectionRes, bookRes] = await Promise.all([
35-
getCollection(id),
37+
getCollection(id, { include_stats: 'true' }, { headers }),
3638
getListCollectionBooks(id, {
3739
include_book: 'true',
3840
book_title: title,
@@ -72,7 +74,7 @@ export default async function CollectionDetailsPage({
7274

7375
<div className="relative aspect-[2] rounded-lg mb-6">
7476
<Image
75-
src={collectionRes.data.cover?.path ?? '/book-placeholder.svg'}
77+
src={collectionRes.data.cover ?? '/book-placeholder.svg'}
7678
alt={collectionRes.data.title}
7779
fill
7880
className="w-full h-full object-cover rounded-t"
@@ -168,18 +170,6 @@ export default async function CollectionDetailsPage({
168170

169171
{/* Books in Collection */}
170172
<div className="lg:col-span-3">
171-
<div className="flex justify-between items-center mb-6">
172-
<h2 className="text-2xl font-semibold">Books in Collection</h2>
173-
<Button asChild>
174-
<Link
175-
href={`/admin/collections/${collectionRes.data.id}/manage-books`}
176-
>
177-
<Plus className="mr-2 h-4 w-4" />
178-
Manage Books
179-
</Link>
180-
</Button>
181-
</div>
182-
183173
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
184174
{bookRes.data.map((collectionBook) => (
185175
<Link

app/(protected)/admin/collections/new/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default async function NewCollectionPage() {
4141
library_id: activeLibraryID ?? '',
4242
title: '',
4343
}}
44-
onSubmit={createCollectionAction}
44+
onSubmitAction={createCollectionAction}
4545
/>
4646
</div>
4747
)

app/(protected)/admin/collections/page.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { Button } from '@/components/ui/button'
2323
import { getListCollections } from '@/lib/api/collection'
2424
import { ListCollection } from '@/components/collections/ListCollection'
2525
import { SearchInput } from '@/components/common/SearchInput'
26+
import { colorsToCssVars } from '@/lib/utils/color-utils'
2627

2728
export const metadata: Metadata = {
2829
title: `Collections · ${SITE_NAME}`,
@@ -50,12 +51,13 @@ export default async function UserCollections({
5051
skip: skip,
5152
title: sp?.title,
5253
include_library: 'true',
54+
include_stats: 'true',
5355
...(library_id ? { library_id } : {}),
5456
} as const
5557

56-
await Verify({ from: '/admin/collections' })
58+
const headers = await Verify({ from: '/admin/collections' })
5759

58-
const res = await getListCollections(query)
60+
const res = await getListCollections(query, { headers })
5961

6062
if ('error' in res) {
6163
console.log(res)
@@ -112,7 +114,10 @@ export default async function UserCollections({
112114
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
113115
{res.data.map((col) => (
114116
<Link key={col.id} href={`/admin/collections/${col.id}`} passHref>
115-
<ListCollection collection={col} />
117+
<ListCollection
118+
collection={col}
119+
style={colorsToCssVars(col.colors)}
120+
/>
116121
</Link>
117122
))}
118123
</div>

app/(protected)/admin/page.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,11 @@ export default async function LibraryDashboard() {
7171
return (
7272
<main className="min-h-[calc(100vh-4rem)] p-8">
7373
<div className="max-w-2xl mx-auto space-y-4">
74-
<div className="flex justify-between items-center">
75-
<h1 className="text-2xl font-bold">Librarease</h1>
76-
<div className="flex items-center gap-2">
77-
<Button variant="ghost" onClick={logoutAction}>
78-
Logout
79-
</Button>
80-
<ModeToggle />
81-
</div>
74+
<div className="place-self-end flex items-center gap-2">
75+
<Button variant="ghost" onClick={logoutAction}>
76+
Logout
77+
</Button>
78+
<ModeToggle />
8279
</div>
8380
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
8481
{menuItems.map((item) => {

app/(protected)/admin/reviews/page.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ export default async function ReviewsPage({
9898
/>
9999
</div>
100100
</Link>
101-
<Link href={`/admin/borrows/${review.borrowing_id}`}>
101+
<Link
102+
className="grow"
103+
href={`/admin/borrows/${review.borrowing_id}`}
104+
>
102105
<div className="space-y-4">
103106
<div className="flex flex-col md:flex-row md:justify-between">
104107
<div>

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { getCollection, getListCollectionBooks } from '@/lib/api/collection'
1212
import { Book, Calendar, Library, Users } from 'lucide-react'
1313
import Image from 'next/image'
1414
import Link from 'next/link'
15+
import { FollowCollectionButton } from '@/components/collections/FollowCollectionButton'
16+
import { Verify } from '@/lib/firebase/firebase'
1517

1618
export default async function CollectionDetailsPage({
1719
params,
@@ -20,13 +22,17 @@ export default async function CollectionDetailsPage({
2022
params: Promise<{ id: string }>
2123
searchParams: { title?: string }
2224
}) {
23-
// const claims = await IsLoggedIn()
24-
2525
const { id } = await params
2626
const { title } = searchParams
2727

28+
const headers = await Verify({ from: `/collections/${id}` })
29+
2830
const [collectionRes, bookRes] = await Promise.all([
29-
getCollection(id),
31+
getCollection(
32+
id,
33+
{ include_stats: 'true', include_book_ids: 'true' },
34+
{ headers }
35+
),
3036
getListCollectionBooks(id, {
3137
include_book: 'true',
3238
book_title: title,
@@ -64,7 +70,7 @@ export default async function CollectionDetailsPage({
6470

6571
<div className="relative aspect-[2] rounded-lg overflow-hidden mb-6">
6672
<Image
67-
src={collectionRes.data.cover?.path || '/book-placeholder.svg'}
73+
src={collectionRes.data.cover || '/book-placeholder.svg'}
6874
alt={collectionRes.data.title}
6975
fill
7076
className="w-full h-full object-cover rounded-t"
@@ -88,6 +94,13 @@ export default async function CollectionDetailsPage({
8894
<span>{collectionRes.data.book_count} books</span>
8995
</div>
9096
</div>
97+
<div className="mt-4">
98+
<FollowCollectionButton
99+
collectionId={collectionRes.data.id}
100+
initialIsFollowed={!!collectionRes.data.stats?.followed_at}
101+
className="w-auto h-9 px-4 text-sm font-medium"
102+
/>
103+
</div>
91104
</div>
92105
</div>
93106

@@ -134,10 +147,6 @@ export default async function CollectionDetailsPage({
134147

135148
{/* Books in Collection */}
136149
<div className="lg:col-span-3">
137-
<div className="flex justify-between items-center mb-6">
138-
<h2 className="text-2xl font-semibold">Books in Collection</h2>
139-
</div>
140-
141150
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
142151
{bookRes.data.map((collectionBook) => (
143152
<Link

app/(protected)/collections/page.tsx

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ import {
1616
import Link from 'next/link'
1717
import type { Metadata } from 'next'
1818
import { SITE_NAME } from '@/lib/consts'
19-
import { BellRing, Heart } from 'lucide-react'
19+
import { BellRing } from 'lucide-react'
2020
import { Badge } from '@/components/ui/badge'
2121
import { Verify } from '@/lib/firebase/firebase'
2222
import { Button } from '@/components/ui/button'
2323
import { getListCollections } from '@/lib/api/collection'
2424
import { ListCollection } from '@/components/collections/ListCollection'
2525
import { SearchInput } from '@/components/common/SearchInput'
26+
import { FollowCollectionButton } from '@/components/collections/FollowCollectionButton'
27+
import { colorsToCssVars } from '@/lib/utils/color-utils'
2628

2729
export const metadata: Metadata = {
2830
title: `Collections · ${SITE_NAME}`,
@@ -50,12 +52,13 @@ export default async function UserCollections({
5052
skip: skip,
5153
title: sp?.title,
5254
include_library: 'true',
55+
include_stats: 'true',
5356
...(library_id ? { library_id } : {}),
5457
} as const
5558

56-
await Verify({ from: '/collections' })
59+
const headers = await Verify({ from: '/collections' })
5760

58-
const res = await getListCollections(query)
61+
const res = await getListCollections(query, { headers })
5962

6063
if ('error' in res) {
6164
console.log(res)
@@ -89,14 +92,6 @@ export default async function UserCollections({
8992
</BreadcrumbItem>
9093
</BreadcrumbList>
9194
</Breadcrumb>
92-
<Button variant="secondary" asChild>
93-
<Link href="/collections/watchlist">
94-
<>
95-
<BellRing className="mr-2 h-4 w-4" />
96-
Followings
97-
</>
98-
</Link>
99-
</Button>
10095
</div>
10196
</nav>
10297

@@ -111,19 +106,15 @@ export default async function UserCollections({
111106
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
112107
{res.data.map((col) => (
113108
<Link key={col.id} href={`/collections/${col.id}`} passHref>
114-
<ListCollection collection={col}>
115-
<Button
116-
size="sm"
117-
className="w-full"
118-
style={{
119-
backgroundColor: 'var(--accent-bg)',
120-
color: 'var(--accent-text)',
121-
}}
122-
disabled
123-
>
124-
<Heart className="mr-2 size-4" />
125-
Follow
126-
</Button>
109+
<ListCollection
110+
collection={col}
111+
style={colorsToCssVars(col.colors)}
112+
>
113+
<FollowCollectionButton
114+
collectionId={col.id}
115+
initialIsFollowed={!!col.stats?.followed_at}
116+
className="bg-(--color-vibrant,var(--color-primary)) hover:bg-(--color-dark-muted,var(--color-muted-foreground)) dark:hover:bg-(--color-light-muted,var(--color-muted-foreground))"
117+
/>
127118
</ListCollection>
128119
</Link>
129120
))}

0 commit comments

Comments
 (0)