Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
e112ad7b40 Salaam 1.1 2025-11-22 16:45:55 +00:00
12 changed files with 1506 additions and 136 deletions

140
add_customer.php Normal file
View File

@ -0,0 +1,140 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
$message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pdo = db();
try {
$sql = "INSERT INTO customers (name, email, phone, address) VALUES (?, ?, ?, ?)";
$stmt= $pdo->prepare($sql);
$stmt->execute([
$_POST['name'],
$_POST['email'],
$_POST['phone'],
$_POST['address']
]);
$message = '<div class="alert alert-success">Customer added successfully!</div>';
} catch (PDOException $e) {
$message = '<div class="alert alert-danger">Error adding customer: ' . $e->getMessage() . '</div>';
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Add Customer</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<style>
body {
background-color: #f0f2f5;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #fff;
padding-top: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
.sidebar .nav-link {
color: #333;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #0d6efd;
}
</style>
</head>
<body>
<div class="sidebar">
<h4 class="px-3">POS System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="false" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link active" href="customers.php"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="d-flex justify-content-between align-items-center mb-4">
<h2>Add New Customer</h2>
<a href="customers.php" class="btn btn-secondary">Back to Customers</a>
</header>
<?= $message ?>
<div class="card">
<div class="card-body">
<form action="add_customer.php" method="post">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email">
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone</label>
<input type="text" class="form-control" id="phone" name="phone">
</div>
<div class="mb-3">
<label for="address" class="form-label">Address</label>
<textarea class="form-control" id="address" name="address" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Add Customer</button>
</form>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
POS System &copy; <?= date('Y') ?>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

184
add_item.php Normal file
View File

@ -0,0 +1,184 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
$message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pdo = db();
try {
$sql = "INSERT INTO products (name, sku, barcode, brand, category, unit, purchase_price, sale_price, tax_percentage, stock_quantity, alert_quantity) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt= $pdo->prepare($sql);
$stmt->execute([
$_POST['name'],
$_POST['sku'],
$_POST['barcode'],
$_POST['brand'],
$_POST['category'],
$_POST['unit'],
$_POST['purchase_price'],
$_POST['sale_price'],
$_POST['tax_percentage'],
$_POST['stock_quantity'],
$_POST['alert_quantity']
]);
$message = '<div class="alert alert-success">Product added successfully!</div>';
} catch (PDOException $e) {
$message = '<div class="alert alert-danger">Error adding product: ' . $e->getMessage() . '</div>';
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Add Item</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<style>
body {
background-color: #f0f2f5;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #fff;
padding-top: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
.sidebar .nav-link {
color: #333;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #0d6efd;
}
</style>
</head>
<body>
<div class="sidebar">
<h4 class="px-3">POS System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="true" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse show" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link active" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="customers.php"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="d-flex justify-content-between align-items-center mb-4">
<h2>Add New Product</h2>
</header>
<?= $message ?>
<div class="card">
<div class="card-body">
<form action="add_item.php" method="post">
<div class="row">
<div class="col-md-6 mb-3">
<label for="name" class="form-label">Product Name</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="col-md-6 mb-3">
<label for="sku" class="form-label">SKU</label>
<input type="text" class="form-control" id="sku" name="sku">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="barcode" class="form-label">Barcode</label>
<input type="text" class="form-control" id="barcode" name="barcode">
</div>
<div class="col-md-6 mb-3">
<label for="brand" class="form-label">Brand</label>
<input type="text" class="form-control" id="brand" name="brand">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="category" class="form-label">Category</label>
<input type="text" class="form-control" id="category" name="category">
</div>
<div class="col-md-6 mb-3">
<label for="unit" class="form-label">Unit (e.g., Pcs, Kg)</label>
<input type="text" class="form-control" id="unit" name="unit">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="purchase_price" class="form-label">Purchase Price</label>
<input type="number" step="0.01" class="form-control" id="purchase_price" name="purchase_price" required>
</div>
<div class="col-md-6 mb-3">
<label for="sale_price" class="form-label">Sale Price</label>
<input type="number" step="0.01" class="form-control" id="sale_price" name="sale_price" required>
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label for="tax_percentage" class="form-label">Tax (%)</label>
<input type="number" step="0.01" class="form-control" id="tax_percentage" name="tax_percentage" value="0">
</div>
<div class="col-md-4 mb-3">
<label for="stock_quantity" class="form-label">Stock Quantity</label>
<input type="number" class="form-control" id="stock_quantity" name="stock_quantity" required>
</div>
<div class="col-md-4 mb-3">
<label for="alert_quantity" class="form-label">Alert Quantity</label>
<input type="number" class="form-control" id="alert_quantity" name="alert_quantity" value="0">
</div>
</div>
<button type="submit" class="btn btn-primary">Add Product</button>
</form>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
POS System &copy; <?= date('Y') ?>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

136
customers.php Normal file
View File

@ -0,0 +1,136 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
$pdo = db();
$stmt = $pdo->query("SELECT * FROM customers ORDER BY name ASC");
$customers = $stmt->fetchAll();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Customers</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css">
<style>
body {
background-color: #f0f2f5;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #fff;
padding-top: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
.sidebar .nav-link {
color: #333;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #0d6efd;
}
</style>
</head>
<body>
<div class="sidebar">
<h4 class="px-3">POS System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="false" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link active" href="customers.php"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="d-flex justify-content-between align-items-center mb-4">
<h2>Customers</h2>
<a href="add_customer.php" class="btn btn-primary">Add New Customer</a>
</header>
<div class="card">
<div class="card-body">
<table id="customersTable" class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($customers as $customer): ?>
<tr>
<td><?= htmlspecialchars($customer['name']) ?></td>
<td><?= htmlspecialchars($customer['email']) ?></td>
<td><?= htmlspecialchars($customer['phone']) ?></td>
<td>
<a href="#" class="btn btn-sm btn-primary"><i class="bi bi-pencil-fill"></i></a>
<a href="#" class="btn btn-sm btn-danger"><i class="bi bi-trash-fill"></i></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
POS System &copy; <?= date('Y') ?>
</footer>
</div>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"></script>
<script>
$(document).ready(function() {
$('#customersTable').DataTable();
});
</script>
</body>
</html>

36
db/migrate.php Normal file
View File

@ -0,0 +1,36 @@
<?php
require_once 'config.php';
function run_migrations() {
$pdo = db();
if (!$pdo) {
echo "Error: Unable to connect to the database.\n";
return;
}
$migration_dir = __DIR__ . '/migrations';
$files = glob($migration_dir . '/*.sql');
if (empty($files)) {
echo "No migration files found.\n";
return;
}
sort($files);
foreach ($files as $file) {
echo "Running migration: " . basename($file) . "\n";
$sql = file_get_contents($file);
try {
$pdo->exec($sql);
echo "Success.\n";
} catch (PDOException $e) {
echo "Error running migration " . basename($file) . ": " . $e->getMessage() . "\n";
// Stop on error
return;
}
}
}
run_migrations();

View File

@ -0,0 +1,93 @@
CREATE TABLE IF NOT EXISTS `products` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`sku` VARCHAR(100),
`barcode` VARCHAR(100),
`brand` VARCHAR(100),
`category` VARCHAR(100),
`unit` VARCHAR(50),
`purchase_price` DECIMAL(10, 2) NOT NULL,
`sale_price` DECIMAL(10, 2) NOT NULL,
`tax_percentage` DECIMAL(5, 2) DEFAULT 0.00,
`stock_quantity` INT NOT NULL DEFAULT 0,
`alert_quantity` INT DEFAULT 0,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `customers` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`email` VARCHAR(255),
`phone` VARCHAR(50),
`address` TEXT,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `sales` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`customer_id` INT,
`total_amount` DECIMAL(10, 2) NOT NULL,
`discount` DECIMAL(10, 2) DEFAULT 0.00,
`tax_amount` DECIMAL(10, 2) DEFAULT 0.00,
`payable_amount` DECIMAL(10, 2) NOT NULL,
`payment_method` VARCHAR(50) DEFAULT 'cash',
`sale_date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `sale_items` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`sale_id` INT NOT NULL,
`product_id` INT NOT NULL,
`quantity` INT NOT NULL,
`price_per_unit` DECIMAL(10, 2) NOT NULL,
`total_price` DECIMAL(10, 2) NOT NULL,
FOREIGN KEY (`sale_id`) REFERENCES `sales`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `expenses` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`description` TEXT NOT NULL,
`amount` DECIMAL(10, 2) NOT NULL,
`expense_date` DATE,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `users` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`email` VARCHAR(255) NOT NULL UNIQUE,
`password` VARCHAR(255) NOT NULL,
`role` ENUM('admin', 'cashier', 'manager') DEFAULT 'cashier',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `suppliers` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`contact_person` VARCHAR(255),
`phone` VARCHAR(50),
`email` VARCHAR(255),
`address` TEXT,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `purchases` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`supplier_id` INT,
`total_amount` DECIMAL(10, 2) NOT NULL,
`purchase_date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`supplier_id`) REFERENCES `suppliers`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `purchase_items` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`purchase_id` INT NOT NULL,
`product_id` INT NOT NULL,
`quantity` INT NOT NULL,
`price_per_unit` DECIMAL(10, 2) NOT NULL,
`total_price` DECIMAL(10, 2) NOT NULL,
FOREIGN KEY (`purchase_id`) REFERENCES `purchases`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@ -0,0 +1,24 @@
<?php
require_once __DIR__ . '/../db/config.php';
function get_dashboard_data() {
$pdo = db();
$data = [];
// Total Sales
$stmt = $pdo->query("SELECT SUM(payable_amount) as total_sales FROM sales");
$data['total_sales'] = $stmt->fetchColumn() ?: 0;
// Total Purchases
$stmt = $pdo->query("SELECT SUM(total_amount) as total_purchases FROM purchases");
$data['total_purchases'] = $stmt->fetchColumn() ?: 0;
// Total Expenses
$stmt = $pdo->query("SELECT SUM(amount) as total_expenses FROM expenses");
$data['total_expenses'] = $stmt->fetchColumn() ?: 0;
// Net Profit
$data['net_profit'] = $data['total_sales'] - ($data['total_purchases'] + $data['total_expenses']);
return $data;
}

258
index.php
View File

@ -4,147 +4,135 @@ declare(strict_types=1);
@error_reporting(E_ALL); @error_reporting(E_ALL);
@date_default_timezone_set('UTC'); @date_default_timezone_set('UTC');
$phpVersion = PHP_VERSION; require_once 'includes/dashboard_data.php';
$now = date('Y-m-d H:i:s');
$dashboard_data = get_dashboard_data();
?> ?>
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title> <title>Admin Dashboard</title>
<?php <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
// Read project preview data from environment <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? ''; <style>
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; body {
?> background-color: #f0f2f5;
<?php if ($projectDescription): ?> }
<!-- Meta description --> .sidebar {
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' /> position: fixed;
<!-- Open Graph meta tags --> top: 0;
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" /> left: 0;
<!-- Twitter meta tags --> height: 100%;
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" /> width: 250px;
<?php endif; ?> background-color: #fff;
<?php if ($projectImageUrl): ?> padding-top: 1rem;
<!-- Open Graph image --> }
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" /> .main-content {
<!-- Twitter image --> margin-left: 250px;
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" /> padding: 2rem;
<?php endif; ?> }
<link rel="preconnect" href="https://fonts.googleapis.com"> .sidebar .nav-link {
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> color: #333;
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"> font-weight: 500;
<style> }
:root { .sidebar .nav-link.active, .sidebar .nav-link:hover {
--bg-color-start: #6a11cb; color: #0d6efd;
--bg-color-end: #2575fc; }
--text-color: #ffffff; .card {
--card-bg-color: rgba(255, 255, 255, 0.01); border: none;
--card-border-color: rgba(255, 255, 255, 0.1); box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
} }
body { </style>
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
</head> </head>
<body> <body>
<main>
<div class="card"> <div class="sidebar">
<h1>Analyzing your requirements and generating your website…</h1> <h4 class="px-3">POS System</h4>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes"> <ul class="nav flex-column">
<span class="sr-only">Loading…</span> <li class="nav-item">
</div> <a class="nav-link active" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p> </li>
<p class="hint">This page will update automatically as the plan is implemented.</p> <li class="nav-item">
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p> <a class="nav-link" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="false" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="customers.php"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="d-flex justify-content-between align-items-center mb-4">
<h2>Dashboard</h2>
<div>
<a href="#" class="btn btn-primary"><i class="bi bi-arrow-clockwise"></i> Refresh</a>
</div>
</header>
<div class="row">
<div class="col-md-3">
<div class="card text-white bg-primary mb-3">
<div class="card-body">
<h5 class="card-title">Total Sales</h5>
<p class="card-text fs-4"><?= number_format($dashboard_data['total_sales'], 2) ?></p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info mb-3">
<div class="card-body">
<h5 class="card-title">Total Purchases</h5>
<p class="card-text fs-4"><?= number_format($dashboard_data['total_purchases'], 2) ?></p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-3">
<div class="card-body">
<h5 class="card-title">Total Expenses</h5>
<p class="card-text fs-4"><?= number_format($dashboard_data['total_expenses'], 2) ?></p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white <?= $dashboard_data['net_profit'] >= 0 ? 'bg-success' : 'bg-danger' ?> mb-3">
<div class="card-body">
<h5 class="card-title">Net Profit</h5>
<p class="card-text fs-4"><?= number_format($dashboard_data['net_profit'], 2) ?></p>
</div>
</div>
</div>
</div> </div>
</main>
<footer> <footer class="pt-3 mt-4 text-muted border-top">
Page updated: <?= htmlspecialchars($now) ?> (UTC) POS System &copy; <?= date('Y') ?>
</footer> </footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body> </body>
</html> </html>

271
pos.php Normal file
View File

@ -0,0 +1,271 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
$pdo = db();
$stmt_products = $pdo->query("SELECT * FROM products WHERE stock_quantity > 0 ORDER BY name ASC");
$products = $stmt_products->fetchAll();
$stmt_customers = $pdo->query("SELECT * FROM customers ORDER BY name ASC");
$customers = $stmt_customers->fetchAll();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>POS Terminal</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<style>
body {
background-color: #f0f2f5;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #fff;
padding-top: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
.sidebar .nav-link {
color: #333;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #0d6efd;
}
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 1rem;
}
.product-card {
cursor: pointer;
}
.product-card:hover {
border-color: #0d6efd;
}
</style>
</head>
<body>
<div class="sidebar">
<h4 class="px-3">POS System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="false" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="customers.php"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<div class="row">
<div class="col-md-7">
<div class="card">
<div class="card-body">
<input type="text" id="productSearch" class="form-control mb-3" placeholder="Search products...">
<div class="product-grid">
<?php foreach ($products as $product): ?>
<div class="card product-card" onclick="addToCart(<?= htmlspecialchars(json_encode($product)) ?>)">
<div class="card-body text-center">
<h6 class="card-title"><?= htmlspecialchars($product['name']) ?></h6>
<p class="card-text text-muted"><?= htmlspecialchars((string)$product['sale_price']) ?></p>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<div class="col-md-5">
<div class="card">
<div class="card-body">
<div class="mb-3">
<label for="customer" class="form-label">Customer</label>
<select id="customer" class="form-select">
<option value="">Select Customer</option>
<?php foreach ($customers as $customer): ?>
<option value="<?= $customer['id'] ?>"><?= htmlspecialchars($customer['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<h5>Cart</h5>
<table class="table">
<thead>
<tr>
<th>Item</th>
<th>Qty</th>
<th>Price</th>
<th>Total</th>
<th></th>
</tr>
</thead>
<tbody id="cart-items">
</tbody>
</table>
<hr>
<div class="d-flex justify-content-between">
<h5>Total:</h5>
<h5 id="cart-total">0.00</h5>
</div>
<div class="d-grid gap-2">
<button class="btn btn-primary" onclick="processPayment()">Pay Now</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
let cart = [];
function addToCart(product) {
const existingProduct = cart.find(item => item.id === product.id);
if (existingProduct) {
existingProduct.quantity++;
} else {
cart.push({ ...product, quantity: 1 });
}
renderCart();
}
function removeFromCart(productId) {
const productIndex = cart.findIndex(item => item.id === productId);
if (productIndex > -1) {
cart.splice(productIndex, 1);
}
renderCart();
}
function updateQuantity(productId, change) {
const product = cart.find(item => item.id === productId);
if (product) {
product.quantity += change;
if (product.quantity <= 0) {
removeFromCart(productId);
}
}
renderCart();
}
function renderCart() {
const cartItems = document.getElementById('cart-items');
cartItems.innerHTML = '';
let total = 0;
cart.forEach(item => {
const itemTotal = item.sale_price * item.quantity;
total += itemTotal;
const row = `
<tr>
<td>${item.name}</td>
<td>
<button class="btn btn-sm btn-secondary" onclick="updateQuantity(${item.id}, -1)">-</button>
${item.quantity}
<button class="btn btn-sm btn-secondary" onclick="updateQuantity(${item.id}, 1)">+</button>
</td>
<td>${item.sale_price}</td>
<td>${itemTotal.toFixed(2)}</td>
<td><button class="btn btn-sm btn-danger" onclick="removeFromCart(${item.id})"><i class="bi bi-x-circle"></i></button></td>
</tr>
`;
cartItems.innerHTML += row;
});
document.getElementById('cart-total').innerText = total.toFixed(2);
}
function processPayment() {
if(cart.length === 0) {
alert("Cart is empty!");
return;
}
const customerId = document.getElementById('customer').value;
const saleData = {
cart: cart,
customer_id: customerId
};
fetch('process_sale.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(saleData),
})
.then(response => response.json())
.then(data => {
if (data.success) {
cart = [];
renderCart();
alert(data.message);
// Optionally, redirect to a success page or print receipt
} else {
alert(data.message);
}
})
.catch((error) => {
console.error('Error:', error);
alert('An error occurred while processing the sale.');
});
}
document.getElementById('productSearch').addEventListener('keyup', function() {
const filter = this.value.toLowerCase();
const products = document.querySelectorAll('.product-card');
products.forEach(product => {
const title = product.querySelector('.card-title').innerText.toLowerCase();
if (title.includes(filter)) {
product.style.display = '';
} else {
product.style.display = 'none';
}
});
});
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

65
process_sale.php Normal file
View File

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
header('Content-Type: application/json');
require_once 'db/config.php';
$response = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$sale_data = json_decode(file_get_contents('php://input'), true);
$cart_data = $sale_data['cart'];
$customer_id = !empty($sale_data['customer_id']) ? (int)$sale_data['customer_id'] : null;
if (empty($cart_data)) {
$response = ['success' => false, 'message' => 'Cart is empty.'];
echo json_encode($response);
exit;
}
$pdo = db();
$pdo->beginTransaction();
try {
// 1. Calculate total amount
$total_amount = 0;
foreach ($cart_data as $item) {
$total_amount += $item['sale_price'] * $item['quantity'];
}
// 2. Insert into sales table
$sql = "INSERT INTO sales (customer_id, total_amount, payable_amount) VALUES (?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$customer_id, $total_amount, $total_amount]);
$sale_id = $pdo->lastInsertId();
// 3. Insert into sale_items and update stock
$sql_item = "INSERT INTO sale_items (sale_id, product_id, quantity, price_per_unit, total_price) VALUES (?, ?, ?, ?, ?)";
$stmt_item = $pdo->prepare($sql_item);
$sql_stock = "UPDATE products SET stock_quantity = stock_quantity - ? WHERE id = ?";
$stmt_stock = $pdo->prepare($sql_stock);
foreach ($cart_data as $item) {
$item_total = $item['sale_price'] * $item['quantity'];
$stmt_item->execute([$sale_id, $item['id'], $item['quantity'], $item['sale_price'], $item_total]);
$stmt_stock->execute([$item['quantity'], $item['id']]);
}
$pdo->commit();
$response = ['success' => true, 'message' => 'Sale processed successfully!', 'sale_id' => $sale_id];
} catch (PDOException $e) {
$pdo->rollBack();
$response = ['success' => false, 'message' => 'Error processing sale: ' . $e->getMessage()];
}
} else {
$response = ['success' => false, 'message' => 'Invalid request method.'];
}
echo json_encode($response);

155
sale_details.php Normal file
View File

@ -0,0 +1,155 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
if (!isset($_GET['id'])) {
header('Location: sales.php');
exit;
}
$sale_id = (int)$_GET['id'];
$pdo = db();
// Get sale details
$stmt = $pdo->prepare("SELECT sales.*, customers.name as customer_name FROM sales LEFT JOIN customers ON sales.customer_id = customers.id WHERE sales.id = ?");
$stmt->execute([$sale_id]);
$sale = $stmt->fetch();
if (!$sale) {
header('Location: sales.php');
exit;
}
// Get sale items
$stmt_items = $pdo->prepare("SELECT sale_items.*, products.name as product_name FROM sale_items JOIN products ON sale_items.product_id = products.id WHERE sale_items.sale_id = ?");
$stmt_items->execute([$sale_id]);
$sale_items = $stmt_items->fetchAll();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Sale Details</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<style>
body {
background-color: #f0f2f5;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #fff;
padding-top: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
.sidebar .nav-link {
color: #333;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #0d6efd;
}
</style>
</head>
<body>
<div class="sidebar">
<h4 class="px-3">POS System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="false" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="d-flex justify-content-between align-items-center mb-4">
<h2>Sale Details #<?= htmlspecialchars((string)$sale['id']) ?></h2>
<a href="sales.php" class="btn btn-secondary">Back to Sales</a>
</header>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-6">
<p><strong>Customer:</strong> <?= htmlspecialchars($sale['customer_name'] ?? 'N/A') ?></p>
<p><strong>Date:</strong> <?= htmlspecialchars($sale['sale_date']) ?></p>
</div>
<div class="col-md-6 text-end">
<h4>Total: <?= htmlspecialchars((string)$sale['payable_amount']) ?></h4>
</div>
</div>
<hr>
<h5>Items Purchased</h5>
<table class="table table-striped">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Price per Unit</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($sale_items as $item): ?>
<tr>
<td><?= htmlspecialchars($item['product_name']) ?></td>
<td><?= htmlspecialchars((string)$item['quantity']) ?></td>
<td><?= htmlspecialchars((string)$item['price_per_unit']) ?></td>
<td><?= htmlspecialchars((string)$item['total_price']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
POS System &copy; <?= date('Y') ?>
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

136
sales.php Normal file
View File

@ -0,0 +1,136 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
$pdo = db();
$stmt = $pdo->query("SELECT sales.*, customers.name as customer_name FROM sales LEFT JOIN customers ON sales.customer_id = customers.id ORDER BY sale_date DESC");
$sales = $stmt->fetchAll();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Sales</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css">
<style>
body {
background-color: #f0f2f5;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #fff;
padding-top: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
.sidebar .nav-link {
color: #333;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #0d6efd;
}
</style>
</head>
<body>
<div class="sidebar">
<h4 class="px-3">POS System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="false" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="customers.php"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="d-flex justify-content-between align-items-center mb-4">
<h2>Sales History</h2>
</header>
<div class="card">
<div class="card-body">
<table id="salesTable" class="table table-striped table-hover">
<thead>
<tr>
<th>Sale ID</th>
<th>Customer</th>
<th>Total Amount</th>
<th>Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($sales as $sale): ?>
<tr>
<td><?= htmlspecialchars((string)$sale['id']) ?></td>
<td><?= htmlspecialchars($sale['customer_name'] ?? 'N/A') ?></td>
<td><?= htmlspecialchars((string)$sale['payable_amount']) ?></td>
<td><?= htmlspecialchars($sale['sale_date']) ?></td>
<td>
<a href="sale_details.php?id=<?= $sale['id'] ?>" class="btn btn-sm btn-primary"><i class="bi bi-eye-fill"></i></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
POS System &copy; <?= date('Y') ?>
</footer>
</div>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"></script>
<script>
$(document).ready(function() {
$('#salesTable').DataTable();
});
</script>
</body>
</html>

142
view_items.php Normal file
View File

@ -0,0 +1,142 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
$pdo = db();
$stmt = $pdo->query("SELECT * FROM products ORDER BY created_at DESC");
$products = $stmt->fetchAll();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>View Items</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css">
<style>
body {
background-color: #f0f2f5;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #fff;
padding-top: 1rem;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}
.sidebar .nav-link {
color: #333;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #0d6efd;
}
</style>
</head>
<body>
<div class="sidebar">
<h4 class="px-3">POS System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pos.php"><i class="bi bi-cart-check-fill"></i> POS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-bs-toggle="collapse" data-bs-target="#inventory-submenu" aria-expanded="true" aria-controls="inventory-submenu"><i class="bi bi-box-seam-fill"></i> Inventory</a>
<div class="collapse show" id="inventory-submenu">
<ul class="nav flex-column ms-3">
<li class="nav-item"><a class="nav-link active" href="view_items.php">View Items</a></li>
<li class="nav-item"><a class="nav-link" href="add_item.php">Add Item</a></li>
</ul>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="customers.php"><i class="bi bi-people-fill"></i> Customers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-truck"></i> Suppliers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sales.php"><i class="bi bi-receipt"></i> Sales</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-wallet-fill"></i> Expenses</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-person-circle"></i> Users</a>
</li>
</ul>
</div>
<div class="main-content">
<header class="d-flex justify-content-between align-items-center mb-4">
<h2>Inventory Items</h2>
<a href="add_item.php" class="btn btn-primary">Add New Item</a>
</header>
<div class="card">
<div class="card-body">
<table id="itemsTable" class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>SKU</th>
<th>Stock</th>
<th>Price</th>
<th>Category</th>
<th>Brand</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($products as $product): ?>
<tr>
<td><?= htmlspecialchars($product['name']) ?></td>
<td><?= htmlspecialchars($product['sku']) ?></td>
<td><?= htmlspecialchars((string)$product['stock_quantity']) ?></td>
<td><?= htmlspecialchars((string)$product['sale_price']) ?></td>
<td><?= htmlspecialchars($product['category']) ?></td>
<td><?= htmlspecialchars($product['brand']) ?></td>
<td>
<a href="#" class="btn btn-sm btn-primary"><i class="bi bi-pencil-fill"></i></a>
<a href="#" class="btn btn-sm btn-danger"><i class="bi bi-trash-fill"></i></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
POS System &copy; <?= date('Y') ?>
</footer>
</div>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"></script>
<script>
$(document).ready(function() {
$('#itemsTable').DataTable();
});
</script>
</body>
</html>