diff --git a/app/attachment/[id]/not-found.tsx b/app/attachment/[id]/not-found.tsx new file mode 100644 index 0000000..b38ad72 --- /dev/null +++ b/app/attachment/[id]/not-found.tsx @@ -0,0 +1,18 @@ +import Link from 'next/link'; +import { FaceFrownIcon } from '@heroicons/react/24/outline'; + +export default function NotFound() { + return ( +
+ +

404 File Not Found

+

Could not find the requested attachment.

+ + Go Back + +
+ ); +} \ No newline at end of file diff --git a/app/attachment/[id]/route.tsx b/app/attachment/[id]/route.tsx new file mode 100644 index 0000000..866b557 --- /dev/null +++ b/app/attachment/[id]/route.tsx @@ -0,0 +1,27 @@ +import { fetchBillById } from '@/app/lib/fetchBillById'; +import { notFound } from 'next/navigation'; + +export async function GET(request: Request, { params:{ id } }: { params: { id:string } }) { + const [invoiceID, billID] = id.split('-'); + + const bill = await fetchBillById(invoiceID, billID); + + if(!bill?.attachment) { + notFound(); + } + + // convert fileContentsBase64 from Base64 string to binary string + const fileContentsBuffer = Buffer.from(bill.attachment.fileContentsBase64, 'base64'); + + // convert fileContentsBuffer to format that can be sent to the client + const fileContents = new Uint8Array(fileContentsBuffer); + + return new Response(fileContents, { + status: 200, + headers: { + 'Content-Type': "application/octet-stream", + 'Content-Disposition': `attachment; filename="${bill.attachment.fileName}"`, + 'Last-Modified': `${bill.attachment.fileLastModified}` + } + }); +} \ No newline at end of file diff --git a/app/bills/[id]/edit/page.tsx b/app/bills/[id]/edit/page.tsx index 85a120b..1525e25 100644 --- a/app/bills/[id]/edit/page.tsx +++ b/app/bills/[id]/edit/page.tsx @@ -1,38 +1,10 @@ import { PlainLocation, PlainBill, MongoLocation } from '@/app/lib/db-types'; +import { fetchBillById } from '@/app/lib/fetchBillById'; import clientPromise from '@/app/lib/mongodb'; import { BillEditForm } from '@/app/ui/BillEditForm'; import { ObjectId } from 'mongodb'; import { notFound } from 'next/navigation'; -const fetchBillById = async (locationID:string, billID:string) => { - const client = await clientPromise; - const db = client.db("rezije"); - - // find a location with the given locationID - const billLocation = await db.collection("lokacije").findOne({ _id: locationID }) - - if(!billLocation) { - console.log(`Location ${locationID} not found`); - return(null); - } - - // find a bill with the given billID - const mongoBill = billLocation?.bills.find(({ _id }) => _id.toString() === billID); - - if(!mongoBill) { - console.log('Bill not found'); - return(null); - } - - const { _id, ...billBase } = mongoBill; - - return({ - id: _id.toString(), - ...billBase - } as PlainBill); - -} - export default async function Page({ params:{ id } }: { params: { id:string } }) { const [invoiceID, billID] = id.split('-'); diff --git a/app/lib/actions.ts b/app/lib/actions.ts index 7cbe5f3..4e152cf 100644 --- a/app/lib/actions.ts +++ b/app/lib/actions.ts @@ -46,13 +46,14 @@ const serializeAttachment = async (billAttachment: File | null) => { return null; } - // convert the file contents to a base64 string + // convert the billAttachment file contents to format that can be stored in the database const fileContents = await billAttachment.arrayBuffer(); const fileContentsBase64 = Buffer.from(fileContents).toString('base64'); + // create an object to store the file in the database return({ - fileName: decodeURIComponent(fileName), + fileName, fileSize, fileType, fileLastModified, diff --git a/app/lib/fetchBillById.ts b/app/lib/fetchBillById.ts new file mode 100644 index 0000000..ea30b51 --- /dev/null +++ b/app/lib/fetchBillById.ts @@ -0,0 +1,31 @@ +import { PlainBill, MongoLocation } from '@/app/lib/db-types'; +import clientPromise from '@/app/lib/mongodb'; + +export const fetchBillById = async (locationID:string, billID:string) => { + const client = await clientPromise; + const db = client.db("rezije"); + + // find a location with the given locationID + const billLocation = await db.collection("lokacije").findOne({ _id: locationID }) + + if(!billLocation) { + console.log(`Location ${locationID} not found`); + return(null); + } + + // find a bill with the given billID + const mongoBill = billLocation?.bills.find(({ _id }) => _id.toString() === billID); + + if(!mongoBill) { + console.log('Bill not found'); + return(null); + } + + const { _id, ...billBase } = mongoBill; + + return({ + id: _id.toString(), + ...billBase + } as PlainBill); + +} \ No newline at end of file diff --git a/app/ui/BillEditForm.tsx b/app/ui/BillEditForm.tsx index 4f91f9f..3b61084 100644 --- a/app/ui/BillEditForm.tsx +++ b/app/ui/BillEditForm.tsx @@ -55,9 +55,9 @@ export const BillEditForm:FC = ({ invoiceID, bill: { id, name // attachment ? - + - {attachment.fileName} + {decodeURIComponent(attachment.fileName)} : null }