document.
addEventListener("DOMContentLoaded", () => {
const uploadForm = document.getElementById("upload-form");
const fileInput = document.getElementById("file-input");
const message = document.getElementById("message");
const fileList = document.getElementById("file-list");
const chartContainer = document.createElement("div");
chartContainer.id = "chart-container";
document.querySelector("main").appendChild(chartContainer);
// Load Chart.js and SheetJS
const chartScript = document.createElement("script");
chartScript.src = "https://cdn.jsdelivr.net/npm/chart.js";
document.head.appendChild(chartScript);
const sheetScript = document.createElement("script");
sheetScript.src =
"https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js";
document.head.appendChild(sheetScript);
function loadFiles() {
fetch("upload.php", {
method: "GET",
headers: {
"X-Requested-With": "XMLHttpRequest",
"Accept": "application/json"
}
})
.then(response => {
if (!response.ok) {
return response.text().then(text => {
throw new Error(`HTTP error! Status: ${response.status},
Response: ${text}`);
});
}
return response.json();
})
.then(data => {
fileList.innerHTML = "";
message.textContent = "";
if (data.error) {
message.textContent = "Error fetching files: " + data.error;
console.error("Server Error:", data.error);
return;
}
if (data.length === 0) {
message.textContent = "No files uploaded yet.";
return;
}
data.forEach(file => {
const li = document.createElement("li");
li.textContent = file.file_name + " ";
const viewBtn = document.createElement("button");
viewBtn.textContent = "VIEW";
viewBtn.onclick = () => {
window.open(`view_file.php?file=$
{encodeURIComponent(file.file_path)}`, "_blank");
};
li.appendChild(viewBtn);
fileList.appendChild(li);
});
// Generate charts for the first file
if (data.length > 0) {
loadExcelData(data[0].file_path);
}
})
.catch(error => {
console.error("Fetch error:", error.message);
message.textContent = "Error fetching uploaded files: " +
error.message;
});
}
function loadExcelData(filePath) {
fetch(filePath)
.then(response => response.arrayBuffer())
.then(data => {
const workbook = XLSX.read(data, { type: 'array' });
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
const headers = jsonData[0];
const dateIdx = headers.indexOf("Date");
const detailsIdx = headers.indexOf("Transaction Details");
const categoryIdx = headers.indexOf("Category");
const amountIdx = headers.indexOf("Amount (₹)");
const transactions = jsonData.slice(1).map(row => ({
date: row[dateIdx],
details: row[detailsIdx],
category: row[categoryIdx],
amount: parseFloat(row[amountIdx]) || 0
}));
// Filter received and sent transactions
const received = transactions.filter(t => t.amount > 0);
const sent = transactions.filter(t => t.amount < 0).map(t => ({ ...t,
amount: -t.amount }));
// Data for charts
const receivedBySender = {};
const sentByPerson = {};
const expenseByCategory = {};
const flowByCategory = {};
const transactionsByDate = {};
received.forEach(t => {
const sender = t.details.match(/Received from (.+)/)?.[1] ||
"Unknown";
receivedBySender[sender] = (receivedBySender[sender] || 0) +
t.amount;
});
sent.forEach(t => {
const recipient = t.details.match(/to (.+)/)?.[1] || t.details ||
"Unknown";
sentByPerson[recipient] = (sentByPerson[recipient] || 0) +
t.amount;
});
transactions.forEach(t => {
const cat = t.category || "Unknown";
if (t.amount < 0) {
expenseByCategory[cat] = (expenseByCategory[cat] || 0) -
t.amount;
}
flowByCategory[cat] = (flowByCategory[cat] || 0) + t.amount;
const date = t.date.split(',')[0]; // Extract date part
if (!transactionsByDate[date]) transactionsByDate[date] = { Bills:
0, Dining: 0, Groceries: 0, Income: 0, Transfer: 0 };
if (t.amount < 0) {
if (cat.includes("Bills")) transactionsByDate[date].Bills++;
else if (cat.includes("Dining"))
transactionsByDate[date].Dining++;
else if (cat.includes("Groceries"))
transactionsByDate[date].Groceries++;
else if (cat.includes("Income"))
transactionsByDate[date].Income++;
else if (cat.includes("Transfer"))
transactionsByDate[date].Transfer++;
}
});
// Create charts with darker, vibrant colors
chartContainer.innerHTML = "";
const createChart = (id, type, labels, datasets, title) => {
const canvas = document.createElement("canvas");
canvas.id = id;
chartContainer.appendChild(canvas);
new Chart(canvas.getContext('2d'), {
type: type,
data: { labels, datasets },
options: {
scales: { y: { beginAtZero: true, title: { display: true,
text: 'Amount (₹)' } } },
plugins: { title: { display: true, text: title } }
}
});
};
createChart("receivedChart", "bar", Object.keys(receivedBySender), [{
label: 'Received',
data: Object.values(receivedBySender),
backgroundColor: '#2E86AB', // Dark teal
borderColor: '#1B5E6F',
borderWidth: 1
}], "Total Money Received per Sender");
createChart("sentChart", "bar", Object.keys(sentByPerson), [{
label: 'Sent',
data: Object.values(sentByPerson),
backgroundColor: '#E63946', // Dark red
borderColor: '#A4161A',
borderWidth: 1
}], "Total Money Sent per Person");
createChart("expenseChart", "bar", Object.keys(expenseByCategory), [{
label: 'Expense',
data: Object.values(expenseByCategory),
backgroundColor: '#4A69BD', // Dark blue
borderColor: '#2D3E8C',
borderWidth: 1
}], "Total Expense by Category");
createChart("flowChart", "bar", Object.keys(flowByCategory), [{
label: 'Net Flow',
data: Object.values(flowByCategory),
backgroundColor: '#F4A261', // Dark orange
borderColor: '#C85400',
borderWidth: 1
}], "Overall Money Flow by Category");
createChart("transactionChart", "bar", Object.keys(transactionsByDate),
[
{ label: 'Bills & Utilities', data:
Object.values(transactionsByDate).map(d => d.Bills), backgroundColor: '#264653',
borderColor: '#1A2F36', borderWidth: 1 },
{ label: 'Dining & Restaurants', data:
Object.values(transactionsByDate).map(d => d.Dining), backgroundColor: '#E76F51',
borderColor: '#B6442C', borderWidth: 1 },
{ label: 'Groceries & Essentials', data:
Object.values(transactionsByDate).map(d => d.Groceries), backgroundColor:
'#2A9D8F', borderColor: '#1D6A64', borderWidth: 1 },
{ label: 'Income & Credits', data:
Object.values(transactionsByDate).map(d => d.Income), backgroundColor: '#E9C46A',
borderColor: '#C99A2A', borderWidth: 1 },
{ label: 'Transfer & Payments', data:
Object.values(transactionsByDate).map(d => d.Transfer), backgroundColor: '#8E5B3A',
borderColor: '#6A3F27', borderWidth: 1 }
], "Number of Transactions Over Time");
})
.catch(error => console.error("Excel load error:", error));
}
uploadForm.addEventListener("submit", (e) => {
e.preventDefault();
if (fileInput.files.length === 0) {
message.textContent = "Please select a file to upload.";
return;
}
const formData = new FormData();
formData.append("file", fileInput.files[0]);
fetch("upload.php", {
method: "POST",
body: formData
})
.then(response => {
if (!response.ok) {
return response.text().then(text => {
throw new Error(`HTTP error! Status: ${response.status},
Response: ${text}`);
});
}
return response.json();
})
.then(data => {
message.textContent = data.success || data.error;
if (data.success) {
fileInput.value = ""; // Clear file input
loadFiles(); // Refresh file list and charts
const li = document.createElement("li");
li.textContent = fileInput.files[0].name + " ";
const runBtn = document.createElement("button");
runBtn.textContent = "RUN";
runBtn.onclick = () => {
runPythonScript("Uploads/" + fileInput.files[0].name);
};
li.appendChild(runBtn);
fileList.appendChild(li);
}
})
.catch(error => {
console.error("Upload failed:", error.message);
message.textContent = "Error uploading file: " + error.message;
});
});
function runPythonScript(filePath) {
fetch("run_script.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ file_path: filePath })
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.success) {
window.location.href = "output.html";
} else {
alert("Error running script: " + data.details);
}
})
.catch(error => {
console.error("Run error:", error.message);
alert("Failed to run script: " + error.message);
});
}
loadFiles();
});
document.addEventListener("DOMContentLoaded", () => {
const uploadForm = document.getElementById("upload-form");
const fileInput = document.getElementById("file-input");
const message = document.getElementById("message");
const fileList = document.getElementById("file-list");
const chartContainer = document.createElement("div");
chartContainer.id = "chart-container";
document.querySelector("main").appendChild(chartContainer);
// Load Chart.js and SheetJS
const chartScript = document.createElement("script");
chartScript.src = "https://cdn.jsdelivr.net/npm/chart.js";
document.head.appendChild(chartScript);
const sheetScript = document.createElement("script");
sheetScript.src =
"https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js";
document.head.appendChild(sheetScript);
function loadFiles() {
fetch("upload.php", {
method: "GET",
headers: {
"X-Requested-With": "XMLHttpRequest",
"Accept": "application/json"
}
})
.then(response => {
if (!response.ok) {
return response.text().then(text => {
throw new Error(`HTTP error! Status: ${response.status},
Response: ${text}`);
});
}
return response.json();
})
.then(data => {
fileList.innerHTML = "";
message.textContent = "";
if (data.error) {
message.textContent = "Error fetching files: " + data.error;
console.error("Server Error:", data.error);
return;
}
if (data.length === 0) {
message.textContent = "No files uploaded yet.";
return;
}
data.forEach(file => {
const li = document.createElement("li");
li.textContent = file.file_name + " ";
const viewBtn = document.createElement("button");
viewBtn.textContent = "VIEW";
viewBtn.onclick = () => {
window.open(`view_file.php?file=$
{encodeURIComponent(file.file_path)}`, "_blank");
};
li.appendChild(viewBtn);
fileList.appendChild(li);
});
// Generate charts for the first file
if (data.length > 0) {
loadExcelData(data[0].file_path);
}
})
.catch(error => {
console.error("Fetch error:", error.message);
message.textContent = "Error fetching uploaded files: " +
error.message;
});
}
function loadExcelData(filePath) {
fetch(filePath)
.then(response => response.arrayBuffer())
.then(data => {
const workbook = XLSX.read(data, { type: 'array' });
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
const headers = jsonData[0];
const dateIdx = headers.indexOf("Date");
const detailsIdx = headers.indexOf("Transaction Details");
const categoryIdx = headers.indexOf("Category");
const amountIdx = headers.indexOf("Amount (₹)");
const transactions = jsonData.slice(1).map(row => ({
date: row[dateIdx],
details: row[detailsIdx],
category: row[categoryIdx],
amount: parseFloat(row[amountIdx]) || 0
}));
// Filter received and sent transactions
const received = transactions.filter(t => t.amount > 0);
const sent = transactions.filter(t => t.amount < 0).map(t => ({ ...t,
amount: -t.amount }));
// Data for charts
const receivedBySender = {};
const sentByPerson = {};
const expenseByCategory = {};
const flowByCategory = {};
const transactionsByDate = {};
received.forEach(t => {
const sender = t.details.match(/Received from (.+)/)?.[1] ||
"Unknown";
receivedBySender[sender] = (receivedBySender[sender] || 0) +
t.amount;
});
sent.forEach(t => {
const recipient = t.details.match(/to (.+)/)?.[1] || t.details ||
"Unknown";
sentByPerson[recipient] = (sentByPerson[recipient] || 0) +
t.amount;
});
transactions.forEach(t => {
const cat = t.category || "Unknown";
if (t.amount < 0) {
expenseByCategory[cat] = (expenseByCategory[cat] || 0) -
t.amount;
}
flowByCategory[cat] = (flowByCategory[cat] || 0) + t.amount;
const date = t.date.split(',')[0]; // Extract date part
if (!transactionsByDate[date]) transactionsByDate[date] = { Bills:
0, Dining: 0, Groceries: 0, Income: 0, Transfer: 0 };
if (t.amount < 0) {
if (cat.includes("Bills")) transactionsByDate[date].Bills++;
else if (cat.includes("Dining"))
transactionsByDate[date].Dining++;
else if (cat.includes("Groceries"))
transactionsByDate[date].Groceries++;
else if (cat.includes("Income"))
transactionsByDate[date].Income++;
else if (cat.includes("Transfer"))
transactionsByDate[date].Transfer++;
}
});
// Create charts
chartContainer.innerHTML = "";
const createChart = (id, type, labels, datasets, title) => {
const canvas = document.createElement("canvas");
canvas.id = id;
chartContainer.appendChild(canvas);
new Chart(canvas.getContext('2d'), {
type: type,
data: { labels, datasets },
options: {
scales: { y: { beginAtZero: true, title: { display: true,
text: 'Amount (₹)' } } },
plugins: { title: { display: true, text: title } }
}
});
};
createChart("receivedChart", "bar", Object.keys(receivedBySender), [{
label: 'Received',
data: Object.values(receivedBySender),
backgroundColor: 'rgba(75, 192, 192, 0.2)'
}], "Total Money Received per Sender");
createChart("sentChart", "bar", Object.keys(sentByPerson), [{
label: 'Sent',
data: Object.values(sentByPerson),
backgroundColor: 'rgba(255, 99, 132, 0.2)'
}], "Total Money Sent per Person");
createChart("expenseChart", "bar", Object.keys(expenseByCategory), [{
label: 'Expense',
data: Object.values(expenseByCategory),
backgroundColor: 'rgba(54, 162, 235, 0.2)'
}], "Total Expense by Category");
createChart("flowChart", "bar", Object.keys(flowByCategory), [{
label: 'Net Flow',
data: Object.values(flowByCategory),
backgroundColor: 'rgba(255, 206, 86, 0.2)'
}], "Overall Money Flow by Category");
createChart("transactionChart", "bar", Object.keys(transactionsByDate),
[{
label: 'Bills & Utilities', data:
Object.values(transactionsByDate).map(d => d.Bills), backgroundColor: 'blue'
}, {
label: 'Dining & Restaurants', data:
Object.values(transactionsByDate).map(d => d.Dining), backgroundColor: 'orange'
}, {
label: 'Groceries & Essentials', data:
Object.values(transactionsByDate).map(d => d.Groceries), backgroundColor: 'green'
}, {
label: 'Income & Credits', data:
Object.values(transactionsByDate).map(d => d.Income), backgroundColor: 'red'
}, {
label: 'Transfer & Payments', data:
Object.values(transactionsByDate).map(d => d.Transfer), backgroundColor: 'purple'
}], "Number of Transactions Over Time");
})
.catch(error => console.error("Excel load error:", error));
}
uploadForm.addEventListener("submit", (e) => {
e.preventDefault();
if (fileInput.files.length === 0) {
message.textContent = "Please select a file to upload.";
return;
}
const formData = new FormData();
formData.append("file", fileInput.files[0]);
fetch("upload.php", {
method: "POST",
body: formData
})
.then(response => {
if (!response.ok) {
return response.text().then(text => {
throw new Error(`HTTP error! Status: ${response.status},
Response: ${text}`);
});
}
return response.json();
})
.then(data => {
message.textContent = data.success || data.error;
if (data.success) {
fileInput.value = ""; // Clear file input
loadFiles(); // Refresh file list and charts
const li = document.createElement("li");
li.textContent = fileInput.files[0].name + " ";
const runBtn = document.createElement("button");
runBtn.textContent = "RUN";
runBtn.onclick = () => {
runPythonScript("Uploads/" + fileInput.files[0].name);
};
li.appendChild(runBtn);
fileList.appendChild(li);
}
})
.catch(error => {
console.error("Upload failed:", error.message);
message.textContent = "Error uploading file: " + error.message;
});
});
function runPythonScript(filePath) {
fetch("run_script.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ file_path: filePath })
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.success) {
window.location.href = "output.html";
} else {
alert("Error running script: " + data.details);
}
})
.catch(error => {
console.error("Run error:", error.message);
alert("Failed to run script: " + error.message);
});
}
loadFiles();
});
upload.php
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
include 'db_connect.php';
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = $_SESSION['user_id'];
// Handle file upload
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
header('Content-Type: application/json');
$upload_dir = "Uploads/";
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$file_name = basename($_FILES["file"]["name"]);
$file_tmp = $_FILES["file"]["tmp_name"];
$file_path = $upload_dir . $file_name;
if ($_FILES["file"]["size"] > 10 * 1024 * 1024) {
echo json_encode(["error" => "File size exceeds 10MB limit"]);
exit;
}
if (move_uploaded_file($file_tmp, $file_path)) {
$conn = reconnect($conn);
$stmt = $conn->prepare("INSERT INTO uploads (user_id, file_name, file_path)
VALUES (?, ?, ?)");
if ($stmt === false) {
die("Prepare failed: " . $conn->error);
}
$stmt->bind_param("iss", $user_id, $file_name, $file_path);
$stmt->execute();
$stmt->close();
echo json_encode(["success" => "File uploaded successfully"]);
} else {
echo json_encode(["error" => "Error moving file to uploads folder"]);
}
exit;
}
// Fetch uploaded files
$conn = reconnect($conn);
$stmt = $conn->prepare("SELECT id, file_name, file_path FROM uploads WHERE user_id
= ?");
if ($stmt === false) {
die("Prepare failed: " . $conn->error);
}
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$files = [];
while ($row = $result->fetch_assoc()) {
$files[] = $row;
}
$stmt->close();
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
header('Content-Type: application/json');
echo json_encode($files);
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Finance Manager</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<header>
<div class="container">
<h1 class="logo">Personal Finance Manager</h1>
<nav>
<ul class="nav-links">
<li><a href="contactus.html" class="btn-login">Contact</a></li>
<li><a href="profile.html" class="btn-login">Profile</a></li>
<li><a href="logout.php" class="btn-login">Logout</a></li>
</ul>
</nav>
</div>
</header>
<main>
<div class="contact-container">
<h5>Upload Your File</h5>
<form id="upload-form" enctype="multipart/form-data">
<input type="file" id="file-input" name="file" required>
<button type="submit" class="btn-signup">Upload</button>
</form>
</div>
<p id="message"></p>
<h2>Your Uploaded Files</h2>
<ul id="file-list"></ul>
<div id="chart-container"></div>
<button class="btn-login">Cash</button>
<button class="btn-login">Any Card</button>
</main>
<footer>
<div>
<p>Follow Us</p>
<div class="social-links">
<a href="https://instagram.com" target="_blank">📸 Instagram</a>
<a href="https://facebook.com" target="_blank">📘 Facebook</a>
<a href="https://linkedin.com" target="_blank">🔗 LinkedIn</a>
<a href="https://youtube.com" target="_blank">▶ YouTube</a>
</div>
<p>© 2025 Personal Finance Manager. All rights reserved.</p>
</div>
</footer>
<script src="upload.js"></script>
</body>
</html>