Skip to content

Commit b4d18e1

Browse files
committed
feat: borrows & subscriptions advance filters
1 parent 7b76343 commit b4d18e1

File tree

10 files changed

+510
-30
lines changed

10 files changed

+510
-30
lines changed

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

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import { TabLink } from '@/components/borrows/TabLink'
2828
import { Badge } from '@/components/ui/badge'
2929
import { BtnReturnBook } from '@/components/borrows/BtnReturnBorrow'
3030
import { cookies } from 'next/headers'
31+
import { ModelFilter } from '@/components/common/ModelFilter'
32+
import { UserFilter, BookFilter, DateFilter } from '@/components/common/filters'
3133

3234
export const metadata: Metadata = {
3335
title: `Borrows · ${SITE_NAME}`,
@@ -40,12 +42,24 @@ export default async function Borrows({
4042
skip?: string
4143
limit?: string
4244
status?: string
45+
user_id?: string
46+
book_id?: string
47+
borrowed_at?: string
48+
due_at?: string
49+
returned_at?: string
50+
lost_at?: string
4351
}>
4452
}) {
4553
const sp = await searchParams
4654
const skip = Number(sp?.skip ?? 0)
4755
const limit = Number(sp?.limit ?? 20)
4856
const status = sp?.status as 'active' | 'overdue' | 'returned' | 'lost'
57+
const user_id = sp?.user_id
58+
const book_id = sp?.book_id
59+
const borrowed_at = sp?.borrowed_at
60+
const due_at = sp?.due_at
61+
const returned_at = sp?.returned_at
62+
const lost_at = sp?.lost_at
4963

5064
const headers = await Verify({
5165
from: '/admin/borrows',
@@ -63,6 +77,12 @@ export default async function Borrows({
6377
skip: skip,
6478
status,
6579
library_id: libID,
80+
user_id,
81+
book_id,
82+
borrowed_at,
83+
due_at,
84+
returned_at,
85+
lost_at,
6686
},
6787
{
6888
headers,
@@ -128,16 +148,36 @@ export default async function Borrows({
128148
</div>
129149
</nav>
130150

131-
<TabLink
132-
tabs={[
133-
{ name: 'All', href: '/admin/borrows' },
134-
{ name: 'Active', href: '/admin/borrows?status=active' },
135-
{ name: 'Overdue', href: '/admin/borrows?status=overdue' },
136-
{ name: 'Returned', href: '/admin/borrows?status=returned' },
137-
{ name: 'Lost', href: '/admin/borrows?status=lost' },
138-
]}
139-
activeHref={`/admin/borrows${status ? `?status=${status}` : ''}`}
140-
/>
151+
<div className="flex flex-col gap-2 md:flex-row justify-between">
152+
<TabLink
153+
tabs={[
154+
{ name: 'All', href: '/admin/borrows' },
155+
{ name: 'Active', href: '/admin/borrows?status=active' },
156+
{ name: 'Overdue', href: '/admin/borrows?status=overdue' },
157+
{ name: 'Returned', href: '/admin/borrows?status=returned' },
158+
{ name: 'Lost', href: '/admin/borrows?status=lost' },
159+
]}
160+
activeHref={`/admin/borrows${status ? `?status=${status}` : ''}`}
161+
/>
162+
163+
<ModelFilter
164+
filterKeys={[
165+
'user_id',
166+
'book_id',
167+
'borrowed_at',
168+
'due_at',
169+
'returned_at',
170+
'lost_at',
171+
]}
172+
>
173+
<UserFilter />
174+
<BookFilter />
175+
<DateFilter filterKey="borrowed_at" placeholder="Borrow Date" />
176+
<DateFilter filterKey="due_at" placeholder="Due Date" />
177+
<DateFilter filterKey="returned_at" placeholder="Returned Date" />
178+
<DateFilter filterKey="lost_at" placeholder="Lost Date" />
179+
</ModelFilter>
180+
</div>
141181

142182
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
143183
{res.data.map((borrow, idx) => (

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import { ListCardSubscription } from '@/components/subscriptions/ListCardSubscri
2323
import { TabLink } from '@/components/borrows/TabLink'
2424
import { Badge } from '@/components/ui/badge'
2525
import { cookies } from 'next/headers'
26+
import { ModelFilter } from '@/components/common/ModelFilter'
27+
import { DateFilter, UserFilter } from '@/components/common/filters'
2628

2729
export const metadata: Metadata = {
2830
title: `Subscriptions · ${SITE_NAME}`,
@@ -35,12 +37,16 @@ export default async function Subscriptions({
3537
skip?: number
3638
limit?: number
3739
status?: 'active' | 'expired'
40+
user_id?: string
41+
// subscribed_at?: string
3842
}>
3943
}) {
4044
const sp = await searchParams
4145
const skip = Number(sp?.skip ?? 0)
4246
const limit = Number(sp?.limit ?? 20)
4347
const status = sp?.status
48+
const user_id = sp?.user_id
49+
// const subscribed_at = sp?.subscribed_at
4450

4551
const headers = await Verify({
4652
from: '/admin/subscriptions',
@@ -58,6 +64,8 @@ export default async function Subscriptions({
5864
skip: skip,
5965
status,
6066
library_id: libID,
67+
user_id,
68+
// created_at: subscribed_at,
6169
},
6270
{
6371
headers,
@@ -103,15 +111,21 @@ export default async function Subscriptions({
103111
</Button>
104112
</div>
105113
</nav>
114+
<div className="flex flex-col gap-2 md:flex-row justify-between">
115+
<TabLink
116+
tabs={[
117+
{ name: 'All', href: '/admin/subscriptions' },
118+
{ name: 'Active', href: '/admin/subscriptions?status=active' },
119+
{ name: 'Expired', href: '/admin/subscriptions?status=expired' },
120+
]}
121+
activeHref={`/admin/subscriptions${status ? `?status=${status}` : ''}`}
122+
/>
106123

107-
<TabLink
108-
tabs={[
109-
{ name: 'All', href: '/admin/subscriptions' },
110-
{ name: 'Active', href: '/admin/subscriptions?status=active' },
111-
{ name: 'Expired', href: '/admin/subscriptions?status=expired' },
112-
]}
113-
activeHref={`/admin/subscriptions${status ? `?status=${status}` : ''}`}
114-
/>
124+
<ModelFilter filterKeys={['user_id']}>
125+
<UserFilter />
126+
{/* <DateFilter filterKey="created_at" placeholder="Subscribed Date" /> */}
127+
</ModelFilter>
128+
</div>
115129

116130
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
117131
{res.data.map((sub) => (

app/(protected)/borrows/page.tsx

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import type { Metadata } from 'next'
2121
import { SITE_NAME } from '@/lib/consts'
2222
import { TabLink } from '@/components/borrows/TabLink'
2323
import { Badge } from '@/components/ui/badge'
24+
import { ModelFilter } from '@/components/common/ModelFilter'
25+
import { BookFilter, DateFilter } from '@/components/common/filters'
2426

2527
export const metadata: Metadata = {
2628
title: `Borrows · ${SITE_NAME}`,
@@ -34,13 +36,23 @@ export default async function Borrows({
3436
limit?: string
3537
library_id?: string
3638
status?: string
39+
book_id?: string
40+
borrowed_at?: string
41+
due_at?: string
42+
returned_at?: string
43+
lost_at?: string
3744
}>
3845
}) {
3946
const sp = await searchParams
4047
const skip = Number(sp?.skip ?? 0)
4148
const limit = Number(sp?.limit ?? 20)
4249
const library_id = sp?.library_id
4350
const status = sp?.status as 'active' | 'overdue' | 'returned' | 'lost'
51+
const book_id = sp?.book_id
52+
const borrowed_at = sp?.borrowed_at
53+
const due_at = sp?.due_at
54+
const returned_at = sp?.returned_at
55+
const lost_at = sp?.lost_at
4456

4557
const headers = await Verify({
4658
from: '/borrows',
@@ -57,6 +69,11 @@ export default async function Borrows({
5769
status,
5870
...(library_id ? { library_id } : {}),
5971
user_id: claims?.librarease?.id,
72+
book_id,
73+
borrowed_at,
74+
due_at,
75+
returned_at,
76+
lost_at,
6077
},
6178
{
6279
headers,
@@ -105,16 +122,34 @@ export default async function Borrows({
105122
</div>
106123
</nav>
107124

108-
<TabLink
109-
tabs={[
110-
{ name: 'All', href: '/borrows' },
111-
{ name: 'Active', href: '/borrows?status=active' },
112-
{ name: 'Overdue', href: '/borrows?status=overdue' },
113-
{ name: 'Returned', href: '/borrows?status=returned' },
114-
{ name: 'Lost', href: '/borrows?status=lost' },
115-
]}
116-
activeHref={`/borrows${status ? `?status=${status}` : ''}`}
117-
/>
125+
<div className="flex flex-col gap-2 md:flex-row justify-between">
126+
<TabLink
127+
tabs={[
128+
{ name: 'All', href: '/borrows' },
129+
{ name: 'Active', href: '/borrows?status=active' },
130+
{ name: 'Overdue', href: '/borrows?status=overdue' },
131+
{ name: 'Returned', href: '/borrows?status=returned' },
132+
{ name: 'Lost', href: '/borrows?status=lost' },
133+
]}
134+
activeHref={`/borrows${status ? `?status=${status}` : ''}`}
135+
/>
136+
137+
<ModelFilter
138+
filterKeys={[
139+
'book_id',
140+
'borrowed_at',
141+
'due_at',
142+
'returned_at',
143+
'lost_at',
144+
]}
145+
>
146+
<BookFilter />
147+
<DateFilter filterKey="borrowed_at" placeholder="Borrow Date" />
148+
<DateFilter filterKey="due_at" placeholder="Due Date" />
149+
<DateFilter filterKey="returned_at" placeholder="Returned Date" />
150+
<DateFilter filterKey="lost_at" placeholder="Lost Date" />
151+
</ModelFilter>
152+
</div>
118153

119154
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
120155
{res.data.map((borrow, idx) => (

app/(protected)/notifications/page.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { readAllNotificationsAction } from '@/lib/actions/notification'
2323
import { TabLink } from '@/components/borrows/TabLink'
2424
import { CheckCircle } from 'lucide-react'
2525
import { Notification } from '@/components/notifications/Notification'
26+
import { Badge } from '@/components/ui/badge'
2627

2728
export const metadata: Metadata = {
2829
title: `Notifications · ${SITE_NAME}`,
@@ -78,7 +79,12 @@ export default async function Notifications({
7879
<BreadcrumbSeparator />
7980

8081
<BreadcrumbItem>
81-
<BreadcrumbPage>Notifications</BreadcrumbPage>
82+
<BreadcrumbPage>
83+
Notifications
84+
<Badge className="ml-4" variant="outline">
85+
{res.meta.total}
86+
</Badge>
87+
</BreadcrumbPage>
8288
</BreadcrumbItem>
8389
</BreadcrumbList>
8490
</Breadcrumb>

0 commit comments

Comments
 (0)