Auto commit: 2025-11-21T12:22:08.788Z
This commit is contained in:
parent
725333cdea
commit
8ccee67363
172
add_food.php
Normal file
172
add_food.php
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
$success_message = "";
|
||||||
|
$error_message = "";
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
if (!empty($_POST['food_name']) && !empty($_POST['calories']) && is_numeric($_POST['calories'])) {
|
||||||
|
try {
|
||||||
|
$food_name = $_POST['food_name'];
|
||||||
|
$calories = (int)$_POST['calories'];
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO food_log (food_name, calories) VALUES (?, ?)");
|
||||||
|
$stmt->execute([$food_name, $calories]);
|
||||||
|
|
||||||
|
$success_message = "Successfully added $food_name with $calories calories!";
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$error_message = "Error: Could not record the food. " . $e->getMessage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$error_message = "Please fill out all fields correctly.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Add Food - Calorie Tracker</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
<?php if ($success_message): ?>
|
||||||
|
<meta http-equiv="refresh" content="2;url=index.php">
|
||||||
|
<?php endif; ?>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="mobile-container">
|
||||||
|
<header class="app-header">
|
||||||
|
<h1>Add Food</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="main-content">
|
||||||
|
<?php if ($success_message): ?>
|
||||||
|
<div class="alert success">
|
||||||
|
<?php echo $success_message; ?>
|
||||||
|
<p>Redirecting you home...</p>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php if ($error_message): ?>
|
||||||
|
<div class="alert error">
|
||||||
|
<?php echo $error_message; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="food-search-container">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="food_search">Search for a food</label>
|
||||||
|
<input type="text" id="food_search" placeholder="e.g., Apple">
|
||||||
|
</div>
|
||||||
|
<button type="button" id="search_btn" class="btn">Search</button>
|
||||||
|
<div id="search_results"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="add_food.php" method="POST" class="add-sale-form">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="food_name">Food Name</label>
|
||||||
|
<input type="text" id="food_name" name="food_name" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="calories">Calories</label>
|
||||||
|
<input type="number" id="calories" name="calories" min="0" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-primary">Log Food</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<nav class="bottom-nav">
|
||||||
|
<a href="index.php" class="nav-item">
|
||||||
|
<i class="bi bi-house-door-fill"></i>
|
||||||
|
<span>Home</span>
|
||||||
|
</a>
|
||||||
|
<a href="add_food.php" class="nav-item active">
|
||||||
|
<i class="bi bi-plus-circle-fill"></i>
|
||||||
|
<span>Add Food</span>
|
||||||
|
</a>
|
||||||
|
<a href="dashboard.php" class="nav-item">
|
||||||
|
<i class="bi bi-bar-chart-line-fill"></i>
|
||||||
|
<span>Dashboard</span>
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function debounce(func, wait) {
|
||||||
|
let timeout;
|
||||||
|
return function(...args) {
|
||||||
|
const context = this;
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(() => func.apply(context, args), wait);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchInput = document.getElementById('food_search');
|
||||||
|
const searchBtn = document.getElementById('search_btn');
|
||||||
|
const resultsContainer = document.getElementById('search_results');
|
||||||
|
|
||||||
|
// Hide the original search button, as search will be triggered by typing
|
||||||
|
searchBtn.style.display = 'none';
|
||||||
|
|
||||||
|
const searchHandler = debounce(function() {
|
||||||
|
const searchTerm = searchInput.value;
|
||||||
|
if (searchTerm.trim() === '') {
|
||||||
|
resultsContainer.innerHTML = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultsContainer.innerHTML = '<p style="padding: 15px;">Searching...</p>';
|
||||||
|
|
||||||
|
fetch(`https://world.openfoodfacts.org/cgi/search.pl?search_terms=${encodeURIComponent(searchTerm)}&action=process&json=1&page_size=10`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
resultsContainer.innerHTML = '';
|
||||||
|
if (data.products && data.products.length > 0) {
|
||||||
|
const list = document.createElement('ul');
|
||||||
|
list.className = 'search-results-list'; // Add a class for styling
|
||||||
|
data.products.forEach(product => {
|
||||||
|
const productName = product.product_name_en || product.product_name || 'Unknown Food';
|
||||||
|
const calories = product.nutriments['energy-kcal_100g'] || product.nutriments['energy-kcal'] || 0;
|
||||||
|
|
||||||
|
if (!productName.trim()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const listItem = document.createElement('li');
|
||||||
|
listItem.innerHTML = `${productName} <span>(${calories} kcal/100g)</span>`;
|
||||||
|
listItem.addEventListener('click', function() {
|
||||||
|
document.getElementById('food_name').value = productName;
|
||||||
|
document.getElementById('calories').value = calories;
|
||||||
|
resultsContainer.innerHTML = '';
|
||||||
|
searchInput.value = '';
|
||||||
|
});
|
||||||
|
list.appendChild(listItem);
|
||||||
|
});
|
||||||
|
resultsContainer.appendChild(list);
|
||||||
|
} else {
|
||||||
|
resultsContainer.innerHTML = '<p style="padding: 15px;">No results found.</p>';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error fetching data:', error);
|
||||||
|
resultsContainer.innerHTML = '<p style="padding: 15px;">An error occurred while searching.</p>';
|
||||||
|
});
|
||||||
|
}, 300); // 300ms debounce delay
|
||||||
|
|
||||||
|
searchInput.addEventListener('input', searchHandler);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
117
add_sale.php
117
add_sale.php
@ -1,117 +0,0 @@
|
|||||||
<?php
|
|
||||||
$products = [
|
|
||||||
[
|
|
||||||
"name" => "Lean Beef Mince",
|
|
||||||
"image" => "assets/pasted-20251121-114725-33d5afd9.jpg",
|
|
||||||
"calories" => 150,
|
|
||||||
"protein" => 20,
|
|
||||||
"carbs" => 0,
|
|
||||||
"fat" => 7,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"name" => "Chicken Breast",
|
|
||||||
"image" => "assets/vm-shot-2025-11-21T11-47-05-928Z.jpg",
|
|
||||||
"calories" => 165,
|
|
||||||
"protein" => 31,
|
|
||||||
"carbs" => 0,
|
|
||||||
"fat" => 3.6,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"name" => "Salmon Fillet",
|
|
||||||
"image" => "https://images.pexels.com/photos/3296279/pexels-photo-3296279.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
|
|
||||||
"calories" => 208,
|
|
||||||
"protein" => 20,
|
|
||||||
"carbs" => 0,
|
|
||||||
"fat" => 13,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"name" => "Broccoli",
|
|
||||||
"image" => "https://images.pexels.com/photos/4057737/pexels-photo-4057737.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
|
|
||||||
"calories" => 55,
|
|
||||||
"protein" => 3.7,
|
|
||||||
"carbs" => 11,
|
|
||||||
"fat" => 0.6,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
require_once __DIR__ . '/db/config.php';
|
|
||||||
|
|
||||||
$success_message = "";
|
|
||||||
$error_message = "";
|
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
|
||||||
if (!empty($_POST['product_name']) && !empty($_POST['quantity']) && is_numeric($_POST['quantity'])) {
|
|
||||||
try {
|
|
||||||
$product_name = $_POST['product_name'];
|
|
||||||
$quantity = (int)$_POST['quantity'];
|
|
||||||
|
|
||||||
$pdo = db();
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO sales (product_name, quantity) VALUES (?, ?)");
|
|
||||||
$stmt->execute([$product_name, $quantity]);
|
|
||||||
|
|
||||||
$success_message = "Successfully added $quantity sale(s) for $product_name!";
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$error_message = "Error: Could not record the sale. " . $e->getMessage();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$error_message = "Please fill out all fields correctly.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Add Sale - Sales Tracker</title>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="mobile-container">
|
|
||||||
<header class="app-header">
|
|
||||||
<a href="index.php" class="back-button">←</a>
|
|
||||||
<h1>Add a New Sale</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main class="main-content">
|
|
||||||
<?php if ($success_message): ?>
|
|
||||||
<div class="alert success">
|
|
||||||
<?php echo $success_message; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if ($error_message): ?>
|
|
||||||
<div class="alert error">
|
|
||||||
<?php echo $error_message; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form action="add_sale.php" method="POST" class="add-sale-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="product_name">Product</label>
|
|
||||||
<select id="product_name" name="product_name" required>
|
|
||||||
<option value="" disabled selected>Select a product</option>
|
|
||||||
<?php foreach ($products as $product): ?>
|
|
||||||
<option value="<?php echo htmlspecialchars($product['name']); ?>"><?php echo htmlspecialchars($product['name']); ?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="quantity">Quantity</label>
|
|
||||||
<input type="number" id="quantity" name="quantity" min="1" value="1" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary">Record Sale</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -214,3 +214,48 @@ body {
|
|||||||
main.p-3 {
|
main.p-3 {
|
||||||
padding-bottom: 100px !important; /* Space for bottom nav */
|
padding-bottom: 100px !important; /* Space for bottom nav */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.food-search-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_results {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #1f1f3d;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
border-top: none;
|
||||||
|
border-radius: 0 0 15px 15px;
|
||||||
|
z-index: 1000;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-list li {
|
||||||
|
padding: 15px;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-list li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-list li:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-list li span {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
assets/pasted-20251121-115632-d3e25129.png
Normal file
BIN
assets/pasted-20251121-115632-d3e25129.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
BIN
assets/pasted-20251121-121911-9a3aea89.png
Normal file
BIN
assets/pasted-20251121-121911-9a3aea89.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
133
dashboard.php
Normal file
133
dashboard.php
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
$food_log_data = [];
|
||||||
|
$error_message = '';
|
||||||
|
$total_foods = 0;
|
||||||
|
$total_calories = 0;
|
||||||
|
$calories_by_food = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->query("SELECT food_name, calories, sale_date FROM food_log ORDER BY sale_date DESC");
|
||||||
|
$food_log_data = $stmt->fetchAll();
|
||||||
|
|
||||||
|
if ($food_log_data) {
|
||||||
|
$total_foods = count($food_log_data);
|
||||||
|
$total_calories = array_sum(array_column($food_log_data, 'calories'));
|
||||||
|
|
||||||
|
foreach ($food_log_data as $food) {
|
||||||
|
if (!isset($calories_by_food[$food['food_name']])) {
|
||||||
|
$calories_by_food[$food['food_name']] = 0;
|
||||||
|
}
|
||||||
|
$calories_by_food[$food['food_name']] += $food['calories'];
|
||||||
|
}
|
||||||
|
arsort($calories_by_food);
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$error_message = "Error fetching food log data: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Dashboard - Calorie Tracker</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="mobile-container">
|
||||||
|
<header class="app-header">
|
||||||
|
<a href="index.php" class="back-button">←</a>
|
||||||
|
<h1>Dashboard</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="main-content">
|
||||||
|
<?php if ($error_message): ?>
|
||||||
|
<div class="alert error">
|
||||||
|
<?php echo htmlspecialchars($error_message); ?>
|
||||||
|
</div>
|
||||||
|
<?php elseif (empty($food_log_data)) : ?>
|
||||||
|
<div class="alert">
|
||||||
|
No food logged yet. Add a food item to see your stats here.
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="stats-summary">
|
||||||
|
<div class="summary-card">
|
||||||
|
<span class="value"><?php echo $total_foods; ?></span>
|
||||||
|
<span class="label">Total Foods</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<span class="value"><?php echo $total_calories; ?></span>
|
||||||
|
<span class="label">Total Calories</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h5 mt-4 mb-3 text-white">Calories by Food</h2>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table sales-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Food</th>
|
||||||
|
<th>Total Calories</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($calories_by_food as $food_name => $calories): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($food_name); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars((string)$calories); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h5 mt-4 mb-3 text-white">Recent Entries</h2>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table sales-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Food</th>
|
||||||
|
<th>Calories</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($food_log_data as $food): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars($food['food_name']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars((string)$food['calories']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars(date("M d, Y H:i", strtotime($food['sale_date']))); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bottom Navigation -->
|
||||||
|
<nav class="bottom-nav">
|
||||||
|
<a href="index.php" class="nav-item">
|
||||||
|
<i class="bi bi-house-door-fill"></i>
|
||||||
|
<span>Home</span>
|
||||||
|
</a>
|
||||||
|
<a href="add_food.php" class="nav-item">
|
||||||
|
<i class="bi bi-plus-circle-fill"></i>
|
||||||
|
<span>Add Food</span>
|
||||||
|
</a>
|
||||||
|
<a href="dashboard.php" class="nav-item active">
|
||||||
|
<i class="bi bi-bar-chart-line-fill"></i>
|
||||||
|
<span>Dashboard</span>
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
14
index.php
14
index.php
@ -12,7 +12,7 @@ $products = [
|
|||||||
['id' => 8, 'name' => 'Almonds', 'calories' => 579, 'protein' => 21, 'carbs' => 22, 'fat' => 49],
|
['id' => 8, 'name' => 'Almonds', 'calories' => 579, 'protein' => 21, 'carbs' => 22, 'fat' => 49],
|
||||||
];
|
];
|
||||||
|
|
||||||
$projectName = $_SERVER['PROJECT_NAME'] ?? 'Sales & Nutrition';
|
$projectName = $_SERVER['PROJECT_NAME'] ?? 'Calorie Tracker';
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@ -22,7 +22,7 @@ $projectName = $_SERVER['PROJECT_NAME'] ?? 'Sales & Nutrition';
|
|||||||
<title><?= htmlspecialchars($projectName) ?></title>
|
<title><?= htmlspecialchars($projectName) ?></title>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Track your sales and product nutrition information easily.';
|
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Track your daily calorie and nutrient intake.';
|
||||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||||
?>
|
?>
|
||||||
<meta name="description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
<meta name="description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||||
@ -52,7 +52,7 @@ $projectName = $_SERVER['PROJECT_NAME'] ?? 'Sales & Nutrition';
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="p-3">
|
<main class="p-3">
|
||||||
<h2 class="h5 mb-3 text-white">Products</h2>
|
<h2 class="h5 mb-3 text-white">Food Library</h2>
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
<?php foreach ($products as $product): ?>
|
<?php foreach ($products as $product): ?>
|
||||||
<?php
|
<?php
|
||||||
@ -87,13 +87,13 @@ $projectName = $_SERVER['PROJECT_NAME'] ?? 'Sales & Nutrition';
|
|||||||
<i class="bi bi-house-door-fill"></i>
|
<i class="bi bi-house-door-fill"></i>
|
||||||
<span>Home</span>
|
<span>Home</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="add_sale.php" class="nav-item">
|
<a href="add_food.php" class="nav-item">
|
||||||
<i class="bi bi-plus-circle-fill"></i>
|
<i class="bi bi-plus-circle-fill"></i>
|
||||||
<span>Add Sale</span>
|
<span>Add Food</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="stats.php" class="nav-item">
|
<a href="dashboard.php" class="nav-item">
|
||||||
<i class="bi bi-bar-chart-line-fill"></i>
|
<i class="bi bi-bar-chart-line-fill"></i>
|
||||||
<span>Stats</span>
|
<span>Dashboard</span>
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
133
stats.php
133
stats.php
@ -1,133 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once __DIR__ . '/db/config.php';
|
|
||||||
|
|
||||||
$sales_data = [];
|
|
||||||
$error_message = '';
|
|
||||||
$total_sales = 0;
|
|
||||||
$total_quantity = 0;
|
|
||||||
$sales_by_product = [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
$pdo = db();
|
|
||||||
$stmt = $pdo->query("SELECT product_name, quantity, sale_date FROM sales ORDER BY sale_date DESC");
|
|
||||||
$sales_data = $stmt->fetchAll();
|
|
||||||
|
|
||||||
if ($sales_data) {
|
|
||||||
$total_sales = count($sales_data);
|
|
||||||
$total_quantity = array_sum(array_column($sales_data, 'quantity'));
|
|
||||||
|
|
||||||
foreach ($sales_data as $sale) {
|
|
||||||
if (!isset($sales_by_product[$sale['product_name']])) {
|
|
||||||
$sales_by_product[$sale['product_name']] = 0;
|
|
||||||
}
|
|
||||||
$sales_by_product[$sale['product_name']] += $sale['quantity'];
|
|
||||||
}
|
|
||||||
arsort($sales_by_product);
|
|
||||||
}
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$error_message = "Error fetching sales data: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Sales Stats - Sales Tracker</title>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="mobile-container">
|
|
||||||
<header class="app-header">
|
|
||||||
<a href="index.php" class="back-button">←</a>
|
|
||||||
<h1>Sales Statistics</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main class="main-content">
|
|
||||||
<?php if ($error_message): ?>
|
|
||||||
<div class="alert error">
|
|
||||||
<?php echo htmlspecialchars($error_message); ?>
|
|
||||||
</div>
|
|
||||||
<?php elseif (empty($sales_data)) : ?>
|
|
||||||
<div class="alert">
|
|
||||||
No sales data yet. Add a sale to see statistics here.
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="stats-summary">
|
|
||||||
<div class="summary-card">
|
|
||||||
<span class="value"><?php echo $total_sales; ?></span>
|
|
||||||
<span class="label">Total Sales</span>
|
|
||||||
</div>
|
|
||||||
<div class="summary-card">
|
|
||||||
<span class="value"><?php echo $total_quantity; ?></span>
|
|
||||||
<span class="label">Items Sold</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="h5 mt-4 mb-3 text-white">Sales by Product</h2>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table sales-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Product</th>
|
|
||||||
<th>Total Quantity Sold</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($sales_by_product as $product_name => $quantity): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($product_name); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars((string)$quantity); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="h5 mt-4 mb-3 text-white">Recent Sales</h2>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table sales-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Product</th>
|
|
||||||
<th>Quantity</th>
|
|
||||||
<th>Date</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($sales_data as $sale): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($sale['product_name']); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars((string)$sale['quantity']); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars(date("M d, Y H:i", strtotime($sale['sale_date']))); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bottom Navigation -->
|
|
||||||
<nav class="bottom-nav">
|
|
||||||
<a href="index.php" class="nav-item">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
|
||||||
<span>Home</span>
|
|
||||||
</a>
|
|
||||||
<a href="add_sale.php" class="nav-item">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
|
|
||||||
<span>Add Sale</span>
|
|
||||||
</a>
|
|
||||||
<a href="stats.php" class="nav-item active">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 2v6h6M2.66 15.57a10 10 0 1 0 .57-8.38"/></svg>
|
|
||||||
<span>Stats</span>
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Loading…
x
Reference in New Issue
Block a user