Improve receipt scanning

This commit is contained in:
Sebastien Castiel
2024-01-30 20:07:46 -05:00
parent 4a9bf575bd
commit e6467b41fc
2 changed files with 151 additions and 21 deletions

105
package-lock.json generated
View File

@@ -1278,6 +1278,111 @@
"node": ">= 10" "node": ">= 10"
} }
}, },
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz",
"integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz",
"integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz",
"integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz",
"integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz",
"integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz",
"integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz",
"integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",

View File

@@ -28,7 +28,7 @@ import { useToast } from '@/components/ui/use-toast'
import { useMediaQuery } from '@/lib/hooks' import { useMediaQuery } from '@/lib/hooks'
import { formatExpenseDate } from '@/lib/utils' import { formatExpenseDate } from '@/lib/utils'
import { Category } from '@prisma/client' import { Category } from '@prisma/client'
import { ChevronRight, Loader2, Receipt } from 'lucide-react' import { ChevronRight, FileQuestion, Loader2, Receipt } from 'lucide-react'
import { getImageData, useS3Upload } from 'next-s3-upload' import { getImageData, useS3Upload } from 'next-s3-upload'
import Image from 'next/image' import Image from 'next/image'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
@@ -154,21 +154,27 @@ export function CreateFromReceiptButton({
</Button> </Button>
<div className="col-span-2"> <div className="col-span-2">
<strong>Title:</strong> <strong>Title:</strong>
<div>{receiptInfo?.title ?? '…'}</div> <div>{receiptInfo ? receiptInfo.title ?? <Unknown /> : '…'}</div>
</div> </div>
<div className="col-span-2"> <div className="col-span-2">
<strong>Category:</strong> <strong>Category:</strong>
<div> <div>
{receiptInfoCategory ? ( {receiptInfo ? (
<div className="flex items-center"> receiptInfoCategory ? (
<CategoryIcon <div className="flex items-center">
category={receiptInfoCategory} <CategoryIcon
className="inline w-4 h-4 mr-2" category={receiptInfoCategory}
/> className="inline w-4 h-4 mr-2"
<span className="mr-1">{receiptInfoCategory.grouping}</span> />
<ChevronRight className="inline w-3 h-3 mr-1" /> <span className="mr-1">
<span>{receiptInfoCategory.name}</span> {receiptInfoCategory.grouping}
</div> </span>
<ChevronRight className="inline w-3 h-3 mr-1" />
<span>{receiptInfoCategory.name}</span>
</div>
) : (
<Unknown />
)
) : ( ) : (
'' || '…' '' || '…'
)} )}
@@ -177,10 +183,14 @@ export function CreateFromReceiptButton({
<div> <div>
<strong>Amount:</strong> <strong>Amount:</strong>
<div> <div>
{receiptInfo?.amount ? ( {receiptInfo ? (
<> receiptInfo.amount ? (
{groupCurrency} {receiptInfo.amount.toFixed(2)} <>
</> {groupCurrency} {receiptInfo.amount.toFixed(2)}
</>
) : (
<Unknown />
)
) : ( ) : (
'…' '…'
)} )}
@@ -189,16 +199,22 @@ export function CreateFromReceiptButton({
<div> <div>
<strong>Date:</strong> <strong>Date:</strong>
<div> <div>
{receiptInfo?.date {receiptInfo ? (
? formatExpenseDate( receiptInfo.date ? (
formatExpenseDate(
new Date(`${receiptInfo?.date}T12:00:00.000Z`), new Date(`${receiptInfo?.date}T12:00:00.000Z`),
) )
: '…'} ) : (
<Unknown />
)
) : (
'…'
)}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<p>Youll be able to edit the expense information after creating it.</p> <p>Youll be able to edit the expense information next.</p>
<div className="text-center"> <div className="text-center">
<Button <Button
disabled={pending || !receiptInfo} disabled={pending || !receiptInfo}
@@ -217,7 +233,7 @@ export function CreateFromReceiptButton({
) )
}} }}
> >
Create expense Continue
</Button> </Button>
</div> </div>
</div> </div>
@@ -225,6 +241,15 @@ export function CreateFromReceiptButton({
) )
} }
function Unknown() {
return (
<div className="flex gap-1 items-center text-muted-foreground">
<FileQuestion className="w-4 h-4" />
<em>Unknown</em>
</div>
)
}
function CreateFromReceiptDialog({ function CreateFromReceiptDialog({
trigger, trigger,
title, title,