1- import Link from 'next/link'
21import { IsLoggedIn , Verify } from '@/lib/firebase/firebase'
32import { getBorrow , getListBorrows } from '@/lib/api/borrow'
4- import { Badge } from '@/components/ui/badge'
5- import {
6- getSubscriptionStatus ,
7- isBorrowDue ,
8- isSubscriptionActive ,
9- } from '@/lib/utils'
10- import { BtnReturnBook } from '@/components/borrows/BtnReturnBorrow'
11- import Image from 'next/image'
12- import { Card , CardContent , CardHeader , CardTitle } from '@/components/ui/card'
13- import {
14- Book ,
15- Calendar ,
16- CalendarCheck ,
17- CalendarClock ,
18- CalendarX ,
19- Clock ,
20- CreditCard ,
21- Gavel ,
22- Library ,
23- Pen ,
24- Tally5 ,
25- User ,
26- UserCog ,
27- } from 'lucide-react'
28- import clsx from 'clsx'
29- import { differenceInDays } from 'date-fns'
303import { Borrow } from '@/lib/types/borrow'
4+ import { redirect , RedirectType } from 'next/navigation'
5+ import { DetailBorrow } from '@/components/borrows/DetailBorrow'
6+ import { BtnReturnBook } from '@/components/borrows/BtnReturnBorrow'
317import { Button } from '@/components/ui/button'
328import { BtnUndoReturn } from '@/components/borrows/BtnUndoReturn'
33- import { redirect , RedirectType } from 'next/navigation'
34- import { DateTime } from '@/components/common/DateTime'
35- import { ThreeDBook } from '@/components/books/three-d-book'
9+ import Link from 'next/link'
10+ import { Pen } from 'lucide-react'
3611
3712export default async function BorrowDetailsPage ( {
3813 params,
@@ -41,7 +16,7 @@ export default async function BorrowDetailsPage({
4116} ) {
4217 const { id } = await params
4318
44- const from = `/borrows/${ id } `
19+ const from = `/admin/ borrows/${ id } `
4520
4621 const headers = await Verify ( { from } )
4722
@@ -51,8 +26,6 @@ export default async function BorrowDetailsPage({
5126 return < div > { JSON . stringify ( borrowRes . message ) } </ div >
5227 }
5328
54- const isDue = isBorrowDue ( borrowRes . data )
55-
5629 const claim = await IsLoggedIn ( )
5730 if ( ! claim || ! claim . librarease ) {
5831 redirect ( `/login?from=${ encodeURIComponent ( from ) } ` , RedirectType . replace )
@@ -78,273 +51,29 @@ export default async function BorrowDetailsPage({
7851 prevBorrows = prevBorrowsRes . data
7952 }
8053
81- const isSuperAdmin = claim . librarease . role === 'SUPERADMIN'
82- const isAdmin = claim . librarease . role === 'ADMIN'
83- const isStaff = claim . librarease . admin_libs
84- . concat ( claim . librarease . staff_libs )
85- . includes ( borrowRes . data . subscription . membership . library_id )
86-
8754 return (
88- < >
89- < div className = "grid grid-cols-1 md:grid-cols-2 gap-4" >
90- < Card className = "md:row-span-2" >
91- < CardHeader >
92- < CardTitle > Book Information</ CardTitle >
93- </ CardHeader >
94- < CardContent className = "grid place-self-center md:place-self-auto md:grid-cols-2 gap-4" >
95- < Link href = { `/books/${ borrowRes . data . book . id } ` } >
96- { /* <Image
97- src={borrowRes.data.book?.cover ?? '/book-placeholder.svg'}
98- alt={borrowRes.data.book.title + "'s cover"}
99- width={256}
100- height={256}
101- className="rounded-md w-56 h-auto hover:shadow-md hover:scale-105 transition-transform"
102- priority
103- /> */ }
104- < ThreeDBook book = { borrowRes . data . book } />
105- </ Link >
106- < div >
107- < Link href = { `/books/${ borrowRes . data . book . id } ` } className = "link" >
108- < h2 className = "text-xl font-semibold" >
109- { borrowRes . data . book . title }
110- </ h2 >
111- </ Link >
112- < p className = "text-foreground/80" > { borrowRes . data . book . author } </ p >
113- < p className = "text-sm text-foreground/60" >
114- { borrowRes . data . book . code }
115- </ p >
116- </ div >
117- </ CardContent >
118- </ Card >
119-
120- < Card >
121- < CardHeader >
122- < CardTitle > User Information</ CardTitle >
123- </ CardHeader >
124- < CardContent className = "grid gap-2 grid-cols-[max-content_1fr] items-center" >
125- < User className = "size-4" />
126- < p >
127- < span className = "font-medium" > Name: </ span >
128- { /* <Link href={`/users/${borrowRes.data.subscription.user.id}`}> */ }
129- { borrowRes . data . subscription . user . name }
130- { /* </Link> */ }
131- </ p >
132- < Library className = "size-4" />
133- < p >
134- < span className = "font-medium" > Library: </ span >
135- < Link
136- className = "link"
137- href = { `/libraries/${ borrowRes . data . subscription . membership . library . id } ` }
138- >
139- { borrowRes . data . subscription . membership . library . name }
140- </ Link >
141- </ p >
142- { /* <CreditCard className="size-4" />
143- <p>
144- <span className="font-medium">Membership: </span>
145- {borrowRes.data.subscription.membership.name}
146- </p>
147- <Clock className="size-4" />
148- <p>
149- <span className="font-medium">Expires: </span>
150- {formatDate(borrowRes.data.subscription.expires_at)}
151- </p> */ }
152- </ CardContent >
153- </ Card >
154-
155- < Card >
156- < CardHeader >
157- < CardTitle > Borrow Details</ CardTitle >
158- </ CardHeader >
159- < CardContent className = "grid gap-2 grid-cols-[max-content_1fr] items-center" >
160- < UserCog className = "size-4 text-muted-foreground" />
161- < p >
162- < span className = "font-medium" > Staff: </ span >
163- { borrowRes . data . staff . name }
164-
165- { borrowRes . data . returning
166- ? '/ ' + borrowRes . data . returning . staff . name
167- : null }
168- </ p >
169-
170- < Calendar className = "size-4 text-muted-foreground" />
171- < p >
172- < span className = "font-medium" > Borrowed: </ span >
173- < DateTime
174- dateTime = { borrowRes . data . borrowed_at }
175- relative = { ! borrowRes . data . returning }
176- />
177- </ p >
178- { isDue ? (
179- < >
180- < Gavel className = "size-4 text-muted-foreground" />
181- < p >
182- < span className = "font-medium" > Fine Expected: </ span >
183- { differenceInDays (
184- borrowRes . data . returning
185- ? new Date ( borrowRes . data . returning . returned_at )
186- : new Date ( ) ,
187- new Date ( borrowRes . data . due_at )
188- ) +
189- ' x ' +
190- ( borrowRes . data . subscription . fine_per_day ?? 0 ) +
191- ' = ' +
192- differenceInDays (
193- borrowRes . data . returning
194- ? new Date ( borrowRes . data . returning . returned_at )
195- : new Date ( ) ,
196- new Date ( borrowRes . data . due_at )
197- ) *
198- ( borrowRes . data . subscription . fine_per_day ?? 0 ) +
199- ' Pts' }
200- </ p >
201- < CalendarX className = "size-4 text-destructive" />
202- </ >
203- ) : (
204- < CalendarClock className = "size-4 text-muted-foreground" />
205- ) }
206- < p className = { clsx ( { 'text-destructive' : isDue } ) } >
207- < span className = "font-medium" > Due: </ span >
208- < DateTime
209- dateTime = { borrowRes . data . due_at }
210- relative = { ! borrowRes . data . returning }
211- />
212- </ p >
213- { borrowRes . data . returning ? (
214- < >
215- < CalendarCheck className = "size-4 text-muted-foreground" />
216- < p >
217- < span className = "font-medium" > Returned: </ span >
218- < DateTime dateTime = { borrowRes . data . returning . returned_at } />
219- </ p >
220- < Gavel className = "size-4 text-muted-foreground" />
221- < p >
222- < span className = "font-medium" > Fine Received: </ span >
223- { borrowRes . data . returning . fine ?? '-' } Pts
224- </ p >
225- </ >
226- ) : null }
227- </ CardContent >
228- </ Card >
55+ < DetailBorrow borrow = { borrowRes . data } prevBorrows = { prevBorrows } >
56+ < div className = "bottom-0 sticky py-2 grid md:grid-cols-2 gap-2" >
57+ { borrowRes . data . returning ? (
58+ < BtnUndoReturn
59+ variant = "outline"
60+ className = "w-full backdrop-blur-md"
61+ borrow = { borrowRes . data }
62+ />
63+ ) : (
64+ < BtnReturnBook
65+ variant = "outline"
66+ className = "w-full"
67+ borrow = { borrowRes . data }
68+ />
69+ ) }
70+ < Button asChild >
71+ < Link href = { `./${ borrowRes . data . id } /edit` } className = "w-full" >
72+ < Pen />
73+ Edit
74+ </ Link >
75+ </ Button >
22976 </ div >
230- < Card >
231- < CardHeader >
232- < div className = "flex justify-between items-center" >
233- < CardTitle > Membership</ CardTitle >
234- < Badge
235- variant = {
236- isSubscriptionActive ( borrowRes . data . subscription )
237- ? 'default'
238- : 'secondary'
239- }
240- className = "capitalize"
241- >
242- { getSubscriptionStatus ( borrowRes . data . subscription ) }
243- </ Badge >
244- </ div >
245- </ CardHeader >
246- < CardContent className = "grid gap-2 grid-cols-[max-content_1fr] md:grid-cols-[max-content_1fr_max-content_1fr] items-center" >
247- < CreditCard className = "size-4" />
248- < p >
249- < span className = "font-medium" > Membership: </ span >
250- < Link
251- href = { `/subscriptions/${ borrowRes . data . subscription . id } ` }
252- className = "link"
253- >
254- { borrowRes . data . subscription . membership . name }
255- </ Link >
256- </ p >
257- < Clock className = "size-4" />
258- < p >
259- < span className = "font-medium" > Expires: </ span >
260- < DateTime dateTime = { borrowRes . data . subscription . expires_at } />
261- </ p >
262- < CalendarClock className = "size-4" />
263- < p >
264- < span className = "font-medium" > Borrow Period: </ span >
265- { borrowRes . data . subscription . loan_period } D
266- </ p >
267- < Tally5 className = "size-4" />
268- < p >
269- < span className = "font-medium" > Usage Limit: </ span >
270- { borrowRes . data . subscription . usage_limit ?? '-' }
271- </ p >
272- < Book className = "size-4" />
273- < p >
274- < span className = "font-medium" > Active Borrow Limit: </ span >
275- { borrowRes . data . subscription . active_loan_limit ?? '-' }
276- </ p >
277- < Gavel className = "size-4" />
278- < p >
279- < span className = "font-medium" > Fine per Day: </ span >
280- { borrowRes . data . subscription . fine_per_day ?? '-' } Pts
281- </ p >
282- < Calendar className = "size-4" />
283- < p >
284- < span className = "font-medium" > Purchased At: </ span >
285- < DateTime dateTime = { borrowRes . data . subscription . created_at } />
286- </ p >
287- </ CardContent >
288- </ Card >
289- { prevBorrows . length > 0 && (
290- < Card >
291- < CardHeader >
292- < CardTitle > Previous Borrows</ CardTitle >
293- </ CardHeader >
294- < CardContent className = "flex items-end overflow-x-scroll p-6 isolate" >
295- { prevBorrows . map ( ( b ) => (
296- < Link
297- href = { `/borrows/${ b . id } ` }
298- key = { b . id }
299- className = { clsx (
300- 'shrink-0 relative left-0 transition-all not-first-of-type:-ml-12 brightness-75' ,
301- 'hover:transition-all hover:-translate-y-4 hover:transform-none hover:brightness-100' ,
302- 'peer peer-hover:left-12 peer-hover:transition-all' ,
303- '[transform:perspective(800px)_rotateY(20deg)]' ,
304- {
305- 'z-10 -translate-y-4 brightness-100 transform-none' :
306- b . id === id ,
307- }
308- ) }
309- >
310- < Image
311- src = { b . book ?. cover ?? '/book-placeholder.svg' }
312- alt = { b . book . title + "'s cover" }
313- width = { 160 }
314- height = { 240 }
315- className = "shadow-md rounded-lg w-40 h-60 place-self-center object-cover"
316- />
317- </ Link >
318- ) ) }
319- </ CardContent >
320- </ Card >
321- ) }
322- { ( isSuperAdmin || isAdmin || isStaff ) && (
323- < div className = "bottom-0 sticky py-2 grid md:grid-cols-2 gap-2" >
324- { borrowRes . data . returning ? (
325- < BtnUndoReturn
326- variant = "outline"
327- className = "w-full backdrop-blur-md"
328- borrow = { borrowRes . data }
329- />
330- ) : (
331- < BtnReturnBook
332- variant = "outline"
333- className = "w-full"
334- borrow = { borrowRes . data }
335- />
336- ) }
337- < Button asChild >
338- < Link
339- href = { `/borrows/${ borrowRes . data . id } /edit` }
340- className = "w-full"
341- >
342- < Pen />
343- Edit
344- </ Link >
345- </ Button >
346- </ div >
347- ) }
348- </ >
77+ </ DetailBorrow >
34978 )
35079}
0 commit comments