From 6d6f59c99a867f9d27ebc620517fd05adbd82e6a Mon Sep 17 00:00:00 2001
From: AmandeepMandal1077 <2023kucp1077@iiitkota.ac.in>
Date: Sat, 11 Oct 2025 01:20:54 +0530
Subject: [PATCH 1/5] added editing for ocr extracted receipt
---
backend/controllers/receiptController.js | 66 ++++++++---
backend/routes/receiptRoutes.js | 3 +-
frontend/src/pages/ReceiptsPage.jsx | 141 +++++++++++++++++++++--
3 files changed, 188 insertions(+), 22 deletions(-)
diff --git a/backend/controllers/receiptController.js b/backend/controllers/receiptController.js
index 4ad7c54..21c4fb7 100644
--- a/backend/controllers/receiptController.js
+++ b/backend/controllers/receiptController.js
@@ -59,19 +59,6 @@ const uploadReceipt = async (req, res) => {
const savedReceipt = await newReceipt.save();
- // Automatically create a corresponding expense transaction
- if (savedReceipt) {
- const newTransaction = new IncomeExpense({
- user: req.user.id,
- name: savedReceipt.extractedData.merchant,
- category: savedReceipt.extractedData.category,
- cost: savedReceipt.extractedData.amount,
- addedOn: savedReceipt.extractedData.date,
- isIncome: false,
- });
- await newTransaction.save();
- }
-
res.status(201).json(savedReceipt);
} catch (error) {
@@ -83,6 +70,59 @@ const uploadReceipt = async (req, res) => {
}
};
+// @desc Save transaction after user confirmation and edits
+// @route POST /api/receipts/save-transaction
+// @access Private
+const saveTransactionFromReceipt = async (req, res) => {
+ try {
+ const { receiptId, transactionData } = req.body;
+
+ // Validate required fields
+ if (!receiptId || !transactionData) {
+ return res.status(400).json({ message: 'Receipt ID and transaction data are required' });
+ }
+
+ // Verify the receipt belongs to the user
+ const receipt = await Receipt.findOne({ _id: receiptId, user: req.user.id });
+ if (!receipt) {
+ return res.status(404).json({ message: 'Receipt not found' });
+ }
+
+ // Create the transaction with user-confirmed data
+ const newTransaction = new IncomeExpense({
+ user: req.user.id,
+ name: transactionData.name,
+ category: transactionData.category,
+ cost: transactionData.cost,
+ addedOn: new Date(transactionData.addedOn),
+ isIncome: transactionData.isIncome || false,
+ });
+
+ const savedTransaction = await newTransaction.save();
+
+ // update the receipt with the final confirmed data
+ receipt.extractedData = {
+ merchant: transactionData.name,
+ amount: transactionData.cost,
+ category: transactionData.category,
+ date: new Date(transactionData.addedOn),
+ isIncome: transactionData.isIncome || false,
+ };
+ await receipt.save();
+
+ res.status(201).json({
+ message: 'Transaction saved successfully',
+ transaction: savedTransaction,
+ receipt: receipt
+ });
+
+ } catch (error) {
+ console.error('Error saving transaction:', error);
+ res.status(500).json({ message: 'Failed to save transaction', error: error.message });
+ }
+};
+
module.exports = {
uploadReceipt,
+ saveTransactionFromReceipt,
};
\ No newline at end of file
diff --git a/backend/routes/receiptRoutes.js b/backend/routes/receiptRoutes.js
index 8e192d3..c9849b3 100644
--- a/backend/routes/receiptRoutes.js
+++ b/backend/routes/receiptRoutes.js
@@ -1,9 +1,10 @@
const express = require('express');
const router = express.Router();
-const { uploadReceipt } = require('../controllers/receiptController');
+const { uploadReceipt, saveTransactionFromReceipt } = require('../controllers/receiptController');
const { protect } = require('../middleware/authMiddleware');
const upload = require('../middleware/uploadMiddleware');
router.post('/upload', protect, upload, uploadReceipt);
+router.post('/save-transaction', protect, saveTransactionFromReceipt);
module.exports = router;
\ No newline at end of file
diff --git a/frontend/src/pages/ReceiptsPage.jsx b/frontend/src/pages/ReceiptsPage.jsx
index 5b7e8b2..3d2ed5d 100644
--- a/frontend/src/pages/ReceiptsPage.jsx
+++ b/frontend/src/pages/ReceiptsPage.jsx
@@ -1,6 +1,7 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import api from '../api/axios';
+import TransactionModal from '../components/TransactionModal';
const ReceiptsPage = () => {
const [file, setFile] = useState(null);
@@ -9,6 +10,25 @@ const ReceiptsPage = () => {
const [error, setError] = useState('');
const navigate = useNavigate();
+ const [openEditReceiptResult, setOpenEditReceiptResult] = useState(false);
+ const [categories, setCategories] = useState([]);
+ const [isEditingResult, setIsEditingResult] = useState(false);
+ const [isSaving, setIsSaving] = useState(false);
+
+ // Fetch categories when component mounts
+ useEffect(() => {
+ const fetchCategories = async () => {
+ try {
+ const response = await api.get('/transactions/categories');
+ setCategories(response.data);
+ } catch (error) {
+ console.error('Failed to fetch categories:', error);
+ }
+ };
+
+ fetchCategories();
+ }, []);
+
const handleFileChange = (e) => {
setFile(e.target.files[0]);
setReceiptResult(null);
@@ -34,8 +54,9 @@ const ReceiptsPage = () => {
},
});
setReceiptResult(response.data);
- alert('Receipt processed successfully and transaction created! Redirecting to dashboard...');
- navigate('/dashboard');
+
+ // Open the modal to allow user to edit the extracted data
+ setOpenEditReceiptResult(true);
} catch (err) {
setError('Upload failed. Please try again.');
console.error(err);
@@ -44,6 +65,66 @@ const ReceiptsPage = () => {
}
};
+ const handleEditReceiptSubmit = async (formData, transactionId) => {
+ try {
+ // Update the receiptResult with the edited data
+ const updatedReceiptResult = {
+ ...receiptResult,
+ extractedData: {
+ merchant: formData.name,
+ amount: parseFloat(formData.cost),
+ category: formData.category,
+ date: formData.addedOn,
+ isIncome: formData.isIncome
+ }
+ };
+
+ setReceiptResult(updatedReceiptResult);
+ setOpenEditReceiptResult(false);
+ } catch (err) {
+ setError('Failed to update receipt data. Please try again.');
+ console.error(err);
+ }
+ };
+
+ // Handle final save to database (second verification step)
+ const handleFinalSave = async () => {
+ try {
+ setIsSaving(true);
+
+ const transactionData = {
+ name: receiptResult.extractedData.merchant,
+ category: receiptResult.extractedData.category,
+ cost: receiptResult.extractedData.amount,
+ addedOn: receiptResult.extractedData.date,
+ isIncome: receiptResult.extractedData.isIncome || false
+ };
+
+ const response = await api.post('/receipts/save-transaction', {
+ receiptId: receiptResult._id,
+ transactionData: transactionData
+ });
+
+ alert('Transaction saved successfully! Redirecting to dashboard...');
+ navigate('/dashboard');
+ } catch (err) {
+ setError('Failed to save transaction. Please try again.');
+ console.error(err);
+ } finally {
+ setIsSaving(false);
+ }
+ };
+
+ // Handle edit button in result div
+ const handleEditResult = () => {
+ setIsEditingResult(true);
+ setOpenEditReceiptResult(true);
+ };
+
+ const handleNewCategory = (newCategory) => {
+ setCategories(prev => [...prev, newCategory].sort());
+ };
+
return (
<>
Upload Receipt
@@ -63,7 +144,7 @@ const ReceiptsPage = () => {
disabled={uploading}
className="mt-4 w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-300"
>
- {uploading ? 'Processing...' : 'Upload & Create Transaction'}
+ {uploading ? 'Processing...' : 'Upload & Extract Data'}
{error && {error}
}
@@ -73,10 +154,33 @@ const ReceiptsPage = () => {
Last Upload Result
{receiptResult ? (
-
Merchant: {receiptResult.extractedData.merchant}
-
Amount: {receiptResult.extractedData.amount.toFixed(2)}
-
Category: {receiptResult.extractedData.category}
-
Date: {new Date(receiptResult.extractedData.date).toLocaleDateString()}
+
+
Merchant: {receiptResult.extractedData.merchant}
+
Amount: {receiptResult.extractedData.amount.toFixed(2)}
+
Category: {receiptResult.extractedData.category}
+
Date: {new Date(receiptResult.extractedData.date).toLocaleDateString()}
+ {receiptResult.extractedData.isIncome && (
+
Income: Yes
+ )}
+
+
+
+
+
+
+
) : (
@@ -85,6 +189,27 @@ const ReceiptsPage = () => {
+
+ {/* Transaction Modal for editing receipt data */}
+ {openEditReceiptResult && receiptResult && (
+ {
+ setOpenEditReceiptResult(false);
+ setIsEditingResult(false);
+ }}
+ onSubmit={handleEditReceiptSubmit}
+ transaction={{
+ name: receiptResult.extractedData.merchant || '',
+ category: receiptResult.extractedData.category || '',
+ cost: receiptResult.extractedData.amount || 0,
+ addedOn: receiptResult.extractedData.date || new Date().toISOString().split('T')[0],
+ isIncome: receiptResult.extractedData.isIncome || false
+ }}
+ categories={categories}
+ onNewCategory={handleNewCategory}
+ />
+ )}
>
);
};
From 3c2693bcd55d800166699449afbcdb16c88ad6fd Mon Sep 17 00:00:00 2001
From: AmandeepMandal1077 <2023kucp1077@iiitkota.ac.in>
Date: Sat, 11 Oct 2025 01:33:09 +0530
Subject: [PATCH 2/5] removed unused parameter
---
backend/controllers/receiptController.js | 2 +-
frontend/src/pages/ReceiptsPage.jsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/backend/controllers/receiptController.js b/backend/controllers/receiptController.js
index 21c4fb7..7ccbedd 100644
--- a/backend/controllers/receiptController.js
+++ b/backend/controllers/receiptController.js
@@ -100,7 +100,7 @@ const saveTransactionFromReceipt = async (req, res) => {
const savedTransaction = await newTransaction.save();
- // update the receipt with the final confirmed data
+ // Update the receipt with the final confirmed data
receipt.extractedData = {
merchant: transactionData.name,
amount: transactionData.cost,
diff --git a/frontend/src/pages/ReceiptsPage.jsx b/frontend/src/pages/ReceiptsPage.jsx
index 3d2ed5d..f498479 100644
--- a/frontend/src/pages/ReceiptsPage.jsx
+++ b/frontend/src/pages/ReceiptsPage.jsx
@@ -65,7 +65,7 @@ const ReceiptsPage = () => {
}
};
- const handleEditReceiptSubmit = async (formData, transactionId) => {
+ const handleEditReceiptSubmit = async (formData) => {
try {
// Update the receiptResult with the edited data
const updatedReceiptResult = {
From d56bee115476a888a053344101a1000067398b16 Mon Sep 17 00:00:00 2001
From: AmandeepMandal1077 <2023kucp1077@iiitkota.ac.in>
Date: Wed, 22 Oct 2025 22:02:53 +0530
Subject: [PATCH 3/5] fix: resolved issues
---
backend/controllers/receiptController.js | 10 +++++--
frontend/src/pages/ReceiptsPage.jsx | 37 ++++++++++--------------
2 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/backend/controllers/receiptController.js b/backend/controllers/receiptController.js
index 71f6139..42c63ae 100644
--- a/backend/controllers/receiptController.js
+++ b/backend/controllers/receiptController.js
@@ -108,13 +108,19 @@ const saveTransactionFromReceipt = async (req, res) => {
return res.status(404).json({ message: 'Receipt not found' });
}
+ // Validate and parse the date
+ const transactionDate = new Date(transactionData.addedOn);
+ if (isNaN(transactionDate.getTime())) {
+ return res.status(400).json({ message: 'Invalid date format provided' });
+ }
+
// Create the transaction with user-confirmed data
const newTransaction = new IncomeExpense({
user: req.user.id,
name: transactionData.name,
category: transactionData.category,
cost: transactionData.cost,
- addedOn: new Date(transactionData.addedOn),
+ addedOn: transactionDate,
isIncome: transactionData.isIncome || false,
});
@@ -125,7 +131,7 @@ const saveTransactionFromReceipt = async (req, res) => {
merchant: transactionData.name,
amount: transactionData.cost,
category: transactionData.category,
- date: new Date(transactionData.addedOn),
+ date: transactionDate,
isIncome: transactionData.isIncome || false,
};
await receipt.save();
diff --git a/frontend/src/pages/ReceiptsPage.jsx b/frontend/src/pages/ReceiptsPage.jsx
index f498479..c969a19 100644
--- a/frontend/src/pages/ReceiptsPage.jsx
+++ b/frontend/src/pages/ReceiptsPage.jsx
@@ -65,26 +65,21 @@ const ReceiptsPage = () => {
}
};
- const handleEditReceiptSubmit = async (formData) => {
- try {
- // Update the receiptResult with the edited data
- const updatedReceiptResult = {
- ...receiptResult,
- extractedData: {
- merchant: formData.name,
- amount: parseFloat(formData.cost),
- category: formData.category,
- date: formData.addedOn,
- isIncome: formData.isIncome
- }
- };
-
- setReceiptResult(updatedReceiptResult);
- setOpenEditReceiptResult(false);
- } catch (err) {
- setError('Failed to update receipt data. Please try again.');
- console.error(err);
- }
+ const handleEditReceiptSubmit = (formData) => {
+ // Update the receiptResult with the edited data
+ const updatedReceiptResult = {
+ ...receiptResult,
+ extractedData: {
+ merchant: formData.name,
+ amount: parseFloat(formData.cost) || 0,
+ category: formData.category,
+ date: formData.addedOn,
+ isIncome: formData.isIncome
+ }
+ };
+
+ setReceiptResult(updatedReceiptResult);
+ setOpenEditReceiptResult(false);
};
// Handle final save to database (second verification step)
@@ -156,7 +151,7 @@ const ReceiptsPage = () => {
Merchant: {receiptResult.extractedData.merchant}
-
Amount: {receiptResult.extractedData.amount.toFixed(2)}
+
Amount: {(parseFloat(receiptResult.extractedData.amount) || 0).toFixed(2)}
Category: {receiptResult.extractedData.category}
Date: {new Date(receiptResult.extractedData.date).toLocaleDateString()}
{receiptResult.extractedData.isIncome && (
From 797fd4b405ae59a247909900ea442ae7b50eee54 Mon Sep 17 00:00:00 2001
From: AmandeepMandal1077 <2023kucp1077@iiitkota.ac.in>
Date: Fri, 31 Oct 2025 18:14:54 +0530
Subject: [PATCH 4/5] Merge master changes
---
frontend/src/pages/ReceiptsPage.jsx | 486 ++++++++++++++++------------
1 file changed, 278 insertions(+), 208 deletions(-)
diff --git a/frontend/src/pages/ReceiptsPage.jsx b/frontend/src/pages/ReceiptsPage.jsx
index c969a19..9d73d57 100644
--- a/frontend/src/pages/ReceiptsPage.jsx
+++ b/frontend/src/pages/ReceiptsPage.jsx
@@ -1,212 +1,282 @@
-import React, { useState, useEffect } from 'react';
-import { useNavigate } from 'react-router-dom';
-import api from '../api/axios';
-import TransactionModal from '../components/TransactionModal';
+import React, { useState, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+import api from "../api/axios";
+import TransactionModal from "../components/TransactionModal";
+import { toast, Bounce } from "react-toastify";
const ReceiptsPage = () => {
- const [file, setFile] = useState(null);
- const [uploading, setUploading] = useState(false);
- const [receiptResult, setReceiptResult] = useState(null);
- const [error, setError] = useState('');
- const navigate = useNavigate();
-
- const [openEditReceiptResult, setOpenEditReceiptResult] = useState(false);
- const [categories, setCategories] = useState([]);
- const [isEditingResult, setIsEditingResult] = useState(false);
- const [isSaving, setIsSaving] = useState(false);
-
- // Fetch categories when component mounts
- useEffect(() => {
- const fetchCategories = async () => {
- try {
- const response = await api.get('/transactions/categories');
- setCategories(response.data);
- } catch (error) {
- console.error('Failed to fetch categories:', error);
- }
- };
-
- fetchCategories();
- }, []);
-
- const handleFileChange = (e) => {
- setFile(e.target.files[0]);
- setReceiptResult(null);
- setError('');
- };
-
- const handleSubmit = async (e) => {
- e.preventDefault();
- if (!file) {
- setError('Please select a file to upload.');
- return;
- }
-
- const formData = new FormData();
- formData.append('receipt', file);
-
- try {
- setUploading(true);
- setError('');
- const response = await api.post('/receipts/upload', formData, {
- headers: {
- 'Content-Type': 'multipart/form-data',
- },
- });
- setReceiptResult(response.data);
-
- // Open the modal to allow user to edit the extracted data
- setOpenEditReceiptResult(true);
- } catch (err) {
- setError('Upload failed. Please try again.');
- console.error(err);
- } finally {
- setUploading(false);
- }
- };
-
- const handleEditReceiptSubmit = (formData) => {
- // Update the receiptResult with the edited data
- const updatedReceiptResult = {
- ...receiptResult,
- extractedData: {
- merchant: formData.name,
- amount: parseFloat(formData.cost) || 0,
- category: formData.category,
- date: formData.addedOn,
- isIncome: formData.isIncome
- }
- };
-
- setReceiptResult(updatedReceiptResult);
- setOpenEditReceiptResult(false);
- };
-
- // Handle final save to database (second verification step)
- const handleFinalSave = async () => {
- try {
- setIsSaving(true);
-
- const transactionData = {
- name: receiptResult.extractedData.merchant,
- category: receiptResult.extractedData.category,
- cost: receiptResult.extractedData.amount,
- addedOn: receiptResult.extractedData.date,
- isIncome: receiptResult.extractedData.isIncome || false
- };
-
- const response = await api.post('/receipts/save-transaction', {
- receiptId: receiptResult._id,
- transactionData: transactionData
- });
-
- alert('Transaction saved successfully! Redirecting to dashboard...');
- navigate('/dashboard');
- } catch (err) {
- setError('Failed to save transaction. Please try again.');
- console.error(err);
- } finally {
- setIsSaving(false);
- }
- };
-
- // Handle edit button in result div
- const handleEditResult = () => {
- setIsEditingResult(true);
- setOpenEditReceiptResult(true);
- };
-
- const handleNewCategory = (newCategory) => {
- setCategories(prev => [...prev, newCategory].sort());
- };
-
- return (
- <>
-
Upload Receipt
-
-
-
-
-
-
Last Upload Result
- {receiptResult ? (
-
-
-
Merchant: {receiptResult.extractedData.merchant}
-
Amount: {(parseFloat(receiptResult.extractedData.amount) || 0).toFixed(2)}
-
Category: {receiptResult.extractedData.category}
-
Date: {new Date(receiptResult.extractedData.date).toLocaleDateString()}
- {receiptResult.extractedData.isIncome && (
-
Income: Yes
- )}
-
-
-
-
-
-
-
-

-
- ) : (
-
Upload a receipt to see the extracted data here.
- )}
-
-
-
-
- {/* Transaction Modal for editing receipt data */}
- {openEditReceiptResult && receiptResult && (
-
{
- setOpenEditReceiptResult(false);
- setIsEditingResult(false);
- }}
- onSubmit={handleEditReceiptSubmit}
- transaction={{
- name: receiptResult.extractedData.merchant || '',
- category: receiptResult.extractedData.category || '',
- cost: receiptResult.extractedData.amount || 0,
- addedOn: receiptResult.extractedData.date || new Date().toISOString().split('T')[0],
- isIncome: receiptResult.extractedData.isIncome || false
- }}
- categories={categories}
- onNewCategory={handleNewCategory}
- />
- )}
- >
- );
+ const [isMobile, setIsMobile] = useState(window.innerWidth <= 767);
+ const [file, setFile] = useState(null);
+ const [uploading, setUploading] = useState(false);
+ const [receiptResult, setReceiptResult] = useState(null);
+ const [error, setError] = useState("");
+ const navigate = useNavigate();
+
+ const [openEditReceiptResult, setOpenEditReceiptResult] = useState(false);
+ const [categories, setCategories] = useState([]);
+ const [isEditingResult, setIsEditingResult] = useState(false);
+ const [isSaving, setIsSaving] = useState(false);
+
+ // Fetch categories when component mounts
+ useEffect(() => {
+ const fetchCategories = async () => {
+ try {
+ const response = await api.get("/transactions/categories");
+ setCategories(response.data);
+ } catch (error) {
+ console.error("Failed to fetch categories:", error);
+ }
+ };
+
+ fetchCategories();
+ }, []);
+
+ // Handle mobile responsive resize
+ useEffect(() => {
+ const handleResize = () => {
+ return setIsMobile(window.innerWidth <= 767);
+ };
+ window.addEventListener("resize", handleResize);
+ return () => window.removeEventListener("resize", handleResize);
+ }, []);
+
+ const handleFileChange = (e) => {
+ setFile(e.target.files[0]);
+ setReceiptResult(null);
+ setError("");
+ };
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ if (!file) {
+ setError("Please select a file to upload.");
+ return;
+ }
+
+ const formData = new FormData();
+ formData.append("receipt", file);
+
+ try {
+ setUploading(true);
+ setError("");
+ const response = await api.post("/receipts/upload", formData, {
+ headers: {
+ "Content-Type": "multipart/form-data",
+ },
+ });
+ setReceiptResult(response.data);
+
+ // Open the modal to allow user to edit the extracted data
+ setOpenEditReceiptResult(true);
+ } catch (err) {
+ setError("Upload failed. Please try again.");
+ console.error(err);
+ } finally {
+ setUploading(false);
+ }
+ };
+
+ const handleEditReceiptSubmit = (formData) => {
+ // Update the receiptResult with the edited data
+ const updatedReceiptResult = {
+ ...receiptResult,
+ extractedData: {
+ merchant: formData.name,
+ amount: parseFloat(formData.cost) || 0,
+ category: formData.category,
+ date: formData.addedOn,
+ isIncome: formData.isIncome,
+ },
+ };
+
+ setReceiptResult(updatedReceiptResult);
+ setOpenEditReceiptResult(false);
+ };
+
+ // Handle final save to database (second verification step)
+ const handleFinalSave = async () => {
+ try {
+ setIsSaving(true);
+
+ const transactionData = {
+ name: receiptResult.extractedData.merchant,
+ category: receiptResult.extractedData.category,
+ cost: receiptResult.extractedData.amount,
+ addedOn: receiptResult.extractedData.date,
+ isIncome: receiptResult.extractedData.isIncome || false,
+ };
+
+ const response = await api.post("/receipts/save-transaction", {
+ receiptId: receiptResult._id,
+ transactionData: transactionData,
+ });
+
+ toast.success("Transaction saved successfully!", {
+ position: "top-right",
+ autoClose: 3000,
+ hideProgressBar: false,
+ closeOnClick: false,
+ pauseOnHover: true,
+ draggable: true,
+ progress: undefined,
+ style: {
+ fontSize: "18px",
+ padding: "16px 24px",
+ minWidth: "500px",
+ },
+ theme: "light",
+ transition: Bounce,
+ });
+
+ setTimeout(() => navigate("/dashboard"), 1000);
+ } catch (err) {
+ setError("Failed to save transaction. Please try again.");
+ console.error(err);
+ } finally {
+ setIsSaving(false);
+ }
+ };
+
+ // Handle edit button in result div
+ const handleEditResult = () => {
+ setIsEditingResult(true);
+ setOpenEditReceiptResult(true);
+ };
+
+ const handleNewCategory = (newCategory) => {
+ setCategories((prev) => [...prev, newCategory].sort());
+ };
+
+ return (
+ <>
+
+ Upload Receipt
+
+
+
+
+
+
+ Last Upload Result
+
+ {receiptResult ? (
+
+
+
+ Merchant:{" "}
+ {receiptResult.extractedData.merchant}
+
+
+ Amount:{" "}
+ {(
+ parseFloat(
+ receiptResult.extractedData.amount
+ ) || 0
+ ).toFixed(2)}
+
+
+ Category:{" "}
+ {receiptResult.extractedData.category}
+
+
+ Date:{" "}
+ {new Date(
+ receiptResult.extractedData.date
+ ).toLocaleDateString()}
+
+ {receiptResult.extractedData.isIncome && (
+
+ Income: Yes
+
+ )}
+
+
+
+
+
+
+
+

+
+ ) : (
+
+ Upload a receipt to see the extracted data here.
+
+ )}
+
+
+
+ {isMobile && (
+
+ )}
+
+ {/* Transaction Modal for editing receipt data */}
+ {openEditReceiptResult && receiptResult && (
+ {
+ setOpenEditReceiptResult(false);
+ setIsEditingResult(false);
+ }}
+ onSubmit={handleEditReceiptSubmit}
+ transaction={{
+ name: receiptResult.extractedData.merchant || "",
+ category: receiptResult.extractedData.category || "",
+ cost: receiptResult.extractedData.amount || 0,
+ addedOn:
+ receiptResult.extractedData.date ||
+ new Date().toISOString().split("T")[0],
+ isIncome: receiptResult.extractedData.isIncome || false,
+ }}
+ categories={categories}
+ onNewCategory={handleNewCategory}
+ />
+ )}
+ >
+ );
};
-export default ReceiptsPage;
\ No newline at end of file
+export default ReceiptsPage;
From e8a018fe77216f7c27e01604d6cee7d07cf72407 Mon Sep 17 00:00:00 2001
From: AmandeepMandal1077 <2023kucp1077@iiitkota.ac.in>
Date: Fri, 31 Oct 2025 18:29:47 +0530
Subject: [PATCH 5/5] fix: issues
---
frontend/src/pages/ReceiptsPage.jsx | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/frontend/src/pages/ReceiptsPage.jsx b/frontend/src/pages/ReceiptsPage.jsx
index 9d73d57..7082bf9 100644
--- a/frontend/src/pages/ReceiptsPage.jsx
+++ b/frontend/src/pages/ReceiptsPage.jsx
@@ -14,7 +14,6 @@ const ReceiptsPage = () => {
const [openEditReceiptResult, setOpenEditReceiptResult] = useState(false);
const [categories, setCategories] = useState([]);
- const [isEditingResult, setIsEditingResult] = useState(false);
const [isSaving, setIsSaving] = useState(false);
// Fetch categories when component mounts
@@ -34,7 +33,7 @@ const ReceiptsPage = () => {
// Handle mobile responsive resize
useEffect(() => {
const handleResize = () => {
- return setIsMobile(window.innerWidth <= 767);
+ setIsMobile(window.innerWidth <= 767);
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
@@ -106,7 +105,7 @@ const ReceiptsPage = () => {
isIncome: receiptResult.extractedData.isIncome || false,
};
- const response = await api.post("/receipts/save-transaction", {
+ await api.post("/receipts/save-transaction", {
receiptId: receiptResult._id,
transactionData: transactionData,
});
@@ -139,12 +138,15 @@ const ReceiptsPage = () => {
// Handle edit button in result div
const handleEditResult = () => {
- setIsEditingResult(true);
setOpenEditReceiptResult(true);
};
- const handleNewCategory = (newCategory) => {
- setCategories((prev) => [...prev, newCategory].sort());
+ const handleNewCategory = (newCategory, isIncome) => {
+ setCategories((prev) =>
+ [...prev, { name: newCategory, isIncome }].sort((a, b) =>
+ a.name.localeCompare(b.name)
+ )
+ );
};
return (
@@ -232,7 +234,10 @@ const ReceiptsPage = () => {

@@ -259,7 +264,6 @@ const ReceiptsPage = () => {
isOpen={openEditReceiptResult}
onClose={() => {
setOpenEditReceiptResult(false);
- setIsEditingResult(false);
}}
onSubmit={handleEditReceiptSubmit}
transaction={{
@@ -271,7 +275,12 @@ const ReceiptsPage = () => {
new Date().toISOString().split("T")[0],
isIncome: receiptResult.extractedData.isIncome || false,
}}
- categories={categories}
+ expenseCategories={categories
+ .filter((cat) => !cat.isIncome)
+ .map((cat) => cat.name || cat)}
+ incomeCategories={categories
+ .filter((cat) => cat.isIncome)
+ .map((cat) => cat.name || cat)}
onNewCategory={handleNewCategory}
/>
)}