@@ -15,15 +15,71 @@ import {
1515} from '@/components/ui/pagination'
1616import { getListBooks } from '@/lib/api/book'
1717import type { Metadata } from 'next'
18- import { SITE_NAME } from '@/lib/consts'
18+ import { REDIS_KEY_BOOK_PRINT_PREFIX , SITE_NAME } from '@/lib/consts'
1919import { Badge } from '@/components/ui/badge'
2020import { cookies } from 'next/headers'
2121import { Verify } from '@/lib/firebase/firebase'
2222import { BookSelectPanel } from '@/components/books/book-select-panel'
2323import { SearchInput } from '@/components/common/SearchInput'
24- import { Button } from '@/components/ui/button'
25- import Link from 'next/link'
26- import { QrCode } from 'lucide-react'
24+ import { cache } from '@/lib/redis-helpers'
25+ import { getBookImportTemplate } from '@/lib/book-utils'
26+
27+ async function onPrintAction (
28+ bookIDs : string [ ]
29+ ) : Promise < { key : string } | { error : string } > {
30+ 'use server'
31+
32+ // hash the key
33+ const hash = await crypto . subtle . digest (
34+ 'SHA-256' ,
35+ new TextEncoder ( ) . encode ( bookIDs . toSorted ( ) . join ( ',' ) )
36+ )
37+ const key = Array . from ( new Uint8Array ( hash ) )
38+ . map ( ( b ) => b . toString ( 16 ) . padStart ( 2 , '0' ) )
39+ . join ( '' )
40+ . slice ( 0 , 16 ) // Shorten to 16 characters
41+
42+ const success = await cache . set (
43+ `${ REDIS_KEY_BOOK_PRINT_PREFIX } :${ key } ` ,
44+ bookIDs ,
45+ 300
46+ )
47+ if ( ! success ) {
48+ return {
49+ error : 'Failed to store print data in cache' ,
50+ }
51+ }
52+ return { key }
53+ }
54+
55+ async function downloadImportTemplateAction (
56+ bookIDs : string [ ]
57+ ) : Promise < { csv : string } | { error : string } > {
58+ 'use server'
59+
60+ if ( ! bookIDs ) {
61+ return { error : 'No book IDs provided' }
62+ }
63+
64+ const cookieStore = await cookies ( )
65+ const cookieName = process . env . LIBRARY_COOKIE_NAME as string
66+ const libID = cookieStore . get ( cookieName ) ?. value
67+
68+ const res = await getListBooks (
69+ bookIDs ? { ids : bookIDs , library_id : libID } : { library_id : libID }
70+ )
71+ if ( 'error' in res ) {
72+ return { error : res . error }
73+ }
74+
75+ const csv = getBookImportTemplate ( res . data )
76+ if ( ! csv ) {
77+ return {
78+ error : 'Failed to generate CSV' ,
79+ }
80+ }
81+ return { csv }
82+ }
2783
2884export const metadata : Metadata = {
2985 title : `Books · ${ SITE_NAME } ` ,
@@ -100,15 +156,13 @@ export default async function BooksSelectPage({
100156 placeholder = "Search by title"
101157 name = "title"
102158 />
103- < Button variant = "outline" asChild >
104- < Link href = "/admin/books/print-qr" >
105- < QrCode className = "mr-2 h-4 w-4" />
106- Print QR Codes
107- </ Link >
108- </ Button >
109159 </ div >
110160
111- < BookSelectPanel books = { res . data } />
161+ < BookSelectPanel
162+ books = { res . data }
163+ onPrintAction = { onPrintAction }
164+ downloadImportTemplateAction = { downloadImportTemplateAction }
165+ />
112166
113167 < Pagination >
114168 < PaginationContent >
0 commit comments