Compare commits
No commits in common. "ai-dev" and "master" have entirely different histories.
140
add_customer.php
140
add_customer.php
@ -1,140 +0,0 @@
|
||||
<?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 © <?= 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
184
add_item.php
@ -1,184 +0,0 @@
|
||||
<?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 © <?= 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
136
customers.php
@ -1,136 +0,0 @@
|
||||
<?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 © <?= 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>
|
||||
@ -1,36 +0,0 @@
|
||||
<?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();
|
||||
|
||||
@ -1,93 +0,0 @@
|
||||
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;
|
||||
@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
260
index.php
260
index.php
@ -4,135 +4,147 @@ declare(strict_types=1);
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
|
||||
require_once 'includes/dashboard_data.php';
|
||||
|
||||
$dashboard_data = get_dashboard_data();
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Admin Dashboard</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.active, .sidebar .nav-link:hover {
|
||||
color: #0d6efd;
|
||||
}
|
||||
.card {
|
||||
border: none;
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
</style>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<?php
|
||||
// Read project preview data from environment
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
?>
|
||||
<?php if ($projectDescription): ?>
|
||||
<!-- Meta description -->
|
||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||
<!-- Open Graph meta tags -->
|
||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<!-- Twitter meta tags -->
|
||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<?php endif; ?>
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<!-- Open Graph image -->
|
||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<!-- Twitter image -->
|
||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<?php endif; ?>
|
||||
<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=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
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>
|
||||
<body>
|
||||
|
||||
<div class="sidebar">
|
||||
<h4 class="px-3">POS System</h4>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" 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" 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>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
</div>
|
||||
|
||||
<footer class="pt-3 mt-4 text-muted border-top">
|
||||
POS System © <?= date('Y') ?>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
271
pos.php
271
pos.php
@ -1,271 +0,0 @@
|
||||
<?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>
|
||||
@ -1,65 +0,0 @@
|
||||
<?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
155
sale_details.php
@ -1,155 +0,0 @@
|
||||
<?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 © <?= 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
136
sales.php
@ -1,136 +0,0 @@
|
||||
<?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 © <?= 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
142
view_items.php
@ -1,142 +0,0 @@
|
||||
<?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 © <?= 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>
|
||||
Loading…
x
Reference in New Issue
Block a user